跳转到内容

Agent 与工具使用:模型不只是聊天

聊天模型只能说话,Agent 则能通过工具作用于世界:查天气、写代码、操作数据库、调用 API。核心思想是把”思考”和”行动”结合:模型先推理当前需要什么信息,然后调用工具获取,再基于结果继续推理。

ReAct 框架把这个循环显式化:模型输出”思考→行动→观察→再思考”的交替序列。这就像人类解决问题时,不是一直空想,而是边查资料边推理。

工程上,Agent 系统的核心挑战是可靠性:

  • 工具定义:用 JSON Schema 或 OpenAPI 描述工具接口,让模型知道每个工具的参数和用途。MCP(Model Context Protocol)试图标准化这一层。
  • 调用解析:模型输出通常是文本,需要可靠地解析出工具调用结构。Function calling 训练让模型原生输出结构化调用,比后解析更稳定。
  • 错误处理:工具可能失败、超时或返回异常。Agent 需要能重试、回退或换用替代工具。
  • 状态管理:多步任务需要维护对话历史、中间结果和计划。Reflexion 等工作让 Agent 能自我反思失败原因并调整策略。
  • 安全边界:Agent 能执行代码或访问外部系统时,权限控制和沙箱化至关重要。提示注入(prompt injection)可能让攻击者劫持 Agent 行为。

评估 Agent 比评估纯文本生成更难:要看任务完成率、步骤效率、错误恢复能力和成本。SWE-bench 等基准测试通过真实代码任务衡量 Agent 的实用性。

示例代码:ReAct 风格的 Agent 循环

Section titled “示例代码:ReAct 风格的 Agent 循环”

下方代码通过浏览器内 Python 运行环境执行,调用了 mock_llm 占位函数;生产环境替换为你自己的 LLM 客户端即可。

可运行示例
import json

def mock_llm(prompt: str) -> str:
    """演示用:返回写死的 ReAct 风格输出(生产环境请替换为真实 LLM 调用)"""
    if "搜索结果" in prompt:
        return (
            "Thought: 已经拿到信息了,可以结束。\\n"
            "Action: finish\\n"
            "Action Input: {\"answer\": \"今天多云,20-25°C\"}"
        )
    return (
        "Thought: 我需要先查询天气信息。\\n"
        "Action: search\\n"
        "Action Input: {\"query\": \"今天天气\"}"
    )

class SimpleAgent:
    """简化的 ReAct Agent 示例"""

    def __init__(self, tools):
        self.tools = tools  # 工具字典 {工具名: 工具函数}
        self.history = []

    def think(self, observation):
        """思考下一步行动(演示:调用 mock_llm)"""
        react = mock_llm(observation)
        print(f"LLM 输出:\\n{react}")

        action = None
        action_input = {}
        for line in react.splitlines():
            if line.startswith("Action:"):
                action = line.split(":", 1)[1].strip()
            if line.startswith("Action Input:"):
                raw = line.split(":", 1)[1].strip()
                try:
                    action_input = json.loads(raw)
                except Exception:
                    action_input = {}

        if not action:
            return "finish", {"answer": "解析失败:没有 Action"}
        return action, action_input

    def act(self, action, params):
        """执行工具调用"""
        if action == "finish":
            return params["answer"], True

        if action in self.tools:
            result = self.tools[action](**params)
            return result, False
        else:
            return f"错误:工具 {action} 不存在", False

    def run(self, task, max_steps=5):
        """运行 Agent 主循环"""
        observation = f"任务: {task}"

        for step in range(max_steps):
            print(f"\n--- 步骤 {step + 1} ---")
            print(f"观察: {observation}")

            # 思考
            action, params = self.think(observation)
            print(f"思考: 执行 {action},参数 {params}")

            # 行动
            observation, done = self.act(action, params)
            print(f"行动结果: {observation}")

            self.history.append({
                "step": step + 1,
                "action": action,
                "params": params,
                "result": observation
            })

            if done:
                print(f"\n✓ 任务完成: {observation}")
                return observation

        return "达到最大步数限制"

