mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-25 05:54:53 +00:00
Merge abc79dd430 into d7620c77a1
This commit is contained in:
commit
076abff4a2
4 changed files with 107 additions and 5 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
32
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
32
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue