
    dhx?                         S r SSKrSSKJrJrJrJr  SSKrSSKrSSK	J
r
  SSKJrJrJrJrJr  S\4S jr " S S	\5      r " S
 S\5      rg)aa  Utility for using SearxNG meta search API.

SearxNG is a privacy-friendly free metasearch engine that aggregates results from
`multiple search engines
<https://docs.searxng.org/admin/engines/configured_engines.html>`_ and databases and
supports the `OpenSearch
<https://github.com/dewitt/opensearch/blob/master/opensearch-1-1-draft-6.md>`_
specification.

More details on the installation instructions `here. <../../integrations/searx.html>`_

For the search API refer to https://docs.searxng.org/dev/search_api.html

Quick Start
-----------


In order to use this utility you need to provide the searx host. This can be done
by passing the named parameter :attr:`searx_host <SearxSearchWrapper.searx_host>`
or exporting the environment variable SEARX_HOST.
Note: this is the only required parameter.

Then create a searx search instance like this:

    .. code-block:: python

        from langchain_community.utilities import SearxSearchWrapper

        # when the host starts with `http` SSL is disabled and the connection
        # is assumed to be on a private network
        searx_host='http://self.hosted'

        search = SearxSearchWrapper(searx_host=searx_host)


You can now use the ``search`` instance to query the searx API.

Searching
---------

Use the :meth:`run() <SearxSearchWrapper.run>` and
:meth:`results() <SearxSearchWrapper.results>` methods to query the searx API.
Other methods are available for convenience.

:class:`SearxResults` is a convenience wrapper around the raw json result.

Example usage of the ``run`` method to make a search:

    .. code-block:: python

        s.run(query="what is the best search engine?")

Engine Parameters
-----------------

You can pass any `accepted searx search API
<https://docs.searxng.org/dev/search_api.html>`_ parameters to the
:py:class:`SearxSearchWrapper` instance.

In the following example we are using the
:attr:`engines <SearxSearchWrapper.engines>` and the ``language`` parameters:

    .. code-block:: python

        # assuming the searx host is set as above or exported as an env variable
        s = SearxSearchWrapper(engines=['google', 'bing'],
                            language='es')

Search Tips
-----------

Searx offers a special
`search syntax <https://docs.searxng.org/user/index.html#search-syntax>`_
that can also be used instead of passing engine parameters.

For example the following query:

    .. code-block:: python

        s = SearxSearchWrapper("langchain library", engines=['github'])

        # can also be written as:
        s = SearxSearchWrapper("langchain library !github")
        # 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
<https://docs.searxng.org/admin/engines/configured_engines.html>`_ and
`SearxNG Search Syntax <https://docs.searxng.org/user/index.html#id1>`_
for more details.

Notes
-----
This wrapper is based on the SearxNG fork https://github.com/searxng/searxng which is
better maintained than the original Searx project and offers more features.

Public searxNG instances often use a rate limiter for API usage, so you might want to
use a self hosted instance and disable the rate limiter.

If you are self-hosting an instance you can customize the rate limiter for your
own network as described
`here <https://docs.searxng.org/src/searx.botdetection.html#limiter-src>`_.


For a list of public SearxNG instances see https://searx.space/
    N)AnyDictListOptional)get_from_dict_or_env)	BaseModel
ConfigDictFieldPrivateAttrmodel_validatorreturnc                      SSS.$ )Nenjson)languageformat r       b/var/www/html/shao/venv/lib/python3.13/site-packages/langchain_community/utilities/searx_search.py_get_default_paramsr      s    //r   c                      ^  \ rS rSr% SrSr\\S'   S\4U 4S jjrS\4S jr	\
S\4S	 j5       r\
S\4S
 j5       rSrU =r$ )SearxResults   z,Dict like wrapper around search api results. _datadatac                 \   > [         R                  " U5      n[        TU ]  U5        X l        g)zATake a raw result from Searx and make it into a dict like object.N)r   loadssuper__init____dict__)selfr   	json_data	__class__s      r   r    SearxResults.__init__   s#    JJt$	#r   r   c                     U R                   $ )z$Text representation of searx result.)r   r"   s    r   __str__SearxResults.__str__   s    zzr   c                 $    U R                  S5      $ )z7Silence mypy for accessing this field.

