Spouštění agentů

Abstrakce základního agenta zveřejňuje různé možnosti spuštění agenta. Volající se můžou rozhodnout zadat nula, jednu nebo mnoho vstupních zpráv. Volající si také můžou vybrat mezi streamováním a ne streamingem. Pojďme se podívat na různé scénáře použití.

Streamování a streamování bez streamování

Microsoft Agent Framework podporuje metody streamování i metody bez streamování pro spuštění agenta.

Pro jiné než streamování použijte metodu RunAsync .

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

Pro streamování použijte metodu RunStreamingAsync .

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

Pro jiné než streamování použijte metodu run .

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

Pro streamování použijte metodu run s stream=True. Tím se vrátí ResponseStream objekt, který se dá itestrovat asynchronně:

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

Objekt ResponseStream vrácený run(..., stream=True) pomocí dvou vzorů spotřeby:

Model 1: Asynchronní iterace – aktualizace procesů při jejich doručení pro zobrazení v reálném čase:

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)

Model 2: Přímá finalizace – přeskočení iterace a získání úplné odpovědi:

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

Vzor 3: Kombinace – iterace pro zobrazení v reálném čase a získání agregovaného výsledku:

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

Pokud se vaše aplikace může před použitím úplného streamu zastavit, použijte ResponseStream ho jako správce kontextu asynchronního kontextu, aby se podkladový stream zprostředkovatele brzy break zavřel:

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

async with response_stream:
    async for update in response_stream:
        if update.text:
            print(update.text, end="", flush=True)
        if should_stop(update):
            break

Úplná spotřeba, chyby datových proudů await response_stream.close()a ukončení async with bloku uvolní podkladový stream. Holý break bez async with zajištění deterministického čištění.

Před zahájením spotřeby můžete zaregistrovat seřazené aktualizace a konečné brány s with_update_gate() a with_result_gate(). Brána se vrátí None , aby byla povolena hodnota nebo vyvolá výjimku, která ji zablokuje. Použít with_update_transform() a with_result_transform() kdy musí být obsah nahrazen.

Volání buffer_updates() , kdy by neměla být vydána žádná aktualizace, dokud stream nedokončí a každá brána bude úspěšná. Pokud transformace výsledku nahradí konečnou odpověď, předejte result_to_updates ji, aby stream mohl znovu sestavit aktualizace v vyrovnávací paměti z tohoto autoritativního výsledku. Starší buffered_and_gated() pomocník je zastaralý.

Úplný příklad řazení bran, transformací, vyrovnávací paměti, finalizace a vyčištění najdete v ukázce ResponseStream.

V Go RunText vrátí ResponseStream iterátor párů (ResponseUpdate, error) .

V případě ne streamingu zavolejte Collect() stream, aby se všechny aktualizace shromáždily do jedné odpovědi:

resp, err := a.RunText(ctx, "What is the weather like in Amsterdam?").Collect()
fmt.Println(resp, err)

Pro streamování iterujte stream přímo pomocí smyčky range :

for update, err := range a.RunText(ctx, "What is the weather like in Amsterdam?", agent.Stream(true)) {
    fmt.Print(update, err)
}

Možnosti spuštění agenta

Abstrakce základního agenta umožňuje předat objekt možností pro každé spuštění agenta, ale schopnost přizpůsobit spuštění na úrovni abstrakce je poměrně omezená. Agenti se můžou výrazně lišit, a proto neexistují skutečně běžné možnosti přizpůsobení.

V případech, kdy volající zná typ agenta, se kterým pracuje, je možné předat konkrétní možnosti pro povolení přizpůsobení spuštění.

Zde je například agent a ChatClientAgent je možné předat ChatClientAgentRunOptions objekt, který dědí z AgentRunOptions. Volající tak může poskytnout vlastní ChatOptions , které se sloučí s možnostmi na úrovni agenta před předáním integrovanému IChatClientChatClientAgent agentu.

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 agenti podporují přizpůsobení jednotlivých spuštění prostřednictvím parametru options. Možnosti se předávají jako TypedDict a lze je nastavit v době výstavby (prostřednictvím default_options) a podle běhu (prostřednictvím options). Každý poskytovatel má svou vlastní třídu TypedDict, která poskytuje úplné automatické dokončování IDE a kontrolu typů pro nastavení specifické pro zprostředkovatele.

