diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index ce874bfde9..378ca75da5 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -797,7 +797,15 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): if content.get("citations") is not None: if citations is None: citations = [] - citations.append(content["citations"]) + citations.append( + [ + { + **citation, + "supported_text": content.get("text", ""), + } + for citation in content["citations"] + ] + ) if thinking_blocks is not None: reasoning_content = "" for block in thinking_blocks: diff --git a/tests/llm_translation/test_anthropic_completion.py b/tests/llm_translation/test_anthropic_completion.py index 45702a261e..f4bd7531b0 100644 --- a/tests/llm_translation/test_anthropic_completion.py +++ b/tests/llm_translation/test_anthropic_completion.py @@ -920,6 +920,14 @@ def test_anthropic_citations_api(): citations = resp.choices[0].message.provider_specific_fields["citations"] assert citations is not None + if citations: + citation = citations[0][0] + assert "supported_text" in citation + assert "cited_text" in citation + assert "document_index" in citation + assert "document_title" in citation + assert "start_char_index" in citation + assert "end_char_index" in citation def test_anthropic_citations_api_streaming(): @@ -955,11 +963,11 @@ def test_anthropic_citations_api_streaming(): has_citations = False for chunk in resp: print(f"returned chunk: {chunk}") - if ( - chunk.choices[0].delta.provider_specific_fields - and "citation" in chunk.choices[0].delta.provider_specific_fields - ): - has_citations = True + if provider_specific_fields := chunk.choices[0].delta.provider_specific_fields: + if "citation" in provider_specific_fields: + has_citations = True + + assert "chunk_type" in provider_specific_fields assert has_citations diff --git a/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py b/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py index ff454968d9..dcca87baf3 100644 --- a/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py +++ b/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py @@ -115,16 +115,11 @@ def test_calculate_usage_nulls(usage_object, expected_usage): assert hasattr(usage, k) assert getattr(usage, k) == v -@pytest.mark.parametrize("usage_object", [ - { - "server_tool_use": { - "web_search_requests": None - } - }, - { - "server_tool_use": None - } -]) + +@pytest.mark.parametrize( + "usage_object", + [{"server_tool_use": {"web_search_requests": None}}, {"server_tool_use": None}], +) def test_calculate_usage_server_tool_null(usage_object): """ Correctly deal with null values in usage object @@ -132,10 +127,11 @@ def test_calculate_usage_server_tool_null(usage_object): Fixes https://github.com/BerriAI/litellm/issues/11920 """ config = AnthropicConfig() - + usage = config.calculate_usage(usage_object=usage_object, reasoning_content=None) assert not hasattr(usage, "server_tool_use") + def test_extract_response_content_with_citations(): config = AnthropicConfig() @@ -188,7 +184,30 @@ def test_extract_response_content_with_citations(): } _, citations, _, _, _ = config.extract_response_content(completion_response) - assert citations is not None + assert citations == [ + [ + { + "type": "char_location", + "cited_text": "The grass is green. ", + "document_index": 0, + "document_title": "My Document", + "start_char_index": 0, + "end_char_index": 20, + "supported_text": "the grass is green", + }, + ], + [ + { + "type": "char_location", + "cited_text": "The sky is blue.", + "document_index": 0, + "document_title": "My Document", + "start_char_index": 20, + "end_char_index": 36, + "supported_text": "the sky is blue", + }, + ], + ] def test_map_tool_helper():