跳转到内容

LangChain 入门教程:Python AI 应用开发五大组件

代码框架的连接之美

学完这一节,你能:

  • 说清楚为什么需要 LangChain——用“做菜用不用切丝器”的比方讲给家里人听
  • 拼出第一条 LCEL 链(prompt | model),理解“接水管”是怎么把组件连起来的
  • 加记忆让模型记得三句话之前你说过啥(模块 1 那个“无状态”的老毛病,这节给它治)

LangChain = AI 应用的“厨房工具套装”。

回想模块 1,你用 10 行代码调通 API——好比你想吃土豆丝,直接拿菜刀一根一根切。能切吗?能。但宴客要做 50 道菜呢?手会废掉。

聪明的厨房里有工具套装:切丝器、压蒜器、削皮刀……每个工具只干一件事,但干得又快又稳。你只要把食材从一个工具递给下一个,一道菜就出来了。

LangChain 就是 AI 应用的这套工具:

  • 模块 1 裸写 chat() = 手拿菜刀切土豆(项目小没事,项目大了手忙脚乱)
  • 模块 2 用 Coze/Dify = 去饭店点菜(现成,但你不能改厨房)
  • LangChain = 自己开厨房:工具是别人造好的标准件,想怎么拼就怎么拼

关键在最后一句:工具是标准件,接口统一。今天用智谱的“切丝器”,明天换成 DeepSeek 的,接口一样、改个名字就行,业务代码几乎不动。

行,但项目稍微大一点就乱。三个真实场景,裸写都头疼:

  • 换模型:老板说“智谱太贵了换 DeepSeek”。裸写你得满代码搜 glm-4-flash 改;框架?改一个变量。
  • 加记忆:你想让机器人记得用户名字。裸写你得自己维护 history 列表、自己拼 messages(模块 1 干过了,累);框架给你一个现成的“会员卡”,挂上去就行。
  • 多组件协作:让模型先查文档、再回答、再翻译。裸写三段调用三段拼接;框架一根“管子”串起来。

一句话:框架不是“功能更强”,而是“约定更整齐”。大家都按同一套接口写,你换零件不疼、别人接手就懂。这是工程化的第一课。

2. 五大组件:开一家 AI 小店的类比

Section titled “2. 五大组件:开一家 AI 小店的类比”

LangChain 有五大核心组件。别记表格,想象你要开一家 AI 小餐馆:

组件 小店里的角色 没有它会怎样
Model(模型) 厨师——真正做菜的人 没厨师店开不了,核心中的核心
Prompt(提示模板) 菜单——顾客点啥、厨师按啥规矩做 没菜单,顾客每次都得现编怎么点
Memory(记忆) 会员卡——记住老顾客叫啥、上次点了啥 没会员卡,每次去都被问“您贵姓?”
Tool(工具) 外卖电话/计算器——能联系外部、能算账 没工具,只能靠嘴说,算账算错、查不了实时信息
Retriever(检索器) 菜谱本——祖传秘方小本子,做菜前翻一翻 没菜谱本,模型凭脑子做菜容易胡说八道

本节只动用前三个(厨师 + 菜单 + 会员卡)。Tool 和 Retriever 后面专门讲,现在只要知道“开店还有这两样宝贝”。

3. LCEL:把组件像“接水管”一样连起来

Section titled “3. LCEL:把组件像“接水管”一样连起来”

LCEL(LangChain Expression Language,你不用记全称)核心就一个符号:管道符 |

不懂“管道符”?把它想成接水管。厨房里:水管 A 出水 → 一根管子 | → 水管 B 过滤 → 又一根 | → 水龙头出水。水从一头进,顺着管子一路流到另一头。

LangChain 里也一样:

chain = prompt | model

读作:“把 prompt 的输出,接到 model 的输入上”prompt 把顾客的话加工成“标准订单”,| 把订单顺水推到 model 那里,model 炒完递回来。一根管子,一气呵成。

