
LangChain設計模式之責任鏈模式LangChain 里隨手寫出的prompt | llm | parser底層并不是三個對象簡單相加而是一條責任鏈。本文從設計模式定義、源碼實現(xiàn)和實戰(zhàn)場景三個層面把它拆清楚。一、先記住一句話在 LangChain 中責任鏈模式解決的核心問題是如何把多個可執(zhí)行步驟串聯(lián)起來讓請求按順序正向傳遞。它是最基礎、最常用的執(zhí)行骨架。你看到的 Prompt 構(gòu)建、模型調(diào)用、輸出解析、工具調(diào)用、格式化最終都會被組織成一條鏈。二、責任鏈模式是什么責任鏈模式是行為型設計模式。經(jīng)典定義是將多個處理者組成一條鏈請求沿著鏈依次傳遞直到某個處理者能夠處理并返回結(jié)果。它通常包含四個角色角色含義LangChain 對應抽象處理者定義統(tǒng)一處理接口Runnable具體處理者處理具體請求Prompt、LLM、Parser鏈將處理者串聯(lián)起來RunnableSequence請求在鏈上傳遞的數(shù)據(jù)invoke(input, config)需要特別說明的是LangChain 中的責任鏈不是“誰先處理完誰返回”的短鏈邏輯而是更偏向固定管線每個步驟都會執(zhí)行上一步的輸出作為下一步的輸入。它繼承的是責任鏈“解耦步驟、串聯(lián)執(zhí)行”的思想同時吸收管道模式對數(shù)據(jù)流的約束。三、LangChain 里的實現(xiàn)RunnableSequence在 LangChain 中|運算符會把左右兩個 Runnable 組合起來。多個組件連續(xù)使用|時最終會被封裝成RunnableSequence。prompt | llm | parser ↓ 底層等價于 RunnableSequence([prompt, llm, parser])3.1 統(tǒng)一接口先行責任鏈能成立前提是鏈上的每個步驟都實現(xiàn)同一個接口。LangChain 用Runnable完成這件事fromabcimportABC,abstractmethodfromtypingimportGeneric,TypeVar,Optional,List InputTypeVar(Input)OutputTypeVar(Output)classRunnable(Generic[Input,Output],ABC):input_type:typeoutput_type:typeabstractmethoddefinvoke(self,input:Input,config:Optional[dict]None)-Output:raiseNotImplementedError()所有 Prompt、LLM、Parser、Chain、Tool以及后續(xù)包裝出來的中間件對象都滿足這個契約。3.2 鏈的組裝與執(zhí)行下面是貼合 LangChain 實際邏輯的簡化版RunnableSequenceclassRunnableSequence(Runnable[Input,Output]):def__init__(self,steps:List[Runnable]):self.stepssteps self._validate_steps()def_validate_steps(self)-None:foriinrange(len(self.steps)-1):current_outputself.steps[i].output_type next_inputself.steps[i1].input_typeifnotissubclass(current_output,next_input):raiseValueError(f步驟{i}的輸出類型{current_output}f不匹配步驟{i1}的輸入類型{next_input})definvoke(self,input:Input,config:Optional[dict]None)-Output:valueinputfori,stepinenumerate(self.steps):step_configself._patch_config(config,step_idxi)valuestep.invoke(value,step_config)returnvaluedef_patch_config(self,config:Optional[dict],step_idx:int)-dict:configconfigor{}return{**config,step_idx:step_idx,step_tag:fstep{step_idx},sequence_id:id(self),}3.3 這四點決定了它像責任鏈線性串聯(lián)請求從第一個步驟進入依次傳到最后一個步驟。步驟解耦每個 Runnable 只關(guān)心自己的輸入和輸出不感知前后步驟??蓴U展通過|可以隨時增刪步驟或調(diào)整順序。上下文傳遞config沿鏈傳遞為日志、會話、狀態(tài)回溯提供基礎。四、實戰(zhàn)從基礎鏈到嵌套鏈4.1 基礎 Prompt-LLM-Parser 鏈這是 LangChain 最常見的一條責任鏈fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_openaiimportChatOpenAIfromlangchain_core.output_parsersimportStrOutputParser promptChatPromptTemplate.from_messages([(system,你是一個專業(yè)的文本總結(jié)助手總結(jié)內(nèi)容需簡潔明了不超過50字。),(user,{input})])llmChatOpenAI(modelgpt-3.5-turbo)parserStrOutputParser()chainprompt|llm|parser input_text(LangChain 是一個用于構(gòu)建大語言模型應用的框架它提供了豐富的組件和工具支持快速開發(fā)復雜的 LLM 應用。)resultchain.invoke({input:input_text})print(result)執(zhí)行順序{input: input_text} ↓ prompt ↓ llm ↓ parser ↓ result4.2 嵌套責任鏈責任鏈里的責任鏈責任鏈的一個步驟本身也可以是一條責任鏈于是形成樹形結(jié)構(gòu)fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.runnablesimportRunnableSequence summary_chainprompt|llm|parser translate_promptChatPromptTemplate.from_messages([(system,將以下文本翻譯成英文保持原意簡潔準確。),(user,{input})])translate_chaintranslate_prompt|llm|parser# 先總結(jié)再翻譯總結(jié)結(jié)果main_chainRunnableSequence([summary_chain,translate_chain])resultmain_chain.invoke({input:input_text})print(result)這種能力讓復雜任務可以被拆成多級子鏈而不是寫一個巨大的處理函數(shù)。五、它在四大模式中的位置責任鏈模式不是孤立存在的。它在 LangChain 內(nèi)核中負責“正向執(zhí)行流的骨架”模式作用關(guān)系命令模式統(tǒng)一Runnable接口責任鏈的前提責任鏈模式串聯(lián)步驟、正向傳遞核心骨架裝飾器模式包裝鏈或組件增強功能對責任鏈做非侵入擴展管道模式約束輸入輸出類型讓責任鏈的數(shù)據(jù)流更規(guī)范一句話總結(jié)命令模式定接口責任鏈模式搭骨架裝飾器模式做增強管道模式規(guī)數(shù)據(jù)流。六、總結(jié)LangChain 的責任鏈模式是怎么實現(xiàn)的LangChain 通過Runnable接口統(tǒng)一所有可執(zhí)行組件。|運算符把組件組合成RunnableSequence。RunnableSequence.invoke把輸入依次傳給每個步驟前一步輸出作為后一步輸入。每個步驟只關(guān)注自身職責通過config傳遞上下文。責任鏈既可以扁平串聯(lián)也可以嵌套成樹形鏈支撐復雜任務拆分。