Skip to content

Commit 3ee9ddd

Browse files
peterychangCopilot
andauthored
Python: OpenAI responses client (#239)
* Responses client WIP * add responses class * fix typing errors * move test * streaming responses, structured outputs * tests * Update python/packages/main/tests/openai/test_openai_responses_client.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * pr comments * fix override import * fix mypy * add missing function override * PR comments * add docstrings --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 233c557 commit 3ee9ddd

7 files changed

Lines changed: 979 additions & 21 deletions

File tree

python/packages/main/agent_framework/_types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
__all__ = [
7979
"AIContent",
8080
"AIContents",
81+
"AITool",
8182
"AgentRunResponse",
8283
"AgentRunResponseUpdate",
8384
"ChatFinishReason",

python/packages/main/agent_framework/openai/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33

44
from ._chat_client import * # noqa: F403
55
from ._exceptions import * # noqa: F403
6+
from ._responses_client import * # noqa: F403
67
from ._shared import * # noqa: F403

python/packages/main/agent_framework/openai/_chat_client.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from collections.abc import AsyncIterable, Mapping, MutableSequence, Sequence
55
from datetime import datetime
66
from itertools import chain
7-
from typing import Any, ClassVar, cast
7+
from typing import Any, cast
88

99
from openai import AsyncOpenAI, AsyncStream
1010
from openai.types import CompletionUsage
@@ -34,16 +34,16 @@
3434
__all__ = ["OpenAIChatClient"]
3535

3636

37+
# region OpenAIChatClientBase
38+
39+
3740
# Implements agent_framework.ChatClient protocol, through ChatClientBase
3841
@use_tool_calling
3942
class OpenAIChatClientBase(OpenAIHandler, ChatClientBase):
4043
"""OpenAI Chat completion class."""
4144

42-
MODEL_PROVIDER_NAME: ClassVar[str] = "openai"
43-
SUPPORTS_FUNCTION_CALLING: ClassVar[bool] = True
44-
4545
# region Overriding base class methods
46-
# most of the methods are overridden from the ChatCompletionClientBase class, otherwise it is mentioned
46+
# most of the methods are overridden from the ChatClientBase class, otherwise it is mentioned
4747

4848
async def _inner_get_response(
4949
self,
@@ -63,7 +63,6 @@ async def _inner_get_response(
6363
self._create_chat_message_content(response, choice, response_metadata) for choice in response.choices
6464
)
6565

66-
# @trace_streaming_chat_completion(MODEL_PROVIDER_NAME)
6766
async def _inner_get_streaming_response(
6867
self,
6968
*,
@@ -79,6 +78,7 @@ async def _inner_get_streaming_response(
7978
if not isinstance(response, AsyncStream):
8079
raise ServiceInvalidResponseError("Expected an AsyncStream[ChatCompletionChunk] response.")
8180
async for chunk in response:
81+
assert isinstance(chunk, ChatCompletionChunk) # nosec # noqa: S101
8282
if len(chunk.choices) == 0 and chunk.usage is None:
8383
continue
8484

@@ -269,6 +269,11 @@ def _openai_content_parser(self, content: AIContents) -> dict[str, Any]:
269269
return content.model_dump(exclude_none=True)
270270

271271

272+
# endregion
273+
274+
# region OpenAIChatClient
275+
276+
272277
class OpenAIChatClient(OpenAIConfigBase, OpenAIChatClientBase):
273278
"""OpenAI Chat completion class."""
274279

@@ -301,21 +306,13 @@ def __init__(
301306
instruction_role (str | None): The role to use for 'instruction' messages, for example,
302307
"""
303308
try:
304-
if api_key:
305-
openai_settings = OpenAISettings(
306-
api_key=SecretStr(api_key),
307-
org_id=org_id,
308-
chat_model_id=ai_model_id,
309-
env_file_path=env_file_path,
310-
env_file_encoding=env_file_encoding,
311-
)
312-
else:
313-
openai_settings = OpenAISettings(
314-
org_id=org_id,
315-
chat_model_id=ai_model_id,
316-
env_file_path=env_file_path,
317-
env_file_encoding=env_file_encoding,
318-
)
309+
openai_settings = OpenAISettings(
310+
api_key=SecretStr(api_key) if api_key else None,
311+
org_id=org_id,
312+
chat_model_id=ai_model_id,
313+
env_file_path=env_file_path,
314+
env_file_encoding=env_file_encoding,
315+
)
319316
except ValidationError as ex:
320317
raise ServiceInitializationError("Failed to create OpenAI settings.", ex) from ex
321318

@@ -345,3 +342,6 @@ def from_dict(cls, settings: dict[str, Any]) -> "OpenAIChatClient":
345342
ai_model_id=settings["ai_model_id"],
346343
default_headers=settings.get("default_headers"),
347344
)
345+
346+
347+
# endregion

0 commit comments

Comments
 (0)