2025年LangChain(V0.3)開發與綜合案例

LangChain是什么?

在實際企業開發中,大模型應用往往比簡單的問答要復雜得多。如果只是簡單地向大模型提問并獲取回答,那么大模型的許多強大功能都沒有被充分利用。

要開始使用LangChain,首先需要安裝相關的庫:

pip install langchain
pip install langchain-openai
pip install langchain-community
pip install langgraph,grandalf

與大模型的集成

LangChain支持各種大模型,包括OpenAI的模型、智譜的GLM等,只需更改幾個參數即可切換不同的模型:

llm = ChatOpenAI(model="glm-4-plus",temperature=1.0,openai_api_key="your_api_key",openai_api_base="your_api_base_url"
)

LangChain的核心概念

提示詞模板

在LangChain中,提示詞通常通過模板定義,支持參數化,方便動態生成提示詞。兩個方式的目的都是創建一個提示詞模板,可以根據個人喜好選擇其中一種使用。
提示詞模板有兩種創建方式:

1. from_template方式

使用對象方式定義模板。

from_messages方式(更常用)

json方式定義模板:

prompt = ChatPromptTemplate.from_messages([("system", "請把下面的語句翻譯成{language}"),("user", "{user_text}")
])

LangChain Expression Language (LCEL)

LCEL允許開發者以聲明式的方式鏈接各個組件,使用豎線"|"操作符來連接不同的組件,創建復雜的處理流程,比如某節點循環、重復等。

串行/并行
  1. 串行執行:節點按順序依次執行,前一個節點的輸出作為后一個節點的輸入。這是最常見的模式,如我們之前示例中的鏈式結構。

  2. 并行執行:多個節點同時接收相同的輸入,各自處理后再匯總結果。這對于需要從不同角度分析同一數據的場景特別有用。

# 串行執行示例
serial_chain = node1 | node2 | node3# 并行執行示例
parallel_chain = (node1 & node2 & node3) | combine_results

鏈可能會越來越復雜,以下可以可視化鏈

# 可視化鏈結構
chain.get_graph().print_ascii()

在這里插入圖片描述

使用串行鏈案例

# 定義大模型
llm = ChatOpenAI(model="glm-4-plus",temperature=1.0,openai_api_key="your_api_key", openai_api_base="your_api_base_url"
)# 創建提示詞模板
prompt = ChatPromptTemplate.from_messages([("system", "請把下面的語句翻譯成{language}"),("history", MessagePlaceholder(variable_name="history")),("user", "{user_text}")
])# 創建鏈
chain = prompt | llm | StrOutputParser()# 調用鏈并傳參
result = chain.invoke({"language": "日文","user_text": "今天天氣怎么樣?"
})
print(result)
RunablePassthrough:靈活的數據處理器

RunablePassthrough是LCEL中處理數據轉換的核心工具,它允許我們以字典方式處理鏈。

使用RunablePassthrough有一個重要前提:它只能處理字典類型的數據。這也符合LangChain中大多數組件的設計理念,使用字典作為標準數據傳遞格式。

下面是一個簡單的示例,展示如何使用RunablePassthrough創建和轉換數據:

# 創建一個將輸入轉換為字典的簡單節點
r1 = lambda x: {"k1": x}# 使用RunablePassthrough添加新的鍵值對
chain = r1 | RunablePassthrough.assign(k2=lambda inputs: inputs["k1"] * 2,k3=lambda inputs: inputs["k1"] + 10
)# 運行鏈
result = chain.invoke(5)
# 輸出: {'k1': 5, 'k2': 10, 'k3': 15}
錯誤處理與后備機制

在生產環境中,錯誤處理是不可避免的挑戰。LCEL提供了優雅的錯誤處理機制,確保應用的穩定性和可靠性。

錯誤處理機制在以下場景中特別有價值:

  1. 外部API集成:當調用第三方服務時,提供平滑的錯誤處理
  2. 網絡操作:處理網絡連接問題和服務中斷
  3. 分布式系統:增強系統在部分組件失敗時的彈性
  4. 用戶體驗優化:即使在發生錯誤的情況下,也能確保用戶獲得有用的反饋
后備選項:優雅處理錯誤

with_fallbacks方法允許我們為節點指定后備選項,當主要節點報錯時啟用:

