Skip to content

LangChain+LangGraph 面试题 - 2026-06-14 23:54 ​

【面试题】1. LangChain的Runnable接口和LCEL到底解决了什么问题?为什么不直接用函数链式调用? ​

【标准答案】核心解决的是统一编排和流式兼容的问题。普通的函数链式调用比如 f1().then(f2).then(f3),你想加流式输出、加重试、加并行、加fallback,每个环节都得自己拼。Runnable接口把这些能力做成了标准协议——任何实现了Runnable的组件天然支持 .stream()、.batch()、.with_retry()、.with_fallbacks(),可以像乐高积木一样自由组合。LCEL就是用 | 管道符把这些Runnable串起来,底层帮你处理类型转换和异步调度。生产环境下这个抽象太重要了,不然你每个chain都得自己写流式和错误处理逻辑。

【面试题】2. LangGraph的State为什么推荐用TypedDict而不是普通的dict?实际踩过什么坑? ​

【标准答案】TypedDict给了你静态类型检查和IDE补全,这在复杂图里是刚需。图节点多了,state key十几二十个,用plain dict很容易拼错key名,运行时才发现。但实际踩坑主要是两点:一是TypedDict默认所有字段都是必填的,初始state要全量赋值,所以生产里我会给可选字段加 NotRequired;二是有些节点只更新部分字段,如果用了 Annotated 的reducer策略(比如 operator.add 做消息列表追加),得确保字段类型和reducer逻辑匹配,否则类型检查会报错但运行时静默出错。

【面试题】3. 如果让你设计一个LangGraph工作流,要求模型调用工具后、结果返回给模型前,加一个人工审批环节,怎么实现? ​

【标准答案】这正好是LangGraph的interrupt机制。在工具调用节点和结果回写节点之间,插入一个审批节点,节点里调用 interrupt() 让图暂停执行,返回当前状态给前端。人工审批通过后,用图的 resume() 方法传入审批结果继续执行,图会从中断点恢复。底层原理是图的checkpointer把完整状态序列化了,中断时持久化,恢复时反序列化继续。这在合规场景很常见,比如金融、医疗的AI决策流。

【面试题】4. LangChain的Memory在多轮对话里经常出现上下文丢失或者token爆炸,你怎么处理? ​

【标准答案】根本原因是Memory不加控制地全量塞进prompt。生产里我一般三层策略:第一,用ConversationSummaryMemory做摘要压缩,超过一定轮数自动总结历史,而不是把原始消息全塞进去;第二,用sliding window,只保留最近N轮的原始对话;第三,也是最关键的,分层记忆——短期记忆放最近对话,长期记忆用向量库存重要信息摘要,RAG检索相关记忆注入。这样既控制了token又不会丢关键上下文。实际效果:token消耗降60%以上,对话质量反而更好,因为检索到的记忆比全量堆砌更精准。

【面试题】5. 用LangGraph做多Agent协作时,Agent之间怎么通信?Supervisor模式和Swarm模式分别适用什么场景? ​

【标准答案】Supervisor模式下有一个中央调度节点,负责接收任务、分发给子Agent、收集结果、决定下一步。适合流程清晰的场景,比如"先检索→再分析→再生成报告",步骤有先后关系。Swarm模式下Agent之间可以Handoff,任何一个Agent觉得该转给别人处理就直接转交,没有中央节点。适合扁平化的场景,比如客服系统里"技术问题转技术Agent、退款问题转售后Agent"。我实际项目里更多用Supervisor,因为可控性更强,方便加日志、加审批、加重试。Swarm的自由度高但调试难度也高,Agent之间循环Handoff死循环是常见坑。

【面试题】6. LangChain的Tool调用在模型输出格式不规范时经常失败,你怎么提高Tool Call的可靠性? ​

【标准答案】这是个高频问题。我会从四个层面加固:第一,Prompt层面,在system prompt里明确写死工具调用的JSON schema示例,让模型见过正确格式;第二,Tool描述层面,description写得越清晰越好,包括参数含义、取值范围、返回值格式,这是模型选择工具和填参的依据;第三,解析层面,用 with_structured_output() 强制模型输出pydantic模型,比让模型自由生成JSON可靠得多;第四,兜底层面,加try-except和重试机制,解析失败时把错误信息反馈给模型让它重新生成。实测加了structured output之后,tool call成功率从85%左右提升到97%以上。

【面试题】7. LangGraph的断点续跑机制在生产中怎么用的?和简单的错误重试有什么区别? ​

【标准答案】断点续跑依赖图的checkpointer,本质是把每个节点执行完的状态快照存到持久化存储(内存、SQLite、PostgreSQL都支持)。和简单重试的区别在于粒度——重试是从当前节点重新执行,断点续跑是从任意历史节点恢复。生产场景:假设你的图跑了8个节点,第9个节点因为外部API超时挂了。简单重试只能重试第9个节点,但如果第9个节点的输入依赖前面某一步的状态被改了,重试就会得到错误结果。而断点续跑可以指定从第5个节点开始重新跑,状态完全一致。另一个重要用途是人机协作——图执行到某个节点暂停,等人工输入后再继续,这就是前面说的interrupt机制。

【面试题】8. 把RAG和LangGraph结合,实现一个带自纠错的文档问答系统,你会怎么设计图结构? ​

【标准答案】我会设计一个至少4个节点的图:第一个节点检索,从向量库召回相关文档;第二个节点生成,把检索结果和问题一起给模型生成答案;第三个节点评分,用另一个LLM调用或者规则判断答案质量,比如检查答案是否引用了文档内容、是否答非所问;第四个节点是条件分支——如果评分达标直接输出,不达标就回到检索节点换个查询重试,或者回到生成节点要求模型基于新信息重新回答。循环设上限,比如最多3轮,避免死循环。这比普通RAG链的优势是有了自纠错闭环,准确率能从70-80%提升到90%以上,尤其对复杂问题效果明显。

【面试题】9. LangGraph的流式输出有几种模式?什么时候用stream mode,什么时候用astream_events? ​

【标准答案】两种主要模式。stream() 和 stream_mode 是按节点粒度输出,每个节点跑完吐一次完整state更新,适合简单场景比如看到"正在检索→正在分析→生成完成"这种进度。astream_events() 是事件粒度的,可以捕获到LLM每个token的生成、工具调用的入参出参、每个chain内部的中间结果,颗粒度非常细。实际选择:给用户看打字机效果必须用 astream_events,因为要从LLM token级别拿流;如果只是要显示工作流进度条,用 stream 就够了,开销更小。一个容易踩的坑是 astream_events 版本迭代快,v1和v2的API不兼容,要注意版本对齐。

【面试题】10. 如果面试官问"你觉得LangChain和LangGraph的缺点是什么",你会怎么回答? ​

【标准答案】我会说三个点,都是实战体会。第一,抽象层太厚。LangChain的封装层级多,出了问题调试困难,你得从Chain→Prompt→Model一层层扒,有时候一个简单的调用经过五六层wrapper。所以现在新项目我更倾向直接用LangGraph + 原生LLM SDK,只在工具封装上用LangChain。第二,版本迭代不稳定,API频繁变动,特别是LCEL和回调系统的接口,升级一次可能改一堆代码。所以生产项目必须锁定版本,不要追最新。第三,文档和实际行为不一致,有些高级特性的文档滞后于代码,得看源码才能搞清楚实际行为。但话说回来,这套生态目前还是LLM应用开发最成熟的框架,缺点都是成长的烦恼。