
如何快速實現REST API集成以優化業務流程
圖 1. 由 LLM 驅動的智能體系統
如圖 1 所示,在基于 LLM 的智能體中,LLM 的充當著智能體的“大腦”的角色,同時還有 3 個關鍵部分:
相信看到這里,我們已經對智能體有了基本的認知。如果你還覺得智能體這個概念有點抽象,沒關系,現在我們來點好玩的,一起來看看智能體能玩出什么花樣?
調研員智能體,可以根據用戶的調研問題,從搜索引擎上搜索資料并總結,然后生成調研報告。這里使用 MetaGPT 框架中的調研員 示例來展示一個智能體的實際作用及其構成。
運行一下試試
~ python3 -m metagpt.roles.researcher "特斯拉FSD vs 華為ADS"
智能體執行調研
圖2. 從搜索引擎進行搜索并獲取Url地址列表
(圖左為馮·諾依曼;右為奧本海默;背后是世界上第一臺馮·諾依曼架構的“現代”計算機)
圖3. 瀏覽網頁并總結網頁內容
圖4.生成調研報告
文件:特斯拉FSD vs 華為ADS.md
圖5
調研員智能體構成
回到前文所說的,如果僅有 LLM 這個大腦,是無法完成整個調研流程的。在調研員智能體中,為 LLM 大腦配備了規劃、工具、記憶的能力,使得他能獨立完成調研任務,下面列出其基本構成,構成分三部分:角色、工具、記憶。在角色中,會注冊各種工具,定義思考規劃的方式,以及本身具備的短期記憶能力。
圖解調研員智能體
圖6
img
智能體 如上圖所示,在基于 LLM 的智能體中,LLM 的充當著智能體的“大腦”的角色,同時還有 3 個關鍵部分:規劃(Planning)、記憶(Memory)、工具使用(Tool use)
規劃,可以為理解觀察和思考。如果用人類來類比,當我們接到一個任務,我們的思維模式可能會像下面這樣:
這是人類的規劃能力,我們希望智能體也擁有這樣的思維模式,因此可以通過 LLM 提示工程,為智能體賦予這樣的思維模式。在智能體中,最重要的是讓 LLM 具備這以下兩個能力:
通過 LLM 使得智能體可以把大型任務分解為更小的、更可控的子任務,從而能夠有效完成復雜的任務。
思維鏈(Chain of Thoughts, CoT)
思維鏈已經是一種比較標準的提示技術,能顯著提升 LLM 完成復雜任務的效果。當我們對 LLM 這樣要求「think step by step」,會發現 LLM 會把問題分解成多個步驟,一步一步思考和解決,能使得輸出的結果更加準確。這是一種線性的思維方式。
思維鏈的 prompt 可以像是如下這樣(這里只是一個極簡的 prompt,實際會按需進行 prompt 調優):
template="Answer the question: Q: {question}? Let's think step by step:"
思維樹(Tree-of-thought, ToT)
對 CoT 的進一步擴展,在思維鏈的每一步,推理出多個分支,拓撲展開成一棵思維樹。使用啟發式方法評估每個推理分支對問題解決的貢獻。選擇搜索算法,使用廣度優先搜索(BFS)或深度優先搜索(DFS)等算法來探索思維樹,并進行前瞻和回溯。
圖7
反思和完善
智能體在執行任務過程中,通過 LLM 對完成的子任務進行反思,從錯誤中吸取教訓,并完善未來的步驟,提高任務完成的質量。同時反思任務是否已經完成,并終止任務。
(剛接觸到這個單詞時,腦子里冒出來的是 「React 是由 Facebook 開源的一個進行創建用戶界面的一款 JavaScript 庫….」,打住,我們好像走錯片場了,此 React 非彼 ReAct ?﹏? )
ReAct(Yao et al. 2023) ,《ReAct: Synergizing Reasoning and Acting in Language Models》 這篇論文提出一種用于增強大型語言模型的方法,它通過結合推理(Reasoning)和行動(Acting)來增強推理和決策的效果。
為什么結合推理和行動,就會有效增強 LLM 完成任務的能力?這個問題其實很好回答,我們用上面的「調研員智能體」舉例,我提出了問題:「特斯拉 FSD 對比華為 ADS」,下面列出幾種不同規劃模式的推演:
推理1:當前知識不足以回答這個問題,要回答該問題,需要知道什么是「特斯拉FSD 」和「華為ADS」
行動1:使用搜索工具搜索「特斯拉FSD 」和「華為ADS」的資料
觀察1:總結行動1的內容
推理2:基于行動1和觀察1的信息,得知這是關于兩個自動駕駛提供商的方案對比,基于已有的信息,現在需要生成報告
行動2:使用生成報告的工具,生成調研報告
觀察2:任務完成
圖8
通過巧妙的 promt 提示設計,使得 LLM 重復地執行推理和行動,最終完成任務。ReAct 的 prompt 模版的大致思路為:
Thought(思考): ...
Action(行動): ...
Observation(觀察): ...
Thought(思考): ...
Action(行動): ...
Observation(觀察): ...
...(Repeated many times(重復多次))
記憶(Memory)
記憶是什么?當我們在思考這個問題,其實人類的大腦已經在使用記憶。記憶是大腦存儲、保留和回憶信息的能力。記憶可以分為不同的類型:
仿照人類的記憶機制,智能體實現了兩種記憶機制:
LLM 是數字世界中的程序,想要與現實世界互動、獲取未知的知識,或是計算某個復雜的公式等,都離不開不工具。所以我們需要為智能體配備各種工具以及賦予它使用工具的能力。
工具是什么?它可以是錘子、螺絲刀,也可以是函數(function)、軟件開發工具包(sdk)。工具是人類智慧的具象化,擴展我們的能力,提升工作效率。在智能體中,工具就是函數(Function),工具使用就是調用函數(Call Function)。
在 LLM 中實現函數調用,使用到 LLM 的這個能力:
Function Calling 是一種實現大型語言模型連接外部工具的機制。通過 API 調用 LLM 時,調用方可以描述函數,包括函數的功能描述、請求參數說明、響應參數說明,讓 LLM 根據用戶的輸入,合適地選擇調用哪個函數,同時理解用戶的自然語言,并轉換為調用函數的請求參數(通過 JSON 格式返回)。調用方使用 LLM 返回的函數名稱和參數,調用函數并得到響應。最后,如果需求,把函數的響應傳給 LLM,讓 LLM 組織成自然語言回復用戶。
function calling 具體工作流程如下圖所示:
圖9
不同 LLM 的 API 接口協議會有所不同,下文將以OpenAI 的 API 協議為例,說明如何實現 Function Calling
函數描述
我們可以按照智能體的需要來實現函數,比如前文的「調研員」智能體,為其實現了這些函數:WebBrowseAndSummarize:瀏覽網頁并總結網頁內容;ConductResearch:生成調研報告等。如果是一個智能家居的智能體,可能會需要這些函數:開關燈、開光空調、獲取環境信息等。函數的實現在這里不展開贅述,一個函數可以自行編碼實現,也可以通過調用外部 API 實現。
假設你的函數已經被實現,我們需要向 LLM 描述這個函數,函數描述的必備要素:
「查詢最近天氣」的函數描述:
tools = [
{
"type": "function",
"function": {
"name": "get_n_day_weather_forecast",
"description": "獲取最近n天的天氣預報",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市或鎮區 如:深圳市南山區",
},
"format": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "要使用的溫度單位,攝氏度 or 華氏度",
},
"num_days": {
"type": "integer",
"description": "預測天數",
}
},
"required": ["location", "format", "num_days"]
},
}
}
]
Function Calling 是通過請求 LLM 的 chat API 實現的,在支持 Function Calling 模型的 chat API 參數中,會有一個 functions 參數 (或 tools,不同 LLM 的參數會有所不同) ,通過傳入這個參數,大模型則會知道擁有哪些參數可供使用。并且會根據用戶的輸入,推理出應該調用哪些函數,并將自然語言轉成函數的請求參數,返回給請求方。下面以 OpenAI 的 SDK 舉例:
from openai import OpenAI
def chat_completion_request(messages, tools=None, tool_choice=None, model="gpt-3.5-turbo"):
try:
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tools,
tool_choice=tool_choice,
)
return response
except Exception as e:
print("Unable to generate ChatCompletion response")
print(f"Exception: {e}")
return e
if __name__ == "__main__":
messages = []
messages.append({"role": "system", "content": "不要假設將哪些值輸入到函數中。如果用戶請求不明確,請要求澄清"})
messages.append({"role": "user", "content": "未來5天深圳南山區的天氣怎么樣"})
chat_response = chat_completion_request(
messages, tools=tools
)
tool_calls = chat_response.choices[0].message.tool_calls
print("===回復===")
print(tool_calls)
LLM 將會返回get_n_day_weather_forecast
函數的調用參數:
===回復===
[ChatCompletionMessageToolCall(id='call_7qGdyUEWp34ihubinIUCTXyH', function=Function(arguments='{"location":"深圳市南山區","format":"celsius","num_days":5}', name='get_n_day_weather_forecast'), type='function')]
// 格式化看看:chat_response.choices[0].message.tool_calls:
[
{
"id": "call_7qGdyUEWp34ihubinIUCTXyH",
"function": {
"arguments": {
"location": "深圳市南山區",
"format": "celsius",
"num_days": 5
},
"name": "get_n_day_weather_forecast"
},
"type": "function"
}
]
調用函數
調用方獲得 LLM 返回的函數調用信息(函數名稱和調用參數)后,自行調用函數,并得到函數執行的響應。如果有需要,還可以把函數執行的響應追加到 chat API 的對話中傳給 LLM,讓 LLM 組織成自然語言回復用戶。
# 執行函數
for tool_call in tool_calls:
function = tool_call.function.name
arguments_list = json.loads(tool_call.function.arguments)
function_to_call = globals().get(function)
result = function_to_call(**arguments_list)
print("===" + function + "===")
print(result)
# 把函數調用結果加入到對話歷史中
messages.append(
{
"tool_call_id": tool_call.id, # 用于標識函數調用的 ID
"role": "user",
"name": function,
"content": "函數執行結果為:" + str(result)
}
)
# 函數執行結果傳給LLM,組織成自然語言回復用戶
chat_response = chat_completion_request(
messages, tools=tools
)
print("===回復===")
print(chat_response.choices[0].message.content)
執行結果:
===get_n_day_weather_forecast===
[{'date': '2023-04-01', 'location': '深圳市南山區', 'temperature': '20°C', 'description': '晴朗'}, {'date': '2023-04-02', 'location': '深圳市南山區', 'temperature': '21°C', 'description': '多云'}, {'date': '2023-04-03', 'location': '深圳市南山區', 'temperature': '22°C', 'description': '晴朗'}, {'date': '2023-04-04', 'location': '深圳市南山區', 'temperature': '23°C', 'description': '多云'}, {'date': '2023-04-05', 'location': '深圳市南山區', 'temperature': '24°C', 'description': '晴朗'}]
===回復===
未來5天深圳南山區的天氣情況如下:
- 4月1日:晴朗,溫度20°C
- 4月2日:多云,溫度21°C
- 4月3日:晴朗,溫度22°C
- 4月4日:多云,溫度23°C
- 4月5日:晴朗,溫度24°C
請注意天氣預報僅供參考,實際情況可能會有所變化。
現在(2024 年 5 月)如果你想要開發一個 AI 智能體,已經比大模型爆發的初期方便太多了,隨著 AI 應用需求的持續火熱,智能體框架層出不窮。智能體開發框架,會抽象和封裝那些被高頻使用的模塊,如記憶能力、規劃能力、RAG 能力、大模型調用等。使用智能體框架,可讓幫助你快速搭建智能體。
根據?awesome-ai-agents?的整理,無論是開源的還是閉源的,智能體應用框架在各個領域,比如自定義智能體、編碼、研究、數據分析、多智能體等等,都有比較有代表性的產品可供選擇。
圖10
上文曾使用到MetaGPT?,MetaGPT 是一個多智能體框架,多智能體框架可以幫你開發一個由多個不同職責的智能體組合起來的多智能體。舉個例子,如果我們想開發一個多智能體軟件團隊,該軟件團隊可以根據用戶需求交付代碼,其內部會通過測試代碼、評審代碼來提升代碼質量。該多智能體將包含:開發(coder)、測試(tester)、評審人(reviewer)這三個不同職責的智能體,他們各司其職,互相協作完成任務。下圖的左側是多智能體的協作流程,右側是單智能體的工作流程。
圖11
隨著大模型的百花齊放,LLM 會支持更長的上下文、更大的參數規模,其推理能力也會愈發強大。因此,基于大模型搭建的智能體(AI Agent)的能力邊界也在不斷突破。通過智能體技術,我們可以創建各種各樣的 AI 應用,比如:Copilot、DB-GPT 等等,一些 AI 應用已經成為工作生活中不可缺少的存在。相信 AI 應用的將會快速全面地重構我們曾經習以為常的軟件形態和交互方式,以及提升人類的生產效率。
本文章轉載微信公眾號@騰訊技術工程