Skip to content

Commit 5c6745c

Browse files
committed
wip first pass at new OpenAI Responses API support
1 parent 2939edd commit 5c6745c

15 files changed

+1333
-497
lines changed

chatlas/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
from ._provider_huggingface import ChatHuggingFace
2828
from ._provider_mistral import ChatMistral
2929
from ._provider_ollama import ChatOllama
30-
from ._provider_openai import ChatAzureOpenAI, ChatOpenAI
30+
from ._provider_openai import ChatOpenAI
31+
from ._provider_openai_azure import ChatAzureOpenAI
32+
from ._provider_openai_responses import ChatOpenAIResponses
3133
from ._provider_openrouter import ChatOpenRouter
3234
from ._provider_perplexity import ChatPerplexity
3335
from ._provider_portkey import ChatPortkey
@@ -59,6 +61,7 @@
5961
"ChatMistral",
6062
"ChatOllama",
6163
"ChatOpenAI",
64+
"ChatOpenAIResponses",
6265
"ChatOpenRouter",
6366
"ChatAzureOpenAI",
6467
"ChatPerplexity",

chatlas/_auto.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
from ._provider_huggingface import ChatHuggingFace
1818
from ._provider_mistral import ChatMistral
1919
from ._provider_ollama import ChatOllama
20-
from ._provider_openai import ChatAzureOpenAI, ChatOpenAI
20+
from ._provider_openai import ChatOpenAI
21+
from ._provider_openai_azure import ChatAzureOpenAI
2122
from ._provider_openrouter import ChatOpenRouter
2223
from ._provider_perplexity import ChatPerplexity
2324
from ._provider_portkey import ChatPortkey

chatlas/_chat.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,12 +2539,11 @@ def emit(text: str | Content):
25392539
result,
25402540
has_data_model=data_model is not None,
25412541
)
2542-
25432542
if echo == "all":
25442543
emit_other_contents(turn, emit)
25452544

