本文主体是宋志学老师在datawhale的宣讲。

辅以一些本人的看法,希望各位大佬一起交流指正。

Agent实践代码

https://github.com/ceilf6/Lab/tree/main/agent/ReAct-starter

一. Agent

1. 原理

Agent = 大模型 + 记忆 + 主动规划 + 工具使用

像人一样会去对环境做出反应的同时,利用工具解决当前任务

当前主流框架

  1. ReAct 推理 + 行动

思考、行动 → 观察、反馈 → 再思考…如此循环往复

将思考和行动融合在每个步骤中

适合需要实时响应的动态任务

  1. Plan-and-Solve 规划-求解

先规划再执行的解耦式架构

就像 claude code 在执行前会生成 todo lists

全程会确保目标一致性,适合需要追求高精度的关键任务

  1. Reflection 反思优化

执行 → 反思 → 优化

像是前两者的补充

实现高质量优化

反射(如果有机会拿到新的外部信息的话,可以提高输出效果)

ReAct

是当前最简洁有效的Agent架构

观察环境 -> 思考推理 -> 采取行动 -> 观察结果 -> 循环

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意设置边界迭代上线,否则一直觉得没有好的结果就会一直递归,浪费Token

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LangChain

基于链式调用的Agent框架

支持多种提示模版

丰富生态、适合复杂工作流

LangGraph

把已有能力按图结构组织起来,让 Agent 更可控地行动

类似于 Agent 行为的交通调度系统,像传统Agent

while (true) {
  response = llm(state)
  if (需要工具) callTool()
  if (结束条件) break
}

行为路径不可控,容易死循环,中间状态难以追踪(追踪中间状态、及时分析,很有利于优化你的Agent),不适合复杂多Agent协作

核心思想

Agent = 节点

决策 = 边

状态 = 显式State

并不是自由对话,而是在一张图里走状态迁移

状态机 Graph State
if / switch Conditional Edge
任务流 Graph traversal
回退 / 重试 Loop / Edge
日志 / traceId State 可追踪
可观测性 LangSmith 集成

AutoGPT

完全自主的目标追求

记忆系统长期

自我提示生成

适合开放任务

MetaGPT

多智能体的Agent框架

模拟真实软件团队角色分工,扮演了产品经理、架构师、工程师等角色

适合自动化软件开发任务

CAMELAI

也是角色扮演、多智能体的框架

(感觉比MetaGPT更好用)

强调通信协议,适合创意写作、教育培训等

2. 实现React Agent

sequenceDiagram
    participant User
    participant Agent
    participant LLM
    participant Tools
    
    User->>Agent: 输入查询
    Agent->>Agent: 构建提示词
    Agent->>LLM: 发送提示
    LLM->>Agent: 返回思考+行动
    
    alt 需要工具
        Agent->>Tools: 调用指定工具
        Tools->>Agent: 返回执行结果
        Agent->>Agent: 更新历史记录
        Agent->>LLM: 再次思考
        LLM->>Agent: 返回最终答案
    else 无需工具
        Agent->>User: 直接返回答案
    end
    
    Agent->>User: 最终结果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

User输入后Agent构建提示词,然后决定下一步要调的API ( LLM 或者 工具库 ),拿到结果后存储到记忆的同时判断是否需要进一步还是返回

1. 构造大模型

思考模型工具调用可能不准确,实践的时候最好用 instant

class BaseModel:
    def __init__(self, api_key: str = '') -> None:
        self.api_key = api_key

    def chat(self, prompt: str, history: List[Dict[str, str]], system_prompt: str = "") -> Tuple[str, List[Dict[str, str]]]:
        """
        基础聊天接口
        
        Args:
            prompt: 用户输入
            history: 对话历史
            system_prompt: 系统提示
            
        Returns:
            (模型响应, 更新后的对话历史)
        """
        pass

首先在 BaseModal 里面管理一下 ApiKey ,

接着写个 chat 方法

  • 用户输入
  • 对话历史
  • 系统提示
