feat: add a Tavily search depth setting (#31308)

Tavily web search always ran at Tavily's default depth (basic), because the search request never sent `search_depth`. The only Tavily depth control in Admin > Settings > Web Search, "Tavily Extract Depth", applies to the Extract API used by the web loader, never to search.

This adds `TAVILY_SEARCH_DEPTH` (env var and persisted setting, default `basic`) and a "Tavily Search Depth" select (ultra-fast, fast, basic, advanced) under the Tavily search engine settings. The value is sent as `search_depth` on every Tavily search request, so admins can set search and extract depth independently, for example fast search with advanced extraction.

The default matches Tavily's own default, so existing setups keep the same behaviour until the setting is changed.

Fixes #29891
This commit is contained in:
Classic298 2026-09-27 21:15:09 +02:00 • committed by GitHub
parent b8de508dbc
commit 6e5e5fe6e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 30 additions and 1 deletions

View file

@ -1302,6 +1302,8 @@ TAVILY_API_KEY = os.getenv('TAVILY_API_KEY', '')
TAVILY_EXTRACT_DEPTH = os.getenv('TAVILY_EXTRACT_DEPTH', 'basic')
TAVILY_SEARCH_DEPTH = os.getenv('TAVILY_SEARCH_DEPTH', 'basic')
STAAN_API_KEY = os.getenv('STAAN_API_KEY', '')
STAAN_MARKET = os.getenv('STAAN_MARKET', 'en-us')
@ -2998,6 +3000,7 @@ DEFAULT_CONFIG = {
'web.search.sougou_api_sk': SOUGOU_API_SK,
'web.search.tavily_api_key': TAVILY_API_KEY,
'web.search.tavily_extract_depth': TAVILY_EXTRACT_DEPTH,
'web.search.tavily_search_depth': TAVILY_SEARCH_DEPTH,
'web.search.staan_api_key': STAAN_API_KEY,
'web.search.staan_market': STAAN_MARKET,
'web.search.staan_max_snippets': STAAN_MAX_SNIPPETS,

View file

@ -14,6 +14,7 @@ def search_tavily(
query: str,
count: int,
filter_list: list[str] | None = None,
search_depth: str = 'basic',
# **kwargs,
) -> list[SearchResult]:
"""Search using Tavily's Search API and return the results as a list of SearchResult objects.
@ -22,6 +23,7 @@ def search_tavily(
api_key (str): A Tavily Search API key
query (str): The query to search for
count (int): The maximum number of results to return
search_depth (str): Tavily search depth
Returns:
A list of SearchResult objects.
@ -31,7 +33,7 @@ def search_tavily(
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_key}',
}
data = {'query': query, 'max_results': count}
data = {'query': query, 'max_results': count, 'search_depth': search_depth}
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()

View file

@ -387,6 +387,7 @@ RETRIEVAL_CONFIG_KEYS = {
'STAAN_MAX_SNIPPETS': 'web.search.staan_max_snippets',
'TAVILY_API_KEY': 'web.search.tavily_api_key',
'TAVILY_EXTRACT_DEPTH': 'web.search.tavily_extract_depth',
'TAVILY_SEARCH_DEPTH': 'web.search.tavily_search_depth',
'TEXT_SPLITTER': 'rag.text_splitter',
'TIKA_SERVER_URL': 'rag.tika_server_url',
'TIKA_SERVER_VERSION': 'rag.tika_server_version',
@ -773,6 +774,7 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
'FIRECRAWL_API_BASE_URL': config.FIRECRAWL_API_BASE_URL,
'FIRECRAWL_TIMEOUT': config.FIRECRAWL_TIMEOUT,
'TAVILY_EXTRACT_DEPTH': config.TAVILY_EXTRACT_DEPTH,
'TAVILY_SEARCH_DEPTH': config.TAVILY_SEARCH_DEPTH,
'EXTERNAL_WEB_SEARCH_URL': config.EXTERNAL_WEB_SEARCH_URL,
'EXTERNAL_WEB_SEARCH_API_KEY': config.EXTERNAL_WEB_SEARCH_API_KEY,
'EXTERNAL_WEB_LOADER_URL': config.EXTERNAL_WEB_LOADER_URL,
@ -856,6 +858,7 @@ class WebConfig(BaseModel):
FIRECRAWL_API_BASE_URL: str | None = None
FIRECRAWL_TIMEOUT: str | None = None
TAVILY_EXTRACT_DEPTH: str | None = None
TAVILY_SEARCH_DEPTH: str | None = None
EXTERNAL_WEB_SEARCH_URL: str | None = None
EXTERNAL_WEB_SEARCH_API_KEY: str | None = None
EXTERNAL_WEB_LOADER_URL: str | None = None
@ -1386,6 +1389,7 @@ async def update_rag_config(request: Request, form_data: ConfigForm, user=Depend
config.EXTERNAL_WEB_LOADER_URL = form_data.web.EXTERNAL_WEB_LOADER_URL
config.EXTERNAL_WEB_LOADER_API_KEY = form_data.web.EXTERNAL_WEB_LOADER_API_KEY
config.TAVILY_EXTRACT_DEPTH = form_data.web.TAVILY_EXTRACT_DEPTH
config.TAVILY_SEARCH_DEPTH = form_data.web.TAVILY_SEARCH_DEPTH
config.YOUTUBE_LOADER_LANGUAGE = form_data.web.YOUTUBE_LOADER_LANGUAGE
config.YOUTUBE_LOADER_PROXY_URL = form_data.web.YOUTUBE_LOADER_PROXY_URL
request.app.state.YOUTUBE_LOADER_TRANSLATION = form_data.web.YOUTUBE_LOADER_TRANSLATION
@ -1535,6 +1539,7 @@ async def update_rag_config(request: Request, form_data: ConfigForm, user=Depend
'FIRECRAWL_API_BASE_URL': config.FIRECRAWL_API_BASE_URL,
'FIRECRAWL_TIMEOUT': config.FIRECRAWL_TIMEOUT,
'TAVILY_EXTRACT_DEPTH': config.TAVILY_EXTRACT_DEPTH,
'TAVILY_SEARCH_DEPTH': config.TAVILY_SEARCH_DEPTH,
'EXTERNAL_WEB_SEARCH_URL': config.EXTERNAL_WEB_SEARCH_URL,
'EXTERNAL_WEB_SEARCH_API_KEY': config.EXTERNAL_WEB_SEARCH_API_KEY,
'EXTERNAL_WEB_LOADER_URL': config.EXTERNAL_WEB_LOADER_URL,
@ -2721,6 +2726,7 @@ async def search_web(request: Request, engine: str, query: str, user=None) -> li
query,
config.WEB_SEARCH_RESULT_COUNT,
config.WEB_SEARCH_DOMAIN_FILTER_LIST,
search_depth=config.TAVILY_SEARCH_DEPTH,
)
else:
raise Exception('No TAVILY_API_KEY found in environment variables')

View file

@ -579,6 +579,20 @@
/>
</div>
</div>
<div class="mb-2.5 flex w-full flex-col">
<div>
<div class=" self-center text-xs text-gray-600 dark:text-gray-400 mb-1">
{$i18n.t('settings.admin.web.tavilySearchDepth.label')}
</div>
<SettingsSelect bind:value={webConfig.TAVILY_SEARCH_DEPTH} className="w-full">
<option value="ultra-fast">{$i18n.t('Ultra-fast')}</option>
<option value="fast">{$i18n.t('Fast')}</option>
<option value="basic">{$i18n.t('Basic')}</option>
<option value="advanced">{$i18n.t('Advanced')}</option>
</SettingsSelect>
</div>
</div>
{:else if webConfig.WEB_SEARCH_ENGINE === 'staan'}
<div class="mb-2.5 flex w-full flex-col">
<div>

View file

@ -285,6 +285,7 @@
"Base Model (From)": "",
"Base Model is required.": "",
"Base Models": "",
"Basic": "",
"Basic text only": "",
"Basics": "",
"Bearer": "",
@ -1000,6 +1001,7 @@
"Failed to update webhook": "",
"Failed to upload background image.": "",
"Failed to upload file.": "",
"Fast": "",
"Features Permissions": "",
"February": "",
"Feedback": "",
@ -2706,6 +2708,7 @@
"settings.admin.web.sougouSearchApiSk.label": "Sougou Search API SK",
"settings.admin.web.tavilyApiKey.label": "Tavily API Key",
"settings.admin.web.tavilyExtractDepth.label": "Tavily Extract Depth",
"settings.admin.web.tavilySearchDepth.label": "Tavily Search Depth",
"settings.admin.web.timeout.description": "Maximum time to wait while loading web content.",
"settings.admin.web.timeout.label": "Timeout",
"settings.admin.web.title": "Web Search",
@ -3319,6 +3322,7 @@
"Type Hugging Face Resolve (Download) URL": "",
"Type your answer": "",
"Uh-oh! There was an issue with the response.": "",
"Ultra-fast": "",
"Unarchive": "",
"Unarchive Chat": "",
"Unassigned": "",