Freigeben über


Upgradehandbuch: Chatoptionen als TypedDict mit Generics

Dieses Handbuch hilft Ihnen, Ihren Python-Code auf das neue TypedDict-basierte Options System zu aktualisieren, das in Version 1.0.0b260114 des Microsoft Agent Framework eingeführt wurde. Dies ist eine grundlegende Änderung , die verbesserte Typsicherheit, IDE-AutoVervollständigen und Laufzeiterweiterung bietet.

Übersicht über Änderungen

In dieser Version wird eine wichtige Umgestaltung der Weitergabe von Optionen an Chatclients und Chat-Agents eingeführt.

Wie es zuvor funktionierte

Zuvor wurden Optionen als direkte Schlüsselwortargumente für Methoden wie get_response(), get_streaming_response(), , run()und Agentkonstruktoren übergeben:

# Options were individual keyword arguments
response = await client.get_response(
    "Hello!",
    model_id="gpt-4",
    temperature=0.7,
    max_tokens=1000,
)

# For provider-specific options not in the base set, you used additional_properties
response = await client.get_response(
    "Hello!",
    model_id="gpt-4",
    additional_properties={"reasoning_effort": "medium"},
)

Aktueller Funktionsablauf

Die meisten Optionen werden nun über einen einzelnen options Parameter als typiertes Wörterbuch übergeben:

# Most options go in a single typed dict
response = await client.get_response(
    "Hello!",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "max_tokens": 1000,
        "reasoning_effort": "medium",  # Provider-specific options included directly
    },
)

Hinweis: Für Agents bleiben die Parameter und instructions als direkte Schlüsselwortargumente bei tools und ChatAgent.__init__() verfügbar. Für agent.run(), ist nur tools als Schlüsselwortargument verfügbar:

# Agent creation accepts both tools and instructions as keyword arguments
agent = ChatAgent(
    chat_client=client,
    tools=[my_function],
    instructions="You are a helpful assistant.",
    default_options={"model_id": "gpt-4", "temperature": 0.7},
)

# agent.run() only accepts tools as a keyword argument
response = await agent.run(
    "Hello!",
    tools=[another_function],  # Can override tools per-run
)

Wichtige Änderungen

  1. Consolidated Options Parameter: Die meisten Schlüsselwortargumente (model_id, temperatureusw.) werden jetzt über ein einzelnes options Diktat übergeben.
  2. Ausnahme für die Agenterstellung: instructions und tools bleiben als direkte Schlüsselwortargumente für ChatAgent.__init__() und create_agent()
  3. Ausnahme für die Agentausführung: tools bleibt als direktes Schlüsselwortargument verfügbar für agent.run()
  4. TypedDict-basierte Optionen: Optionen werden als TypedDict Klassen für die Typsicherheit definiert.
  5. Generische Typunterstützung: Chatclients und Agents unterstützen Generika für anbieterspezifische Optionen, um Laufzeitüberladungen zuzulassen
  6. Anbieterspezifische Optionen: Jeder Anbieter verfügt über ein standardmäßiges eigenes TypedDict (z. B. OpenAIChatOptions, OllamaChatOptions)
  7. Keine mehr additional_properties: Anbieterspezifische Parameter sind jetzt erstklassige typierte Felder.

Vorteile

  • Typsicherheit: Autovervollständigung und Typüberprüfung für alle Optionen
  • Anbieterflexibilität: Unterstützung für anbieterspezifische Parameter am ersten Tag
  • Cleaner Code: Konsistentes diktierbasiertes Übergeben von Parametern
  • Einfachere Erweiterung: Erstellen von benutzerdefinierten Optionen für spezielle Anwendungsfälle (z. B. Gründemodelle oder andere API-Back-Ends)

Migrationshandbuch

1. Konvertieren von Schlüsselwortargumenten in OptionsDict

Die häufigste Änderung besteht darin, einzelne Schlüsselwortargumente in das options Wörterbuch zu konvertieren.

Vorher (Schlüsselwortargumente):

from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient()

# Options passed as individual keyword arguments
response = await client.get_response(
    "Hello!",
    model_id="gpt-4",
    temperature=0.7,
    max_tokens=1000,
)

# Streaming also used keyword arguments
async for chunk in client.get_streaming_response(
    "Tell me a story",
    model_id="gpt-4",
    temperature=0.9,
):
    print(chunk.text, end="")

After (options dict):

from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient()

# All options now go in a single 'options' parameter
response = await client.get_response(
    "Hello!",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "max_tokens": 1000,
    },
)

# Same pattern for streaming
async for chunk in client.get_streaming_response(
    "Tell me a story",
    options={
        "model_id": "gpt-4",
        "temperature": 0.9,
    },
):
    print(chunk.text, end="")

Wenn Sie Optionen übergeben, die für diesen Client nicht geeignet sind, erhalten Sie einen Typfehler in Ihrer IDE.

2. Verwenden von Provider-Specific Optionen (keine additional_properties mehr)

Um anbieterspezifische Parameter zu übergeben, die nicht Teil des Basissatzes von Schlüsselwortargumenten waren, mussten Sie den additional_properties Parameter verwenden:

Vorher (mit additional_properties):

from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient()
response = await client.get_response(
    "What is 2 + 2?",
    model_id="gpt-4",
    temperature=0.7,
    additional_properties={
        "reasoning_effort": "medium",  # No type checking or autocomplete
    },
)

After (direkte Optionen mit TypedDict):

from agent_framework.openai import OpenAIChatClient

# Provider-specific options are now first-class citizens with full type support
client = OpenAIChatClient()
response = await client.get_response(
    "What is 2 + 2?",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "reasoning_effort": "medium",  # Type checking or autocomplete
    },
)

Nach (benutzerdefinierte Unterklassen für neue Parameter):

Oder wenn es sich um einen Parameter handelt, der noch nicht Teil des Agent Frameworks ist (da es neu ist oder weil er für ein openAI-kompatibles Back-End benutzerdefinierte ist), können Sie jetzt die Optionen unterklassen und die generische Unterstützung verwenden:

from typing import Literal
from agent_framework.openai import OpenAIChatOptions, OpenAIChatClient

class MyCustomOpenAIChatOptions(OpenAIChatOptions, total=False):
    """Custom OpenAI chat options with additional parameters."""

    # New or custom parameters
    custom_param: str

# Use with the client
client = OpenAIChatClient[MyCustomOpenAIChatOptions]()
response = await client.get_response(
    "Hello!",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "custom_param": "my_value",  # IDE autocomplete works!
    },
)

Der Hauptvorteil besteht darin, dass die meisten anbieterspezifischen Parameter jetzt Teil des typierten Optionswörterbuchs sind und Ihnen folgendes bieten:

  • AutoVervollständigen für IDE für alle verfügbaren Optionen
  • Typüberprüfung zum Abfangen ungültiger Schlüssel oder Werte
  • Keine Notwendigkeit für additional_properties für bekannte Anbieterparameter
  • Einfache Erweiterung für benutzerdefinierte oder neue Parameter

3. Aktualisieren der ChatAgent-Konfiguration

Die ChatAgent-Initialisierung und -Ausführungsmethoden folgen demselben Muster:

Vorher (Schlüsselwortargumente für Konstruktor und Ausführung):

from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient()

# Default options as keyword arguments on constructor
agent = ChatAgent(
    chat_client=client,
    name="assistant",
    model_id="gpt-4",
    temperature=0.7,
)

# Run also took keyword arguments
response = await agent.run(
    "Hello!",
    max_tokens=1000,
)

After:

from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient, OpenAIChatOptions

client = OpenAIChatClient()
agent = ChatAgent(
    chat_client=client,
    name="assistant",
    default_options={ # <- type checkers will verify this dict
        "model_id": "gpt-4",
        "temperature": 0.7,
    },
)

response = await agent.run("Hello!", options={ # <- and this dict too
    "max_tokens": 1000,
})

4. Anbieter-spezifische Optionen

Jeder Anbieter verfügt jetzt über ein eigenes TypedDict für Optionen, diese sind standardmäßig aktiviert. Auf diese Weise können Sie anbieterspezifische Parameter mit voller Typsicherheit verwenden:

OpenAI-Beispiel:

from agent_framework.openai import OpenAIChatClient

client = OpenAIChatClient()
response = await client.get_response(
    "Hello!",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "reasoning_effort": "medium",
    },
)

Sie können sie aber auch explizit festlegen:

from agent_framework_anthropic import AnthropicClient, AnthropicChatOptions

client = AnthropicClient[AnthropicChatOptions]()
response = await client.get_response(
    "Hello!",
    options={
        "model_id": "claude-3-opus-20240229",
        "max_tokens": 1000,
    },
)

5. Erstellen von benutzerdefinierten Optionen für spezialisierte Modelle

Ein leistungsfähiges Feature des neuen Systems ist die Möglichkeit, benutzerdefinierte TypedDict-Optionen für spezialisierte Modelle zu erstellen. Dies ist besonders hilfreich für Modelle mit eindeutigen Parametern, z. B. Reasoning-Modelle mit OpenAI:

from typing import Literal
from agent_framework.openai import OpenAIChatOptions, OpenAIChatClient

class OpenAIReasoningChatOptions(OpenAIChatOptions, total=False):
    """Chat options for OpenAI reasoning models (o1, o3, o4-mini, etc.)."""

    # Reasoning-specific parameters
    reasoning_effort: Literal["none", "minimal", "low", "medium", "high", "xhigh"]

    # Unsupported parameters for reasoning models (override with None)
    temperature: None
    top_p: None
    frequency_penalty: None
    presence_penalty: None
    logit_bias: None
    logprobs: None
    top_logprobs: None
    stop: None


