资讯详情

LangChain实战入门:从核心概念到带记忆对话应用

📅 2026/10/23 10:47:39 | 华诺云谱 👁 阅读
LangChain实战入门:从核心概念到带记忆对话应用
过去两年里大模型应用开发从一个听起来很前沿的技术话题迅速变成了很多团队真正开工落地的事情。我也算是最早一批用 LangChain 做实际项目的开发者从最初的简单封装到后来的多智能体协作、知识库问答一路下来踩坑不少但收获更多。坦白说LangChain 并不是一个不学不行的框架但如果你想用大模型做正经的业务系统而不是停留在调接口、玩 Demo 的阶段那它会帮你省掉大量重复劳动。这篇文章是 LangChain 系列的第一篇我会先把框架解决的核心问题、核心概念和最小 Demo 讲清楚然后带你手写一个带记忆的对话应用最后把新手最容易翻车的几个地方整理出来。适合刚接触大模型开发、或者已经会调 API 但想系统搭建应用层的人阅读。1. 为什么大模型应用开发需要 LangChain 这类框架先说一下我的经历。最早接触大模型应用时我做的第一件事就是直接拿 HTTP 请求去调大模型服务的接口把用户问题拼进 Prompt再把返回内容处理后丢给前端。前两个接口写起来很爽但等到需求变复杂事情就不对了。1.1 只靠裸调 API代码会越来越不可控裸掉 API 的问题不在调通这一步而在维护这一步。第一多轮对话的状态管理非常麻烦。每次都要手动把历史消息拼好再一起发给模型。用户多问两句消息记录越来越长拼接逻辑要处理转义、截断、去重代码越写越脏。第二Prompt 复用困难。不同场景要用不同的系统提示词我最初的做法是写一堆字符串拼接函数有的地方用 join有的地方用 f-string改一个词就要全局搜索。等到提示词版本多起来根本分不清哪段逻辑对应哪个版本的 pPrompt调试效率极低。第三换模型服务商等于重构。模型服务商各有各的接口风格。最开始我用了 A 家后来因为成本和效果转向 B 家的兼容接口结果不只是把 URL 换掉那么简单响应结构不同、消息格式不同、流式输出的字段不同几乎所有解析逻辑都要重写。还有更复杂的场景比如让大模型自己决定下一步调哪个工具。只靠裸调的话你得自己实现一套推理-行动-观察循环自己解析模型的输出自己维护工具列表。这套东西写一次可以但每个项目都从头写一遍显然是在重复造轮子。1.2 LangChain 的核心设计理念一切皆组件LangChain 想解决的就是上面这些与应用层强相关、但每个项目都要重写一遍的重复劳动。它的核心思路可以概括为四个字抽象与编排。抽象指的是把大模型调用、提示词管理、输出解析、记忆存储、工具调用这些动作都封装成有标准接口的组件。你在代码里不再关心这个厂商的消息格式长什么样只需要操作统一的输入输出结构。编排指的是把这些组件像流水线一样串起来形成一条条链。比如一个典型的问答流程是接收用户输入 → 组装 Prompt → 调模型 → 解析结果 → 存记忆。在 LangChain 里这几步可以非常清楚地串成一条可读性很强的链后续要增加一个先检索资料再回答的环节也只是往链里多插一个组件。很多人批评 LangChain 太抽象、太重这点我不否认。但对刚上手的人来说抽象反而是一张地图你先理解它把整个大模型应用拆成了哪几个零件再回头去看要做的事心里就有数了。框架的具体 API 会变但模型、提示词、链、记忆、代理这套拆解思路是稳定的这也是我想在这个系列先讲清楚概念的根本原因。2. 核心概念拆解先打地基再谈实现LangChain 官方把框架分成若干个模块但对新手来说真正要理解的就五个Model、Prompt、Chain、Memory、Agent。后面的所有高级功能基本都是从这五个词演化出来的。2.1 Model 层把各家模型接口统一起来Model 层解决的是怎么跟大模型对话的问题。LangChain 把模型接口统一成了三种类型LLM纯文本进、纯文本出适合早期那种填空式模型。ChatModel按对话消息处理输入是消息列表输出也带角色信息。现在主流模型基本都是这种。EmbeddingModel把文本转成向量用于检索和相似度计算在知识库问答里是主角。这里面最实用的设计是不管底层是哪家服务商ChatModel 的调用方式几乎一样。你只需要在初始化时指定模型名、API Key、接口地址后面的 invoke 方法、消息对象、输出解析方式都是统一的。这个统一接口的价值是真正做过项目的人才能体会到的。我实际维护过一个问答系统因为模型厂商接口调整需要整体切换服务。在裸调方案里这是个大工程但切到 LangChain 之后改动的只有初始化那一两行配置业务代码几乎没动。2.2 Prompt 模板提示词也要工程化Prompt 是决定大模型输出质量的关键但它太容易被写成魔法字符串了。LangChain 里的 PromptTemplate 就是给提示词做工程化管理的工具。你可以把提示词里会变的部分抽成变量固定部分写成模板。比如from langchain.prompts import PromptTemplate template 你是一位{role}。 请用简洁、准确的语言回答用户的问题。 用户问题{question} prompt PromptTemplate.from_template(template)之后要生成不同角色的回答不用再复制粘贴一堆字符串只要调用prompt.format(rolePython工程师, question如何理解装饰器)就行。PromptTemplate 还有几个实用的子类比如聊天消息模板 ChatPromptTemplate可以把系统消息、用户消息分别组合起来。我以前觉得这玩意儿可有可无直到有一次系统提示词加了 200 行才发现没有模板管理根本没法维护。提示词的版本、变量、默认值、检验逻辑都应该有明确归属。2.3 Chain 链让单次调用变成业务流程Chain 是 LangChain 最标志性的概念也是组合思想的直接体现。一条链就是把多个组件串成一个完整流程。最简单的链是 LLMChain它的内部逻辑就是接收输入 → 格式化 Prompt → 传给模型 → 返回结果。但真正强大的是顺序链和路由链。顺序链适合前一步输出是后一步输入的场景。举个例子你要写一个产品文案生成器第一步让大模型生成产品卖点第二步再让大模型把卖点扩写成推广文案。用顺序链可以很直观地描述这个两步流程中间不需要你手动搬运数据。路由链则适合根据问题类型选择不同处理路径的场景。比如用户输入一句今天天气怎么样系统可以直接查到对应知识库返回如果用户输入的是闲聊则走通用对话链路。LangChain 里可以用路由链对输入先做一次判断再决定后续走哪条分支。我个人的建议是链条别设计得太长。一次流程超过五六个节点排查问题的难度会指数级上升。先保证每个节点可靠再去拼接更复杂的链。2.4 Memory对话上下文不能只靠变量硬塞用过 ChatGPT 的人都知道多轮对话很依赖上下文。但大模型接口本身是无状态的它不记得你上一轮说了什么。每个请求都是独立的要让对话有记忆就得自己把历史消息传给模型。LangChain 的 Memory 模块就是干这个的。最基础的是 ConversationBufferMemory它会缓存整段对话历史在每次请求时拼进 Prompt。此外还有滑动窗口记忆、摘要记忆、向量记忆等几种形式。用记忆组件最大的好处是你不用自己写历史消息拼接器。它会把历史包装成标准消息格式配合链的使用几行代码就能实现一个多轮对话机器人。但记忆也是双刃剑记忆内容越长单次请求消耗的 token 就越多响应速度也会变慢。我自己经常遇到的情况是对话到十几轮之后模型开始忘记前面的关键设定。这时候光靠大记忆并不能解决根本问题你得考虑滑动窗口、摘要压缩甚至引入外部数据库做长期记忆。这个话题后面我会专门写一篇。2.5 Agent让大模型学会使用工具Agent 是大模型应用里最有想象力的部分。普通链是固定流程模型只是执行者Agent 则是模型自己决定下一步做什么。最常见的 Agent 工作模式是 ReAct。模型先观察当前环境然后思考要不要调用某个工具比如搜索、计算器、数据库查询接着产生行动系统把工具返回的结果再交给模型如此循环直到得到最终答案。比如用户问北京和上海之间的距离大概多少模型可以决定调用地图工具拿数据再结合计算结果回答。整个过程看起来就像是模型自己在使用工具。LangChain 里做 Agent 需要三样东西一个负责决策的模型一组工具一个执行器。工具可以是自定义函数也可以是框架内置的网络搜索、文档读取、代码解释器等。在项目里最常见的做法是把公司内部 API 封装成工具让 Agent 根据用户意图去调用。但我要提醒一句Agent 不是越多越好。模型自己决策的环节越多出错概率越高。如果你的业务场景是固定流程用 Chain 就够了只有当你实在无法预判用户会触发哪条路径时再考虑 Agent。3. 环境准备与第一个最小 Demo概念讲完接下来动手。你先不用关心特别复杂的工程结构先把环境搭好跑通最简单的链路。3.1 安装与工程结构LangChain 的安装比前几年复杂了因为它把很多模型服务商的适配拆成了独立包。以我常用的 Python 环境为例通常要装这么几个pip install langchain pip install langchain-openai pip install langchain-community如果要做文档加载、向量库、网页搜索之类的功能后面还会加别的包。第一次接触的话别一口气全装用到一个装一个。因为版本之间依赖关系比较敏感装多了容易出现包冲突。工程结构上我建议哪怕是 Demo 也按个小项目来组织方便后面扩展。我的一个习惯是my_langchain_demo/ .env main.py chains/ prompts/ utils/.env文件存放 API Key 和接口地址main.py放入口逻辑chains放自定义链prompts放提示词模板utils放公共方法。别小看这个习惯系列后面的文章会在这个基础上持续扩展。3.2 跑通第一个最小链路这里我以最常见的兼容大模型接口为例。你用哪家服务商都可以只要初始化时把模型名、API Key、接口地址换成你自己的就行。from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI # 第一步定义提示词模板 prompt PromptTemplate.from_template( 你是一位{role}。\n请回答用户问题{question} ) # 第二步初始化模型 model ChatOpenAI( model实际的模型名称, # 换成你在用的模型 api_key你的API Key, base_url你的接口地址, # 用默认服务可以省略 temperature0.7 ) # 第三步用管道符把模板和模型串成一条链 chain prompt | model # 第四步执行 response chain.invoke({ role: Python进阶开发者, question: 请解释什么是闭包 }) print(response.content)如果你安装的版本正常、密钥配置正确运行后就会看到模型输出的回答。这段代码只有十几行但已经完整覆盖了组装提示词 → 调用大模型 → 拿结果的过程。3.3 核心代码背后的设计思路说明代码里最值得注意的是prompt | model这个管道符写法。这是 LangChain 较新版本的主推写法官方叫 LangChain Expression Language简称 LCEL。LCEL 的核心思想是任何实现了 Runnable 接口的对象都可以用|连接起来。prompt是一个 Runnablemodel也是一个 Runnable两者连接后生成的 chain 同样是一个 Runnable。所有 Runnable 都有统一的 invoke / stream / batch 方法所以上层用法完全一致。用 LCEL 而不是传统的 LLMChain主要好处有三个代码自然流式输出。只要模型支持chain 直接调用.stream()就能把结果一点一点吐给前端而不是等全部生成完。这对聊天类应用几乎是刚需。可以轻松做并行和批处理。chain.batch([...])一次处理多条输入不需要自己写循环。调试更直观。每条链的中间结果都可以通过回调或者.debug打印出来定位哪一步出问题会清晰很多。我第一次上手 LCEL 时有点不习惯觉得管道符有点像函数式编程。但用过几个项目后就回不去了它把流程即代码这件事表达得非常清楚。4. 实操构建一个带记忆的对话问答 Demo现在我们把概念串起来做一个真正能跑的多轮对话机器人。这是系列第一篇的收尾项目也是后续所有复杂应用的地基一个带记忆的对话链。4.1 需求拆解与选型需求很简单用户提问机器人回答并且能记住前面聊了什么。比如用户先说我要学 Python下一轮问那我先学什么机器人应该能联想到前面的话题。这个需求虽然看着简单但拆解下来包含三个关键点模型会话、历史记忆、对话链组装。在选型上Model 用 ChatModel因为对话场景本身就是消息式的。Memory 我选择 ConversationBufferMemory这是最基础、最好理解的记忆方式不加修饰地记录全部历史。对话链用 LangChain 提供的 ConversationChain它会自动把记忆内容注入到每次请求的 Prompt 里。注意记忆组件不是把历史存放在模型那边而是在你的应用内存里维护一份记录每次请求前拼装到 Prompt 里。应用重启记忆就清空。如果需要持久化得接数据库这个后面再讲。4.2 逐步实现从模型到记忆再到对话链先创建一个配置文件把密钥和模型参数放进去。这里我直接读取环境变量方便后续部署import os from dotenv import load_dotenv load_dotenv() model_name os.getenv(MODEL_NAME) api_key os.getenv(API_KEY) base_url os.getenv(BASE_URL)接下来实现主逻辑。先把模型和记忆初始化再创建对话链from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain # 初始化模型 llm ChatOpenAI( modelmodel_name, api_keyapi_key, base_urlbase_url, temperature0.7 ) # 初始化记忆return_messagesTrue 表示按消息列表形式保存 memory ConversationBufferMemory(return_messagesTrue) # 创建对话链 conversation ConversationChain( llmllm, memorymemory, verboseTrue # 开启后会在控制台打印详细过程 ) # 命令行交互 while True: user_input input(你) if user_input in (退出, exit, quit): break response conversation.run(user_input) print(AI, response)这里最核心的一行是ConversationChain(llmllm, memorymemory)。它的内部逻辑是每次run调用时把memory里的历史记录取出来和当前用户输入一起格式化到默认提示词模板里然后把完整 Prompt 发给模型拿到回答后再把用户输入 模型输出追加进记忆里。这一切对使用者完全透明你只需要关心业务逻辑。return_messagesTrue这个参数新手经常忽略。如果设为默认的 False记忆会以纯文本拼接形式保存在简单场景也能用但遇到结构化的聊天消息或者后续要接更复杂的链就很容易出问题。我建议在一开始就养成用消息格式的好习惯。4.3 运行效果与调优细节项目跑起来后你可以连续问几个关联性问题比如你我正在学 Python AI很好Python 是一门非常适合入门的语言你想重点了解哪方面 你那我应该先学基础语法还是先学爬虫 AI建议先学基础语法因为爬虫会用到变量、循环、函数等知识……最后一句回答能引用前面的话题说明记忆已经生效。但我用下来有几处细节值得注意。第一verboseTrue开启后控制台会打印出链内部完整执行的的情况。它会展示拼进了哪些历史记忆、最终 Prompt 长什么样、模型返回了什么这对排查问题是利器。等调试完成记得把它关掉否则生产日志会变得很嘈杂。第二温度参数要按场景调。闲聊场景可以设高一点比如 0.8回答会更有创意。做客服或者知识问答我一般降到 0.2 甚至 0。温度越低输出越稳定越不容易瞎编。第三对话默认是无限存储的。从上面的实现来看聊了几个小时历史列表就会变得非常长。每次请求都要把全部历史发给模型有几轮后我明显感觉响应变慢了token 消耗也在上升。处理办法有两个一是改用滑动窗口记忆只保留最近若干轮二是用摘要记忆让模型定期把历史压缩成摘要再喂回去。后者实现稍复杂但效果更好。5. 常见问题排查与避坑经验这个主题放在第一篇是因为我见到的初学者问题相当有共性。提前把这些坑说出来你后面会省很多事。5.1 问题排查速查表常见问题可能原因解决方法提示ModuleNotFoundError组件包没装全按报错信息提示安装对应模块别一次性装全套API Key 报错密钥没挂到环境变量确认.env文件的加载函数路径与位置用print(os.getenv())验证model参数无效模型名与实际服务不匹配换成服务商文档里的准确的模型字符串请求超时或连接失败接口地址配置不对或服务商暂时不可用检查base_url确认 API Key 权限和账号状态中文乱码或格式不对输出解析层处理不当使用输出解析器或让模型按 JSON 格式返回后手动解析多轮对话答非所问记忆失效或 Prompt 太长检查记忆组件是否生效适当压缩历史重设系统提示词报错提示 LangChain 内部类废弃版本太新API 变了看官方变更日志把调用方式改成新写法反复出现包版本冲突依赖 Python 包互相不兼容建议新建虚拟环境安装固定版本组合不要追新这张表是浓缩版。多数问题本质上都不是 LangChain 的问题而是配置或环境问题。报错信息只要肯仔细读基本都能定位。5.2 我实测下来最容易忽略的三件事第一件版本意识。LangChain 迭代非常快不同版本之间的 API 差别很大。网上教程往往写了旧版写法照抄后在新版运行直接报错。我的经验是看教程时注意发布时间不确定就查官方文档对应版本项目里锁定依赖版本不要哪天升级环境后突然把代码跑挂。第二件别把密钥写进代码。见过太多人把 API Key 直接写在 Python 文件里然后往 Git 仓库一推密钥就泄露了。正确做法是用环境变量或者密钥管理服务。这一点我觉得怎么强调都不为过。第三件别盲目上 Agent。有些开发者一看到 Agent 觉得很酷把简单的问答也做成代理模式结果模型自己调用工具绕来绕去既慢又不稳定。我的原则是能用普通链解决的问题绝不升级到 Agent能用一个模型调用的任务绝不用两个。6. 后续系列内容预告这篇文章是大模型应用开发系列的开篇。到这里为止你已经把 LangChain 的概念、最小链路、对话记忆和常见的坑都过了一遍。后面的系列里我最想写的是这几个方向也是实际项目里真正高频使用的部分首先是大模型知识库问答也就是业界常说的检索增强生成。它解决的问题是让模型基于你自己的文档回答问题而不是靠它的记忆瞎编。里面会涉及文档加载、文本切分、向量化、向量存储、召回重排这些详细的技术环节。其次是 Agent 的深度实战。我会用一到两个完整的项目拆解让大模型自动调用工具的前因后果以及如何做好工具失败时的兜底。还有 LCEL 高级用法和可观测性。写出能上生产环境的链日志、流式输出、错误重试、性能监控一个都不能少。最后是记忆系统的完整方案。从短期滑动窗口到长期向量记忆再到用数据库存用户配置和偏好这正好接上今天这篇末尾没讲完的部分。按照我自己带项目的经验把这一系列跟下来的读者应该能独立完成一个中等复杂度的大模型应用而不是只会跑通教程示例。今天这篇只是开始真正的硬核内容还在后面。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