核心要点
能讲清本质:Callback 是事件钩子系统,在 LLM、Chain、Tool、Agent 运行的各个阶段(on_llm_start/on_llm_new_token/on_llm_end/on_chain_start/on_tool_error 等)触发回调,让你在不改业务逻辑的前提下插入副作用
能列举典型用途:流式输出(on_llm_new_token 逐 token 推送)、日志记录、监控与链路追踪(接 LangSmith)、token 用量与成本统计、自定义副作用(写库、发告警)
能说出实现方式:继承 BaseCallbackHandler 重写对应事件方法,挂载方式有构造期 callbacks 与运行期 config={"callbacks": [...]},可全局或单次调用粒度生效
能区分 LCEL 下的演进:新版更常用 LangSmith 追踪和 astream_events 事件流统一消费事件,Callback 仍是底层机制但很多观测场景已被托管追踪替代
标准回答
机制本质
LangChain 运行一条链时,内部组件(LLM、Chain、Tool、Retriever、Agent)会在关键节点发出事件。Callback 机制就是让你注册一组 handler,在这些事件触发时执行自定义代码,从而把「可观测性、流式、副作用」与核心业务逻辑解耦。
主要事件
- LLM 级:on_llm_start、on_llm_new_token(流式逐 token)、on_llm_end、on_llm_error。
- Chain 级:on_chain_start、on_chain_end、on_chain_error。
- Tool 级:on_tool_start、on_tool_end、on_tool_error。
- Agent / Retriever 级:on_agent_action、on_agent_finish、on_retriever_start 等。
典型用途
- 流式输出:在 on_llm_new_token 把 token 推给前端或 SSE,实现打字机效果。
- 日志与调试:记录每步输入输出、耗时,定位链路问题。
- 监控与追踪:挂 LangSmith 的追踪 handler,自动可视化整条调用树。
- 成本统计:在 on_llm_end 累加 prompt/completion token,估算调用成本。
- 自定义副作用:异常时告警、命中策略时写审计日志等。
实现与挂载
自定义时继承 BaseCallbackHandler 并重写需要的事件方法。挂载有两种粒度:构造组件时传 callbacks(对该组件生效),或在调用时通过 config={"callbacks": [handler]} 传入(仅本次运行生效,更灵活)。
2026 的实践
LCEL 普及后,流式更多直接用 stream/astream,而要细粒度消费各阶段事件可用 astream_events(统一的事件流 API);可观测性则普遍交给 LangSmith 托管追踪。Callback 仍是这些能力的底层机制,但日常开发中直接手写 handler 的场景减少,多见于自定义副作用和接入自有监控系统。
常见误区
⚠️ 常见踩坑
在 Callback 里做重阻塞操作(同步写库、远程请求)会拖慢甚至卡住主链路,副作用应尽量轻量或异步化;以为 Callback 能修改链的中间结果——它主要用于观测和副作用,不该承担业务流程控制;异步执行环境里用同步 handler 可能丢事件或报错,要用对应的异步回调(如 AsyncCallbackHandler);把可观测性全靠手写日志,其实接 LangSmith 追踪更省事也更完整。
追问
追问 1:用 Callback 做流式输出和直接用 stream/astream 有什么区别?
抽象层级:on_llm_new_token 回调是底层 token 事件钩子,需要自己写 handler 把 token 推出去;stream/astream 是 LCEL 的高层接口,直接以迭代器形式产出增量结果,代码更简洁。
适用面:只想把最终输出流式给前端,用 stream/astream 即可;要同时观测中间各组件事件、做成本统计或自定义副作用,Callback(或 astream_events)更合适。
关系:stream 底层其实也依赖回调事件,两者并不互斥,常组合使用——用 stream 拿输出,用 callback/LangSmith 做追踪。
追问 2:怎么用 Callback 统计一次调用的 token 用量和成本?
取数:在 on_llm_end 事件里,从返回的 LLMResult.llm_output(或 usage_metadata)读 prompt_tokens、completion_tokens,按模型单价换算成本并累加。
现成工具:OpenAI 系可用 get_openai_callback() 上下文管理器,块内自动汇总 token 数与美元成本,省去手写 handler。
落地:把每次调用的 token 与成本写进日志/数据库,按用户或会话聚合,用于配额限流和成本看板;多模型混用时按模型分别记单价。
追问 3:BaseCallbackHandler 和 LangSmith 追踪是什么关系?生产上怎么取舍?
关系:LangSmith 的自动追踪本质就是内置的一组 callback handler,挂在运行上把每一步事件上报到平台,形成可视化调用树;BaseCallbackHandler 则是让你写自定义 handler 的基类。
取舍:通用可观测性(链路、耗时、token、错误)优先用 LangSmith,配置环境变量即开箱即用,省去自研监控;自定义 handler 留给平台覆盖不到的需求,如写入自有数据仓库、触发业务告警、对接公司内部 APM。
实践:二者并存,LangSmith 兜底全链路追踪,手写 handler 补充特定副作用,注意控制 handler 开销避免影响主链路。
🔗 相似问题
同一考点的不同问法,面试官可能换着问,一起刷更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习