聊《同样是LangChain,为什么有的能上线、有的只能演示?》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。
摘要
做过LangChain项目的都知道,调个API、写个Chain,两小时就能跑出能演示的结果。但真正接进业务系统、交给你带的人或者上线之后,问题才一个个冒出来。我第一次栽跟头,是因为以为"能跑就行"——实际上,Demo和线上之间隔着权限、日志、错误处理这三道坎。这篇文章把我当时的排查过程、踩过的坑、以及最终的取舍路线拆清楚,希望能帮你少走弯路。
目录
- LangChain能解决什么问题
- 核心组件
- 实战案例:一个RAG客服Agent的联调翻车
- 排查过程
- 关键代码实现
- 失败原因分类
- 适用边界
- 总结
LangChain能解决什么问题

LangChain的定位是"组装模型的工具链"。模型本身只会生成文本,它不懂怎么调工具、怎么存上下文、怎么处理用户的意图。LangChain要解决的,就是把模型嵌入到一个有状态、可观测、可迭代的应用框架里。
具体来说,它做了三件事:
- Prompt管理:把各种模板、变量替换、消息格式统一起来
- Chain编排:把多个步骤串成执行流,支持条件分支和循环
- 工具集成:给模型暴露外部API,让它能"动手"而不是只"动嘴"
但说实话,LangChain不是银弹。它解决了"怎么把模型接进流程"的问题,却解决不了"流程对不对"和"出了事怎么查"的问题。后者才是Demo到线上的真正门槛。
核心组件

LangChain的组件体系不算复杂,但很多人一开始就搞混。我把它们按实际使用频率排个序:
LLM类:这是最基础的。ChatOpenAI、ChatAnthropic这些是接口,真正调用的是模型。国内项目现在普遍用ChatGLM、Qwen这些,接口类似,差异在参数和Token计算方式。
Prompt类:ChatPromptTemplate是主力。它允许你把变量嵌进消息里,然后让链去填充。注意,Prompt本身不执行,它只是数据。
Chain类:LCEL(LangChain Expression Language)是现在的推荐写法。相比早期的Chain基类,LCEL更轻量、更易调试。RunnablePassthrough和RunnableLambda是两个很常用的算子。
Memory类:对话历史管理。BufferMemory最简单,但生产环境建议自己写一个带过期时间的缓存,否则Token会无限增长。
Tool类:工具的定义和注册。@tool装饰器是最方便的方式,但也最容易写出有安全隐患的工具——这个问题后面会说。
实战案例:一个RAG客服Agent的联调翻车
我做的案例是一个企业内部知识库的问答Agent。输入是员工的问题,输出是带来源引用的回答。技术栈:LangChain + Qwen模型 + Elasticsearch作为向量检索。
Demo阶段一切正常。员工问"报销流程怎么走",Agent能检索出相关文章并给出答案。业务方看了很满意,说要接入内部系统。
接入第二天,问题爆发:
- 一部分用户反映"看不到回答"
- 另一部分用户收到权限不足的错误
- 日志里全是乱码,根本定位不到是哪一步出错