from langchain.schema.runnable import RunnableLambda# 定義一個可能失敗的主要節點
def primary_processor(x):if isinstance(x, int):return x + 10else:raise ValueError("Input must be an integer")# 定義后備節點
def backup_processor(x):try:return int(x) + 20  # 嘗試將輸入轉換為整數后加20except:return "Unable to process input"# 創建帶后備的鏈
resilient_chain = (RunnableLambda(primary_processor).with_fallbacks([RunnableLambda(backup_processor)])
)# 測試
result_normal = resilient_chain.invoke(5) 
print(result_normal) # 正常情況,返回15
result_fallback = resilient_chain.invoke("2")
print(result_fallback) # 主處理器失敗,使用后備,返回22

在這個例子中,主處理器只接受整數輸入。當收到字符串輸入時,它會失敗并觸發后備處理器,后者會嘗試將輸入轉換為整數并加上20。

多級后備鏈
我們可以設置多個后備選項,系統會按順序嘗試,直到找到一個可成功執行的選項:

multi_fallback_chain = primary_node.with_fallbacks([backup_node1,  # 首選后備backup_node2,  # 備選后備final_fallback  # 最后的保障
])

這種設計特別適合處理不同類型的錯誤或異常情況,確保系統在各種條件下都能提供有意義的響應。

重試機制:處理臨時故障

對于可能由于網絡中斷、服務暫時不可用等臨時問題導致的失敗,LCEL提供了重試機制:

