介紹 smolagents,一個構建智慧體的簡單庫

釋出於 2024 年 12 月 31 日
在 GitHub 上更新

今天我們釋出了 smolagents,這是一個非常簡單的庫,可為語言模型解鎖智慧體能力。以下是它的一些亮點:

from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel

agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=HfApiModel())

agent.run("How many seconds would it take for a leopard at full speed to run through Pont des Arts?")

目錄

🤔 什麼是智慧體?

任何高效使用 AI 的系統都需要為 LLM 提供對現實世界的某種訪問許可權:例如,調用搜索工具以獲取外部資訊,或對某些程式進行操作以解決任務的可能性。換句話說,LLM 應該擁有**代理能力**。智慧體程式是 LLM 通往外部世界的門戶。

AI 智慧體是**LLM 輸出控制工作流的程式**。

任何利用 LLM 的系統都會將 LLM 輸出整合到程式碼中。LLM 輸入對程式碼工作流的影響是 LLM 在系統中的代理能力水平。

請注意,根據此定義,“智慧體”不是一個離散的 0 或 1 定義:相反,“代理能力”在一個連續的範圍內演變,具體取決於您賦予 LLM 對工作流的權力大小。

下表說明了不同系統中代理能力的變化

代理能力等級 描述 名稱 示例模式
☆☆☆ LLM 輸出對程式流程無影響 簡單處理器 process_llm_output(llm_response)
★☆☆ LLM 輸出決定基本控制流 路由器 if llm_decision(): path_a() else: path_b()
★★☆ LLM 輸出決定函式執行 工具呼叫 run_function(llm_chosen_tool, llm_chosen_args)
★★★ LLM 輸出控制迭代和程式繼續 多步智慧體 while llm_should_continue(): execute_next_step()
★★★ 一個代理工作流可以啟動另一個代理工作流 多智慧體 if llm_trigger(): execute_agent()

多步智慧體具有以下程式碼結構

memory = [user_defined_task]
while llm_should_continue(memory): # this loop is the multi-step part
    action = llm_get_next_action(memory) # this is the tool-calling part
    observations = execute_action(action)
    memory += [action, observations]

因此,該系統在一個迴圈中執行,每一步執行一個新動作(該動作可能涉及呼叫一些預先確定的**工具**,這些工具只是函式),直到其觀察結果表明已達到令人滿意的狀態以解決給定任務。以下是一個多步智慧體如何解決一個簡單數學問題的示例

✅ 何時使用智慧體 / ⛔ 何時避免使用它們

當您需要 LLM 來確定應用程式的工作流時,智慧體非常有用。但它們通常是殺雞用牛刀。問題是:我是否真的需要工作流的靈活性才能有效地解決手頭的任務?如果預定的工作流經常不足,則意味著您需要更大的靈活性。讓我們舉一個例子:假設您正在開發一個處理衝浪旅行網站客戶請求的應用程式。

您可以提前知道請求將屬於兩個類別中的一個(基於使用者選擇),並且您為這兩個類別中的每個類別都有預定義的工作流。

  1. 想了解旅行資訊?⇒ 讓他們使用搜索欄搜尋您的知識庫
  2. 想與銷售人員交談?⇒ 讓他們填寫聯絡表格。

如果這種確定性工作流適用於所有查詢,那麼請盡情編寫所有程式碼!這將為您提供一個 100% 可靠的系統,沒有任何由於讓不可預測的 LLM 干預您的工作流而引入的錯誤風險。為了簡單和健壯性,建議避免使用任何代理行為。

但是,如果工作流無法提前確定得那麼好呢?

例如,使用者想問:“我星期一可以來,但我忘了帶護照,所以可能會延遲到星期三,星期二早上可以帶我和我的東西去衝浪,併購買取消保險嗎?”這個問題取決於許多因素,上面預先確定的任何標準可能都不足以滿足此請求。

如果預定的工作流經常不足,則意味著您需要更大的靈活性。

這就是代理設定有幫助的地方。

在上面的例子中,您只需建立一個多步代理,它可以訪問天氣 API 以獲取天氣預報、Google Maps API 以計算旅行距離、員工可用性儀表板以及知識庫上的 RAG 系統。

