This commit is contained in:
poppy12345 2026-10-19 19:10:31 +00:00 • committed by GitHub
commit 076abff4a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 107 additions and 5 deletions

View file

@ -484,8 +484,8 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
)
if sanitized_tools is not None:
response_api_optional_request_params["tools"] = sanitized_tools
final_request_params: Final = dict(
ResponsesAPIRequestParams(model=model, input=replay_safe_input, **response_api_optional_request_params)
final_request_params: Final = dict[str, object](
model=model, input=replay_safe_input, **response_api_optional_request_params
)
return final_request_params
@ -1197,9 +1197,7 @@ class OpenAIResponsesAPIConfig(BaseResponsesAPIConfig):
)
if sanitized_tools is not None:
response_api_optional_request_params["tools"] = sanitized_tools
data: Final = dict(
ResponsesAPIRequestParams(model=model, input=replay_safe_input, **response_api_optional_request_params)
)
data: Final = dict[str, object](model=model, input=replay_safe_input, **response_api_optional_request_params)
return url, data

View file

@ -1323,6 +1323,26 @@ class ResponsesAPIStreamOptions(TypedDict, total=False):
include_obfuscation: bool
class ResponsesAPIModerationPolicyEntry(TypedDict, total=False):
"""Moderation policy for either the input or the output of a response."""
mode: Required[ReadOnly[Literal["score", "block"]]]
class ResponsesAPIModerationPolicy(TypedDict, total=False):
"""Policy applied to moderated response input and output."""
input: ReadOnly[ResponsesAPIModerationPolicyEntry | None]
output: ReadOnly[ResponsesAPIModerationPolicyEntry | None]
class ResponsesAPIModeration(TypedDict, total=False):
"""Configuration for running moderation on the input and output of a response."""
model: Required[ReadOnly[str]]
policy: ReadOnly[ResponsesAPIModerationPolicy | None]
class ResponsesAPIOptionalRequestParams(TypedDict, total=False):
"""TypedDict for Optional parameters supported by the responses API."""
@ -1355,6 +1375,8 @@ class ResponsesAPIOptionalRequestParams(TypedDict, total=False):
partial_images: int | None # Number of partial images to generate (1-3) for streaming image generation
context_management: list[ContextManagementEntry] | None
"""Context management configuration. E.g. [{\"type\": \"compaction\", \"compact_threshold\": 200000}] for server-side compaction (minimum 1000)."""
moderation: ReadOnly[ResponsesAPIModeration | None]
"""Moderation configuration for the response input and output. E.g. {\"model\": \"omni-moderation-latest\"}."""
class ResponsesAPIRequestParams(ResponsesAPIOptionalRequestParams, total=False):

View file

@ -228,6 +228,56 @@ async def test_aresponses_drops_stream_options():
assert "stream_options" not in request_body
@pytest.mark.asyncio
async def test_aresponses_forwards_moderation():
"""OpenAI's top-level `moderation` param must reach the wire instead of being silently dropped."""
moderation: Final = {
"model": "omni-moderation-latest",
"policy": {"input": {"mode": "score"}, "output": {"mode": "block"}},
}
with patch(
"litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post",
new_callable=AsyncMock,
) as mock_post:
mock_post.return_value = MockResponse(_minimal_responses_api_payload("resp_moderation_test", "gpt-5.4"), 200)
await litellm.aresponses(
model="openai/gpt-5.4",
api_key="fake-api-key",
input="hi",
moderation=moderation,
)
mock_post.assert_called_once()
post_kwargs = mock_post.call_args.kwargs
request_body = post_kwargs["json"] if "json" in post_kwargs else json.loads(post_kwargs["data"])
assert request_body["moderation"] == moderation
@pytest.mark.asyncio
async def test_aresponses_omits_moderation_when_none():
"""An explicit moderation=None is a default value and must not be sent to the provider."""
with patch(
"litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post",
new_callable=AsyncMock,
) as mock_post:
mock_post.return_value = MockResponse(
_minimal_responses_api_payload("resp_moderation_none_test", "gpt-5.4"), 200
)
await litellm.aresponses(
model="openai/gpt-5.4",
api_key="fake-api-key",
input="hi",
moderation=None,
)
mock_post.assert_called_once()
post_kwargs = mock_post.call_args.kwargs
request_body = post_kwargs["json"] if "json" in post_kwargs else json.loads(post_kwargs["data"])
assert "moderation" not in request_body
@pytest.mark.asyncio
async def test_aresponses_forwards_non_enum_reasoning_effort(
monkeypatch: pytest.MonkeyPatch, respx_mock: respx.MockRouter

View file

@ -43893,6 +43893,34 @@ export interface components {
*/
type: "tool_search_output";
};
/**
* ResponsesAPIModeration
* @description Configuration for running moderation on the input and output of a response.
*/
ResponsesAPIModeration: {
/** Model */
model: string;
policy?: components["schemas"]["ResponsesAPIModerationPolicy"] | null;
};
/**
* ResponsesAPIModerationPolicy
* @description Policy applied to moderated response input and output.
*/
ResponsesAPIModerationPolicy: {
input?: components["schemas"]["ResponsesAPIModerationPolicyEntry"] | null;
output?: components["schemas"]["ResponsesAPIModerationPolicyEntry"] | null;
};
/**
* ResponsesAPIModerationPolicyEntry
* @description Moderation policy for either the input or the output of a response.
*/
ResponsesAPIModerationPolicyEntry: {
/**
* Mode
* @enum {string}
*/
mode: "score" | "block";
};
/**
* ResponsesAPIRequestParams
* @description TypedDict for request parameters supported by the responses API.
@ -43918,6 +43946,7 @@ export interface components {
} | null;
/** Model */
model: string;
moderation?: components["schemas"]["ResponsesAPIModeration"] | null;
/** Parallel Tool Calls */
parallel_tool_calls?: boolean | null;
/** Partial Images */
@ -66337,6 +66366,7 @@ export interface operations {
} | null;
/** Model */
model: string;
moderation?: components["schemas"]["ResponsesAPIModeration"] | null;
/** Parallel Tool Calls */
parallel_tool_calls?: boolean | null;
/** Partial Images */
@ -69801,6 +69831,7 @@ export interface operations {
} | null;
/** Model */
model: string;
moderation?: components["schemas"]["ResponsesAPIModeration"] | null;
/** Parallel Tool Calls */
parallel_tool_calls?: boolean | null;
/** Partial Images */
@ -80458,6 +80489,7 @@ export interface operations {
} | null;
/** Model */
model: string;
moderation?: components["schemas"]["ResponsesAPIModeration"] | null;
/** Parallel Tool Calls */
parallel_tool_calls?: boolean | null;
/** Partial Images */