系列目标:30 天从 LangChain 入门到企业级部署
今日任务:理解 Agent 与 Chain 的区别 → 掌握 ReAct 原理 → 构建能调用计算器和搜索的 AI 智能体!
🤖 一、Chain vs Agent:关键区别
表格
| 能力 | Chain | Agent ✅ |
|---|---|---|
| 执行流程 | 固定顺序(你设计好) | 动态决策(AI 自己规划) |
| 工具调用 | 不能直接调用外部工具 | 可调用 Tools(API/函数/搜索等) |
| 适用场景 | 确定性任务(翻译、摘要) | 开放性任务(“帮我算一下…”、“查一下…”) |
💡 Agent = LLM + Reasoning(推理) + Action(行动)
今天我们将基于 ReAct(Reason + Act)框架,构建一个能:
- 自动判断是否需要计算
- 调用计算器执行数学运算
- 必要时使用搜索(模拟)
的智能体!
🔍 二、ReAct 是什么?
ReAct 是一种经典 Agent 范式,其思考过程如下:
Question: 2024年杭州GDP是多少乘以2?
Thought: 我需要先知道2024年杭州GDP,但这是未知的。假设为2万亿元。
Action: Calculator
Action Input: 2 * 2000000000000
Observation: 4000000000000
Thought: 我现在知道答案了。
Final Answer: 4万亿元。
✅ LangChain 内置了 ReAct Agent 实现,开箱即用!
🛠️ 三、动手实践:构建带计算器的 AI 智能体
步骤 1:安装依赖
bash
编辑
pip install langchain-ollama
# 如果要用搜索,还需安装:langchain-community(含 DuckDuckGoSearch)
💡 今天先用自定义计算器工具,避免网络依赖。
步骤 2:定义 Tool(工具)
# day10_agent_react.py
from langchain_ollama import ChatOllama
from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain_core.prompts import ChatPromptTemplate
import re
# 自定义计算器函数
def calculator(expression: str) -> str:
"""安全计算器:仅支持 + - * / 和数字"""
# 简单过滤非数学字符(生产环境请用 ast.literal_eval 或专用库)
expr = re.sub(r'[^0-9+-*/().\s]', '', expression)
try:
result = eval(expr, {"__builtins__": {}}, {})
return str(result)
except:
return "计算错误,请输入合法表达式"
# 注册为 Tool
tools = [
Tool(
name="Calculator",
func=calculator,
description="用于执行数学计算,输入应为合法算术表达式,如 '2 + 3 * 4'"
)
]
⚠️ 注意:
eval()有安全风险!仅用于演示,生产环境请用simpleeval或numexpr。
步骤 3:创建 ReAct Agent
# 初始化 LLM(必须支持停用词 stop=["\nObservation"],Qwen 支持)
llm = ChatOllama(model="qwen:7b", temperature=0)
# 获取 ReAct 默认 Prompt(含 Thought/Action/Answer 指令)
prompt = create_react_agent.get_default_prompt()
# 创建 Agent
agent = create_react_agent(llm=llm, tools=tools, prompt=prompt)
# 创建 AgentExecutor(负责执行循环)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印思考过程
handle_parsing_errors=True # 防止格式错误崩溃
)
🔑 关键点:
create_react_agent自动构造符合 ReAct 格式的 promptAgentExecutor管理“思考 → 行动 → 观察”循环
步骤 4:测试智能体
# 测试用例
questions = [ "123 加 456 等于多少?", "如果一个正方形边长是 8 米,面积是多少?", "今天的天气怎么样?" # 没有天气工具,会直接回答]
for q in questions:
print(f"\n👤 用户:{q}")
response = agent_executor.invoke({"input": q})
print(f"🤖 AI:{response['output']}")
▶️ 输出示例(verbose 模式):
Thought: 这是一个加法问题,我可以使用 Calculator。
Action: Calculator
Action Input: 123 + 456
Observation: 579
Thought: 我现在知道答案了。
Final Answer: 579
👤 用户:123 加 456 等于多少?
🤖 AI:579
✅ AI 成功自主调用工具完成任务!
🌐 四、扩展:加入搜索工具(可选)
如果你想让 Agent 能查实时信息,可添加 DuckDuckGo 搜索:
# 需先安装:pip install langchain-community duckduckgo-search
from langchain_community.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
tools.append(
Tool(name="Search", func=search.run, description="用于搜索实时信息")
)
💡 注意:本地模型(如 Qwen)可能对 ReAct 格式理解不如 GPT,若效果不佳:
- 在 prompt 中强调格式
- 使用
temperature=0- 或改用
create_tool_calling_agent(需模型支持 function calling,如 GPT-4)
⚠️ 五、注意事项 & 局限
表格
| 问题 | 建议 |
|---|---|
| 本地模型不遵循 ReAct 格式 | 尝试在 system prompt 中强化指令;或换用支持 function calling 的模型 |
| 工具被滥用(如“删除文件”) | 永远不要暴露危险操作!所有 Tool 必须经过安全封装 |
| 循环调用(Thought → Action → Thought...) | 设置 max_iterations=5 防止死循环 |
| 中文理解偏差 | 使用 Qwen、GLM 等中文优化模型 |
🔒 安全第一:Agent 能力越强,越要限制其工具权限!
📦 六、配套代码结构
langchain-30-days/
└── day10/
└── react_agent_with_calculator.py # 带计算器的 ReAct 智能体
📝 七、今日小结
- ✅ 理解了 Agent 与 Chain 的本质区别:自主决策 vs 固定流程
- ✅ 学会了 ReAct 框架的工作原理(Thought → Action → Observation)
- ✅ 实现了自定义 Tool(计算器)并注册给 Agent
- ✅ 成功运行了能自动调用工具的 AI 智能体
- ✅ 知道了 Agent 的安全边界与局限
🎯 明日预告:Day 11 —— 内置 Tools 大揭秘!用 Wikipedia、Google Search、Python REPL 等官方工具快速构建强大 Agent!