:meta private:
resultsgetr'   s    r   r+   SearxResults.results   s     xx	""r   c                 $    U R                  S5      $ )z#Helper accessor on the json result.answersr,   r'   s    r   r0   SearxResults.answers   s     xx	""r   )r!   )__name__
__module____qualname____firstlineno____doc__r   str__annotations__r    r(   propertyr   r+   r0   __static_attributes____classcell__)r$   s   @r   r   r      s]    6E3OS   # # # # # #r   r   c                   X   \ rS rSr% Sr\" 5       r\\S'   Sr	\
\S'   Sr\\S'   \" \S9r\\S	'   S
r\\   \S'   / r\\\
      \S'   / r\\\
      \S'   Sr\\
   \S'   Sr\\S'   S
r\\   \S'   \" SS9\S\S\4S j5       5       r\" SS9r S	\S\4S jr!S	\S\4S jr"   S#S\
S\\\
      S\\\
      S\\
   S\S\
4S jjr#  S$S\
S\\\
      S\\
   S\S\
4
S jjr$   S#S\
S\S\\\
      S\\\
      S\\
   S\S\\   4S  jjr%  S$S\
S\S\\\
      S\\
   S\S\\   4S! jjr&S"r'g
)%SearxSearchWrapper   a  Wrapper for Searx API.

To use you need to provide the searx host by passing the named parameter
``searx_host`` or exporting the environment variable ``SEARX_HOST``.

In some situations you might want to disable SSL verification, for example
if you are running searx locally. You can do this by passing the named parameter
``unsecure``. You can also pass the host url scheme as ``http`` to disable SSL.

Example:
    .. code-block:: python

        from langchain_community.utilities import SearxSearchWrapper
        searx = SearxSearchWrapper(searx_host="http://localhost:8888")

Example with SSL disabled:
    .. code-block:: python

        from langchain_community.utilities import SearxSearchWrapper
        # note the unsecure parameter is not needed if you pass the url scheme as
        # http
        searx = SearxSearchWrapper(searx_host="http://localhost:8888",
                                                unsecure=True)


_resultr   
searx_hostFunsecure)default_factoryparamsNheadersengines
categoriesquery_suffix
   k
aiosessionbefore)modevaluesr   c                    UR                  S0 5      n[        5       n0 UEUEUS'   UR                  S5      nU(       a  SR                  U5      US   S'   UR                  S5      nU(       a  SR                  U5      US   S'   [        USS5      nUR	                  S5      (       d  [        SU S	35        S
U-   nOUR	                  S5      (       a  SUS'   XaS'   U$ )z?Validate that custom searx params are merged with default ones.rC   rE   ,rF   r@   
SEARX_HOSThttpzRWarning: missing the url scheme on host                 ! assuming secure https:// zhttps://zhttp://TrA   )r-   r   joinr   
startswithprint)clsrM   user_paramsdefaultrE   rF   r@   s          r   validate_params"SearxSearchWrapper.validate_params   s     jj2.%'5g55x**Y'*-((7*;F8Y'ZZ-
-0XXj-AF8\*)&,M
$$V,,++5,a9 $j0J""9--!%F:)|r   forbid)extrac                     [         R                  " U R                  U R                  UU R                  (       + S9nUR
                  (       d  [        SUR                  5      e[        UR                  5      nX0l	        U$ )zActual request to searx API.rD   rC   verifySearx API returned an error: )
requestsr-   r@   rD   rA   ok
ValueErrortextr   r?   )r"   rC   
raw_resultress       r   _searx_api_query#SearxSearchWrapper._searx_api_query   s^    \\OOLL}}$	

 }}<jooNN:??+
