智慧體課程文件
構建使用程式碼的 Agent
並獲得增強的文件體驗
開始使用
構建使用程式碼的 Agent
程式碼 Agent 是 smolagents
中的預設 Agent 型別。它們生成 Python 工具呼叫來執行動作,從而實現高效、富有表現力且準確的動作表示。
它們精簡的方法減少了所需動作的數量,簡化了複雜操作,並實現了對現有程式碼函式的重用。smolagents
為構建程式碼 Agent 提供了一個輕量級框架,程式碼量約 1000 行。
圖片來自論文 Executable Code Actions Elicit Better LLM Agents
為何選擇程式碼 Agent?
在多步 Agent 流程中,LLM 編寫並執行動作,通常涉及外部工具呼叫。傳統方法使用 JSON 格式指定工具名稱和引數(作為字串),系統必須解析這些資訊才能確定執行哪個工具。
然而,研究表明,直接使用程式碼能讓工具呼叫型 LLM 更有效地工作。這是 smolagents
的核心原則,正如上圖所示(該圖來自論文 Executable Code Actions Elicit Better LLM Agents)。
用程式碼而非 JSON 編寫動作有以下幾個關鍵優勢:
- 可組合性:輕鬆組合和重用動作
- 物件管理:直接處理複雜結構,如影像
- 通用性:能夠表達任何計算上可能的任務
- 對 LLM 更自然:高質量的程式碼已經存在於 LLM 的訓練資料中
程式碼 Agent 如何工作?
上圖展示了 CodeAgent.run()
的工作方式,它遵循了我們在第一單元中提到的 ReAct 框架。smolagents
中 Agent 的主要抽象是 MultiStepAgent
,它是核心構建塊。CodeAgent
是一種特殊的 MultiStepAgent
,我們將在下面的例子中看到。
一個 CodeAgent
透過一系列步驟的迴圈來執行動作,現有的變數和知識被整合到 Agent 的上下文中,並儲存在執行日誌中。
系統提示儲存在
SystemPromptStep
中,使用者查詢則記錄在TaskStep
中。然後,執行以下 while 迴圈:
2.1 方法
agent.write_memory_to_messages()
將 Agent 的日誌寫入一個 LLM 可讀的聊天訊息列表。2.2 這些訊息被髮送給一個
Model
,該模型生成一個補全。2.3 解析補全以提取動作,在我們的例子中,由於我們使用的是
CodeAgent
,這個動作應該是一個程式碼片段。2.4 執行該動作。
2.5 結果被記錄到記憶體中的一個
ActionStep
裡。
在每一步結束時,如果 Agent 包含任何函式呼叫(在 agent.step_callback
中),它們將被執行。
看幾個例子
阿福(Alfred)正在韋恩莊園策劃一場派對,他需要你的幫助來確保一切順利進行。為了協助他,我們將運用所學的關於多步 CodeAgent
如何運作的知識。

如果你還沒有安裝 smolagents
,可以執行以下命令進行安裝:
pip install smolagents -U
我們還要登入到 Hugging Face Hub,以便訪問無伺服器推理 API(Serverless Inference API)。
from huggingface_hub import login
login()
使用 smolagents 為派對選擇播放列表
音樂是一場成功派對的重要組成部分!阿福需要一些幫助來選擇播放列表。幸運的是,smolagents
能幫我們解決這個問題!我們可以構建一個能夠使用 DuckDuckGo 在網上搜索的 Agent。為了讓 Agent 能夠使用這個工具,我們在建立 Agent 時將其包含在工具列表中。

對於模型,我們將依賴 InferenceClientModel
,它提供了對 Hugging Face 的無伺服器推理 API 的訪問。預設模型是 "Qwen/Qwen2.5-Coder-32B-Instruct"
,它效能優越且可用於快速推理,但你也可以從 Hub 中選擇任何相容的模型。
執行一個 Agent 非常直接:
from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=InferenceClientModel())
agent.run("Search for the best music recommendations for a party at the Wayne's mansion.")
當你執行這個例子時,輸出將顯示正在執行的工作流步驟的跟蹤資訊。它還會打印出相應的 Python 程式碼以及訊息。
─ Executing parsed code: ────────────────────────────────────────────────────────────────────────────────────────
results = web_search(query="best music for a Batman party")
print(results)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
幾步之後,你就會看到生成的播放列表,阿福可以用它來為派對助興!🎵
使用自定義工具準備選單

