From 83f94755846c21fb8ec9f27d85bc40b3c2ee9771 Mon Sep 17 00:00:00 2001 From: Yash-1511 Date: Tue, 11 Jun 2024 19:49:08 +0530 Subject: [PATCH] feat: add DuckDuckGo search functionality using duckduckgo_search library --- backend/apps/rag/main.py | 3 ++ backend/apps/rag/search/duckduckgo.py | 46 +++++++++++++++++++ .../admin/Settings/WebSearch.svelte | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 backend/apps/rag/search/duckduckgo.py diff --git a/backend/apps/rag/main.py b/backend/apps/rag/main.py index 99730ad7c..94df7f531 100644 --- a/backend/apps/rag/main.py +++ b/backend/apps/rag/main.py @@ -70,6 +70,7 @@ from apps.rag.search.searxng import search_searxng from apps.rag.search.serper import search_serper from apps.rag.search.serpstack import search_serpstack from apps.rag.search.serply import search_serply +from apps.rag.search.duckduckgo import search_duckduckgo from utils.misc import ( calculate_sha256, @@ -820,6 +821,8 @@ def search_web(engine: str, query: str) -> list[SearchResult]: ) else: raise Exception("No SERPLY_API_KEY found in environment variables") + elif engine == "duckduckgo": + return search_duckduckgo(query, app.state.config.RAG_WEB_SEARCH_RESULT_COUNT) else: raise Exception("No search engine API key found in environment variables") diff --git a/backend/apps/rag/search/duckduckgo.py b/backend/apps/rag/search/duckduckgo.py new file mode 100644 index 000000000..188ae2bea --- /dev/null +++ b/backend/apps/rag/search/duckduckgo.py @@ -0,0 +1,46 @@ +import logging + +from apps.rag.search.main import SearchResult +from duckduckgo_search import DDGS +from config import SRC_LOG_LEVELS + +log = logging.getLogger(__name__) +log.setLevel(SRC_LOG_LEVELS["RAG"]) + + +def search_duckduckgo(query: str, count: int) -> list[SearchResult]: + """ + Search using DuckDuckGo's Search API and return the results as a list of SearchResult objects. + Args: + query (str): The query to search for + count (int): The number of results to return + + Returns: + List[SearchResult]: A list of search results + """ + # Use the DDGS context manager to create a DDGS object + with DDGS() as ddgs: + # Use the ddgs.text() method to perform the search + ddgs_gen = ddgs.text( + query, safesearch="moderate", max_results=count, backend="api" + ) + # Check if there are search results + if ddgs_gen: + # Convert the search results into a list + search_results = [r for r in ddgs_gen] + + # Create an empty list to store the SearchResult objects + results = [] + # Iterate over each search result + for result in search_results: + # Create a SearchResult object and append it to the results list + results.append( + SearchResult( + link=result["href"], + title=result.get("title"), + snippet=result.get("body"), + ) + ) + print(results) + # Return the list of search results + return results diff --git a/src/lib/components/admin/Settings/WebSearch.svelte b/src/lib/components/admin/Settings/WebSearch.svelte index eeafdce15..b5dc8a3b9 100644 --- a/src/lib/components/admin/Settings/WebSearch.svelte +++ b/src/lib/components/admin/Settings/WebSearch.svelte @@ -11,7 +11,7 @@ export let saveHandler: Function; let webConfig = null; - let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper', 'serply']; + let webSearchEngines = ['searxng', 'google_pse', 'brave', 'serpstack', 'serper', 'serply', 'duckduckgo']; let youtubeLanguage = 'en'; let youtubeTranslation = null;