mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
fix(responses-bridge): emit annotations on output_text input items
Closes #35213 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
c274cf321c
commit
075bb3d245
2 changed files with 80 additions and 4 deletions
|
|
@ -740,7 +740,7 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
if role == "user" or role == "system" or role == "tool":
|
||||
return {"type": "input_text", "text": content}
|
||||
else:
|
||||
return {"type": "output_text", "text": content}
|
||||
return {"type": "output_text", "text": content, "annotations": []}
|
||||
|
||||
def _convert_content_to_responses_format_image(
|
||||
self, content: "ChatCompletionImageObject", role: str
|
||||
|
|
@ -851,9 +851,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
"computer_screenshot",
|
||||
"summary_text",
|
||||
]:
|
||||
# Already in responses API format
|
||||
result.append(item)
|
||||
verbose_logger.debug(f"Chat provider: passthrough -> {item}")
|
||||
passthrough = {"annotations": [], **item} if item_type == "output_text" else item
|
||||
result.append(passthrough)
|
||||
verbose_logger.debug(f"Chat provider: passthrough -> {passthrough}")
|
||||
else:
|
||||
# Default to input_text for unknown types
|
||||
converted = self._convert_content_str_to_input_text(str(item.get("text", item)), role)
|
||||
|
|
|
|||
|
|
@ -2962,3 +2962,79 @@ async def test_acompletion_bridge_normalizes_stream_options_on_the_wire(
|
|||
assert "stream_options" not in request_body
|
||||
else:
|
||||
assert request_body["stream_options"] == expected_wire_stream_options
|
||||
|
||||
|
||||
def test_assistant_history_output_text_items_include_annotations():
|
||||
"""
|
||||
Regression test for issue #35213: assistant history replayed through the
|
||||
chat -> responses bridge produced ``output_text`` blocks without the
|
||||
``annotations`` key, which strict Responses backends reject with
|
||||
"Required property 'annotations' is missing".
|
||||
"""
|
||||
from openai.types.responses.response_output_text_param import ResponseOutputTextParam
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
from litellm.completion_extras.litellm_responses_transformation.transformation import (
|
||||
LiteLLMResponsesTransformationHandler,
|
||||
)
|
||||
|
||||
handler = LiteLLMResponsesTransformationHandler()
|
||||
|
||||
messages = [
|
||||
{"role": "user", "content": "first question"},
|
||||
{"role": "assistant", "content": "plain string answer"},
|
||||
{"role": "user", "content": "second question"},
|
||||
{"role": "assistant", "content": [{"type": "text", "text": "list text answer"}]},
|
||||
{"role": "user", "content": "third question"},
|
||||
{"role": "assistant", "content": [{"type": "output_text", "text": "passthrough answer"}]},
|
||||
]
|
||||
|
||||
input_items, _ = handler.convert_chat_completion_messages_to_responses_api(messages)
|
||||
|
||||
output_text_blocks = [
|
||||
block
|
||||
for item in input_items
|
||||
if item.get("role") == "assistant"
|
||||
for block in item["content"]
|
||||
if block.get("type") == "output_text"
|
||||
]
|
||||
assert len(output_text_blocks) == 3
|
||||
assert [block["text"] for block in output_text_blocks] == [
|
||||
"plain string answer",
|
||||
"list text answer",
|
||||
"passthrough answer",
|
||||
]
|
||||
output_text_adapter = TypeAdapter(ResponseOutputTextParam)
|
||||
for block in output_text_blocks:
|
||||
assert block["annotations"] == []
|
||||
output_text_adapter.validate_python(block)
|
||||
|
||||
|
||||
def test_assistant_history_output_text_preserves_existing_annotations():
|
||||
from litellm.completion_extras.litellm_responses_transformation.transformation import (
|
||||
LiteLLMResponsesTransformationHandler,
|
||||
)
|
||||
|
||||
annotations = [
|
||||
{
|
||||
"type": "url_citation",
|
||||
"url": "https://example.com",
|
||||
"title": "example",
|
||||
"start_index": 0,
|
||||
"end_index": 5,
|
||||
}
|
||||
]
|
||||
handler = LiteLLMResponsesTransformationHandler()
|
||||
|
||||
input_items, _ = handler.convert_chat_completion_messages_to_responses_api(
|
||||
[
|
||||
{"role": "user", "content": "hi"},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": [{"type": "output_text", "text": "cited", "annotations": annotations}],
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
assistant_item = next(item for item in input_items if item.get("role") == "assistant")
|
||||
assert assistant_item["content"][0]["annotations"] == annotations
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue