• <tfoot id="ukgsw"><input id="ukgsw"></input></tfoot>
    
    • 久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
      分享

      徹底搞懂LangGraph:構建強大的Multi-Agent多智能體應用的LangChain新利器 【1】

       天承辦公室 2024-04-12 發布于北京

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

      圖片

      我們會用一系列文章深入LangGraph,結合官方例子介紹與剖析其在幾個重點Agent方向的應用。

      • LangGraph誕生的動力及設計思想

      • LangGraph應用:增強的RAG應用

      • LangGraph應用:自修復代碼助手

      • LangGraph應用:Multi-Agent系統

      • LangGraph應用:構建Web Agents

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


      PART 01

      圖片
      圖片

      預備知識


      【LangChain中的鏈與LCEL】

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

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

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

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

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

      對于最常見的RAG應用來說,使用LCEL也無非是在此之上增加一個檢索相關文檔的動作,類似:

      chain = setup_and_retrieval | prompt | model | output_parser

      這里很清晰地看到一個簡單的RAG應用處理過程:檢索關聯文檔 => 組裝Prompt => 調用大模型 => 輸出處理。

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

      【LCEL構建與調度Agent】

      那么如何用LCEL來創建一個AI Agent并調度運行呢?以最常見的React(推理&行動)范式的Agent來說,相對于Chain需要擴展的能力有:

      • 增加工具使用能力。這體現在Prompt中需要注入可用工具信息,并能自動調用工具獲得結果。

      • 增加“循環”能力。Agent的運行通常需要多次Reason(推理)-Act(行動)的反復與循環,直到完成任務。

      以LCEL來組裝并創建運行一個Agent的簡單過程如下:

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

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

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

      注意到,相對于Chain.invoke()直接運行,這里的Agent_executor的作用就是為了能夠實現多次循環ReAct的動作,以最終完成任務。

      【什么是圖(Graph)】

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

      • 圖是表示多個元素及其之間關系的一種結構。其特點是,任何兩個元素之間都可以直接發生聯系,所以適合表達更復雜的元素關系。

      • 圖的基本表示就是N個元素(節點/頂點)及這些元素之間的關系(邊)的集合。

        圖片

      • 有向無環圖(Directed Acyclic Graph,DAG):有向指的是圖中的“邊”有方向;無環指的是無法從某個節點經過若干“邊”返回這個節點。

        其他的一些圖的理論,包括不同類型圖的存儲結構、相關算法等,這里對理解LangGraph無關緊要。


      PART 02

      圖片
      圖片

      LangGraph的驅動力


      即然上文介紹的LCEL已經很強大,但是為什么還需要LangGraph呢?基于LCEL構建的Chain與Agent又存在哪些不足呢?

      * 鏈(Chain):無法滿足在循環中調用LLM以完成任務。

      上文中,我們可以輕易地使用LCEL來快速創建一個鏈,但是很顯然的一個問題是:如果我們把鏈中的組件想象成Graph中的節點,組件之間的聯系想象成Graph中的邊,那么這個鏈就是一個有向無環圖(DAG)。即在一次Chain運行中,一個調用節點無法重復/循環進入。

      圖片

      那么為什么需要將循環引入運行時呢?考慮一個增強的RAG應用:

      圖片

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

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

      其他一些典型的依賴“循環”的場景包括:

      • 代碼生成時的自我糾正:當借助LLM自動生成軟件代碼時,根據代碼執行的結果進行自我反省,并要求LLM重新生成代碼。

      • Web訪問自動導航:每當進入下一界面時,需要借助多模態模型來決定下一步的動作(點擊、滾動、輸入等),直至完成導航。

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

      那么,如果我們需要在循環中調用LLM能力,就需要借助于AgentExecutor。其調用的過程主要就是兩個步驟:

      1. 通過大模型來決定采取什么行動,使用什么工具,或者向用戶輸出響應(如運行結束時);

      2. 執行1步驟中的行動,比如調用某個工具,并把結果繼續交給大模型來決定,即返回步驟1;

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

      • 某個Agent要求首先強制調用某個Tool

      • 在 Agent運行過程中增加人機交互步驟

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

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

      所以,讓我們簡單總結LangGraph誕生的動力:LangChain簡單的鏈(Chain)不具備“循環”能力;而AgentExecutor調度的Agent運行又過于“黑盒”。因此需要一個具備更精細控制能力的框架來支持更復雜場景的LLM應用。


      PART 03

      圖片
      圖片

      LangGraph的設計思想


      LangGraph并非一個獨立于Langchain的新框架,它是基于Langchain之上構建的一個擴展庫,可以與Langchain現有的鏈、LCEL等無縫協作。LangGraph能夠協調多個Chain、Agent、Tool等共同協作來完成輸入任務,支持LLM調用“循環”以及Agent過程的更精細化的控制。

      LangGraph的實現方式是把之前基于AgentExecutor的黑盒調用過程用一種新的形式來構建:狀態圖(StateGraph)。把基于LLM的任務(比如RAG、代碼生成等)細節用Graph進行精確的定義(定義圖的節點與邊),最后基于這個圖來編譯生成應用;在任務運行過程中,維持一個中央狀態對象(state),會根據節點的跳轉不斷更新,狀態包含的屬性可自行定義。

      我們用官方的一個增強的RAG應用的Graph來幫助理解:

      圖片

      這個Graph中體現了LangGraph的幾個基本概念:

      • StateGraph:這是代表整個狀態圖的基礎類。

      • Nodes:節點。在有了圖之后,可以向圖中添加節點,節點通常是一個可調用的函數、一個可運行的Chain或者Agent。有一個特殊的節點叫END,進入這個節點,代表運行結束。

      • 在上圖中,推理函數調用、調用檢索器、生成響應內容、問題重寫等都是其中的任務節點。

      • Edges:邊。有了節點后,需要向圖中添加邊,邊代表從上一個節點跳轉到下一個節點的關系。目前有三種類型的邊:

      • Starting Edge:一種特殊的邊。用來定義任務運行的開始節點,所以它沒有上一個節點。

      • Normal Edge:普通邊。代表上一個節點運行完成后立即進入下一個節點。比如在調用Tools后獲得結果后,立刻進入LLM推理節點。

      • Conditional Edge:條件邊。代表上一個節點運行完成后,需要根據條件跳轉到某個節點,因此這種邊不僅需要上游節點、下游節點,還需要一個條件函數,根據條件函數的返回來決定下游節點。

      在上圖中,Check Relevance就是一個條件邊,它的上游節點是檢索相關文檔,條件函數是判斷文檔是否相關,如果相關,則進入下游節點【產生回答】;如果不相關,則進入下游節點【重寫輸入問題】。

      在構建好StateGraph,并增加Node和Edge后,可以通過compile編譯成可運行的應用:

      app = graph.compile()

      接下來你就可以調用這個app來完成你的任務。


      PART 04

      圖片
      圖片

      LangGraph構建基礎Agent


      我們可以粗暴的認為LangGraph就是把現在黑盒的AgentExecutor揉碎掰開,允許你定義內部的細節結構(用圖的方式),從而實現更強大的功能。那么我們當然可以用LangGraph來重新實現原來的AgentExecutor,即實現一個最基礎的ReAct范式的Agent應用。

      對應的Graph如下:

      圖片

      簡單的實現代碼如下(省略了部分細節):

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

      # 兩個節點

      #節點1: 推理節點,調用LLM決定action,省略了runreason細節
      workflow.add_node('reason', run_reason)

      #節點2: 行動節點,調用tools執行action,省略executetools細節
      workflow.add_node('action', execute_tools)

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

      #條件邊:根據推理節點的結果決定下一步
      workflow.add_conditional_edges(
      'reason',
      should_continue, #條件判斷函數(自定義,根據狀態中的推理結果判斷)
      {
      'continue': 'action', #如果條件函數返回continue,進action節點
      'end': END, #如果條件函數返回end,進END節點
      },
      )

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

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

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

      代碼中的注釋對graph構建的細節做了解釋。顯然,這要比簡單的使用agentExecutor要復雜的多,但同時也展示了LangGraph在構建LLM應用時強大的控制能力:通過Graph的定義,可以對一個LLM應用的處理過程進行非常細節的編排設計,從而滿足大量復雜場景的AI Agent應用。

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

      圖片

      END

        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發表

        請遵守用戶 評論公約

        類似文章 更多

        主站蜘蛛池模板: 久久精品亚洲乱码伦伦中文| 无码国产69精品久久久久孕妇| 最近2019中文字幕大全视频1| 欧洲精品久久久AV无码电影| 99国产成人综合久久精品| 国产中文字幕一区二区| 亚洲愉拍一区二区三区| 国产精品黑色丝袜在线观看| 亚洲欧美偷国产日韩| 国产精品久久久久影院| 中文字幕人妻在线精品| 无码精品国产VA在线观看DVD| 中文字幕av无码免费一区| 丰满爆乳在线播放| 一本av高清一区二区三区| 激情 自拍 另类 亚洲| 成人片黄网站色大片免费观看软件| 成人免费无码大片A毛片抽搐色欲| 成人午夜福利视频镇东影视| 国厂精品114福利电影免费| 国产亚洲精品国产福APP| 精品偷拍一区二区三区| 国产精品 视频一区 二区三区| 亚洲欧美高清在线精品一区二区| 亚洲AV无码不卡私人影院| 亚洲欧美自偷自拍视频图片| 亚洲成AV人片在线观看麦芽| 国产中年熟女大集合| 国产成人无码区免费内射一片色欲| 欧美老少配性行为| 五月丁香啪啪| 人妻少妇久久久久久97人妻| 国产亚洲精品第一综合另类无码无遮挡又大又爽又黄的视频 | 亚洲一区中文字幕人妻| 成在线人视频免费视频| 超清无码熟妇人妻AV在线电影| 麻豆成人传媒一区二区| 色噜噜亚洲男人的天堂| 久久影院午夜伦手机不四虎卡| 国产线播放免费人成视频播放| 国内精品国产成人国产三级|