class Siliconflow(BaseModel):
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.client = OpenAI(api_key=self.api_key, base_url="https://api.siliconflow.cn/v1")

    def chat(self, prompt: str, history: List[Dict[str, str]] = [], system_prompt: str = "") -> Tuple[str, List[Dict[str, str]]]:
        """
        与 Siliconflow API 进行聊天
        
        Args:
            prompt: 用户输入
            history: 对话历史
            system_prompt: 系统提示
            
        Returns:
            (模型响应, 更新后的对话历史)
        """
        # 构建消息列表
        messages = [
            {"role": "system", "content": system_prompt or "You are a helpful assistant."}
        ]
        
        # 添加历史消息
        if history:
            messages.extend(history)
        
        # 添加当前用户消息
        messages.append({"role": "user", "content": prompt})

        # 调用 API
        response = self.client.chat.completions.create(
            model="Qwen/Qwen3-30B-A3B-Instruct-2507",
            messages=messages,
            temperature=0.6,
            max_tokens=2000,
        )

        model_response = response.choices[0].message.content
        
        # 更新对话历史
        updated_history = messages.copy()
        updated_history.append({"role": "assistant", "content": model_response})

        return model_response, updated_history

继承自基准模型类,实现chat方法

硅基流动平台提供了很多开源模型的 api 服务方便调试和开发

注意将 Endpoint 模型接口修改为硅基的

历史消息 - 记忆

temperature 模型的创意程度

2. 构造工具

tools.py 中实现 Tools 类

告诉LLM可以调用的工具

class ReactTools:
    """
    React Agent 工具类
    
    为 ReAct Agent 提供标准化的工具接口
    """
    
    def __init__(self) -> None:
        self.toolConfig = self._build_tool_config()
    
    def _build_tool_config(self) -> List[Dict[str, Any]]:
        """构建工具配置信息"""
        return [
            {
                'name_for_human': '谷歌搜索',
                'name_for_model': 'google_search',
                'description_for_model': '谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。',
                'parameters': [
                    {
                        'name': 'search_query',
                        'description': '搜索关键词或短语',
                        'required': True,
                        'schema': {'type': 'string'},
                    }
                ],
            }
        ]

    def google_search(self, search_query: str) -> str:
        """执行谷歌搜索

        可在 https://serper.dev/dashboard 申请 api key

        Args:
            search_query: 搜索关键词
            
        Returns:
            格式化的搜索结果字符串
        """
        url = "https://google.serper.dev/search"

        payload = json.dumps({"q": search_query})
        headers = {
            'X-API-KEY': 'your serper api key',
            'Content-Type': 'application/json'
        }

        pass
    
    def get_available_tools(self) -> List[str]:
        pass

    def get_tool_description(self, tool_name: str) -> str:
        pass

需要使用 Google 搜索功能得去申请 然后填 ApiKey

https://serper.dev/dashboard

3. React Agent

分层方便维护

  • 接口层:对外暴露简单的 run() 方法
  • 协调层:管理思考-行动-观察的循环
  • 解析层:从模型输出中提取结构化信息 - JSON
  • 执行层:调用具体工具完成任务
class ReactAgent:
    def __init__(self, api_key: str = '') -> None:
        """初始化 React Agent"""
        self.api_key = api_key
        self.tools = Tools()                    # 工具管理
        self.model = Siliconflow(api_key)      # LLM 客户端
        self.system_prompt = self._build_system_prompt()
    
    def _build_system_prompt(self) -> str:
        """构建 ReAct 系统提示"""
        # 组合工具描述和 ReAct 模式指导
        return prompt_template
    
    def _parse_action(self, text: str) -> tuple[str, dict]:
        """解析模型输出中的行动和参数"""
        # 使用正则表达式提取行动和参数
        action_pattern = r"行动[::]\s*(\w+)"
        action_input_pattern = r"行动输入[::]\s*({.*?}|[^\n]*)"
        return action, action_input_dict
    
    def _execute_action(self, action: str, action_input: dict) -> str:
        """执行指定的工具行动"""
        # 调用对应工具并返回结果
        
    def run(self, query: str, max_iterations: int = 3, verbose: bool = True) -> str:
        """运行 ReAct Agent 主循环"""
        # 实现思考-行动-观察循环

verbose - 是否显示中间执行过程(推荐打开,方便优化)

系统提示

决定了 Agent 的行为模式

