fix: forward all perplexity search params instead of a hardcoded subset (#30752)

* Forward all Perplexity search params instead of a hardcoded subset

PerplexitySearchConfig.transform_search_request only copied four keys
(max_results, search_domain_filter, max_tokens_per_page, country) into
the outgoing request body and silently dropped everything else, so
documented Search API parameters like search_after_date_filter,
search_before_date_filter, last_updated_after_filter,
last_updated_before_filter, search_recency_filter, search_language_filter,
search_context_size and max_tokens never reached Perplexity even though
callers could set them.

Perplexity's native parameter names already match LiteLLM's unified search
spec, so there is nothing to remap; the transformation now passes every set
optional parameter through as-is, the same approach the Exa AI search
transformation already takes. None-valued params are still omitted.

* fix: update litellm/llms/perplexity/search/transformation.py

add key != "query"

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Add search transformation tests and extend PerplexitySearchRequest

Adds unit tests asserting the Perplexity Search request body forwards the
full documented parameter set (search_after_date_filter,
search_before_date_filter, last_updated_after_filter,
last_updated_before_filter, search_recency_filter, search_language_filter,
search_context_size, max_tokens and the original four), omits None/unset
params, passes through arbitrary params, and never lets an optional_params
"query" key override the query argument.

Extends the PerplexitySearchRequest TypedDict with those documented fields
so it no longer advertises only the original four.

* Use builtin list[str] for new search_language_filter field

The UP006 strict-budget gate is over its ceiling on the base branch, so
any net-new typing.List usage fails CI. Type the newly added
search_language_filter field with the builtin list[str] generic instead of
List[str] so the change adds no new UP006 violations.

---------

Co-authored-by: Mehmet Can Şakiroğlu <can.sakiroglu@getmidas.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Mehmet Can Şakiroğlu 2026-06-23 16:45:46 +03:00 • committed by Sameer Kankute
parent 4d31446b91
commit 6f1a183b17
No known key found for this signature in database
3 changed files with 92 additions and 29 deletions

View file

@ -29,6 +29,14 @@ class PerplexitySearchRequest(_PerplexitySearchRequestRequired, total=False):
max_results: int # Optional - maximum number of results (1-20), default 10
search_domain_filter: List[str] # Optional - list of domains to filter (max 20)
search_recency_filter: str # Optional - hour | day | week | month | year
search_after_date_filter: str # Optional - publish date >= MM/DD/YYYY
search_before_date_filter: str # Optional - publish date <= MM/DD/YYYY
last_updated_after_filter: str # Optional - last-updated date >= MM/DD/YYYY
last_updated_before_filter: str # Optional - last-updated date <= MM/DD/YYYY
search_language_filter: list[str] # Optional - ISO 639-1 codes (max 20)
search_context_size: str # Optional - low | medium | high
max_tokens: int # Optional - max tokens across results
max_tokens_per_page: int # Optional - max tokens per page, default 1024
country: str # Optional - country code filter (e.g., 'US', 'GB', 'DE')
@ -90,45 +98,33 @@ class PerplexitySearchConfig(BaseSearchConfig):
"""
Transform Search request to Perplexity API format.
Note: LiteLLM's native spec is the perplexity search spec.
There's no transformation needed for the request data.
Perplexity's native parameter names match LiteLLM's unified search spec,
so every set optional parameter is passed through as-is rather than an
arbitrary subset. None-valued params are omitted.
https://docs.perplexity.ai/api-reference/search-post
Args:
query: Search query (string or list of strings)
optional_params: Optional parameters for the request
- max_results: Maximum number of search results (1-20)
- search_domain_filter: List of domains to filter (max 20)
- max_tokens_per_page: Max tokens per page (default 1024)
- country: Country code filter (e.g., 'US', 'GB', 'DE')
optional_params: Optional Perplexity Search API parameters, forwarded
as-is (e.g. max_results, search_domain_filter, country,
max_tokens_per_page, search_recency_filter, search_after_date_filter,
search_before_date_filter, last_updated_after_filter,
last_updated_before_filter, search_language_filter,
search_context_size, max_tokens)
Returns:
Dict with typed request data following PerplexitySearchRequest spec
Dict with the Perplexity Search request body
"""
request_data: PerplexitySearchRequest = {
"query": query,
request_data: PerplexitySearchRequest = {"query": query}
forwarded = {
key: value
for key, value in optional_params.items()
if value is not None and key != "query"
}
# Add optional parameters following Perplexity API spec (only if not None)
max_results = optional_params.get("max_results")
if max_results is not None:
request_data["max_results"] = max_results
search_domain_filter = optional_params.get("search_domain_filter")
if search_domain_filter is not None:
request_data["search_domain_filter"] = search_domain_filter
max_tokens_per_page = optional_params.get("max_tokens_per_page")
if max_tokens_per_page is not None:
request_data["max_tokens_per_page"] = max_tokens_per_page
country = optional_params.get("country")
if country is not None:
request_data["country"] = country
return dict(request_data)
return dict(request_data, **forwarded)
def transform_search_response(
self,

View file

@ -0,0 +1,67 @@
from litellm.llms.perplexity.search.transformation import PerplexitySearchConfig
class TestPerplexitySearchRequestTransformation:
def test_forwards_full_documented_param_set(self):
config = PerplexitySearchConfig()
optional_params = {
"search_after_date_filter": "01/01/2026",
"search_before_date_filter": "06/15/2026",
"last_updated_after_filter": "03/01/2026",
"last_updated_before_filter": "03/31/2026",
"search_recency_filter": "month",
"search_language_filter": ["en"],
"search_context_size": "high",
"max_tokens": 2048,
"max_results": 5,
"search_domain_filter": ["europa.eu"],
"max_tokens_per_page": 1024,
"country": "US",
}
body = config.transform_search_request(
query="EU AI Act", optional_params=optional_params
)
assert body == {"query": "EU AI Act", **optional_params}
def test_omits_unset_and_none_optional_params(self):
config = PerplexitySearchConfig()
body = config.transform_search_request(
query="hello",
optional_params={"search_recency_filter": None, "max_results": 5},
)
assert body == {"query": "hello", "max_results": 5}
def test_passes_through_arbitrary_params(self):
config = PerplexitySearchConfig()
body = config.transform_search_request(
query="hello",
optional_params={"some_new_perplexity_param": "x", "country": "GB"},
)
assert body == {
"query": "hello",
"some_new_perplexity_param": "x",
"country": "GB",
}
def test_query_argument_is_not_overridden_by_optional_params(self):
config = PerplexitySearchConfig()
body = config.transform_search_request(
query="real query",
optional_params={"query": "injected", "search_recency_filter": "week"},
)
assert body == {"query": "real query", "search_recency_filter": "week"}
def test_query_only_request(self):
config = PerplexitySearchConfig()
body = config.transform_search_request(query=["a", "b"], optional_params={})
assert body == {"query": ["a", "b"]}