Переглянути джерело

feat: 添加CodeTutorAgent 毕业设计项目

lll0807 6 місяців тому
батько
коміт
adf616bb8e
21 змінених файлів з 1488 додано та 0 видалено
  1. 45 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/.env.example
  2. 79 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/README.md
  3. 0 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/__init__.py
  4. 40 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/code_reviewer.py
  5. 140 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/exercise.py
  6. 102 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/planner.py
  7. 63 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/reviewer.py
  8. 114 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/tutor.py
  9. 37 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/data/README.md
  10. 35 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/main.py
  11. 71 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_001617_12.md
  12. 71 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_001749_13.md
  13. 64 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_002318_14.md
  14. 58 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_003209_15.md
  15. 168 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/notes_index.json
  16. 0 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/__init__.py
  17. 98 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/knowledge.py
  18. 118 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/problem_repository.py
  19. 54 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/agent_tool.py
  20. 68 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/code_runner.py
  21. 63 0
      Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/note_tools.py

+ 45 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/.env.example

@@ -0,0 +1,45 @@
+LLM_API_KEY=""
+LLM_MODEL_ID=""
+LLM_BASE_URL=""
+SERPAPI_API_KEY=""
+
+QDRANT_URL=""
+QDRANT_API_KEY=""
+
+# Qdrant集合配置
+QDRANT_COLLECTION=hello_agents_vectors
+QDRANT_VECTOR_SIZE=384
+QDRANT_DISTANCE=cosine
+QDRANT_TIMEOUT=30
+
+# 使用Neo4j Aura云服务 (推荐)
+NEO4J_URI=""
+NEO4J_USERNAME=
+NEO4J_PASSWORD=
+
+# Neo4j连接配置
+NEO4J_DATABASE=neo4j
+NEO4J_MAX_CONNECTION_LIFETIME=3600
+NEO4J_MAX_CONNECTION_POOL_SIZE=50
+NEO4J_CONNECTION_TIMEOUT=60
+
+# ==========================
+# 嵌入(Embedding)配置示例 - 可从阿里云控制台获取:https://dashscope.aliyun.com/
+# ==========================
+# - 若为空,dashscope 默认 text-embedding-v3;local 默认 sentence-transformers/all-MiniLM-L6-v2
+EMBED_MODEL_TYPE=dashscope
+EMBED_MODEL_NAME=""
+EMBED_API_KEY=""
+EMBED_BASE_URL=""
+# 超时时间(可选,默认60秒)
+LLM_TIMEOUT=90
+
+# 服务器配置
+HOST=0.0.0.0
+PORT=8000
+
+# CORS配置
+CORS_ORIGINS=http://localhost:5173,http://localhost:3000
+
+# 日志级别
+LOG_LEVEL=INFO

+ 79 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/README.md

@@ -0,0 +1,79 @@
+# TutorAgent
+
+> 一个基于多智能体协作的智能编程导师系统,支持学习路径规划、RAG 出题、代码评审与学习记忆回顾。
+
+---
+
+## 📝 项目简介
+
+**TutorAgent** 是一个基于 LLM 与多智能体(Agent-to-Agent, A2A)协作架构的智能编程导师系统,旨在模拟“真人导师”的教学流程,为用户提供**可持续、可回顾、可演进**的编程学习体验。
+## 📌 项目来源说明
+
+本项目基于@chen070808的毕业设计进行二次开发,
+
+---
+
+## ✨ 核心功能
+
+- [x] **学习路径规划(PlannerAgent)**  
+  根据用户目标与当前水平,自动生成结构化学习计划(Markdown),并支持阶段进度动态更新。
+
+- [x] **智能出题(ExerciseAgent + RAG)**  
+  基于 RAG 技术从题库中检索与当前学习阶段和难度匹配的编程题目。
+
+- [x] **代码评审与反馈(CodeReview-Agent)**  
+  对用户提交的代码进行自动化分析与执行测试,生成覆盖正确性、代码风格与复杂度的专业反馈。
+
+- [x] **学习记忆与回顾(Memory + NoteTool)**  
+  对学习行为、阶段进展与关键知识点进行持久化记录,支持跨会话的学习状态维护与自然语言回顾查询。
+
+---
+
+## 🛠️ 技术栈
+
+- **框架**
+  - HelloAgents(Agent 框架)
+
+- **核心技术**
+  - LLM(OpenAI / 本地模型)
+  - RAG(检索增强生成)
+  - 长短期 Memory 机制
+  - 结构化 Markdown 笔记(NoteTool)
+
+- **语言与依赖**
+  - Python 3.10+
+  - dotenv / pydantic / requests 等
+
+---
+
+## 🚀 快速开始
+
+### 环境要求
+
+- Python 3.10+
+- 已配置可用的 LLM API Key(或本地模型)
+
+# 创建环境变量文件
+cp .env.example .env
+
+# 在 .env 中填写你的 LLM API Key
+python main.py
+
+用户输入:
+我想学习 Python 的列表推导式
+
+系统行为:
+- PlannerAgent 生成学习计划并保存为学习笔记
+- Memory 记录学习目标
+- 后续可通过“我想回顾学习目标”进行回顾
+用户输入:
+我想要更新学习计划
+
+系统行为:
+- 自动更新学习计划进度
+- 将对应阶段标记为已完成 [x]
+
+## 🙏 致谢
+
+感谢Datawhale社区和Hello-Agents项目!
+感谢@chen070808

+ 0 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/__init__.py


+ 40 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/code_reviewer.py

@@ -0,0 +1,40 @@
+from hello_agents import SimpleAgent, HelloAgentsLLM
+from hello_agents.tools.builtin.note_tool import NoteTool
+
+class CodeReviewAgent(SimpleAgent):
+    """
+    负责评测用户提交的代码
+    """
+
+    def __init__(self, llm: HelloAgentsLLM):
+        system_prompt = """
+你是一位【严格但友好的编程导师】。
+
+你的任务是评测用户提交的代码。
+
+你将收到:
+- 题目描述
+- 示例
+- 约束条件
+- 用户代码
+
+你必须按照以下步骤思考并输出:
+
+1️⃣ 判断代码是否【逻辑正确】
+2️⃣ 检查是否覆盖题目示例
+3️⃣ 指出潜在的边界问题
+4️⃣ 分析时间和空间复杂度
+5️⃣ 给出改进建议(如果有)
+
+⚠️ 重要规则:
+- 不要直接给出完整正确代码
+- 不要替用户重写解法
+- 重点是【诊断 + 引导】
+
+请使用 Markdown 输出。
+"""
+        super().__init__(
+            name="CodeReview",
+            llm=llm,
+            system_prompt=system_prompt
+        )