現在我們已經選好了播放列表,我們需要為客人準備選單。阿福同樣可以利用 smolagents
來完成這項工作。在這裡,我們使用 @tool
裝飾器來定義一個作為工具的自定義函式。我們稍後會更詳細地介紹工具的建立,所以現在,我們只需執行程式碼即可。
正如你在下面的例子中看到的,我們將使用 @tool
裝飾器建立一個工具,並將其包含在 tools
列表中。
from smolagents import CodeAgent, tool, InferenceClientModel
# Tool to suggest a menu based on the occasion
@tool
def suggest_menu(occasion: str) -> str:
"""
Suggests a menu based on the occasion.
Args:
occasion (str): The type of occasion for the party. Allowed values are:
- "casual": Menu for casual party.
- "formal": Menu for formal party.
- "superhero": Menu for superhero party.
- "custom": Custom menu.
"""
if occasion == "casual":
return "Pizza, snacks, and drinks."
elif occasion == "formal":
return "3-course dinner with wine and dessert."
elif occasion == "superhero":
return "Buffet with high-energy and healthy food."
else:
return "Custom menu for the butler."
# Alfred, the butler, preparing the menu for the party
agent = CodeAgent(tools=[suggest_menu], model=InferenceClientModel())
# Preparing the menu for the party
agent.run("Prepare a formal menu for the party.")
Agent 將會執行幾步直到找到答案。在文件字串中明確允許的值有助於引導 Agent 使用存在的 `occasion` 引數值,並減少幻覺。
選單準備好了!🥗
在 Agent 內部使用 Python 匯入
我們已經準備好了播放列表和選單,但還需要檢查一個至關重要的細節:準備時間!
阿福需要計算一下,如果他現在開始準備,所有東西什麼時候能準備好,以防萬一需要其他超級英雄的幫助。
smolagents
專注於編寫和執行 Python 程式碼片段的 Agent,並提供沙盒執行以確保安全。
程式碼執行有嚴格的安全措施 —— 預設情況下,不在預定義安全列表中的匯入會被阻止。但是,你可以透過在 additional_authorized_imports
中以字串形式傳遞它們來授權額外的匯入。有關安全程式碼執行的更多詳細資訊,請參閱官方指南。
在建立 Agent 時,我們將使用 additional_authorized_imports
來允許匯入 datetime
模組。
from smolagents import CodeAgent, InferenceClientModel
import numpy as np
import time
import datetime
agent = CodeAgent(tools=[], model=InferenceClientModel(), additional_authorized_imports=['datetime'])
agent.run(
"""
Alfred needs to prepare for the party. Here are the tasks:
1. Prepare the drinks - 30 minutes
2. Decorate the mansion - 60 minutes
3. Set up the menu - 45 minutes
4. Prepare the music and playlist - 45 minutes
If we start right now, at what time will the party be ready?
"""
)
這些例子只是你能用程式碼 Agent 做的開始,我們已經開始看到它們在準備派對方面的實用性。你可以在 smolagents 文件中瞭解更多關於如何構建程式碼 Agent 的資訊。
總而言之,smolagents
專注於編寫和執行 Python 程式碼片段的 Agent,並提供沙盒執行以確保安全。它同時支援本地和基於 API 的語言模型,使其能夠適應各種開發環境。
將我們的自定義派對準備 Agent 分享到 Hub
如果能把我們自己製作的阿福 Agent 分享給社群,那該多棒啊!這樣一來,任何人都可以輕鬆地從 Hub 下載並直接使用這個 Agent,將哥譚市的終極派對策劃師帶到他們的指尖!讓我們實現它吧!🎉
smolagents
庫使這成為可能,它允許你與社群分享一個完整的 Agent,並下載其他人制作的 Agent 以便立即使用。就像下面這樣簡單:
# Change to your username and repo name
agent.push_to_hub('sergiopaniego/AlfredAgent')
要再次下載這個 Agent,請使用以下程式碼:
# Change to your username and repo name
alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True)
alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme")
更令人興奮的是,分享的 Agent 可以直接作為 Hugging Face Spaces 使用,讓你能夠即時與它們互動。你可以在這裡探索其他 Agent。
例如,AlfredAgent 可以在這裡找到。你可以直接在下方試用它:
你可能想知道——阿福是如何使用 smolagents
構建出這樣一個 Agent 的?透過整合多個工具,他可以像下面這樣生成一個 Agent。現在不用擔心工具的問題,因為本單元后面會有一個專門的部分詳細探討這個問題:
from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, Tool, tool, VisitWebpageTool
@tool
def suggest_menu(occasion: str) -> str:
"""
Suggests a menu based on the occasion.
Args:
occasion: The type of occasion for the party.
"""
if occasion == "casual":
return "Pizza, snacks, and drinks."
elif occasion == "formal":
return "3-course dinner with wine and dessert."
elif occasion == "superhero":
return "Buffet with high-energy and healthy food."
else:
return "Custom menu for the butler."
@tool
def catering_service_tool(query: str) -> str:
"""
This tool returns the highest-rated catering service in Gotham City.
Args:
query: A search term for finding catering services.
"""
# Example list of catering services and their ratings
services = {
"Gotham Catering Co.": 4.9,
"Wayne Manor Catering": 4.8,
"Gotham City Events": 4.7,
}
# Find the highest rated catering service (simulating search query filtering)
best_service = max(services, key=services.get)
return best_service
class SuperheroPartyThemeTool(Tool):
name = "superhero_party_theme_generator"
description = """
This tool suggests creative superhero-themed party ideas based on a category.
It returns a unique party theme idea."""
inputs = {
"category": {
"type": "string",
"description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').",
}
}
output_type = "string"
def forward(self, category: str):
themes = {
"classic heroes": "Justice League Gala: Guests come dressed as their favorite DC heroes with themed cocktails like 'The Kryptonite Punch'.",
"villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.",
"futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets."
}
return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.")
# Alfred, the butler, preparing the menu for the party
agent = CodeAgent(
tools=[
DuckDuckGoSearchTool(),
VisitWebpageTool(),
suggest_menu,
catering_service_tool,
SuperheroPartyThemeTool(),
FinalAnswerTool()
],
model=InferenceClientModel(),
max_steps=10,
verbosity_level=2
)
agent.run("Give me the best playlist for a party at the Wayne's mansion. The party idea is a 'villain masquerade' theme")
如你所見,我們建立了一個帶有多項工具的 CodeAgent
,這些工具增強了 Agent 的功能,使其成為終極派對策劃師,並準備好與社群分享!🎉
現在輪到你了:利用我們剛剛學到的知識,構建你自己的 Agent 並與社群分享吧!🕵️♂️💡
使用 OpenTelemetry 和 Langfuse 檢查我們的派對準備 Agent 📡
在阿福微調派對準備 Agent 的過程中,他對除錯執行過程感到越來越厭倦。Agent 天生具有不可預測性,難以檢查。但既然他的目標是構建終極的派對準備 Agent 並將其部署到生產環境中,他需要強大的可追溯性以便未來進行監控和分析。
smolagents
再次挺身而出!它採用了 OpenTelemetry 標準來檢測 Agent 的執行情況,實現了無縫的檢查和日誌記錄。在 Langfuse 和 SmolagentsInstrumentor
的幫助下,阿福可以輕鬆地跟蹤和分析他的 Agent 的行為。
設定過程非常簡單!
首先,我們需要安裝必要的依賴項:
pip install opentelemetry-sdk opentelemetry-exporter-otlp openinference-instrumentation-smolagents langfuse
接下來,阿福已經在 Langfuse 上建立了一個賬戶並準備好了他的 API 金鑰。如果你還沒有這樣做,可以在這裡註冊 Langfuse Cloud,或探索其他替代方案。
一旦你有了你的 API 金鑰,需要像下面這樣正確配置它們:
import os
# Get keys for your project from the project settings page: https://cloud.langfuse.com
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..."
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..."
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 EU region
# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 US region
設定好環境變數後,我們現在可以初始化 Langfuse 客戶端了。get_client() 使用環境變數中提供的憑據來初始化 Langfuse 客戶端。
from langfuse import get_client
langfuse = get_client()
# Verify connection
if langfuse.auth_check():
print("Langfuse client is authenticated and ready!")
else:
print("Authentication failed. Please check your credentials and host.")
最後,阿福準備好初始化 SmolagentsInstrumentor
並開始跟蹤他的 Agent 的效能了。
from openinference.instrumentation.smolagents import SmolagentsInstrumentor
SmolagentsInstrumentor().instrument()
阿福現在連線上了 🔌!來自 smolagents
的執行記錄正在 Langfuse 中被記錄下來,這讓他可以全面瞭解 Agent 的行為。有了這個設定,他就可以回顧之前的執行情況,並進一步完善他的派對準備 Agent。
from smolagents import CodeAgent, InferenceClientModel
agent = CodeAgent(tools=[], model=InferenceClientModel())
alfred_agent = agent.from_hub('sergiopaniego/AlfredAgent', trust_remote_code=True)
alfred_agent.run("Give me the best playlist for a party at Wayne's mansion. The party idea is a 'villain masquerade' theme")
阿福現在可以在這裡訪問這些日誌,以進行審查和分析。
與此同時,建議的播放列表為派對準備營造了完美的氛圍。很酷,對吧?🎶
現在我們已經建立了我們的第一個程式碼 Agent,讓我們來學習如何建立工具呼叫 Agent,這是 smolagents
中可用的第二種 Agent 型別。
資源
- smolagents 部落格 - smolagents 和程式碼互動簡介
- smolagents: 構建優秀的 Agent - 構建可靠 Agent 的最佳實踐
- 構建有效的 Agent - Anthropic - Agent 設計原則
- 使用 OpenTelemetry 分享執行記錄 - 關於如何設定 OpenTelemetry 來跟蹤你的 Agent 的詳細資訊。