# Use with the client
client = OpenAIChatClient[OpenAIReasoningChatOptions]()
response = await client.get_response(
    "What is 2 + 2?",
    options={
        "model_id": "o3",
        "max_tokens": 100,
        "allow_multiple_tool_calls": True,
        "reasoning_effort": "medium",  # IDE autocomplete works!
        # "temperature": 0.7,  # Would raise a type error, because the value is not None
    },
)

6. Chat-Agents mit Optionen

Die generische Einrichtung wurde auch auf Chat-Agents erweitert:

from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient

agent = ChatAgent(
    chat_client=OpenAIChatClient[OpenAIReasoningChatOptions](),
    default_options={
        "model_id": "o3",
        "max_tokens": 100,
        "allow_multiple_tool_calls": True,
        "reasoning_effort": "medium",
    },
)

und Sie können das Generika sowohl für den Client als auch für den Agent angeben, sodass dies auch gültig ist:

from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient

agent = ChatAgent[OpenAIReasoningChatOptions](
    chat_client=OpenAIChatClient(),
    default_options={
        "model_id": "o3",
        "max_tokens": 100,
        "allow_multiple_tool_calls": True,
        "reasoning_effort": "medium",
    },
)

6. Aktualisieren benutzerdefinierter Chatclientimplementierungen

Wenn Sie einen benutzerdefinierten Chatclient durch Erweitern BaseChatClientimplementiert haben, aktualisieren Sie die internen Methoden:

Before:

from agent_framework import BaseChatClient, ChatMessage, ChatOptions, ChatResponse

class MyCustomClient(BaseChatClient):
    async def _inner_get_response(
        self,
        *,
        messages: MutableSequence[ChatMessage],
        chat_options: ChatOptions,
        **kwargs: Any,
    ) -> ChatResponse:
        # Access options via class attributes
        model = chat_options.model_id
        temp = chat_options.temperature
        # ...

After:

from typing import Generic
from agent_framework import BaseChatClient, ChatMessage, ChatOptions, ChatResponse

# Define your provider's options TypedDict
class MyCustomChatOptions(ChatOptions, total=False):
    my_custom_param: str

# This requires the TypeVar from Python 3.13+ or from typing_extensions, so for Python 3.13+:
from typing import TypeVar

TOptions = TypeVar("TOptions", bound=TypedDict, default=MyCustomChatOptions, covariant=True)

class MyCustomClient(BaseChatClient[TOptions], Generic[TOptions]):
    async def _inner_get_response(
        self,
        *,
        messages: MutableSequence[ChatMessage],
        options: dict[str, Any],  # Note: parameter renamed and just a dict
        **kwargs: Any,
    ) -> ChatResponse:
        # Access options via dict access
        model = options.get("model_id")
        temp = options.get("temperature")
        # ...

Allgemeine Migrationsmuster

Muster 1: Einfaches Parameterupdate

# Before - keyword arguments
await client.get_response("Hello", temperature=0.7)

# After - options dict
await client.get_response("Hello", options={"temperature": 0.7})

Muster 2: Mehrere Parameter

# Before - multiple keyword arguments
await client.get_response(
    "Hello",
    model_id="gpt-4",
    temperature=0.7,
    max_tokens=1000,
)

# After - all in options dict
await client.get_response(
    "Hello",
    options={
        "model_id": "gpt-4",
        "temperature": 0.7,
        "max_tokens": 1000,
    },
)

Muster 3: Chatclient mit Tools

Für Chat-Clients geht tools jetzt in das Options-Wörterbuch:

# Before - tools as keyword argument on chat client
await client.get_response(
    "What's the weather?",
    model_id="gpt-4",
    tools=[my_function],
    tool_choice="auto",
)

# After - tools in options dict for chat clients
await client.get_response(
    "What's the weather?",
    options={
        "model_id": "gpt-4",
        "tools": [my_function],
        "tool_choice": "auto",
    },
)

Muster 4: Agent mit Tools und Anweisungen

Für die Agenterstellung tools und instructions können als Schlüsselwortargumente beibehalten werden. Für run() ist nur tools verfügbar.

# Before
agent = ChatAgent(
    chat_client=client,
    name="assistant",
    tools=[my_function],
    instructions="You are helpful.",
    model_id="gpt-4",
)

# After - tools and instructions stay as keyword args on creation
agent = ChatAgent(
    chat_client=client,
    name="assistant",
    tools=[my_function],  # Still a keyword argument!
    instructions="You are helpful.",  # Still a keyword argument!
    default_options={"model_id": "gpt-4"},
)

