您可以提供內嵌 Python 程式碼做為代理程式的工具,彈性擴充代理程式的功能。這段程式碼可以接受代理程式提供的輸入內容,並傳回代理程式在對話中使用的結果。您可以實作任何自訂邏輯、連結至專屬 API 或資料庫,並確保需要精確度的工作能獲得確定性結果。
名稱與說明
建立工具時,工具名稱和要呼叫的主要函式名稱應相同,且採用蛇形命名法。
定義 Python 工具時,說明字串是不可或缺的一環。 函式的 docstring 會做為工具說明提供給使用該工具的代理。請將文件字串視為提示的延伸。 清楚、詳盡且結構良好的 docstring 會直接影響模型對工具功能、使用時機和提供哪些引數的理解程度。這是選用可靠且準確工具的關鍵。
環境
在 Python 工具程式碼中,您可以存取特定類別和函式,協助您編寫程式碼。詳情請參閱 Python 執行階段參考資料。
舉例來說,context 物件是全域可用的變數,可提供目前對話狀態的快照。您不需要匯入或定義為參數,可以直接存取。其中包含執行複雜邏輯的重要資訊。
以下是情境物件中可用的鍵:
function_call_id:正在執行的特定工具呼叫專屬 ID。user_content:包含使用者最新訊息的字典,包括文字和角色。這是最常用的屬性之一。state:代表工作階段狀態的字典。您可以使用這項功能儲存及擷取需要在對話中保留的變數 (使用者個人資料、購物車內容等)。events:對話記錄中所有事件的清單,可讓您建構脈絡感知能力更複雜的工具。session_id:整個對話工作階段的專屬 ID。invocation_id:目前對話輪次的專屬 ID。agent_name:執行工具的代理程式名稱。
呼叫其他工具的 Python 工具
定義 Python 程式碼工具時,您可以明確呼叫在代理程式應用程式中定義的其他工具。舉例來說,如果您有名為 crm_service_get_cart_information 的 OpenAPI 工具,可以使用下列程式碼呼叫該工具:
# Deterministically call another tool from this tool.
# This syntax for OpenAPI spec tool is:
# tools.<tool_name>_<endpoint_name>({tool_args})
res = tools.crm_service_get_cart_information({})
程式碼範例
下列各節提供範例。
取得上次使用者輸入內容
這個範例示範基本功能:存取使用者最近的訊息。這項工具會檢查 context.user_content 物件,並從上一個使用者回合中擷取文字。如果工具需要根據使用者剛才說的內容直接執行動作,就必須採用這種模式。
from typing import Optional
# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def get_last_user_utterance() -> Optional[str]:
"""
Retrieves the most recent message sent by the user from the conversation history.
Returns:
The text of the last user message, or None if no user messages are found.
"""
# The 'context.user_content' contains the last input data
# provided by the user.
# We can filter it to find only the text input from the user.
user_messages = [
part["text"] for part in context.user_content["parts"]
if context.user_content["role"] == "user"
]
if user_messages:
# The most recent message is the first one in the list.
return user_messages[0]
return None
取得及更新變數
語言模型無法直接修改工作階段狀態。 這是刻意設計的行為,可確保狀態變更以可控且可預測的方式處理。狀態只能透過兩種機制修改:Python 工具或回呼。
這個範例說明 Python 工具如何管理狀態。這項工具會先從 context.state 讀取目前的 customer_profile。
然後執行其業務邏輯 (新增點數),並將更新後的設定檔寫回 context.state。在工作階段的其餘時間,代理程式和其他工具都可以使用這個新狀態。
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any
# Using Pydantic defines the expected structure of your state variables. This makes your code more reliable and easier to
# debug.
class CustomerProfile(BaseModel):
email: Optional[str] = None
loyalty_points: int = Field(default=0, ge=0) # Must be >= 0
plan: str = "Standard"
# Docstrings in tools are important because they are directly
# sent to the model as the description for the tool. You should
# think of docstrings as an extension of prompting. Clear and
# descriptive docstrings will yield higher quality tool
# selection from the model.
def update_customer_loyalty_points(points_to_add: int) -> Dict[str, Any]:
"""
Adds loyalty points to the customer's profile and returns the updated profile.
Args:
points_to_add: The number of loyalty points to add to the existing total.
Returns:
A dictionary containing the customer's updated profile information.
"""
# 1. Get the current profile data from the session state.
# The .get() method safely returns an empty dict if
# 'customer_profile' doesn't exist.
current_profile_data = context.state.get("customer_profile", {})
# 2. Load the data into a Pydantic model for validation and easy access.
profile = CustomerProfile(**current_profile_data)
# 3. Perform the business logic.
# Print statements can be used for debugging and will show
# up in the tracing details.
profile.loyalty_points += points_to_add
print(f"Updated loyalty points to: {profile.loyalty_points}")
# 4. Save the updated data back into the session state.
# .model_dump() converts the Pydantic model back to a
# dictionary.
context.state["customer_profile"] = profile.model_dump()
return context.state["customer_profile"]
外部網路要求
Python 工具可以發出外部網路要求,這對於擷取即時資料或整合沒有 OpenAPI 規格的第三方服務很有幫助。這項功能提供彈性替代方案,可取代以 OpenAPI 為基礎的工具。 本範例使用標準要求程式庫 (環境中提供) 呼叫公開 API,並擷取隨機事實。
from typing import Optional
# Docstrings in tools are important because they are directly sent to the model as the
# description for the tool. You should think of docstrings as an extension of prompting.
# Clear and descriptive docstrings will yield higher quality tool selection from the model.
def get_random_fact() -> Optional[str]:
"""
Fetches a random fact from a public API.
Returns:
A string containing the fact on success, or None if an error occurs.
"""
# The 'ces_requests' library is inspired by 'requests', a standard and powerful way in Python
# to make HTTP network calls to any external API, just like you would with `curl` or a web browser.
url = "https://uselessfacts.jsph.pl/api/v2/facts/random"
try:
# This example calls a public API that is completely open and requires no authentication
# (like an API key). Many other APIs for services like weather or e-commerce require you
# to send credentials, often as an API key in the request headers or parameters.
res = ces_requests.get(url=url, json=request_body, headers=headers)
# Example POST request
#res = ces_requests.post(url=url, json=request_body, headers=headers)
# This is a standard practice with 'ces_requests' to check if the call was successful. It will
# raise an error for statuses like 404 or 500.
res.raise_for_status()
fact_data = res.json()
return fact_data.get("text")
except:
return None