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