从零构建一个能思考、会搜索的 LLM Agent

1 阅读8分钟

从零构建一个能思考、会搜索的 LLM Agent

当大语言模型不再是“只会接龙的鹦鹉”,而是拥有工具和推理能力的智能体。

一、为什么“让模型一步步思考”能大幅提升推理能力?

一个让所有开发者惊讶的训练发现

在没有任何微调的情况下,仅仅在提示词末尾加上**“Let’s think step by step”**,GPT-3 在数学推理任务上的准确率就能从 17.7% 飙升到 78.7%。摘自 Google Brain 团队 2022 年论文中展示的真实数据。

初看时我难以置信——这不就是让人多写几个字吗?但亲手实验后,我彻底服了。

从“黑盒一跳”到“白盒推演”

没有 CoT 时,模型的行为像这样:

问:小明有5个苹果,给小红2个,又买了3个,现在有几个?
模型内心:5 → (某种神秘计算) → 6
输出:6

你永远不知道它是怎么得出 6 的,错了也无从修正。

有了 CoT,模型变成:

问:小明有5个苹果,给小红2个,又买了3个,现在有几个?
模型输出:一开始有5个。给小红2个,剩下3个。又买了3个,3+3=6。所以答案是6

这不仅仅是多写几个字,而是彻底改变了模型的计算路径

深度拆解:CoT 为何有效?

我根据自己的实验和论文理解,总结了三个核心原因:

  1. 将复杂问题分解为原子步骤
    模型本质上是一个词级别的概率模型。直接输出最终答案相当于要求它“一步跨越鸿沟”。CoT 把大跳跃变成小碎步——每一步的推理压力小得多,正确率自然更高。

  2. 激活了模型的“工作记忆”
    标准输出时,模型只能依赖内部隐状态。而 CoT 要求它把中间结果写出来,这些文字就成了外部扩展记忆。当你写“剩下 3 个”时,后面的计算可以直接引用这个数字,不会遗忘。

  3. 错误可定位、可修复
    有一次模型算错了,输出:“5-2=2,然后 2+3=5”。我一眼看出 5-2=2 错了。如果没有 CoT,我连哪里错都不知道。这种可解释性对调试 Agent 至关重要。

实验数据(我自己跑的)

用 10 道小学数学题测试 GPT-3.5:

模式准确率
直接输出答案40%
加一句“Let's think step by step”80%
加 CoT + 3 次采样投票90%

CoT 带来的提升是翻倍级的,零成本,高回报。


二、ReAct 模式:让 Agent 真正“动起来”

如果说 CoT 让模型会“思考”,那 ReAct 就是让模型 “思考 + 行动”。论文《ReAct: Synergizing Reasoning and Acting in Language Models》提出了一个简单却强大的循环:

Thought → Action → Observation → (重复) → Final Answer

我实现的一个真实案例

用户问:“《星际穿越》的导演哪一年出生的?到 2026 年他多少岁?”

没有工具的模型会瞎编:“导演是诺兰,1970 年出生,2026 年 56 岁。”——蒙对了还好,蒙错就完蛋。

用 ReAct 模式,模型的行为变成了:

Thought: 我需要先找到《星际穿越》的导演,然后查他的出生年份,最后计算年龄。
Action: search_wikipedia
Action Input: 星际穿越 导演
Observation: 搜索结果:克里斯托弗·诺兰(Christopher Nolan),1970年7月30日出生...
Thought: 导演是克里斯托弗·诺兰,出生于1970年。现在计算到2026年的年龄。
Action: calculate
Action Input: 2026 - 1970
Observation: 计算结果: 56
Thought: 我有足够信息了。
Final Answer: 导演克里斯托弗·诺兰出生于1970年,到2026年他将满56岁。

注意每次 Action 实际上是我在代码里拦截并真正调用了工具(Wikipedia API 或计算器),然后把结果以 Observation 的形式塞回给模型。模型再根据观察决定下一步。

这就是最朴素的 Agent 形态:模型负责规划,代码负责执行

踩坑记录:格式化是魔鬼

ReAct 对格式的要求极其严格。模型必须输出:

Action: search_wikipedia
Action Input: 星际穿越 导演

稍有偏差(比如 Action Input: 写成 Action input:,或者多了个冒号,或者把 Input 写到了下一行),解析就会失败。

