text: accept max_completion_tokens as an alias for max_tokens

Newer OpenAI clients send max_completion_tokens instead of the deprecated
max_tokens. Our request model only read max_tokens, so such a request arrived with
max_tokens=None and fell back to the default — ignoring the client's limit. Add a
max_completion_tokens field and a model_validator that maps it onto max_tokens when
max_tokens is omitted (max_tokens wins when both are present).
Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdMufYvtTbtGDWsiZVoXce
parent e410d4be
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
import time import time
from typing import Dict, List, Optional, Union from typing import Dict, List, Optional, Union
from pydantic import BaseModel, Field, field_validator, ConfigDict from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
class ToolFunction(BaseModel): class ToolFunction(BaseModel):
...@@ -73,6 +73,7 @@ class ChatCompletionRequest(BaseModel): ...@@ -73,6 +73,7 @@ class ChatCompletionRequest(BaseModel):
top_p: float = Field(1.0, description="Nucleus sampling probability mass.") top_p: float = Field(1.0, description="Nucleus sampling probability mass.")
n: int = Field(1, description="Number of completions to generate.") n: int = Field(1, description="Number of completions to generate.")
max_tokens: Optional[int] = Field(None, description="Max tokens to generate (model default if omitted).") max_tokens: Optional[int] = Field(None, description="Max tokens to generate (model default if omitted).")
max_completion_tokens: Optional[int] = Field(None, description="Newer OpenAI alias for max_tokens; used when max_tokens is omitted.")
stream: bool = Field(False, description="Stream the response as Server-Sent Events.") stream: bool = Field(False, description="Stream the response as Server-Sent Events.")
stop: Optional[Union[str, List[str]]] = Field(None, description="Stop sequence(s) that end generation.") stop: Optional[Union[str, List[str]]] = Field(None, description="Stop sequence(s) that end generation.")
presence_penalty: float = Field(0.0, description="Penalize tokens already present (encourages new topics).") presence_penalty: float = Field(0.0, description="Penalize tokens already present (encourages new topics).")
...@@ -92,6 +93,14 @@ class ChatCompletionRequest(BaseModel): ...@@ -92,6 +93,14 @@ class ChatCompletionRequest(BaseModel):
model_config = ConfigDict(extra="allow") # Allow extra fields to prevent 422 errors model_config = ConfigDict(extra="allow") # Allow extra fields to prevent 422 errors
@model_validator(mode="after")
def _alias_max_completion_tokens(self):
"""Accept the newer OpenAI ``max_completion_tokens`` as an alias for
``max_tokens``. ``max_tokens`` wins when both are sent."""
if self.max_tokens is None and self.max_completion_tokens is not None:
self.max_tokens = self.max_completion_tokens
return self
class CompletionRequest(BaseModel): class CompletionRequest(BaseModel):
model: str = Field(..., description="Text model id to use.") model: str = Field(..., description="Text model id to use.")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment