| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- """Code Plan Agent - 智能代码计划工具,具备Reflection反思功能"""
- import json
- from typing import Optional, List, Dict, Any, AsyncGenerator
- from datetime import datetime
- from hello_agents.core.agent import Agent
- from hello_agents.core.llm import HelloAgentsLLM
- from hello_agents.core.config import Config
- from hello_agents.core.message import Message
- from hello_agents.core.streaming import StreamEvent, StreamEventType
- from hello_agents.core.lifecycle import LifecycleHook
- from hello_agents.tools.registry import ToolRegistry
- class PlanMemory:
- """
- 计划记忆模块,用于存储代码计划的生成轨迹和反思记录
- """
- def __init__(self):
- self.records: List[Dict[str, Any]] = []
- def add_record(self, record_type: str, content: str, metadata: Optional[Dict] = None):
- """向记忆中添加一条新记录"""
- self.records.append({
- "type": record_type,
- "content": content,
- "metadata": metadata or {},
- "timestamp": datetime.now().isoformat()
- })
- def get_trajectory(self) -> str:
- """将所有记忆记录格式化为一个连贯的字符串文本"""
- trajectory = ""
- for record in self.records:
- if record['type'] == 'plan':
- trajectory += f"--- 代码计划 ---\n{record['content']}\n\n"
- elif record['type'] == 'reflection':
- trajectory += f"--- 反思反馈 ---\n{record['content']}\n\n"
- elif record['type'] == 'revision':
- trajectory += f"--- 优化后计划 ---\n{record['content']}\n\n"
- return trajectory.strip()
- def get_last_plan(self) -> str:
- """获取最近一次的代码计划"""
- for record in reversed(self.records):
- if record['type'] in ['plan', 'revision']:
- return record['content']
- return ""
- def get_last_reflection(self) -> str:
- """获取最近一次的反思反馈"""
- for record in reversed(self.records):
- if record['type'] == 'reflection':
- return record['content']
- return ""
- class CodePlanAgent(Agent):
- """
- Code Plan Agent - 智能代码计划工具,具备Reflection反思功能
- 核心能力:
- 1. 代码计划生成:根据需求描述生成结构化的代码实现计划
- 2. 自我反思:对生成的代码计划进行质量评估和改进建议
- 3. 迭代优化:根据反思结果优化代码计划
- 4. 支持工具调用(可选)
- 输出格式:
- - 代码计划采用结构化格式,包含多个步骤
- - 每个步骤包含:步骤编号、任务描述、实现要点、预期输出
- 反思维度:
- - 完整性:计划是否覆盖所有需求
- - 可行性:技术方案是否可行
- - 效率:是否存在性能优化空间
- - 可维护性:代码结构是否清晰
- - 安全性:是否存在安全风险
- """
- def __init__(
- self,
- name: str,
- llm: HelloAgentsLLM,
- system_prompt: Optional[str] = None,
- config: Optional[Config] = None,
- max_reflection_iterations: int = 2,
- tool_registry: Optional['ToolRegistry'] = None,
- enable_tool_calling: bool = True,
- max_tool_iterations: int = 3
- ):
- """
- 初始化CodePlanAgent
- Args:
- name: Agent名称
- llm: LLM实例
- system_prompt: 系统提示词(定义角色和行为)
- config: 配置对象
- max_reflection_iterations: 最大反思迭代次数
- tool_registry: 工具注册表(可选)
- enable_tool_calling: 是否启用工具调用
- max_tool_iterations: 最大工具调用迭代次数
- """
- # 默认 system_prompt - 代码规划专家
- default_system_prompt = """你是一位资深的软件架构师和代码规划专家。
- 你擅长将业务需求转化为清晰、可行的代码实现计划。
- ## 核心职责
- 1. 分析需求并生成结构化的代码实现计划
- 2. 确保计划覆盖所有核心功能和边界情况
- 3. 设计合理的模块划分和接口定义
- 4. 考虑代码的可维护性、扩展性和性能
- ## 输出格式要求
- 请按照以下结构化格式输出代码计划:
- ```code_plan
- ## 项目概述
- [简要描述项目目标和核心功能]
- ## 技术栈
- - 语言:[编程语言]
- - 框架:[主要框架]
- - 数据库:[数据库类型]
- - 其他:[关键依赖]
- ## 目录结构
- ```
- [项目目录结构]
- ```
- ## 实现步骤
- 1. [步骤1描述]
- - 实现要点:[关键实现细节]
- - 文件路径:[涉及文件]
- - 预期输出:[预期结果]
- 2. [步骤2描述]
- - 实现要点:[关键实现细节]
- - 文件路径:[涉及文件]
- - 预期输出:[预期结果]
- ...
- ## 关键设计
- - [设计决策1]:[说明原因]
- - [设计决策2]:[说明原因]
- ## 注意事项
- - [注意事项1]
- - [注意事项2]
- ```
- 请确保计划详细、清晰、可执行。"""
- super().__init__(
- name,
- llm,
- system_prompt or default_system_prompt,
- config,
- tool_registry=tool_registry
- )
- self.max_reflection_iterations = max_reflection_iterations
- self.memory = PlanMemory()
- self.enable_tool_calling = enable_tool_calling
- self.max_tool_iterations = max_tool_iterations
- def run(self, input_text: str, **kwargs) -> str:
- """
- 运行CodePlanAgent
- Args:
- input_text: 需求描述
- **kwargs: 其他参数(temperature, max_tokens等)
- Returns:
- 最终优化后的代码计划
- """
- print(f"\n🤖 {self.name} 开始处理代码规划任务: {input_text[:50]}...")
- # 重置记忆
- self.memory = PlanMemory()
- # 1. 生成初始代码计划
- print("\n--- 阶段1: 生成初始代码计划 ---")
- initial_plan = self._generate_code_plan(input_text, **kwargs)
- self.memory.add_record("plan", initial_plan, {"phase": "initial"})
- print(f"\n✅ 初始计划已生成:\n{initial_plan}")
- # 2. 迭代反思与优化
- for i in range(self.max_reflection_iterations):
- print(f"\n--- 阶段2: 第 {i+1}/{self.max_reflection_iterations} 轮反思优化 ---")
- # a. 反思当前计划
- print("\n-> 正在进行计划反思...")
- last_plan = self.memory.get_last_plan()
- reflection = self._reflect_on_plan(input_text, last_plan, **kwargs)
- self.memory.add_record("reflection", reflection, {"iteration": i + 1})
- print(f"\n💡 反思结果:\n{reflection}")
- # b. 检查是否需要停止
- if "无需改进" in reflection or "no need for improvement" in reflection.lower():
- print("\n✅ 反思认为计划已无需改进,任务完成。")
- break
- # c. 优化计划
- print("\n-> 正在优化代码计划...")
- refined_plan = self._refine_plan(input_text, last_plan, reflection, **kwargs)
- self.memory.add_record("revision", refined_plan, {"iteration": i + 1})
- print(f"\n🔄 优化后的计划:\n{refined_plan}")
- final_plan = self.memory.get_last_plan()
- print(f"\n--- 🎉 任务完成 ---\n最终代码计划:\n{final_plan}")
- # 保存到历史记录
- self.add_message(Message(input_text, "user"))
- self.add_message(Message(final_plan, "assistant"))
- return final_plan
- def _generate_code_plan(self, requirements: str, **kwargs) -> str:
- """
- 生成初始代码计划
- Args:
- requirements: 需求描述
- **kwargs: LLM调用参数
- Returns:
- 代码计划文本
- """
- messages = [
- {"role": "system", "content": self.system_prompt},
- {"role": "user", "content": f"""请根据以下需求描述,生成一份详细的代码实现计划:
- ## 需求描述
- {requirements}
- 请按照指定的格式输出代码计划。"""}
- ]
- return self._get_llm_response(messages, **kwargs)
- def _reflect_on_plan(self, requirements: str, plan: str, **kwargs) -> str:
- """
- 对代码计划进行反思评估
- Args:
- requirements: 原始需求
- plan: 当前代码计划
- **kwargs: LLM调用参数
- Returns:
- 反思反馈文本
- """
- reflection_prompt = f"""你是一位资深的技术评审专家。请对以下代码计划进行全面评估:
- ## 原始需求
- {requirements}
- ## 当前代码计划
- {plan}
- ## 评审维度
- 请从以下维度进行评估:
- 1. **完整性**:计划是否覆盖了所有核心需求?是否有遗漏的功能?
- 2. **可行性**:技术方案是否可行?是否存在技术风险?
- 3. **架构合理性**:模块划分是否合理?接口设计是否清晰?
- 4. **可维护性**:代码结构是否清晰?是否遵循最佳实践?
- 5. **性能考虑**:是否考虑了性能优化?是否存在潜在的性能瓶颈?
- 6. **安全性**:是否存在安全风险?是否需要添加安全措施?
- 7. **测试覆盖**:是否考虑了测试策略?关键路径是否有测试覆盖?
- ## 输出要求
- 请给出具体的改进建议。如果计划已经很好,请回答"无需改进"。"""
- messages = [
- {"role": "system", "content": "你是一位严格的技术评审专家,擅长发现代码计划中的潜在问题并提出改进建议。"},
- {"role": "user", "content": reflection_prompt}
- ]
- return self._get_llm_response(messages, **kwargs)
- def _refine_plan(self, requirements: str, current_plan: str, feedback: str, **kwargs) -> str:
- """
- 根据反馈优化代码计划
- Args:
- requirements: 原始需求
- current_plan: 当前代码计划
- feedback: 反思反馈
- **kwargs: LLM调用参数
- Returns:
- 优化后的代码计划
- """
- refinement_prompt = f"""请根据评审反馈优化以下代码计划:
- ## 原始需求
- {requirements}
- ## 当前代码计划
- {current_plan}
- ## 评审反馈
- {feedback}
- ## 优化要求
- 请根据反馈意见对代码计划进行修改和完善,确保:
- 1. 解决反馈中指出的所有问题
- 2. 保持计划的结构化格式
- 3. 提供具体的改进方案
- 请输出优化后的完整代码计划。"""
- messages = [
- {"role": "system", "content": self.system_prompt},
- {"role": "user", "content": refinement_prompt}
- ]
- return self._get_llm_response(messages, **kwargs)
- def _get_llm_response(self, messages: List[Dict[str, str]], **kwargs) -> str:
- """
- 调用LLM并获取完整响应(支持 Function Calling)
- Args:
- messages: 消息列表
- **kwargs: 其他参数
- Returns:
- LLM响应文本
- """
- # 如果没有启用工具调用,直接返回
- if not self.enable_tool_calling or not self.tool_registry:
- llm_response = self.llm.invoke(messages, **kwargs)
- return llm_response.content if hasattr(llm_response, 'content') else str(llm_response)
- # 启用工具调用模式
- tool_schemas = self._build_tool_schemas()
- current_iteration = 0
- while current_iteration < self.max_tool_iterations:
- current_iteration += 1
- try:
- response = self.llm.invoke_with_tools(
- messages=messages,
- tools=tool_schemas,
- tool_choice="auto",
- **kwargs
- )
- except Exception as e:
- print(f"❌ LLM 调用失败: {e}")
- break
- response_message = response.choices[0].message
- # 处理工具调用
- tool_calls = response_message.tool_calls
- if not tool_calls:
- # 没有工具调用,返回文本响应
- return response_message.content or ""
- # 将助手消息添加到历史
- messages.append({
- "role": "assistant",
- "content": response_message.content,
- "tool_calls": [
- {
- "id": tc.id,
- "type": "function",
- "function": {
- "name": tc.function.name,
- "arguments": tc.function.arguments
- }
- }
- for tc in tool_calls
- ]
- })
- # 执行所有工具调用
- for tool_call in tool_calls:
- tool_name = tool_call.function.name
- tool_call_id = tool_call.id
- try:
- arguments = json.loads(tool_call.function.arguments)
- except json.JSONDecodeError as e:
- print(f"❌ 工具参数解析失败: {e}")
- messages.append({
- "role": "tool",
- "tool_call_id": tool_call_id,
- "content": f"错误:参数格式不正确 - {str(e)}"
- })
- continue
- # 执行工具(复用基类方法)
- result = self._execute_tool_call(tool_name, arguments)
- # 添加工具结果到消息
- messages.append({
- "role": "tool",
- "tool_call_id": tool_call_id,
- "content": result
- })
- # 如果超过最大迭代次数,获取最后一次回答
- if current_iteration >= self.max_tool_iterations:
- llm_response = self.llm.invoke(messages, **kwargs)
- return llm_response.content if hasattr(llm_response, 'content') else str(llm_response)
- return ""
- async def arun_stream(
- self,
- input_text: str,
- on_start: LifecycleHook = None,
- on_finish: LifecycleHook = None,
- on_error: LifecycleHook = None,
- **kwargs
- ) -> AsyncGenerator[StreamEvent, None]:
- """
- CodePlanAgent 流式执行
- 实时返回:
- - 计划生成阶段的输出
- - 反思阶段的思考过程
- - 优化阶段的输出
- Args:
- input_text: 用户输入
- on_start: 开始钩子
- on_finish: 完成钩子
- on_error: 错误钩子
- **kwargs: 其他参数
- Yields:
- StreamEvent: 流式事件
- """
- # 发送开始事件
- yield StreamEvent.create(
- StreamEventType.AGENT_START,
- self.name,
- input_text=input_text
- )
- try:
- # 阶段 1:生成代码计划
- yield StreamEvent.create(
- StreamEventType.STEP_START,
- self.name,
- phase="plan_generation",
- description="生成初始代码计划"
- )
- messages = []
- if self.system_prompt:
- messages.append({"role": "system", "content": self.system_prompt})
- plan_prompt = f"""请根据以下需求描述,生成一份详细的代码实现计划:
- ## 需求描述
- {input_text}
- 请按照指定的格式输出代码计划。"""
- messages.append({"role": "user", "content": plan_prompt})
- initial_plan = ""
- async for chunk in self.llm.astream_invoke(messages, **kwargs):
- initial_plan += chunk
- yield StreamEvent.create(
- StreamEventType.LLM_CHUNK,
- self.name,
- chunk=chunk,
- phase="plan_generation"
- )
- yield StreamEvent.create(
- StreamEventType.STEP_FINISH,
- self.name,
- phase="plan_generation",
- result=initial_plan
- )
- # 阶段 2:反思与优化循环
- current_plan = initial_plan
- for iteration in range(self.max_reflection_iterations):
- # 反思阶段
- yield StreamEvent.create(
- StreamEventType.STEP_START,
- self.name,
- phase="reflection",
- iteration=iteration + 1,
- description=f"第 {iteration + 1} 次反思"
- )
- reflection_prompt = f"""你是一位资深的技术评审专家。请对以下代码计划进行全面评估:
- ## 原始需求
- {input_text}
- ## 当前代码计划
- {current_plan}
- ## 评审维度
- 请从以下维度进行评估:
- 1. 完整性:计划是否覆盖了所有核心需求?
- 2. 可行性:技术方案是否可行?
- 3. 架构合理性:模块划分是否合理?
- 4. 可维护性:代码结构是否清晰?
- 5. 性能考虑:是否考虑了性能优化?
- 6. 安全性:是否存在安全风险?
- 7. 测试覆盖:是否考虑了测试策略?
- 请给出具体的改进建议。如果计划已经很好,请回答"无需改进"。"""
- reflection_messages = [{"role": "user", "content": reflection_prompt}]
- reflection = ""
- async for chunk in self.llm.astream_invoke(reflection_messages, **kwargs):
- reflection += chunk
- yield StreamEvent.create(
- StreamEventType.THINKING,
- self.name,
- chunk=chunk,
- phase="reflection",
- iteration=iteration + 1
- )
- yield StreamEvent.create(
- StreamEventType.STEP_FINISH,
- self.name,
- phase="reflection",
- iteration=iteration + 1,
- reflection=reflection
- )
- # 检查是否需要停止
- if "无需改进" in reflection or "no need for improvement" in reflection.lower():
- break
- # 优化阶段
- yield StreamEvent.create(
- StreamEventType.STEP_START,
- self.name,
- phase="refinement",
- iteration=iteration + 1,
- description=f"第 {iteration + 1} 次优化"
- )
- refinement_prompt = f"""请根据评审反馈优化以下代码计划:
- ## 原始需求
- {input_text}
- ## 当前代码计划
- {current_plan}
- ## 评审反馈
- {reflection}
- 请输出优化后的完整代码计划。"""
- refinement_messages = [{"role": "user", "content": refinement_prompt}]
- refined_plan = ""
- async for chunk in self.llm.astream_invoke(refinement_messages, **kwargs):
- refined_plan += chunk
- yield StreamEvent.create(
- StreamEventType.LLM_CHUNK,
- self.name,
- chunk=chunk,
- phase="refinement",
- iteration=iteration + 1
- )
- yield StreamEvent.create(
- StreamEventType.STEP_FINISH,
- self.name,
- phase="refinement",
- iteration=iteration + 1,
- result=refined_plan
- )
- current_plan = refined_plan
- # 发送完成事件
- yield StreamEvent.create(
- StreamEventType.AGENT_FINISH,
- self.name,
- result=current_plan,
- total_iterations=self.max_reflection_iterations
- )
- # 保存到历史
- self.add_message(Message(input_text, "user"))
- self.add_message(Message(current_plan, "assistant"))
- except Exception as e:
- # 发送错误事件
- yield StreamEvent.create(
- StreamEventType.ERROR,
- self.name,
- error=str(e),
- error_type=type(e).__name__
- )
- raise
- def get_plan_trajectory(self) -> str:
- """获取完整的计划生成轨迹"""
- return self.memory.get_trajectory()
- def create_code_plan_agent(llm: HelloAgentsLLM) -> CodePlanAgent:
- """
- 创建CodePlanAgent实例的便捷工厂函数
- Args:
- llm: LLM实例
- Returns:
- CodePlanAgent实例
- """
- return CodePlanAgent(
- name="CodePlanAgent",
- llm=llm,
- max_reflection_iterations=2
- )
|