LangChain 深入:链条、代理与记忆的高级用法

FreeGuideOnline 最新 2026-06-14

链条的进阶:从线性到动态控制

链条(Chain)是 LangChain 中最基础的执行单元。它把多个组件串联成一条流水线,让数据在模型、工具和解析器之间流动。初学者通常从 LLMChain 入门,但真正的威力藏在那些能按条件分叉、并行运行或多步推理的链条中。

自定义链条:封装你自己的业务逻辑

当内置链条无法满足需求时,你可以通过继承 Chain 基类来实现完全自定义的执行流程。自定义链条需要实现两个关键方法:

  • input_keys:声明链条需要哪些输入键。
  • _call:定义实际的执行逻辑。

下面的例子创建了一条“情感分析增强回答”链条:先将用户问题送入情感分类器,若情感为消极则追加安抚性前缀,再调用大模型生成答案。

from langchain.chains.base import Chain
from typing import Dict, List, Optional
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

class SentimentAwareChain(Chain):
    llm: OpenAI
    sentiment_prompt: PromptTemplate
    answer_prompt: PromptTemplate

    @property
    def input_keys(self) -> List[str]:
        return ["question"]

    @property
    def output_keys(self) -> List[str]:
        return ["response"]

    def _call(self, inputs: Dict[str, str]) -> Dict[str, str]:
        question = inputs["question"]
        # 情感分析阶段
        sentiment = self.llm(self.sentiment_prompt.format(question=question))
        # 根据情感选择回答模板
        if "negative" in sentiment.lower():
            prefix = "我理解你可能感到困扰。"
        else:
            prefix = ""
        full_prompt = prefix + self.answer_prompt.format(question=question)
        response = self.llm(full_prompt)
        return {"response": response}

路由链条:让模型自动选择执行路径

RouterChain 允许模型根据输入动态选择下游链条。这在构建“意图分发系统”时特别有用——用户一句话可能对应查询订单、咨询售后或闲聊,你希望系统自动路由到对应处理逻辑。

LangChain 提供了多种路由策略,包括基于 LLM 判断的 LLMRouterChain 和基于嵌入相似度的 EmbeddingRouterChain。下面展示 LLM 路由器的典型配置:

from langchain.chains.router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE

# 定义不同意图对应的提示词与链条
order_template = "你是订单助手。用户问题:{input}"
chat_template = "你是闲聊伙伴。用户说:{input}"

destinations = {
    "order": {
        "name": "订单查询",
        "description": "处理订单、物流相关问题",
        "prompt_template": order_template,
    },
    "chat": {
        "name": "日常聊天",
        "description": "处理问候、天气等闲聊",
        "prompt_template": chat_template,
    },
}

# 构建路由器链条
router_prompt = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=...)
router_chain = LLMRouterChain.from_llm(llm, router_prompt)

当用户输入“我的快递到哪了?”,路由器会将其解析为 order 意图,并将请求传递给对应的订单处理链条。

序列化与并行:组合多个链条

SequentialChain 让你将多个链条按顺序串联,前一个链条的输出会自动成为下一个的输入。当任务天然是流水线式时(例如:生成大纲 → 扩写段落 → 润色校对),这种模式非常高效。

对于相互独立的子任务,可以使用 SimpleChain 手动并行调用,再将结果汇总。使用 asyncio.gather 即可轻松实现并发,大幅降低响应延迟。

import asyncio

async def parallel_chains(question):
    summary_chain = load_summary_chain()
    translation_chain = load_translation_chain()
    # 并行运行
    summary_task = summary_chain.arun(question)
    translation_task = translation_chain.arun(question)
    summary, translation = await asyncio.gather(summary_task, translation_task)
    return {"summary": summary, "translation": translation}

高级代理:赋予模型行动能力

代理(Agent)是 LangChain 中真正让 LLM“行动”起来的组件。它不只会生成文本,还会规划步骤、选择工具、执行操作并观察结果,直到完成目标。深入理解代理的类型与自定义工具,可以让你构建出自主决策的应用。

代理的决策核心:ReAct 与 OpenAI Functions

最早的代理基于 ReAct(Reasoning + Acting)范式,模型交替生成“思考-行动-观察”链路。LangChain 的 ZERO_SHOT_REACT_DESCRIPTION 代理类型便是此模式的经典实现。它仅靠工具的描述就能零样本决定调用哪个工具。

OpenAI 函数调用模型(如 gpt-3.5-turbo-1106)则提供了更结构化的代理模式。通过 OPENAI_FUNCTIONS 代理类型,工具被转换为函数定义注入请求,模型直接返回 JSON 函数调用,彻底消除了解析错误。

from langchain.agents import initialize_agent, AgentType

# 使用 OpenAI Functions 代理
agent = initialize_agent(
    tools=[search_tool, calculator_tool],
    llm=chat_model,
    agent=AgentType.OPENAI_FUNCTIONS,
    verbose=True,
)

当问题为“2023年特斯拉的净利润除以4是多少?”,代理会先调用搜索工具得到净利润数值,再调用计算器工具进行除法,最终返回准确答案。

自定义工具:让代理接入任何 API

工具是代理的手和脚。LangChain 的 @tool 装饰器可以将任意 Python 函数快速封装为工具,只需要清晰的函数名和 docstring。

from langchain.agents import tool