+ 140 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/exercise.py

@@ -0,0 +1,140 @@
+from hello_agents import SimpleAgent, HelloAgentsLLM
+from programmer.services.problem_repository import ProblemRepository
+from hello_agents.tools import RAGTool
+import re
+
+
+class ExerciseAgent(SimpleAgent):
+    """
+    从本地题库中筛选编程题目的智能体(RAG + LLM 决策)
+    """
+
+    def __init__(self, llm: HelloAgentsLLM):
+        system_prompt = """
+你是一位【编程题目筛选助手】。
+
+你的职责是:
+- 理解用户对【难度】【知识点】【学习目标】的要求
+- 输出你理解的用户需要的题目难度,只有两种选择Easy或Medium
+
+⚠️ 重要规则:
+- 不要生成新题目
+你只需要输出Easy或Medium
+"""
+        super().__init__(
+            name="Exercise",
+            llm=llm,
+            system_prompt=system_prompt
+        )
+
+        root_dir = r"E:\PycharmProject_lmx\HelloAgents-main\output"
+        self.repo = ProblemRepository(root_dir)
+
+        # ===== 初始化 RAG =====
+        self.rag = RAGTool(
+            collection_name="rag_knowledge_base",
+            rag_namespace="problems"
+        )
+        # ===== 判断是否需要初始化题库 =====
+        need_init = False
+
+        try:
+            # 尝试随便搜一个词,判断库是否为空
+            test = self.rag.search(query="Easy", limit=1)
+            if not test:
+                need_init = True
+        except Exception:
+            # 向量库不存在 / 第一次运行
+            need_init = True
+
+        if need_init:
+            # 第一次运行先添加题目到rag中
+            for problem in self.repo.problems:
+                self.rag.add_text(
+                    text=f"""
+                Title: {problem['title']}
+                Difficulty: {problem['difficulty']}
+                Tags: {", ".join(problem['tags'])}
+                Description: {problem['description'][:200]}
+                """.strip(),
+                    document_id=problem["title"]
+                )
+        print("✅ 编程题目向量仓库构建完成")
+
+    def run(self, input_text: str, max_tool_iterations: int = 3, **kwargs) -> str:
+
+        result = super().run(input_text)
+        # ========= RAG 语义召回 =========
+        rag_results = self.rag.search(
+            query=result,
+            limit=3,
+            min_score=0.3
+        )
+        titles = re.findall(r"Title:\s*(.+)", rag_results)
+
+        user_problems = []
+        # ========= 2️⃣ 本地题库精确过滤 =========
+        for title in titles:
+            problem = self.get_problem_by_title(title)
+            if problem:
+                user_problems.append(problem)
+
+        if not user_problems:
+            return "❌ 没有找到相关题目"
+
+        # ========= 4️⃣ 返回标准化结果 =========
+        return "\n\n".join(
+            self._format_problem(problem)
+            for problem in user_problems
+        )
+
+        # =========================================================
+        # RAG 解析
+        # =========================================================
+
+    def get_problem_by_title(self, title: str):
+        for problem in self.repo.problems:
+            if problem.get("title") == title:
+                return problem
+        return None
+
+    def _format_problem(self, problem: dict) -> str:
+        examples_md = ""
+
+        for i, ex in enumerate(problem["examples"], start=1):
+            examples_md += f"""
+    **Example {i}**
+
+    Input: {ex["input"]}  
+    Output: {ex["output"]}  
+    """
+            if ex["explanation"]:
+                examples_md += f"Explanation: {ex['explanation']}\n"
+
+        return f"""
+    ### 推荐练习题:{problem['title']}
+
+    **Difficulty:** {problem['difficulty']}  
+    **Tags:** {", ".join(problem['tags'])}
+
+    ---
+
+    ## 📘 题目描述
+
+    {problem['description']}
+
+    ---
+
+    ## 🧪 示例
+    {examples_md}
+
+    ---
+
+    ## 📌 约束条件
+
+    {problem['constraints']}
+
+    ---
+
+    💡 *请先尝试独立完成,不要直接查看题解。完成后可提交代码进行评审。*
+    """

+ 102 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/planner.py

