smolagents 文件
代理 - 引導式教程
並獲得增強的文件體驗
開始使用
代理 - 引導式教程
在本引導式教程中,您將學習如何構建代理、如何執行代理以及如何自定義代理以使其更好地適用於您的用例。
選擇代理型別:CodeAgent 或 ToolCallingAgent
smolagents
提供兩個代理類:CodeAgent 和 ToolCallingAgent,它們代表了代理與工具互動的兩種不同正規化。關鍵區別在於如何指定和執行操作:程式碼生成與結構化工具呼叫。
CodeAgent 生成作為 Python 程式碼片段的工具呼叫。
- 程式碼在本地(可能不安全)或安全沙盒中執行。
- 工具作為 Python 函式(透過繫結)公開。
- 工具呼叫示例
result = search_docs("What is the capital of France?") print(result)
- 優點
- 高度表達:允許複雜的邏輯和控制流,可以組合工具、迴圈、轉換、推理。
- 靈活:無需預定義所有可能的操作,可以動態生成新的操作/工具。
- 湧現推理:適用於多步問題或動態邏輯。
- 侷限性
- 錯誤風險:必須處理語法錯誤、異常。
- 可預測性較差:更容易產生意外或不安全的輸出。
- 需要安全的執行環境。
ToolCallingAgent 將工具呼叫寫入結構化 JSON。
- 這是許多框架(OpenAI API)中使用的常見格式,允許結構化工具互動而無需程式碼執行。
- 工具透過 JSON 模式定義:名稱、描述、引數型別等。
- 工具呼叫示例
{ "tool_call": { "name": "search_docs", "arguments": { "query": "What is the capital of France?" } } }
- 優點
- 可靠:不易產生幻覺,輸出結構化且經過驗證。
- 安全:引數經過嚴格驗證,沒有任意程式碼執行的風險。
- 互操作性:易於對映到外部 API 或服務。
- 侷限性
- 表達能力低:無法輕鬆動態組合或轉換結果,或執行復雜的邏輯或控制流。
- 不靈活:必須預先定義所有可能的操作,僅限於預定義工具。
- 無程式碼合成:僅限於工具功能。
何時使用哪種代理型別
在以下情況下使用 CodeAgent
- 您需要推理、鏈式操作或動態組合。
- 工具是可組合的函式(例如,解析 + 數學 + 查詢)。
- 您的代理是問題解決者或程式設計師。
在以下情況下使用 ToolCallingAgent
- 您擁有簡單、原子化的工具(例如,呼叫 API、獲取文件)。
- 您希望實現高可靠性和明確驗證。
- 您的代理類似於排程器或控制器。
CodeAgent
CodeAgent 生成 Python 程式碼片段來執行操作和解決任務。
預設情況下,Python 程式碼在您的本地環境中執行。這應該是安全的,因為唯一可以呼叫的函式是您提供的工具(特別是如果它僅是 Hugging Face 的工具)以及一組預定義的安全函式,例如 print
或 math
模組中的函式,因此您已經受到執行內容的限制。
Python 直譯器預設也不允許在安全列表之外進行匯入,因此所有最明顯的攻擊都不應成為問題。您可以透過在初始化 CodeAgent 時將授權模組作為字串列表傳遞給引數 additional_authorized_imports
來授權其他匯入
model = InferenceClientModel()
agent = CodeAgent(tools=[], model=model, additional_authorized_imports=['requests', 'bs4'])
agent.run("Could you get me the title of the page at url 'https://huggingface.co/blog'?")
此外,作為額外的安全層,子模組的訪問預設是禁止的,除非在匯入列表中明確授權。例如,要訪問 numpy.random
子模組,您需要將 'numpy.random'
新增到 additional_authorized_imports
列表中。這也可以透過使用 numpy.*
來授權,這將允許 numpy
以及任何子包,例如 numpy.random
及其自己的子包。
LLM 可以生成任意程式碼,然後執行:請勿新增任何不安全的匯入!
當任何程式碼嘗試執行非法操作或代理生成的程式碼存在常規 Python 錯誤時,執行將停止。
您也可以使用 E2B 程式碼執行器 或 Docker 而非本地 Python 直譯器。對於 E2B,首先設定 E2B_API_KEY
環境變數,然後在代理初始化時傳遞 executor_type="e2b"
。對於 Docker,在初始化時傳遞 executor_type="docker"
。
透過此教程瞭解更多關於程式碼執行的資訊。
ToolCallingAgent
ToolCallingAgent 輸出 JSON 工具呼叫,這是許多框架(OpenAI API)中使用的常見格式,允許結構化工具互動而無需程式碼執行。
它的工作方式與 CodeAgent 大致相同,當然沒有 additional_authorized_imports
,因為它不執行程式碼
from smolagents import ToolCallingAgent
agent = ToolCallingAgent(tools=[], model=model)
agent.run("Could you get me the title of the page at url 'https://huggingface.co/blog'?")
構建您的代理
要初始化一個最小代理,您至少需要以下兩個引數
model
,一個驅動代理的文字生成模型——因為代理不同於簡單的 LLM,它是一個使用 LLM 作為其引擎的系統。您可以使用以下任何選項- TransformersModel 使用預初始化的
transformers
管道在本地機器上執行推理。 - InferenceClientModel 在底層利用
huggingface_hub.InferenceClient
,並支援 Hub 上的所有推理提供商:Cerebras、Cohere、Fal、Fireworks、HF-Inference、Hyperbolic、Nebius、Novita、Replicate、SambaNova、Together 等。 - LiteLLMModel 同樣允許您透過 LiteLLM 呼叫 100 多個不同的模型和提供商!
- AzureOpenAIServerModel 允許您使用部署在 Azure 中的 OpenAI 模型。
- AmazonBedrockServerModel 允許您在 AWS 中使用 Amazon Bedrock。
- MLXModel 建立一個 mlx-lm 管道以在您的本地機器上執行推理。
- TransformersModel 使用預初始化的
tools
,代理可用於解決任務的Tools
列表。它可以是一個空列表。您還可以透過定義可選引數add_base_tools=True
將預設工具箱新增到您的tools
列表之上。
一旦您擁有這兩個引數 tools
和 model
,您就可以建立一個代理並執行它。您可以使用任何您喜歡的 LLM,無論是透過 Inference Providers、transformers、ollama、LiteLLM、Azure OpenAI、Amazon Bedrock 或 mlx-lm。
推理提供商需要 HF_TOKEN
進行身份驗證,但免費的 HF 賬戶已經包含積分。升級到 PRO 賬戶以提高您的包含積分。
要使用 PRO 賬戶訪問受限模型或提高您的速率限制,您需要設定環境變數 HF_TOKEN
或在初始化 InferenceClientModel
時傳遞 token
變數。您可以從您的設定頁面獲取您的令牌。
from smolagents import CodeAgent, InferenceClientModel
model_id = "meta-llama/Llama-3.3-70B-Instruct"
model = InferenceClientModel(model_id=model_id, token="<YOUR_HUGGINGFACEHUB_API_TOKEN>") # You can choose to not pass any model_id to InferenceClientModel to use a default model
# you can also specify a particular provider e.g. provider="together" or provider="sambanova"
agent = CodeAgent(tools=[], model=model, add_base_tools=True)
agent.run(
"Could you give me the 118th number in the Fibonacci sequence?",
)
高階代理配置
自定義代理終止條件
預設情況下,代理會一直執行,直到它呼叫 final_answer
函式或達到最大步數。final_answer_checks
引數讓您可以更好地控制代理何時以及如何終止其執行
from smolagents import CodeAgent, InferenceClientModel
# Define a custom final answer check function
def is_integer(final_answer: str, agent_memory=None) -> bool:
"""Return True if final_answer is an integer."""
try:
int(final_answer)
return True
except ValueError:
return False
# Initialize agent with custom final answer check
agent = CodeAgent(
tools=[],
model=InferenceClientModel(),
final_answer_checks=[is_integer]
)
agent.run("Calculate the least common multiple of 3 and 7")
final_answer_checks
引數接受一個函式列表,每個函式都
- 將代理的最終答案字串和代理的記憶體作為引數
- 返回一個布林值,指示最終答案是否有效(True)或無效(False)
如果任何函式返回 False
,代理將記錄錯誤訊息並繼續執行。此驗證機制允許
- 強制執行輸出格式要求(例如,確保數學問題的數字答案)
- 實施領域特定的驗證規則
- 建立更健壯的代理來驗證自己的輸出
檢查代理執行
以下是一些有用的屬性,用於檢查執行後發生的情況
agent.logs
儲存代理的詳細日誌。在代理執行的每一步,所有內容都儲存在一個字典中,然後附加到agent.logs
中。- 執行
agent.write_memory_to_messages()
會將代理的記憶體作為聊天訊息列表寫入,供模型檢視。此方法會遍歷日誌的每一步,並且只將它感興趣的內容作為訊息儲存:例如,它會將系統提示和任務儲存在單獨的訊息中,然後對於每一步,它會將 LLM 輸出儲存為訊息,將工具呼叫輸出儲存為另一條訊息。如果您想對發生的事情有一個更高層次的瞭解,請使用此方法 - 但並非所有日誌都會透過此方法進行轉錄。
工具
工具是代理使用的原子函式。要被 LLM 使用,它還需要一些屬性來構成其 API,這些屬性將用於向 LLM 描述如何呼叫此工具
- 一個名字
- 一個描述
- 輸入型別和描述
- 一個輸出型別
例如,您可以檢視 PythonInterpreterTool:它有一個名稱、描述、輸入描述、輸出型別以及執行操作的 forward
方法。
當代理初始化時,工具屬性用於生成工具描述,該描述烘焙到代理的系統提示中。這讓代理知道它可以使用哪些工具以及原因。
預設工具箱
如果您安裝 smolagents
時帶有“toolkit”額外功能,它會附帶一個預設工具箱,用於增強代理功能,您可以在初始化時使用引數 add_base_tools=True
將其新增到您的代理中
- DuckDuckGo 網頁搜尋*:使用 DuckDuckGo 瀏覽器執行網頁搜尋。
- Python 程式碼直譯器:在安全環境中執行 LLM 生成的 Python 程式碼。此工具僅在您使用
add_base_tools=True
初始化 ToolCallingAgent 時才會新增到其中,因為基於程式碼的代理已經可以原生執行 Python 程式碼 - 轉錄器:一個基於 Whisper-Turbo 構建的語音轉文字管道,將音訊轉錄為文字。
您可以透過呼叫工具並傳遞其引數來手動使用工具。
# !pip install smolagents[toolkit]
from smolagents import WebSearchTool
search_tool = WebSearchTool()
print(search_tool("Who's the current president of Russia?"))
建立一個新工具
您可以建立自己的工具,用於 Hugging Face 預設工具未涵蓋的用例。例如,讓我們建立一個工具,該工具返回 Hub 上給定任務的下載量最多的模型。
您將從下面的程式碼開始。
from huggingface_hub import list_models
task = "text-classification"
most_downloaded_model = next(iter(list_models(filter=task, sort="downloads", direction=-1)))
print(most_downloaded_model.id)
此程式碼可以透過將其包裝在函式中並新增 tool
裝飾器來快速轉換為工具:這不是構建工具的唯一方法:您可以直接將其定義為 Tool 的子類,這為您提供了更大的靈活性,例如初始化重型類屬性的可能性。
讓我們看看這兩種選項是如何工作的
from smolagents import tool
@tool
def model_download_tool(task: str) -> str:
"""
This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub.
It returns the name of the checkpoint.
Args:
task: The task for which to get the download count.
"""
most_downloaded_model = next(iter(list_models(filter=task, sort="downloads", direction=-1)))
return most_downloaded_model.id
該函式需要
- 一個清晰的名稱。名稱應足以描述此工具的作用,以幫助驅動代理的 LLM 大腦。由於此工具返回任務中下載量最多的模型,我們將其命名為
model_download_tool
。 - 輸入和輸出的型別提示
- 一個描述,其中包含一個“Args:”部分,其中描述了每個引數(此時沒有型別指示,它將從型別提示中提取)。與工具名稱一樣,此描述是驅動代理的 LLM 的說明手冊,因此請不要忽視它。
所有這些元素都將在初始化時自動烘焙到代理的系統提示中:因此請努力使它們儘可能清晰!
此定義格式與 apply_chat_template
中使用的工具模式相同,唯一的區別是添加了 tool
裝飾器:在此閱讀更多關於我們的工具使用 API。
然後您可以直接初始化您的代理
from smolagents import CodeAgent, InferenceClientModel
agent = CodeAgent(tools=[model_download_tool], model=InferenceClientModel())
agent.run(
"Can you give me the name of the model that has the most downloads in the 'text-to-video' task on the Hugging Face Hub?"
)
您將獲得以下日誌
╭──────────────────────────────────────── New run ─────────────────────────────────────────╮ │ │ │ Can you give me the name of the model that has the most downloads in the 'text-to-video' │ │ task on the Hugging Face Hub? │ │ │ ╰─ InferenceClientModel - Qwen/Qwen2.5-Coder-32B-Instruct ───────────────────────────────────────────╯ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 0 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ╭─ Executing this code: ───────────────────────────────────────────────────────────────────╮ │ 1 model_name = model_download_tool(task="text-to-video") │ │ 2 print(model_name) │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ Execution logs: ByteDance/AnimateDiff-Lightning Out: None [Step 0: Duration 0.27 seconds| Input tokens: 2,069 | Output tokens: 60] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ╭─ Executing this code: ───────────────────────────────────────────────────────────────────╮ │ 1 final_answer("ByteDance/AnimateDiff-Lightning") │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ Out - Final answer: ByteDance/AnimateDiff-Lightning [Step 1: Duration 0.10 seconds| Input tokens: 4,288 | Output tokens: 148] Out[20]: 'ByteDance/AnimateDiff-Lightning'
在專用教程中閱讀更多關於工具的資訊。
多代理
多代理系統已透過 Microsoft 的框架 Autogen 引入。
在這種型別的框架中,您有多個代理協同工作來解決您的任務,而不是隻有一個。經驗上,它在大多數基準測試中都能產生更好的效能。這種更好效能的原因在概念上很簡單:對於許多工,您寧願將單元專門化於子任務,而不是使用一個全能系統。在這裡,擁有具有獨立工具集和記憶體的代理可以實現高效的專業化。例如,為什麼要用網頁搜尋代理訪問的所有網頁內容來填充程式碼生成代理的記憶體呢?最好將它們分開。
您可以使用 smolagents
輕鬆構建分層多代理系統。
為此,只需確保您的代理具有 name
和 description
屬性,然後這些屬性將被嵌入到管理器代理的系統提示中,以使其知道如何呼叫此受管代理,就像我們對工具所做的那樣。然後您可以在管理器代理初始化時在引數 managed_agents
中傳遞此受管代理。
這是一個使用我們原生 WebSearchTool 構建管理特定網頁搜尋代理的代理示例
from smolagents import CodeAgent, InferenceClientModel, WebSearchTool
model = InferenceClientModel()
web_agent = CodeAgent(
tools=[WebSearchTool()],
model=model,
name="web_search_agent",
description="Runs web searches for you. Give it your query as an argument."
)
manager_agent = CodeAgent(
tools=[], model=model, managed_agents=[web_agent]
)
manager_agent.run("Who is the CEO of Hugging Face?")
有關高效多代理實現深入示例,請參閱我們如何將多代理系統推向 GAIA 排行榜榜首。
與您的代理對話,並在炫酷的 Gradio 介面中視覺化其思想
您可以使用 GradioUI
互動式地向您的代理提交任務,並觀察其思維和執行過程,示例如下
from smolagents import (
load_tool,
CodeAgent,
InferenceClientModel,
GradioUI
)
# Import tool from Hub
image_generation_tool = load_tool("m-ric/text-to-image", trust_remote_code=True)
model = InferenceClientModel(model_id=model_id)
# Initialize the agent with the image generation tool
agent = CodeAgent(tools=[image_generation_tool], model=model)
GradioUI(agent).launch()
在底層,當用戶輸入新答案時,代理將透過 agent.run(user_request, reset=False)
啟動。reset=False
標誌意味著在啟動此新任務之前不會重新整理代理的記憶體,這使得對話可以繼續進行。
您也可以使用此 reset=False
引數來在任何其他代理應用程式中保持對話的連續性。
在 Gradio UI 中,如果您想允許使用者中斷正在執行的代理,可以透過一個觸發 agent.interrupt()
方法的按鈕來實現。這將在代理當前步驟結束時停止代理,然後引發錯誤。
下一步
最後,當您根據需要配置好代理後,就可以將其分享到 Hub!
agent.push_to_hub("m-ric/my_agent")
類似地,要載入已推送到 Hub 的代理,如果您信任其工具的程式碼,請使用
agent.from_hub("m-ric/my_agent", trust_remote_code=True)
有關更深入的用法,您將需要檢視我們的教程
< > 在 GitHub 上更新