Bagikan melalui


Panduan Pembaruan: Opsi Obrolan sebagai TypedDict dengan Generik

Panduan ini membantu Anda meningkatkan kode Python ke sistem berbasis Options TypedDict baru yang diperkenalkan dalam versi 1.0.0b260114 dari Microsoft Agent Framework. Ini adalah perubahan signifikan yang memberikan peningkatan keamanan tipe, pelengkapan otomatis IDE, dan ekstensibilitas runtime.

Gambaran Umum Perubahan

Rilis ini memperkenalkan pengaturan ulang utama tentang cara opsi diteruskan ke klien obrolan dan agen obrolan.

Cara Kerjanya Sebelumnya

Sebelumnya, opsi diteruskan sebagai argumen kata kunci langsung pada metode seperti get_response(), get_streaming_response(), run(), dan konstruktor agen.

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

Cara Kerjanya Sekarang

Sebagian besar opsi sekarang diteruskan melalui satu options parameter sebagai kamus yang ditik:

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

Catatan: Untuk Agen, instructions parameter dan tools tetap tersedia sebagai argumen kata kunci langsung pada ChatAgent.__init__() dan client.as_agent(). Untuk agent.run(), hanya tools tersedia sebagai argumen kata kunci:

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

Perubahan Kunci

  1. Parameter Opsi Terkonsolidasi: Sebagian besar argumen kata kunci (model_id, , temperaturedll.) sekarang diteruskan melalui satu options dict
  2. Pengecualian untuk Pembuatan Agen: instructions dan tools tetap tersedia sebagai argumen kata kunci langsung pada ChatAgent.__init__() dan create_agent()
  3. Pengecualian untuk Eksekusi Agen: tools tetap tersedia sebagai argumen kata kunci langsung pada agent.run()
  4. Opsi berbasis TypedDict: Opsi didefinisikan sebagai TypedDict kelas untuk keamanan jenis
  5. Dukungan Jenis Generik: Klien dan agen obrolan mendukung jenis generik untuk opsi-opsi khusus penyedia, memungkinkan kelebihan beban runtime
  6. Opsi khusus penyedia: Setiap penyedia memiliki TypedDict default sendiri (misalnya, OpenAIChatOptions, OllamaChatOptions)
  7. Tidak Ada Lagi sifat_tambahan: Parameter khusus penyedia sekarang menjadi bidang tipe kelas satu

Keuntungan

  • Keamanan Jenis: Pelengkapan otomatis IDE dan pemeriksaan jenis untuk semua opsi
  • Fleksibilitas Penyedia: Dukungan untuk parameter khusus penyedia pada hari pertama
  • Kode Bersih: Meneruskan parameter berbasis dict yang konsisten
  • Ekstensi Yang Lebih Mudah: Membuat opsi kustom untuk kasus penggunaan khusus (misalnya, model penalaran atau backend API lainnya)

Panduan Migrasi

1. Konversi Argumen Kata Kunci ke Kamus Opsi

Perubahan yang paling umum adalah mengonversi argumen kata kunci individual ke options kamus.

Sebelum (argumen kata kunci):

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

Setelah (opsi kamus):

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

Jika Anda meneruskan opsi yang tidak sesuai untuk klien tersebut, Anda akan mendapatkan kesalahan jenis di IDE Anda.

2. Menggunakan Opsi Provider-Specific (Tidak Ada Lagi additional_properties)

Sebelumnya, untuk meneruskan parameter khusus penyedia yang bukan bagian dari kumpulan dasar argumen kata kunci, Anda harus menggunakan additional_properties parameter :

Sebelum (menggunakan 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
    },
)

Setelah (opsi langsung dengan 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
    },
)

Setelah (subkelas kustom untuk parameter baru):

Atau jika itu adalah parameter yang belum menjadi bagian dari Kerangka Kerja Agen (karena baru, atau karena ini kustom untuk backend yang kompatibel dengan OpenAI), Anda sekarang dapat mensubkelas opsi dan menggunakan dukungan generik:

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

Manfaat utamanya adalah bahwa sebagian besar parameter khusus penyedia sekarang menjadi bagian dari kamus opsi yang ditik, memberi Anda:

  • Penyelesaian otomatis IDE untuk semua opsi yang tersedia
  • Pemeriksaan tipe untuk menangkap kunci atau nilai yang tidak valid
  • Tidak perlu additional_properties untuk parameter penyedia yang diketahui
  • Ekstensi mudah untuk parameter kustom atau baru

3. Perbarui Konfigurasi ChatAgent

Inisialisasi ChatAgent dan metode eksekusi mengikuti pola yang sama:

Sebelum (argumen kata kunci pada konstruktor dan operasi):

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. Opsi Spesifik Penyedia

Setiap penyedia sekarang memiliki TypedDict sendiri untuk opsi, ini diaktifkan secara default. Ini memungkinkan Anda menggunakan parameter khusus penyedia dengan keamanan jenis penuh:

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

Tetapi Anda juga dapat membuatnya eksplisit:

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. Membuat Opsi Kustom untuk Model Khusus