直到最近,計算機程式還侷限於預設的工作流,試圖透過堆積 if/else 開關來處理複雜性。它們專注於極其狹窄的任務,例如“計算這些數字的總和”或“找到此圖中的最短路徑”。但實際上,大多數現實生活中的任務,例如我們上面提到的旅行示例,都不適合預設的工作流。代理系統為程式打開了廣闊的現實世界任務!

程式碼智慧體

在多步智慧體中,在每一步,LLM 都可以以呼叫外部工具的形式編寫一個動作。一種常見的(Anthropic、OpenAI 和許多其他公司使用的)編寫這些動作的格式通常是不同程度的“將動作編寫為工具名稱和要使用的引數的 JSON,然後您解析該 JSON 以瞭解要執行哪個工具以及使用哪個引數”。

多篇 研究 論文 表明,在程式碼中呼叫 LLM 工具效果更好。

其原因很簡單,我們**專門設計了我們的程式碼語言,使其成為表達計算機執行操作的最佳方式**。如果 JSON 片段是更好的表達方式,那麼 JSON 將是頂級的程式語言,而程式設計將是人間地獄。

下圖摘自 可執行程式碼操作能激發更好的 LLM 智慧體,說明了在程式碼中編寫操作的一些優點

在程式碼中而不是 JSON 類似片段中編寫操作提供了更好的

  • **可組合性:** 您可以將 JSON 操作相互巢狀,或者定義一組 JSON 操作供以後重用,就像您可以定義一個 Python 函式一樣嗎?
  • **物件管理:** 如何在 JSON 中儲存 generate_image 等操作的輸出?
  • **通用性:** 程式碼旨在簡單地表達計算機可以做的任何事情。
  • **LLM 訓練資料中的表示:** 大量高質量的程式碼操作已包含在 LLM 的訓練資料中,這意味著它們已經為此進行了訓練!

介紹 smolagents:讓智慧體變得簡單 🥳

我們構建 smolagents 的目標是

✨ **簡單性**:智慧體的邏輯程式碼只有約數千行(請參閱 此檔案)。我們將抽象層保持在原始程式碼之上的最小形態!

🧑‍💻 **一流的程式碼智慧體支援**,即編寫程式碼動作的智慧體(而不是“用於編寫程式碼的智慧體”)。為了確保安全,我們透過 E2B 支援在沙盒環境中執行。

🤗 **Hub 整合**:您可以將工具分享到 Hub 並從 Hub 載入工具,未來還會更多!

🌐 **支援任何 LLM**:它支援在 Hub 上以 transformers 版本載入或透過我們的推理 API 託管的模型,但也透過我們的 LiteLLM 整合支援來自 OpenAI、Anthropic 和許多其他公司的模型。

smolagentstransformers.agents 的繼任者,未來將取代它,因為 transformers.agents 將被棄用。

構建智慧體

要構建智慧體,您至少需要兩個元素

  • tools:智慧體可以訪問的工具列表
  • model:將作為智慧體引擎的 LLM。

對於 model,您可以使用任何 LLM,無論是使用我們利用 Hugging Face 免費推理 API 的 HfApiModel 類的開放模型(如上面的豹子示例所示),還是可以使用 LiteLLMModel 來利用 litellm 並從 100 多個不同的雲 LLM 中進行選擇。

對於工具,您只需建立一個帶有輸入和輸出型別提示的函式,以及提供輸入描述的文件字串,然後使用 @tool 裝飾器將其轉換為工具。

以下是如何建立一個從 Google 地圖獲取旅行時間的自定義工具,以及如何將其用於旅行規劃智慧體

from typing import Optional
from smolagents import CodeAgent, HfApiModel, tool

@tool
def get_travel_duration(start_location: str, destination_location: str, transportation_mode: Optional[str] = None) -> str:
    """Gets the travel time between two places.

    Args:
        start_location: the place from which you start your ride
        destination_location: the place of arrival
        transportation_mode: The transportation mode, in 'driving', 'walking', 'bicycling', or 'transit'. Defaults to 'driving'.
    """
    import os   # All imports are placed within the function, to allow for sharing to Hub.
    import googlemaps
    from datetime import datetime

    gmaps = googlemaps.Client(os.getenv("GMAPS_API_KEY"))

    if transportation_mode is None:
        transportation_mode = "driving"
    try:
        directions_result = gmaps.directions(
            start_location,
            destination_location,
            mode=transportation_mode,
            departure_time=datetime(2025, 6, 6, 11, 0), # At 11, date far in the future
        )
        if len(directions_result) == 0:
            return "No way found between these places with the required transportation mode."
        return directions_result[0]["legs"][0]["duration"]["text"]
    except Exception as e:
        print(e)
        return e

