mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
fix(exa): fall back to highlights/summary when text is missing (#42213)
* fix(exa): fall back to highlights/summary when text is missing (#36905) * test: type exa search transformation test helpers * test(exa): drop type: ignore in test helper and trim redundant comments * test(exa): move snippet fallback test to tests/unit and parametrize it Uses a real httpx.Response instead of a Mock and annotates snippet as Final. * fix(exa): inline snippet fallback since Final is not allowed inside a loop --------- Co-authored-by: ryan-crabbe-berri <ryan@berri.ai>
This commit is contained in:
parent
ac59ec6824
commit
4a847ac936
4 changed files with 39 additions and 1 deletions
|
|
@ -165,6 +165,8 @@ class ExaAISearchConfig(BaseSearchConfig):
|
|||
- results[].title → SearchResult.title
|
||||
- results[].url → SearchResult.url
|
||||
- results[].text → SearchResult.snippet
|
||||
- results[].highlights → SearchResult.snippet (fallback when "text" is absent)
|
||||
- results[].summary → SearchResult.snippet (fallback when "text" and "highlights" are absent)
|
||||
- results[].publishedDate → SearchResult.date
|
||||
- No last_updated field in Exa AI response (set to None)
|
||||
|
||||
|
|
@ -183,7 +185,10 @@ class ExaAISearchConfig(BaseSearchConfig):
|
|||
search_result = SearchResult(
|
||||
title=result.get("title", ""),
|
||||
url=result.get("url", ""),
|
||||
snippet=result.get("text", ""), # Exa AI uses "text" for content
|
||||
snippet=result.get("text")
|
||||
or "\n\n".join(result.get("highlights") or [])
|
||||
or result.get("summary")
|
||||
or "",
|
||||
date=result.get("publishedDate"), # ISO 8601 datetime string
|
||||
last_updated=None, # Exa AI doesn't provide last_updated in response
|
||||
)
|
||||
|
|
|
|||
0
tests/unit/llms/exa_ai/__init__.py
Normal file
0
tests/unit/llms/exa_ai/__init__.py
Normal file
0
tests/unit/llms/exa_ai/search/__init__.py
Normal file
0
tests/unit/llms/exa_ai/search/__init__.py
Normal file
33
tests/unit/llms/exa_ai/search/test_transformation.py
Normal file
33
tests/unit/llms/exa_ai/search/test_transformation.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
from typing import Final
|
||||
from unittest.mock import Mock
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
from litellm.llms.exa_ai.search.transformation import ExaAISearchConfig
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("content_fields", "expected_snippet"),
|
||||
[
|
||||
({"text": "full text"}, "full text"),
|
||||
({"highlights": ["first highlight", "second highlight"]}, "first highlight\n\nsecond highlight"),
|
||||
({"summary": "a summary"}, "a summary"),
|
||||
({"text": "full text", "highlights": ["a highlight"], "summary": "a summary"}, "full text"),
|
||||
({"highlights": ["a highlight"], "summary": "a summary"}, "a highlight"),
|
||||
({"text": "", "highlights": ["a highlight"]}, "a highlight"),
|
||||
({"highlights": [], "summary": "a summary"}, "a summary"),
|
||||
({}, ""),
|
||||
],
|
||||
)
|
||||
def test_transform_search_response_snippet_falls_back_through_content_modes(
|
||||
content_fields: dict[str, str | list[str]], expected_snippet: str
|
||||
):
|
||||
raw_response: Final = httpx.Response(
|
||||
200,
|
||||
json={"results": [{"title": "Title", "url": "https://example.com", **content_fields}]},
|
||||
)
|
||||
|
||||
response: Final = ExaAISearchConfig().transform_search_response(raw_response, logging_obj=Mock())
|
||||
|
||||
assert response.results[0].snippet == expected_snippet
|
||||
Loading…
Add table
Reference in a new issue