Skip to content

Commit 2ea9d85

Browse files
committed
add reasoning content to ChatCompletion
1 parent 472e8c1 commit 2ea9d85

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

src/agents/models/chatcmpl_stream_handler.py

+64-11
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ async def handle_stream(
4848
usage: CompletionUsage | None = None
4949
state = StreamingState()
5050

51+
is_reasoning_model = False
52+
emit_reasoning_content = False
53+
emit_content = False
5154
async for chunk in stream:
5255
if not state.started:
5356
state.started = True
@@ -62,9 +65,16 @@ async def handle_stream(
6265
continue
6366

6467
delta = chunk.choices[0].delta
68+
reasoning_content = None
69+
content = None
70+
if hasattr(delta, "reasoning_content"):
71+
reasoning_content = delta.reasoning_content
72+
is_reasoning_model = True
73+
if hasattr(delta, "content"):
74+
content = delta.content
6575

6676
# Handle text
67-
if delta.content:
77+
if reasoning_content or content:
6878
if not state.text_content_index_and_output:
6979
# Initialize a content tracker for streaming text
7080
state.text_content_index_and_output = (
@@ -100,16 +110,59 @@ async def handle_stream(
100110
),
101111
type="response.content_part.added",
102112
)
103-
# Emit the delta for this segment of content
104-
yield ResponseTextDeltaEvent(
105-
content_index=state.text_content_index_and_output[0],
106-
delta=delta.content,
107-
item_id=FAKE_RESPONSES_ID,
108-
output_index=0,
109-
type="response.output_text.delta",
110-
)
111-
# Accumulate the text into the response part
112-
state.text_content_index_and_output[1].text += delta.content
113+
114+
if reasoning_content is not None:
115+
if not emit_reasoning_content:
116+
emit_reasoning_content = True
117+
118+
reasoning_content_title = "# reasoning content\n\n"
119+
# Emit the reasoning content title
120+
yield ResponseTextDeltaEvent(
121+
content_index=state.text_content_index_and_output[0],
122+
delta=reasoning_content_title,
123+
item_id=FAKE_RESPONSES_ID,
124+
output_index=0,
125+
type="response.output_text.delta",
126+
)
127+
# Accumulate the text into the response part
128+
state.text_content_index_and_output[1].text += reasoning_content_title
129+
130+
# Emit the delta for this segment of content
131+
yield ResponseTextDeltaEvent(
132+
content_index=state.text_content_index_and_output[0],
133+
delta=reasoning_content,
134+
item_id=FAKE_RESPONSES_ID,
135+
output_index=0,
136+
type="response.output_text.delta",
137+
)
138+
# Accumulate the text into the response part
139+
state.text_content_index_and_output[1].text += reasoning_content
140+
141+
if content is not None:
142+
if not emit_content and is_reasoning_model:
143+
emit_content = True
144+
content_title = "\n\n# content\n\n"
145+
# Emit the content title
146+
yield ResponseTextDeltaEvent(
147+
content_index=state.text_content_index_and_output[0],
148+
delta=content_title,
149+
item_id=FAKE_RESPONSES_ID,
150+
output_index=0,
151+
type="response.output_text.delta",
152+
)
153+
# Accumulate the text into the response part
154+
state.text_content_index_and_output[1].text += content_title
155+
156+
# Emit the delta for this segment of content
157+
yield ResponseTextDeltaEvent(
158+
content_index=state.text_content_index_and_output[0],
159+
delta=content,
160+
item_id=FAKE_RESPONSES_ID,
161+
output_index=0,
162+
type="response.output_text.delta",
163+
)
164+
# Accumulate the text into the response part
165+
state.text_content_index_and_output[1].text += content
113166

114167
# Handle refusals (model declines to answer)
115168
if delta.refusal:

0 commit comments

Comments
 (0)