@@ -0,0 +1,102 @@
+from hello_agents import SimpleAgent, HelloAgentsLLM
+from hello_agents.tools.builtin.note_tool import NoteTool
+
+
+class PlannerAgent(SimpleAgent):
+    """
+    负责创建和更新学习路径的智能体。
+    """
+
+    def __init__(self, llm: HelloAgentsLLM, knowledge_service):
+        """
+        初始化 PlannerAgent。
+        
+        Args:
+            llm: 用于生成计划的大语言模型实例。
+        """
+        # 在 PlannerAgent.run() 中
+        self.knowledge = knowledge_service
+
+
+        system_prompt = """
+        你是一位专业的计算机科学课程规划师。
+        你的工作是根据用户的目标和当前水平为他们创建个性化的学习路径。
+        
+        当被要求创建计划时:
+        1. 分析用户的目标(例如,"学习 Python 数据科学")。
+        2. 将其分解为逻辑模块/里程碑。
+        3. 对于每个模块,列出要掌握的关键概念。
+        4.所有阶段名称的最后必须使用 Markdown 任务列表格式:
+           - `[ ]` 表示未完成
+           - `[x]` 表示已完成(创建时默认未完成)      
+        5. 当你创建学习计划时,必须遵循以下输出格式:
+
+            ### 学习计划
+            
+            # 学习主题:<主题>
+            
+            ## 学习目标
+            - ...
+            
+            ## 学习路径
+            1. 第一阶段:<阶段名称> []
+               - 关键概念
+            2. 第一阶段:<阶段名称> []
+               - 关键概念
+            
+            ## 学习建议
+            - ...
+            
+            请确保整个学习计划是一个完整、可直接保存的 Markdown 文档。
+        
+        当被要求【更新学习计划 / 更新进度】时,你必须:
+        
+        1. 假设已有一份“学习计划”文档存在。
+        2. 根据用户的最新学习行为(如:完成了某个知识点、提交了代码并通过评审):
+           - 将对应的 `[ ]` 更新为 `[x]`
+        3. 输出【更新后的完整学习计划 Markdown 文档】(而不是只输出差异)以### 更新学习计划作为开头。
+        
+        """
+        super().__init__(
+            name="Planner",
+            llm=llm,
+            system_prompt=system_prompt
+        )
+        self.note_tool = NoteTool(workspace="notes")
+
+    def run(self, input_text: str, max_tool_iterations: int = 3, **kwargs) -> str:
+        # ===== 学习回顾 =====
+        if any(k in input_text for k in ["之前", "回顾", "学过", "记得"]):
+            return self.knowledge.recall(input_text)
+        # 正常让 LLM 生成内容
+        result = super().run(input_text)
+        # Planner 自己判断:这是学习计划
+        if result.strip().startswith("### 学习计划"):
+            self._save_learning_plan(result, input_text)
+        if result.strip().startswith("### 更新学习计划"):
+            self._update_learning_plan(result, input_text)
+
+        # 原样返回给 Tutor
+        return result
+
+    def _update_learning_plan(self, markdown: str, input_text: str):
+        title_and_note_id_str = self.knowledge.recall(input_text)
+        self.note_tool.run({
+            "note_id": self.note_tool.notes_index['notes'][-1]['id'],
+            "action": "update",  # 注意是 update
+            "title": "学习计划",
+            "content": markdown,
+            "tags": ["learning-plan", "progress"]
+        })
+        # self.knowledge.add_note(content=markdown)
+
+    def _save_learning_plan(self, markdown: str, input_text: str):
+
+        note_id = self.note_tool.run({
+            "action": "create",
+            "title": "学习计划",
+            "content": markdown,
+            "tags": ["learning-plan", "planner"]
+        })
+        content = f"title: {input_text} note_id: {note_id}"
+        self.knowledge.add_note(content=content)

+ 63 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/reviewer.py

@@ -0,0 +1,63 @@
+from hello_agents import SimpleAgent, HelloAgentsLLM
+from hello_agents.tools import Tool
+from typing import List
+
+class ReviewerAgent(SimpleAgent):
+    """
+    负责评审代码的智能体。
+    它可以访问 CodeRunner 工具来执行代码。
+    """
+    
+    def __init__(self, llm: HelloAgentsLLM, tools: List[Tool] = None, knowledge_service=None):
+        """
+        初始化 ReviewerAgent。
+        
+        Args:
+            llm: 用于评审代码的大语言模型实例。
+            tools: 智能体可用的工具列表(例如 CodeRunner)。
+        """
+        system_prompt = """
+        你是一位细致的编程代码评审员。
+        你的目标是分析用户代码的正确性、风格和效率。
+        
+        你配备了一个 'code_runner' 工具,可以用来执行 Python 代码。
+        
+        **重要:代码形式识别**
+        - 代码片段(Code Snippet):可以直接运行的简短代码,如变量赋值、简单计算等
+        - 函数定义(Function):以 def 开头,包含函数体的完整代码
+        - 不完整代码:缺少必要的语法元素(如未闭合的括号、缺少 return 等)
+        
+        **评审流程**:
+        1. **识别代码类型**:判断是代码片段还是函数定义
+        2. **运行代码**(推荐):使用 'code_runner' 工具执行代码,验证是否能正常运行
+        3. **分析逻辑**:检查代码逻辑是否正确,是否达到预期目标
+        4. **检查风格**:评估代码风格(变量命名、PEP8规范)
+        5. **性能分析**:提出优化建议(时间/空间复杂度)
+        6. **建设性反馈**:指出优点和改进空间
+        
+        **评审原则**:
+        - ✅ 如果代码可以正常运行,不要说它"不完整"
+        - ✅ 针对实际代码逻辑进行评审,而不是臆测用户意图
+        - ✅ 区分"代码片段"和"需要函数封装"的建议
+        - ✅ 先肯定做得好的地方,再提出改进建议
+        
+        如果代码有错误,解释原因并提供修复提示,但不要直接给出完整的解决方案,除非用户多次尝试失败。
+        """
+        self.knowledge = knowledge_service
+        super().__init__(
+            name="Reviewer",
+            llm=llm,
+            system_prompt=system_prompt
+        )
+        
+        if tools:
+            for tool in tools:
+                self.add_tool(tool)
+
+    def run(self, input_text: str, max_tool_iterations: int = 3, **kwargs) -> str:
+        result = super().run(input_text, max_tool_iterations, **kwargs)
+        self.knowledge.add_note(
+            content=f"代码评审结论:{result}",
+            concept="code_review"
+        )
+        return result

+ 114 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/agents/tutor.py

