mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
Merge 54f15b9a53 into 44d84360fb
This commit is contained in:
commit
47cb8e8a16
2 changed files with 75 additions and 1 deletions
|
|
@ -324,7 +324,15 @@ class ChunkProcessor:
|
|||
system_fingerprint: Final = chunk.get("system_fingerprint", None)
|
||||
|
||||
first_chunk_with_choices: Final = next((c for c in chunks if c.get("choices")), chunk)
|
||||
role: Final = first_chunk_with_choices["choices"][0]["delta"]["role"]
|
||||
if (
|
||||
first_chunk_with_choices.get("choices")
|
||||
and len(first_chunk_with_choices["choices"]) > 0
|
||||
and first_chunk_with_choices["choices"][0].get("delta")
|
||||
and "role" in first_chunk_with_choices["choices"][0]["delta"]
|
||||
):
|
||||
role: Final = first_chunk_with_choices["choices"][0]["delta"]["role"]
|
||||
else:
|
||||
role = "assistant"
|
||||
finish_reason = "stop"
|
||||
for chunk in chunks:
|
||||
if "choices" in chunk and len(chunk["choices"]) > 0:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../../..")
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
from litellm.litellm_core_utils.streaming_chunk_builder_utils import ChunkProcessor
|
||||
|
||||
|
||||
def test_build_base_response_all_chunks_empty_choices():
|
||||
"""
|
||||
Regression test for the IndexError in ChunkProcessor.build_base_response
|
||||
when every chunk has choices=[] (e.g. Anthropic usage-only events).
|
||||
``next((c for c in chunks if c.get("choices")), chunk)`` skips every chunk
|
||||
(empty list is falsy) and falls back to ``chunk``, whose ``choices`` is also
|
||||
``[]`` — the old code then did ``choices[0]`` and raised IndexError.
|
||||
build_base_response should default to role='assistant'.
|
||||
"""
|
||||
chunks = [
|
||||
{
|
||||
"id": "chatcmpl-all-empty-choices",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 1234567890,
|
||||
"model": "gpt-4.1-mini",
|
||||
"choices": [],
|
||||
},
|
||||
{
|
||||
"id": "chatcmpl-all-empty-choices",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 1234567890,
|
||||
"model": "gpt-4.1-mini",
|
||||
"choices": [],
|
||||
},
|
||||
]
|
||||
|
||||
processor = ChunkProcessor(chunks=chunks)
|
||||
response = processor.build_base_response(chunks)
|
||||
|
||||
assert response.choices[0].message.role == "assistant"
|
||||
assert response.choices[0].message.content == ""
|
||||
|
||||
|
||||
def test_build_base_response_falls_back_to_assistant_when_role_missing():
|
||||
"""
|
||||
When a chunk has non-empty choices but its delta omits the role key,
|
||||
build_base_response should still produce a valid response and default
|
||||
to 'assistant'.
|
||||
"""
|
||||
chunks = [
|
||||
{
|
||||
"id": "chatcmpl-no-role",
|
||||
"object": "chat.completion.chunk",
|
||||
"created": 1234567890,
|
||||
"model": "gpt-4.1-mini",
|
||||
"choices": [
|
||||
{"index": 0, "delta": {"content": "hello"}}
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
processor = ChunkProcessor(chunks=chunks)
|
||||
response = processor.build_base_response(chunks)
|
||||
|
||||
assert response.choices[0].message.role == "assistant"
|
||||
assert response.choices[0].message.content == ""
|
||||
Loading…
Add table
Reference in a new issue