LangGraph vs CrewAI vs OpenAI Swarm:三大AI框架怎么選? 原創(chuàng)
LangGraph介紹
LangGraph是由LangChain團隊開發(fā)的前沿開源框架,它代表了AI應用架構的重要進步,專為構建、部署和管理復雜的生成式AI工作流而設計。作為一個強大的編排工具,它提供了底層基礎設施,用于支持長時間運行、有狀態(tài)的工作流或智能體(agent)系統(tǒng),為開發(fā)者提供了構建下一代AI應用的關鍵能力。
LangGraph is a low-level orchestration framework for building, managing, and deploying long-running, stateful agents.
在當今AI應用開發(fā)的浪潮中,簡單的問答式交互已無法滿足復雜應用場景的需求。企業(yè)和開發(fā)者正在尋求構建更加智能、持久且具有上下文感知能力的系統(tǒng)。從基礎的聊天機器人到復雜的多智能體系統(tǒng),開發(fā)者需要一種能夠有效管理狀態(tài)、協(xié)調(diào)多個組件之間交互的框架。LangGraph正是為解決這一挑戰(zhàn)而生,它通過狀態(tài)機的概念,使開發(fā)者能夠構建具有持久狀態(tài)和復雜邏輯流的LLM應用,從而實現(xiàn)真正的"智能"交互體驗。
什么是LangGraph?
LangGraph是一個優(yōu)雅而強大的Python庫,它使用圖結構來建模和管理AI工作流中各組件之間的復雜關系。與其他框架不同,LangGraph不抽象化提示(prompt)或架構,而是專注于提供底層支持基礎設施,賦予開發(fā)者最大的靈活性和控制力。它的設計理念源于計算機科學中的狀態(tài)機概念,但針對LLM應用場景進行了專門優(yōu)化。
LangGraph的核心理念是將應用邏輯表示為一個圖(Graph),其中:
- 節(jié)點(Nodes):代表工作流中的獨立組件或智能體,可以視為以特定方式相互交互的"參與者"。每個節(jié)點可以執(zhí)行特定的功能,如生成文本、分析數(shù)據(jù)或調(diào)用外部工具。
- 邊(Edges):是Python中的函數(shù),基于當前狀態(tài)決定下一個要執(zhí)行的節(jié)點,實現(xiàn)了工作流中的條件邏輯和控制流。
- 狀態(tài)(State):作為一種"記憶庫",記錄和跟蹤AI系統(tǒng)處理的所有有價值的信息,確保系統(tǒng)能夠維持上下文并做出連貫的響應。
這種設計使得開發(fā)者可以:
- 構建具有清晰定義的狀態(tài)轉換邏輯的應用,使復雜的AI行為變得可預測和可控
- 實現(xiàn)復雜的條件分支和循環(huán),使AI能夠根據(jù)不同情況做出不同反應
- 維護和恢復應用狀態(tài),即使在系統(tǒng)重啟或故障后也能繼續(xù)之前的對話
- 設計多智能體協(xié)作系統(tǒng),讓多個專業(yè)化的AI組件協(xié)同工作,解決復雜問題
LangGraph的核心優(yōu)勢
LangGraph提供了以下關鍵優(yōu)勢,使其成為構建復雜AI工作流的理想選擇:
- 持久執(zhí)行(Durable Execution)- 構建能夠在故障中持續(xù)運行的智能體,可以自動從中斷點精確恢復,確保長時間運行的任務不會因臨時問題而失敗
- 人機協(xié)作(Human-in-the-loop)- 無縫整合人類監(jiān)督,允許在執(zhí)行過程中的任何點檢查和修改智能體狀態(tài),實現(xiàn)人類智慧與AI能力的最佳結合
- 全面記憶管理(Comprehensive Memory)- 創(chuàng)建真正有狀態(tài)的智能體,同時具備短期工作記憶和跨會話的長期持久記憶,使AI能夠提供個性化和上下文相關的體驗
- 調(diào)試能力(Debugging)- 通過LangSmith提供的可視化工具深入了解復雜的智能體行為,追蹤執(zhí)行路徑和狀態(tài)轉換,大大簡化了開發(fā)和故障排除過程
- 生產(chǎn)級部署(Production-ready Deployment)- 使用專為處理有狀態(tài)、長時間運行的工作流而設計的可擴展基礎設施,確保在實際應用中的可靠性和性能
- 工具集成- 無縫集成各種外部工具和API,擴展LLM的能力邊界,使AI能夠執(zhí)行實際操作并訪問最新信息
- 多智能體支持- 內(nèi)置支持多智能體系統(tǒng)的構建,使多個LLM實例能夠協(xié)同工作,分工合作解決復雜問題
LangGraph的關鍵組件
LangGraph框架圍繞幾個關鍵組件構建,這些組件協(xié)同工作,使用戶能夠創(chuàng)建和管理復雜的AI工作流:
圖架構組件
- 狀態(tài)圖(Stateful Graphs):每個節(jié)點代表計算中的一步,本質(zhì)上設計一個狀態(tài)圖。這種有狀態(tài)的方法允許圖保留關于先前步驟的信息,隨著計算的展開實現(xiàn)信息的連續(xù)和上下文處理。
- 循環(huán)圖(Cyclical Graph):包含至少一個循環(huán)的圖,對智能體運行時至關重要。這意味著存在一條路徑,從同一節(jié)點開始和結束,在圖中形成一個循環(huán)。
- 節(jié)點(Nodes):在LangGraph中,節(jié)點代表AI工作流中的獨立組件或智能體。例如,可以使用ToolNode添加用于工具調(diào)用的節(jié)點。
- 邊(Edges):邊是Python中的函數(shù),基于當前狀態(tài)確定下一個要執(zhí)行的節(jié)點。邊可以是條件分支或固定轉換。
監(jiān)控機制
- 人機協(xié)作(Human-in-the-loop):指在過程中某個點需要人類交互的要求。在機器學習領域,人機協(xié)作指的是人類增強機器計算能力以做出明智決策的協(xié)作過程。
工具和集成
- RAG(檢索增強生成):將LLM的能力與外部來源的上下文信息相結合,通過檢索相關文檔,然后將其用作答案生成的輸入。
- 工作流(Workflows):定義AI工作流的節(jié)點交互序列。通過將節(jié)點排列成工作流,用戶可以創(chuàng)建更復雜和動態(tài)的工作流。
- APIs:LangGraph提供了一組API,使用戶能夠以編程方式與LangGraph的組件交互。
- LangSmith:LangSmith是一個專門用于在LangGraph中構建和管理LLM的API,提供了初始化LLM、添加條件邊和優(yōu)化性能的工具。
通過這些組件的創(chuàng)新組合,用戶可以構建更復雜的AI工作流,充分利用各個組件的優(yōu)勢。
LangGraph與其他框架的對比
在AI智能體框架領域,LangGraph、CrewAI和OpenAI Swarm是三個主要的競爭者,每個框架都有其獨特的優(yōu)勢和適用場景。本節(jié)將對這三個框架進行對比分析,幫助開發(fā)者選擇最適合自己項目需求的框架。
LangGraph的特點
LangGraph是一個基于圖結構的AI系統(tǒng),主要針對涉及結構化工作流的任務,特別是自然語言處理(NLP)領域。其圖驅(qū)動的架構使其在需要上下文連貫性的應用中表現(xiàn)尤為出色。
優(yōu)勢:
- 任務依賴可視化:LangGraph的圖驅(qū)動架構允許用戶清晰地映射和理解任務組件之間的交互和依賴關系,對于聊天機器人設計或虛擬助手開發(fā)等領域尤為重要。
- 可擴展架構:模塊化設計使其能與各種工具和框架無縫集成,支持從NLP到基礎數(shù)據(jù)分析的廣泛應用。
- 改進的任務管理:通過可視化任務依賴和工作流,提供了一種組織化的任務管理方法,有助于團隊有效管理復雜流程。
- 增強的協(xié)作功能:工作流的可視化表示促進了團隊之間的更好協(xié)作,開發(fā)人員、數(shù)據(jù)科學家和領域?qū)<铱梢暂p松交流AI流程背后的邏輯。
- 自動錯誤檢測:工作流的可視化表示有助于快速識別任務執(zhí)行中的錯誤或漏洞,使故障排除變得更加直觀。
挑戰(zhàn):
- 學習曲線陡峭:對于不熟悉基于圖的模型的用戶,掌握LangGraph可能比較耗時。
- 中等可擴展性:雖然LangGraph有效處理NLP密集型任務,但其架構在需要大規(guī)模智能體協(xié)作的系統(tǒng)中可能無法高效擴展。
- 高級AI功能有限:對于涉及機器學習模型訓練、強化學習或?qū)崟r數(shù)據(jù)處理的復雜任務,LangGraph的能力可能有限。
- 配置復雜:對于不熟悉該平臺的用戶,配置LangGraph的工作流可能是一項艱巨的任務。
CrewAI的特點
CrewAI強調(diào)易用性和協(xié)作,是需要AI智能體與人類操作員密切互動環(huán)境的突出選擇。其設計理念圍繞著為非技術用戶簡化復雜操作,同時增強多智能體協(xié)作。
優(yōu)勢:
- 對非技術用戶的直觀設計:拖放界面和預構建模板使其非常用戶友好,降低了非技術團隊的采用門檻。
- 注重人機協(xié)同:優(yōu)化了需要人類操作員和AI智能體無縫協(xié)作的工作流,適用于客戶支持或應急響應系統(tǒng)等場景。
- 實時監(jiān)控和控制:提供強大的工具來實時監(jiān)控AI智能體性能,允許人類操作員在必要時進行干預。
- 多智能體系統(tǒng)的可擴展性:專為管理多智能體環(huán)境而構建,適用于大型操作的擴展。
- 可定制模板:提供可輕松適應特定業(yè)務需求的可定制模板,適合具有獨特操作要求的組織。
挑戰(zhàn):
- 對高度技術應用的適用性有限:其簡單性意味著它可能不足以應對復雜的技術工作流,如檢索增強生成(RAG)或需要深度技術集成的數(shù)據(jù)處理。
- 協(xié)作優(yōu)先于計算效率:對協(xié)作和易用性的強調(diào)有時可能以犧牲計算效率為代價。
- 高級協(xié)作功能的學習曲線:盡管CrewAI用戶友好,但不熟悉多智能體系統(tǒng)的團隊可能需要額外培訓才能有效利用其高級協(xié)作功能。
- 大型部署資源密集:對于擴展操作以包含數(shù)百或數(shù)千個智能體的組織,CrewAI可能需要大量計算資源和人力監(jiān)督。
OpenAI Swarm的特點
OpenAI Swarm專為大規(guī)模、計算密集型任務而設計。其架構支持檢索密集型工作流和實時處理,是需要強大數(shù)據(jù)處理能力行業(yè)的有力工具。
優(yōu)勢:
- 對檢索型工作流的強力支持:在知識檢索、數(shù)據(jù)集成和實時分析至關重要的場景中表現(xiàn)出色。
- 與開源工具的無縫集成:與Chroma和LangChain等開源工具的兼容性增強了其實用性。
- 實時分析和處理:支持高性能數(shù)據(jù)分析,適用于需要快速決策或?qū)崟r數(shù)據(jù)處理的應用。
- 高性能計算能力:能夠處理極高的計算工作負載,使其能夠有效擴展用于大型、數(shù)據(jù)密集型應用。
- 先進的AI模型支持:為強化學習、監(jiān)督學習和深度學習網(wǎng)絡等高級機器學習模型提供強大支持。
挑戰(zhàn):
- 手動配置要求:通常需要廣泛的手動設置才能達到最佳性能,特別是對于專業(yè)用例。
- 高計算需求:雖然OpenAI Swarm的高級功能令人印象深刻,但它們伴隨著高昂的計算成本。
- 與遺留系統(tǒng)集成的復雜性:其高級功能在與較舊或較不靈活的遺留系統(tǒng)協(xié)作時可能會帶來集成挑戰(zhàn)。
- 對較小應用可能過度:對于不需要復雜、數(shù)據(jù)密集型處理的小規(guī)模應用,OpenAI Swarm的高級功能可能過于強大。
- 持續(xù)維護要求:考慮到Swarm的高級功能和計算需求,可能需要持續(xù)維護和微調(diào)以保持系統(tǒng)順利運行。
框架選擇指南
選擇合適的AI智能體框架取決于您的具體業(yè)務需求:
- 選擇LangGraph:如果您的項目圍繞創(chuàng)建或分析文本,LangGraph是完美選擇。其強大的自然語言處理(NLP)能力,結合基于圖的架構,確保了上下文數(shù)據(jù)流的無縫銜接。LangGraph在聊天機器人、虛擬助手等應用中表現(xiàn)出色,特別適合需要維持連貫對話的場景。
- 選擇CrewAI:如果您的業(yè)務專注于自動化團隊任務和改進協(xié)作,CrewAI是理想選擇。其多智能體協(xié)作模型有助于簡化通信和任務委派,非常適合智能工廠、協(xié)調(diào)物流和團隊驅(qū)動項目等行業(yè)。
- 選擇OpenAI Swarm:如果您的業(yè)務處理大型數(shù)據(jù)集并需要能夠通過協(xié)作解決復雜問題的AI系統(tǒng),OpenAI Swarm是最佳選擇。它對金融或醫(yī)療保健等行業(yè)特別有效,這些行業(yè)需要復雜的數(shù)據(jù)處理和復雜的決策制定。憑借其可擴展性和與GPT等高級模型的集成,OpenAI Swarm可以支持實時監(jiān)控或金融建模等大規(guī)模應用。
總結來說:
- 如果需要強大的文本分析和NLP功能,選擇LangGraph。
- 如果想要自動化團隊任務并改進協(xié)作,選擇CrewAI。
- 如果處理復雜數(shù)據(jù)并需要可擴展解決方案,選擇OpenAI Swarm。
每個框架都提供獨特的優(yōu)勢,因此請選擇與您特定業(yè)務需求相符的框架。
功能對比表
下表提供了三個框架在關鍵特性上的對比:
特性 | LangGraph | CrewAI | OpenAI Swarm |
可擴展性 | 中等 | 高 | 非常高 |
協(xié)作支持 | 有限 | 廣泛 | 中等 |
API集成 | 優(yōu)秀 | 良好 | 優(yōu)秀 |
學習模型 | 專注NLP | 通用型 | 高級 |
部署平臺 | 云端和本地 | 多平臺 | 云端優(yōu)化 |
這個對比表可以幫助您快速了解每個框架的優(yōu)勢領域,從而根據(jù)項目需求做出更明智的選擇。
構建基礎聊天機器人
在本節(jié)中,我們將使用LangGraph構建一個基礎的聊天機器人,并集成DeepSeek大模型作為對話引擎。雖然這是一個簡單的示例,但它將展示LangGraph的核心概念和工作流程,為后續(xù)構建更復雜的應用奠定基礎。
環(huán)境準備
在開始之前,我們需要使用uv工具安裝必要的依賴(uv是一個現(xiàn)代化的Python包管理工具,具有更快的安裝速度和更好的依賴解析):
# 使用uv安裝LangGraph和相關依賴
uv pip install -U langgraph langchain python-dotenv typing-extensions接下來,我們需要創(chuàng)建一個??.env??文件來存儲API密鑰。在項目根目錄創(chuàng)建該文件:
# .env文件內(nèi)容
DEEPSEEK_API_KEY=your_deepseek_api_key_here實現(xiàn)基礎聊天機器人
現(xiàn)在,讓我們開始實現(xiàn)一個基礎的聊天機器人。創(chuàng)建一個名為??1-build-basic-chatbot.py??的文件,并添加以下代碼:
from typing import Annotated
from langchain.chat_models import init_chat_model
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
from langgraph.graph.message import add_messages
import os
from dotenv import load_dotenv
# 加載.env文件中的環(huán)境變量
load_dotenv()
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
llm = init_chat_model(
"deepseek-chat", # 使用DeepSeek模型
api_key=os.environ.get("DEEPSEEK_API_KEY")
)
def chatbot(state: State):
return {"messages": [llm.invoke(state["messages"])]}
# 添加節(jié)點和邊
graph_builder.add_node("chatbot", chatbot)
graph_builder.add_edge(START, "chatbot")
graph = graph_builder.compile()
def stream_graph_updates(user_input: str):
for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
for value in event.values():
print("Assistant:", value["messages"][-1].content)
whileTrue:
try:
user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!")
break
stream_graph_updates(user_input)
except KeyboardInterrupt:
print("\nGoodbye!")
break代碼解析
讓我們逐步分析這個簡單聊天機器人的實現(xiàn):
導入必要的庫
from typing import Annotated
from langchain.chat_models import init_chat_model
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
from langgraph.graph.message import add_messages
import os
from dotenv import load_dotenv這里我們導入了必要的庫,包括:
- ?
?typing??? 和??typing_extensions?? 用于類型注釋 - ?
?langchain.chat_models?? 用于初始化聊天模型 - ?
?langgraph.graph?? 提供了構建狀態(tài)圖的核心組件 - ?
?os??? 和??dotenv?? 用于環(huán)境變量管理
加載環(huán)境變量
load_dotenv()這行代碼會從項目根目錄的 ??.env??? 文件中加載環(huán)境變量,包括我們的 ??DEEPSEEK_API_KEY??。
定義狀態(tài)
class State(TypedDict):
messages: Annotated[list, add_messages]這里我們定義了一個 ??State??? 類,它是我們圖中的狀態(tài)表示。在這個簡單的例子中,狀態(tài)只包含一個 ??messages??? 字段,用于存儲對話消息。我們使用 ??add_messages?? 注解來指定這是一個消息列表,并且LangGraph應該使用消息添加的方式來處理它。
創(chuàng)建圖構建器
graph_builder = StateGraph(State)這行創(chuàng)建了一個狀態(tài)圖構建器,它將使用我們定義的 ??State?? 類型。
初始化模型
llm = init_chat_model(
"deepseek-chat", # 使用DeepSeek模型
api_key=os.environ.get("DEEPSEEK_API_KEY")
)這里我們初始化了DeepSeek的聊天模型,直接從環(huán)境變量中獲取API密鑰。
定義節(jié)點函數(shù)
def chatbot(state: State):
return {"messages": [llm.invoke(state["messages"])]}這個函數(shù)定義了聊天機器人節(jié)點的行為。它接收當前狀態(tài)(包含消息歷史),將其傳遞給LLM模型,然后返回模型的響應作為新消息。
構建圖
graph_builder.add_node("chatbot", chatbot)
graph_builder.add_edge(START, "chatbot")
graph = graph_builder.compile()這里我們:
- 添加了一個名為 "chatbot" 的節(jié)點,并將我們的?
?chatbot?? 函數(shù)與其關聯(lián) - 添加了一條從?
?START??(這是LangGraph的一個特殊常量)到 "chatbot" 節(jié)點的邊 - 編譯圖以生成可執(zhí)行的圖實例
實現(xiàn)流式響應
def stream_graph_updates(user_input: str):
for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
for value in event.values():
print("Assistant:", value["messages"][-1].content)這個函數(shù)實現(xiàn)了流式響應處理。它:
- 創(chuàng)建一個初始狀態(tài),其中包含用戶輸入作為消息
- 調(diào)用圖的?
?stream?? 方法來流式處理圖的執(zhí)行 - 對于每個事件,打印出助手的響應
主循環(huán)
while True:
try:
user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!")
break
stream_graph_updates(user_input)
except KeyboardInterrupt:
print("\nGoodbye!")
break最后,我們實現(xiàn)了一個簡單的命令行界面,允許用戶與聊天機器人進行交互。用戶可以輸入消息,程序會調(diào)用我們的 ??stream_graph_updates?? 函數(shù)來處理響應。用戶也可以通過輸入 "quit"、"exit" 或 "q" 來退出程序。
運行聊天機器人
現(xiàn)在我們可以運行這個簡單的聊天機器人了。確保你已經(jīng)在??.env??文件中設置了有效的DeepSeek API密鑰,然后運行:
uv run 1-build-basic-chatbot.py你將看到一個交互式的命令行界面,可以開始與聊天機器人對話:
User: who are you?
Assistant: I’m DeepSeek Chat, your AI assistant created by **DeepSeek**! ??? I’m here to help answer your questions, provide insights, and assist with anything from general knowledge to coding, writing, and more.
Think of me as a friendly, knowledgeable companion—always ready to chat, research, or brainstorm with you! ??
What can I help you with today? ??
User: exit
Goodbye!上訴代碼執(zhí)行 while True 前添加流程圖打印
print(graph.get_graph().draw_mermaid())輸出結果如下:
---
config:
flowchart:
curve: linear
---
graph TD;
__start__([<p>__start__</p>]):::first
chatbot(chatbot)
__end__([<p>__end__</p>]):::last
__start__ --> chatbot;
chatbot --> __end__;
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc添加工具使用能力
在上一節(jié)中,我們構建了一個基礎的聊天機器人,它可以回答用戶的問題,但僅限于模型訓練數(shù)據(jù)中包含的知識。在這一節(jié)中,我們將通過添加工具使用能力來增強我們的聊天機器人,使其能夠訪問外部信息源,回答更廣泛的問題。
環(huán)境準備
在開始之前,我們需要安裝額外的依賴項。我們將使用Tavily搜索API作為我們的外部知識源,它允許我們的聊天機器人在網(wǎng)絡上搜索信息。
uv pip install -U langchain-tavily httpx你還需要獲取一個Tavily API密鑰,可以從Tavily官網(wǎng)注冊獲取。獲取API密鑰后,將其添加到你的??.env??文件中:
DEEPSEEK_API_KEY=your_deepseek_api_key
TAVILY_API_KEY=your_tavily_api_key使用工具增強聊天機器人
現(xiàn)在,讓我們創(chuàng)建一個名為??2-add-tools.py??的文件,實現(xiàn)一個具有工具使用能力的聊天機器人:
from typing import Annotated
from langchain.chat_models import init_chat_model
from langchain_tavily import TavilySearch
from langchain_core.messages import BaseMessage
from typing_extensions import TypedDict
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
import os
from dotenv import load_dotenv
# 加載.env文件中的環(huán)境變量
load_dotenv()
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
llm = init_chat_model(
"deepseek-chat", # 使用DeepSeek模型
api_key=os.environ.get("DEEPSEEK_API_KEY")
)
# 初始化Tavily搜索工具
tool = TavilySearch(max_results=2)
tools = [tool]
# 將工具綁定到LLM
llm_with_tools = llm.bind_tools(tools)
def chatbot(state: State):
return {"messages": [llm_with_tools.invoke(state["messages"])]}
# 添加聊天機器人節(jié)點
graph_builder.add_node("chatbot", chatbot)
# 添加工具節(jié)點
tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)
# 添加條件邊
graph_builder.add_conditional_edges(
"chatbot",
tools_condition,
)
# 工具調(diào)用完成后,返回到聊天機器人節(jié)點
graph_builder.add_edge("tools", "chatbot")
graph_builder.set_entry_point("chatbot")
graph = graph_builder.compile()
# 打印圖結構
print(graph.get_graph().draw_mermaid())
def stream_graph_updates(user_input: str):
for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
for value in event.values():
print("Assistant:", value["messages"][-1].content)
whileTrue:
try:
user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!")
break
stream_graph_updates(user_input)
except KeyboardInterrupt:
print("\nGoodbye!")
break代碼解析
讓我們詳細分析這個增強版聊天機器人的實現(xiàn):
導入新的依賴項
from langchain_tavily import TavilySearch
from langgraph.prebuilt import ToolNode, tools_condition與基礎版本相比,我們添加了兩個關鍵導入:
- ?
?TavilySearch??:Tavily的搜索API客戶端 - ?
?ToolNode??? 和??tools_condition??:LangGraph提供的預構建組件,用于處理工具調(diào)用
初始化搜索工具
tool = TavilySearch(max_results=2)
tools = [tool]這里我們創(chuàng)建了一個Tavily搜索工具實例,并將其放入工具列表中。??max_results=2??參數(shù)指定每次搜索最多返回2個結果。
綁定工具到LLM
llm_with_tools = llm.bind_tools(tools)??bind_tools??方法將工具列表綁定到LLM,使模型知道它可以使用這些工具,并了解如何正確格式化工具調(diào)用。
添加工具節(jié)點
tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)這里我們創(chuàng)建了一個??ToolNode??實例,它是LangGraph提供的預構建節(jié)點,專門用于處理工具調(diào)用。我們將Tavily搜索工具傳遞給它,并將其添加到圖中作為"tools"節(jié)點。
添加條件邊
graph_builder.add_conditional_edges(
"chatbot",
tools_condition,
)這是最關鍵的部分。我們使用??add_conditional_edges???方法添加條件邊,它決定了圖的執(zhí)行流程。??tools_condition??是一個預構建的條件函數(shù),它檢查聊天機器人的輸出是否包含工具調(diào)用:
- 如果包含工具調(diào)用,流程將轉向"tools"節(jié)點
- 如果不包含工具調(diào)用,流程將結束
完成圖的構建
graph_builder.add_edge("tools", "chatbot")
graph_builder.set_entry_point("chatbot")
graph = graph_builder.compile()我們添加了一條從"tools"節(jié)點回到"chatbot"節(jié)點的邊,這樣在工具執(zhí)行完畢后,控制流會回到聊天機器人,讓它處理工具返回的結果。然后我們設置入口點為"chatbot"節(jié)點,并編譯圖。
可視化圖結構
print(graph.get_graph().draw_mermaid())這行代碼會打印出圖的Mermaid格式表示,幫助我們理解圖的結構。
運行聊天機器人
現(xiàn)在我們可以運行這個增強版的聊天機器人了:
uv run 2-add-tools.py運行后,你會首先看到圖的結構表示, 從圖中可以看到,我們的聊天機器人現(xiàn)在有了一個循環(huán)流程:
- 用戶輸入傳遞給聊天機器人節(jié)點
- 如果聊天機器人決定使用工具,控制流轉向工具節(jié)點
- 工具執(zhí)行完畢后,結果返回給聊天機器人
- 聊天機器人處理工具結果并生成最終響應
下面是一個示例交互:
User: 什么是LangGraph的核心組件?
Assistant:
Assistant: {"query": "LangGraph 核心組件", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://cloud.tencent.com/developer/news/2180955", "title": "Agent快速構建框架的langGraph到底是什么及案例 - 騰訊云", "content": "LangGraph是一個使用 LLM 構建有狀態(tài)、多參與者應用程序的庫,用于創(chuàng)建代理和多代理工作流。請在此處查看入門教程。\n\nLangGraph 的靈感來自Pregel和Apache Beam。公共接口靈感來自NetworkX。LangGraph 由 LangChain 的創(chuàng)建者 LangChain Inc 構建,但可以在沒有 LangChain 的情況下使用。\n\nLangGraph核心組件\n\nLangGraph的核心組件包括Graphs、State、Nodes、Edges、Send、Checkpointer。LangGraph有哪些優(yōu)點:可控性、持久性、Human-in-the-loop、ReactAgent。\n\nstate\n\nfrom langgraph.graph import StateGraph\n\nfrom typing import TypedDict, List, Annotated\n\nimport Operator\n\nclass State(TypedDict):\n\n input: str", "score": 0.9403148, "raw_content": null}, {"url": "https://blog.csdn.net/TaloyerG/article/details/142546057", "title": "Langgraph 的Planning Agent 深度解析原創(chuàng) - CSDN博客", "content": "Langgraph 的核心組件包括語言理解模塊、知識庫和規(guī)劃模塊。 1.2.1 語言理解模塊. 語言理解模塊負責解析用戶的自然語言輸入,將其轉化為可供計算機處理的", "score": 0.9348309, "raw_content": null}], "response_time": 1.87}
Assistant: LangGraph的核心組件主要包括以下幾個方面:
1. **Graphs(圖)**:用于構建和管理工作流的結構。
2. **State(狀態(tài))**:用于跟蹤和管理應用程序的狀態(tài)。
3. **Nodes(節(jié)點)**:表示工作流中的單個步驟或操作。
4. **Edges(邊)**:定義節(jié)點之間的關系和流程控制。
5. **Send(發(fā)送)**:用于在節(jié)點之間傳遞數(shù)據(jù)或消息。
6. **Checkpointer(檢查點)**:用于持久化和恢復工作流的狀態(tài)。
此外,LangGraph還支持可控性、持久性、Human-in-the-loop(人工干預)和ReactAgent(反應式代理)等功能特性。
這些組件共同構成了LangGraph的基礎,使其能夠高效地構建和管理有狀態(tài)的多參與者應用程序或代理工作流。
User: exit
Goodbye!小結
在這一節(jié)中,我們成功地增強了聊天機器人,使其具備了使用外部工具的能力。通過集成Tavily搜索API,我們的聊天機器人現(xiàn)在可以:
- 識別需要外部信息的問題
- 自動調(diào)用搜索工具獲取相關信息
- 處理搜索結果并生成基于這些信息的回答
這種增強極大地擴展了聊天機器人的能力范圍,使其不再局限于模型的訓練數(shù)據(jù)。
我們還學習了LangGraph的幾個重要概念:
- 工具綁定(Tool Binding):通過?
?bind_tools??方法將工具與LLM集成 - 預構建組件:使用?
?ToolNode??和??tools_condition??簡化工具處理 - 條件邊:根據(jù)狀態(tài)動態(tài)決定執(zhí)行流程
- 循環(huán)流程:創(chuàng)建包含循環(huán)的復雜工作流
在下一節(jié)中,我們將進一步增強聊天機器人,添加記憶功能,使其能夠記住對話歷史并提供更連貫的回答。
添加記憶功能
在上一節(jié)中,我們?yōu)榱奶鞕C器人添加了使用外部工具的能力。然而,我們的聊天機器人仍然存在一個重要的限制:它不記得之前的對話內(nèi)容。每次新的交互都是從零開始的,這使得進行連貫的多輪對話變得困難。
在這一節(jié)中,我們將通過添加記憶功能來解決這個問題,使聊天機器人能夠記住用戶之前說過的話,并在后續(xù)對話中引用這些信息。
環(huán)境準備
對于這一部分,我們不需要額外的依賴項,因為LangGraph已經(jīng)內(nèi)置了記憶功能。我們將使用??langgraph.checkpoint.memory???模塊中的??MemorySaver??類來實現(xiàn)記憶功能。
使用記憶增強聊天機器人
讓我們創(chuàng)建一個名為??3-add-memory.py??的文件,實現(xiàn)一個具有記憶功能的聊天機器人:
"""LangGraph 教程: 添加記憶功能的聊天機器人
本示例展示了如何使用 LangGraph 的檢查點功能為聊天機器人添加記憶功能,
使其能夠記住對話歷史并在多輪對話中保持上下文。
"""
from typing import Annotated
from langchain.chat_models import init_chat_model
from langchain_tavily import TavilySearch
from langchain_core.messages import BaseMessage
from typing_extensions import TypedDict
# 導入 MemorySaver 用于實現(xiàn)記憶功能
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode, tools_condition
import os
from dotenv import load_dotenv
# 加載.env文件中的環(huán)境變量
load_dotenv()
# 定義狀態(tài)類型,使用 add_messages 注解來自動合并消息列表
class State(TypedDict):
messages: Annotated[list, add_messages] # 消息列表將使用 add_messages reducer 自動合并
# 初始化 DeepSeek 聊天模型
llm = init_chat_model(
"deepseek-chat", # 使用DeepSeek模型
api_key=os.environ.get("DEEPSEEK_API_KEY") # 從環(huán)境變量中獲取API密鑰
)
# 創(chuàng)建狀態(tài)圖構建器
graph_builder = StateGraph(State)
# 初始化Tavily搜索工具
print("\n初始化Tavily搜索工具...")
tool = TavilySearch(max_results=2) # 設置最多返回2個搜索結果
tools = [tool]
# 將工具綁定到LLM
llm_with_tools = llm.bind_tools(tools)
# 定義聊天機器人節(jié)點函數(shù)
def chatbot(state: State):
"""LLM節(jié)點函數(shù),處理用戶輸入并生成響應"""
return {"messages": [llm_with_tools.invoke(state["messages"])]}
# 添加聊天機器人節(jié)點
graph_builder.add_node("chatbot", chatbot)
# 添加工具節(jié)點
tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)
# 添加條件邊
graph_builder.add_conditional_edges(
"chatbot",
tools_condition,
)
# 工具調(diào)用完成后,返回到聊天機器人節(jié)點
graph_builder.add_edge("tools", "chatbot")
graph_builder.set_entry_point("chatbot")
print("\n構建圖并添加記憶功能...")
# 創(chuàng)建內(nèi)存保存器
print("\n創(chuàng)建 MemorySaver 實例作為檢查點保存器...")
memory = MemorySaver() # 在內(nèi)存中保存狀態(tài),適用于開發(fā)和測試
# 使用內(nèi)存保存器編譯圖
print("使用檢查點保存器編譯圖...")
graph = graph_builder.compile(checkpointer=memory) # 將內(nèi)存保存器傳遞給圖
# 打印圖結構
print("\n圖結構如下:")
print(graph.get_graph().draw_mermaid())
# 定義對話線程ID
print("\n設置對話線程 ID = '1'...")
config = {"configurable": {"thread_id": "1"}} # 使用線程ID來標識和區(qū)分不同的對話
# 示例 1: 第一次對話
print("\n示例 1: 第一次對話 - 用戶介紹自己")
user_input = "Hi there! My name is Will."
print(f"\n用戶輸入: '{user_input}'")
# 注意: config 是 stream() 函數(shù)的第二個參數(shù)!
print("使用線程 ID '1' 調(diào)用圖...")
events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config, # 傳遞包含 thread_id 的配置
stream_mode="values",
)
print("\n助理回應:")
for event in events:
event["messages"][-1].pretty_print() # 打印助理的回應
# 示例 2: 測試記憶功能
print("\n\n示例 2: 第二次對話 - 測試記憶功能")
user_input = "Remember my name?"
print(f"\n用戶輸入: '{user_input}'")
# 使用相同的線程ID再次調(diào)用圖
print("使用相同的線程 ID '1' 再次調(diào)用圖...")
events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config, # 使用相同的配置,圖將加載之前保存的狀態(tài)
stream_mode="values",
)
print("\n助理回應 (應該記得用戶名字):")
for event in events:
event["messages"][-1].pretty_print()
# 示例 3: 新對話線程
print("\n\n示例 3: 新對話線程 - 測試線程隔離")
print("創(chuàng)建新的線程 ID = '2'...")
# 使用不同的線程ID
print("使用新的線程 ID '2' 調(diào)用圖...")
events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
{"configurable": {"thread_id": "2"}}, # 使用新的線程ID
stream_mode="values",
)
print("\n助理回應 (不應該記得用戶名字):")
for event in events:
event["messages"][-1].pretty_print()
# 示例 4: 返回第一個線程
print("\n\n示例 4: 返回第一個線程 - 驗證記憶持久性")
print(f"\n用戶輸入: '{user_input}'")
# 再次使用第一個線程ID
print("再次使用線程 ID '1' 調(diào)用圖...")
events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config, # 使用原始線程ID
stream_mode="values",
)
print("\n助理回應 (應該仍然記得用戶名字):")
for event in events:
event["messages"][-1].pretty_print()代碼解析
讓我們詳細分析這個帶有記憶功能的聊天機器人實現(xiàn):
導入新的依賴項
from langgraph.checkpoint.memory import MemorySaver與上一版本相比,我們添加了一個關鍵導入:??MemorySaver??,這是LangGraph提供的內(nèi)存檢查點保存器,用于在對話過程中保存和恢復狀態(tài)。
創(chuàng)建內(nèi)存保存器
memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)這里有兩個關鍵步驟:
- 創(chuàng)建一個?
?MemorySaver??實例,它將在內(nèi)存中存儲圖的狀態(tài) - 在編譯圖時,通過?
?checkpointer??參數(shù)將內(nèi)存保存器傳遞給圖
這樣,圖在執(zhí)行過程中會自動保存狀態(tài),并在下一次調(diào)用時恢復狀態(tài)。
注意:?
?MemorySaver???將狀態(tài)保存在內(nèi)存中,適合開發(fā)和測試。在生產(chǎn)環(huán)境中,你可能需要使用??SqliteSaver???或??PostgresSaver??等持久化存儲方案。
配置對話線程
config = {"configurable": {"thread_id": "1"}}這里我們定義了一個配置對象,其中包含一個??thread_id???。這個ID非常重要,它是用來標識和區(qū)分不同對話的關鍵。當使用相同的??thread_id??調(diào)用圖時,圖會加載之前保存的狀態(tài),從而實現(xiàn)對話的連續(xù)性。
修改流式處理函數(shù)
def stream_graph_updates(user_input: str):
# 注意:config是stream()的第二個位置參數(shù)
for event in graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config,
stream_mode="values",
):
for value in event.values():
print("Assistant:", value["messages"][-1].content)在調(diào)用??graph.stream()??時,我們現(xiàn)在傳遞了三個參數(shù):
- 用戶輸入消息
- 包含?
?thread_id??的配置對象 - 流模式設置
這確保了每次調(diào)用都與特定的對話線程相關聯(lián),從而能夠保持對話的上下文。
運行聊天機器人
現(xiàn)在我們可以運行這個帶有記憶功能的聊天機器人了:
uv run 3-add-memory.py運行后,你會首先看到圖的結構表示,它與上一節(jié)中的結構相同, 圖的結構沒有變化,但現(xiàn)在每次節(jié)點執(zhí)行后,狀態(tài)都會被保存到內(nèi)存中。
下面是一個輸出內(nèi)容,展示了記憶功能的效果:
設置對話線程 ID = '1'...
示例 1: 第一次對話 - 用戶介紹自己
用戶輸入: 'Hi there! My name is Will.'
使用線程 ID '1' 調(diào)用圖...
助理回應:
================================ Human Message =================================
Hi there! My name is Will.
================================== Ai Message ==================================
Hi Will! It's great to meet you. How can I assist you today?
示例 2: 第二次對話 - 測試記憶功能
用戶輸入: 'Remember my name?'
使用相同的線程 ID '1' 再次調(diào)用圖...
助理回應 (應該記得用戶名字):
================================ Human Message =================================
Remember my name?
================================== Ai Message ==================================
Of course, Will! I’ll remember your name for the rest of our conversation. How can I help you today? ??
示例 3: 新對話線程 - 測試線程隔離
創(chuàng)建新的線程 ID = '2'...
使用新的線程 ID '2' 調(diào)用圖...
助理回應 (不應該記得用戶名字):
================================ Human Message =================================
Remember my name?
================================== Ai Message ==================================
I don’t have the ability to remember personal details like names between interactions. However, you can tell me your name, and I’ll happily use it for the rest of our current conversation! What should I call you?
示例 4: 返回第一個線程 - 驗證記憶持久性
用戶輸入: 'Remember my name?'
再次使用線程 ID '1' 調(diào)用圖...
助理回應 (應該仍然記得用戶名字):
================================ Human Message =================================
Remember my name?
================================== Ai Message ==================================
Got it, Will! I’ll keep your name in mind while we chat. Let me know how I can assist you! ??這個示例展示了 LangGraph 的記憶功能如何工作:
- 使用相同的 thread_id 可以保持對話上下文
- 不同的 thread_id 創(chuàng)建獨立的對話線程
- MemorySaver 使狀態(tài)在多次調(diào)用之間持久化
小結
在這一節(jié)中,我們成功地為聊天機器人添加了記憶功能,使其能夠記住對話歷史并提供更連貫的回答。這是通過LangGraph的檢查點功能實現(xiàn)的,它允許我們在每次交互后保存圖的狀態(tài),并在后續(xù)交互中恢復該狀態(tài)。這種能力對于構建真正智能的對話系統(tǒng)至關重要,因為它使AI能夠維持上下文并提供個性化的用戶體驗。
我們學習了LangGraph的幾個重要概念:
- 檢查點(Checkpointing):使用?
?MemorySaver??在內(nèi)存中保存圖的狀態(tài),為應用提供持久性。在生產(chǎn)環(huán)境中,可以替換為持久化存儲解決方案。 - 線程ID(Thread ID):用于標識和區(qū)分不同的對話,實現(xiàn)多用戶場景下的會話隔離。
- 配置對象(Config):在調(diào)用圖時傳遞額外的配置信息,靈活控制執(zhí)行行為。
這些功能共同構成了LangGraph強大的狀態(tài)管理能力,為構建復雜的AI應用奠定了基礎。
總結
通過本教程,我們從零開始構建了一個功能完善的聊天機器人,逐步增強其能力:從基礎的對話功能,到工具集成,再到記憶管理。這個漸進式的開發(fā)過程展示了LangGraph作為狀態(tài)機框架的強大靈活性和實用價值。
本文轉載自???AI 博物院??? 作者:longyunfeigu

