Salah satu fitur canggih dari sistem baru adalah kemampuan untuk membuat opsi TypedDict kustom untuk model khusus. Ini sangat berguna untuk model yang memiliki parameter unik, seperti model penalaran dengan 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. Agen Chat dengan Opsi

Pengaturan generik juga telah diperluas ke Agen Obrolan.

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

dan Anda dapat menentukan tipe generik pada klien dan agen, sehingga ini juga valid.

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. Perbarui Implementasi Klien Obrolan Khusus

Jika Anda telah menerapkan klien obrolan kustom dengan memperluas BaseChatClient, perbarui metode internal:

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

Pola Migrasi Umum

Pola 1: Pembaruan Parameter Sederhana

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

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

Pola 2: Beberapa 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,
    },
)

Pola 3: Klien Obrolan menggunakan Alat

Untuk klien obrolan, tools sekarang masuk ke dalam kamus opsi.

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

Pola 4: Agen dengan Alat dan Instruksi

Untuk pembuatan agen, tools dan instructions dapat tetap sebagai argumen kata kunci. Untuk run(), hanya tools tersedia:

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

Pola 5: Parameter Spesifik Penyedia

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

Ringkasan Perubahan yang Mengganggu

Aspek Sebelumnya Setelahnya
Opsi aplikasi percakapan Argumen kata kunci individual (temperature=0.7) Dict tunggal options (options={"temperature": 0.7})
Perangkat klien chat tools=[...] argumen kata kunci options={"tools": [...]}
Pembuatan agen tools dan instructions Argumen kata kunci Argumen kata kunci masih (tidak berubah)
Agen run()tools Argumen kata kunci Argumen kata kunci masih (tidak berubah)
Agen run()instructions Argumen kata kunci Dipindahkan ke options={"instructions": ...}
Opsi khusus penyedia additional_properties={...} Disertakan langsung dalam options dict
Opsi bawaan agen Argumen kata kunci pada konstruktor default_options={...}
Opsi eksekusi agen Argumen kata kunci pada run() parameter options={...}
Klien sedang mengetik OpenAIChatClient() OpenAIChatClient[CustomOptions]() (pilihan)
Agen sedang mengetik ChatAgent(...) ChatAgent[CustomOptions](...) (pilihan)

Menguji Migrasi Anda

Pembaruan ChatClient

  1. Temukan semua panggilan ke get_response() dan get_streaming_response() yang menggunakan argumen kata kunci seperti model_id=, , temperature=tools=, dll.
  2. Memindahkan semua argumen kata kunci ke dalam options={...} kamus
  3. Memindahkan nilai apa pun additional_properties langsung ke options dict

Pembaruan ChatAgent

  1. Menemukan semua ChatAgent konstruktor dan run() panggilan yang menggunakan argumen kata kunci
  2. Memindahkan argumen kata kunci pada konstruktor ke default_options={...}
  3. Pindahkan argumen run() kata kunci ke options={...}
  4. Pengecualian: tools dan instructions dapat tetap sebagai argumen kata kunci pada ChatAgent.__init__() dan create_agent()
  5. Pengecualian: tools dapat tetap sebagai argumen kata kunci pada run()

Pembaruan Klien Obrolan Khusus

  1. Perbarui tanda tangan metode _inner_get_response() dan _inner_get_streaming_response(): ubah parameter chat_options: ChatOptions menjadi options: dict[str, Any]
  2. Perbarui akses atribut (misalnya, chat_options.model_id) ke akses kamus (misalnya, options.get("model_id"))
  3. (Opsional) Jika menggunakan parameter non-standar: Tentukan TypedDict kustom
  4. Menambahkan parameter jenis generik ke kelas klien Anda

Untuk Semua

  1. Jalankan Pemeriksa Jenis: Gunakan mypy atau pyright untuk menangkap kesalahan jenis
  2. Uji End-to-End: Jalankan aplikasi Anda untuk memverifikasi fungsionalitas

Dukungan IDE

Sistem berbasis TypedDict baru memberikan dukungan IDE yang sangat baik:

  • Lengkapi Otomatis: Dapatkan saran untuk semua opsi yang tersedia
  • Pemeriksaan Jenis: Menangkap kunci opsi yang tidak valid pada waktu pengembangan
  • Dokumentasi: Arahkan mouse ke atas kunci untuk melihat deskripsi
  • Khusus penyedia: Setiap opsi penyedia hanya menampilkan parameter yang relevan

Langkah Selanjutnya

Untuk melihat dict yang ditik dalam tindakan untuk kasus penggunaan OpenAI Reasoning Models dengan CHAT Completion API, jelajahi sampel ini

Setelah menyelesaikan migrasi:

  1. Menjelajahi opsi khusus penyedia dalam dokumentasi API
  2. Meninjau sampel yang diperbarui
  3. Pelajari tentang membuat klien obrolan kustom

Untuk bantuan tambahan, lihat dokumentasi Kerangka Kerja Agen atau hubungi komunitas.