共用方式為


執行代理程式

基本代理程式抽象概念會公開執行代理程式的各種選項。 呼叫者可選擇提供零、一或多個輸入訊息。 來電者還可以在流媒體和非流媒體之間進行選擇。 讓我們深入研究不同的使用場景。

串流和非串流

Microsoft Agent Framework 支援串流與非串流兩種方式來執行代理程式。

對於非串流,請使用RunAsync

Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));

對於串流,請使用RunStreamingAsync

await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.Write(update);
}

對於非串流,請使用run

result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)

對於串流,請使用run_stream

async for update in agent.run_stream("What is the weather like in Amsterdam?"):
    if update.text:
        print(update.text, end="", flush=True)

代理程式執行選項

基本代理程式抽象化允許為每個代理程式執行傳遞選項物件,但在抽象層級自訂執行的能力非常有限。 代理可能會有很大差異,因此沒有真正常見的自定義選項。

對於呼叫者知道他們正在使用的代理的類型,可以傳遞特定於類型的選項以允許自訂運行。

例如,這裡的代理程式是 , ChatClientAgent 並且可以傳遞繼 ChatClientAgentRunOptions 承自 AgentRunOptions的物件。 這允許呼叫者提供與任何代理級別選項合併的自定義ChatOptions,然後再傳遞給構建的IChatClientChatClientAgent

var chatOptions = new ChatOptions() { Tools = [AIFunctionFactory.Create(GetWeather)] };
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", options: new ChatClientAgentRunOptions(chatOptions)));

Python 代理程式支援透過 options 參數自訂每次執行。 選項以 TypedDict 形式傳遞,並可在建構時(透過 default_options)或每次執行(透過 options)設定。 每個提供者都有自己的 TypedDict 類別,提供完整的 IDE 自動補全功能,並為提供者特定設定進行類型檢查。

常用選項包含:

  • max_tokens:要產生的權杖數目上限
  • temperature:控制響應生成的隨機性
  • model_id:覆寫此特定執行的模型
  • top_p: 核取樣參數
  • response_format:指定回應格式(例如結構化輸出)

備註

toolsinstructions參數仍作為直接關鍵字參數,不會透過options字典傳遞。

from agent_framework.openai import OpenAIChatClient, OpenAIChatOptions

# Set default options at construction time
agent = OpenAIChatClient().create_agent(
    instructions="You are a helpful assistant",
    default_options={
        "temperature": 0.7,
        "max_tokens": 500
    }
)

# Run with custom options (overrides defaults)
# OpenAIChatOptions provides IDE autocomplete for all OpenAI-specific settings
options: OpenAIChatOptions = {
    "temperature": 0.3,
    "max_tokens": 150,
    "model_id": "gpt-4o",
    "presence_penalty": 0.5,
    "frequency_penalty": 0.3
}

result = await agent.run(
    "What is the weather like in Amsterdam?",
    options=options
)

# Streaming with custom options
async for update in agent.run_stream(
    "Tell me a detailed weather forecast",
    options={"temperature": 0.7, "top_p": 0.9},
    tools=[additional_weather_tool]  # tools is still a keyword argument
):
    if update.text:
        print(update.text, end="", flush=True)

每個提供者都有自己的 TypedDict 類別(例如 OpenAIChatOptions, , AnthropicChatOptions), OllamaChatOptions該類別會揭露該提供者所支援的完整選項集合。

default_options 同時提供 和 每次運行 options 時,每次運行選項優先,並與預設值合併。

回應類型

來自客服人員的串流和非串流回應都包含客服人員產生的所有內容。 內容可能包含與代理人非結果(即用戶問題的答案)有關的資料。 傳回的其他資料範例包括函式工具呼叫、函式工具呼叫的結果、推理文字、狀態更新等等。

由於並非所有傳回的內容都是結果,因此在嘗試將結果與其他內容隔離時,請務必尋找特定的內容類型。

若要從回應擷取文字結果, TextContent 必須彙總所有 ChatMessages 專案中的所有專案。 為了簡化說明,所有 Text 回應類型都有一個屬性,可以聚合所有 TextContent

針對非串流案例,所有專案都會傳回在一個 AgentResponse 物件中。 AgentResponse 允許透過屬性存取 Messages 產生的訊息。

var response = await agent.RunAsync("What is the weather like in Amsterdam?");
Console.WriteLine(response.Text);
Console.WriteLine(response.Messages.Count);

