Freigeben über


Ausführen von Agents

Die Basis-Agent-Abstraktion macht verschiedene Optionen für die Ausführung des Agents verfügbar. Anrufer können auswählen, dass null, eins oder viele Eingabemeldungen eingegeben werden sollen. Anrufer können auch zwischen Streaming und Nicht-Streaming wählen. Schauen wir uns die verschiedenen Nutzungsszenarien an.

Streaming und Nicht-Streaming

Microsoft Agent Framework unterstützt Streaming- und Nicht-Streaming-Methoden zum Ausführen eines Agents.

Verwenden Sie die RunAsync Methode für Nichtstreaming.

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

Verwenden Sie zum Streaming die RunStreamingAsync Methode.

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

Verwenden Sie die run Methode für Nichtstreaming.

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

Verwenden Sie zum Streaming die run Methode mit stream=True. Dadurch wird ein ResponseStream Objekt zurückgegeben, das asynchron durchlaufen werden kann:

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

ResponseStream

Das ResponseStream zurückgegebene run(..., stream=True) Objekt unterstützt zwei Verbrauchsmuster:

Muster 1: Asynchrone Iteration – Verarbeiten von Updates, sobald sie für die Echtzeitanzeige eingehen:

response_stream = agent.run("Tell me a story", stream=True)
async for update in response_stream:
    if update.text:
        print(update.text, end="", flush=True)

Muster 2: Direkte Fertigstellung – Iteration überspringen und die vollständige Antwort erhalten:

response_stream = agent.run("Tell me a story", stream=True)
final = await response_stream.get_final_response()
print(final.text)

Muster 3: Kombiniert – Iterieren sie für die Echtzeitanzeige, und rufen Sie dann das aggregierte Ergebnis ab:

response_stream = agent.run("Tell me a story", stream=True)

# First, iterate to display streaming output
async for update in response_stream:
    if update.text:
        print(update.text, end="", flush=True)

# Then get the complete response (uses already-collected updates, does not re-iterate)
final = await response_stream.get_final_response()
print(f"\n\nFull response: {final.text}")
print(f"Messages: {len(final.messages)}")

Agent-Ausführungsoptionen

Die Abstraktion des Basis-Agents ermöglicht das Übergeben eines Optionsobjekts für jede Agentausführung. Die Möglichkeit zum Anpassen einer Ausführung auf Abstraktionsebene ist jedoch ziemlich begrenzt. Agents können erheblich variieren und daher gibt es keine wirklich gängigen Anpassungsoptionen.

Für Fälle, in denen der Anrufer den Typ des Agents kennt, mit dem sie arbeiten, ist es möglich, typspezifische Optionen zu übergeben, um die Ausführung zuzulassen.

Hier ist beispielsweise der Agent ein ChatClientAgent Und es ist möglich, ein ChatClientAgentRunOptions Objekt zu übergeben, das von AgentRunOptions. Auf diese Weise kann der Aufrufer benutzerdefinierte Optionen ChatOptions bereitstellen, die mit allen Optionen auf Agentebene zusammengeführt werden, bevor sie an die IChatClientChatClientAgent integrierte Funktion übergeben werden.

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-Agents unterstützen das Anpassen der einzelnen Ausführungen über den options Parameter. Optionen werden als TypedDict übergeben und können sowohl zur Bauzeit (über default_options) als auch pro Ausführung (über options) festgelegt werden. Jeder Anbieter verfügt über eine eigene TypedDict-Klasse, die vollständige IDE-AutoVervollständigen und Typüberprüfung für anbieterspezifische Einstellungen bereitstellt.

Zu den gängigen Optionen gehören:

  • max_tokens: Maximale Anzahl der zu generierenden Token
  • temperature: Steuert zufallslos bei der Reaktionsgenerierung
  • model_id: Überschreiben des Modells für diese spezifische Ausführung
  • top_p: Kernsamplingparameter
  • response_format: Angeben des Antwortformats (z. B. strukturierte Ausgabe)

Hinweis

Die tools Parameter instructions bleiben als direkte Schlüsselwortargumente und werden nicht über das options Wörterbuch übergeben.

from agent_framework.openai import OpenAIChatClient, OpenAIChatOptions

# Set default options at construction time
agent = OpenAIChatClient().as_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(
    "Tell me a detailed weather forecast",
    stream=True,
    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)

Jeder Anbieter verfügt über eine eigene TypedDict-Klasse (z. B. , OpenAIChatOptions, ), AnthropicChatOptionsdie den vollständigen Satz von Optionen verfügbar macht, OllamaChatOptionsdie von diesem Anbieter unterstützt werden.

Wenn sowohl als auch default_options pro Ausführung bereitgestellt werden, haben die Optionen pro Ausführung options Vorrang und werden mit den Standardwerten zusammengeführt.

Antworttypen

Sowohl Streaming- als auch Nicht-Streaming-Antworten von Agents enthalten alle vom Agent produzierten Inhalte. Inhalte können Daten enthalten, die nicht das Ergebnis (d. h. die Antwort auf die Benutzerfrage) vom Agent sind. Beispiele für andere zurückgegebene Daten sind Funktionstoolaufrufe, Ergebnisse von Funktionstoolaufrufen, Grundursachentext, Statusaktualisierungen und vieles mehr.

Da nicht alle zurückgegebenen Inhalte das Ergebnis sind, ist es wichtig, nach bestimmten Inhaltstypen zu suchen, wenn Sie versuchen, das Ergebnis vom anderen Inhalt zu isolieren.

