☰
LangChain设计模式02:责任链模式
2026/9/30 1:35:32 网站建设 项目流程

LangChain设计模式之责任链模式

LangChain 里随手写出的prompt | llm | parser,底层并不是三个对象简单相加,而是一条责任链。本文从设计模式定义、源码实现和实战场景三个层面,把它拆清楚。

一、先记住一句话

在 LangChain 中,责任链模式解决的核心问题是:

如何把多个可执行步骤串联起来,让请求按顺序正向传递。

它是最基础、最常用的执行骨架。你看到的 Prompt 构建、模型调用、输出解析、工具调用、格式化,最终都会被组织成一条链。

二、责任链模式是什么

责任链模式是行为型设计模式。经典定义是:

将多个处理者组成一条链,请求沿着链依次传递,直到某个处理者能够处理并返回结果。

它通常包含四个角色:

角色含义LangChain 对应
抽象处理者定义统一处理接口Runnable
具体处理者处理具体请求Prompt、LLM、Parser
链将处理者串联起来RunnableSequence
请求在链上传递的数据invoke(input, config)

需要特别说明的是,LangChain 中的责任链不是“谁先处理完谁返回”的短链逻辑,而是更偏向固定管线:每个步骤都会执行,上一步的输出作为下一步的输入。它继承的是责任链“解耦步骤、串联执行”的思想,同时吸收管道模式对数据流的约束。

三、LangChain 里的实现:RunnableSequence

在 LangChain 中,|运算符会把左右两个 Runnable 组合起来。多个组件连续使用|时,最终会被封装成RunnableSequence。

prompt | llm | parser ↓ 底层等价于 RunnableSequence([prompt, llm, parser])

3.1 统一接口先行

责任链能成立,前提是链上的每个步骤都实现同一个接口。LangChain 用Runnable完成这件事:

fromabcimportABC,abstractmethodfromtypingimportGeneric,TypeVar,Optional,List Input=TypeVar("Input")Output=TypeVar("Output")classRunnable(Generic[Input,Output],ABC):input_type:typeoutput_type:type@abstractmethoddefinvoke(self,input:Input,config:Optional[dict]=None)->Output:raiseNotImplementedError()

所有 Prompt、LLM、Parser、Chain、Tool,以及后续包装出来的中间件对象,都满足这个契约。

3.2 链的组装与执行

下面是贴合 LangChain 实际逻辑的简化版RunnableSequence:

classRunnableSequence(Runnable[Input,Output]):def__init__(self,steps:List[Runnable]):self.steps=steps self._validate_steps()def_validate_steps(self)->None:foriinrange(len(self.steps)-1):current_output=self.steps[i].output_type next_input=self.steps[i+1].input_typeifnotissubclass(current_output,next_input):raiseValueError(f"步骤{i}的输出类型{current_output}"f"不匹配步骤{i+1}的输入类型{next_input}")definvoke(self,input:Input,config:Optional[dict]=None)->Output:value=inputfori,stepinenumerate(self.steps):step_config=self._patch_config(config,step_idx=i)value=step.invoke(value,step_config)returnvaluedef_patch_config(self,config:Optional[dict],step_idx:int)->dict:config=configor{}return{**config,"step_idx":step_idx,"step_tag":f"step{step_idx}","sequence_id":id(self),}

3.3 这四点决定了它像责任链

  1. 线性串联:请求从第一个步骤进入,依次传到最后一个步骤。
  2. 步骤解耦:每个 Runnable 只关心自己的输入和输出,不感知前后步骤。
  3. 可扩展:通过|可以随时增删步骤或调整顺序。
  4. 上下文传递:config沿链传递,为日志、会话、状态回溯提供基础。

四、实战:从基础链到嵌套链

4.1 基础 Prompt-LLM-Parser 链

这是 LangChain 最常见的一条责任链:

fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_openaiimportChatOpenAIfromlangchain_core.output_parsersimportStrOutputParser prompt=ChatPromptTemplate.from_messages([("system","你是一个专业的文本总结助手,总结内容需简洁明了,不超过50字。"),("user","{input}")])llm=ChatOpenAI(model="gpt-3.5-turbo")parser=StrOutputParser()chain=prompt|llm|parser input_text=("LangChain 是一个用于构建大语言模型应用的框架,""它提供了丰富的组件和工具,支持快速开发复杂的 LLM 应用。")result=chain.invoke({"input":input_text})print(result)

执行顺序:

{"input": input_text} ↓ prompt ↓ llm ↓ parser ↓ result

4.2 嵌套责任链:责任链里的责任链

责任链的一个步骤本身也可以是一条责任链,于是形成树形结构:

fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.runnablesimportRunnableSequence summary_chain=prompt|llm|parser translate_prompt=ChatPromptTemplate.from_messages([("system","将以下文本翻译成英文,保持原意,简洁准确。"),("user","{input}")])translate_chain=translate_prompt|llm|parser# 先总结,再翻译总结结果main_chain=RunnableSequence([summary_chain,translate_chain])result=main_chain.invoke({"input":input_text})print(result)

这种能力让复杂任务可以被拆成多级子链,而不是写一个巨大的处理函数。

五、它在四大模式中的位置

责任链模式不是孤立存在的。它在 LangChain 内核中负责“正向执行流的骨架”:

模式作用关系
命令模式统一Runnable接口责任链的前提
责任链模式串联步骤、正向传递核心骨架
装饰器模式包装链或组件,增强功能对责任链做非侵入扩展
管道模式约束输入输出类型让责任链的数据流更规范

一句话总结:命令模式定接口,责任链模式搭骨架,装饰器模式做增强,管道模式规数据流。

六、总结

LangChain 的责任链模式是怎么实现的:

  1. LangChain 通过Runnable接口统一所有可执行组件。
  2. |运算符把组件组合成RunnableSequence。
  3. RunnableSequence.invoke把输入依次传给每个步骤,前一步输出作为后一步输入。
  4. 每个步骤只关注自身职责,通过config传递上下文。
  5. 责任链既可以扁平串联,也可以嵌套成树形链,支撑复杂任务拆分。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询