mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-13 12:55:19 +00:00
feat/enh: perplexity search support
This commit is contained in:
parent
b38d59dee6
commit
7f411dd5cc
3 changed files with 93 additions and 0 deletions
64
backend/open_webui/retrieval/web/perplexity_search.py
Normal file
64
backend/open_webui/retrieval/web/perplexity_search.py
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import logging
|
||||||
|
from typing import Optional, Literal
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from open_webui.retrieval.web.main import SearchResult, get_filtered_results
|
||||||
|
from open_webui.env import SRC_LOG_LEVELS
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
log.setLevel(SRC_LOG_LEVELS["RAG"])
|
||||||
|
|
||||||
|
|
||||||
|
def search_perplexity_search(
|
||||||
|
api_key: str,
|
||||||
|
query: str,
|
||||||
|
count: int,
|
||||||
|
filter_list: Optional[list[str]] = None,
|
||||||
|
) -> list[SearchResult]:
|
||||||
|
"""Search using Perplexity API and return the results as a list of SearchResult objects.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
api_key (str): A Perplexity API key
|
||||||
|
query (str): The query to search for
|
||||||
|
count (int): Maximum number of results to return
|
||||||
|
filter_list (Optional[list[str]]): List of domains to filter results
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Handle PersistentConfig object
|
||||||
|
if hasattr(api_key, "__str__"):
|
||||||
|
api_key = str(api_key)
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = "https://api.perplexity.ai/search"
|
||||||
|
|
||||||
|
# Create payload for the API call
|
||||||
|
payload = {
|
||||||
|
"query": query,
|
||||||
|
"max_results": count,
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {api_key}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make the API request
|
||||||
|
response = requests.request("POST", url, json=payload, headers=headers)
|
||||||
|
# Parse the JSON response
|
||||||
|
json_response = response.json()
|
||||||
|
|
||||||
|
# Extract citations from the response
|
||||||
|
results = json_response.get("results", [])
|
||||||
|
|
||||||
|
return [
|
||||||
|
SearchResult(
|
||||||
|
link=result["url"], title=result["title"], snippet=result["snippet"]
|
||||||
|
)
|
||||||
|
for result in results
|
||||||
|
]
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
log.error(f"Error searching with Perplexity Search API: {e}")
|
||||||
|
return []
|
||||||
|
|
@ -46,6 +46,7 @@ from open_webui.retrieval.loaders.youtube import YoutubeLoader
|
||||||
from open_webui.retrieval.web.main import SearchResult
|
from open_webui.retrieval.web.main import SearchResult
|
||||||
from open_webui.retrieval.web.utils import get_web_loader
|
from open_webui.retrieval.web.utils import get_web_loader
|
||||||
from open_webui.retrieval.web.ollama import search_ollama_cloud
|
from open_webui.retrieval.web.ollama import search_ollama_cloud
|
||||||
|
from open_webui.retrieval.web.perplexity_search import search_perplexity_search
|
||||||
from open_webui.retrieval.web.brave import search_brave
|
from open_webui.retrieval.web.brave import search_brave
|
||||||
from open_webui.retrieval.web.kagi import search_kagi
|
from open_webui.retrieval.web.kagi import search_kagi
|
||||||
from open_webui.retrieval.web.mojeek import search_mojeek
|
from open_webui.retrieval.web.mojeek import search_mojeek
|
||||||
|
|
@ -1801,6 +1802,16 @@ def search_web(request: Request, engine: str, query: str) -> list[SearchResult]:
|
||||||
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
|
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
|
||||||
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
|
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
|
||||||
)
|
)
|
||||||
|
elif engine == "perplexity_search":
|
||||||
|
if request.app.state.config.PERPLEXITY_API_KEY:
|
||||||
|
return search_perplexity_search(
|
||||||
|
request.app.state.config.PERPLEXITY_API_KEY,
|
||||||
|
query,
|
||||||
|
request.app.state.config.WEB_SEARCH_RESULT_COUNT,
|
||||||
|
request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise Exception("No PERPLEXITY_API_KEY found in environment variables")
|
||||||
elif engine == "searxng":
|
elif engine == "searxng":
|
||||||
if request.app.state.config.SEARXNG_QUERY_URL:
|
if request.app.state.config.SEARXNG_QUERY_URL:
|
||||||
return search_searxng(
|
return search_searxng(
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
let webSearchEngines = [
|
let webSearchEngines = [
|
||||||
'ollama_cloud',
|
'ollama_cloud',
|
||||||
|
'perplexity_search',
|
||||||
'searxng',
|
'searxng',
|
||||||
'yacy',
|
'yacy',
|
||||||
'google_pse',
|
'google_pse',
|
||||||
|
|
@ -148,6 +149,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if webConfig.WEB_SEARCH_ENGINE === 'perplexity_search'}
|
||||||
|
<div class="mb-2.5 flex w-full flex-col">
|
||||||
|
<div>
|
||||||
|
<div class=" self-center text-xs font-medium mb-1">
|
||||||
|
{$i18n.t('Perplexity API Key')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1">
|
||||||
|
<SensitiveInput
|
||||||
|
placeholder={$i18n.t('Enter Perplexity API Key')}
|
||||||
|
bind:value={webConfig.PERPLEXITY_API_KEY}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{:else if webConfig.WEB_SEARCH_ENGINE === 'searxng'}
|
{:else if webConfig.WEB_SEARCH_ENGINE === 'searxng'}
|
||||||
<div class="mb-2.5 flex w-full flex-col">
|
<div class="mb-2.5 flex w-full flex-col">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue