Поделиться через


Руководство по обновлению: параметры чата в формате TypedDict с универсальными типами

Это руководство поможет обновить код Python до новой системы на основе Options TypedDict, представленной в версии 1.0.0b260114 Microsoft Agent Framework. Это критическое изменение , которое обеспечивает улучшенную безопасность типов, автозавершение интегрированной среды разработки и расширяемость среды выполнения.

Обзор изменений

В этом выпуске представлено основное рефакторинг способов передачи параметров клиентам чата и агентам чата.

Как это работало раньше

Ранее параметры были переданы в качестве прямых аргументов ключевых слов в таких методах, как get_response(), get_streaming_response()run()и конструкторы агента:

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

Как это работает сейчас

Большинство параметров теперь передаются через один options параметр в виде типизированного словаря:

# 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
    },
)

Примечание: Для Агентов параметры instructions и tools остаются доступными в качестве прямых аргументов на ChatAgent.__init__() и client.as_agent(). Для agent.run() доступен только tools в качестве аргумента ключевого слова.

# 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
)

Ключевые изменения

  1. Параметр консолидированных параметров: большинство аргументов ключевых слов (model_id, temperatureи т. д.) теперь передаются через один options дикт.
  2. Исключение для создания агента: instructions и tools остаются доступными как ключевые слова для ChatAgent.__init__() и create_agent()
  3. Исключение для запуска агента: tools остается доступным в качестве прямого аргумента ключевого слова в agent.run()
  4. Параметры на основе TypedDict: Опции определяются как TypedDict классы для безопасности типов
  5. Поддержка универсальных типов: клиенты и агенты чата поддерживают универсальные шаблоны для параметров, относящихся к поставщику, чтобы разрешить перегрузки среды выполнения.
  6. Параметры для конкретного поставщика: у каждого поставщика есть собственный типdDict по умолчанию (например, OpenAIChatOptions, ) OllamaChatOptions
  7. Нет больше additional_properties: параметры, относящиеся к поставщику, теперь являются типизированными полями первого класса.

Преимущества

  • Безопасность типов: автозавершение и проверка типов для всех опций в IDE
  • Гибкость поставщика: поддержка параметров для конкретного поставщика в день один
  • Более чистый код: последовательная передача параметров на основе словаря
  • Упрощенное расширение. Создание настраиваемых параметров для специализированных вариантов использования (например, моделей причин или других серверных компонентов API)

Руководство по миграции

1. Преобразование аргументов ключевых слов в параметры Дикт

Наиболее частое изменение — преобразование отдельных аргументов ключевых слов в options словарь.

До (аргументы ключевых слов):

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

После (словарь параметров):

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

Если вы передаете параметры, которые не подходят для этого клиента, вы получите ошибку типа в интегрированной среде разработки.

2. Использование специфических параметров поставщика (нет больше additional_properties)

Ранее для передачи параметров, относящихся к поставщику, которые не были частью базового набора аргументов ключевых слов, необходимо было использовать additional_properties этот параметр:

Перед использованием 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
    },
)

После (прямые параметры с 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
    },
)

После (настраиваемое подклассирование для новых параметров):

Или если это параметр, который еще не является частью Agent Framework (так как он новый или поскольку он настраивается для серверной части, совместимой с OpenAI), теперь можно подклассить параметры и использовать универсальную поддержку:

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!
    },
)

Ключевым преимуществом является то, что большинство параметров для конкретного поставщика теперь являются частью словаря типизированных параметров, предоставляя вам следующее:

  • Автозавершение интегрированной среды разработки для всех доступных параметров
  • Проверка типа для перехвата недопустимых ключей или значений
  • Нет необходимости в дополнительных_свойствах для известных параметров поставщика
  • Простое расширение для пользовательских или новых параметров

3. Обновление конфигурации ChatAgent

Методы инициализации ChatAgent и запуска соответствуют тому же шаблону:

До (аргументы ключевых слов в конструкторе и выполнении):

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. Специфические параметры поставщика

Теперь у каждого поставщика есть собственный TypedDict для параметров, они включены по умолчанию. Это позволяет использовать параметры, специфичные для поставщика, обеспечивая полную безопасность типов.

Пример OpenAI:

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

Но вы также можете сделать его явным:

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. Создание настраиваемых параметров для специализированных моделей

