fix: openai moderation guardrails - #20718
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile OverviewGreptile SummaryThis change removes the OpenAI moderation guardrail’s old streaming hook that buffered the entire response before moderating, and instead relies on the UnifiedLLMGuardrails streaming hook to yield chunks immediately while running moderation checks on sampled content in parallel. Tests were updated to exercise the unified streaming path, and a new test module was added to validate time-to-first-token behavior and that harmful content is blocked during streaming. Key issues to address before merge are in the test suite: one streaming test function name is duplicated (so half the intended coverage is silently skipped), and the new latency test uses wall-clock thresholds/sleeps that can be flaky and can also crash if no chunks are yielded. Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/openai/moderations.py | Removes the buffering streaming hook and routes moderation through the unified apply_guardrail path; code looks consistent, but runtime behavior depends on UnifiedLLMGuardrails sampling/stream assembly. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py | Updates moderation tests to use UnifiedLLMGuardrails streaming hook; introduces a duplicate test function name that prevents one test from running. |
| tests/test_openai_moderation_streaming.py | Adds new streaming latency/harmful-content tests; current latency assertion is wall-clock based and can be flaky, and the test can crash if no chunks are yielded. |
Sequence Diagram
sequenceDiagram
participant Client
participant Proxy as LiteLLM Proxy
participant Unified as UnifiedLLMGuardrails
participant Model as LLM Streaming Response
participant Builder as stream_chunk_builder
participant Mod as OpenAIModerationGuardrail
participant OpenAI as OpenAI Moderations API
Client->>Proxy: /chat/completions (stream=true)
Proxy->>Model: initiate upstream stream
Model-->>Proxy: stream chunks (delta.content)
Proxy->>Unified: async_post_call_streaming_iterator_hook(response iterator, request_data)
loop For each streamed chunk
Unified-->>Client: yield chunk immediately (no buffering)
Unified->>Unified: sample chunk(s) per streaming_sampling_rate
end
Note over Unified,Builder: When sampling triggers or stream ends
Unified->>Builder: assemble sampled chunks into ModelResponse
Builder-->>Unified: ModelResponse
Unified->>Mod: apply_guardrail(inputs from assembled content, input_type="response")
Mod->>OpenAI: POST /moderations {model,input}
OpenAI-->>Mod: moderation result
alt flagged
Mod-->>Unified: raise HTTPException(400)
Unified-->>Proxy: propagate error
Proxy-->>Client: 400 Violated moderation policy
else not flagged
Mod-->>Unified: ok
end
a4f1625 to
111dd0a
Compare
|
@greptile please re-review this |
Greptile OverviewGreptile SummaryRefactors the OpenAI Moderation guardrail to delegate streaming to
Confidence Score: 2/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/openai/moderations.py | Removed log_guardrail_information import but it's still used as a decorator on apply_guardrail — will cause NameError at runtime. Also removed buffering-based streaming hook in favor of UnifiedLLMGuardrails delegation. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py | Updated streaming tests to route through UnifiedLLMGuardrails instead of the removed direct streaming hook. Tests use proper mocks. Formatting cleanup throughout. |
| tests/test_openai_moderation_streaming.py | New streaming test file with deterministic assertions. Unused asyncio import. Tests verify chunk passthrough and harmful content detection via UnifiedLLMGuardrails. |
Last reviewed commit: 5b732e3
|
@greptile re-review this PR please thanks |
Greptile OverviewGreptile SummaryRefactored
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/openai/moderations.py | Removed the buffering async_post_call_streaming_iterator_hook and _extract_response_text methods, delegating streaming to UnifiedLLMGuardrails. Cleaned up unused imports. The log_guardrail_information import (previously reported as missing) has been restored. |
| tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py | Updated streaming tests to use UnifiedLLMGuardrails instead of the removed async_post_call_streaming_iterator_hook. Properly mocks stream_chunk_builder and uses real litellm types for isinstance checks. Minor formatting cleanup. |
| tests/test_openai_moderation_streaming.py | New test file for streaming latency and harmful content detection via UnifiedLLMGuardrails. Properly mocked, but placed outside tests/test_litellm/ directory (violates PR contribution requirements). Has unused asyncio import. |
Sequence Diagram
sequenceDiagram
participant Client
participant Proxy as LiteLLM Proxy
participant UG as UnifiedLLMGuardrails
participant LLM as LLM Provider
participant Mod as OpenAI Moderation API
Client->>Proxy: Chat Completion (stream=true)
Proxy->>LLM: Forward request
LLM-->>UG: Stream chunks
loop For each chunk
UG-->>Client: Yield chunk immediately
Note over UG: Collect chunk in buffer
end
Note over UG: Stream ended (finish_reason=stop)
UG->>UG: stream_chunk_builder (assemble response)
UG->>Mod: apply_guardrail (full text)
Mod-->>UG: Moderation result
alt Content flagged
UG->>Client: HTTPException 400
end
Last reviewed commit: b6657d0
7f6563f
into
BerriAI:litellm_oss_staging_02_13_2026
* fix: openai moderation guardrails * adds missing import * mv: test file to right place
Relevant issues
Fixes latency issues with OpenAI Moderation guardrail during streaming.
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unitCI (LiteLLM team)
Link:
Link:
Links:
Type
🐛 Bug Fix
✅ Test
🧹 Refactoring
Changes
OpenAIModerationGuardrailto utilize UnifiedLLMGuardrails for streaming. This allows moderation checks to happen on sampled chunks in parallel with the stream, rather than buffering the entire response.litellm.ModelResponsestructures for the new unified guardrail flow.