精选LangChain新闻
我们为何重建 LangChain 的聊天机器人以及我们学到了什么
LangChain 团队分享了其聊天机器人的重建经验,采用 Deep Agents 和子图技术,将响应时间缩短至 15 秒以内,并提供精确引用。文章总结了技术选型、架构调整及可复用的实践方法,对构建高效对话系统具有参考价值。

背景
每个成功的平台都需要可靠的支持,但我们意识到自己的团队花了大量时间查找技术问题的答案。这种低效不仅拖慢了工程师的进度,更是用户面临的关键瓶颈。
我们决定用自己力推的工具来解决这个问题:LangChain、LangGraph 和 LangSmith。我们最初将 chat.langchain.com 构建为一个原型,明确设计为承担两个功能:
- 产品问答:帮助用户——以及我们自己的团队——即时获得关于产品问题的权威答案。
- 客户原型:作为一个活生生的示例,展示客户如何利用 LangChain 技术栈构建复杂、可靠的智能体。
我们有明确的目标,也有可用的产品。但我们要坦白一件事:我们的支持工程师并没有积极使用 LangChain Chatbot。这才是我们真正学习的开始。这就是我们如何修复自己的智能体——以及我们在构建客户可以采纳和使用的、真正可靠的生产级应用中学到的东西。
我们的团队没有积极使用 Chat LangChain,不是因为它坏了,也不是因为不信任它。而是因为当有人问“为什么生产环境中流式输出不工作?”时,他们需要比仅仅把文档当作唯一资源更深入的东西。我们都知道文档永远不够。
- 第 1 步:搜索我们的文档(docs.langchain.com),了解该功能应该做什么。
- 第 2 步:查看我们的知识库(support.langchain.com),看看其他用户是否遇到同样的问题以及如何解决。
- 第 3 步:打开 Claude Code,搜索实际实现,验证代码实际做了什么。
文档提供官方说明。知识库提供真实世界的问题。代码库提供事实依据。
我们决定将其自动化
这个三步流程效果非常好。我们看着他们每天重复几十次,心想:如果我们把这个工作流自动化会怎样?
于是我们构建了一个内部 Deep Agent(一个用于构建能够处理复杂多步任务的智能体的库),包含三个专门的子智能体——一个负责文档,一个负责知识库,一个负责代码库搜索——每个子智能体在将见解传递给主编排智能体之前,都会提出后续问题并筛选结果。
示例输出:“要从子图进行流式输出,请根据 LangGraph 流式文档在流配置中设置 subgraphs: true。有一篇支持文章题为‘为什么升级后令牌流式输出不工作’,正好解释了这个问题——你需要启用子图流式输出才能从嵌套智能体获得令牌级更新。实现位于 pregel/main.py 第 3373-3279 行,其中 subgraphs 标志控制嵌套图输出是否包含在流中。”
我们的工程师非常喜欢。
这每周为他们节省了大量复杂调试的时间。他们描述一个生产问题,就能得到一个全面的答案,其中引用了文档、参考了已知解决方案,并指出了关键代码的确切行号。
然后我们有了一个领悟
然后有人问了一个显而易见的问题:如果这对我们这么有效,为什么我们的公开版 Chat LangChain 不这样做?
这是个合理的质疑。我们的公开工具是将文档切分成片段、生成嵌入、存储在向量数据库中。文档更新时我们必须不断重新索引。用户能得到答案,但引用需要改进,上下文也是碎片化的。
我们无意中通过复制有效的方法,在内部构建了更好的东西。是时候把同样的方法带到公开产品中了。
当我们开始重建时,很快意识到需要结合两种不同的架构,以应对两大类问题。大多数问题可以通过文档和知识库来回答,其余问题则需要分析代码基础。
我们如何构建新 Agent
针对简单文档:创建 Create Agent
我们选择 createAgent(langchain 中的 Agent 抽象)作为 chat.langchain.com 的默认模式,因为它最适合追求速度。
它没有规划阶段,没有编排开销——只有即时的工具调用和回答。该 agent 会搜索文档,必要时查阅知识库,如果结果不清晰则优化查询,然后返回答案。大多数文档类问题可以通过 3-6 次工具调用解决,而 Create Agent 能在几秒内完成这些调用。
模型选项:
我们为终端用户提供多种模型——Claude Haiku 4.5、GPT-4o Mini 和 GPT-4o-nano——并且发现 Haiku 4.5 在工具调用方面异常快速,同时保持较高的准确性。createAgent 与 Haiku 4.5 的组合让大多数查询都能在 15 秒内得到响应,这正是文档问答所需要的。
优化方式:
我们使用 LangSmith 追踪每一次对话,识别 agent 在哪些地方进行了不必要的工具调用,并优化提示词。数据显示,如果我们教会 agent 提出更好的后续问题,大多数问题只需 3-6 次工具调用就能解决。LangSmith 的评估套件让我们能够对不同提示策略进行 A/B 测试,并衡量速度和准确性的提升。