25462545
else:
2547-
response = self.provider.chat_perform(
2546+
result = self.provider.chat_perform(
25482547
stream=False,
25492548
turns=[*self._turns, user_turn],
25502549
tools=self._tools,
@@ -2553,7 +2552,7 @@ def emit(text: str | Content):
25532552
)
25542553

25552554
turn = self.provider.value_turn(
2556-
response, has_data_model=data_model is not None
2555+
result, has_data_model=data_model is not None
25572556
)
25582557
if turn.text:
25592558
emit(turn.text)
@@ -2610,7 +2609,7 @@ def emit(text: str | Content):
26102609
emit_other_contents(turn, emit)
26112610

26122611
else:
2613-
response = await self.provider.chat_perform_async(
2612+
result = await self.provider.chat_perform_async(
26142613
stream=False,
26152614
turns=[*self._turns, user_turn],
26162615
tools=self._tools,
@@ -2619,7 +2618,7 @@ def emit(text: str | Content):
26192618
)
26202619

26212620
turn = self.provider.value_turn(
2622-
response, has_data_model=data_model is not None
2621+
result, has_data_model=data_model is not None
26232622
)
26242623
if turn.text:
26252624
emit(turn.text)

chatlas/_content.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ def from_tool(cls, tool: "Tool") -> "ToolInfo":
125125
"tool_result_resource",
126126
"json",
127127
"pdf",
128+
"thinking",
128129
]
129130
"""
130131
A discriminated union of all content types.
@@ -682,6 +683,40 @@ def __repr__(self, indent: int = 0):
682683
return " " * indent + f"<ContentPDF size={len(self.data)}>"
683684

684685

686+
class ContentThinking(Content):
687+
"""
688+
Thinking/reasoning content
689+
690+
This content type represents reasoning traces from models that support
691+
extended thinking (like OpenAI's o-series models). The thinking content
692+
is not meant to be sent back to the model but is useful for debugging
693+
and understanding the model's reasoning process.
694+
695+
Parameters
696+
----------
697+
thinking
698+
The thinking/reasoning text from the model.
699+
extra
700+
Additional metadata associated with the thinking content (e.g.,
701+
encrypted content, status information).
702+
"""
703+
704+
thinking: str
705+
extra: Optional[dict[str, Any]] = None
706+
707+
content_type: ContentTypeEnum = "thinking"
708+
709+
def __str__(self):
710+
return f"<thinking>\n{self.thinking}\n</thinking>\n"
711+
712+
def _repr_markdown_(self):
713+
return self.__str__()
714+
715+
def __repr__(self, indent: int = 0):
716+
preview = self.thinking[:50] + "..." if len(self.thinking) > 50 else self.thinking
717+
return " " * indent + f"<ContentThinking thinking='{preview}'>"
718+
719+
685720
ContentUnion = Union[
686721
ContentText,
687722
ContentImageRemote,
@@ -692,6 +727,7 @@ def __repr__(self, indent: int = 0):
692727
ContentToolResultResource,
693728
ContentJson,
694729
ContentPDF,
730+
ContentThinking,
695731
]
696732

697733

@@ -724,6 +760,8 @@ def create_content(data: dict[str, Any]) -> ContentUnion:
724760
return ContentJson.model_validate(data)
725761
elif ct == "pdf":
726762
return ContentPDF.model_validate(data)
763+
elif ct == "thinking":
764+
return ContentThinking.model_validate(data)
727765
else:
728766
raise ValueError(f"Unknown content type: {ct}")
729767

chatlas/_provider_anthropic.py

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -242,28 +242,6 @@ def list_models(self):
242242

243243
return res
244244

245-
@overload
246-
def chat_perform(
247-
self,
248-
*,
249-
stream: Literal[False],
250-
turns: list[Turn],
251-
tools: dict[str, Tool],
252-
data_model: Optional[type[BaseModel]] = None,
253-
kwargs: Optional["SubmitInputArgs"] = None,
254-
): ...
255-
256-
@overload
257-
def chat_perform(
258-
self,
259-
*,
260-
stream: Literal[True],
261-
turns: list[Turn],
262-
tools: dict[str, Tool],
263-
data_model: Optional[type[BaseModel]] = None,
264-
kwargs: Optional["SubmitInputArgs"] = None,
265-
): ...
266-
267245
def chat_perform(
268246
self,
269247
*,
@@ -276,28 +254,6 @@ def chat_perform(
276254
kwargs = self._chat_perform_args(stream, turns, tools, data_model, kwargs)
277255
return self._client.messages.create(**kwargs) # type: ignore
278256

279-
@overload
280-
async def chat_perform_async(
281-
self,
282-
*,
283-
stream: Literal[False],
284-
turns: list[Turn],
285-
tools: dict[str, Tool],
286-
data_model: Optional[type[BaseModel]] = None,
287-
kwargs: Optional["SubmitInputArgs"] = None,
288-
): ...
289-
290-
@overload
291-
async def chat_perform_async(
292-
self,
293-
*,
294-
stream: Literal[True],
295-
turns: list[Turn],
296-
tools: dict[str, Tool],
297-
data_model: Optional[type[BaseModel]] = None,
298-
kwargs: Optional["SubmitInputArgs"] = None,
299-
): ...
300-
301257
async def chat_perform_async(
302258
self,
303259
*,

chatlas/_provider_github.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from ._chat import Chat
99
from ._logging import log_model_default
10-
from ._provider_openai import ModelInfo, OpenAIProvider
10+
from ._provider import ModelInfo
11+
from ._provider_openai import OpenAIProvider
1112
from ._utils import MISSING, MISSING_TYPE, is_testing
1213

1314
if TYPE_CHECKING:

chatlas/_provider_ollama.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
import orjson
88

99
from ._chat import Chat
10-
from ._provider_openai import ModelInfo, OpenAIProvider
10+
from ._provider import ModelInfo
11+
from ._provider_openai import OpenAIProvider
1112
from ._utils import MISSING_TYPE, is_testing
1213

1314
if TYPE_CHECKING:

0 commit comments

Comments
 (0)