Одной из мощных функций новой системы является возможность создания настраиваемых параметров TypedDict для специализированных моделей. Это особенно полезно для моделей с уникальными параметрами, такими как модели причин с помощью 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. Агенты чата с параметрами

Универсальная настройка также распространяется на агентов чата.

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

и вы можете указать универсальный тип как для клиента, так и агента, поэтому это также допустимо:

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. Обновление пользовательских реализаций клиента чата

Если вы реализовали пользовательский клиент чата, расширив BaseChatClient, обновите внутренние методы:

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")
        # ...

Общие шаблоны миграции

Шаблон 1. Простое обновление параметров

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

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

Шаблон 2. Несколько параметров

# 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,
    },
)

Шаблон 3. Клиент чата с инструментами

Для чат-клиентов tools теперь переходит в словарь параметров:

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

Шаблон 4. Агент с инструментами и инструкциями

Для создания агента tools и instructions могут оставаться в качестве ключевых аргументов. Для run(), доступно только tools :

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

Шаблон 5. Параметры, специфичные для поставщика

# 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}

Сводка критических изменений

Аспект До После
Параметры клиента чата Отдельные аргументы ключевых слов (temperature=0.7) Один options словарь (options={"temperature": 0.7})
Клиентские средства чата tools=[...] аргумент ключевого слова options={"tools": [...]}
Создание tools агента и instructions Аргументы ключевых слов Аргументы ключевых слов по-прежнему (без изменений)
Агент run()tools Аргумент ключевого слова По-прежнему аргумент ключевого слова (без изменений)
Агент run()instructions Аргумент ключевого слова Перемещено в options={"instructions": ...}
Параметры, специфические для поставщика additional_properties={...} Включен непосредственно в options словарь
Параметры агента по умолчанию Ключевые аргументы конструктора default_options={...}
Параметры запуска агента Аргументы ключевых слов в run() options={...} параметр
Клиент набирает текст OpenAIChatClient() OpenAIChatClient[CustomOptions]() (необязательно)
Агент печатает ChatAgent(...) ChatAgent[CustomOptions](...) (необязательно)

Тестирование миграции

Обновления ChatClient

  1. Найдите все вызовы get_response() и get_streaming_response(), которые используют ключевые аргументы, например model_id=, temperature=, tools=, и т. д.
  2. Переместите все ключевые аргументы в options={...} словарь
  3. Переместите любые additional_properties значения непосредственно в options словарь

Обновления ChatAgent

  1. Поиск всех ChatAgent конструкторов и run() вызовов, использующих аргументы ключевых слов
  2. Переместите ключевые аргументы в конструкторах в default_options={...}
  3. Переместите аргументы ключевых слов с run() на options={...}
  4. Исключение: tools и instructions могут оставаться в качестве аргументов ключевых слов на ChatAgent.__init__() и create_agent()
  5. Исключение: tools может оставаться в качестве аргумента ключевого слова в run()

Обновления пользовательского клиента чата

  1. Обновите сигнатуры метода _inner_get_response() и _inner_get_streaming_response(): измените параметр chat_options: ChatOptions на options: dict[str, Any]
  2. Обновите доступ к атрибутам (например, chat_options.model_id) для доступа к словарю (например, options.get("model_id"))
  3. (Необязательно) При использовании нестандартных параметров: определение настраиваемого TypedDict
  4. Добавление параметров универсального типа в клиентский класс

Для всех

  1. Запуск средства проверки типов: используйте mypy или pyright для перехвата ошибок типа
  2. Сквозное тестирование: запустите приложение для проверки функциональности

Поддержка интегрированной среды разработки

Новая система typedDict обеспечивает отличную поддержку интегрированной среды разработки:

  • Автозавершение: получение предложений для всех доступных параметров
  • Проверка типов: обнаружение недопустимых ключей опций в процессе разработки
  • Документация. Наведите указатель мыши на ключи для просмотра описаний
  • Для конкретного поставщика: параметры каждого поставщика отображают только соответствующие параметры.

Дальнейшие шаги

Чтобы просмотреть типизированные словари в действии при использовании моделей логического вывода OpenAI с API завершения чата, изучите этот пример.

После завершения миграции:

  1. Изучение параметров, относящихся к поставщику, в документации по API
  2. Просмотр обновленных примеров
  3. Узнайте о создании пользовательских клиентов чата

Дополнительные сведения см. в документации по Agent Framework или обратитесь к сообществу.