[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
c45fa95c20
commit
ac8d5aee02
3 changed files with 51 additions and 19 deletions
|
|
@ -456,12 +456,14 @@ class ChatCompletion(BaseModel):
|
|||
|
||||
class ResponsesInputTextPart(BaseModel):
|
||||
"""Text content part in a Responses API message (type=input_text)."""
|
||||
|
||||
type: Literal["input_text"]
|
||||
text: str
|
||||
|
||||
|
||||
class ResponsesInputImagePart(BaseModel):
|
||||
"""Image content part in a Responses API message (type=input_image)."""
|
||||
|
||||
type: Literal["input_image"]
|
||||
image_url: str = Field(..., description = "data:image/png;base64,... or https://...")
|
||||
detail: Optional[Literal["auto", "low", "high"]] = "auto"
|
||||
|
|
@ -472,12 +474,14 @@ ResponsesContentPart = Union[ResponsesInputTextPart, ResponsesInputImagePart]
|
|||
|
||||
class ResponsesInputMessage(BaseModel):
|
||||
"""A single message in the Responses API input array."""
|
||||
|
||||
role: Literal["system", "user", "assistant", "developer"]
|
||||
content: Union[str, list[ResponsesContentPart]]
|
||||
|
||||
|
||||
class ResponsesRequest(BaseModel):
|
||||
"""OpenAI Responses API request."""
|
||||
|
||||
model: str = Field("default", description = "Model identifier")
|
||||
input: Union[str, list[ResponsesInputMessage]] = Field(
|
||||
default = [],
|
||||
|
|
@ -510,6 +514,7 @@ class ResponsesRequest(BaseModel):
|
|||
|
||||
class ResponsesOutputTextContent(BaseModel):
|
||||
"""A text content block inside an output message."""
|
||||
|
||||
type: Literal["output_text"] = "output_text"
|
||||
text: str
|
||||
annotations: list = Field(default_factory = list)
|
||||
|
|
@ -517,6 +522,7 @@ class ResponsesOutputTextContent(BaseModel):
|
|||
|
||||
class ResponsesOutputMessage(BaseModel):
|
||||
"""An output message in the Responses API response."""
|
||||
|
||||
type: Literal["message"] = "message"
|
||||
id: str = Field(default_factory = lambda: f"msg_{uuid.uuid4().hex[:12]}")
|
||||
status: Literal["completed", "in_progress"] = "completed"
|
||||
|
|
@ -526,6 +532,7 @@ class ResponsesOutputMessage(BaseModel):
|
|||
|
||||
class ResponsesUsage(BaseModel):
|
||||
"""Token usage for a Responses API response (input_tokens, not prompt_tokens)."""
|
||||
|
||||
input_tokens: int = 0
|
||||
output_tokens: int = 0
|
||||
total_tokens: int = 0
|
||||
|
|
@ -533,6 +540,7 @@ class ResponsesUsage(BaseModel):
|
|||
|
||||
class ResponsesResponse(BaseModel):
|
||||
"""Top-level Responses API response object."""
|
||||
|
||||
id: str = Field(default_factory = lambda: f"resp_{uuid.uuid4().hex[:12]}")
|
||||
object: Literal["response"] = "response"
|
||||
created_at: int = Field(default_factory = lambda: int(time.time()))
|
||||
|
|
|
|||
|
|
@ -1953,16 +1953,20 @@ def _normalise_responses_input(payload: ResponsesRequest) -> list[ChatMessage]:
|
|||
if isinstance(part, ResponsesInputTextPart):
|
||||
parts.append(TextContentPart(type = "text", text = part.text))
|
||||
elif isinstance(part, ResponsesInputImagePart):
|
||||
parts.append(ImageContentPart(
|
||||
type = "image_url",
|
||||
image_url = ImageUrl(url = part.image_url, detail = part.detail),
|
||||
))
|
||||
parts.append(
|
||||
ImageContentPart(
|
||||
type = "image_url",
|
||||
image_url = ImageUrl(url = part.image_url, detail = part.detail),
|
||||
)
|
||||
)
|
||||
messages.append(ChatMessage(role = role, content = parts if parts else ""))
|
||||
|
||||
return messages
|
||||
|
||||
|
||||
def _build_chat_request(payload: ResponsesRequest, messages: list[ChatMessage], stream: bool) -> ChatCompletionRequest:
|
||||
def _build_chat_request(
|
||||
payload: ResponsesRequest, messages: list[ChatMessage], stream: bool
|
||||
) -> ChatCompletionRequest:
|
||||
"""Build a ChatCompletionRequest from a ResponsesRequest."""
|
||||
chat_kwargs = dict(
|
||||
model = payload.model,
|
||||
|
|
@ -2097,7 +2101,9 @@ async def _responses_stream(
|
|||
usage = chunk_data.get("usage")
|
||||
if usage:
|
||||
input_tokens = usage.get("prompt_tokens", input_tokens)
|
||||
output_tokens = usage.get("completion_tokens", output_tokens)
|
||||
output_tokens = usage.get(
|
||||
"completion_tokens", output_tokens
|
||||
)
|
||||
continue
|
||||
|
||||
delta = choices[0].get("delta", {})
|
||||
|
|
@ -2139,13 +2145,21 @@ async def _responses_stream(
|
|||
"created_at": created_at,
|
||||
"status": "completed",
|
||||
"model": payload.model,
|
||||
"output": [{
|
||||
"type": "message",
|
||||
"id": msg_id,
|
||||
"status": "completed",
|
||||
"role": "assistant",
|
||||
"content": [{"type": "output_text", "text": full_text, "annotations": []}],
|
||||
}],
|
||||
"output": [
|
||||
{
|
||||
"type": "message",
|
||||
"id": msg_id,
|
||||
"status": "completed",
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{
|
||||
"type": "output_text",
|
||||
"text": full_text,
|
||||
"annotations": [],
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"input_tokens": input_tokens,
|
||||
"output_tokens": output_tokens,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ from models.inference import (
|
|||
# pulls in heavy dependencies (structlog/twisted/torch). This is a
|
||||
# direct copy of the function for testing purposes.
|
||||
|
||||
|
||||
def _normalise_responses_input(payload: ResponsesRequest) -> list:
|
||||
"""Convert a ResponsesRequest into a list of ChatMessage for the completions backend."""
|
||||
messages = []
|
||||
|
|
@ -65,10 +66,12 @@ def _normalise_responses_input(payload: ResponsesRequest) -> list:
|
|||
if isinstance(part, ResponsesInputTextPart):
|
||||
parts.append(TextContentPart(type = "text", text = part.text))
|
||||
elif isinstance(part, ResponsesInputImagePart):
|
||||
parts.append(ImageContentPart(
|
||||
type = "image_url",
|
||||
image_url = ImageUrl(url = part.image_url, detail = part.detail),
|
||||
))
|
||||
parts.append(
|
||||
ImageContentPart(
|
||||
type = "image_url",
|
||||
image_url = ImageUrl(url = part.image_url, detail = part.detail),
|
||||
)
|
||||
)
|
||||
messages.append(ChatMessage(role = role, content = parts if parts else ""))
|
||||
|
||||
return messages
|
||||
|
|
@ -106,7 +109,10 @@ class TestResponsesRequest:
|
|||
"role": "user",
|
||||
"content": [
|
||||
{"type": "input_text", "text": "What is in this image?"},
|
||||
{"type": "input_image", "image_url": "https://example.com/img.png"},
|
||||
{
|
||||
"type": "input_image",
|
||||
"image_url": "https://example.com/img.png",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
@ -270,7 +276,10 @@ class TestNormaliseResponsesInput:
|
|||
"role": "user",
|
||||
"content": [
|
||||
{"type": "input_text", "text": "Describe this:"},
|
||||
{"type": "input_image", "image_url": "data:image/png;base64,abc"},
|
||||
{
|
||||
"type": "input_image",
|
||||
"image_url": "data:image/png;base64,abc",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
@ -315,4 +324,5 @@ class TestNormaliseResponsesInput:
|
|||
|
||||
if __name__ == "__main__":
|
||||
import pytest
|
||||
|
||||
pytest.main([__file__, "-v"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue