午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

徹底搞懂LangGraph:構(gòu)建強(qiáng)大的Multi-Agent多智能體應(yīng)用的LangChain新利器 【1】

 天承辦公室 2024-04-12 發(fā)布于北京

上個(gè)月LangChain剛剛發(fā)布了正式的0.1穩(wěn)定版本(沒錯(cuò),是0.1而不是1.0),在版本公告里面首當(dāng)其沖宣布的最重要更新,是在這個(gè)版本里面引入了一個(gè)最新庫 - LangGraph。這是一個(gè)面向當(dāng)前LLM開發(fā)領(lǐng)域最火熱的AI Agent開發(fā)與控制的開發(fā)庫,也是LangChain試圖用來彌補(bǔ)其在Agent開發(fā)、特別是復(fù)雜的多Agent系統(tǒng)定制方面的不足的重大嘗試,相信也會(huì)成為LangChain在2024升級更新的重點(diǎn)領(lǐng)域!

圖片

我們會(huì)用一系列文章深入LangGraph,結(jié)合官方例子介紹與剖析其在幾個(gè)重點(diǎn)Agent方向的應(yīng)用。

  • LangGraph誕生的動(dòng)力及設(shè)計(jì)思想

  • LangGraph應(yīng)用:增強(qiáng)的RAG應(yīng)用

  • LangGraph應(yīng)用:自修復(fù)代碼助手

  • LangGraph應(yīng)用:Multi-Agent系統(tǒng)

  • LangGraph應(yīng)用:構(gòu)建Web Agents

由于官方文檔較為晦澀,加上LangChain一貫的“重量級”風(fēng)格。為了更好地幫助深入淺出的理解LangGraph,并照顧到?jīng)]有LangChain基礎(chǔ)的朋友,我們首先來了解一些“預(yù)備知識”。


PART 01

圖片
圖片

預(yù)備知識


【LangChain中的鏈與LCEL】

Chain(鏈)是LangChain中最核心的概念之一(看名字就知道)。簡單的說,就是把自然語言輸入、關(guān)聯(lián)知識檢索、Prompt組裝、可用Tools信息、大模型調(diào)用、輸出格式化等這些LLM 應(yīng)用中的常見動(dòng)作,組裝成一個(gè)可以運(yùn)行的“鏈”式過程。鏈可以直接調(diào)用,也可以用來進(jìn)一步構(gòu)建更強(qiáng)大的Agent。

LCEL即LangChain Express Language,即LangChain表達(dá)語言。這是LangChain提供的一種簡潔的、用于組裝上述“鏈”的聲明性方式。

我們看一個(gè)官方使用LCEL“組裝”Chain的例子就明白:

prompt = ChatPromptTemplate.from_template('講一個(gè)關(guān)于 {topic} 的笑話')
model = ChatOpenAI(model='gpt-4')
output_parser = StrOutputParser()
chain = prompt | model | output_parser
#調(diào)用chain
chain.invoke({'topic': '冰淇淋'})

這個(gè)官方的例子中,把提示(prompt)、大模型(model)、輸出解析(output_parser)幾個(gè)組件使用管道符號“|”鏈接在一起,上個(gè)組件的輸出作為下一個(gè)組件的輸入,一起形成了一個(gè)鏈。

對于最常見的RAG應(yīng)用來說,使用LCEL也無非是在此之上增加一個(gè)檢索相關(guān)文檔的動(dòng)作,類似:

chain = setup_and_retrieval | prompt | model | output_parser

這里很清晰地看到一個(gè)簡單的RAG應(yīng)用處理過程:檢索關(guān)聯(lián)文檔 => 組裝Prompt => 調(diào)用大模型 => 輸出處理。

最后總結(jié)一下:LCEL就是LangChain提供用來組裝Chain的一種簡單表示方式。用這種方式組裝鏈,可以自動(dòng)獲得諸如批量、流輸出、并行、異步等一系列能力;而且鏈可以進(jìn)一步通過LCEL組裝成更復(fù)雜的鏈與Agent。

【LCEL構(gòu)建與調(diào)度Agent】

那么如何用LCEL來創(chuàng)建一個(gè)AI Agent并調(diào)度運(yùn)行呢?以最常見的React(推理&行動(dòng))范式的Agent來說,相對于Chain需要擴(kuò)展的能力有:

  • 增加工具使用能力。這體現(xiàn)在Prompt中需要注入可用工具信息,并能自動(dòng)調(diào)用工具獲得結(jié)果。

  • 增加“循環(huán)”能力。Agent的運(yùn)行通常需要多次Reason(推理)-Act(行動(dòng))的反復(fù)與循環(huán),直到完成任務(wù)。

