Coverage for open_webui/retrieval/web/perplexity.py: 23%
31 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 05:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 05:07 +0000
1import logging
2from typing import Literal, Optional
4import requests
5from open_webui.env import VERSION
6from open_webui.retrieval.web.main import SearchResult, get_filtered_results
8MODELS = Literal[
9 'sonar',
10 'sonar-pro',
11 'sonar-reasoning',
12 'sonar-reasoning-pro',
13 'sonar-deep-research',
14]
15SEARCH_CONTEXT_USAGE_LEVELS = Literal['low', 'medium', 'high']
18log = logging.getLogger(__name__)
21def search_perplexity(
22 api_key: str,
23 query: str,
24 count: int,
25 filter_list: Optional[list[str]] = None,
26 model: MODELS = 'sonar',
27 search_context_usage: SEARCH_CONTEXT_USAGE_LEVELS = 'medium',
28) -> list[SearchResult]:
29 """Search using Perplexity API and return the results as a list of SearchResult objects.
31 Args:
32 api_key (str): A Perplexity API key
33 query (str): The query to search for
34 count (int): Maximum number of results to return
35 filter_list (Optional[list[str]]): List of domains to filter results
36 model (str): The Perplexity model to use (sonar, sonar-pro)
37 search_context_usage (str): Search context usage level (low, medium, high)
39 """
41 api_key = str(api_key)
43 try:
44 url = 'https://api.perplexity.ai/chat/completions'
46 # Create payload for the API call
47 payload = {
48 'model': model,
49 'messages': [
50 {
51 'role': 'system',
52 'content': 'You are a search assistant. Provide factual information with citations.',
53 },
54 {'role': 'user', 'content': query},
55 ],
56 'temperature': 0.2, # Lower temperature for more factual responses
57 'stream': False,
58 'web_search_options': {
59 'search_context_usage': search_context_usage,
60 },
61 }
63 headers = {
64 'Authorization': f'Bearer {api_key}',
65 'Content-Type': 'application/json',
66 'X-Pplx-Integration': f'open-webui/{VERSION}',
67 }
69 # Make the API request
70 response = requests.request('POST', url, json=payload, headers=headers)
72 # Parse the JSON response
73 json_response = response.json()
75 # Extract citations from the response
76 citations = json_response.get('citations', [])
78 # Create search results from citations
79 results = []
80 for i, citation in enumerate(citations[:count]):
81 # Extract content from the response to use as snippet
82 content = ''
83 if 'choices' in json_response and json_response['choices']:
84 if i == 0:
85 content = json_response['choices'][0]['message']['content']
87 result = {'link': citation, 'title': f'Source {i + 1}', 'snippet': content}
88 results.append(result)
90 if filter_list:
91 results = get_filtered_results(results, filter_list)
93 return [
94 SearchResult(link=result['link'], title=result['title'], snippet=result['snippet'])
95 for result in results[:count]
96 ]
98 except Exception as e:
99 log.error(f'Error searching with Perplexity API: {e}')
100 return []