@tool
def get_weather(city: str) -> str:
    """查询指定城市的实时天气。输入应为城市中文名称,如'北京'"""
    # 调用实际的天气 API
    weather_data = weather_api.call(city)
    return f"{city}当前气温{weather_data['temp']}℃,{weather_data['desc']}"

# 注册工具后,代理就能自动根据用户意图调用它

对于更复杂的输入,可以使用 Pydantic 模型定义参数模式,确保代理传递的数据完全符合 API 要求。

代理的陷阱与对策:中断、回退与安全

在实际应用中,代理容易陷入无限循环、工具调用失败或产生有害操作。LangChain 提供了多层防护:

  • max_iterations:限制最大推理步骤,防止无限循环。
  • handle_parsing_errors=True:当输出格式错误时自动重试。
  • early_stopping_method:在 generate 方法中设置停止策略,避免模型空转。
  • 为敏感工具添加人工审批回调,在真正执行前请求用户确认。
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=5,
    handle_parsing_errors=True,
    early_stopping_method="force",
    callbacks=[human_approval_callback],
)

记忆的深层设计:让对话持续而有上下文

记忆(Memory)是构建有状态对话应用的核心。LangChain 提供了多种记忆实现,从简单的缓冲区到跨会话的持久化存储,你可以根据场景选择合适的策略。

记忆的演变:从缓冲区到智能摘要

ConversationBufferMemory 忠实地保存全部对话历史,适合短对话,但长对话会迅速撑爆上下文窗口。ConversationBufferWindowMemory 通过滑动窗口只保留最近 K 轮对话,缓解了 token 消耗。

更优雅的方案是 ConversationSummaryMemory,它会在对话变长时自动调用 LLM 对历史进行摘要,只保留摘要信息。这对于深度对话、客服场景非常有效。

from langchain.memory import ConversationSummaryMemory, ConversationBufferWindowMemory

summary_memory = ConversationSummaryMemory(llm=llm, max_token_limit=200)
# 当对话积累超过一定长度,旧内容会被压缩为摘要

实体记忆:记住对话中提及的“人”与“事”

ConversationEntityMemory 会从对话流中提取实体(人物、地点、概念等),并为每个实体建立独立的知识卡片。在后续对话中,模型可以精确引用这些实体信息,而不需要全量历史。

例如,聊过“张三喜欢喝美式咖啡”后,当用户说“给上次那个人点他常喝的”,代理能从实体存储中检索出“张三”和“美式咖啡”并完成操作。

持久化与多会话记忆

生产环境需要记忆跨进程、跨重启保持。LangChain 允许你对接外部存储作为记忆后端。使用 RedisChatMessageHistoryDynamoDBChatMessageHistory 或自定义 BaseChatMessageHistory,可实现对话的持久化。

如果你需要为每个用户维护独立记忆,只需在创建记忆实例时传入不同的 session_id

from langchain.memory import ConversationBufferMemory
from langchain.memory.chat_message_histories import RedisChatMessageHistory

def create_user_memory(user_id):
    history = RedisChatMessageHistory(session_id=user_id, url="redis://localhost:6379")
    return ConversationBufferMemory(chat_memory=history)

结合向量存储的长程记忆

当对话跨越多次会话且信息量巨大时,摘要和实体记忆还不够。此时可以将对话历史切块存入向量数据库,再用检索器根据当前问题提取相关记忆。这种“检索增强型记忆”让代理仿佛拥有了无限上下文。

LangChain 的 VectorStoreRetrieverMemory 就是此模式的现成实现:

from langchain.memory import VectorStoreRetrieverMemory

retriever = vectorstore.as_retriever(search_kwargs=dict(k=5))
memory = VectorStoreRetrieverMemory(retriever=retriever)
# 每次对话前,memory 会根据当前输入返回最相关的历史片段

综合实战:打造自主研究助手

将链条、代理与记忆融会贯通,我们可以构建一个自主研究助手:它会根据研究主题自动搜索资料、阅读文章、做笔记,并在多轮对话中记住用户偏好。

  1. 记忆层:使用 VectorStoreRetrieverMemory 存储所有研究笔记,每当用户提出新问题,先检索相关旧笔记。
  2. 代理层:配置一个 OpenAI Functions 代理,挂载搜索工具、文章抓取工具、笔记保存工具和笔记检索工具。
  3. 链条编排:当代理判断需要深度阅读一篇长文时,内部调用一个 RetrievalQA 链条,将长文分块后用嵌入检索回答问题,而不是让模型直接阅读整篇。
  4. 安全控制:为笔记保存工具添加人工审批,避免自动记录错误信息。

这个助手能跨多个会话持续学习,调用外部世界,并像真正的分析师一样工作。实现的核心在于将记忆、工具和链条背后的抽象组合起来,而非孤立的代码片段。


总结与资源

LangChain 的高级用法远不止接口调用,它提供了一套强大的抽象来编排 LLM 应用。掌握自定义链条、智能代理和结构化记忆,你就能从“写提示词”跃迁到“设计智能工作流”。

  • 官方文档LangChain 核心概念 是最权威的参考资料。
  • 示例仓库:GitHub 上的 langchain-ai 组织下有大量 cookbook 和模板项目。
  • 社区生态:LangSmith 用于调试与观测,LangServe 帮助你快速部署链条为 API。

保持实验,生产环境中谨慎添加人工审核与速率限制,你会打造出稳健且强大的 LLM 应用。