@@ -0,0 +1,114 @@
+from hello_agents import SimpleAgent, HelloAgentsLLM
+from typing import Dict, Any
+
+class TutorAgent(SimpleAgent):
+    """
+    主要协调智能体,直接管理 Planner、Exercise 和 Reviewer 子智能体。
+    使用简单的直接调用模式,不依赖 A2A 协议。
+    """
+    
+    def __init__(self, llm: HelloAgentsLLM, knowledge_service):
+        """
+        初始化 TutorAgent 和所有子智能体。
+        
+        Args:
+            llm: 用于所有 agents 的大语言模型实例。
+        """
+        # 导入放在这里避免循环导入
+        from agents.planner import PlannerAgent
+        from agents.exercise import ExerciseAgent
+        from agents.reviewer import ReviewerAgent
+        from tools.code_runner import CodeRunner
+        from tools.agent_tool import AgentTool
+        self.knowledge = knowledge_service
+        # 创建子智能体实例
+        self.planner = PlannerAgent(llm, knowledge_service)
+        self.exercise = ExerciseAgent(llm)
+        self.reviewer = ReviewerAgent(llm, tools=[CodeRunner()], knowledge_service=knowledge_service)
+        
+        # 定义系统提示词
+        system_prompt = """
+        你是一位智能编程导师 (Tutor)。你负责协调个性化的学习体验。
+        
+        你拥有以下专业助手(工具):
+        - call_planner: 课程规划师,制定个性化学习计划, 回顾已经创建过的学习计划
+        - call_exercise: 出题人,生成编程练习题
+        - call_reviewer: 评审员,评审代码并提供反馈
+        
+        **关键:你必须使用工具,不能自己完成这些任务!**
+        
+        工具调用格式(严格遵守此格式):
+        [TOOL_CALL:工具名称:参数]
+        
+        具体示例:
+        
+        示例1 - 学习计划:
+        用户:"我想学习Python中的列表推导式"
+        你的回答:[TOOL_CALL:call_planner:query=请为学习Python列表推导式制定学习计划]
+        
+        示例2 - 回顾学习计划:
+        用户:"我想回顾Python中的列表推导式的学习计划"
+        你的回答:[TOOL_CALL:call_planner:query=请回顾Python中的列表推导式的学习计划]
+        
+        示例3 - 练习题:
+        用户:"请给我出一道编程题目"
+        你的回答:[TOOL_CALL:call_exercise:query=请给我出一道编程题目]
+        
+        示例4 - 代码评审(最重要!):
+        用户:"请评审以下代码: numbers = [1, 2, 3]"
+        你的回答:[TOOL_CALL:call_reviewer:query=请评审以下代码: numbers = [1, 2, 3]]
+        
+        工作流程(必须严格遵守):
+        1. 当用户表达学习目标时 → 立即调用 call_planner
+        2. 当用户请求编程题时 → 立即调用 call_exercise  
+        3. 当用户提交代码或请求评审时 → 立即调用 call_reviewer
+        
+        **绝对禁止的行为**:
+        - ❌ 不要自己制定学习计划
+        - ❌ 不要自己出练习题
+        - ❌ 不要自己评审代码(即使代码很简单)
+        - ❌ 不要说"工具调用失败"然后自己完成任务
+        
+        正确的行为:
+        - ✅ 识别用户意图
+        - ✅ 立即生成工具调用(格式:[TOOL_CALL:工具名:query=...])
+        - ✅ 等待工具返回结果
+        - ✅ 将结果友好地呈现给用户
+        """
+        
+        # 初始化父类
+        super().__init__(
+            name="Tutor",
+            llm=llm,
+            system_prompt=system_prompt
+        )
+
+        # 简单的用户标识
+        self.user_id = "default_user"
+        self.current_problem = []
+
+        # 将子智能体包装为工具并注册
+        self.add_tool(AgentTool(
+            self.planner,
+            name="call_planner",
+            description="调用课程规划师,为用户制定个性化的学习计划"
+        ))
+        
+        self.add_tool(AgentTool(
+            self.exercise,
+            name="call_exercise",
+            description="调用出题人,根据学习内容生成编程练习题"
+        ))
+        
+        self.add_tool(AgentTool(
+            self.reviewer,
+            name="call_reviewer",
+            description="调用评审员,对用户提交的代码进行评审和反馈"
+        ))
+
+
+    # def run(self, input_text: str, max_tool_iterations: int = 3, **kwargs) -> str:
+    #     result = super().run(input_text)
+    #     return result
+
+

+ 37 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/data/README.md

@@ -0,0 +1,37 @@
+# 编程题库数据集(Practice Question Bank)
+
+本仓库提供智能编程导师系统所使用的**编程题库数据**,用于支持基于 RAG(检索增强生成)的练习题检索与生成。
+
+## 📦 数据内容说明
+
+题库数据主要用于以下场景:
+- 根据学习计划与当前阶段检索匹配的编程练习题
+- 支持不同难度
+- 作为智能编程导师系统的离线知识源
+
+具体题目结构与字段说明请参考项目代码中的数据加载与解析模块。
+
+## 🔗 数据下载地址
+
+- **百度网盘链接**:  
+  https://pan.baidu.com/s/1UGCA9W3yT2_lLbTEz_2RLg
+
+- **提取码**:  
+  `i8v1`
+
+## 📁 使用方式
+
+1. 下载并解压题库数据
+2. 将数据目录放置到项目指定路径(如 `data/`)
+3. 在exercise.py代码中指定题库路径
+4. 启动系统即可通过 RAG 模块进行题目检索
+
+## ⚠️ 注意事项
+
+- 本题库仅用于**学习、研究与非商业用途**
+- 如用于公开展示或二次分发,请注明来源
+- 若题库内容有更新,将在仓库中同步说明
+
+## 🙏 致谢
+
+感谢社区开源资源与数据整理者的贡献,为智能教学系统研究与实践提供了重要支持。

+ 35 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/main.py

@@ -0,0 +1,35 @@
+import os
+import sys
+from dotenv import load_dotenv
+from hello_agents.core.llm import HelloAgentsLLM
+from services.knowledge import LearningKnowledgeService
+
+# 2. 初始化 Tutor(自动创建所有子智能体)
+from agents.tutor import TutorAgent
+
+load_dotenv()
+
+if "src" not in sys.path:
+    sys.path.append(os.path.abspath("src"))
+
+# 初始化 LLM
+llm = HelloAgentsLLM()
+
+print("✅ 环境配置完成")
+print("✅ LLM 已初始化")
+
+print("创建智能编程导师...")
+knowledge = LearningKnowledgeService(user_id="1")
+tutor = TutorAgent(llm, knowledge)
+
+while True:
+    user_goal = input("请输入:")
+    # 我想学习 Python 中的列表推导式
+    # 我想更新学习计划
+    print(f"用户目标: {user_goal}\n")
+
+    # Tutor 会调用 call_planner 工具
+    response = tutor.run(f"用户说:'{user_goal}'。")
+
+    print("=== Tutor 回应 ===")
+    print(response)

+ 71 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_001617_12.md