agent = CodeAgent(tools=[get_travel_duration], model=HfApiModel(), additional_authorized_imports=["datetime"])

agent.run("Can you give me a nice one-day trip around Paris with a few locations and the times? Could be in the city or outside, but should fit in one day. I'm travelling only with a rented bicycle.")

在收集旅行時間和執行計算後,智慧體返回最終方案

One-day Paris bike trip itinerary:
1. Start at Eiffel Tower at 9:00 AM.
2. Sightseeing at Eiffel Tower until 10:30 AM.
3. Travel to Notre-Dame Cathedral at 10:46 AM.
4. Sightseeing at Notre-Dame Cathedral until 12:16 PM.
5. Travel to Montmartre at 12:41 PM.
6. Sightseeing at Montmartre until 2:11 PM.
7. Travel to Jardin du Luxembourg at 2:33 PM.
8. Sightseeing at Jardin du Luxembourg until 4:03 PM.
9. Travel to Louvre Museum at 4:12 PM.
10. Sightseeing at Louvre Museum until 5:42 PM.
11. Lunch break until 6:12 PM.
12. Planned end time: 6:12 PM.

構建工具後,將其分享到 Hub 就像這樣簡單

get_travel_duration.push_to_hub("{your_username}/get-travel-duration-tool")

您可以在 這個空間 下看到結果。您可以在 空間中的 tool.py 檔案 下檢視工具的邏輯。如您所見,該工具實際上被匯出為一個繼承自 Tool 類的類,這是我們所有工具的底層結構。

開放模型在智慧體工作流中的能力如何?

我們建立了 CodeAgent 例項,並使用一些領先的模型,在 此基準測試 上進行了比較,該基準測試從幾個不同的基準測試中收集問題,以提供各種挑戰的混合。

在此處查詢基準測試 以獲取有關所用代理設定的更多詳細資訊,並檢視程式碼代理與工具呼叫代理的比較(劇透:程式碼效果更好)。

benchmark of different models on agentic workflows

這項比較表明,開源模型現在可以與最好的閉源模型媲美!

下一步 🚀

社群

這是一篇很棒的部落格文章!

謝謝你澄清了智慧體到底是什麼,
順便說一下,這是一篇很棒的帖子,使用智慧體解決現實世界的問題將很有趣

/me 接著製作了一個簡單的智慧體,用於獲取隨機的 XKCD 漫畫。看看吧!😄 👉 http://github.com/hemanth/notebooks/blob/main/notebooks/smolagents.ipynb
image.png

嗨,順便說一句,這是一個很棒的專案,但我有一個小問題,

我正在將 smolagents 與 QWEN 32B 模型(透過 CodeAgent)一起使用,並遇到了生成程式碼的問題。有時,代理生成的程式碼包含對 final_answer 的多次呼叫,其中一次出現在指令碼中間。由於 final_answer 旨在表示執行結束,因此其第一次出現之後的所有程式碼(例如,像 task_to_do() 這樣的呼叫)都不會執行。

我嘗試過什麼

  • 我曾嘗試“教導”模型避免將 final_answer 放在程式碼中間,但這種方法不可靠。

我的目標是

  • 在 smolagents 中擁有一個執行模型或變通方法,以確保完整的程式碼塊執行,即使生成了過早的 final_answer

問題
smolagents 中是否存在可以允許所有程式碼執行(即使 final_answer 被提前呼叫)的代理配置、變通方法或最佳實踐?任何指導或建議都將不勝感激。

先謝謝了!

·

是的,同樣的問題

這很棒,透過智慧體課程瞭解了這一點。

太棒了

感謝您以這種方式介紹這個領域,它讓人們迫不及待地想深入探索!

這對於學習者來說非常容易,他們可以相應地提升自己的技能。

謝謝。

註冊登入 發表評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.