
1. 为什么现在还要聊 LangChain1.1 大模型应用开发到底在解决什么问题很多人第一次接触大模型都是从聊天窗口开始的。问一句答一句感觉挺新鲜但真到要把它塞进业务系统里问题就来了模型不知道你公司的内部文档记不住上一轮对话的上下文更没法自己去查数据库、调接口、跑脚本。这时候就需要一个“胶水层”把大模型和外部世界连起来LangChain 就是干这个的。我自己的理解是LangChain 本质上是一套大模型应用开发的脚手架。它不生产模型也不训练模型它做的是把“模型调用、提示词管理、上下文记忆、工具调用、流程编排”这些重复劳动封装成标准组件。你可以把它想象成做菜时的料理台食材模型是买来的但切菜、配料、下锅的顺序它帮你安排好了。适合看这篇内容的人大概分三类。第一类是刚学完 Python、想找个方向练手的开发者LangChain 的入门门槛相对友好第二类是做后端或数据工程、被要求“接一下大模型”的工程师需要快速出活第三类是对 AI 应用感兴趣的产品或运营同学想搞明白这些应用到底是怎么搭出来的。不管哪一类只要你能写基本的 Python后面这些内容都能跟着走一遍。1.2 LangChain 和 LangGraph 到底啥关系这是最近被问得最多的问题之一。简单说LangChain 是基础组件库LangGraph 是在它之上做有状态、多步骤流程编排的框架。LangChain 里的 Chain 更像一条直线输入进去经过几步处理输出出来。但真实业务往往不是直线会有分支、循环、人工介入、失败重试这时候用 LangGraph 会更顺手。打个比方LangChain 像一套乐高积木LangGraph 像是给你一张可以画流程图的图纸让你把积木按条件拼成会拐弯的结构。两者不是替代关系LangGraph 的很多底层能力还是复用 LangChain 的。所以我的建议是先把 LangChain 的核心概念吃透再去碰 LangGraph不然容易一头雾水。至于“LangChain 过时了吗”这种说法我的看法是单纯用 Chain 串一串提示词确实有点不够看了但 LangChain 生态里的文档加载器、向量库集成、工具封装这些依然是目前最省事的选择。工具会迭代但“把模型和外部能力接起来”这个需求不会消失。2. 环境搭建与第一个可运行示例2.1 用 conda 还是 venv依赖怎么装才不打架环境这块我踩过坑必须单独说。LangChain 的包拆得很细langchain、langchain-core、langchain-community、各家模型的适配包是分开的版本对不上就会报一堆 ImportError。我的习惯是用 conda 建一个干净的虚拟环境Python 版本选 3.10 或 3.11太新或太旧都容易遇到轮子编译问题。conda create -n lc-demo python3.11 -y conda activate lc-demo pip install langchain langchain-core langchain-community如果你要用某家特定模型再单独装对应的适配包比如langchain-openai。这里有个经验不要一次性把所有包都装上用到哪个装哪个装完立刻pip freeze requirements.txt锁版本。我见过太多人环境跑通了过两周重装就崩就是因为没锁版本。提示国内网络环境下装包可能比较慢可以配置镜像源但注意不要使用任何来路不明的第三方源优先用官方或可信的镜像。2.2 一个最小可运行的调用示例先别急着上 RAG、Agent 这些复杂玩意第一步就是让模型能回你一句话。下面这段代码是通用结构把模型换成你实际用的那家即可。from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser prompt ChatPromptTemplate.from_messages([ (system, 你是一个简洁的助手回答不超过三句话。), (human, {question}) ]) # model 这里替换成你实际使用的对话模型实例 chain prompt | model | StrOutputParser() result chain.invoke({question: 用一句话解释什么是向量数据库}) print(result)这段代码里有三个关键点值得说。第一ChatPromptTemplate把系统提示和用户输入分开管理比手拼字符串清晰得多。第二|这个管道符号是 LangChain 表达式语言LCEL的核心它把组件串成一条链数据从左往右流。第三StrOutputParser负责把模型返回的复杂对象转成纯字符串省得你自己去扒字段。实测下来这个最小示例跑通之后你对 LangChain 的感觉就建立起来了。后面所有复杂应用本质上都是在这条链上不断加东西。3. 核心组件逐个拆解3.1 Prompt、Model、Parser 三件套LangChain 里最基础的就是这三样。Prompt 负责组织输入Model 负责推理Parser 负责把输出变成程序能用的格式。很多人一上来就追求复杂其实把这三样玩熟已经能解决不少问题。Prompt 模板支持变量填充也支持少样本示例。比如你想让模型按固定格式输出可以在提示里塞几个“输入-输出”的例子这叫 few-shot。我一般会把提示词单独放在一个文件或常量里方便反复调不要散落在代码各处。Parser 这块除了字符串解析还有 JSON 解析、Pydantic 解析。如果你要模型返回结构化数据强烈建议用 Pydantic 解析器它会帮你做校验字段缺失或类型不对会直接报错比拿到一坨字符串再手动处理靠谱得多。组件作用常见坑Prompt组织输入、注入变量和示例变量名拼错运行时才报错Model调用大模型推理不同厂商参数名不统一Parser解析模型输出模型不按格式返回导致解析失败3.2 Memory 与上下文管理大模型本身是无状态的每次调用都是全新的。要让对话有“记忆”就得把历史消息带上。LangChain 提供了多种 Memory 组件早期有ConversationBufferMemory现在更推荐用RunnableWithMessageHistory这类新方式。这里有个关键取舍历史消息全带上token 消耗会越来越大迟早超上下文窗口。所以实际项目里我一般用“滑动窗口 摘要”的组合保留最近几轮原文更早的用模型压缩成一段摘要。这样既省 token又不至于完全失忆。注意Memory 不是越多越好。带太多无关历史反而会干扰模型对当前问题的判断实测中经常出现“答非所问”就是历史污染导致的。3.3 文档加载、切分与向量化做知识库问答绕不开 RAG检索增强生成。流程是加载文档 → 切分成小块 → 向量化 → 存进向量库 → 查询时检索相关块 → 拼进提示词给模型。切分这一步最容易被忽视但影响巨大。切太大检索出来的块包含太多无关信息切太小语义不完整。我的经验是中文文档按 300 到 500 字一块块之间留 50 字左右重叠避免把一句话从中间切断。LangChain 的RecursiveCharacterTextSplitter支持按段落、句子逐级切比硬切友好。向量库的选择上本地小规模测试用 Chroma 就够了部署简单。数据量上来了再考虑 Milvus、PGVector 这类。下面是一个本地知识库的典型组合思路from langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Chroma loader TextLoader(docs/manual.txt, encodingutf-8) docs loader.load() splitter RecursiveCharacterTextSplitter( chunk_size400, chunk_overlap50, separators[\n\n, \n, 。, , , , ] ) chunks splitter.split_documents(docs) # embeddings 替换成你实际使用的向量化模型 vectorstore Chroma.from_documents(chunks, embeddingembeddings, persist_directory./db) retriever vectorstore.as_retriever(search_kwargs{k: 4})separators里我把中文标点加进去了这是中文场景必须做的调整默认的分隔符对中文不友好容易切得乱七八糟。4. 从 Chain 到 Agent 的进阶路径4.1 LCEL 表达式语言怎么用才顺LCEL 是 LangChain 现在主推的编排方式核心就是|管道。它支持并行、分支、回退写法上很接近函数式编程。比如你想让两个检索器同时跑可以用RunnableParallel想加个兜底逻辑可以用with_fallbacks。我个人的使用心得是简单的线性流程用 LCEL 非常爽但一旦逻辑复杂到需要条件跳转和循环就该考虑 LangGraph 了。硬用 LCEL 去实现复杂分支代码会变得很难读维护成本陡增。4.2 Agent 与工具调用Agent 是 LangChain 里比较有意思的部分。它让模型自己决定“要不要调工具、调哪个工具、传什么参数”。比如你给它一个计算器工具和一个搜索工具问它“今天天气怎么样顺便算下 23 乘 47”它会先调搜索再调计算器。工具的定义很简单用tool装饰器包一个函数就行函数的 docstring 就是给模型看的说明所以 docstring 一定要写清楚这个工具是干嘛的、参数是什么。我见过很多人工具调不通最后发现是 docstring 写得太含糊模型根本不知道啥时候该用。from langchain_core.tools import tool tool def multiply(a: int, b: int) - int: 计算两个整数的乘积。当用户需要做乘法时使用。 return a * bAgent 的执行过程是“思考 → 行动 → 观察 → 再思考”的循环直到它认为可以给出最终答案。这个循环次数要设上限不然模型可能陷入死循环白白烧 token。4.3 Human in the loop 人工介入怎么做有些场景不能让 Agent 全自动跑比如涉及转账、删除数据这类敏感操作必须人工确认。LangGraph 对 human-in-the-loop 的支持比较完善可以在流程中间插入一个中断点等人工审批后再继续。实现思路是在关键节点前设置中断把当前状态保存下来人工检查后决定是继续、修改还是终止。这个能力在工业场景里特别重要因为完全放手的自动化在关键业务上没人敢用。5. 实战案例几个能直接抄的场景5.1 本地知识库问答的完整链路把前面几块拼起来就是一个能用的本地知识库。完整链路是用户提问 → 问题向量化 → 向量库检索 top-k 相关块 → 把相关块和问题拼进提示词 → 模型生成答案 → 返回并附上引用来源。这里有个提升效果的小技巧让模型在回答时标注引用了哪一段。这样用户能核对也方便你排查是检索错了还是模型编的。提示词里可以明确要求“如果检索内容里没有答案就直说不知道不要编造”。这句话能大幅降低幻觉。5.2 自动生成测试脚本的 Agent 思路热词里提到“读取测试用例自动生成 UI 自动化测试脚本”这个场景挺典型。思路是把测试用例文本喂给模型让它输出对应框架的脚本代码再用工具去校验语法、甚至试运行。关键难点在于模型生成的代码不一定能跑。所以流程里要加一步“语法校验”用对应语言的解析器检查一遍报错就把错误信息回喂给模型让它改循环几次。这其实就是 Agent 的自我修正能力。工具选型上浏览器自动化可以用 Playwright它的 API 比较清晰模型生成起来也相对稳定。5.3 工业智能体场景的注意事项工业场景对可靠性要求高我的建议是能用固定流程就别用 Agent。Agent 的灵活性是以不确定性为代价的。如果业务流程是确定的用 LangGraph 画一张明确的状态图每个节点做什么都写死只在真正需要判断的地方才让模型介入。这样既可控又便于排查问题。另外工业场景往往有数据隔离要求模型和向量库尽量本地化部署数据不出内网。这块在选型阶段就要考虑清楚别等上线了才发现合规过不去。6. 常见问题与避坑清单6.1 版本冲突与依赖问题速查LangChain 生态迭代快版本冲突是新手第一大坑。下面这张表是我整理的高频问题和处理方式。现象可能原因处理方式ImportError 找不到模块包拆分了装错包确认装的是 langchain-community 还是 langchain-core方法不存在版本过旧或过新锁版本查对应版本文档向量库连接失败依赖库缺失单独装向量库的客户端包模型调用报参数错适配包版本不匹配升级对应模型适配包我的习惯是新建项目第一件事就是建虚拟环境并锁版本这个动作能省掉后面 80% 的玄学问题。6.2 检索效果差的排查思路RAG 效果不好先别怪模型八成是检索环节的问题。排查顺序是先看切分是否合理再看向量化模型是否适合中文然后看 top-k 设得对不对最后才看提示词。有个实用技巧是把检索到的原文打印出来看。很多时候你会发现检索出来的块跟问题根本不相关那模型答不好就理所当然了。向量化模型对中文的支持差异很大选型时一定要用你自己的数据实测别只看榜单。6.3 成本与性能的平衡大模型调用是按 token 计费的Agent 多轮循环很容易把成本拉高。控制成本的手段有几个一是精简提示词去掉冗余描述二是控制历史长度三是给 Agent 设最大循环次数四是简单任务用小模型复杂任务才上大模型。性能上检索和模型调用是主要耗时点。向量库可以加缓存相同问题直接返回缓存结果。模型调用如果支持流式输出前端体验会好很多用户不用干等。7. 我踩过的坑和几条实在建议先说一个最容易被忽略的点提示词里的变量一定要做转义和长度限制。用户输入如果特别长或者包含特殊字符可能把提示词结构撑坏甚至引发注入问题。我一般会在拼进提示词前对用户输入做截断和清洗。第二个坑是过度依赖框架封装。LangChain 封装得很好用但出问题时如果你不了解底层到底发了什么请求排查会很痛苦。我的建议是关键环节用日志把实际发送的请求和收到的响应打出来心里有数。第三个是别一上来就追求全自动 Agent。我见过不少项目明明是个固定流程非要套个 Agent结果又慢又不稳。先把确定的部分用固定流程做扎实把不确定的部分留给模型这才是务实的做法。最后分享一个我常用的调试习惯把每次调用的输入、输出、耗时、token 消耗都记到日志里。跑一段时间回头看哪些提示词效率低、哪些环节最烧钱一目了然。这个习惯帮我省下的成本比任何优化技巧都多。