@@ -0,0 +1,71 @@
+---
+id: note_20251222_001617_12
+title: 学习计划
+type: general
+tags: ["learning-plan", "planner"]
+created_at: 2025-12-22T00:16:17.374040
+updated_at: 2025-12-22T00:16:17.374040
+---
+
+# 学习计划
+
+### 学习计划
+
+# 学习主题:Python 列表推导式
+
+## 学习目标
+- 理解列表推导式的语法结构和基本用法。
+- 掌握列表推导式在数据过滤、转换和生成中的实际应用。
+- 能够在代码中用列表推导式替代传统循环+append的写法,提升代码简洁性和可读性。
+- 比较列表推导式与生成器表达式、map/filter函数的异同。
+- 能在项目中灵活运用列表推导式解决常见编程问题。
+
+## 学习路径
+1. 第一阶段:列表推导式基础语法 []  
+   - 关键概念:
+     - 列表推导式的基本语法 `[expression for item in iterable]`
+     - 列表推导式与普通for循环的区别
+     - 无条件列表推导式(直接转换)
+     - 基础示例:平方数、偶数提取、字符串大写等
+
+2. 第二阶段:带条件的列表推导式 []  
+   - 关键概念:
+     - 条件语句语法 `[expression for item in iterable if condition]`
+     - 多层条件嵌套
+     - 在列表推导式中使用布尔表达式过滤数据
+     - 实际案例:筛选成绩、过滤非空字符串、奇偶分组
+
+3. 第三阶段:嵌套列表推导式 []  
+   - 关键概念:
+     - 嵌套循环结构在列表推导式中的体现
+     - 如何处理二维列表、矩阵转置、笛卡尔积等场景
+     - 避免过度嵌套导致可读性下降
+     - 示例:生成坐标对、矩阵乘法元素计算
+
+4. 第四阶段:性能与风格对比 []  
+   - 关键概念:
+     - 列表推导式 vs map/filter + lambda 函数
+     - 列表推导式 vs 传统for循环性能分析(可用timeit测试)
+     - Python官方推荐风格:何时用列表推导式,何时不用
+     - 可读性优先原则:避免过度复杂嵌套
+
+5. 第五阶段:实战项目练习 []  
+   - 关键概念:
+     - 使用列表推导式重构现有代码片段(如数据清洗、格式化输出)
+     - 从真实项目中提取需求并设计列表推导式解决方案
+     - 提交代码并通过评审(如GitHub或在线平台)
+
+## 学习建议
+- 每完成一个阶段后,尝试自己编写至少3个不同场景下的列表推导式。
+- 对比传统写法和列表推导式版本,思考优劣。
+- 阅读Python官方文档中关于列表推导式的部分。
+- 尝试将列表推导式应用于NumPy/Pandas数据处理场景(进阶)。
+- 不要追求“炫技”,优先保证代码清晰易懂。
+
+```markdown
+- [ ] 第一阶段:列表推导式基础语法
+- [ ] 第二阶段:带条件的列表推导式
+- [ ] 第三阶段:嵌套列表推导式
+- [ ] 第四阶段:性能与风格对比
+- [ ] 第五阶段:实战项目练习
+```

+ 71 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_001749_13.md

@@ -0,0 +1,71 @@
+---
+id: note_20251222_001749_13
+title: 学习计划
+type: general
+tags: ["learning-plan", "planner"]
+created_at: 2025-12-22T00:17:49.761113
+updated_at: 2025-12-22T00:17:49.761113
+---
+
+# 学习计划
+
+### 学习计划
+
+# 学习主题:Python 列表推导式
+
+## 学习目标
+- 理解列表推导式的语法结构和基本用法。
+- 掌握列表推导式在数据过滤、转换和生成中的实际应用。
+- 能够在代码中用列表推导式替代传统循环+append的写法,提升代码简洁性和可读性。
+- 比较列表推导式与生成器表达式、map/filter函数的异同。
+- 能在项目中灵活运用列表推导式解决常见编程问题。
+
+## 学习路径
+1. 第一阶段:列表推导式基础语法 []  
+   - 关键概念:
+     - 列表推导式的基本语法 `[expression for item in iterable]`
+     - 列表推导式与普通for循环的区别
+     - 无条件列表推导式(直接转换)
+     - 基础示例:平方数、偶数提取、字符串大写等
+
+2. 第二阶段:带条件的列表推导式 []  
+   - 关键概念:
+     - 条件语句语法 `[expression for item in iterable if condition]`
+     - 多层条件嵌套
+     - 在列表推导式中使用布尔表达式过滤数据
+     - 实际案例:筛选成绩、过滤非空字符串、奇偶分组
+
+3. 第三阶段:嵌套列表推导式 []  
+   - 关键概念:
+     - 嵌套循环结构在列表推导式中的体现
+     - 如何处理二维列表、矩阵转置、笛卡尔积等场景
+     - 避免过度嵌套导致可读性下降
+     - 示例:生成坐标对、矩阵乘法元素计算
+
+4. 第四阶段:性能与风格对比 []  
+   - 关键概念:
+     - 列表推导式 vs map/filter + lambda 函数
+     - 列表推导式 vs 传统for循环性能分析(可用timeit测试)
+     - Python官方推荐风格:何时用列表推导式,何时不用
+     - 可读性优先原则:避免过度复杂嵌套
+
+5. 第五阶段:实战项目练习 []  
+   - 关键概念:
+     - 使用列表推导式重构现有代码片段(如数据清洗、格式化输出)
+     - 从真实项目中提取需求并设计列表推导式解决方案
+     - 提交代码并通过评审(如GitHub或在线平台)
+
+## 学习建议
+- 每完成一个阶段后,尝试自己编写至少3个不同场景下的列表推导式。
+- 对比传统写法和列表推导式版本,思考优劣。
+- 阅读Python官方文档中关于列表推导式的部分。
+- 尝试将列表推导式应用于NumPy/Pandas数据处理场景(进阶)。
+- 不要追求“炫技”,优先保证代码清晰易懂。
+
+```markdown
+- [ ] 第一阶段:列表推导式基础语法
+- [ ] 第二阶段:带条件的列表推导式
+- [ ] 第三阶段:嵌套列表推导式
+- [ ] 第四阶段:性能与风格对比
+- [ ] 第五阶段:实战项目练习
+```

+ 64 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_002318_14.md

