1
0

perplexity.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import logging
  2. from typing import Optional, Literal
  3. import requests
  4. from open_webui.retrieval.web.main import SearchResult, get_filtered_results
  5. from open_webui.env import SRC_LOG_LEVELS
  6. MODELS = Literal[
  7. "sonar",
  8. "sonar-pro",
  9. "sonar-reasoning",
  10. "sonar-reasoning-pro",
  11. "sonar-deep-research",
  12. ]
  13. SEARCH_CONTEXT_USAGE_LEVELS = Literal["low", "medium", "high"]
  14. log = logging.getLogger(__name__)
  15. log.setLevel(SRC_LOG_LEVELS["RAG"])
  16. def search_perplexity(
  17. api_key: str,
  18. query: str,
  19. count: int,
  20. filter_list: Optional[list[str]] = None,
  21. model: MODELS = "sonar",
  22. search_context_usage: SEARCH_CONTEXT_USAGE_LEVELS = "medium",
  23. ) -> list[SearchResult]:
  24. """Search using Perplexity API and return the results as a list of SearchResult objects.
  25. Args:
  26. api_key (str): A Perplexity API key
  27. query (str): The query to search for
  28. count (int): Maximum number of results to return
  29. filter_list (Optional[list[str]]): List of domains to filter results
  30. model (str): The Perplexity model to use (sonar, sonar-pro)
  31. search_context_usage (str): Search context usage level (low, medium, high)
  32. """
  33. # Handle PersistentConfig object
  34. if hasattr(api_key, "__str__"):
  35. api_key = str(api_key)
  36. try:
  37. url = "https://api.perplexity.ai/chat/completions"
  38. # Create payload for the API call
  39. payload = {
  40. "model": model,
  41. "messages": [
  42. {
  43. "role": "system",
  44. "content": "You are a search assistant. Provide factual information with citations.",
  45. },
  46. {"role": "user", "content": query},
  47. ],
  48. "temperature": 0.2, # Lower temperature for more factual responses
  49. "stream": False,
  50. "web_search_options": {
  51. "search_context_usage": search_context_usage,
  52. },
  53. }
  54. headers = {
  55. "Authorization": f"Bearer {api_key}",
  56. "Content-Type": "application/json",
  57. }
  58. # Make the API request
  59. response = requests.request("POST", url, json=payload, headers=headers)
  60. # Parse the JSON response
  61. json_response = response.json()
  62. # Extract citations from the response
  63. citations = json_response.get("citations", [])
  64. # Create search results from citations
  65. results = []
  66. for i, citation in enumerate(citations[:count]):
  67. # Extract content from the response to use as snippet
  68. content = ""
  69. if "choices" in json_response and json_response["choices"]:
  70. if i == 0:
  71. content = json_response["choices"][0]["message"]["content"]
  72. result = {"link": citation, "title": f"Source {i+1}", "snippet": content}
  73. results.append(result)
  74. if filter_list:
  75. results = get_filtered_results(results, filter_list)
  76. return [
  77. SearchResult(
  78. link=result["link"], title=result["title"], snippet=result["snippet"]
  79. )
  80. for result in results[:count]
  81. ]
  82. except Exception as e:
  83. log.error(f"Error searching with Perplexity API: {e}")
  84. return []