排查过程
我按以下链路逐步排查:
现象一:部分用户无响应
先确认是不是模型挂了。直接调用Qwen的API,正常。所以不是模型问题。
再查LangChain的执行日志。发现问题出在工具调用环节——某些用户触发的查询,走到了一个需要读内部DB的工具,而这个工具没有做权限校验。没有权限的用户触发了异常,但异常被吞掉了,前端只看到"请求超时"。
现象二:日志乱码
这个问题更隐蔽。原来我在调试时直接print了完整请求体,包括用户token。上线后环境变了,sys.stdout的编码不对,导致中文乱码。而且日志没有分层,错误信息和正常信息混在一起,根本分不清是哪里出的问题。
现象三:Response没有溯源信息
这个属于业务逻辑问题。原本设计里,回答应该带上来源链接。但实际输出时,来源信息在中间环节被丢弃了——因为我把原始文档内容拼进了Prompt,却没有把元数据透传到最后一步。
排查下来,三个问题分别对应:权限缺失、日志缺失、数据透传缺失。都是Demo阶段不会被发现的"隐形问题"。
关键代码实现
我把最核心的部分贴出来,逐段解释。
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
# 1. 工具定义:必须加权限校验,不能信任模型的输入
@tool
def search_knowledge(question: str) -> dict:
"""搜索知识库,返回相关文章"""
# 这里应该加权限校验:用户是否有权访问该类别的知识库
results = elasticsearch.search(question)
return {"docs": results, "count": len(results)}
# 2. Prompt模板:变量替换
prompt = ChatPromptTemplate.from_messages([
("system", "你是内部客服助手,请根据参考资料回答问题。"),
("user", "{question}")
])
# 3. Chain编排:用LCEL串联
chain = (
{"question": RunnablePassthrough()}
| prompt
| model
| RunnableLambda(format_response) # 自定义输出格式化
)
代码解释:
第一段search_knowledge是一个工具函数。注意注释里的权限校验——这是很多人忽略的地方。Demo阶段你可能用同一个账号测试,不会发现问题。但线上用户角色不同,有的能查财务知识,有的不能。如果工具本身不做过滤,模型可能会把不该让用户看到的内容返回出去。
第二段的ChatPromptTemplate是标准的消息模板。这里没有复杂的动态拼接,保持简单。实际项目中,Prompt往往会根据用户身份做动态调整,这时候建议在Chain层做,而不是在Prompt模板里写条件逻辑。
第三段的LCEL链条是核心。RunnablePassthrough直接把输入透传到下一个环节,RunnableLambda用于自定义处理。format_response负责把模型的输出和检索结果拼接成最终格式,同时把溯源信息保留下来——这就是之前丢元数据的问题的修复方式。
失败原因分类
把这次的问题归类,其实就三种:
业务错误:比如溯源信息没透传,属于设计缺陷。这种问题只能在测试阶段发现,Demo不会暴露是因为Demo的数据量小、场景单一。
配置错误:比如ES的查询权限配置和代码里的硬编码不一致。这种问题在联调时最容易出,因为每个人的环境不一样。
环境错误:比如日志编码、依赖版本、网络限制。这种问题往往在"在我机器上是好的"这句台词里诞生。
区分这三类的办法很简单:改代码能不能解决。业务错误需要改逻辑,配置错误需要改配置,环境错误需要改部署。分不清的话,就会在错误的方向上浪费时间。
适用边界
LangChain适合什么样的项目?我的判断是:
- 工具数量中等(5-20个),Chain逻辑清晰,不需要复杂的状态机
- 模型调用频繁,需要统一管理Prompt和缓存
- 团队有人愿意维护,不是交接就走人的项目
什么情况下不建议用?
- 只需要简单调用模型,一个HTTP请求就够,别上LangChain
- 需要复杂的多Agent协作,这时候
LangGraph比Chain更合适 - 团队没有能力维护,Demo级别的代码一旦接进生产,维护成本会指数级上升
另外,权限和日志这两个问题,不管用不用LangChain,都绕不开。它只是让这些问题更容易出现,而不是更难出现。
总结
LangChain确实降低了构建AI应用的门槛,但它也给项目引入了新的复杂性——尤其是权限、日志、错误处理这些"看不见的部分"。Demo能跑通只是第一步,真正的考验是:
1. 每个工具都要假设会被滥用,加权限校验
2. 日志要分层,区分正常流程、警告、错误,且要结构化
3. 数据要透传,不要在中途丢掉元数据
4. 责任要明确,模型的问题是Prompt问题,工具的问题是代码问题,权限的问题是配置问题
这些不是LangChain教你的,是你自己在踩坑之后学会的。但早点知道,总比上线第一天崩了再查要好。
资料展示
下面是我整理的AI大模型学习资料和工具包预览,适合收藏后按主题逐步学习。



如果你想看完整资料目录,可以在评论区留言「资料」;也欢迎告诉我你更关注AI大模型里的哪类内容。


2152

被折叠的 条评论
为什么被折叠?