@@ -0,0 +1,64 @@
+---
+id: note_20251222_002318_14
+title: 学习计划
+type: general
+tags: ["learning-plan", "planner"]
+created_at: 2025-12-22T00:23:18.286681
+updated_at: 2025-12-22T00:23:18.286681
+---
+
+# 学习计划
+
+### 学习计划
+
+# 学习主题:Python 列表推导式
+
+## 学习目标
+- 理解列表推导式的语法结构和基本用途。
+- 掌握列表推导式在数据过滤、转换和生成中的实际应用。
+- 能够将传统 for 循环 + append 的写法重构为更简洁高效的列表推导式。
+- 通过练习熟练运用条件表达式(if/else)嵌套在列表推导式中。
+- 比较列表推导式与 map/filter 函数的性能与可读性差异。
+
+## 学习路径
+1. 第一阶段:列表推导式基础语法 []  
+   - 关键概念:
+     - 基本语法:`[expression for item in iterable]`
+     - 示例:生成平方数列表 `[x**2 for x in range(10)]`
+     - 不使用循环和 append 的优势对比
+
+2. 第二阶段:带条件筛选的列表推导式 []  
+   - 关键概念:
+     - 条件过滤语法:`[expression for item in iterable if condition]`
+     - 示例:筛选偶数 `[x for x in range(20) if x % 2 == 0]`
+     - 多层条件组合
+
+3. 第三阶段:嵌套条件与复杂表达式 []  
+   - 关键概念:
+     - 使用 `if else` 在表达式中嵌套:`[x if x%2==0 else -x for x in range(5)]`
+     - 多重嵌套列表推导式(如二维矩阵变换)
+     - 避免过度嵌套导致代码难以维护
+
+4. 第四阶段:列表推导式 vs map/filter []  
+   - 关键概念:
+     - 对比 `map()` 和 `filter()` 的用法及效率
+     - 何时选择列表推导式,何时选择函数式编程工具
+     - 可读性与性能权衡分析
+
+5. 第五阶段:实战项目与优化练习 []  
+   - 关键概念:
+     - 实战题目:从字符串列表中提取长度大于5的单词
+     - 数据清洗示例:去除空字符串并转小写
+     - 性能测试:比较列表推导式 vs for 循环 vs map
+     - 重构已有代码为列表推导式
+
+## 学习建议
+- 优先掌握基础语法后再尝试条件嵌套。
+- 多动手编写例子,避免死记硬背。
+- 阅读他人代码时注意是否存在可以简化为列表推导式的部分。
+- 避免滥用列表推导式——当逻辑复杂时,优先考虑可读性。
+- 推荐资源:Python 官方文档、《流畅的 Python》第 5 章、LeetCode 中相关题目。
+
+---
+
+请确保整个学习计划是一个完整、可直接保存的 Markdown 文档。

+ 58 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/note_20251222_003209_15.md

@@ -0,0 +1,58 @@
+---
+id: note_20251222_003209_15
+title: 学习计划
+type: general
+tags: ["learning-plan", "planner"]
+created_at: 2025-12-22T00:32:09.002895
+updated_at: 2025-12-22T00:32:09.002895
+---
+
+# 学习计划
+
+### 学习计划
+
+# 学习主题:Python 列表推导式
+
+## 学习目标
+- 理解列表推导式的语法结构和基本用法。
+- 掌握列表推导式在数据过滤、转换和生成中的实际应用。
+- 能够对比列表推导式与传统 for 循环的性能和可读性差异。
+- 能独立编写复杂嵌套列表推导式解决实际问题。
+
+## 学习路径
+1. 第一阶段:列表推导式基础语法 []  
+   - 关键概念  
+     - 基本语法结构 `[expression for item in iterable]`  
+     - 表达式 vs 循环体  
+     - 简单示例(如平方数、偶数筛选)  
+
+2. 第二阶段:条件过滤与嵌套结构 []  
+   - 关键概念  
+     - 条件语句 `if condition` 的添加位置(前/后)  
+     - 嵌套列表推导式(如二维数组扁平化、矩阵转置)  
+     - 多层条件判断  
+
+3. 第三阶段:与传统循环对比及实战应用 []  
+   - 关键概念  
+     - 与 for 循环代码对比(可读性、性能差异)  
+     - 实战案例:数据清洗、字符串处理、数学运算  
+     - 使用列表推导式重构已有函数  
+
+4. 第四阶段:高级技巧与最佳实践 []  
+   - 关键概念  
+     - 使用函数表达式(lambda)嵌入推导式  
+     - 避免常见陷阱(如副作用、性能瓶颈)  
+     - 性能测试与调试技巧  
+
+## 学习建议
+- 每完成一个阶段,尝试写 3 个不同场景的应用练习。
+- 使用 Python Tutor 或 Jupyter Notebook 观察执行过程。
+- 对比相同功能的传统循环版本,思考为何列表推导式更优。
+- 尝试阅读开源项目中如何使用列表推导式提升代码简洁性。
+
+```markdown
+- [ ] 第一阶段:列表推导式基础语法
+- [ ] 第二阶段:条件过滤与嵌套结构
+- [ ] 第三阶段:与传统循环对比及实战应用
+- [ ] 第四阶段:高级技巧与最佳实践
+```

+ 168 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/notes/notes_index.json

@@ -0,0 +1,168 @@
+{
+  "notes": [
+    {
+      "id": "note_20251218_005353_0",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T00:53:53.741961"
+    },
+    {
+      "id": "note_20251218_010338_1",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T01:03:38.461378"
+    },
+    {
+      "id": "note_20251218_010541_2",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T01:05:41.350527"
+    },
+    {
+      "id": "note_20251218_010838_3",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T01:08:38.694208"
+    },
+    {
+      "id": "note_20251218_011500_4",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "progress"
+      ],
+      "created_at": "2025-12-18T01:15:00.063425"
+    },
+    {
+      "id": "note_20251218_145033_5",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T14:50:33.166185"
+    },
+    {
+      "id": "note_20251218_145805_6",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T14:58:05.724763"
+    },
+    {
+      "id": "note_20251218_155950_7",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T15:59:50.969192"
+    },
+    {
+      "id": "note_20251218_160033_8",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T16:00:33.369281"
+    },
+    {
+      "id": "note_20251218_161848_9",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T16:18:48.058754"
+    },
+    {
+      "id": "note_20251218_170211_10",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T17:02:11.756431"
+    },
+    {
+      "id": "note_20251218_171050_11",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-18T17:10:50.309354"
+    },
+    {
+      "id": "note_20251222_001617_12",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-22T00:16:17.374040"
+    },
+    {
+      "id": "note_20251222_001749_13",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-22T00:17:49.761113"
+    },
+    {
+      "id": "note_20251222_002318_14",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-22T00:23:18.286681"
+    },
+    {
+      "id": "note_20251222_003209_15",
+      "title": "学习计划",
+      "type": "general",
+      "tags": [
+        "learning-plan",
+        "planner"
+      ],
+      "created_at": "2025-12-22T00:32:09.002895"
+    }
+  ],
+  "metadata": {
+    "created_at": "2025-12-18T00:49:44.771082",
+    "total_notes": 16
+  }
+}

