#012 LangChain 入门:环境搭建与第一个 Agent 应用

从一次诡异的“模型不响应”说起

上周帮团队排查一个 LangChain Agent 的 bug,现象很诡异:同样的代码,在 A 同事的 Mac 上跑得飞起,在 B 同事的 Windows 上就卡在 AgentExecutorinvoke 方法里,日志最后一行永远是 Entering new AgentExecutor chain...,然后就没有然后了。查了三天,最后发现是 openai 库版本不一致——A 同事用的是 0.28.0,B 同事是 1.6.0,而 LangChain 在 0.1.0 之后对 OpenAI 的调用接口做了大改。这种“环境地狱”问题,做 AI Agent 开发的人迟早都会遇到。所以这篇笔记,咱们就从最基础的环境搭建开始,把坑先踩一遍。

环境搭建:别信官方文档的“一行命令”

官方文档说 pip install langchain 就完事了,但实际开发中你至少需要装这些:

# 核心库,注意版本锁定
pip install langchain==0.1.12
pip install langchain-community==0.0.28
pip install langchain-openai==0.1.3

# 工具链,缺一个都可能报“ModuleNotFoundError”
pip install python-dotenv==1.0.0  # 管理 API Key,别硬编码在代码里
pip install numexpr==2.8.7        # 计算器工具依赖,踩过坑
pip install wikipedia==1.4.0      # 维基百科工具,测试用

这里踩过坑langchain-communitylangchain-openai 是后来拆分的包,如果你只装了 langchain,调用 from langchain.agents import load_tools 时会报 ImportError: cannot import name 'load_tools' from 'langchain.agents'。别问我怎么知道的,问就是 debug 到凌晨两点。

环境变量配置,我习惯在项目根目录建一个 .env 文件:

OPENAI_API_KEY=sk-你的key
OPENAI_BASE_URL=https://api.openai.com/v1  # 如果你用代理或国内中转,这里改地址

然后在代码里:

from dotenv import load_dotenv
load_dotenv()  # 别这样写:os.environ["OPENAI_API_KEY"] = "xxx"

别这样写:把 API Key 硬编码在代码里,然后不小心 push 到 GitHub。我见过有人因此被 AI 服务商封号,还一脸无辜地说“我只是想分享代码”。

第一个 Agent:让 AI 学会用计算器

先别急着搞复杂的 ReAct 或 Plan-and-Execute,我们从最简单的“工具调用”开始。目标是让 LLM 能调用一个计算器工具,而不是自己瞎算数学题。

from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
from langchain_community.tools import Tool

# 初始化模型,这里用 gpt-3.5-turbo 就够了,别浪费 gpt-4
llm = ChatOpenAI(
    model="gpt-3.5-turbo",
    temperature=0,  # 做 Agent 时 temperature 设 0,减少随机性
    verbose=True    # 打开调试日志,新手必开
)

# 自定义一个计算器工具
def calculator(expression: str) -> str:
    """计算数学表达式,例如 '2 + 3 * 4'"""
    try:
        # 这里用 eval 有安全风险,但演示够用
        result = eval(expression, {"__builtins__": {}}, {})
        return str(result)
    except Exception as e:
        return f"计算错误:{str(e)}"

calc_tool = Tool(
    name="计算器",
    func=calculator,
    description="用于执行数学计算,输入应为数学表达式,如 '2 + 3 * 4'"
)

# 初始化 Agent
agent = initialize_agent(
    tools=[calc_tool],
    llm=llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
    handle_parsing_errors=True  # 这个参数很重要,后面说
)

# 测试
response = agent.invoke("计算 12345 * 67890 的结果是多少?")
print(response["output"])

运行后你会看到类似这样的日志:

> Entering new AgentExecutor chain...
我需要计算 12345 * 67890 的结果。
Action: 计算器
Action Input: 12345 * 67890
Observation: 838102050
Thought: 我得到了计算结果。
Final Answer: 12345 * 67890 的结果是 838,102,050。

这里踩过坑:第一次跑的时候,模型可能输出 Action: 计算器 但后面没有 Action Input,导致解析失败。handle_parsing_errors=True 就是用来兜底的——当模型输出格式不对时,Agent 会重试而不是直接崩溃。

深入理解 Agent 的“思考-行动-观察”循环

上面那个例子看起来简单,但背后是 LangChain 的 ReAct 模式在运作。你可以把 Agent 想象成一个“会思考的机器人”:

  1. 思考(Thought):模型分析当前问题,决定下一步做什么
  2. 行动(Action):调用某个工具,传入参数
  3. 观察(Observation):获取工具返回的结果
  4. 循环:根据观察结果,再次思考,直到得出最终答案

这个循环在日志里看得一清二楚。新手最容易犯的错误是:以为 Agent 是一次性输出答案。实际上,Agent 可能会调用多次工具,比如先查维基百科,再用计算器算结果,最后整合答案。

调试技巧:让 Agent 的“思考过程”可视化

verbose=True 是调试利器,但有时候日志太多,你只想看关键步骤。可以这样:

import logging
logging.basicConfig(level=logging.INFO)
# 只打印 INFO 级别以上的日志,忽略 DEBUG 级别的工具调用细节

更高级的调试方式是用 langchain.callbacks

from langchain.callbacks import StdOutCallbackHandler

handler = StdOutCallbackHandler()
agent = initialize_agent(
    ...,
    callbacks=[handler]
)

这样你可以自定义回调函数,比如把 Agent 的思考过程写入文件,方便复盘。

常见翻车现场及修复

1. 模型输出格式不对

ValueError: Could not parse LLM output: `I need to calculate...`

原因:模型没有按照 Action: ...\nAction Input: ... 的格式输出。
修复:加 handle_parsing_errors=True,或者换一个更稳定的模型(比如从 gpt-3.5-turbo 换成 gpt-4)。

2. 工具返回结果太长

Error: String too long for LLM context window

原因:工具返回了超长文本(比如维基百科全文),超过了模型的上下文窗口。
修复:在工具函数里做截断,或者用 max_tokens 限制输出。

3. Agent 陷入死循环

Agent stopped due to max iterations (15) reached.

原因:模型反复调用同一个工具,无法收敛到最终答案。
修复:减少 max_iterations 参数(默认15),或者优化工具的 description,让模型更清楚什么时候该停止。

个人经验:从“能用”到“好用”的三个建议

  1. 工具的 description 比工具本身更重要。模型是通过 description 来决定是否调用工具的。别写“这是一个计算器”,要写“用于执行数学计算,输入应为数学表达式,如 ‘2 + 3 * 4’”。描述越具体,模型调用越准确。

  2. 永远不要信任模型的输出格式。即使是最强的模型,偶尔也会输出不符合规范的 JSON 或 Action 格式。handle_parsing_errors=Truemax_retries 是保命符。

  3. 从最简单的 Agent 开始,逐步增加复杂度。先跑通一个工具,再加第二个,最后才考虑多工具协作。我见过太多人一上来就搞 ReAct + 记忆 + 多工具,结果 debug 到怀疑人生。

最后说一句:LangChain 的版本迭代很快,这篇笔记基于 0.1.12 版本。如果你看到报错,先检查版本是否匹配。别问我为什么知道——就在写这篇文章的时候,LangChain 又发布了 0.2.0 的 beta 版,API 又变了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的陶老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值