比裸写好在哪?每个组件都是标准水管,接口统一:.invoke(...) 进,结果出。想中间加个“翻译组件”?直接 prompt | translator | model,管子接长一点,原代码不动。

🛠️ 动手实操(分 4 小步,逐步叠加)

Section titled “🛠️ 动手实操(分 4 小步,逐步叠加)”

我们一上来 import 一堆。先 1 个组件,再加 1 个——每一步都能跑,每一步都看得见进步。

Step 1:装依赖 + 只调一个 Model(请个厨师)

Section titled “Step 1:装依赖 + 只调一个 Model(请个厨师)”
Terminal window
pip install langchain langchain-openai langchain-community

新建 langchain_step1.py:

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI # "请厨师"的工具
load_dotenv()
# 这就是厨师本人(模块1用过的智谱 glm-4-flash)
model = ChatOpenAI(
model="glm-4-flash",
api_key=os.getenv("GLM_API_KEY"), # 你的密码,从 .env 读
base_url="https://open.bigmodel.cn/api/paas/v4/" # 智谱的门牌号
)
# 直接让厨师回答一句话
print(model.invoke("用一句话告诉我:什么是 LangChain?").content)

python langchain_step1.py,看到一句话回答。这一步和模块 1 没本质区别,只是换了套工具请厨师。

Step 2:加 Prompt 模板(给厨师一份菜单)

Section titled “Step 2:加 Prompt 模板(给厨师一份菜单)”

光有厨师不行,每次问题都得自己拼“人设 + 问题”。做个菜单模板,以后填空就行。在 Step 1 代码基础上加:

from langchain_core.prompts import ChatPromptTemplate # "做菜单"的工具
# 一份菜单:固定人设 + 一个"顾客问题"的空位 {question}
prompt = ChatPromptTemplate.from_messages([
("system", "你是 FDE 学习助手,用一句话、像跟老奶奶讲话那样回答"),
("human", "{question}") # {question} 是空位,等会儿填
])
# 填空看看菜单长啥样(还没请厨师)
print(prompt.invoke({"question": "什么是 API?"}))

这一步还没调用模型,只是“把菜单准备好”。

Step 3:用 LCEL 把 Prompt 和 Model 接起来(接水管!)

Section titled “Step 3:用 LCEL 把 Prompt 和 Model 接起来(接水管!)”

现在请主角——管道符 |——把“菜单”和“厨师”接成一根管子:

# 👇 重点这一行:菜单 | 厨师。订单从菜单流到厨师
chain = prompt | model
# 整根管子一气呵成,只管往里灌问题
print(chain.invoke({"question": "什么是 API?"}).content)

看懂 prompt | model 了吗?它就是“接水管”。以后想加翻译?prompt | translator | model。想加输出格式化?后面再接一段。这是 LangChain 全部魔法的核心

Step 4:加 Memory(发张会员卡,记得老顾客)

Section titled “Step 4:加 Memory(发张会员卡,记得老顾客)”

模块 1 说过模型“无状态”——三句之前你说啥它都忘。现在给它治病:挂个记忆组件。新文件 langchain_step4.py:

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
load_dotenv()
model = ChatOpenAI(
model="glm-4-flash", api_key=os.getenv("GLM_API_KEY"),
base_url="https://open.bigmodel.cn/api/paas/v4/"
)
# 会员卡:在内存里存对话(生产环境换成 Redis/数据库)
history = ChatMessageHistory()
# 菜单多留个空位 {history}:专门放"以前聊过啥"
prompt = ChatPromptTemplate.from_messages([
("system", "你是 FDE 学习助手,简洁、友好"),
MessagesPlaceholder(variable_name="history"), # ← 历史对话塞这里
("human", "{input}")
])
chain = prompt | model # 还是那根管子
# 给管子"挂上"会员卡:每次对话自动读写 history
chain_with_memory = RunnableWithMessageHistory(
chain, lambda _: history, # 用哪张会员卡(这里固定一张)
input_messages_key="input", # 用户输入对应 {input}
history_messages_key="history" # 历史记录对应 {history}
)
# 同一会话用同一个 session_id,这样才知道是同一个顾客
config = {"configurable": {"session_id": "user1"}}
print(chain_with_memory.invoke({"input": "我叫小明"}, config).content)
print(chain_with_memory.invoke({"input": "我叫什么?"}, config).content) # 应答出"小明"

验收:第二轮答出“小明”,说明会员卡生效——模型“记得”你是谁了。把 session_id 换成 "user2" 再试,它会“装作不认识你”,因为换了张卡。

报错 / 现象 大白话原因 怎么解决
NotFoundError / 模型不认识 base_url 没填或写错 国产模型必须base_url="https://open.bigmodel.cn/api/paas/v4/"
第二轮不记得第一轮的话 session_id 不一致,或没传 config 每次调用都传同一个 config,session_id 别变
ImportError: ... MessagesPlaceholder langchain 版本太旧 pip install -U langchain langchain-core langchain-community
LCEL 写 prompt + model 报错 用错符号,不是 +| 永远是管道符 |,想象“接水管”
AuthenticationError: 401 API Key 没填或多了空格 检查 .envGLM_API_KEY= 后面无空格
1. 用"开小店"的类比,说清楚 Memory 解决什么问题?没它会怎样?

Memory 就像店里的会员卡,记录老顾客上次聊过啥、叫什么。没它,模型因为“无状态”——每次调用都像第一次见面——你三句之前说的名字它就忘了,得每次重新自我介绍。FDE 做客服机器人时 Memory 是必备组件,否则体验极差。

2. `chain = prompt | model` 里的 `|` 是什么意思?为什么不用 `+` 或 `,`?

| 是 LCEL 的管道符,读作“把左边的输出接到右边的输入”,就像厨房接水管——左边管子流出的水自动流进右边管子。不用 +, 因为这不是“加法”或“并列”,而是有方向的数据流:prompt 加工出的“订单”必须顺着管子流到 model 才能被处理。统一用 | 还有个好处:想加组件就再接一段 | new_component,原代码不动。

🚀 实战小项目:三家分店的会员卡

Section titled “🚀 实战小项目:三家分店的会员卡”

把 Step 4 改成同时服务 3 个用户(user1/2/3),每人有自己的记忆。提示:把 lambda _: history 改成“根据 session_id 返回不同的 ChatMessageHistory”,用一个字典 {"user1": ChatMessageHistory(), "user2": ...} 存。

验收:

  • user1 说“我叫小明”,user2 说“我叫小红”,互不串扰
  • 问 user1“我叫什么?“答”小明“;问 user2 同样问题答“小红”
  • 你能直观感受到:session_id 就是“哪张会员卡”的钥匙

做完你就懂了 ChatGPT“多用户会话隔离”的底层逻辑——每个会话窗口一张独立的记忆卡。

3 句话回顾:

  1. LangChain = AI 应用的厨房工具套装,标准件、接口统一,换模型/加组件都不疼
  2. 五大组件用“开小店”记:Model 厨师、Prompt 菜单、Memory 会员卡、Tool 外卖电话、Retriever 菜谱本
  3. LCEL 用 | 接水管:prompt | model,想加啥再接一段,业务代码不动

下一节:当流程需要“循环、分支、人工审批”——比如模型回答完让人审核、不过关打回重写——LangChain 这根直管子就不够用了。那时换上 LangGraph(带岔路的管子网络)。

  • LangChain 官方教程 — 跟着官方 5 个 tutorial 跑一遍,每个都是可运行 notebook(免费)
  • LangChain Academy — 官方免费课程,从基础到 LangGraph(免费、英文)
  • 把本节的 chat() 函数改成“带记忆版本”,测试连续对话

← 上一节:Dify 平台 | 下一节:LangGraph 工作流