+ 0 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/__init__.py


+ 98 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/knowledge.py

@@ -0,0 +1,98 @@
+# services/learning_knowledge_service.py
+
+from hello_agents.tools import MemoryTool, RAGTool
+from datetime import datetime
+from typing import Optional
+
+
+class LearningKnowledgeService:
+    """
+    学习记忆 + 知识检索服务
+    供多智能体通过 A2A 调用
+    """
+
+    def __init__(self, user_id: str):
+        self.user_id = user_id
+        self.session_id = f"session_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
+
+        self.memory = MemoryTool(user_id=user_id)
+        self.rag = RAGTool(rag_namespace=f"learning_{user_id}")
+        self.active_learning_plan = {}
+
+    def set_active_learning_plan(self, plan_id: str):
+        self.active_learning_plan_id = plan_id
+
+    def get_active_learning_plan(self):
+        return self.active_learning_plan_id
+
+    # ======================
+    # 知识库相关
+    # ======================
+    def add_learning_material(self, file_path: str):
+        return self.rag.run({
+            "action": "add_document",
+            "file_path": file_path,
+            "chunk_size": 1000,
+            "chunk_overlap": 200
+        })
+
+    def ask_knowledge(self, question: str):
+        self._log_working_memory(f"提问: {question}")
+        answer = self.rag.run({
+            "action": "ask",
+            "question": question,
+            "limit": 5,
+            "enable_advanced_search": True,
+            "enable_mqe": True,
+            "enable_hyde": True
+        })
+
+        self._log_episodic_memory(f"围绕问题 `{question}` 的学习")
+        return answer
+
+    # ======================
+    # 记忆系统
+    # ======================
+    def add_note(self, content: str, concept: Optional[str] = None):
+        self.memory.run({
+            "action": "add",
+            "content": content,
+            "memory_type": "semantic",
+            "importance": 0.8,
+            "concept": concept or "general",
+            "session_id": self.session_id
+        })
+
+    def recall(self, query: str):
+        return self.memory.run({
+            "action": "search",
+            "query": query,
+            "limit": 5
+        })
+
+    def summarize_learning(self):
+        return self.memory.run({
+            "action": "summary",
+            "limit": 10
+        })
+
+    # ======================
+    # 内部日志
+    # ======================
+    def _log_working_memory(self, content: str):
+        self.memory.run({
+            "action": "add",
+            "content": content,
+            "memory_type": "working",
+            "importance": 0.6,
+            "session_id": self.session_id
+        })
+
+    def _log_episodic_memory(self, content: str):
+        self.memory.run({
+            "action": "add",
+            "content": content,
+            "memory_type": "episodic",
+            "importance": 0.7,
+            "session_id": self.session_id
+        })

+ 118 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/services/problem_repository.py

@@ -0,0 +1,118 @@
+import os
+import re
+from typing import List, Dict
+
+
+class ProblemRepository:
+    def __init__(self, root_dir="E:\PycharmProject_lmx\HelloAgents-main\output"):
+        self.root_dir = root_dir
+        self.problems = self._load_all_problems()
+
+    def _load_all_problems(self) -> List[Dict]:
+        problems = []
+
+        for dirname in os.listdir(self.root_dir):
+            readme_path = os.path.join(self.root_dir, dirname, "README.md")
+            if not os.path.exists(readme_path):
+                continue
+
+            with open(readme_path, "r", encoding="utf-8") as f:
+                content = f.read()
+
+            problem = self._parse_problem(content)
+            if problem:
+                problem["slug"] = dirname
+                problem["path"] = readme_path
+                problem["content"] = content
+                problems.append(problem)
+
+        return problems
+
+    def _parse_problem(self, text: str) -> Dict | None:
+        title = self._extract(r"# \[(.*?)\]", text)
+        if not title:
+            return None
+
+        description = self._extract_block(
+            text,
+            start="## Description",
+            end="\\*\\*Example"
+        )
+
+        examples = self._parse_examples(text)
+
+        constraints = self._extract_block(
+            text,
+            start="\\*\\*Constraints:\\*\\*",
+            end="\\*\\*Follow-up"
+        )
+
+        tags = self._extract(r"\*\*Tags:\*\*(.*)", text)
+        difficulty = self._extract(r"\*\*Difficulty:\*\*(.*)", text)
+
+        return {
+            "title": title.strip(),
+            "description": description.strip() if description else "",
+            "examples": examples,
+            "constraints": constraints.strip() if constraints else "",
+            "tags": [t.strip() for t in tags.split(",")] if tags else [],
+            "difficulty": difficulty.strip() if difficulty else "Unknown",
+        }
+
+    def _extract_block(self, text: str, start: str, end: str) -> str | None:
+        pattern = rf"{start}(.*?){end}"
+        match = re.search(pattern, text, re.S)
+        return match.group(1) if match else None
+
+    def _parse_examples(self, text: str) -> List[Dict]:
+        examples = []
+
+        pattern = re.compile(
+            r"\*\*Example\s*\d+:\*\*(.*?)(?=\*\*Example|\*\*Constraints|\Z)",
+            re.S
+        )
+
+        for block in pattern.findall(text):
+            input_ = self._extract(
+                r"Input:\s*(.*?)(?=\s*Output:|\s*Explanation:|\Z)",
+                block
+            )
+
+            output = self._extract(
+                r"Output:\s*(.*?)(?=\s*Explanation:|\Z)",
+                block
+            )
+
+            explanation = self._extract(
+                r"Explanation:\s*(.*)",
+                block
+            )
+
+            examples.append({
+                "input": input_.strip() if input_ else "",
+                "output": output.strip() if output else "",
+                "explanation": explanation.strip() if explanation else ""
+            })
+
+        return examples
+
+    def _extract(self, pattern: str, text: str) -> str | None:
+        match = re.search(pattern, text)
+        return match.group(1) if match else None
+
+    def filter(self, *, tags=None, difficulty=None) -> List[Dict]:
+        results = self.problems
+
+        if tags:
+            results = [
+                p for p in results
+                if any(tag in p["tags"] for tag in tags)
+            ]
+
+        if difficulty:
+            results = [
+                p for p in results
+                if p["difficulty"].lower() == difficulty.lower()
+            ]
+
+        return results