Mezi běžné možnosti patří:

  • max_tokens: Maximální počet tokenů, které se mají vygenerovat
  • temperature: Řídí náhodnost při generování odpovědí.
  • model: Přepsání modelu pro toto konkrétní spuštění
  • top_p: Parametr vzorkování vzorků na vzorkování vzorků
  • response_format: Zadejte formát odpovědi (např. strukturované výstupy).

Poznámka:

tools Parametry instructions zůstanou jako argumenty přímého klíčového slova a nepředají se prostřednictvím slovníkuoptions.

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

Každý poskytovatel má svou vlastní třídu TypedDict (např OpenAIChatOptions. , AnthropicChatOptions, OllamaChatOptions), která zveřejňuje úplnou sadu možností podporovaných tímto poskytovatelem.

Pokud jsou k dispozici možnosti default_options pro jednotlivé spuštění i pro jednotlivá spuštění options , mají přednost a slučují se s výchozími nastaveními.

Když se zkombinují nástroje na úrovni agenta a nástroje na úrovni spuštění, je jedno mapování, jako {"type": "web_search"} je například jeden nástroj zprostředkovatele. Mapování není rozbalené do svých klíčů.

Možnosti se předávají jako variadické agent.Option argumenty. Mezi dostupné možnosti patří:

  • agent.Stream(true) – Povolení streamování
  • agent.WithSession(session) - Připojení relace pro více konverzací
  • agent.WithStructuredOutput(&v) – Vyžádání strukturovaného výstupu do typové hodnoty
  • agent.WithResponseFormat(format) – Zadejte formát odpovědi.
  • agent.WithTool(tool) - Přidání nástroje pro toto spuštění
  • agent.AllowBackgroundResponses(true) - Povolit odpovědi na pozadí
resp, err := a.RunText(ctx, "Tell me a joke.",
    agent.Stream(true),
    agent.WithSession(session),
).Collect()

Typy odpovědí

Streamované i nestreamové odpovědi z agentů obsahují veškerý obsah vytvořený agentem. Obsah může obsahovat data, která nejsou výsledkem (tj. odpověď na otázku uživatele) z agenta. Mezi vrácená data patří volání nástroje funkcí, výsledky volání nástrojů funkcí, odůvodnění textu, aktualizace stavu a mnoho dalších.

Vzhledem k tomu, že ne veškerý vrácený obsah je výsledkem, je důležité při pokusu o izolaci výsledku od jiného obsahu hledat konkrétní typy obsahu.

Chcete-li extrahovat výsledek textu z odpovědi, je potřeba agregovat všechny TextContent položky ze všech ChatMessages položek. Pro zjednodušení je Text vlastnost k dispozici pro všechny typy odpovědí, které agregují všechny TextContent.

V případě nestreamovaného případu se vše vrátí v jednom AgentResponse objektu. AgentResponse umožňuje přístup k vytvořeným zpráv prostřednictvím Messages vlastnosti.

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

V případě AgentResponseUpdate streamování se objekty streamují při jejich generování. Každá aktualizace může obsahovat část výsledku z agenta a také různé další položky obsahu. Podobně jako u případu bez streamování je možné pomocí Text vlastnosti získat část výsledku obsaženou v aktualizaci a přejít k podrobnostem prostřednictvím Contents vlastnosti.

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

V případě nestreamovaného případu se vše vrátí v jednom AgentResponse objektu. AgentResponse umožňuje přístup k vytvořeným zpráv prostřednictvím messages vlastnosti.

Chcete-li extrahovat výsledek textu z odpovědi, je potřeba agregovat všechny TextContent položky ze všech Message položek. Pro zjednodušení je Text vlastnost k dispozici pro všechny typy odpovědí, které agregují všechny 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}")

