Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/openai/resources/chat/completions/completions.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseForma
"/chat/completions",
body=maybe_transform(
{
"messages": messages,
"model": model,
"stream": False,
"service_tier": service_tier,
"messages": messages,
"audio": audio,
"frequency_penalty": frequency_penalty,
"function_call": function_call,
Expand All @@ -219,10 +221,8 @@ def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseForma
"response_format": _type_to_response_format(response_format),
"safety_identifier": safety_identifier,
"seed": seed,
"service_tier": service_tier,
"stop": stop,
"store": store,
"stream": False,
"stream_options": stream_options,
"temperature": temperature,
"tool_choice": tool_choice,
Expand Down Expand Up @@ -1829,8 +1829,10 @@ def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseForma
"/chat/completions",
body=await async_maybe_transform(
{
"messages": messages,
"model": model,
"stream": False,
"service_tier": service_tier,
"messages": messages,
"audio": audio,
"frequency_penalty": frequency_penalty,
"function_call": function_call,
Expand All @@ -1853,10 +1855,8 @@ def parser(raw_completion: ChatCompletion) -> ParsedChatCompletion[ResponseForma
"response_format": _type_to_response_format(response_format),
"safety_identifier": safety_identifier,
"seed": seed,
"service_tier": service_tier,
"store": store,
"stop": stop,
"stream": False,
"stream_options": stream_options,
"temperature": temperature,
"tool_choice": tool_choice,
Expand Down
12 changes: 6 additions & 6 deletions src/openai/resources/responses/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,9 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"/responses",
body=maybe_transform(
{
"model": model,
"stream": stream,
"service_tier": service_tier,
"access_programs": access_programs,
"background": background,
"context_management": context_management,
Expand All @@ -1407,7 +1410,6 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"max_output_tokens": max_output_tokens,
"max_tool_calls": max_tool_calls,
"metadata": metadata,
"model": model,
"moderation": moderation,
"parallel_tool_calls": parallel_tool_calls,
"previous_response_id": previous_response_id,
Expand All @@ -1417,9 +1419,7 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"prompt_cache_retention": prompt_cache_retention,
"reasoning": reasoning,
"safety_identifier": safety_identifier,
"service_tier": service_tier,
"store": store,
"stream": stream,
"stream_options": stream_options,
"temperature": temperature,
"text": text,
Expand Down Expand Up @@ -3305,6 +3305,9 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"/responses",
body=maybe_transform(
{
"model": model,
"stream": stream,
"service_tier": service_tier,
"access_programs": access_programs,
"background": background,
"context_management": context_management,
Expand All @@ -3315,7 +3318,6 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"max_output_tokens": max_output_tokens,
"max_tool_calls": max_tool_calls,
"metadata": metadata,
"model": model,
"moderation": moderation,
"parallel_tool_calls": parallel_tool_calls,
"previous_response_id": previous_response_id,
Expand All @@ -3325,9 +3327,7 @@ def parser(raw_response: Response) -> ParsedResponse[TextFormatT]:
"prompt_cache_retention": prompt_cache_retention,
"reasoning": reasoning,
"safety_identifier": safety_identifier,
"service_tier": service_tier,
"store": store,
"stream": stream,
"stream_options": stream_options,
"temperature": temperature,
"text": text,
Expand Down
155 changes: 155 additions & 0 deletions tests/test_request_body_routing_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
from __future__ import annotations

import json
from typing import Any

import httpx2
import pytest

from openai import OpenAI, AsyncOpenAI

LARGE_PAYLOAD = "x" * (1024 * 1024)


def response_for(request: httpx2.Request) -> httpx2.Response:
if request.url.path.endswith("/responses"):
return httpx2.Response(
200,
json={
"id": "resp_test",
"created_at": 0,
"model": "gpt-test",
"object": "response",
"output": [],
"parallel_tool_calls": True,
"status": "completed",
"tool_choice": "auto",
"tools": [],
},
)

return httpx2.Response(
200,
json={
"id": "chatcmpl_test",
"choices": [],
"created": 0,
"model": "gpt-test",
"object": "chat.completion",
},
)


def request_keys(request: httpx2.Request) -> list[str]:
pairs: list[tuple[str, Any]] = json.loads(request.content, object_pairs_hook=lambda items: items)
return [key for key, _ in pairs]


def assert_request_keys(
request: httpx2.Request,
*,
prefix: list[str],
absent: tuple[str, ...] = (),
) -> None:
keys = request_keys(request)
assert keys[: len(prefix)] == prefix
assert not set(absent).intersection(keys)


def test_parse_helpers_prioritize_routing_fields_on_the_wire() -> None:
requests: list[httpx2.Request] = []

def record(request: httpx2.Request) -> httpx2.Response:
requests.append(request)
return response_for(request)

with OpenAI(
api_key="test-key",
base_url="https://example.test/v1",
http_client=httpx2.Client(transport=httpx2.MockTransport(record), trust_env=False),
) as client:
client.responses.parse(
model="gpt-test",
stream=False,
service_tier="default",
input=LARGE_PAYLOAD,
)
client.chat.completions.parse(
model="gpt-test",
service_tier="default",
messages=[{"role": "user", "content": LARGE_PAYLOAD}],
)
client.responses.parse(model="gpt-test", input=LARGE_PAYLOAD)
client.chat.completions.parse(
model="gpt-test",
messages=[{"role": "user", "content": LARGE_PAYLOAD}],
)

assert_request_keys(
requests[0],
prefix=["model", "stream", "service_tier", "input"],
)
assert_request_keys(
requests[1],
prefix=["model", "stream", "service_tier", "messages"],
)
assert_request_keys(
requests[2],
prefix=["model", "input"],
absent=("stream", "service_tier"),
)
assert_request_keys(
requests[3],
prefix=["model", "stream", "messages"],
absent=("service_tier",),
)


@pytest.mark.asyncio
async def test_async_parse_helpers_prioritize_routing_fields_on_the_wire() -> None:
requests: list[httpx2.Request] = []

def record(request: httpx2.Request) -> httpx2.Response:
requests.append(request)
return response_for(request)

async with AsyncOpenAI(
api_key="test-key",
base_url="https://example.test/v1",
http_client=httpx2.AsyncClient(transport=httpx2.MockTransport(record), trust_env=False),
) as client:
await client.responses.parse(
model="gpt-test",
stream=False,
service_tier="default",
input=LARGE_PAYLOAD,
)
await client.chat.completions.parse(
model="gpt-test",
service_tier="default",
messages=[{"role": "user", "content": LARGE_PAYLOAD}],
)
await client.responses.parse(model="gpt-test", input=LARGE_PAYLOAD)
await client.chat.completions.parse(
model="gpt-test",
messages=[{"role": "user", "content": LARGE_PAYLOAD}],
)

assert_request_keys(
requests[0],
prefix=["model", "stream", "service_tier", "input"],
)
assert_request_keys(
requests[1],
prefix=["model", "stream", "service_tier", "messages"],
)
assert_request_keys(
requests[2],
prefix=["model", "input"],
absent=("stream", "service_tier"),
)
assert_request_keys(
requests[3],
prefix=["model", "stream", "messages"],
absent=("service_tier",),
)
Loading