Um das Textergebnis aus einer Antwort zu extrahieren, müssen alle TextContent Elemente aus allen ChatMessages Elementen aggregiert werden. Um dies zu vereinfachen, steht eine Text Eigenschaft für alle Antworttypen zur Verfügung, die alle TextContentaggregiert.

Für den Nicht-Streaming-Fall wird alles in einem AgentResponse Objekt zurückgegeben. AgentResponse ermöglicht den Zugriff auf die erzeugten Nachrichten über die Messages Eigenschaft.

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

Für den Streamingfall werden Objekte gestreamt, AgentResponseUpdate während sie produziert werden. Jedes Update kann einen Teil des Ergebnisses des Agents und auch verschiedene andere Inhaltselemente enthalten. Ähnlich wie beim Nicht-Streaming-Fall ist es möglich, die Text Eigenschaft zu verwenden, um den Teil des Ergebnisses abzurufen, der in der Aktualisierung enthalten ist, und einen Drilldown in das Detail über die Contents Eigenschaft durchzuführen.

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

Für den Nicht-Streaming-Fall wird alles in einem AgentResponse Objekt zurückgegeben. AgentResponse ermöglicht den Zugriff auf die erzeugten Nachrichten über die messages Eigenschaft.

Um das Textergebnis aus einer Antwort zu extrahieren, müssen alle TextContent Elemente aus allen Message Elementen aggregiert werden. Um dies zu vereinfachen, steht eine Text Eigenschaft für alle Antworttypen zur Verfügung, die alle TextContentaggregiert.

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}")

Für den Streaming-Fall werden Objekte gestreamt, AgentResponseUpdate während sie über die ResponseStream zurückgegebene run(..., stream=True)von . Jedes Update kann einen Teil des Ergebnisses des Agents und auch verschiedene andere Inhaltselemente enthalten. Ähnlich wie beim Nicht-Streaming-Fall ist es möglich, die text Eigenschaft zu verwenden, um den Teil des Ergebnisses abzurufen, der in der Aktualisierung enthalten ist, und einen Drilldown in das Detail über die contents Eigenschaft durchzuführen.

response_stream = agent.run("What is the weather like in Amsterdam?", stream=True)
async for update in response_stream:
    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}")

# Get the aggregated final response after streaming
final = await response_stream.get_final_response()
print(f"Complete text: {final.text}")

Nachrichtentypen

Eingaben und Ausgaben von Agents werden als Nachrichten dargestellt. Nachrichten werden in Inhaltselemente unterteilt.

Das Microsoft Agent Framework verwendet die Nachrichten- und Inhaltstypen, die von den Microsoft.Extensions.AI Abstraktionen bereitgestellt werden. Nachrichten werden durch die ChatMessage Klasse dargestellt, und alle Inhaltsklassen erben von der Basisklasse AIContent .

Es gibt verschiedene AIContent Unterklassen, die verwendet werden, um verschiedene Inhaltstypen darzustellen. Einige werden als Teil der Basisabstraktionen Microsoft.Extensions.AI bereitgestellt, aber Anbieter können bei Bedarf auch eigene Typen hinzufügen.

Hier sind einige beliebte Typen von Microsoft.Extensions.AI:

Typ Description
TextContent Textinhalte, die sowohl von einem Benutzer als auch von Einem Entwickler eingegeben werden können, und die Ausgabe des Agents. Enthält in der Regel das Textergebnis eines Agents.
DataContent Binäre Inhalte, die sowohl Eingabe als auch Ausgabe sein können. Kann verwendet werden, um Bild-, Audio- oder Videodaten an den Agent (sofern unterstützt) zu übergeben.
UriContent Eine URL, die in der Regel auf gehostete Inhalte verweist, z. B. ein Bild, Audio oder Video.
FunctionCallContent Eine Anforderung eines Rückschlussdiensts zum Aufrufen eines Funktionstools.
FunctionResultContent Das Ergebnis eines Funktionstoolaufrufs.

Das Python Agent Framework verwendet Nachrichten- und Inhaltstypen aus dem agent_framework Paket. Nachrichten werden durch die Message Klasse dargestellt, und alle Inhaltsklassen erben von der Basisklasse Content .

Es gibt verschiedene Content Unterklassen, die verwendet werden, um verschiedene Inhaltstypen darzustellen:

Typ Description
Content Einheitlicher Inhaltstyp mit Factorymethoden (Content.from_text(), Content.from_data(), Content.from_uri()). Verwenden Sie die type Eigenschaft, um den Inhaltstyp ("text", "data", "uri") zu überprüfen.
FunctionCallContent Eine Anforderung eines KI-Diensts zum Aufrufen eines Funktionstools.
FunctionResultContent Das Ergebnis eines Funktionstoolaufrufs.
ErrorContent Fehlerinformationen bei der Verarbeitung.
UsageContent Tokenverwendungs- und Abrechnungsinformationen vom KI-Dienst.

Hier erfahren Sie, wie Sie mit verschiedenen Inhaltstypen arbeiten:

from agent_framework import Message, Content

# Create a text message
text_message = Message(role="user", contents=["Hello!"])

# Create a message with multiple content types
image_data = b"..."  # your image bytes
mixed_message = Message(
    role="user",
    contents=[
        Content.from_text("Analyze this image:"),
        Content.from_data(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 content.type == "text":
            print(f"Text: {content.text}")
        elif content.type == "data":
            print(f"Data URI: {content.uri}")
        elif content.type == "uri":
            print(f"External URI: {content.uri}")

Nächste Schritte