From 889aada1f03da065b3778830bc66d74686bdf9ec Mon Sep 17 00:00:00 2001 From: blob42 Date: Thu, 23 Feb 2023 16:02:39 +0100 Subject: [PATCH] searx: add `query_suffix` parameter - allows to build tools and dynamically inject extra searxh suffix in the query example: search.run("python library", query_suffix="site:github.com") resulting query: "python library site:github.com" --- langchain/utilities/searx_search.py | 52 ++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/langchain/utilities/searx_search.py b/langchain/utilities/searx_search.py index e0814b2f..4ed6ef1b 100644 --- a/langchain/utilities/searx_search.py +++ b/langchain/utilities/searx_search.py @@ -78,6 +78,28 @@ For example the following query: # or even: s = SearxSearchWrapper("langchain library !gh") + +In some situations you might want to pass an extra string to the search query. +For example when the `run()` method is called by an agent. The search suffix can +also be used as a way to pass extra parameters to searx or the underlying search +engines. + + .. code-block:: python + + # select the github engine and pass the search suffix + s = SearchWrapper("langchain library", query_suffix="!gh") + + + s = SearchWrapper("langchain library") + # select github the conventional google search syntax + s.run("large language models", query_suffix="site:github.com") + + +*NOTE*: A search suffix can be defined on both the instance and the method level. +The resulting query will be the concatenation of the two with the former taking +precedence. + + See `SearxNG Configured Engines `_ and `SearxNG Search Syntax `_ @@ -128,12 +150,15 @@ class SearxResults(dict): @property def results(self) -> Any: - """Silence mypy for accessing this field.""" + """Silence mypy for accessing this field. + + :meta private: + """ return self.get("results") @property def answers(self) -> Any: - """Accessor helper on the json result.""" + """Helper accessor on the json result.""" return self.get("answers") @@ -171,6 +196,7 @@ class SearxSearchWrapper(BaseModel): params: dict = Field(default_factory=_get_default_params) headers: Optional[dict] = None engines: Optional[List[str]] = [] + query_suffix: Optional[str] = "" k: int = 10 @validator("unsecure") @@ -232,13 +258,15 @@ class SearxSearchWrapper(BaseModel): self._result = res return res - def run(self, query: str, engines: List[str] = [], **kwargs: Any) -> str: + def run(self, query: str, engines: List[str] = [], + query_suffix: str = "", **kwargs: Any) -> str: """Run query through Searx API and parse results. You can pass any other params to the searx query API. Args: query: The query to search for. + query_suffix: Extra suffix appended to the query. engines: List of engines to use for the query. **kwargs: extra parameters to pass to the searx API. @@ -251,12 +279,21 @@ class SearxSearchWrapper(BaseModel): searx = SearxSearchWrapper(searx_host="http://my.searx.host") searx.run("what is the weather in France ?", engine="qwant") + # the same result can be achieved using the `!` syntax of searx + # to select the engine using `query_suffix` + searx.run("what is the weather in France ?", query_suffix="!qwant") """ _params = { "q": query, } params = {**self.params, **_params, **kwargs} + if len(self.query_suffix) > 0: + params["q"] += " " + self.query_suffix + + if isinstance(query_suffix, str) and len(query_suffix) > 0: + params["q"] += " " + query_suffix + if isinstance(engines, list) and len(engines) > 0: params["engines"] = ",".join(engines) @@ -274,13 +311,16 @@ class SearxSearchWrapper(BaseModel): return toret def results( - self, query: str, num_results: int, engines: List[str] = [], **kwargs: Any + self, query: str, num_results: int, engines: List[str] = [], + query_suffix: str = "", **kwargs: Any ) -> List[Dict]: """Run query through Searx API and returns the results with metadata. Args: query: The query to search for. + query_suffix: Extra suffix appended to the query. + num_results: Limit the number of results to return. engines: List of engines to use for the query. @@ -308,6 +348,10 @@ class SearxSearchWrapper(BaseModel): "q": query, } params = {**self.params, **_params, **kwargs} + if len(self.query_suffix) > 0: + params["q"] += " " + self.query_suffix + if isinstance(query_suffix, str) and len(query_suffix) > 0: + params["q"] += " " + query_suffix if isinstance(engines, list) and len(engines) > 0: params["engines"] = ",".join(engines) results = self._searx_api_query(params).results[:num_results]