V případě streamování se objekty streamují tak, AgentResponseUpdate jak se vytvářejí prostřednictvím ResponseStream vrácené run(..., stream=True). Každá aktualizace může obsahovat část výsledku z agenta a také různé další položky obsahu. Podobně jako u případu bez streamování je možné pomocí text vlastnosti získat část výsledku obsaženou v aktualizaci a přejít k podrobnostem prostřednictvím contents vlastnosti.

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

ResponseStream *agent.ResponseUpdate získá hodnoty. Každá aktualizace obsahuje:

  • Contents - Řez message.Content hodnot, jako je text, volání funkcí a použití
  • Role - Role zprávy, jako je asistent nebo systém
  • MessageID / ResponseID - Identifikátory zprávy a odpovědi

Pokud chcete získat výsledek celého textu z odpovědi, která není streamovaná, použijte Collect():

resp, err := a.RunText(ctx, "What is the weather like in Amsterdam?").Collect()
fmt.Println(resp, err)

Typy zpráv

Vstupy a výstupy z agentů jsou reprezentovány jako zprávy. Zprávy jsou rozdělené na položky obsahu.

Rozhraní agenta Microsoft používá typy zpráv a obsahu poskytované Microsoft.Extensions.AI abstrakce. Zprávy jsou reprezentovány ChatMessage třídou a všechny třídy obsahu dědí ze základní AIContent třídy.

Existují různé AIContent podtřídy, které se používají k reprezentaci různých typů obsahu. Některé jsou poskytovány jako součást základní Microsoft.Extensions.AI abstrakce, ale poskytovatelé mohou také přidat vlastní typy tam, kde je to potřeba.

Tady je několik oblíbených typů z Microsoft.Extensions.AI:

Typ Description
TextContent Textový obsah, který může být vstupní, například od uživatele nebo vývojáře, a výstup z agenta. Obvykle obsahuje textový výsledek z agenta.
DataContent Binární obsah, který může být vstupní i výstupní. Dá se použít k předávání obrázků, zvukových dat nebo dat videa do a z agenta (kde je to podporováno).
UriContent Adresa URL, která obvykle odkazuje na hostovaný obsah, jako je obrázek, zvuk nebo video.
FunctionCallContent Požadavek odvozované služby pro vyvolání nástroje funkce
FunctionResultContent Výsledek vyvolání nástroje funkce.

Rozhraní agenta Python používá typy zpráv a obsahu z balíčku agent_framework. Zprávy jsou reprezentovány Message třídou a všechny položky obsahu jsou reprezentovány Content třídou diskriminovanou type vlastností.

Veškerý obsah je reprezentován sjednocenou Content třídou s metodami továrny pro každý typ obsahu. type Pomocí vlastnosti zkontrolujte typ obsahu. K dispozici jsou následující typy obsahu:

Typ obsahu Metoda továrny Description
"text" Content.from_text() Textový obsah pro vstup a výstup Obvykle obsahuje textový výsledek z agenta.
"text_reasoning" Content.from_text_reasoning() Zdůvodnění textu z modelů, které podporují řetězové myšlení. Může obsahovat chráněná data.
"data" Content.from_data(), Content.from_uri() Binární obsah kódovaný jako identifikátor URI dat. Používá se pro obrázky, zvuk, video a dokumenty.
"uri" Content.from_uri() Adresa URL odkazující na hostovaný obsah, jako je obrázek, zvuk nebo video.
"error" Content.from_error() Informace o chybě při zpracování se nezdaří. Obsahuje volitelný kód chyby a podrobnosti.
"function_call" Content.from_function_call() Požadavek služby AI k vyvolání nástroje funkce
"function_result" Content.from_function_result() Výsledek vyvolání nástroje funkce.
"usage" Content.from_usage() Využití tokenů a fakturační údaje ze služby AI
"hosted_file" Content.from_hosted_file() Odkaz na soubor hostovaný poskytovatelem (například nahraný do OpenAI).
"hosted_vector_store" Content.from_hosted_vector_store() Odkaz na vektorové úložiště hostované poskytovatelem.
"code_interpreter_tool_call" Content.from_code_interpreter_tool_call() Požadavek služby AI ke spuštění kódu prostřednictvím interpretu kódu.
"code_interpreter_tool_result" Content.from_code_interpreter_tool_result() Výsledek spuštění interpreta kódu.
"image_generation_tool_call" Content.from_image_generation_tool_call() Žádost služby AI o vygenerování image
"image_generation_tool_result" Content.from_image_generation_tool_result() Výsledek požadavku na generování image.
"mcp_server_tool_call" Content.from_mcp_server_tool_call() Žádost o vyvolání nástroje na serveru MCP
"mcp_server_tool_result" Content.from_mcp_server_tool_result() Výsledek vyvolání nástroje serveru MCP.
"shell_tool_call" Content.from_shell_tool_call() Požadavek služby AI ke spouštění příkazů prostředí.
"shell_tool_result" Content.from_shell_tool_result() Agregovaný výsledek volání nástroje prostředí.
"shell_command_output" Content.from_shell_command_output() Výstup spuštění jednoho příkazu prostředí.
"function_approval_request" Content.from_function_approval_request() Žádost o schválení uživatele před provedením volání funkce
"function_approval_response" Content.from_function_approval_response() Odpověď uživatele na žádost o schválení funkce.
"oauth_consent_request" Content.from_oauth_consent_request() Žádost uživatele o dokončení souhlasu OAuth prostřednictvím poskytnutého odkazu