針對串流案例, AgentResponseUpdate 物件會在產生時串流。 每次更新可能包含代理的部分結果,以及其他各種內容項目。 與非串流案例類似,可以使用 Text 屬性來取得更新中包含的結果部分,並透過屬性切 Contents 入詳細數據。

await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?"))
{
    Console.WriteLine(update.Text);
    Console.WriteLine(update.Contents.Count);
}

針對非串流案例,所有專案都會傳回在一個 AgentResponse 物件中。 AgentResponse 允許透過屬性存取 messages 產生的訊息。

若要從回應擷取文字結果, TextContent 必須彙總所有 ChatMessage 專案中的所有專案。 為了簡化說明,所有 Text 回應類型都有一個屬性,可以聚合所有 TextContent

response = await agent.run("What is the weather like in Amsterdam?")
print(response.text)
print(len(response.messages))

# Access individual messages
for message in response.messages:
    print(f"Role: {message.role}, Text: {message.text}")

針對串流案例, AgentResponseUpdate 物件會在產生時串流。 每次更新可能包含代理的部分結果,以及其他各種內容項目。 與非串流案例類似,可以使用 text 屬性來取得更新中包含的結果部分,並透過屬性切 contents 入詳細數據。

async for update in agent.run_stream("What is the weather like in Amsterdam?"):
    print(f"Update text: {update.text}")
    print(f"Content count: {len(update.contents)}")

    # Access individual content items
    for content in update.contents:
        if hasattr(content, 'text'):
            print(f"Content: {content.text}")

訊息類型

代理程式的輸入和輸出會表示為訊息。 訊息會細分為內容項目。

Microsoft Agent Framework 會使用抽象概念所 Microsoft.Extensions.AI 提供的訊息和內容類型。 訊息由類別表示 ChatMessage ,而所有內容類別都繼承自基類 AIContent

存在各種 AIContent 子類別,可用來表示不同類型的內容。 有些是作為基本 Microsoft.Extensions.AI 抽象的一部分提供的,但提供者也可以根據需要添加自己的類型。

以下是一些流行的類型 Microsoft.Extensions.AI

類型 Description
TextContent 文字內容可以是輸入的,例如來自使用者或開發者,也可以是代理人的輸出。 通常包含來自客服專員的文字結果。
DataContent 既可以是輸入,也可以是輸出的二進位內容。 可用於將影像、音訊或視訊資料傳遞至代理程式或從代理程式傳遞(如果支援)。
UriContent 一個通常指向託管內容的網址,例如圖片、音訊或影片。
FunctionCallContent 推論服務叫用函式工具的要求。
FunctionResultContent 函數工具呼叫的結果。

Python 代理程式架構會使用套件中的 agent_framework 訊息和內容類型。 訊息由類別表示 ChatMessage ,而所有內容類別都繼承自基類 BaseContent

存在各種 BaseContent 子類別,可用來表示不同類型的內容:

類型 Description
TextContent 可以是代理程式輸入和輸出的文字內容。 通常包含來自客服專員的文字結果。
DataContent 二進位內容以資料 URI 表示(例如 base64 編碼的影像)。 可用來將二進位資料傳遞至代理程式或從代理程式傳遞。
UriContent 指向託管內容的 URI,例如影像、音訊檔案或文件。
FunctionCallContent AI 服務叫用函式工具的要求。
FunctionResultContent 函數工具呼叫的結果。
ErrorContent 處理失敗時的錯誤資訊。
UsageContent 來自 AI 服務的權杖使用情況和計費資訊。

以下是如何使用不同的內容類型:

from agent_framework import ChatMessage, TextContent, DataContent, UriContent

# Create a text message
text_message = ChatMessage(role="user", text="Hello!")

# Create a message with multiple content types
image_data = b"..."  # your image bytes
mixed_message = ChatMessage(
    role="user",
    contents=[
        TextContent("Analyze this image:"),
        DataContent(data=image_data, media_type="image/png"),
    ]
)

# Access content from responses
response = await agent.run("Describe the image")
for message in response.messages:
    for content in message.contents:
        if isinstance(content, TextContent):
            print(f"Text: {content.text}")
        elif isinstance(content, DataContent):
            print(f"Data URI: {content.uri}")
        elif isinstance(content, UriContent):
            print(f"External URI: {content.uri}")

後續步驟