Skip to content

Commit b6eb991

Browse files
fix(openai): Avoid consuming iterables passed to Completions API
1 parent 28d9288 commit b6eb991

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

sentry_sdk/integrations/openai.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,6 @@ def _set_completions_api_input_data(
371371
_commmon_set_input_data(span, kwargs)
372372
return
373373

374-
system_instructions = _get_system_instructions_completions(messages)
375-
if len(system_instructions) > 0:
376-
span.set_data(
377-
SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS,
378-
json.dumps(_transform_system_instructions(system_instructions)),
379-
)
380-
381374
if isinstance(messages, str):
382375
normalized_messages = normalize_message_roles([messages]) # type: ignore
383376
scope = sentry_sdk.get_current_scope()
@@ -390,6 +383,21 @@ def _set_completions_api_input_data(
390383
_commmon_set_input_data(span, kwargs)
391384
return
392385

386+
if not isinstance(messages, Iterable):
387+
set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "chat")
388+
_commmon_set_input_data(span, kwargs)
389+
return
390+
391+
messages = list(messages)
392+
kwargs["messages"] = messages
393+
394+
system_instructions = _get_system_instructions_completions(messages)
395+
if len(system_instructions) > 0:
396+
span.set_data(
397+
SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS,
398+
json.dumps(_transform_system_instructions(system_instructions)),
399+
)
400+
393401
non_system_messages = [
394402
message
395403
for message in messages

tests/integrations/openai/test_openai.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,21 @@ def test_nonstreaming_chat_completion_no_prompts(
204204
],
205205
id="parts",
206206
),
207+
pytest.param(
208+
iter(
209+
[
210+
{
211+
"role": "system",
212+
"content": [
213+
{"type": "text", "text": "You are a helpful assistant."},
214+
{"type": "text", "text": "Be concise and clear."},
215+
],
216+
},
217+
{"role": "user", "content": "hello"},
218+
]
219+
),
220+
id="iterator",
221+
),
207222
],
208223
)
209224
def test_nonstreaming_chat_completion(sentry_init, capture_events, messages, request):
@@ -335,6 +350,21 @@ async def test_nonstreaming_chat_completion_async_no_prompts(
335350
],
336351
id="parts",
337352
),
353+
pytest.param(
354+
iter(
355+
[
356+
{
357+
"role": "system",
358+
"content": [
359+
{"type": "text", "text": "You are a helpful assistant."},
360+
{"type": "text", "text": "Be concise and clear."},
361+
],
362+
},
363+
{"role": "user", "content": "hello"},
364+
]
365+
),
366+
id="iterator",
367+
),
338368
],
339369
)
340370
async def test_nonstreaming_chat_completion_async(
@@ -521,6 +551,21 @@ def test_streaming_chat_completion_no_prompts(
521551
],
522552
id="parts",
523553
),
554+
pytest.param(
555+
iter(
556+
[
557+
{
558+
"role": "system",
559+
"content": [
560+
{"type": "text", "text": "You are a helpful assistant."},
561+
{"type": "text", "text": "Be concise and clear."},
562+
],
563+
},
564+
{"role": "user", "content": "hello"},
565+
]
566+
),
567+
id="iterator",
568+
),
524569
],
525570
)
526571
def test_streaming_chat_completion(sentry_init, capture_events, messages, request):
@@ -757,6 +802,21 @@ async def test_streaming_chat_completion_async_no_prompts(
757802
],
758803
id="parts",
759804
),
805+
pytest.param(
806+
iter(
807+
[
808+
{
809+
"role": "system",
810+
"content": [
811+
{"type": "text", "text": "You are a helpful assistant."},
812+
{"type": "text", "text": "Be concise and clear."},
813+
],
814+
},
815+
{"role": "user", "content": "hello"},
816+
]
817+
),
818+
id="iterator",
819+
),
760820
],
761821
)
762822
async def test_streaming_chat_completion_async(

0 commit comments

Comments
 (0)