Streamování foundry i odpovědi bez streamování můžou zahrnovat oauth_consent_request obsah, když sada nástrojů nebo hostovaný nástroj MCP vyžaduje souhlas uživatele. Zkontrolujte obsah odpovědi nebo user_input_requests namísto předpokladu, že odpověď, která není streamovaná, obsahuje pouze text. Informace o nastavení a omezeních sady nástrojů najdete v tématu Sada nástrojů Foundry.

Obsah volání funkce také zveřejňuje vlastnictví provádění. hosted=True znamená, že poskytovatel nebo služba volání spustí, takže ho rozhraní Agent Framework nespustí místně. server_name popisuje hranici hostovaného serveru, ale neprovádí volání hostované samostatně.

Zprostředkovatel a metadata protokolu vlastněná architekturou patří do oboru názvů additional_propertiesna jedné úrovni, například core, openai, foundrynebo a2a. Používejte get_namespaced_value() a with_namespaced_value() při čtení nebo aktualizaci hodnot oboru názvů tak, aby adaptéry zachovaly pravidla kopírování a slučování architektury.

Sloučitelné datové proudy ContentChatResponseUpdatea AgentResponseUpdate hodnoty mohou být nastaveny "append"merge_mode na přírůstkový rozdíl nebo "replace" pro autoritativní datovou část nebo snímek zprávy. Konečná agregace odpovědí spotřebovává instrukce streamování a vymaže úroveň merge_modeobsahu .

Odmítnutí poskytovatele zůstávají viditelná jako Content(type="text"). Když poskytovatel zveřejňuje sémantiku odmítnutí, Python zachová experimentální serializovatelnou značku additional_properties["core"]["model_output_kind"] == "refusal". Extrakce strukturovaného výstupu neanalyduje text nesoucí tuto značku.

Tady je postup, jak pracovat s různými typy obsahu:

from agent_framework import Message, Content

# A bare string creates one text content item
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}")

Holý řetězec a seznam řetězců s jednou položkou jsou ekvivalentní: Message("user", "Hello!") a Message("user", ["Hello!"]) každý z nich vytvoří jednu textovou položku obsahu.

Rozhraní agenta Go používá typy zpráv a obsahu z message balíčku. Aktualizace odpovědí mohou obsahovat více položek obsahu; zkontrolujte jednotlivé položky potřebného typu obsahu.

V případě streamování se aktualizace aktualizují jednotlivě, jakmile dorazí:

for update, err := range a.RunText(ctx, "Tell me a story.", agent.Stream(true)) {
    fmt.Print(err)
    for _, c := range update.Contents {
        if text, ok := c.(*message.TextContent); ok {
            fmt.Print(text.Text)
        }
    }
}

Tip

Kompletní příklad spustitelného souboru najdete v úplné ukázce .

Další kroky