boxmoe_header_banner_img

Hello! 欢迎来到我的博客!

加载中

文章导读

3.Agent – Reflection


avatar
xiaoifei 2026年8月18日 4

当工具调用调用结果返回给模型后,模型会进入到Reflection阶段,在这个阶段模型将回答交给Critic进行反思,评价任务是否被正确执行。

举一个例子,当询问”帮我查找三个适合日本摇滚乐队使用的 Bass 音箱插件”,模型会做如下判断

1. 搜索插件
2. 找到三个
3. Reflection:
   - 我是否真的找到了三个?
   - 三个插件是不是都属于 Bass Amp?
   - 有没有把 Guitar Amp 当成 Bass Amp?
   - 用户说的是“日系摇滚”,我的推荐是否符合?
4. 发现某个插件其实是 Guitar Amp,结束Reflection进入主Agent
5. 再搜索一个 Bass Amp
6. 重新整理
7. 输出最终答案
SYSTEM_PROMPT = """
你是一个 ReAct 文件整理助手。
目标:检查 inbox,移动 inbox/a.txt 到 archive/a.txt,查看整理后的目录,然后总结。
每一轮最多调用一个工具。
如果有 reflection note,请优先参考它决定下一步。
""".strip()

REFLECTION_PROMPT = """
你是 reviewer。根据最近的工具结果,给 agent 一句下一步建议。
目标:检查 inbox -> 移动 inbox/a.txt 到 archive/a.txt -> 查看整理后的目录 -> 总结。
如果已经看到 archive/a.txt,请提醒 agent 停止调用工具并总结。
只输出一句 reflection note。
""".strip()


def main() -> None:
    task = " ".join(sys.argv[1:]).strip() or DEFAULT_TASK
    reset_workspace()

    print("=== 03. LangGraph ReAct + Reflection Node ===")
    print("\n用户任务:")
    print(task)
    print("\n运行前 workspace:")
    print(show_workspace())

    tools = [list_files, move_file]
    tool_map = {item.name: item for item in tools}
    base_llm = load_llm()
    tool_llm = base_llm.bind_tools(tools)

    def agent_node(state: AgentState) -> AgentState:
        print("\n[agent] 模型思考")
        prompt = SYSTEM_PROMPT
        if state["reflection"]:
            prompt += f"\n\nReflection note: {state['reflection']}"
        response = tool_llm.invoke([SystemMessage(content=prompt), *state["messages"]])
        return {"messages": [*state["messages"], response], "reflection": state["reflection"]}

    def tools_node(state: AgentState) -> AgentState:
        response = state["messages"][-1]
        new_messages = list(state["messages"])

        for tool_call in response.tool_calls:
            print("\n[tools] 执行工具")
            print(f"tool_name = {tool_call['name']}")
            print(f"tool_args = {tool_call['args']}")
            result = tool_map[tool_call["name"]].invoke(tool_call["args"])
            print(result)
            new_messages.append(
                ToolMessage(
                    content=str(result),
                    name=tool_call["name"],
                    tool_call_id=tool_call["id"],
                )
            )

        return {"messages": new_messages, "reflection": state["reflection"]}

    def reflection_node(state: AgentState) -> AgentState:
        print("\n[reflection] 复盘工具结果")
        transcript = "\n".join(str(message.content) for message in state["messages"][-4:])
        note = base_llm.invoke(
            [
                SystemMessage(content=REFLECTION_PROMPT),
                HumanMessage(content=transcript),
            ]
        ).content
        print(note)
        return {"messages": state["messages"], "reflection": str(note)}

    def should_continue(state: AgentState) -> str:
        last_message = state["messages"][-1]
        return "tools" if getattr(last_message, "tool_calls", None) else END

    graph = StateGraph(AgentState)
    graph.add_node("agent", agent_node)
    graph.add_node("tools", tools_node)
    graph.add_node("reflection", reflection_node)
    
    graph.add_edge(START, "agent")
    graph.add_conditional_edges("agent", should_continue)
    graph.add_edge("tools", "reflection")
    graph.add_edge("reflection", "agent")

    result = graph.compile().invoke(
        {"messages": [HumanMessage(content=task)], "reflection": ""},
        config={"recursion_limit": 12},
    )

    print("\n最终回答:")
    print(result["messages"][-1].content)
    print("\n运行后 workspace:")
    print(show_workspace())

上面例子中,我们将reflection_node的输出结果传递给state上下文的reflection字段,并由agent_node节点单独处理这个字段(不过实现方式是追加到System Prompt中),这种做法并不优雅。

我们可以让reflection节点直接处理messages记录,而不是专门设计reflection字段传递给Agent节点,让agent节点负责其他职责的工作

def reflection_node(state):
    note = ...
    return {
        "messages": [
            *state["messages"],
            HumanMessage(content=f"[Reflection] {note}")
        ]
    }


评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码