跳转到内容

Thinking / 反思在 Agent 循环中的集成

Thinking / 反思在 Agent 循环中的集成

学习目标

  • 理解 ChatDev 的 ThinkingPayload 容器与两阶段思考管线
  • 掌握 Self-Reflection 的 After-Gen 反思实现
  • 了解思考结果如何注入 Agent 对话上下文
  • 能够评估何时启用思考与何时跳过以节省 Token

前置知识

本章涉及 Agent 核心循环的通用原理,建议先阅读:

下文聚焦 ChatDev 的具体思考管线实现。


项目实践

ThinkingPayload 容器

ChatDev 使用 ThinkingPayload 作为多模态上下文的传递容器:

ThinkingPayload:
- text: 文本内容
- blocks: 多模态消息块列表
- metadata: 元数据字典
- raw: 任意原始数据

这个容器贯穿思考管线的三个阶段,确保多模态上下文在思考过程中不丢失。

两阶段思考管线

ChatDev 的 ThinkingManagerBase 定义了抽象的两阶段思考接口:

Before-Gen Thinking(生成前思考)

  • 在调用模型 API 之前执行
  • 可对输入进行预处理、分析、规划
  • 当前 ChatDev 内置实现未启用 Before-Gen
  • 扩展点:_before_gen_think() 抽象方法

After-Gen Thinking(生成后思考)— Self-Reflection

ChatDev 内置的 Self-Reflection 是 After-Gen 的具体实现:

class SelfReflectionThinkingManager(ThinkingManagerBase):
def _after_gen_think(self, agent_invoker, input_payload, agent_role, memory, gen_payload):
conversations = [
f"SYSTEM: {agent_role}",
f"USER: {input_payload.text}",
f"ASSISTANT: {gen_payload.text}",
]
if memory and memory.text:
conversations = [memory.text] + conversations
prompt = self.base_prompt.format(
conversations="\n\n".join(conversations),
reflection_prompt=self.reflection_prompt
)
reflection_message = agent_invoker(
[Message(role=MessageRole.USER, content=prompt)]
)
return reflection_message.text_content(), True # True = 替换原始输出

反射过程:

原始对话: [System Role] + [User Input] + [Assistant Output]
反思 Prompt: "Here is a conversation... {reflection_prompt}"
二次模型调用 → 反思结果
替换原始输出 (replace=True)

YAML 中的 Thinking 配置

- id: Reviewer
type: agent
config:
thinking:
type: reflection
config:
reflection_prompt: "Review the generated code for bugs and security issues."

thinkingnull 时不启用思考:

thinking: # null → 不启用,节省 Token

思考管线的执行时序

AgentNodeExecutorexecute() 方法中,思考管线的集成点:

1. 构建输入 (input_data, input_payload)
2. ┌─ Before-Gen Thinking(可选)
3. │ _apply_pre_generation_thinking()
4. └─ 可能修改 conversation
5. 记忆检索 _apply_memory_retrieval()
6. 调用模型 _invoke_provider()
7. ┌─ After-Gen Thinking(可选)
8. │ _apply_post_generation_thinking()
9. └─ 可能替换最终输出
10. 工具调用循环(如有工具)
11. 最终输出

问题与规避

问题表现规避策略
反思结果质量差模型反思偏离主题设计精确的 reflection_prompt
Token 消耗倍增每次 Agent 调用后额外一次 LLM 调用仅在关键节点(Reviewer、Quality Inspector)启用
思考替换原始输出的风险replace=True 可能丢失有用信息在反思结果中保留原始输出的关键部分
Memory 注入导致上下文膨胀历史记忆 + 对话 = 超长 prompt限制记忆检索的 top_ksimilarity_threshold
多级思考嵌套思考结果再次触发思考ThinkingManager 不允许递归

设计取舍

内置 Reflection vs 外部反思 Agent

维度内置 Reflection外部反思 Agent
实现复杂度低(复用同一 Provider)高(需定义独立节点)
灵活性低(固定管线)高(可自定义完整 Agent)
Token 效率较高(共享上下文)较低(独立上下文)
ChatDev 的选择✅ 内置为默认可用独立节点实现

两阶段 vs 单阶段

ChatDev 设计了两个思考阶段但仅启用了 After-Gen:

  • Before-Gen 的价值:在生成前进行分析规划(适合复杂任务分解)
  • After-Gen 的价值:对生成结果进行质量检查(适合代码审查、事实核查)
  • 仅启用 After-Gen 的原因:大部分场景的反思价值在于质量提升而非输入改造

参考来源