+ 54 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/agent_tool.py

@@ -0,0 +1,54 @@
+"""
+AgentTool: 将 SimpleAgent 包装为 Tool,实现直接调用
+这是比 A2A 协议更简单的多智能体模式
+"""
+from hello_agents import SimpleAgent
+from hello_agents.tools import Tool
+from typing import Dict, Any
+
+class AgentTool(Tool):
+    """将一个 SimpleAgent 包装为可被其他 Agent 调用的工具"""
+    
+    def __init__(self, agent: SimpleAgent, name: str, description: str):
+        """
+        Args:
+            agent: 要包装的 SimpleAgent 实例
+            name: 工具名称
+            description: 工具描述
+        """
+        self.agent = agent
+        self._name = name
+        self._description = description
+    
+    @property
+    def name(self) -> str:
+        return self._name
+    
+    @property
+    def description(self) -> str:
+        return self._description
+    
+    def get_parameters(self) -> list:
+        """定义工具参数"""
+        from hello_agents.tools.base import ToolParameter
+        return [
+            ToolParameter(
+                name="query",
+                type="string",
+                description="发送给智能体的查询或指令",
+                required=True
+            )
+        ]
+    
+    def run(self, parameters: Dict[str, Any]) -> str:
+        """执行工具 - 直接调用被包装的 agent"""
+        query = parameters.get('query', '')
+        
+        if not query:
+            return "错误:需要提供 query 参数"
+        
+        try:
+            # 直接调用 agent 的 run 方法
+            return self.agent.run(query)
+        except Exception as e:
+            return f"调用 {self.name} 时出错: {str(e)}"

+ 68 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/code_runner.py

@@ -0,0 +1,68 @@
+
+import io
+import contextlib
+from hello_agents.tools import Tool
+from typing import Dict, Any
+
+class CodeRunner(Tool):
+    """
+    安全执行 Python 代码并返回输出的工具。
+    警告:此工具使用 exec(),在生产环境中不安全。
+    对于真实产品,请使用 Docker 等沙箱环境。
+    """
+    
+    def __init__(self):
+        super().__init__(
+            name="code_runner",
+            description="执行 Python 代码并返回标准输出/错误。输入应为包含 'code' 键的字典。"
+        )
+
+    def get_parameters(self) -> Dict[str, Any]:
+        return {
+            "type": "object",
+            "properties": {
+                "code": {
+                    "type": "string",
+                    "description": "要执行的 Python 代码片段"
+                }
+            },
+            "required": ["code"]
+        }
+
+    def run(self, parameters: Dict[str, Any]) -> str:
+        code = parameters.get("code", "")
+        if not code:
+            return "错误:未提供代码。"
+
+        # 捕获标准输出和标准错误
+        stdout_capture = io.StringIO()
+        stderr_capture = io.StringIO()
+
+        try:
+            with contextlib.redirect_stdout(stdout_capture), contextlib.redirect_stderr(stderr_capture):
+                # 创建受限的全局作用域
+                safe_globals = {
+                    "__builtins__": __builtins__,
+                    "print": print,
+                    "range": range,
+                    "len": len,
+                    # 根据需要添加更多安全的内置函数
+                }
+                exec(code, safe_globals)
+            
+            output = stdout_capture.getvalue()
+            errors = stderr_capture.getvalue()
+            
+            result = ""
+            if output:
+                result += f"输出:\n{output}\n"
+            if errors:
+                result += f"错误:\n{errors}\n"
+            
+            if not result:
+                result = "代码执行成功,无输出。"
+                
+            return result
+
+        except Exception as e:
+            return f"运行时错误: {str(e)}"

+ 63 - 0
Co-creation-projects/lll0807-CodeTutorAgent/programmer/tools/note_tools.py

@@ -0,0 +1,63 @@
+from hello_agents.tools.builtin.note_tool import NoteTool
+
+class LearningNotesService:
+    def __init__(self, workspace: str):
+        self.note_tool = NoteTool(workspace=workspace)
+
+    def save_learning_progress(
+        self,
+        user_id: str,
+        progress: "LearningProgress"
+    ):
+        """保存学习路径与进度"""
+        content = self._format_learning_content(progress)
+
+        self.note_tool.run({
+            "action": "create",
+            "title": f"学习进度|{progress.topic}",
+            "content": content,
+            "tags": [
+                "learning",
+                "progress",
+                progress.level,
+                user_id
+            ]
+        })
+
+    def _format_learning_content(self, progress: "LearningProgress") -> str:
+        content = f"# 学习主题:{progress.topic}\n\n"
+        content += f"**当前水平**:{progress.level}\n\n"
+
+        # 学习路径
+        content += "## 学习路径\n\n"
+        for idx, step in enumerate(progress.steps, start=1):
+            status_icon = {
+                "completed": "✅",
+                "in_progress": "⏳",
+                "not_started": "⬜"
+            }.get(step.status, "⬜")
+
+            content += f"{idx}. {status_icon} **{step.title}**\n"
+            if step.notes:
+                content += f"   - 备注:{step.notes}\n"
+        content += "\n"
+
+        # 掌握点
+        if progress.mastered_points:
+            content += "## 已掌握知识点\n\n"
+            for p in progress.mastered_points:
+                content += f"- ✅ {p}\n"
+            content += "\n"
+
+        # 薄弱点
+        if progress.weak_points:
+            content += "## 薄弱点\n\n"
+            for p in progress.weak_points:
+                content += f"- ⚠️ {p}\n"
+            content += "\n"
+
+        # 下一步建议
+        content += "## 下一步学习建议\n\n"
+        content += f"{progress.next_suggestion}\n"
+
+        return content