# 創建帶重試的鏈
retry_chain = (network_dependent_node.with_retry(max_attempts=4,  # 最多嘗試4次(初始嘗試+3次重試)stop_after_attempt=4,  # 4次嘗試后停止wait_exponential_jitter=True  # 使用指數退避策略,避免同時重試)
)
生命周期管理

生命周期管理是指監控和控制節點從創建到銷毀整個過程中的各個狀態。在LCEL中,每個節點都有一系列生命周期事件,我們可以為這些事件注冊回調函數,實現精細的控制和監控。

主要的生命周期事件包括:

  1. 啟動事件(on_start):節點開始執行時觸發
  2. 結束事件(on_end):節點執行完成時觸發
  3. 錯誤事件(on_error):節點執行出錯時觸發
    LCEL提供了簡潔的API來實現生命周期監聽:
from langchain.schema.runnable import RunnableLambda
import time# 定義一個簡單的處理節點
def text_processor(seconds):# 模擬耗時操作time.sleep(seconds)return seconds * 2# 封裝為節點
node = RunnableLambda(text_processor)# 添加生命周期監聽器
monitored_node = node.with_listeners(on_start=lambda run_obj: print(f"節點啟動時間: {run_obj.start_time}"),on_end=lambda run_obj: print(f"節點結束時間: {run_obj.end_time}")
)# 執行節點
result = monitored_node.invoke(2)  # 將休眠2秒,然后返回4

在這個例子中,我們為節點添加了兩個監聽器:一個在節點啟動時記錄時間,另一個在節點結束時記錄時間。這使我們能夠精確了解節點的執行持續時間。

歷史記錄管理

在選擇歷史記錄存儲方案時,有幾種常見選擇:

  1. 內存存儲:簡單快速,但存在容量限制。隨著用戶數量和并發請求的增加,內存占用會迅速增長。
  2. 磁盤存儲:更為持久,通常是通過數據庫實現。

對于生產環境,數據庫存儲是推薦的方案。數據可以存儲在本地數據庫(如SQLite)或遠程服務器上,只需更改連接URL即可切換。

以下是一個使用SQLite實現歷史記錄管理的示例:

def get_session_history(session_id: str):"""根據會話ID來讀取和保存歷史記錄Args:session_id: 會話的唯一標識符Returns:一個消息歷史對象"""return SQLMessageHistory(session_id=session_id,connection_string="sqlite:///history.db")result = chain.run_with_message_history({"input": "中國一共有哪些直轄市?"},get_session_history,config={"configurable": {"session_id": "user001"}}
)

這個函數創建并返回一個SQLMessageHistory對象,該對象負責管理與特定會話ID相關的所有對話歷史。

綜合案例

串行鏈:餐廳推薦系統

用戶輸入需求 ↓
需求分析與整理 → [展示整理后的結構化需求]↓
餐廳推薦生成 → [展示3家符合條件的餐廳]

核心價值:將用戶非結構化輸入轉化為結構化決策流程,使整個推薦過程透明可見,幫助用戶做出更明智的選擇。
以下是一個餐廳推薦系統的設計,它展示了如何處理多步驟的復雜決策流程:

from langchain.chat_models import init_chat_model
from langchain.prompts import PromptTemplate
from langchain.schema.output_parser import StrOutputParserapi_key = "X"
api_base = "https://api.deepseek.com/"llm = init_chat_model(model="deepseek-chat",api_key=api_key,api_base=api_base,temperature=0,model_provider="deepseek",
)# 創建處理用戶需求的提示模板
requirement_analysis_prompt = PromptTemplate.from_template("""你是一位專業的需求分析師。請對以下用戶輸入的餐廳選擇要求進行歸納總結,提取關鍵點,并組織成有邏輯性的結構:用戶原始要求:{user_requirements}請輸出整理后的需求描述:"""
)# 創建餐廳推薦的提示模板
restaurant_selection_prompt = PromptTemplate.from_template("""你是一位美食專家。根據以下用戶的需求,推薦3家最符合條件的餐廳:用戶需求:{organized_requirements}請列出3家餐廳的名稱和簡要描述:"""
)# 使用管道操作符直接連接所有節點
restaurant_recommendation_chain = (requirement_analysis_prompt | llm |restaurant_selection_prompt | llm | StrOutputParser()
)# 執行鏈的示例代碼
if __name__ == "__main__":result = restaurant_recommendation_chain.invoke({"user_requirements": "我想找一家餐廳,價格不能太貴,最好有素食選擇,環境要安靜一點,適合和朋友聊天,最好是亞洲菜系,我不太能吃辣。位置最好在市中心附近,因為我們坐公共交通。"})print(result)

在這個復雜的推薦系統中,我們看到了幾個重要的設計模式:

  1. 逐步細化處理:從用戶的原始(可能混亂)需求開始,逐步進行分析、推薦和評估
  2. 數據傳遞與保留:使用RunnablePassthrough和Lambda函數確保關鍵數據在鏈中被正確傳遞
  3. 中間結果可視化:通過定制的處理函數展示每個步驟的輸出,使整個流程透明可見
  4. 模塊化設計:將復雜流程分解為可管理的組件,每個組件負責特定功能

動態鏈:智能選擇問題模板

核心要點是創建模板不同,根據用戶的輸入信息AI判斷應該屬于什么類。再根據不同類用不同回答

from langchain.chat_models import init_chat_model
from langchain.schema.output_parser import StrOutputParser
from langchain.prompts import PromptTemplate
from langchain.schema.runnable import RunnableLambda
from langchain_core.output_parsers import JsonOutputParserapi_key = "X"
api_base = "https://api.deepseek.com/"llm = init_chat_model(model="deepseek-chat",api_key=api_key,api_base=api_base,temperature=0,model_provider="deepseek",
)# 定義各領域專用提示詞模板
physics_template = PromptTemplate.from_template("你是一位物理學專家。請回答以下物理問題:\n\n{input}"
)math_template = PromptTemplate.from_template("你是一位數學專家。請解答以下數學問題:\n\n{input}"
)history_template = PromptTemplate.from_template("你是一位歷史學家。請回答以下歷史問題:\n\n{input}"
)computer_science_template = PromptTemplate.from_template("你是一位計算機科學家。請回答以下計算機科學問題:\n\n{input}"
)default_template = PromptTemplate.from_template("你輸入的內容無法歸類到特定領域。我將盡力回答:\n\n{input}"
)# 定義各領域處理鏈
physics_chain = physics_template | llm
math_chain = math_template | llm
history_chain = history_template | llm
computer_science_chain = computer_science_template | llm
default_chain = default_template | llm# 創建分類提示詞
classification_prompt = PromptTemplate.from_template("""不要回答下面用戶的問題,只要根據用戶的輸入來判斷分類。一共有物理、數學、歷史、計算機、其他五種分類。用戶的輸入是: {input}輸出格式為JSON,其中類別的key為"type",用戶輸入內容的key為"input""""
)# 創建路由函數
def router(input_data):# 根據分類結果選擇合適的處理鏈question_type = input_data["type"]if "物理" in question_type:print("1號路由:物理問題")return physics_chainelif "數學" in question_type:print("2號路由:數學問題")return math_chainelif "歷史" in question_type:print("3號路由:歷史問題")return history_chainelif "計算機" in question_type:print("4號路由:計算機問題")return computer_science_chainelse:print("5號路由:其他問題")return default_chain# 創建路由節點
router_node = RunnableLambda(router)# 構建完整的智能體鏈
agent_chain = (classification_prompt |llm |JsonOutputParser()|router_node|StrOutputParser()
)# 測試智能體
test_questions = ["什么是黑體輻射?","計算1+1的結果","第二次世界大戰是什么時候爆發的?","解釋什么是遞歸算法"
]for input_question in test_questions:result = agent_chain.invoke({"input":input_question})print(f"問題:{input_question}")print(f"回答:{result}\n")

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81922.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81922.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81922.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

十分鐘了解 @MapperScan

MapperScan 是 MyBatis 和 MyBatis-Plus 提供的一個 Spring Boot 注解,用于自動掃描并注冊 Mapper 接口,使其能夠被 Spring 容器管理,并與對應的 XML 或注解 SQL 綁定。它的核心作用是簡化 MyBatis Mapper 接口的配置,避免手動逐個…

深度解析 MindTorch:無縫遷移 PyTorch 到 MindSpore 的高效工具

在深度學習領域,框架的選擇往往取決于開發者的習慣、硬件支持以及項目需求。PyTorch 作為當前最受歡迎的深度學習框架之一,以其動態圖機制和簡潔的 API 設計深受開發者喜愛。然而,隨著昇騰硬件的崛起,如何高效地利用昇騰的強大計算…

[250506] Auto-cpufreq 2.6 版本發布:帶來增強的 TUI 監控及多項改進

目錄 Auto-cpufreq 2.6 版本發布:帶來增強的 TUI 監控及多項改進 Auto-cpufreq 2.6 版本發布:帶來增強的 TUI 監控及多項改進 Auto-cpufreq,一款適用于 Linux 的免費開源自動 CPU 速度與功耗優化器,已發布其最新版本 2.6。該工具…

Linux 更改內存交換 swap 為 zram 壓縮,減小磁盤寫入

1、查看當前 swap 的方式 swapon --show 我這里是默認的 swap 文件,大小為 2G。 2、安裝 zram Ubuntu 下: sudo apt install zram-tools安裝后默認會啟動: 3、關閉默認的 swap 文件 sudo swapoff /swapfile 其次是關閉 /etc/fstab 中的 …

ORCAD打印pdf

1 筆記本電腦綁定了打印機,要改成這個

C++中指針使用詳解(4)指針的高級應用匯總

C 中指針的高級應用非常豐富,掌握這些內容能讓你寫出更高性能、更底層控制力強的代碼。下面是應用模塊梳理和例子講解。 目錄預覽 函數指針與回調機制指針數組 vs 數組指針指針與類成員函數(成員函數指針)智能指針(unique_ptr, s…

圖像處理軟件imgPro—調參救星!

推薦一款圖像處理軟件imgPro,該軟件是逛B站時偶然間發現,雖然up主是新號,但是視頻中看起來非常實用! 核心是多種算法高效調參,亮點是自動生成源碼!這您受得了嗎?調試之后,直接復制代…

DOM基礎學習

一、DOM文檔對象模型 通常將DOM看作一顆“樹”,DOM將整個文檔看作一顆“家譜樹 ” 二、對象 用戶定義的對象內建對象(Array、Date、Math)宿主對象 三、節點 node 元素節點(element node)文本節點(text…

初識人工智能、機器學習、深度學習和大模型

文章目錄 1. 前言2. 相關概念3. 層級關系4. 應用場景對比4. 實際案例 初識人工智能、機器學習、深度學習和大模型 1. 前言 之前經常聽人說AI、機器學習,深度學習之類的詞匯,總是傻傻的不了解他們的區別,近來有空,來通俗說說個人看…

n8n系列(1)初識n8n:工作流自動化平臺概述

1. 引言 隨著各類自動化工具的涌現,n8n作為一款開源的工作流自動化平臺,憑借其靈活性、可擴展性和強大的集成能力,正在獲得越來越多技術團隊的青睞。 本文作為n8n系列的開篇,將帶您全面了解這個強大的自動化平臺,探索其起源、特性以及與其他工具的差異,幫助您判斷n8n是否…

Linux:web服務

一、nginx的安裝及啟用 1、為主機配置IP和搭建軟件倉庫 (1)IP的配置 (2)搭建軟件倉庫 2、 web服務的安裝與啟用 (1)nginx的端口 更改nginx端口號 效果 (2) 默認發布目錄 修改默認發…

用卷積神經網絡 (CNN) 實現 MNIST 手寫數字識別

在深度學習領域,MNIST 手寫數字識別是經典的入門級項目,就像編程世界里的 “Hello, World”。卷積神經網絡(Convolutional Neural Network,CNN)作為處理圖像數據的強大工具,在該任務中展現出卓越的性能。本…

從 MDM 到 Data Fabric:下一代數據架構如何釋放 AI 潛能

從 MDM 到 Data Fabric:下一代數據架構如何釋放 AI 潛能 —— 傳統治理與新興架構的范式變革與協同進化 引言:AI 規模化落地的數據困境 在人工智能技術快速發展的今天,企業對 AI 的期望已從 “單點實驗” 轉向 “規模化落地”。然而&#…

蒼穹外賣部署到云服務器使用Docker

部署前端 1.創建nginx鏡像 docker pull nginx 2.宿主機(云服務器)創建掛載目錄和文件 最好手動創建 而不是通過docker run創建,否則nginx.conf 默認會被創建為文件夾 nginx.conf 和html可以直接從黑馬給的資料里導入 3.運行nginx容器&am…

C++ 滲透 數據結構中的二叉搜索樹

歡迎來到干貨小倉庫 "沙漠盡頭必是綠洲。" --面對技術難題時,堅持終會看到希望。 1.二叉搜索樹的概念 二叉搜索樹又稱二叉排序樹,它或者是一顆空樹,或者是具有以下性質的二叉樹: a、若它的左子樹不為空,則…

實現滑動選擇器從離散型的數組中選擇

1.使用原生的input 詳細代碼如下&#xff1a; <template><div class"slider-container"><!-- 滑動條 --><inputtype"range"v-model.number"sliderIndex":min"0":max"customValues.length - 1"step&qu…

ARM尋址方式

尋址方式指的是確定操作數位置的方式。 尋址方式&#xff1a; 立即數尋址 直接尋址&#xff08;絕對尋址&#xff09;&#xff0c;ARM不支持這種尋址方式&#xff0c;但所有CISC處理器都支持 寄存器間接尋址 3種尋址方式總結如下&#xff1a; 助記符 RTL格式 描述 ADD r0,r1…

學苑教育雜志學苑教育雜志社學苑教育編輯部2025年第9期目錄

專題研究 核心素養下合作學習在初中數學中的應用 鄭鐵洪; 4-6 教育管理 小學班級管理應用賞識教育的策略研究 芮望; 7-9 課堂教學 小學數學概念教學的實踐策略 劉淑萍; 10-12 “減負提質”下小學五年級語文課堂情境教學 王利;梁巖; 13-15 小練筆的美麗轉身…

關于類型轉換的細節(隱式類型轉換的臨時變量和理解const權限)

文章目錄 前言類型轉換的細節1. 類型轉換的臨時變量細節二&#xff1a;const與指針 前言 關于類型轉換的細節&#xff0c;這里小編和大家探討兩個方面&#xff1a; 關于類型轉化的臨時變量的問題const關鍵字的權限問題 — 即修改權限。小編或通過一道例題&#xff08;配圖&am…

技術對暴力的削弱

信息時代的大政治分析&#xff1a;效率對暴力的顛覆 一、工業時代勒索邏輯的終結 工廠罷工的消亡 1930年代通用汽車罷工依賴工廠的物理集中、高資本投入和流水線脆弱性&#xff0c;通過暴力癱瘓生產實現勒索。 信息時代企業分散化、資產虛擬化&#xff08;如軟件公司可攜帶代碼…