searx: add query_suffix parameter (#1259)

- 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`

Co-authored-by: blob42 <spike@w530>
This commit is contained in:
blob42 2023-02-24 00:00:40 +00:00 committed by GitHub
parent 9381005098
commit 5457d48416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -78,6 +78,28 @@ For example the following query:
# or even: # or even:
s = SearxSearchWrapper("langchain library !gh") 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 See `SearxNG Configured Engines
<https://docs.searxng.org/admin/engines/configured_engines.html>`_ and <https://docs.searxng.org/admin/engines/configured_engines.html>`_ and
`SearxNG Search Syntax <https://docs.searxng.org/user/index.html#id1>`_ `SearxNG Search Syntax <https://docs.searxng.org/user/index.html#id1>`_
@ -128,12 +150,15 @@ class SearxResults(dict):
@property @property
def results(self) -> Any: def results(self) -> Any:
"""Silence mypy for accessing this field.""" """Silence mypy for accessing this field.
:meta private:
"""
return self.get("results") return self.get("results")
@property @property
def answers(self) -> Any: def answers(self) -> Any:
"""Accessor helper on the json result.""" """Helper accessor on the json result."""
return self.get("answers") return self.get("answers")
@ -171,6 +196,7 @@ class SearxSearchWrapper(BaseModel):
params: dict = Field(default_factory=_get_default_params) params: dict = Field(default_factory=_get_default_params)
headers: Optional[dict] = None headers: Optional[dict] = None
engines: Optional[List[str]] = [] engines: Optional[List[str]] = []
query_suffix: Optional[str] = ""
k: int = 10 k: int = 10
@validator("unsecure") @validator("unsecure")
@ -232,13 +258,20 @@ class SearxSearchWrapper(BaseModel):
self._result = res self._result = res
return res return res
def run(self, query: str, engines: List[str] = [], **kwargs: Any) -> str: def run(
self,
query: str,
engines: Optional[List[str]] = None,
query_suffix: Optional[str] = "",
**kwargs: Any,
) -> str:
"""Run query through Searx API and parse results. """Run query through Searx API and parse results.
You can pass any other params to the searx query API. You can pass any other params to the searx query API.
Args: Args:
query: The query to search for. query: The query to search for.
query_suffix: Extra suffix appended to the query.
engines: List of engines to use for the query. engines: List of engines to use for the query.
**kwargs: extra parameters to pass to the searx API. **kwargs: extra parameters to pass to the searx API.
@ -251,12 +284,21 @@ class SearxSearchWrapper(BaseModel):
searx = SearxSearchWrapper(searx_host="http://my.searx.host") searx = SearxSearchWrapper(searx_host="http://my.searx.host")
searx.run("what is the weather in France ?", engine="qwant") 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 = { _params = {
"q": query, "q": query,
} }
params = {**self.params, **_params, **kwargs} params = {**self.params, **_params, **kwargs}
if self.query_suffix and 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: if isinstance(engines, list) and len(engines) > 0:
params["engines"] = ",".join(engines) params["engines"] = ",".join(engines)
@ -274,13 +316,20 @@ class SearxSearchWrapper(BaseModel):
return toret return toret
def results( def results(
self, query: str, num_results: int, engines: List[str] = [], **kwargs: Any self,
query: str,
num_results: int,
engines: Optional[List[str]] = None,
query_suffix: Optional[str] = "",
**kwargs: Any,
) -> List[Dict]: ) -> List[Dict]:
"""Run query through Searx API and returns the results with metadata. """Run query through Searx API and returns the results with metadata.
Args: Args:
query: The query to search for. query: The query to search for.
query_suffix: Extra suffix appended to the query.
num_results: Limit the number of results to return. num_results: Limit the number of results to return.
engines: List of engines to use for the query. engines: List of engines to use for the query.
@ -308,6 +357,10 @@ class SearxSearchWrapper(BaseModel):
"q": query, "q": query,
} }
params = {**self.params, **_params, **kwargs} params = {**self.params, **_params, **kwargs}
if self.query_suffix and 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: if isinstance(engines, list) and len(engines) > 0:
params["engines"] = ",".join(engines) params["engines"] = ",".join(engines)
results = self._searx_api_query(params).results[:num_results] results = self._searx_api_query(params).results[:num_results]