diff --git a/python/sglang/srt/entrypoints/openai/protocol.py b/python/sglang/srt/entrypoints/openai/protocol.py index b44f338e5..192869c31 100644 --- a/python/sglang/srt/entrypoints/openai/protocol.py +++ b/python/sglang/srt/entrypoints/openai/protocol.py @@ -313,6 +313,18 @@ class ChatCompletionMessageGenericParam(BaseModel): reasoning_content: Optional[str] = None tool_calls: Optional[List[ToolCall]] = Field(default=None, examples=[None]) + @field_validator("role", mode="before") + @classmethod + def _normalize_role(cls, v): + if isinstance(v, str): + v_lower = v.lower() + if v_lower not in {"system", "assistant", "tool"}: + raise ValueError( + "'role' must be one of 'system', 'assistant', or 'tool' (case-insensitive)." + ) + return v_lower + raise ValueError("'role' must be a string") + class ChatCompletionMessageUserParam(BaseModel): role: Literal["user"]