feat: add duckduckgo search component (#3798)

* 🔧 (pyproject.toml): add duckduckgo-search dependency to the project
 (DuckDuckGoSearchRun.py): introduce DuckDuckGoSearchComponent for performing web searches using DuckDuckGo search engine
 (DuckDuckGo.jsx): add SVG icon for DuckDuckGo
 (index.tsx): create DuckDuckGoIcon component for displaying DuckDuckGo icon
🔧 (styleUtils.ts): import DuckDuckGoIcon for nodeIconsLucide in styleUtils

* 📝 (DuckDuckGoSearchRun.py): remove unnecessary whitespace to improve code readability and consistency

*  (DuckDuckGoSearchRun.py): Add retry logic to DuckDuckGo search component for rate-limited requests
📝 (DuckDuckGoSearchRun.py): Update component description to reflect the addition of retry logic
📝 (DuckDuckGoSearchRun.py): Add new inputs for max_retries and initial_delay to configure retry behavior
📝 (DuckDuckGoSearchRun.py): Update search_response method to use search_with_retry method with retry logic
📝 (DuckDuckGoSearchRun.py): Update format_results method to handle formatted results
📝 (DuckDuckGoSearchRun.py): Add search_with_retry method to handle search with retry logic
📝 (DuckDuckGoSearchRun.py): Update search_response method to use search_with_retry method
📝 (DuckDuckGoSearchRun.py): Update search_response method to set status messages
📝 (DuckDuckGoSearchRun.py): Handle exceptions and set appropriate status messages in search_response method
 (duckduckgo.spec.ts): Add integration test for DuckDuckGo search component in frontend

* 📝 (DuckDuckGoSearchRun.py): add newline at the end of the file to follow best practices and avoid potential issues with some tools that expect it

* [autofix.ci] apply automated fixes

* updating duckudckgo

* [autofix.ci] apply automated fixes

*  (DuckDuckGoSearchRun.py): Refactor DuckDuckGoSearchComponent to use pydantic BaseModel for schema definition and improve code structure for better readability and maintainability. Add support for result limiting in search functionality.

* 🔧 (DuckDuckGoSearchRun.py): Remove unnecessary import and update status message for DuckDuckGo Search Tool to improve clarity

* [autofix.ci] apply automated fixes

*  (duckduckgo.spec.ts): update test selectors for duckduckgo search component to match changes in the frontend code and improve test reliability

* 🐛 (linkComponent.spec.ts): fix an issue where the key combination for selecting all text was not working correctly on Mac devices. Updated the key combination to use the correct modifier key based on the user's operating system.

* 📝 (frontend): mark is-unicode-supported package as extraneous in package-lock.json

* rollback lock file

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2024-09-17 16:39:17 -03:00 committed by GitHub
commit 8c8be151e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 253 additions and 2 deletions

View file

@ -0,0 +1,69 @@
from typing import Dict, Any, List
from pydantic import BaseModel, Field
from langchain_community.tools import DuckDuckGoSearchRun
from langflow.base.langchain_utilities.model import LCToolComponent
from langflow.inputs import MessageTextInput, IntInput
from langflow.schema import Data
from langflow.field_typing import Tool
from langchain.tools import StructuredTool
class DuckDuckGoSearchComponent(LCToolComponent):
display_name: str = "DuckDuckGo Search"
description: str = "Perform web searches using the DuckDuckGo search engine with result limiting"
name = "DuckDuckGoSearch"
documentation: str = "https://python.langchain.com/docs/integrations/tools/ddg"
icon: str = "DuckDuckGo"
inputs = [
MessageTextInput(
name="input_value",
display_name="Search Query",
required=True,
),
IntInput(name="max_results", display_name="Max Results", value=5, advanced=True),
IntInput(name="max_snippet_length", display_name="Max Snippet Length", value=100, advanced=True),
]
class DuckDuckGoSearchSchema(BaseModel):
query: str = Field(..., description="The search query")
max_results: int = Field(5, description="Maximum number of results to return")
max_snippet_length: int = Field(100, description="Maximum length of each result snippet")
def _build_wrapper(self):
return DuckDuckGoSearchRun()
def build_tool(self) -> Tool:
wrapper = self._build_wrapper()
def search_func(query: str, max_results: int = 5, max_snippet_length: int = 100) -> List[Dict[str, Any]]:
full_results = wrapper.run(f"{query} (site:*)")
result_list = full_results.split("\n")[:max_results]
limited_results = []
for result in result_list:
limited_result = {
"snippet": result[:max_snippet_length],
}
limited_results.append(limited_result)
return limited_results
tool = StructuredTool.from_function(
name="duckduckgo_search",
description="Search for recent results using DuckDuckGo with result limiting",
func=search_func,
args_schema=self.DuckDuckGoSearchSchema,
)
self.status = "DuckDuckGo Search Tool created"
return tool
def run_model(self) -> List[Data]:
tool = self.build_tool()
results = tool.run(
{
"query": self.input_value,
"max_results": self.max_results,
"max_snippet_length": self.max_snippet_length,
}
)
data_list = [Data(data=result, text=result.get("snippet", "")) for result in results]
self.status = data_list
return data_list