以LCEL來組裝并創(chuàng)建運(yùn)行一個(gè)Agent的簡單過程如下:

'''
定義Agent需要使用的Tools
'''
@tool
def search(query: str) -> str:
'''此處省略'''

'''
LCEL創(chuàng)建一個(gè)Agent,與Chain類似
'''
agent = (
{input:{輸入信息}, agent_scratchpad:{中間步驟}}
| prompt
| model
| AgentOutputParser()
)

'''
注意:Agent需要使用agent_executor調(diào)用,以增加上述兩個(gè)能力
'''
agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True)
agent_executor.invoke({'input': 'whats the weather in New york?'})

注意到,相對于Chain.invoke()直接運(yùn)行,這里的Agent_executor的作用就是為了能夠?qū)崿F(xiàn)多次循環(huán)ReAct的動(dòng)作,以最終完成任務(wù)。

【什么是圖(Graph)】

圖是計(jì)算機(jī)科學(xué)中的一種數(shù)據(jù)結(jié)構(gòu)。大部分人可能都接觸過一些基本的數(shù)據(jù)結(jié)構(gòu),比如隊(duì)列(Queue)、堆棧(Stack)、鏈表(List)或者樹(Tree)等,圖(Graph)也是其中的一種相對復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。我們無意在此普及圖的數(shù)據(jù)結(jié)構(gòu)知識,你只需要了解的圖的幾個(gè)基本知識:

  • 圖是表示多個(gè)元素及其之間關(guān)系的一種結(jié)構(gòu)。其特點(diǎn)是,任何兩個(gè)元素之間都可以直接發(fā)生聯(lián)系,所以適合表達(dá)更復(fù)雜的元素關(guān)系。

  • 圖的基本表示就是N個(gè)元素(節(jié)點(diǎn)/頂點(diǎn))及這些元素之間的關(guān)系(邊)的集合。

    圖片

  • 有向無環(huán)圖(Directed Acyclic Graph,DAG):有向指的是圖中的“邊”有方向;無環(huán)指的是無法從某個(gè)節(jié)點(diǎn)經(jīng)過若干“邊”返回這個(gè)節(jié)點(diǎn)。

    其他的一些圖的理論,包括不同類型圖的存儲(chǔ)結(jié)構(gòu)、相關(guān)算法等,這里對理解LangGraph無關(guān)緊要。


PART 02

圖片
圖片

LangGraph的驅(qū)動(dòng)力


即然上文介紹的LCEL已經(jīng)很強(qiáng)大,但是為什么還需要LangGraph呢?基于LCEL構(gòu)建的Chain與Agent又存在哪些不足呢?

* 鏈(Chain):無法滿足在循環(huán)中調(diào)用LLM以完成任務(wù)。

上文中,我們可以輕易地使用LCEL來快速創(chuàng)建一個(gè)鏈,但是很顯然的一個(gè)問題是:如果我們把鏈中的組件想象成Graph中的節(jié)點(diǎn),組件之間的聯(lián)系想象成Graph中的邊,那么這個(gè)鏈就是一個(gè)有向無環(huán)圖(DAG)。即在一次Chain運(yùn)行中,一個(gè)調(diào)用節(jié)點(diǎn)無法重復(fù)/循環(huán)進(jìn)入。

圖片

那么為什么需要將循環(huán)引入運(yùn)行時(shí)呢?考慮一個(gè)增強(qiáng)的RAG應(yīng)用:

圖片

在這個(gè)RAG應(yīng)用設(shè)計(jì)中,我們可以對語義檢索出來的關(guān)聯(lián)文檔(上下文)進(jìn)行評估:如果評估的文檔質(zhì)量很差,可以對檢索的問題進(jìn)行重寫(Rewrite,比如把輸入的問題結(jié)合對話歷史用更精確的方式來表達(dá)),并把重寫結(jié)果重新交給檢索器,檢索出新的關(guān)聯(lián)文檔,這樣有助于獲得更精確的結(jié)果。

這里把Rewrite的問題重新交給檢索器,就是一個(gè)典型的“循環(huán)”動(dòng)作。而在目前LangChain的簡單鏈中是無法支持的。

其他一些典型的依賴“循環(huán)”的場景包括:

  • 代碼生成時(shí)的自我糾正:當(dāng)借助LLM自動(dòng)生成軟件代碼時(shí),根據(jù)代碼執(zhí)行的結(jié)果進(jìn)行自我反省,并要求LLM重新生成代碼。

  • Web訪問自動(dòng)導(dǎo)航:每當(dāng)進(jìn)入下一界面時(shí),需要借助多模態(tài)模型來決定下一步的動(dòng)作(點(diǎn)擊、滾動(dòng)、輸入等),直至完成導(dǎo)航。