一个好的ReAct系统提示词应该包含

  1. 时间信息:让 Agent 知道当前时间,避免过时信息
  2. 工具清单:明确告诉 Agent 有哪些工具可用
  3. 行为模式:详细的 ReAct 流程指导
  4. 输出格式:规范化的思考-行动-观察格式

通过 py 的 f-string 动态格式

prompt = f"""现在时间是 {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}。
你是一位智能助手,可以使用以下工具来回答问题:

{tool_descriptions}

请遵循以下 ReAct 模式:

思考:分析问题和需要使用的工具
行动:选择工具 [google_search] 中的一个
行动输入:提供工具的参数
观察:工具返回的结果

你可以重复以上循环,直到获得足够的信息来回答问题。

最终答案:基于所有信息给出最终答案

开始!"""

注意

  • 中文提示:更符合国内用户习惯
  • 具体工具名:明确告诉模型可用工具
  • 循环指导:说明可以多次使用工具
  • 最终答案:明确结束条件

行动解析

复杂是为了规范大模型的输出格式

  • 中英文混合的冒号
  • JSON格式不规范
  • 参数缺失或格式错误
  • 多余的空格或换行

因此我们需要一个鲁棒的解析机制

解析思路

  1. 多层匹配:先用正则提取,再用JSON解析
  2. 容错设计:解析失败时提供降级方案
  3. 格式兼容:支持JSON字符串和纯文本参数

解析流程

模型输出:
思考:用户询问特朗普生日,需要搜索
行动:google_search
行动输入:{"search_query": "特朗普生日"}

解析步骤:
1. 正则提取行动 → google_search
2. 正则提取参数 → {"search_query": "特朗普生日"}
3. JSON解析 → {'search_query': '特朗普生日'}
4. 返回结构化数据 → ('google_search', {'search_query': '特朗普生日'})

ReAct 主循环

ReAct 循环是 Agent 的"心跳",它让 Agent 能够:

  • 持续思考:基于新信息不断调整策略
  • 工具调用:在需要时主动获取外部信息
  • 结果整合:将工具结果与已有知识结合

循环的四个阶段

  1. 思考阶段(Thought):模型分析问题,决定是否需要工具
  2. 行动阶段(Action):选择合适的工具并提供参数
  3. 观察阶段(Observation):执行工具并获取结果
  4. 整合阶段(Integration):将新信息整合到上下文中

为什么需要 max_iterations?

  • 防止无限循环:避免模型陷入死循环
  • 控制成本:限制 API 调用次数
  • 用户体验:避免过长的响应时间

注意每次都需要

  • 保持上下文:将观察结果加入对话历史
  • 更新输入:为下一轮循环准备新的提示
  • 历史记录:确保模型知道之前做了什么

QA

  • Q: Agent框架、强化学习、优化算法这三者是什么关系?

    A: Agent是和LLM相关的;强化学习分为两种,一种是用于矫正大模型回答,另一种是做Agent的强化学习,让模型更好的思考、工具调用

  • Q: 开发框架怎么说

    A: 使用层面各个框架都好,如果想学习底层原理,可以看OpenAI的swam框架

  • langgraph 的稳定性更好

  • Q: 什么场景下需要自己搭建实现Agent而不是用框架?

    A: 需要在领域特定化修改

  • Q: 理解Agent原理对Agent应用开发有哪些帮助?

    A: 上限更高

  • Q: 怎么管理长期记忆?

    1. 记忆的持久化保存一般用什么方法

      太长的记忆处理方法(超过最大输入尺寸)可以做前文总结,一般会保存为本地文件以RAG支持大模型;还有一种方法是通过正则匹配去搜索你输入的内容进行召回

    2. Agent如何高效且准确地应用记忆

      向量数据库或者直接搜索

  • Q: 调用工具失败,有反思纠错逻辑吗?

    A: 换个模型

  • Q: codex 和 cc 里的 agent 设计有什么区别?

    A: 并不开源,得去拦截才能分析

  • 框架选一个即可

  • Q: 工程中的优化点

    A: 得先明确目标,明确使用Agent想要解决的问题

  • 推荐 agentscope 和 MSA

  • ReAct Agent 这种循环基本是现在框架基石

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