LangChain 学习笔记 07:没有运行轨迹,LLM 应用只能靠猜来排错
传统接口报错时,我们至少能看到状态码和堆栈。LLM 应用更麻烦:它可能没有抛出异常,只是悄悄给出一个不完整、跑题或缺少证据的答案。
第 8 章介绍回调处理器。篇幅不算长,却提醒了我一件很重要的事:模型调用、检索和工具执行如果没有留下轨迹,系统上线以后几乎只能靠猜。
一次回答里到底发生了什么
一个 RAG 问答请求可能经历:
用户问题 -> 查询改写 -> 检索 -> 重排序 -> Prompt -> 模型 -> 输出解析
最终答案错了,原因可能是检索不到、检索正确但 Prompt 截断了、模型忽略证据,或者解析器删掉了字段。只记录最后答案,无法区分这些情况。
回调或追踪机制的作用,就是在组件开始、结束、失败和流式输出时收集事件,把一条请求还原成完整路径。
我希望一条 Trace 至少包含什么
{
"trace_id": "req-20260730-001",
"step": "retrieve_documents",
"duration_ms": 86,
"input_summary": "如何重置企业账号密码",
"result_count": 4,
"status": "success"
}
除了步骤和耗时,LLM 应用还应记录模型名称、Prompt 版本、token 使用量、检索文档 ID、工具名称、重试次数和错误类型。
但日志不应原样保存全部用户输入、文档正文和密钥。可观察性和隐私需要同时设计:敏感字段脱敏,正文只记摘要或引用 ID,日志设置访问权限和保留期限。
日志、指标和 Trace 各看什么
日志适合记录离散事件,例如某次解析失败、某个工具返回权限不足。
指标适合看整体趋势,例如请求量、P95 延迟、错误率、平均 token、检索空结果率和单次成本。
Trace用来还原一次请求跨组件的完整路径,特别适合排查“没有报错但回答变差”的问题。
三者不能互相替代。只有日志,很难看趋势;只有指标,看不到某次请求的细节;只有 Trace,也不容易快速发现系统性退化。
流式输出也需要被观察
流式返回可以改善等待体验,却增加了取消、断线和部分结果处理。除了总耗时,还可以记录首 token 延迟、流式中断位置和客户端取消状态。
如果输出解析必须等待完整内容,就要明确告诉调用链:前面可以流式展示,最终结构校验仍在结束后完成。不能因为用户已经看到半段文字,就默认整个调用成功。
先定义问题,再决定记录什么
可观察性不是“能记多少就记多少”。我更愿意从排障问题反推字段:
- 为什么这次回答没有引用?记录检索文档与引用映射。
- 为什么今天成本突然升高?记录模型、输入输出 token 和重试次数。
- 为什么 Agent 一直不结束?记录每轮工具、参数、结果和停止原因。
- 为什么新版 Prompt 质量下降?记录 Prompt 版本并保留评测样本。
有了明确问题,日志才不会变成昂贵又没人看的数据堆积。
这章给我的启发
Callback 不只是一个打印 token 的辅助功能,它是 LLM 应用可观察性的入口。
当系统由多个非确定组件组成时,“运行成功”不能只看有没有返回 200。我们还要知道它走过哪些步骤、使用了哪些证据、花了多少成本,以及结果为什么变成现在这样。能回答这些问题,应用才真正具备迭代和维护的基础。

浙公网安备 33010602011771号