* AgentExecutor:盡管支持“循環(huán)”,但缺乏精確控制能力。

那么,如果我們需要在循環(huán)中調(diào)用LLM能力,就需要借助于AgentExecutor。其調(diào)用的過程主要就是兩個(gè)步驟:

  1. 通過大模型來決定采取什么行動(dòng),使用什么工具,或者向用戶輸出響應(yīng)(如運(yùn)行結(jié)束時(shí));

  2. 執(zhí)行1步驟中的行動(dòng),比如調(diào)用某個(gè)工具,并把結(jié)果繼續(xù)交給大模型來決定,即返回步驟1;

這里的AgentExecute存在的問題是:過于黑盒,所有的決策過程隱藏在AgentExecutor背后,缺乏更精細(xì)的控制能力,在構(gòu)建復(fù)雜Agent的時(shí)候受限。這些精細(xì)化的控制要求比如:

  • 某個(gè)Agent要求首先強(qiáng)制調(diào)用某個(gè)Tool

  • 在 Agent運(yùn)行過程中增加人機(jī)交互步驟

  • 能夠靈活更換Prompt或者背后的LLM

  • 多Agent(Multi-Agent)智能體構(gòu)建的需求,即多個(gè)Agent協(xié)作完成任務(wù)的場景支持。(這也是Langchain相對于競爭對手Autogen等最薄弱的能力之一,也是眾多開發(fā)者千呼萬喚的特性)

所以,讓我們簡單總結(jié)LangGraph誕生的動(dòng)力:LangChain簡單的鏈(Chain)不具備“循環(huán)”能力;而AgentExecutor調(diào)度的Agent運(yùn)行又過于“黑盒”。因此需要一個(gè)具備更精細(xì)控制能力的框架來支持更復(fù)雜場景的LLM應(yīng)用。


PART 03

圖片
圖片

LangGraph的設(shè)計(jì)思想


LangGraph并非一個(gè)獨(dú)立于Langchain的新框架,它是基于Langchain之上構(gòu)建的一個(gè)擴(kuò)展庫,可以與Langchain現(xiàn)有的鏈、LCEL等無縫協(xié)作。LangGraph能夠協(xié)調(diào)多個(gè)Chain、Agent、Tool等共同協(xié)作來完成輸入任務(wù),支持LLM調(diào)用“循環(huán)”以及Agent過程的更精細(xì)化的控制。

LangGraph的實(shí)現(xiàn)方式是把之前基于AgentExecutor的黑盒調(diào)用過程用一種新的形式來構(gòu)建:狀態(tài)圖(StateGraph)。把基于LLM的任務(wù)(比如RAG、代碼生成等)細(xì)節(jié)用Graph進(jìn)行精確的定義(定義圖的節(jié)點(diǎn)與邊),最后基于這個(gè)圖來編譯生成應(yīng)用;在任務(wù)運(yùn)行過程中,維持一個(gè)中央狀態(tài)對象(state),會(huì)根據(jù)節(jié)點(diǎn)的跳轉(zhuǎn)不斷更新,狀態(tài)包含的屬性可自行定義。

我們用官方的一個(gè)增強(qiáng)的RAG應(yīng)用的Graph來幫助理解:

圖片

這個(gè)Graph中體現(xiàn)了LangGraph的幾個(gè)基本概念:

  • StateGraph:這是代表整個(gè)狀態(tài)圖的基礎(chǔ)類。

  • Nodes:節(jié)點(diǎn)。在有了圖之后,可以向圖中添加節(jié)點(diǎn),節(jié)點(diǎn)通常是一個(gè)可調(diào)用的函數(shù)、一個(gè)可運(yùn)行的Chain或者Agent。有一個(gè)特殊的節(jié)點(diǎn)叫END,進(jìn)入這個(gè)節(jié)點(diǎn),代表運(yùn)行結(jié)束。

  • 在上圖中,推理函數(shù)調(diào)用、調(diào)用檢索器、生成響應(yīng)內(nèi)容、問題重寫等都是其中的任務(wù)節(jié)點(diǎn)。

  • Edges:邊。有了節(jié)點(diǎn)后,需要向圖中添加邊,邊代表從上一個(gè)節(jié)點(diǎn)跳轉(zhuǎn)到下一個(gè)節(jié)點(diǎn)的關(guān)系。目前有三種類型的邊:

  • Starting Edge:一種特殊的邊。用來定義任務(wù)運(yùn)行的開始節(jié)點(diǎn),所以它沒有上一個(gè)節(jié)點(diǎn)。

  • Normal Edge:普通邊。代表上一個(gè)節(jié)點(diǎn)運(yùn)行完成后立即進(jìn)入下一個(gè)節(jié)點(diǎn)。比如在調(diào)用Tools后獲得結(jié)果后,立刻進(jìn)入LLM推理節(jié)點(diǎn)。

  • Conditional Edge:條件邊。代表上一個(gè)節(jié)點(diǎn)運(yùn)行完成后,需要根據(jù)條件跳轉(zhuǎn)到某個(gè)節(jié)點(diǎn),因此這種邊不僅需要上游節(jié)點(diǎn)、下游節(jié)點(diǎn),還需要一個(gè)條件函數(shù),根據(jù)條件函數(shù)的返回來決定下游節(jié)點(diǎn)。

