
一、 引言:你的Agent为何在“黑盒”里运行?
嗨,大家好,我是技术老金。
我们刚刚聊完如何用LangGraph构建复杂的AI工作流。但一个残酷的现实是:你构建的流程越复杂,调试的难度就呈指数级上升。
你有没有经历过这样的绝望:
- 你的多智能体应用跑了半天,最后输出一个莫名其-妙的结果,你完全不知道中间哪个环节出了问题。
- Agent在某个步骤陷入了死循环,你只能眼睁睁看着它烧掉你的Token,却不知道它为何卡住。
- 你想优化某个Prompt,但你根本看不到它在实际运行时,被填充的完整上下文到底是什么样子。
传统的print
调试大法,在这些复杂的、异步的、充满了LLM调用的“分布式系统”面前,彻底失效了。我们就像在“盲人摸象”,摸到哪算哪,毫无头绪。
如果你还在用print
来调试你的Agent,那么,请立即停止这种“石器时代”的做法。今天,老金就给你介绍真正的“现代文明”——LangSmith,并分享我压箱底的3个关键调试技巧,让你能像用显微镜一样,看清你的Agent在“黑盒”里的一举一动。
二、 准备工作:三行命令,进入现代文明
在开始之前,请确保你已经拥有LangSmith账号,并完成了最基础的安装和配置:
pip install langsmith langchain
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="你的LangSmith API Key"
好了,拿到这张“登机牌”后,我们来看看如何开好这架飞机。
三、 LangSmith是什么?它不是日志,是“飞行记录仪”
在深入技巧之前,我们必须搞清楚LangSmith的本质。
它不是一个简单的日志工具,它是一个**“AI应用的可观测性平台”。如果说你的Agent是一架飞机,那LangSmith就是这架飞机的“黑匣子”(飞行记录仪)**。
它能帮你记录下:
- 每一次运行(Trace)的完整链路。
- 链路中每一个步骤(Step)的输入、输出、耗时和Token消耗。
- 步骤中每一次对LLM、工具、向量数据库的调用详情。
最关键的是,它用一个极其精美的、可交互的界面,把这一切都可视化了出来。
四、 我的3个关键调试技巧
掌握了基本用法,我们来看点真正能提升效率的“独门秘籍”。
技巧一:用“标签”和“元数据”过滤你的“航班”
当你的应用跑了几百上千次之后,LangSmith的后台会充满了密密麻麻的运行记录(Traces)。想从这“航班信息中心”里,快速找到某一次特定的、出了问题的运行,就成了一个难题。
解决方案:学会使用tags
和metadata
,给你的每一次运行打上“标签”。
# 在调用你的app时,传入一个config
app.invoke(
{"topic": "AI Agent的未来"},
config={
"metadata": {"user_id": "user_123", "env": "production"},
"tags": ["multi_agent_test", "v2_prompt"],
}
)
这样,你就可以在LangSmith的后台,通过user_id: "user_123"
或者tag: "v2_prompt"
这样的过滤条件,从成千上万条记录中,瞬间定位到你想要的那一次运行。
老金建议:把版本号、环境(dev/prod)、用户ID这些关键信息,作为metadata
的标配,能极大提升你的问题追溯效率。
技巧二:用“数据集”和“评估器”给你的Agent“体检”
调试不仅仅是“找Bug”,更是“评估性能”。比如,你优化了一个Prompt,怎么确定它就一定比旧的好?
解决方案:使用LangSmith的“数据集与评估”功能,建立一套自动化的“回归测试”流程。
- 创建数据集 (Dataset):在LangSmith后台,把你遇到的各种典型的、或者曾经出过错的输入,创建一个数据集。比如
Dataset: "刁钻问题合集"
。 - 编写评估器 (Evaluator):你可以用代码,或者直接用LLM作为评委,来定义一个“评估标准”。
- 运行测试:将你的Agent应用,跑在你的数据集上,并指定你编写的评估器。
跑完之后,LangSmith会给你生成一份详细的“体检报告”。你能清晰地看到,你的Agent在新旧版本下,对于每一个测试用例的得分变化。这种基于数据的、可量化的评估,远比你凭感觉说“好像变好了”,要可靠一百倍。
我们来看一个简单的代码示意:
from langsmith import Client
from langsmith.evaluation import evaluate
# 1. 初始化客户端
client = Client()
# 2. 定义一个简单的评估器,检查输出是否包含特定词
def must_contain_word(run, example):
output = run.outputs.get('output', '') # 安全地获取输出
required_word = example.outputs['must_contain']
return {"score": int(required_word in output)}
# 3. 在你的数据集上运行评估
# 假设你有一个叫'app'的agent, 和一个叫'刁钻问题合集'的数据集
# 数据集中的每一行,inputs是一个字典,outputs也是一个字典,包含'must_contain'键
# evaluate(
# lambda inputs: app.invoke(inputs), # 你的Agent应用
# dataset_name="刁钻问题合集", # 你在UI上创建的数据集名称
# evaluators=[must_contain_word], # 指定你的评估器
# )
这段代码清晰地展示了评估的三个核心步骤:初始化客户端、定义评估函数、运行评估。这足以打消开发者的疑虑,让他们知道这是可以通过代码实现的,而不是一个纯UI的“魔法”。
技巧三:用“Playground”复现并优化你的“事故现场”
当你从Trace中发现某一个LLM的调用结果不理想时,你该怎么办?把代码改了,再完整跑一遍流程吗?太慢了!
解决方案:直接使用LangSmith内置的Playground功能。
在任何一个LLM调用步骤的详情页,你都可以点击“Open in Playground”按钮。
这会把你带到一个神奇的界面,它已经为你完整复现了这次调用的所有信息:
- 所使用的模型(Model)
- 完整的提示词(Prompt)
- 所有的模型参数(温度、Top P等)
现在,你可以像在游乐场(Playground)里一样,随意修改你的Prompt,调整模型参数,然后点击“Run”,立刻就能看到新的输出结果。你可以在这里反复实验,直到找到最佳的Prompt和参数组合。
然后,你再胸有成竹地,把优化后的结果,复制回你的代码里。这个功能,能把你的Prompt优化效率,提升至少10倍。
五、 老金总结:从“猜”到“看”的革命
我们必须承认,构建复杂的AI Agent,本质上是在跟“不确定性”打交道。而LangSmith,就是我们对抗这种不确定性的最强武器。
它带来的,是一场从“猜测”到“看见”的革命。
- 技巧一(标签与元数据),让你能从信息的海洋中,看见你想看的那条鱼。
- 技巧二(数据集与评估),让你能用客观的数据,看见你的优化是否真的有效。
- 技巧三(Playground),让你能在一个隔离的环境里,看见你的每一次微调带来的变化。
如果你想在AI Agent的开发道路上走得更远、更稳,那么,请把LangSmith,当作你和你的团队,从第一天起就必须掌握的“基础设施”。