我学到的一课:永远在 System Prompt 里给出完美的示例,并且实现解析失败重试机制。当正则匹配不到 Action 时,返回一条 Observation:“格式错误,请严格按照 Thought/Action/Action Input 格式输出”,模型通常会自动修正。

工具的真实实现(关键代码片段)

def search_wikipedia(query):
    url = "https://en.wikipedia.org/w/api.php"
    params = {
        "action": "query",
        "list": "search",
        "srsearch": query,
        "format": "json",
        "srlimit": 3,
    }
    resp = requests.get(url, params=params)
    data = resp.json()
    return format_search_results(data)

完全不用 LangChain,只用 requests 加 Wikipedia 官方 API,就能获得真实的搜索能力。这让我意识到:Agent 框架降低的是门槛,而不是必要性。手动实现能让人更深刻地理解每一步。


三、temperature:一个参数如何决定模型的“性格”

在实验中,我发现 temperature 对推理任务的影响常常被低估。

直观理解:从“老实人”到“疯癫诗人”

temperature行为特征
0每次都选概率最高的词,输出完全确定,像背诵标准答案
0.3~0.5有一定随机性但保持逻辑,像有经验的专家
0.7~1.0创意丰富但偶尔跑偏,像头脑风暴中的成员
>1.2输出可能胡言乱语,像醉酒后的胡话

对推理任务的特殊影响

  1. 数学题temperature=0 最佳。稍有随机性就可能从“5-2=3”跳成“5-2=2”,一步错步步错。
  2. 需要多样性的任务:例如代码生成、头脑风暴,0.7 左右能产生惊喜。
  3. 自洽性(Self-Consistency):这正是利用高 temperature + 多次采样来获取多条推理路径,然后用投票选出最常出现的答案。原理是:不同的随机路径可能通往同一个正确答案,而错误答案分散

我的调参经验表

任务类型推荐 temperature原因
事实问答0确定性越高越好
数学推理0 ~ 0.3需要精确,但略高可为自洽性服务
创意写作0.7 ~ 1.0需要发散
代码生成0.2 ~ 0.5既要有规范,又要避免死板
Agent 规划0.3需要稳定格式,又要有一定灵活性

四、亲手搭建一个 Agent 的真实感悟

我犯过的错误

  1. 过度依赖框架:一开始想用 LangChain,但配置复杂、抽象多,反而掩盖了基本原理。最后决定自己写解析器 + 工具调用,200 行代码搞定。
  2. 忘记处理工具返回的异常:Wikipedia 可能返回空结果,calculate 可能除零。如果不处理,模型会收到奇怪的 Observation,然后彻底懵掉。
  3. 设置过高的温度:在 Agent 的规划阶段用高 temperature,模型开始随意编造工具名,乱输出格式,完全失控。
  4. 上下文爆炸:每次循环都把完整的 Thought/Action/Observation 历史塞回去,很快超过 token 限制。解决方案是只保留最近的几轮,或使用更长的上下文模型。

成功的关键

  • 严格的 System Prompt:用 3-5 个示例教会模型格式。
  • 健壮的解析器:支持多种变体(带引号/不带,多行输入等)。
  • 最大步数限制:防止 Agent 陷入无限循环。
  • 清晰的彩色输出:调试时能一眼看到模型在每个步骤的思考过程。

推荐的学习路径

  1. 先用 API 跑通单次 CoT 调用,体会“思考”的价值。
  2. 手动实现两个工具函数(搜索,计算)。
  3. 写一个死循环:调用模型 → 解析 Action → 执行 → 拼接 Observation → 继续。
  4. 加入解析失败重试、最大步数、详细日志。
  5. 测试一个需要多步的任务(比如本文的“星际穿越导演年龄”)。

踩完这些坑,你会比任何框架文档都更理解 Agent。


写在最后

从“只会接龙”到“能搜索、能计算、能规划”,大语言模型的能力边界在被新的提示范式不断拓宽。最让我兴奋的是,这些进步不需要改变模型参数,只需要改变我们与模型对话的方式

CoT 教会模型“慢思考”,ReAct 赋予模型“手脚”,temperature 调节模型的“性格”。当我把这三者组合起来,一个能够自主完成复杂任务的 Agent 就在几百行代码内诞生了。

附:本文所有实验代码已整理到 GitHub(可私信获取),包含:

  • 带彩色输出的 ReAct Agent 完整实现
  • CoT 与自洽性对比测试脚本
  • Temperature 影响的可视化实验