在上圖中,Check Relevance就是一個(gè)條件邊,它的上游節(jié)點(diǎn)是檢索相關(guān)文檔,條件函數(shù)是判斷文檔是否相關(guān),如果相關(guān),則進(jìn)入下游節(jié)點(diǎn)【產(chǎn)生回答】;如果不相關(guān),則進(jìn)入下游節(jié)點(diǎn)【重寫輸入問題】。

在構(gòu)建好StateGraph,并增加Node和Edge后,可以通過compile編譯成可運(yùn)行的應(yīng)用:

app = graph.compile()

接下來你就可以調(diào)用這個(gè)app來完成你的任務(wù)。


PART 04

圖片
圖片

LangGraph構(gòu)建基礎(chǔ)Agent


我們可以粗暴的認(rèn)為LangGraph就是把現(xiàn)在黑盒的AgentExecutor揉碎掰開,允許你定義內(nèi)部的細(xì)節(jié)結(jié)構(gòu)(用圖的方式),從而實(shí)現(xiàn)更強(qiáng)大的功能。那么我們當(dāng)然可以用LangGraph來重新實(shí)現(xiàn)原來的AgentExecutor,即實(shí)現(xiàn)一個(gè)最基礎(chǔ)的ReAct范式的Agent應(yīng)用。

對應(yīng)的Graph如下:

圖片

簡單的實(shí)現(xiàn)代碼如下(省略了部分細(xì)節(jié)):

# 定義一個(gè)Graph,傳入state定義(參考上圖state屬性)
workflow = StateGraph(AgentState)

# 兩個(gè)節(jié)點(diǎn)

#節(jié)點(diǎn)1: 推理節(jié)點(diǎn),調(diào)用LLM決定action,省略了runreason細(xì)節(jié)
workflow.add_node('reason', run_reason)

#節(jié)點(diǎn)2: 行動(dòng)節(jié)點(diǎn),調(diào)用tools執(zhí)行action,省略executetools細(xì)節(jié)
workflow.add_node('action', execute_tools)

#入口節(jié)點(diǎn):總是從推理節(jié)點(diǎn)開始
workflow.set_entry_point('reason')

#條件邊:根據(jù)推理節(jié)點(diǎn)的結(jié)果決定下一步
workflow.add_conditional_edges(
'reason',
should_continue, #條件判斷函數(shù)(自定義,根據(jù)狀態(tài)中的推理結(jié)果判斷)
{
'continue': 'action', #如果條件函數(shù)返回continue,進(jìn)action節(jié)點(diǎn)
'end': END, #如果條件函數(shù)返回end,進(jìn)END節(jié)點(diǎn)
},
)

#普通邊:action結(jié)束后,總是返回reason
workflow.add_edge('action', 'reason')

#編譯成app
app = workflow.compile()

#可以調(diào)用app了,并使用流式輸出
inputs = {'input': 'you task description', 'chat_history': []}
for s in app.stream(inputs):
print(list(s.values())[0])
print('----')

代碼中的注釋對graph構(gòu)建的細(xì)節(jié)做了解釋。顯然,這要比簡單的使用agentExecutor要復(fù)雜的多,但同時(shí)也展示了LangGraph在構(gòu)建LLM應(yīng)用時(shí)強(qiáng)大的控制能力:通過Graph的定義,可以對一個(gè)LLM應(yīng)用的處理過程進(jìn)行非常細(xì)節(jié)的編排設(shè)計(jì),從而滿足大量復(fù)雜場景的AI Agent應(yīng)用。

由于LangGraph剛推出不久,一些細(xì)節(jié)與易用性在后期也會(huì)不斷完善。比如未來是否會(huì)提供更直觀的定義界面等,也值得期待。在后續(xù)的文章中,我們將逐漸實(shí)踐幾個(gè)代表性場景下的LangGraph的應(yīng)用,比如代碼助手,自省式RAG,多Agent應(yīng)用等,敬請期待。

圖片

END

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多