# For run(), only tools is available as keyword argument
response = await agent.run(
    "Hello!",
    tools=[another_function],  # Can override tools
    options={"max_tokens": 100},
)
# Before - using additional_properties
await client.get_response(
    "Solve this problem",
    model_id="o3",
    additional_properties={"reasoning_effort": "high"},
)

# After - directly in options
await client.get_response(
    "Solve this problem",
    options={
        "model_id": "o3",
        "reasoning_effort": "high",
    },
)

Muster 5: Provider-Specific Parameter

# Define reusable options
my_options: OpenAIChatOptions = {
    "model_id": "gpt-4",
    "temperature": 0.7,
}

# Use with different messages
await client.get_response("Hello", options=my_options)
await client.get_response("Goodbye", options=my_options)

# Extend options using dict merge
extended_options = {**my_options, "max_tokens": 500}

Zusammenfassung der änderungen

Aspekt Vorher Nach
Chatclientoptionen Einzelne Schlüsselwortargumente (temperature=0.7) Einzelnes options Diktat (options={"temperature": 0.7})
Chatclienttools tools=[...] Schlüsselwortargument options={"tools": [...]}
Agent-Erstellung tools und instructions Schlüsselwortargumente Noch Schlüsselwortargumente (unverändert)
Agent run()tools Schlüsselwortargument Schlüsselwortargument ( unverändert)
Agent run()instructions Schlüsselwortargument Verschoben nach options={"instructions": ...}
Anbieterspezifische Optionen additional_properties={...} Direkt im options Diktat enthalten
Standardoptionen des Agenten Schlüsselwortargumente im Konstruktor default_options={...}
Agent-Ausführungsoptionen Schlüsselwortargumente für run() options={...} Parameter
Clienteingabe OpenAIChatClient() OpenAIChatClient[CustomOptions]() (wahlweise)
Agent-Eingabe ChatAgent(...) ChatAgent[CustomOptions](...) (wahlweise)

Testen Ihrer Migration

ChatClient-Updates

  1. Suchen Sie alle Aufrufe von get_response() und get_streaming_response(), die Schlüsselwortargumente wie model_id=, temperature=, tools= usw. verwenden.
  2. Verschieben aller Schlüsselwortargumente in ein options={...} Wörterbuch
  3. Verschieben Sie die additional_properties Werte direkt in das options Dictionary

ChatAgent-Updates

  1. Suchen aller ChatAgent Konstruktoren und run() Aufrufe, die Schlüsselwortargumente verwenden
  2. Schlüsselwortargumente für Konstruktoren verschieben in default_options={...}
  3. Verschieben Sie die Schlüsselwortargumente von run() nach options={...}
  4. Ausnahme: tools und instructions können als Schlüsselwortargumente bei ChatAgent.__init__() und create_agent() bleiben
  5. Ausnahme: tools kann als Schlüsselwortargument beibehalten werden run()

Benutzerdefinierte Chat-Client-Updates

  1. Aktualisieren Sie die _inner_get_response()- und _inner_get_streaming_response()-Methodensignaturen: Ändern Sie den Parameter chat_options: ChatOptions zu options: dict[str, Any].
  2. Aktualisieren des Attributzugriffs (z. B. chat_options.model_id) auf Dict-Zugriff (z. B. options.get("model_id"))
  3. (Optional) Verwenden von nicht standardmäßigen Parametern: Definieren eines benutzerdefinierten TypedDict
  4. Hinzufügen von generischen Typparametern zur Clientklasse

Für alle

  1. Typprüfer ausführen: Verwenden Sie mypy oder pyright, um Typfehler abzufangen
  2. End-to-End testen: Führen Sie Ihre Anwendung aus, um die Funktionalität zu überprüfen.

IDE-Unterstützung

Das neue TypedDict-basierte System bietet hervorragende IDE-Unterstützung:

  • AutoVervollständigen: Abrufen von Vorschlägen für alle verfügbaren Optionen
  • Typüberprüfung: Erfassen ungültiger Optionsschlüssel während der Entwicklungszeit
  • Dokumentation: Zeigen Sie mit der Maus auf Schlüssel, um Beschreibungen anzuzeigen.
  • Anbieterspezifisch: Die Optionen jedes Anbieters zeigen nur relevante Parameter an

Nächste Schritte

Um die eingegebenen Diktats in Aktion für den Fall der Verwendung von OpenAI-Begründungsmodellen mit der Chat-Abschluss-API anzuzeigen, erkunden Sie dieses Beispiel

Nach Abschluss der Migration:

  1. Erkunden von anbieterspezifischen Optionen in der API-Dokumentation
  2. Überprüfen aktualisierter Beispiele
  3. Informationen zum Erstellen von benutzerdefinierten Chatclients

Weitere Hilfe finden Sie in der Agent Framework-Dokumentation oder wenden Sie sich an die Community.