概要
開源大型語言模型 (LLMs) 現已達到一種效能水平,使它們適合作為推動智慧體工作流的推理引擎: Mixtral 甚至在我們的基準測試中 超過了 GPT-3.5,並且透過微調,其效能可以輕易的得到進一步增強。
引言
針對 因果語言建模 訓練的大型語言模型 (LLMs) 可以處理廣泛的任務,但它們經常在邏輯、計算和搜尋等基本任務上遇到困難。最糟糕的情況是,它們在某個領域,比如數學,表現不佳,卻仍然試圖自己處理所有計算。
為了克服這一弱點,除其他方法外,可以將 LLM 整合到一個系統中,在該系統中,它可以呼叫工具: 這樣的系統稱為 LLM 智慧體。
在這篇文章中,我們將解釋 ReAct 智慧體的內部工作原理,然後展示如何使用最近在 LangChain 中整合的 ChatHuggingFace
類來構建它們。最後,我們將幾個開源 LLM 與 GPT-3.5 和 GPT-4 進行基準測試。
什麼是智慧體?
LLM 智慧體的定義非常寬泛: 它們指的是所有將 LLMs 作為核心引擎,並能夠根據觀察對其環境施加影響的系統。這些系統能夠透過多次迭代“感知 ⇒ 思考 ⇒ 行動”的迴圈來實現既定任務,並常常融入規劃或知識管理系統以提升其表現效能。你可以在 Xi et al., 2023 的研究中找到對智慧體領域綜述的精彩評述。
今天,我們將重點放在 ReAct 智慧體 上。ReAct 採用一種基於“推理 (Reasoning)”與“行動 (Acting)”結合的方式來構建智慧體。在提示詞中,我們闡述了模型能夠利用哪些工具,並引導它“逐步”思考 (亦稱為 思維鏈 行為),以規劃並實施其後續動作,達成最終的目標。
ReAct 智慧體內部工作原理示例
上述圖解雖顯得有些抽象,但其核心原理其實相當直接。
參見 此筆記本: 我們藉助 Transformers 庫展示了一個最基礎的工具呼叫例項。
本質上,LLM 透過一個迴圈被呼叫,迴圈中的提示包含如下內容:
這裡是一個問題: “{question}”
你可以使用這些工具: {tools_descriptions}。
首先,你需要進行‘思考: {your_thoughts}’,接下來你可以:
- 以正確的 JSON 格式發起工具呼叫,
- 或者,以‘最終答案:’為字首來輸出你的答案。
接下來,你需要解析 LLM 的輸出:
- 如果輸出中包含
‘最終答案:’
字串,迴圈便結束,並輸出該答案; - 若不包含,則表示 LLM 進行了工具呼叫: 你需解析此輸出以獲得工具的名稱及其引數,隨後根據這些引數執行相應工具的呼叫。此工具呼叫的結果將被追加至提示資訊中,然後你將帶有這些新增資訊的提示再次傳遞給 LLM,直至它獲得足夠的資訊來給出問題的最終答案。
例如,LLM 的輸出在回答問題: 1:23:45 中有多少秒?
時可能看起來像這樣:
思考: 我需要將時間字串轉換成秒。
動作:
{
"action": "convert_time",
"action_input": {
"time": "1:23:45"
}
}
鑑於此輸出未包含 ‘最終答案:’
字串,它代表進行了工具呼叫。因此我們解析該輸出,獲取工具呼叫的引數: 以引數 {"time": "1:23:45"}
呼叫 convert_time
工具,執行該工具呼叫後返回 {'seconds': '5025'}
。
於是,我們將這整個資訊塊追加至提示詞中。
更新後的提示詞現在變為 (更為詳盡的版本):
這是一個問題: “1:23:45 包含多少秒?”
你可以使用以下工具:
- convert_time: 將小時、分鐘、秒格式的時間轉換為秒。
首先,進行“思考: {your_thoughts}”,之後你可以:
- 使用正確的 JSON 格式呼叫工具,
- 或以“最終答案:”為字首輸出你的答案。
思考: 我需要把時間字串轉換成秒數。
行動:
{
"action": "convert_time",
"action_input": {
"time": "1:23:45"
}
}
觀測結果: {'seconds': '5025'}
➡️ 我們用這個新的提示再次呼叫 LLM,鑑於它可以訪問工具呼叫結果中的 觀測結果
,LLM 現在最有可能輸出:
思考: 我現在有了回答問題所需的資訊。
最終答案: 1:23:45 中有 5025 秒。
任務就這樣完成了!
智慧體系統的挑戰
一般來說,執行 LLM 引擎的智慧體系統的難點包括:
- 從提供的工具中選擇一個能夠幫助實現目標的工具: 例如,當詢問
“大於 30,000 的最小質數是什麼?”
時,智慧體可能會呼叫“K2 的高度是多少?”
的Search
工具,但這並無幫助。 以嚴格的引數格式呼叫工具: 例如,在嘗試計算一輛汽車 10 分鐘內行駛 3 公里的速度時,你必須呼叫
Calculator
工具,透過distance
除以time
來計算: 即便你的 Calculator 工具接受 JSON 格式的呼叫{“tool”: “Calculator”, “args”: “3km/10min”}
,也存在許多陷阱,例如:- 工具名稱拼寫錯誤:
“calculator”
或“Compute”
是無效的 - 提供的是引數名稱而非其值:
“args”: “distance/time”
- 格式非標準化:
“args": "3km in 10minutes”
- 工具名稱拼寫錯誤:
- 高效地吸收和利用過去觀察到的資訊,無論是初始上下文還是使用工具後返回的觀察結果。
那麼,完整的智慧體設定會是怎樣的呢?
使用 LangChain 執行智慧體
我們剛剛在 🦜🔗LangChain 中整合了一個 ChatHuggingFace
封裝器,使你能夠基於開源模型建立智慧體。
建立 ChatModel 併為其配備工具的程式碼非常簡單,你可以在 Langchain 文件 中檢視所有相關程式碼。
from langchain_community.llms import HuggingFaceHub
from langchain_community.chat_models.huggingface import ChatHuggingFace
llm = HuggingFaceHub(
repo_id="HuggingFaceH4/zephyr-7b-beta",
task="text-generation",
)
chat_model = ChatHuggingFace(llm=llm)
你可以透過為其提供 ReAct 風格的提示詞和工具,將 chat_model
轉化為一個智慧體:
from langchain import hub
from langchain.agents import AgentExecutor, load_tools
from langchain.agents.format_scratchpad import format_log_to_str
from langchain.agents.output_parsers import (
ReActJsonSingleInputOutputParser,
)
from langchain.tools.render import render_text_description
from langchain_community.utilities import SerpAPIWrapper
# 設定工具
tools = load_tools(["serpapi", "llm-math"], llm=llm)
# 設定 ReAct 風格的提示詞
prompt = hub.pull("hwchase17/react-json")
prompt = prompt.partial(
tools=render_text_description(tools),
tool_names=", ".join([t.name for t in tools]),
)
# 定義智慧體
chat_model_with_stop = chat_model.bind(stop=["\nObservation"])
agent = (
{
"input": lambda x: x["input"],
"agent_scratchpad": lambda x: format_log_to_str(x["intermediate_steps"]),
}
| prompt
| chat_model_with_stop
| ReActJsonSingleInputOutputParser()
)
# 例項化 AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke(
{
"input": "Who is the current holder of the speed skating world record on 500 meters? What is her current age raised to the 0.43 power?"
}
)
智慧體將處理如下輸入:
思考: 為了回答這個問題,我需要找出當前速滑世界紀錄保持者的年齡。我將使用搜尋工具來獲取這些資訊。
行動:
{
"action": "search",
"action_input": " 速滑 500 米世界紀錄保持者的年齡 "
}
觀察: ...
智慧體對決: 開源 LLM 作為通用推理智慧體的表現如何?
你可以在 這裡 找到這個基準測試的程式碼。
評估
我們旨在評估開源大型語言模型 (LLMs) 作為通用推理智慧體的表現。因此,我們選擇了需要運用邏輯和使用基本工具 (如計算器和網際網路搜尋訪問) 的問題。
最終資料集 是從其他三個資料集中選取樣本的組合:
- 為了測試網際網路搜尋能力,我們選取了 HotpotQA 中的問題: 雖然這是一個檢索型資料集,但它也可用於需要網際網路訪問的通用問題解答。有些問題原本需要結合來自不同來源的資訊: 在我們的設定中,這意味著需要進行多步網際網路搜尋以整合結果。
- 對於計算器的應用,我們加入了來自 GSM8K 的問題: 這個資料集測試小學數學能力,並且完全可以透過正確利用 4 個運算子 (加、減、乘、除) 來解決。
- 我們還從 GAIA 中挑選了問題,這是一個對通用 AI 助理來說極具挑戰性的基準測試。原始資料集中的問題可能需要許多其他不同的工具,如程式碼直譯器或 PDF 閱讀器: 我們精選了那些僅需搜尋和計算器的問題。
評估採用了 GPT-4 作為評判員,基於 Prometheus 提示格式 的提示進行,結果以 5 點李克特量表 (5-point Likert Scale) 表示: 具體的提示內容可在 此處 檢視。
模型
我們評估了一些強大的開源模型:
- Llama2-70b-chat
- Mixtral-8x7B-Instruct-v0.1
- OpenHermes-2.5-Mistral-7B
- Zephyr-7b-beta
- SOLAR-10.7B-Instruct-v1.0
這些模型透過 LangChain 的 ReAct 實現 進行了評估
這意味著我們引導它們按照以下格式輸出函式呼叫:
{
"action": $TOOL_NAME,
"action_input": $INPUT
}
作為比較,我們還利用 LangChain 的 專為 OpenAI 設計的智慧體 對 GPT-3.5 和 GPT-4 在相同的例子上進行了評估。
由於這涉及到它們自己的函式呼叫模板,並在此基礎上進行了微調,這意味著 OpenAI 模型應當展現出最佳效能。
結果
鑑於開源模型並沒有針對特定的輸出格式進行特別的函式呼叫微調,相較於 OpenAI 智慧體,它們處於稍微不利的位置。
儘管存在這樣的不利條件,某些模型的表現依然非常優秀!💪
這是 Mixtral-8x7B 回答“貴陽和塔城哪個城市人口更多?”問題的示例:
思考: 為了回答這個問題,我需要找到貴陽和塔城當前的人口數。我將利用搜尋工具來查詢這些資訊。
操作:
{
"action": "search",
"action_input": " 貴陽當前人口 "
}
4.697 百萬 (2016 年)
思考: 我已獲得貴陽的人口數,為 4.697 百萬 (截至 2016 年)。現在,我將再次使用搜尋工具來確定塔城的人口數。
操作:
{
"action": "search",
"action_input": " 塔城當前人口 "
}
人口: 新疆: 塔城的資料在 2021 年報告為 1,110,000 人。這比 2020 年的 1,138,638 人有所下降。
人口: 新疆: 塔城的資料每年更新,從 2005 年 12 月到 2021 年,平均人口為 1,023,000 人,共 17 次觀察。
我已確定塔城的人口約為 1.11 百萬 (截至 2021 年)。對比兩地人口,貴陽的人口超過塔城。
思考: 我現在清楚最終答案了
最終答案: 貴陽的人口更多,約為 4.697 百萬 (截至 2016 年),而塔城的人口約為 1.11 百萬 (截至 2021 年)。
這是各模型在我們的評估資料集上的基準測試結果 (原始平均分按 1-5 的評分量表,已轉換為 0-100%的量表以便閱讀):
正如所見,一些開源模型在推動智慧體工作流程方面表現欠佳: 雖然對於小型的 Zephyr-7b 而言這是預期之中的,但令人驚訝的是 Llama2-70b 的表現相當差。
👉 然而,Mixtral-8x7B 的表現非常出色: 它甚至超越了 GPT-3.5!🏆
這是即開即用的效能: 與 GPT-3.5 不同的是,據我們所知,Mixtral 沒有針對智慧體工作流程進行過微調 ,這在一定程度上影響了其效能。例如,在 GAIA 上,因為 Mixtral 嘗試使用格式不正確的引數呼叫工具,導致 10%的問題失敗。 如果對功能呼叫和任務規劃技能進行適當的微調,Mixtral 的得分可能會更高。
➡️ 我們強烈建議開源開發者開始針對智慧體對 Mixtral 進行微調,以超越下一個挑戰者: GPT-4!🚀
結語:
- 雖然 GAIA 基準測試僅在一小部分問題和少數工具上進行了嘗試,但它似乎是智慧體工作流程整體模型效能的一個非常強大的指標,因為它通常涉及多個推理步驟和嚴格的邏輯。
- 智慧體工作流程使 LLMs 能夠提升效能: 例如,在 GSM8K 上,GPT-4 的技術報告 顯示,使用 5 次 CoT 提示的情況下得分為 92%: 透過提供一個計算器,我們能夠在零次提示的情況下達到 95%。對於 Mixtral-8x7B,LLM 排行榜 報告了使用 5 次提示的情況下為 57.6%,而我們在零次提示的情況下達到了 73%。 (記住,我們僅測試了 GSM8K 的 20 個問題)
英文原文: https://hf.co/blog/open-source-llms-as-agents
作者: Aymeric Roucher, Joffrey THOMAS, Andrew Reed
譯者: Evinci