You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-03-30 10:57:20 -07:00
chore: Do not treat FinishReason.STOP as error case for LLM responses containing candidates with empty contents
Fixes #2905 PiperOrigin-RevId: 825263302
This commit is contained in:
committed by
Copybara-Service
parent
8eeff35b35
commit
2f72ceb49b
@@ -148,7 +148,9 @@ class LlmResponse(BaseModel):
|
||||
usage_metadata = generate_content_response.usage_metadata
|
||||
if generate_content_response.candidates:
|
||||
candidate = generate_content_response.candidates[0]
|
||||
if candidate.content and candidate.content.parts:
|
||||
if (
|
||||
candidate.content and candidate.content.parts
|
||||
) or candidate.finish_reason == types.FinishReason.STOP:
|
||||
return LlmResponse(
|
||||
content=candidate.content,
|
||||
grounding_metadata=candidate.grounding_metadata,
|
||||
|
||||
@@ -317,3 +317,20 @@ def test_llm_response_create_error_case_with_citation_metadata():
|
||||
assert (
|
||||
response.error_message == 'Response blocked due to recitation triggered'
|
||||
)
|
||||
|
||||
|
||||
def test_llm_response_create_empty_content_with_stop_reason():
|
||||
"""Test LlmResponse.create() with empty content and stop finish reason."""
|
||||
generate_content_response = types.GenerateContentResponse(
|
||||
candidates=[
|
||||
types.Candidate(
|
||||
content=types.Content(parts=[]),
|
||||
finish_reason=types.FinishReason.STOP,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
response = LlmResponse.create(generate_content_response)
|
||||
|
||||
assert response.error_code is None
|
||||
assert response.content is not None
|
||||
|
||||
@@ -179,3 +179,24 @@ class TestStreamingResponseAggregator:
|
||||
assert closed_response.content.parts[0].text == "Error"
|
||||
assert closed_response.error_code == types.FinishReason.RECITATION
|
||||
assert closed_response.error_message == "Recitation error"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_process_response_with_none_content(self):
|
||||
"""Test that StreamingResponseAggregator handles content=None."""
|
||||
aggregator = streaming_utils.StreamingResponseAggregator()
|
||||
response = types.GenerateContentResponse(
|
||||
candidates=[
|
||||
types.Candidate(
|
||||
content=types.Content(parts=[]),
|
||||
finish_reason=types.FinishReason.STOP,
|
||||
)
|
||||
]
|
||||
)
|
||||
results = []
|
||||
async for r in aggregator.process_response(response):
|
||||
results.append(r)
|
||||
assert len(results) == 1
|
||||
assert results[0].content is not None
|
||||
|
||||
closed_response = aggregator.close()
|
||||
assert closed_response is None
|
||||
|
||||
Reference in New Issue
Block a user