LangChain 核心组件实战:Chains、输出解析器、Memory 深度解析

2 阅读7分钟

LangChain 核心组件实战:Chains、输出解析器、Memory 深度解析

前言

LangChain 作为大应用开发最主流的框架,把大模型能力封装成模块化组件,让开发者不用重复处理提示词拼接、会话记忆、流程串联等底层逻辑。想要基于大模型快速搭建业务应用,有三个核心组件是必须掌握的:Chains(链)、返回结果解析器(Output Parser)、Memory(记忆模块)。本文就围绕这三大核心模块,讲解各自作用、使用场景、开发要点,同时补充极简可运行代码示例,帮助快速理解 LangChain 应用的底层构建逻辑。

前置依赖安装

pip install langchain langchain-openai python-dotenv

一、Chains 链:串联大模型的业务流程

什么是 Chains

Chains 是 LangChain 里的流程编排核心组件。简单理解就是把大模型、提示词模板、工具、数据库等多个单元串联起来,组成一条完整可执行的业务链路。

大模型本身只是输入文本输出文本,没有业务逻辑能力。Chain 负责定义执行顺序:输入经过 PromptTemplate 组装,传给 LLM,拿到结果后可以再交给其他组件继续处理,实现复杂任务流水线。

常见分类与使用场景

  1. LLMChain:最基础的链,提示词模板 + 大模型组合,完成单次问答、文本生成。适合简单文案生成、摘要、翻译场景。
  2. SequentialChain 顺序链:多条 Chain 按顺序串行执行,上一条链输出作为下一条链输入。适合多步骤任务,例如先做文本摘要,再基于摘要生成标签,最后根据标签生成营销文案。
  3. RouterChain 路由链:根据用户输入内容,动态路由分发到不同的处理链。比如客服系统,问题是查订单就走订单链,问题是咨询产品就走产品问答链。
  4. 工具链(ToolChain) :结合 Agent 调用外部工具,完成联网查询、数据库查询、代码执行等能力。

开发提示:不要所有逻辑都写在一条 Chain 里面,尽量拆分为细粒度 Chain,便于调试、复用和维护。

代码示例:基础 LLMChain + SequentialChain 顺序链

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import LLMChain, SequentialChain

load_dotenv()
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# 链1:对文章做摘要
prompt1 = PromptTemplate(
    input_variables=["article"],
    template="请对下面的文章做简短摘要:\n{article}"
)
chain_1 = LLMChain(llm=llm, prompt=prompt1, output_key="summary")

# 链2:基于摘要生成关键词
prompt2 = PromptTemplate(
    input_variables=["summary"],
    template="从下面摘要提取3个关键词,用逗号分割:\n{summary}"
)
chain_2 = LLMChain(llm=llm, prompt=prompt2, output_key="keywords")

# 串行执行链路
seq_chain = SequentialChain(
    chains=[chain_1, chain_2],
    input_variables=["article"],
    output_variables=["summary", "keywords"]
)

result = seq_chain.run(article="LangChain提供Chains、Memory、OutputParser组件,用来快速搭建大模型应用,降低LLM应用开发门槛。")
print(result)

二、返回结果解析器 OutputParser:标准化大模型输出

为什么需要结果解析器

大模型的输出是自由的自然语言文本,输出格式不可控。业务程序往往需要结构化数据,比如 JSON、列表、对象,直接解析大模型返回的自由文本很容易出错。

OutputParser(返回结果解析器)的作用:约束大模型输出格式,并且把大模型返回的字符串解析成程序可直接使用的结构化对象。

它会做两件事:

  1. 自动向提示词追加格式要求,告诉大模型应该按什么格式输出;
  2. 将大模型返回的文本,解析成 Python 对象(字典、数组、Pydantic 实体类等)。

常用解析器

  1. JsonOutputParser:解析输出为 JSON 字典。业务接口调用、参数提取场景高频使用。
  2. PydanticOutputParser:基于 Pydantic 模型,定义字段类型、校验规则,输出强类型对象。适合对输出字段、数据类型有严格要求的业务。
  3. CommaSeparatedListOutputParser:把返回文本解析成列表,多用于标签提取、关键词抽取。

代码示例:PydanticOutputParser 强类型解析

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

load_dotenv()
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# 定义期望输出的数据结构
class ProductInfo(BaseModel):
    product_name: str = Field(description="商品名称")
    price: float = Field(description="商品价格")
    tags: list[str] = Field(description="商品标签数组")

parser = PydanticOutputParser(pydantic_object=ProductInfo)

prompt = PromptTemplate(
    template="提取商品信息。{format_instructions}\n商品描述:{desc}",
    input_variables=["desc"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

chain = prompt | llm | parser
output = chain.invoke({"desc": "这是一款无线蓝牙耳机,售价199元,适合运动、通勤使用。"})

print(type(output))
print(output.product_name, output.price, output.tags)
# 直接拿到Python对象,可以点访问属性

开发注意点

  • 大模型偶尔会输出额外解释文本,会导致解析报错;可以搭配错误重试、格式修复解析器增强稳定性。
  • 解析器要和 PromptTemplate 配合,将解析器的格式说明注入提示词,不能只靠后处理强行切割字符串。

三、Memory 记忆模块:给大模型带上会话上下文

Memory 解决什么问题

原生大模型 API 每次请求都是独立的,本身不会保存历史对话。每一轮调用,模型不知道上一轮聊过什么。

Memory 组件就是 LangChain 提供的会话记忆管理模块,负责存储、读取历史对话上下文,在每次请求的时候把历史消息拼接到 Prompt,实现多轮连续对话。

主流 Memory 类型

  1. ConversationBufferMemory:完整保存全部对话历史,直接全部塞入提示词。优点简单;缺点对话轮次多的时候 token 消耗暴涨,容易触发上下文长度超限。适合短会话场景。
  2. ConversationSummaryMemory:不会存储完整原文,会调用 LLM 把历史对话压缩成摘要保存。大幅节约 token,适合长会话;缺点会消耗额外大模型调用,摘要会丢失部分细节。
  3. ConversationBufferWindowMemory:滑动窗口记忆,只保留最近 N 轮对话,丢弃更早记录。可控 token 数量,但是旧对话信息会丢失。
  4. VectorStoreMemory:把对话向量化存入向量库,需要的时候检索相关历史片段。适合超长历史,只召回相关记忆片段。

代码示例:Memory 结合 Chain 实现多轮对话

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory

load_dotenv()
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

memory = ConversationBufferMemory(memory_key="chat_history")

prompt = PromptTemplate(
    input_variables=["chat_history", "human_input"],
    template="下面是对话历史:\n{chat_history}\n用户:{human_input}\nAI:"
)

conversation_chain = LLMChain(
    llm=llm,
    prompt=prompt,
    memory=memory,
    verbose=False
)

# 多轮对话调用
print(conversation_chain.run(human_input="我叫张三"))
print(conversation_chain.run(human_input="我叫什么名字?"))
# memory可以查看全部历史
print(memory.load_memory_variables({}))

实践建议

  • 在线对话应用优先评估 token 成本,不要无脑使用 BufferMemory;
  • Memory 可以和 Chain 结合,自动把历史上下文注入链的输入,不需要手动拼接历史;
  • 生产环境持久化记忆不要只放在内存,需要对接数据库存储会话记录。

四、三者如何协同工作

一个典型 LangChain 对话应用执行流程:

  1. Memory 读取当前会话历史,把历史对话取出;
  2. PromptTemplate 拼接用户问题 + 历史记忆,组装完整提示;
  3. 交给 Chain 编排执行逻辑,调用大模型获取原始输出文本;
  4. OutputParser 对模型返回结果做结构化解析,得到程序可用数据;
  5. 将本轮用户提问与模型回答写入 Memory,供下一轮会话使用。

Chain 负责流程调度,Memory 负责会话上下文,OutputParser 负责输出标准化,三者互相配合,构成 LangChain 业务应用的基础骨架。

整合极简示例(Chain + Memory + OutputParser)

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain.memory import ConversationBufferMemory
from pydantic import BaseModel, Field

load_dotenv()
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

class ChatResult(BaseModel):
    reply: str = Field(description="AI回答内容")
    emotion: str = Field(description="用户当前情绪:开心/普通/疑惑")

parser = PydanticOutputParser(pydantic_object=ChatResult)
memory = ConversationBufferMemory(memory_key="history")

prompt = PromptTemplate(
    template="对话历史:{history}\n用户问题:{query}\n{format_instructions}",
    input_variables=["history", "query"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

chain = prompt | llm | parser

# 模拟一轮会话
history = memory.load_memory_variables({})["history"]
resp = chain.invoke({"history": history, "query":"今天好郁闷"})
print(f"回答:{resp.reply},情绪:{resp.emotion}")

# 存入记忆
memory.save_context({"input":"今天好郁闷"}, {"output":resp.reply})

总结

  1. Chains:流程编排,把零散组件组装成任务流水线,解决 “任务怎么做”;
  2. OutputParser 输出解析器:约束、解析模型输出,把自由文本转为结构化数据,解决 “输出格式乱”;
  3. Memory 记忆组件:管理会话上下文,实现多轮对话,解决 “模型记不住历史”。

理解这三个核心组件,才算真正入门 LangChain 开发。后续开发 Agent、知识库问答等复杂应用,都是在这三者基础之上扩展更多能力。