# 定义工具
def search_tool(query):
    """模拟搜索工具"""
    return f"搜索结果:{query} - 今天多云,20-25°C"

def calculator_tool(expression):
    """简单计算器(⚠️ 演示用:eval 有代码注入风险,生产环境请用 ast.literal_eval 或安全解析器)"""
    try:
        # 仅允许基本数学运算符(演示级过滤)
        allowed_chars = set('0123456789.+-*/() ')
        if not all(c in allowed_chars for c in expression):
            return "计算错误:包含不允许的字符"
        return f"计算结果:{expression} = {eval(expression)}"
    except:
        return "计算错误"

# 使用 Agent
tools = {
    "search": search_tool,
    "calculator": calculator_tool
}

agent = SimpleAgent(tools)
agent.run("查询今天天气")

研究版:从单 Agent 到多 Agent 与自主系统

Section titled “研究版:从单 Agent 到多 Agent 与自主系统”

研究层面,单 Agent 的局限在于:一个模型同时承担规划、执行、记忆和反思,容易出错且难以扩展。多 Agent 系统把不同角色分配给不同实例:有的负责规划,有的负责执行,有的负责验证,通过对话或共享状态协作。

更深的问题是:Agent 的”自主性”边界在哪里?当模型能自己决定调用什么工具、修改什么文件、访问什么数据时,如何定义和监督它的目标?这是技术、产品和伦理的交叉领域。

🔬 开放研究问题

该领域的关键问题与研究方向:

  1. Agent 系统的可靠性如何形式化验证?现有 benchmarks(如 SWE-bench)是否足够?
  2. MCP 等工具调用协议的标准化能否真正解决跨模型/跨工具的互操作问题?
  3. 多 Agent 协作与单 Agent 反思(ReAct/Reflexion)的能力边界在哪里?

本文引用论文

  • ReAct: Synergizing Reasoning and Acting in Language Models — Shunyu Yao et al. (2022)

    ReAct 框架将推理(Reasoning)和行动(Acting)交织在一起:LLM 先思考(Thought), 再执行工具调用(Action),观察结果(Observation),如此循环。这是现代 AI Agent 框架的原型,直接影响了 LangChain、AutoGPT 等 agent 框架的设计。

  • Toolformer: Language Models Can Teach Themselves to Use Tools — Timo Schick et al. (2023)

    让模型自己生成"调用 API 的 token"并通过自监督评估有用性。是 function-calling / tool-use 训练范式的奠基论文,直接影响 GPT-4 function calling 的设计。

  • Reflexion: Language Agents with Verbal Reinforcement Learning — Noah Shinn et al. (2023)

    让 agent 在失败后用自然语言做"复盘",下一轮把反思塞进 prompt。"无梯度的自我改进"思路被广泛复用于 coding agent、SWE-agent。

  • SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering — John Yang et al. (2024)

    提出 ACI(Agent-Computer Interface)概念,强调"agent 用什么工具/界面 ≥ 用什么模型"。把 GPT-4 + 良好 ACI 在 SWE-bench 提升 6 倍,奠定 coding agent 工程方法论。

  • Model Context Protocol (MCP) — Anthropic (2024)

    模型上下文协议(MCP)是 Anthropic 提出的开放标准,规定了 LLM 应用如何与外部工具、 数据源和服务进行标准化通信。通过统一的"resources/tools/prompts"接口, 任何 MCP-compatible 的工具都可以无缝接入任何 MCP-compatible 的模型, 目标是成为 AI 工具调用的 USB 标准。

  • Tree of Thoughts: Deliberate Problem Solving with Large Language Models — Shunyu Yao et al. (2023)

    Tree of Thoughts(ToT)将问题求解建模为树搜索:LLM 生成多个"思维步骤"作为树节点, 用评估函数打分并进行 BFS/DFS 搜索。在需要复杂规划的任务(如 24 点游戏)上, ToT 比普通 CoT 提升巨大,是 o1 风格慢思考的先驱工作。