LangChain Agent:賦予 LLM 行動力的神祕力量

image

LangChain Agent 是什麼?有什麼用?基本原理是什麼?

那麼多 Agent 類型在實際開發中又該如何選擇?

如果以上有你想知道的答案,那麼請往下看

那麼如果沒有呢?看看嘛,反正又不喫虧 (~ ̄▽ ̄)~

What & Why

丹尼爾:蛋兄,我又來了。今天主要想跟你深入瞭解下 LangChain 中的 Agent

蛋先生:Agent,知道中文是什麼意思嗎?

丹尼爾:這可難不倒我,我可是過了英文 8 (′▽`〃)... 4 級的男人。不就是代理的意思嘛

蛋先生:哈哈,你還挺自信的嘛。沒錯,Agent 就是代理。代理啥意思呢?小明代理小紅去辦理事務,就是小明因某些原因沒法做這件事,需要小紅出面去做這件事

丹尼爾:蛋兄,恕小弟我愚昧,還請更通俗易懂地展開說說

蛋先生:你知道大腦和身體的關係嗎?

丹尼爾:大腦會思考,而身體會根據大腦的指令行動,比如拿東西,走路等。

蛋先生:說得沒錯。大腦本身缺乏行動能力,所以需要有身體來實現它的意圖,這裏可以把身體看成是大腦的代理

丹尼爾:這我明白,所以 Agent 就是 ...

蛋先生:LLM 擁有強大的推理能力,就像我們的大腦。Agent 嘛,當然就像我們的身體。通過 Agent,就可以讓 LLM 走起來。(⚆_⚆) 哦不,就可以讓 LLM 擁有推理能力之外的其它能力

丹尼爾:概念上是理解了,這個推理能力之外的其它能力都有哪些呢,能舉一個例子讓我更加清晰嗎?

蛋先生:你可以試下直接詢問 LLM 當前時間,你覺得它回答得了嗎?

丹尼爾:哦,這肯定不行,就算能回答也是胡說八道

蛋先生:恩,LLM 的知識受限於訓練數據,實時信息是它的軟肋。但有了 Agent,這個問題就難不倒它了

How

Agent 的基本原理

丹尼爾:哇哦,Agent 擁有讓 LLM “走”起來的神奇力量,我對它是如何實現的好奇不已!

蛋先生:老規矩,先來瞧瞧一段代碼示例

import os
from langchain import hub
from langchain.agents import create_structured_chat_agent
from langchain.agents import AgentExecutor
from datetime import datetime
from langchain.tools import tool
from langchain_community.chat_models.fireworks import ChatFireworks

@tool
def get_current_time() -> str:
    """Get the current time."""
    return str(datetime.now().strftime("%Y年%m月%d日 %H時%M分"))


os.environ["FIREWORKS_API_KEY"] = '<FIREWORKS_API_KEY>'
fw_chat = ChatFireworks(model="accounts/fireworks/models/llama-v2-70b-chat")
tools = [get_current_time]
prompt = hub.pull("hwchase17/structured-chat-agent")

agent = create_structured_chat_agent(fw_chat, tools, prompt)

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke({"input": "What's the date today?"})

丹尼爾:每個單詞我都懂,畢竟我是過了英語 4 級的男人。但...你還是趕緊解釋一下吧!

蛋先生:代碼嘛,我就不多解釋了。我只想通過簡單地拆解下上面代碼的內部工作流程,從而介紹 Agent 是如何運作的

第一步,Agent 將用戶的問題直接扔給 LLM

image

第二步,LLM 推理出可以使用 get_current_time 這個小工具來回答這個問題,於是它用 JSON 的形式告訴 Agent 去執行這個工具。

image

第三步,Agent 將 get_current_time 工具的執行結果呈現給 LLM

image

最後一步,LLM 把工具的輸出內容進行總結,然後把答案扔給 Agent。Agent 把這個答案呈現給用戶,大功告成!

image

這是一個最簡單的流程。然而,當面臨更復雜的問題時,LLM 會將問題分解爲若干子問題,然後通過不斷循環第二步和第三步,逐個解決這些子問題,最後得到一個最終的答案。

丹尼爾:LLM 就是“大腦”,Agent 就是“身體”,Tool 就是“手腳”,這下完全理解了。那 LLM 的回答爲何可以如此準確呢?

蛋先生:這可得感謝 Prompt 工程的功勞!

比如在 Prompt 中,會告訴 LLM 可以使用的小工具:

You have access to the following tools:

get_current_time: get_current_time() -> str - Get the current time.

Valid "action" values: "Final Answer" or get_current_time

還有比如在 Prompt 中,會告訴 LLM 用 JSON 格式返回:

Provide only ONE action per $JSON_BLOB, as shown:

{
  "action": $TOOL_NAME,
  "action_input": $INPUT
}

具體可以參考這個 Prompt 模板 【hwchase17/structured-chat-agent

丹尼爾:666

Agent 類型這麼多,如何抉擇?

丹尼爾:我瞅了瞅官網上的 Agent 類型,簡直讓我眼花繚亂。我這個選擇困難症患者該如何選呢?

image

蛋先生:首先,我們來梳理一下 LLM 和 Chat Model 這兩個 model type 的區別。在 LangChain 中,LLM 和 Chat Model 的本質區別在於輸入輸出。LLM 的輸入輸出都是字符串,而 Chat Model 的輸入輸出都是 Message 實例。

丹尼爾:然後呢?

蛋先生:如果你對 OpenAI 的 API 比較熟悉,可以把 LLM 當做 Completions,把 Chat Model 當做 Chat Completions。

  • Completions image

  • Chat Completions image

由於 Completions 已經被標記爲 Legacy(不建議使用),所以在實際應用中,建議使用 Chat Model 類型的 Agent 就可以了。

丹尼爾:哦,拋開 LLM 類型,還有 OpenAI Tools / OpenAI Functions / Structured Chat / JSON Chat。那這些又該如何選擇呢?

蛋先生:OpenAI functions 參數已經過時了,建議使用 tools 參數。So,可以把 OpenAI Functions 類型排除掉

image

丹尼爾:好的,還剩下 OpenAI Tools / Structured Chat / JSON Chat。

蛋先生:如果你使用的是 OpenAI 的語言模型(實際上只要 API 支持 tools 參數的大語言模型都可以用此類型),那就選擇 OpenAI Tools 類型的;否則就選用 Structured Chat。

Structured Chat 與 JSON Chat 的區別

丹尼爾:那 JSON Chat 類型呢?爲啥直接無視它了?

蛋先生:Structured Chat 和 JSON Chat 的區別在於對 tool 入參類型的支持上。

JSON Chat 只支持一個參數的 tool,比如以下工具:

@tool
def search(query: str) -> str:
    """Look up things online."""
    return "LangChain"

如果是多參數的 tool,那你就得升級成 Structured Chat,比如如下工具:

@tool
def multiply(a: int, b: int) -> int:
    """Multiply two numbers."""
    return a * b

丹尼爾:哦,看起來 Structured Chat 已經包含了 JSON Chat 的功能了呀。

蛋先生:沒錯,但如果你用的大語言模型比較糟糕,可能就需要用 JSON Chat。因爲對於大語言模型來說,調用只有一個參數的 tool 會更簡單一些。不過現在的大語言模型只會變得越來越厲害,所以 Structured Chat 就可以了。

丹尼爾:好咧,我已經迫不及待要去試試了!

蛋先生:那,後會有期

丹尼爾:謝謝蛋兄,後會有期

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章