r   c                   #    U R                   (       d  [        R                  " 5        IS h  vN nU R                  US.nU R                  (       a  SUS'   UR
                  " U R                  40 UD6 IS h  vN nUR                  (       d  [        SUR                  5      e[        UR                  5       I S h  vN 5      nXPl        S S S 5      IS h  vN   S S S 5      IS h  vN   W$ U R                   R                  U R                  U R                  UU R                  (       + S9 IS h  vN nUR                  (       d  [        SUR                  5      e[        UR                  5       I S h  vN 5      nXPl        S S S 5      IS h  vN   U$  GNh GN  N N! , IS h  vN  (       d  f       N= f N! , IS h  vN  (       d  f       W$ = f N Nc NK! , IS h  vN  (       d  f       W$ = f7f)N)rD   rC   Fsslr`   r^   )rJ   aiohttpClientSessionrD   rA   r-   r@   rb   rc   rd   r   r?   )r"   rC   sessionkwargsresponseresults         r   _asearx_api_query$SearxSearchWrapper._asearx_api_query	  sw    ,,..'#||$  ==$)F5M";;tA&AAX#;;()H(--XX)*?@F#)L	 BA /.0  **==(	 +  
 {{$%DhmmTT%HMMO&;<%  1 / B +@ BAAA /..0  '<   s   +G7FG7AF;8F9F;<A F<F=FF;FF;G7&F9'A	G70G1G74A G4G
5GG7GG7F;FF;F6	%F(&F6	2F;9G7;GGG	G7GG7G4"G%#G4/G7queryrn   c           	      J   SU0n0 U R                   EUEUEnU R                  (       a3  [        U R                  5      S:  a  US==   SU R                  -   -  ss'   [        U[        5      (       a  [        U5      S:  a  US==   SU-   -  ss'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   U R                  U5      n[        UR                  5      S:  a  UR                  S   n	U	$ [        UR                  5      S:  aI  SR                  UR                  SU R                    V
s/ sH  oR                  S	S
5      PM     sn
5      n	U	$ Sn	U	$ s  sn
f )a  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.
    categories: List of categories to use for the query.
    **kwargs: extra parameters to pass to the searx API.

Returns:
    str: The result of the query.

Raises:
    ValueError: If an error occurred with the query.


Example:
    This will make a query to the qwant engine:

    .. code-block:: python

        from langchain_community.utilities import SearxSearchWrapper
        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")
qr   rR   rO   rE   rF   

Ncontentr   No good search result found)rC   rG   len
isinstancer7   listrS   rg   r0   r+   rI   r-   )r"   rs   rE   rF   rG   rn   _paramsrC   rf   toretrs              r   runSearxSearchWrapper.run%  sy   P 
 6DKK575f5T%6%6!7!!;3K3!2!222KlC((S->-B3K3--Kgt$$W)9 # 1F9j$''C
Oa,?#&88J#7F< ##F+s{{aKKNE  !KKs{{8TVV?T U?T!y"!5?T UVE  2E	 !Vs   9F c           	        #    SU0n0 U R                   EUEUEnU R                  (       a3  [        U R                  5      S:  a  US==   SU R                  -   -  ss'   [        U[        5      (       a  [        U5      S:  a  US==   SU-   -  ss'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   U R                  U5      I Sh  vN n[        UR                  5      S:  a  UR                  S   nU$ [        UR                  5      S:  aI  SR                  UR                  SU R                    V	s/ sH  oR                  SS	5      PM     sn	5      nU$ S
nU$  Ns  sn	f 7f)z Asynchronously version of `run`.ru   r   rR   rO   rE   Nrv   rw   r   rx   )rC   rG   ry   rz   r7   r{   rS   rq   r0   r+   rI   r-   )
r"   rs   rE   rG   rn   r|   rC   rf   r}   r~   s
             r   arunSearxSearchWrapper.arunj  sX     
 6DKK575f5T%6%6!7!!;3K3!2!222KlC((S->-B3K3--Kgt$$W)9 # 1F9**622s{{aKKNE  !KKs{{8TVV?T U?T!y"!5?T UVE  2E 3 !Vs%   CE9E2A-E9E4%E94E9num_resultsc           	         SU0n0 U R                   EUEUEnU R                  (       a3  [        U R                  5      S:  a  US==   SU R                  -   -  ss'   [        U[        5      (       a  [        U5      S:  a  US==   SU-   -  ss'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   U R                  U5      R                  SU n	[        U	5      S:X  a  SS	0/$ U	 V
s/ sH'  n
U
R                  S
S5      U
S   U
S   U
S   U
S   S.PM)     sn
$ s  sn
f )a  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.
    categories: List of categories to use for the query.
    **kwargs: extra parameters to pass to the searx API.