针对代码回答:带子图的 Deep Agent
很多问题除了需要利用文档、知识库和交叉参考已知问题作为资源外,还需要深入搜索我们的代码库来验证实现细节。
架构:
针对这些任务,我们构建了一个带有专门子图的 Deep Agent:一个用于文档搜索,一个用于知识库搜索,一个用于代码库搜索。
每个子 agent 独立运行,提出后续问题,筛选信息,只提取最相关的见解,然后传递给主编排 agent。这既防止主 agent 被上下文淹没,又允许每个领域专家尽可能深入挖掘。
代码库搜索的优势:
代码库搜索子 agent 尤其强大。它可以使用模式匹配搜索我们的私有仓库,浏览文件结构以理解上下文,并以行号级别的精度读取具体实现。
权衡:
这种深度 agent 架构运行时间更长——复杂查询有时需要 1-3 分钟——但彻底性值得。当初始响应未能解决核心问题时,我们会使用 DeepAgent。
免责声明:此模式在发布时仅对部分用户启用,将在几天内向所有用户开放。
我们为何放弃向量嵌入
标准的文档搜索方法——将文档切块、生成嵌入、存储在向量数据库中、按相似度检索——对于 PDF 这类非结构化内容效果不错。但对于结构化产品文档,我们不断遇到三个问题。
切块破坏结构。当你把文档切成 500 token 的片段时,会丢失标题、子章节和上下文。Agent 会引用“设置 streaming=True”却不解释原因和时机。用户不得不在页面中翻找所需信息。
持续重新索引。我们的文档每天多次更新。每次更改都意味着重新切块、重新嵌入、重新上传。这拖慢了我们的速度。
引用不明确。用户无法验证答案或追溯信息来源。
突破点在于我们意识到自己一直在解决错误的问题。文档本就已有组织结构,知识库本就已有分类体系,代码库本就具备可导航性。我们需要的不是更智能的检索——而是让智能体直接访问这些已有的结构。
更好的方案:直接API访问与智能提示
我们没有采用分块和嵌入的方式,而是让智能体直接访问真实内容。对于文档,我们使用Mintlify的API,返回完整的页面,包含所有标题、子章节和代码示例。对于知识库,我们先按标题搜索支持文章,然后完整阅读最相关的几篇。对于代码库搜索,我们将代码库上传到LangGraph Cloud部署中,使用ripgrep进行模式匹配、目录遍历来理解结构,以及文件读取来提取具体实现。
智能体不基于相似度分数进行检索。它像人类一样搜索——使用关键词、逐步细化和追问。
这就是神奇之处所在。我们不只是让智能体搜索一次然后返回找到的内容。我们提示它批判性地思考自己是否拥有足够的信息。如果结果模糊或不完整,智能体会优化查询并再次搜索。如果文档提到某个概念但没有解释,智能体会专门搜索这个概念。如果存在多种可能的解释,智能体会缩小范围到最相关的那一个。
工具设计:为人类工作流程而构建
我们设计的工具旨在模仿人类实际的搜索方式,而非检索算法的工作方式。
文档搜索:完整页面,而非片段
文档搜索工具查询Mintlify的API并返回完整页面。当有人询问流式传输时,智能体不会从不同章节获取三段互不连贯的段落——它会获得完整的流式传输文档页面,其结构正如人类阅读时的样子。
@tool def SearchDocsByLangChain(query: str, page_size: int = 5, language: Optional[str] = None) -> str: """通过Mintlify API搜索LangChain文档""" params = {"query": query, "page_size": page_size} if language: params["language"] = language response = requests.get(MINTLIFY_API_URL, params=params) return _format_search_results(response.json())
但我们不止于此。我们提示智能体评估初始结果是否真正回答了问题。这是正确的章节吗?是否有需要澄清的相关概念?是否有更具体的搜索词会更合适?
智能体有4-6次工具调用的预算,我们鼓励它策略性地使用这些调用来完善理解,然后再做出回答。
以下是实际效果:
用户问:“如何为我的智能体添加记忆?”
智能体搜索“memory”,得到的结果涵盖检查点、对话历史和Store API。智能体没有随机选择一个,而是意识到这个问题存在歧义——记忆可能意味着在线程内持久化对话状态,也可能意味着跨多个对话存储事实。
它再次搜索“checkpointing”来缩小到线程级持久化,获取了支持文章“如何在LangGraph中配置检查点?”,并发现这篇文章没有涵盖跨线程记忆。
于是它搜索“store API”来填补这一空白。
最终答案同时涵盖了用于对话历史的检查点和用于长期记忆的Store API,并精确引用了所使用的支持文章和文档。
这种迭代式搜索过程在Create Agent中只需几秒钟即可完成,但它从根本上改变了回答的质量。智能体不仅仅在检索——它在推理用户真正需要什么。
知识库搜索:先扫描,再阅读
我们将知识库(由Pylon提供支持)搜索构建为两步流程,因为这就是人类使用知识库的方式。
首先,智能体会检索文章标题——有时多达几十个——并快速浏览以判断哪些可能相关。然后,它只完整阅读那些筛选出的文章。
@tooldef search_support_articles(collections: str = "all", limit: int = 50) -> str: """第1步:获取文章标题以供浏览""" articles = pylon_client.list_articles(collections=collections, limit=limit) return json.dumps([{ "id": a["id"], "title": a["title"], "url": a["url"] } for a in articles])@tooldef get_article_content(article_ids: List[str]) -> str: """第2步:阅读最相关的文章""" articles = pylon_client.get_articles(article_ids) return "\\n\\n---\\n\\n".join([ f"# {a['title']}\\n\\n{a['content']}\\n\\nSource: {a['url']}" for a in articles ])
为什么这样有效:
这避免了智能体被信息淹没。与其将30篇完整文章塞进上下文窗口,智能体会筛选出真正重要的2-3篇,仔细阅读,并提取关键信息。
提示词设计也强化了这一点:重质不重量,必要时缩小搜索范围,只返回直接回答问题的信息。
代码库搜索:搜索、导航、验证
这是我们的Deep Agent大放异彩的地方。
@tooldef search_public_code(pattern: str, path: Optional[str] = None) -> str: """第1步:查找匹配模式的代码""" cmd = ["rg", pattern, str(path or search_path)] return subprocess.run(cmd, capture_output=True, text=True).stdout@tooldef list_public_directory(path: str, max_depth: int = 2) -> str: """第2步:了解文件结构""" cmd = ["tree", "-L", str(max_depth), str(path)] return subprocess.run(cmd, capture_output=True, text=True).stdout@tooldef read_public_file(file_path: str, start_line: int = 1, num_lines: int = 100) -> str: """第3步:阅读实际实现代码""" with open(file_path, "r") as f: lines = f.readlines() return "\\n".join(lines[start_line-1:start_line-1+num_lines])
工作原理:
首先,它使用ripgrep在代码库中搜索模式。然后列出目录结构以了解文件的组织方式。最后,它读取特定文件,聚焦相关代码段,并返回带行号的实现代码。
实际案例:
用户报告生产环境中流式传输令牌出现挂起。文档子智能体发现流式传输配置涉及缓冲区设置。知识库子智能体找到一篇关于升级后令牌流式传输问题的支持文章。
但代码库子智能体才是找到实际实现的那个——它搜索“streaming buffer”,导航到callbacks/streaming.py,并返回第47-83行,那里硬编码了默认缓冲区大小。
这就是能解决实际问题的深度调查。
区别在哪里?Deep Agent可以在这三个领域并行工作,并将中间发现汇总为一个连贯的答案。
Deep Agent和子图如何解决上下文过载问题
当我们最初将deep agent构建为一个可访问全部三种工具的单体系统时,它会返回找到的所有内容。主智能体会同时收到五篇文档页面、十二篇知识库文章和二十段代码片段。
上下文窗口会瞬间爆炸,最终回复要么被无关细节充斥,要么完全错过关键信息。
于是我们改用专门的子图来重构它。
每个子智能体独立运行。它搜索自己的领域,提出后续问题以澄清歧义,筛选结果,只提取核心数据:回答问题所需的基本事实、引用和上下文。
主编排智能体永远不会看到原始搜索结果。它只接收来自每个领域专家的精炼洞察。完整的追踪记录和提示词请参见**此处。
为什么这很重要:
文档子代理可能会阅读整整五页,却只返回两段关键内容。知识库子代理可能会扫描二十个文章标题,却只返回三条相关摘要。代码库子代理可能会搜索五十个文件,却只返回带有行号的具体实现。
主代理获得的是干净、精选的信息,可以将其综合成全面的答案。
为生产环境做好准备
即使是最优雅的代理设计,也需要生产级基础设施才能在真实用户面前站得住脚。我们构建了模块化中间件来处理运维层面的问题,否则这些问题会塞满我们的提示词。
middleware = [ guardrails_middleware, # 过滤无关查询 model_retry_middleware, # API 失败时重试 model_fallback_middleware, # 必要时切换模型 anthropic_cache_middleware # 缓存高成本调用]
每一层的作用:
Guardrails 过滤掉与主题无关的查询,让代理专注于 LangChain 相关问题。
Retry 中间件优雅地处理临时 API 故障,用户永远不会看到晦涩难懂的错误信息。
Fallback 中间件在某个模型不可用时,在 Haiku、GPT-4o Mini 和 Gemini Nano 之间切换。
Caching 通过复用相同查询的结果来降低成本。
这些层对用户不可见,但对可靠性至关重要。它们让代理专注于推理,而基础设施负责处理故障模式、成本优化和质量控制。
将代理交付给用户
构建一个优秀的代理只是成功了一半。另一半是什么?是以快速且智能的方式将其交付给用户。
我们使用 LangGraph SDK 来处理流式传输和状态管理的所有复杂性。
加载用户线程:
const userThreads = await client.threads.search({ metadata: { user_id: userId }, limit: THREAD_FETCH_LIMIT,})
每个线程都将用户 ID 存储在元数据中,因此对话在会话之间保持私密和持久。LangGraph SDK 自动处理过滤。
实时流式响应:
const streamResponse = client.runs.stream(threadId, "docs_agent", { input: { messages: [{ role: "user", content: userMessage }] }, streamMode: ["values", "updates", "messages"], streamSubgraphs: true,})for await (const chunk of streamResponse) { if (chunk.event === "messages/partial") { setMessages(prev => updateWithPartialContent(chunk.data.content)) }}
用户看到的内容:
- messages — 令牌随着代理的书写逐步出现
- updates — 工具调用揭示代理正在搜索什么
- values — 处理完成后的最终完整状态
用户可以看到代理思考、搜索文档、查阅知识库,并逐令牌构建回答。没有加载转圈。
对话记忆
在消息之间传递相同的 thread_id,LangGraph 的检查点机制会处理其余工作。它存储对话历史,为每一轮检索上下文,并在会话之间维护状态。我们设置了 7 天的 TTL。仅此而已。
成果
自新系统上线以来,我们看到了显著的改进。
对于公开的 Chat LangChain,用户可以在 15 秒内获得带有精确引用的回答。他们可以立即验证答案,因为我们直接链接到相关的文档页面或知识库文章。而且我们不再需要花费数小时重新建立索引——文档会自动更新。
在内部,我们的支持工程师使用 Deep Agent 来处理最复杂的工单。它搜索文档、交叉参考已知问题,并深入我们的私有代码库,找到真正解释问题根源的实现细节。这个代理并不会取代我们的工程师——它放大了他们的能力,处理研究工作,让他们专注于解决问题。
关键经验
- 遵循用户的工作流程:不要重复造轮子;将最优秀用户(或内部专家)已经使用的成功工作流自动化。对 LangChain 而言,这意味着复现“查文档、查知识库、查代码库”这三步常规流程。
- 评估向量嵌入是否适用:对于产品文档和代码这类结构化内容,使用向量嵌入可能会破坏文档结构,导致引用模糊,并且需要持续重建索引。向量嵌入非常适合非结构化内容、较短的文本块或聚类场景。
- 让智能体直接访问结构:这种方法允许智能体通过 API 直接访问内容的现有结构,使其能像人类一样使用关键词和细化条件进行搜索。
- 将推理置于检索之上:设计工具时模仿人类工作流:先浏览文章标题再阅读内容,对代码使用模式匹配和目录导航。提示智能体在初始结果不明确时提出后续问题并细化查询,确保最终答案覆盖用户的真实需求。
- 使用 Deep Agents 和子图管理上下文:对于复杂的跨领域问题,使用带有专门子图的 Deep Agent 可以防止主编排智能体被大量原始搜索结果淹没。每个子智能体先在其领域内过滤并提取“精华数据”,再将提炼后的洞察向上传递。
- 生产级中间件的必要性:即使智能体设计再优雅,也需要健壮的基础设施才能保证可靠性。实现模块化中间件用于护栏(过滤离题查询)、重试(应对 API 故障)、回退(切换模型)和缓存,对于生产级的可靠性、成本优化和质量控制至关重要。
下一步计划
公开代码库搜索(将在未来几天内上线)——当文档和知识库不够用时,智能体将搜索我们的公开仓库以验证实现,并引用精确的行号。
亲自体验
Chat LangChain 已在 chat.langchain.com 上线。你可以使用 Claude Haiku 4.5 获得最快的响应,也可以尝试 GPT-5 Mini 和 GPT-5 Nano,看看不同模型的表现差异。
加入讨论
构建兼顾速度与深度的智能体并不容易,我们仍在不断学习。如果你也在解决类似问题,我们很乐意听听你的发现。
欢迎加入 LangChain 社区论坛,或关注我们的 Twitter。
了解你的智能体到底在做什么
LangSmith,我们的智能体工程平台,帮助开发者调试智能体的每一个决策、评估变更,并一键部署。
译文已达到本站中文翻译的字数上限,剩余内容请查看原文。