
一、為什么需要 Chain前面學習 LangChain 時我們已經接觸到了LLM Prompt Output Parser Memory如果只是完成一個非常簡單的任務我們可以直接用戶輸入 ↓ Prompt ↓ LLM ↓ Answer例如輸入 大號床單套裝 Prompt 描述制造“大號床單套裝”的一個公司的最佳名稱是什么 LLM 豪華床紡這種任務非常簡單。但是實際的大模型應用通常不是“一次 Prompt 調用”就結束。例如我們希望處理一條國外用戶評論法語評論 ↓ 翻譯成英文 ↓ 總結評論 ↓ 識別原始語言 ↓ 根據總結生成回復 ↓ 使用原始語言回復用戶這已經包含多個步驟。如果全部手寫result1 llm(...) result2 llm(...) result3 llm(...) result4 llm(...)代碼會越來越復雜。因此 LangChain 提出了Chain也就是把多個模型調用、Prompt、數據處理步驟按照一定邏輯連接起來。可以把 Chain 理解成AI 應用中的流水線二、什么是 ChainChain 最簡單的理解Input ↓ Step 1 ↓ Step 2 ↓ Step 3 ↓ Output每一個 Step 都可以是Prompt LLM Retriever Parser 另一個 Chain Tool 自定義函數因此Chain 的核心不是“大語言模型”而是流程編排。三、本章四種 Chain本章主要介紹Chain │ ├── LLMChain │ ├── SimpleSequentialChain │ ├── SequentialChain │ └── Router Chain └── MultiPromptChain它們的關系可以簡單理解為LLMChain ↓ 單個任務 SimpleSequentialChain ↓ 多個單輸入單輸出任務串聯 SequentialChain ↓ 復雜多輸入多輸出任務串聯 Router Chain ↓ 根據輸入動態選擇執行哪條鏈這是整章最需要掌握的結構。四、LLMChain4.1 什么是 LLMChainLLMChain是最基礎的一種 Chain。它主要把Prompt LLM組合起來。即Input ↓ PromptTemplate ↓ LLM ↓ Output五、初始化語言模型教程首先導入from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.chains import LLMChain然后llm ChatOpenAI( temperature0.0 )七、創建 Prompt Template定義提示prompt ChatPromptTemplate.from_template( 描述制造{product}的一個公司的最佳名稱是什么? )這里{product}是一個變量。例如product 大號床單套裝那么真正發送給模型的 Prompt 類似描述制造大號床單套裝的一個公司的最佳名稱是什么?所以PromptTemplate可以理解為固定 Prompt 動態變量八、創建 LLMChain接下來chain LLMChain( llmllm, promptprompt )這一步把Prompt LLM組合成LLMChain內部結構LLMChain │ ┌────────────┴────────────┐ │ │ Prompt LLM │ │ └────────────┬────────────┘ ↓ Output九、運行 LLMChain例如product 大號床單套裝 chain.run(product)內部過程大號床單套裝 ↓ 替換 {product} ↓ 完整 Prompt ↓ LLM ↓ 公司名稱例如輸出豪華床紡十、LLMChain 的本質因此LLMChain( llmllm, promptprompt )本質就是Input ↓ Format Prompt ↓ Call LLM ↓ Output可以近似理解成def chain(product): prompt_text prompt.format( productproduct ) result llm(prompt_text) return resultLangChain 只是把這個過程進行了標準化封裝。十一、為什么一個 LLMChain 不夠假設我們想實現產品 ↓ 生成公司名稱 ↓ 根據公司名稱生成公司介紹這里已經需要調用 LLM 兩次。第一步產品 ↓ 公司名稱第二步公司名稱 ↓ 公司介紹這時就需要Sequential Chain十二、SimpleSequentialChainSimpleSequentialChain中文可以理解為簡單順序鏈。其特點是Chain 1 Output ↓ Chain 2 Input ↓ Chain 2 Output ↓ Chain 3 Input即上一條鏈的輸出直接作為下一條鏈的輸入。十三、創建第一個子鏈首先first_prompt ChatPromptTemplate.from_template( 描述制造{product}的一個公司的最好的名稱是什么 )構建chain_one LLMChain( llmllm, promptfirst_prompt )它的作用product ↓ Chain 1 ↓ company_name例如大號床單套裝 ↓ 優床制造公司十四、創建第二個子鏈第二個 Promptsecond_prompt ChatPromptTemplate.from_template( 寫一個20字的描述對于下面這個公司{company_name}的 )然后chain_two LLMChain( llmllm, promptsecond_prompt )它的作用company_name ↓ Chain 2 ↓ company_description例如優床制造公司 ↓ 優床制造公司是一家專注于生產高品質床具的公司。十五、組合兩個 Chain然后from langchain.chains import SimpleSequentialChain創建overall_simple_chain SimpleSequentialChain( chains[ chain_one, chain_two ], verboseTrue )結構SimpleSequentialChain │ ↓ chain_one │ 公司名稱 ↓ chain_two │ ↓ 公司介紹十六、運行 SimpleSequentialChain例如product 大號床單套裝 overall_simple_chain.run(product)完整過程大號床單套裝 ↓ Chain 1 ↓ 優床制造公司 ↓ Chain 2 ↓ 優床制造公司是一家專注于生產高品質床具的公司。十七、verboseTrue 是什么這里verboseTrue非常適合調試。它會輸出鏈的執行過程。例如 Entering new SimpleSequentialChain chain... 優床制造公司 優床制造公司是一家專注于生產高品質床具的公司。 Finished chain.如果verboseFalse通常只返回最終結果。因此開發階段非常推薦verboseTrue因為可以觀察每個 Chain 的輸出是什么 數據有沒有正確傳給下一步 哪里出現了異常十八、SimpleSequentialChain 的限制它非常簡單但是限制也非常明顯每一步只能處理一個輸入和一個輸出。結構必須類似A ↓ B ↓ C ↓ D不能很方便地處理A ────────┐ │ ↓ B → C → D ↑ │ E如果后面的 Chain 同時需要原始輸入 前面某一步結果 另外一個 Chain 的結果SimpleSequentialChain 就不夠用了。因此需要SequentialChain十九、SequentialChainSequentialChain 是更加通用的順序鏈。核心特點可以同時保存和傳遞多個變量。例如原始評論 Review │ ├───────────────┐ ↓ ↓ 翻譯成英文 判斷語言 ↓ ↓ English_Review language ↓ │ 生成 summary │ ↓ │ └───────┬───────┘ ↓ 生成最終回復 ↓ followup_message這已經不是簡單的“一條直線”。而是多變量數據流二十、SequentialChain 示例任務教程實現的是用戶評論 ↓ 翻譯成英文 ↓ 英文評論 ↓ 進行總結同時原始評論 ↓ 判斷是什么語言最后總結 原始語言 ↓ 生成對應語言的回復因此完整流程Review │ ┌────────────┴────────────┐ │ │ ↓ ↓ Chain 1 Chain 3 │ │ English_Review language │ │ ↓ │ Chain 2 │ │ │ summary │ └────────────┬────────────┘ ↓ Chain 4 ↓ followup_message這個圖非常重要。二十一、第一個 Chain翻譯評論first_prompt ChatPromptTemplate.from_template( 把下面的評論review翻譯成英文: \n\n{Review} )構建chain_one LLMChain( llmllm, promptfirst_prompt, output_keyEnglish_Review )輸入Review輸出English_Review特別注意output_keyEnglish_Review二十二、output_key 的作用為什么需要output_key因為 SequentialChain 中同時存在很多數據Review English_Review summary language followup_message必須告訴 LangChain當前 Chain 輸出的數據叫什么名字。因此output_keyEnglish_Review可以理解為state[English_Review] chain_one(...)這樣后面的 Chain 就可以引用{English_Review}二十三、第二個 Chain總結評論Promptsecond_prompt ChatPromptTemplate.from_template( 請你用一句話來總結下面的評論review: \n\n{English_Review} )Chainchain_two LLMChain( llmllm, promptsecond_prompt, output_keysummary )數據流English_Review ↓ Chain 2 ↓ summary二十四、第三個 Chain識別語言Promptthird_prompt ChatPromptTemplate.from_template( 下面的評論review使用的什么語言:\n\n{Review} )Chainchain_three LLMChain( llmllm, promptthird_prompt, output_keylanguage )注意這里輸入不是English_Review而是最初的Review所以 SequentialChain 能夠保存原始輸入供后面的 Chain 再次使用。二十五、第四個 Chain生成最終回復Promptfourth_prompt ChatPromptTemplate.from_template( 使用特定的語言對下面的總結寫一個后續回復: \n\n總結: {summary} \n\n語言: {language} )Chainchain_four LLMChain( llmllm, promptfourth_prompt, output_keyfollowup_message )這里非常關鍵。Chain 4 同時依賴summary language即Chain 2 Output Chain 3 Output這就是為什么SimpleSequentialChain已經不夠了。二十六、構建 SequentialChainfrom langchain.chains import SequentialChain創建overall_chain SequentialChain( chains[ chain_one, chain_two, chain_three, chain_four ], input_variables[ Review ], output_variables[ English_Review, summary, followup_message ], verboseTrue )二十七、input_variables這里input_variables[Review]表示整個 SequentialChain 最開始需要用戶提供Review相當于函數def overall_chain(Review): ...二十八、output_variables這里output_variables[ English_Review, summary, followup_message ]表示整個 Chain 最后需要返回English_Review summary followup_message例如{ Review: ..., English_Review: ..., summary: ..., followup_message: ... }二十九、SequentialChain 的核心狀態字典理解 SequentialChain 最好的方法是把它想象成維護了一個state {}假設最初state { Review: 法語評論 }運行 Chain 1state[English_Review] ...得到state { Review: ..., English_Review: ... }運行 Chain 2state[summary] ...現在state { Review: ..., English_Review: ..., summary: ... }運行 Chain 3state[language] French于是state { Review: ..., English_Review: ..., summary: ..., language: French }最后 Chain 4 使用summary language得到state[followup_message] ...所以SequentialChain 的本質是讓多個 Chain 共享一個不斷擴展的變量狀態。三十、SimpleSequentialChain 和 SequentialChain 區別這是本章非常容易考察的一個知識點。對比SimpleSequentialChainSequentialChain數據流單線多變量每步輸入通常一個可以多個每步輸出通常一個可以多個保留中間變量較弱可以支持復雜依賴不適合適合配置復雜度低高最簡單的記憶SimpleSequentialChain A → B → C → D而SequentialChain A → B ──┐ │ ↓ └→ C → D三十一、前面三種 Chain 都有一個共同特點截至目前LLMChain SimpleSequentialChain SequentialChain都有一個共同點執行路徑是提前確定好的。例如Chain1 ↓ Chain2 ↓ Chain3 ↓ Chain4無論用戶輸入什么流程都固定。但真實系統可能不是這樣。比如用戶問題可能屬于物理 數學 歷史 計算機如果全部使用同一個 Prompt你是一個專家請回答 {question}效果通常不如物理問題 → 物理 Prompt 數學問題 → 數學 Prompt 歷史問題 → 歷史 Prompt 計算機問題 → 計算機 Prompt所以需要Router Chain三十二、什么是 Router ChainRouter Chain 可以理解為大模型世界中的路由器。輸入Question首先判斷這個問題屬于哪一類然后Question │ ↓ Router │ ┌───────────┼───────────┐ │ │ │ ↓ ↓ ↓ Physics Math History Chain Chain Chain因此 Router Chain 的最大特點是運行路徑不是固定的而是根據輸入動態選擇。三十三、Router Chain 的兩個核心組成Router 系統主要包含Router Chain和Destination ChainsRouter Chain負責判斷輸入應該去哪里Destination Chains負責真正執行任務例如Router │ ├── Physics Chain ├── Math Chain ├── History Chain └── Computer Science Chain三十四、本章 Router 示例教程創建了四類專家物理學 數學 歷史 計算機科學每個專家擁有不同 Prompt。因此整體結構Question │ ↓ LLM Router │ 判斷問題屬于哪個領域 │ ┌─────────────┼─────────────┐ ↓ ↓ ↓ Physics Math History Chain Chain Chain ↓ Computer Science Chain三十五、物理 Prompt例如physics_template 你是一個非常聰明的物理專家。 你擅長用一種簡潔并且易于理解的方式回答問題。 當你不知道問題答案時你承認你不知道。 這是一個問題 {input} 核心就是角色設定 回答風格 約束 用戶問題三十六、數學 Prompt數學 Prompt 強調把復雜問題拆成多個子問題例如復雜數學問題 ↓ 拆分 ↓ 解決子問題 ↓ 組合結果 ↓ 最終答案三十七、歷史 Prompt歷史 Prompt 強調歷史背景 歷史證據 分析 反思 評估因此同樣的問題如果使用不同 Prompt模型行為也會產生明顯差異。三十八、計算機 Prompt計算機 Prompt 強調算法 步驟 復雜度 問題求解 時間復雜度 空間復雜度這實際上就是給不同任務配置不同的 Expert Prompt。三十九、prompt_infos定義好多個 Prompt 后需要告訴 Router有哪些可選 Prompt 每個 Prompt 擅長什么例如prompt_infos [ { 名字: 物理學, 描述: 擅長回答關于物理學的問題, 提示模板: physics_template }, { 名字: 數學, 描述: 擅長回答數學問題, 提示模板: math_template }, { 名字: 歷史, 描述: 擅長回答歷史問題, 提示模板: history_template }, { 名字: 計算機科學, 描述: 擅長回答計算機科學問題, 提示模板: computerscience_template } ]四十、Router 為什么需要 description這是非常關鍵的一點。Router 并不是根據chain 的代碼判斷應該選擇誰。而主要依賴name description例如物理學 擅長回答關于物理學的問題 數學 擅長回答數學問題當輸入什么是黑體輻射Router 根據描述判斷黑體輻射 → 物理學因此Router 的路由質量很大程度取決于 Destination Description 是否清晰。四十一、構建 Destination Chains首先創建一個字典destination_chains {}然后for p_info in prompt_infos: name p_info[名字] prompt_template p_info[提示模板] prompt ChatPromptTemplate.from_template( templateprompt_template ) chain LLMChain( llmllm, promptprompt ) destination_chains[name] chain最終destination_chains大致類似{ 物理學: physics_chain, 數學: math_chain, 歷史: history_chain, 計算機科學: computer_chain }四十二、Default Chain還有一個非常重要的設計Default Chain因為用戶可能問推薦幾部科幻電影這既不是物理 數學 歷史 計算機怎么辦需要Default Chain作為兜底。四十三、創建 Default Chaindefault_prompt ChatPromptTemplate.from_template( {input} ) default_chain LLMChain( llmllm, promptdefault_prompt )也就是說如果 Router 無法匹配任何專家 ↓ Default Chain ↓ 普通 LLM 回答這是一種非常重要的軟件設計思想Fallback / Graceful Degradation即無法走專業路徑 ↓ 至少還有通用路徑四十四、Router 本身也是一個 LLM這是這一節非常值得理解的一點。教程使用LLMRouterChain它并不是傳統的if question.contains(physics):也不是關鍵詞分類。而是Question ↓ LLM ↓ 判斷屬于哪個 Destination所以實際上Router本身也是一次 LLM 調用。四十五、Router 的輸出Router 需要返回{ destination: ..., next_inputs: ... }其中destination表示接下來調用哪個 Chain例如物理學 數學 歷史 計算機科學 DEFAULT而next_inputs表示傳給目標 Chain 的輸入四十六、RouterOutputParser因為 Router LLM 返回的是文本。但是程序真正需要的是{ destination: ..., next_inputs: ... }所以需要RouterOutputParser()它負責LLM Text Output ↓ Parser ↓ Structured Data例如json { destination: 物理學, next_inputs: 什么是黑體輻射 }Parser 將其轉換成程序可以讀取的數據。 --- # 四十七、構建 Router Chain 核心代碼 python router_prompt PromptTemplate( templaterouter_template, input_variables[input], output_parserRouterOutputParser() )然后router_chain LLMRouterChain.from_llm( llm, router_prompt )整體Question ↓ Router Prompt ↓ LLM ↓ RouterOutputParser ↓ destination next_inputs四十八、MultiPromptChain最終chain MultiPromptChain( router_chainrouter_chain, destination_chainsdestination_chains, default_chaindefault_chain, verboseTrue )整體結構終于完整User Input │ ↓ Router Chain │ 判斷 Destination │ ┌──────────────┼──────────────┐ │ │ │ ↓ ↓ ↓ Physics Mathematics History Chain Chain Chain │ └── Computer Science 如果無法匹配 ↓ Default Chain四十九、物理問題的執行過程輸入chain.run( 什么是黑體輻射 )Router黑體輻射 ↓ 屬于物理問題所以Router ↓ Physics Chain ↓ 物理專家 Prompt ↓ LLM ↓ Answer五十、數學問題輸入chain.run( 22等于多少 )Router22 ↓ 數學于是Math Chain負責回答。五十一、Router Chain 的優勢如果沒有 Router所有問題 ↓ 同一個 Prompt ↓ LLM而有了 RouterUser Question │ ↓ Router │ ┌────────┼────────┐ ↓ ↓ ↓ Prompt A Prompt B Prompt C ↓ ↓ ↓ LLM LLM LLM優勢不同任務使用不同 Prompt 不同領域使用不同策略 系統模塊化 更容易維護 更容易擴展五十二、Router Chain 在真實系統中的應用例如 AI 客服用戶問題 ↓ Router │ ├── 售前咨詢 Chain ├── 訂單查詢 Chain ├── 退款 Chain ├── 技術支持 Chain └── 投訴 Chain再例如企業 AI 助手User Query ↓ Router │ ├── HR Chain ├── Finance Chain ├── IT Chain ├── Legal Chain └── General Chain五十三、四種 Chain 的完整對比Chain核心功能數據流特點使用場景LLMChainPrompt LLM單步單任務SimpleSequentialChain多個 Chain 串聯一進一出簡單流水線SequentialChain多 Chain 多變量多輸入多輸出復雜工作流Router Chain動態選擇 Chain分支結構多任務系統五十四、從程序結構角度理解四種 ChainLLMChain類似def task(x): return llm(prompt(x))SimpleSequentialChain類似def workflow(x): x chain1(x) x chain2(x) x chain3(x) return xSequentialChain類似def workflow(review): english_review chain1(review) summary chain2(english_review) language chain3(review) reply chain4( summary, language ) return { english_review: english_review, summary: summary, reply: reply }Router Chain類似def router(question): category classify(question) if category physics: return physics_chain(question) elif category math: return math_chain(question) elif category history: return history_chain(question) elif category computer: return computer_chain(question) else: return default_chain(question)這四段偽代碼把本章幾乎所有核心內容都概括了。五十五、Chain 本質上是在構建有向圖如果進一步抽象會發現Chain其實就是節點之間的數據流。比如 SequentialChainReview │ ├─────────────┐ ↓ ↓ Translate Detect Language ↓ ↓ Summary │ └──────┬──────┘ ↓ Reply可以看成Directed Graph也就是有向圖。節點Prompt LLM Parser Retriever Tool Function邊數據流這其實已經非常接近現代 LLM Workflow / Agent Framework 的底層思想。五十六、Chain 和普通 Python Pipeline 有什么區別有人可能會問這些東西我直接用 Python 函數串起來不就可以了嗎當然可以。例如english translate(review) summary summarize(english) language detect_language(review) reply generate_reply(summary, language)完全可以實現。LangChain Chain 的價值主要是統一接口 Prompt 管理 模型調用 日志 Tracing 輸入輸出約定 組件組合 后續擴展所以Chain 不是 Python 做不到而是把 LLM Application Workflow 標準化。五十七、一個容易產生的誤區很多初學者看到Chain會認為Chain 多次調用 ChatGPT。并不準確。更準確地說Chain 多個組件按照既定的數據依賴關系組成一個工作流。里面可以有LLM Prompt Memory Retriever Parser Tool Database Function因此LLM Chain只是 Chain 中的一種。五十八、Chain 與 Prompt Chain 的區別Prompt Chain 更強調Prompt1 ↓ LLM ↓ Prompt2 ↓ LLM而 LangChain 中的 Chain 是更加通用的抽象Component A ↓ Component B ↓ Component C例如后面的 RAGQuestion ↓ Retriever ↓ Documents ↓ Prompt ↓ LLM也可以看成一個 Chain。五十九、為什么 Chain 對復雜 LLM 應用很重要一個真正的 AI Application 往往不是Question ↓ LLM ↓ Answer而是Question ↓ Intent Classification ↓ Router ↓ Knowledge Retrieval ↓ Prompt Construction ↓ LLM ↓ Output Parser ↓ Validation ↓ Answer甚至Answer ↓ 不通過 ↓ 重新調用模型因此隨著系統復雜度提高最困難的問題會逐漸從 Prompt Engineering 轉向 Workflow Engineering。六十、LLM Application 的三個層次學習到這里可以把 LLM 應用分成三個層次。第一層單次 PromptPrompt ↓ LLM第二層ChainPrompt ↓ LLM ↓ Prompt ↓ LLM ↓ Parser第三層復雜 Workflow / AgentInput ↓ Router ↓ Planning ↓ Tool ↓ Retriever ↓ LLM ↓ Evaluation ↓ Replan所以 Chain 實際上是從簡單 LLM 調用走向復雜 AI Agent 的重要過渡。六十一、本章最重要的變量關系SequentialChain 中一定要搞清input_variables output_key output_variablesinput_variables整個 Chain 的入口input_variables[Review]output_key某一個子 Chain 的輸出名稱output_keysummaryoutput_variables整個 Chain 最終返回哪些變量output_variables[ English_Review, summary, followup_message ]關系input_variables ↓ Chain ↓ output_key ↓ 成為其他 Chain 的 Input ↓ 最終部分結果進入 output_variables六十二、Router 最重要的三個概念Router 部分重點記住Router Chain Destination Chains Default Chain對應Router Chain 負責 去哪 Destination Chain 負責 干活 Default Chain 負責 沒人匹配怎么辦可以記成Router 調度員 Destination Chain 專家 Default Chain 全科醫生六十三、本章完整知識結構LangChain Chains │ ├── LLMChain │ │ │ ├── Prompt │ └── LLM │ ├── SimpleSequentialChain │ │ │ ├── Chain 1 │ ├── Chain 2 │ └── Chain 3 │ ├── SequentialChain │ │ │ ├── input_variables │ ├── output_key │ ├── output_variables │ └── 多變量依賴 │ └── Router Chain │ ├── Router Chain │ ├── Destination Chains │ ├── Default Chain │ └── RouterOutputParser六十四、一張圖理解本章第一階段 Input ↓ Prompt ↓ LLM ↓ Output LLMChain然后升級Input ↓ Chain1 ↓ Chain2 ↓ Chain3 ↓ Output SimpleSequentialChain繼續升級Input │ ┌─────┴─────┐ ↓ ↓ Chain1 Chain3 ↓ ↓ Chain2 │ └─────┬─────┘ ↓ Chain4 SequentialChain最后Input │ ↓ Router │ ┌────────┼────────┐ ↓ ↓ ↓ Chain A Chain B Chain C │ 無匹配 → Default Router Chain這就是本章的完整演進過程。六十九、最終總結本章介紹的核心并不是四個 LangChain 類而是 AI Workflow 從簡單到復雜的四個階段LLMChain ↓ 封裝單個 LLM 任務 SimpleSequentialChain ↓ 線性流水線 SequentialChain ↓ 多變量數據流 Router Chain ↓ 動態分支工作流最終可以用一句話總結Chain 的本質就是把大模型應用中的多個處理步驟通過明確的數據輸入輸出關系連接起來。如果再進一步抽象節點 數據流 路由 LLM Workflow七十、本章思維導圖模型鏈 Chains │ ├── 1. LLMChain │ ├── PromptTemplate │ ├── LLM │ └── Input → Prompt → LLM → Output │ ├── 2. SimpleSequentialChain │ ├── 多 Chain │ ├── 單輸入單輸出 │ └── A → B → C → D │ ├── 3. SequentialChain │ ├── input_variables │ ├── output_key │ ├── output_variables │ └── 多輸入、多輸出、多依賴 │ └── 4. Router Chain ├── Router Chain ├── Destination Chains ├── Default Chain ├── RouterOutputParser └── 根據輸入動態選擇執行路徑