Returns:
    Dict with the following keys:
    {
        snippet:  The description of the result.
        title:  The title of the result.
        link: The link to the result.
        engines: The engines used for the result.
        category: Searx category of the result.
    }

ru   r   rR   rO   rE   rF   NResultNo good Search Result was foundrw   r   titleurlcategorysnippetr   linkrE   r   )
rC   rG   ry   rz   r7   r{   rS   rg   r+   r-   )r"   rs   r   rE   rF   rG   rn   r|   rC   r+   rp   s              r   r+   SearxSearchWrapper.results  sq   > 
 6DKK575f5T%6%6!7!!;3K3!2!222KlC((S->-B3K3--Kgt$$W)9 # 1F9j$''C
Oa,?#&88J#7F< ''/77Ew<1@ABB "	
 " "::i4u!),":. "	
 		
 	
s   5-E%c           	        #    SU0n0 U R                   EUEUEnU R                  (       a3  [        U R                  5      S:  a  US==   SU R                  -   -  ss'   [        U[        5      (       a  [        U5      S:  a  US==   SU-   -  ss'   [        U[
        5      (       a#  [        U5      S:  a  SR                  U5      US'   U R                  U5      I Sh  vN R                  SU n[        U5      S:X  a  SS0/$ U V	s/ sH'  n	U	R                  S	S
5      U	S   U	S   U	S   U	S   S.PM)     sn	$  NYs  sn	f 7f)zTAsynchronously query with json results.

Uses aiohttp. See `results` for more info.
ru   r   rR   rO   rE   Nr   r   rw   r   r   r   r   r   )
rC   rG   ry   rz   r7   r{   rS   rq   r+   r-   )
r"   rs   r   rE   rG   rn   r|   rC   r+   rp   s
             r   aresultsSearxSearchWrapper.aresults  sQ     
 6DKK575f5T%6%6!7!!;3K3!2!222KlC((S->-B3K3--Kgt$$W)9 # 1F9//77@@+Nw<1@ABB "	
 " "::i4u!),":. "	
 		
	 8	
s$   CD>D7)D>-D94D>9D>)r?   )NNr   )Nr   )(r2   r3   r4   r5   r6   r   r?   r   r8   r@   r7   rA   boolr
   r   rC   dictrD   r   rE   r   rF   rG   rI   intrJ   r   r   classmethodr   rY   r	   model_configrg   rq   r   r   r+   r   r:   r   r   r   r=   r=      ss   6 (MG\)JHd)<=FD="GXd^"#%GXd3i %&(Jc#("$L(3-$AsK $J$(#T c   $6 Lt  d | > (,*.&(CC $s)$C T#Y'	C
 smC C 
CP (,&(	!! $s)$! sm	!
 ! 
!N (,*.&(7
7
 7
 $s)$	7

 T#Y'7
 sm7
 7
 
d7
z (,&($
$
 $
 $s)$	$

 sm$
 $
 
d$
 $
r   r=   )r6   r   typingr   r   r   r   rk   ra   langchain_core.utilsr   pydanticr   r	   r
   r   r   r   r   r   r=   r   r   r   <module>r      sP   B  , ,   5 0T 0#4 #:x
 x
r   