mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-28 01:32:17 +00:00
Merge 91c77e4d73 into 8b001d4024
This commit is contained in:
commit
23c820d7f4
3 changed files with 53 additions and 2 deletions
|
|
@ -845,7 +845,7 @@ class ModelResponseIterator:
|
|||
# Track current content block type for filtering deltas
|
||||
self.current_content_block_type = content_block_start["content_block"]["type"]
|
||||
if content_block_start["content_block"]["type"] == "text":
|
||||
text = content_block_start["content_block"]["text"]
|
||||
text = content_block_start["content_block"].get("text") or ""
|
||||
elif (
|
||||
content_block_start["content_block"]["type"] == "tool_use"
|
||||
or content_block_start["content_block"]["type"] == "server_tool_use"
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ class ToolUseBlock(TypedDict):
|
|||
caller: ToolCaller | None
|
||||
|
||||
|
||||
class TextBlock(TypedDict):
|
||||
class TextBlock(TypedDict, total=False):
|
||||
text: str
|
||||
|
||||
type: Literal["text"]
|
||||
|
|
|
|||
51
tests/test_anthropic_streaming_content_block_start.py
Normal file
51
tests/test_anthropic_streaming_content_block_start.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import pytest
|
||||
from litellm.llms.anthropic.chat.handler import ModelResponseIterator
|
||||
|
||||
|
||||
def test_chunk_parser_content_block_start_omits_text():
|
||||
"""
|
||||
Test that ModelResponseIterator.chunk_parser handles content_block_start
|
||||
when the 'text' key is omitted by third-party Anthropic-compatible upstreams.
|
||||
Fixes Issue #40689.
|
||||
"""
|
||||
iterator = ModelResponseIterator(streaming_response=[], sync_stream=True)
|
||||
|
||||
# 1. Chunk omitting "text" entirely
|
||||
chunk_without_text = {
|
||||
"type": "content_block_start",
|
||||
"index": 0,
|
||||
"content_block": {"type": "text"},
|
||||
}
|
||||
res = iterator.chunk_parser(chunk_without_text)
|
||||
assert res is not None
|
||||
assert res.choices[0].delta.content == ""
|
||||
|
||||
# 2. Chunk with standard official empty string text
|
||||
chunk_with_empty_text = {
|
||||
"type": "content_block_start",
|
||||
"index": 0,
|
||||
"content_block": {"type": "text", "text": ""},
|
||||
}
|
||||
res = iterator.chunk_parser(chunk_with_empty_text)
|
||||
assert res is not None
|
||||
assert res.choices[0].delta.content == ""
|
||||
|
||||
# 3. Chunk with text as None
|
||||
chunk_with_none_text = {
|
||||
"type": "content_block_start",
|
||||
"index": 0,
|
||||
"content_block": {"type": "text", "text": None},
|
||||
}
|
||||
res = iterator.chunk_parser(chunk_with_none_text)
|
||||
assert res is not None
|
||||
assert res.choices[0].delta.content == ""
|
||||
|
||||
# 4. Chunk with actual initial text
|
||||
chunk_with_text = {
|
||||
"type": "content_block_start",
|
||||
"index": 0,
|
||||
"content_block": {"type": "text", "text": "hello"},
|
||||
}
|
||||
res = iterator.chunk_parser(chunk_with_text)
|
||||
assert res is not None
|
||||
assert res.choices[0].delta.content == "hello"
|
||||
Loading…
Add table
Reference in a new issue