
    Ngx?                         d Z ddlZddlmZmZmZmZ ddlZddlZddl	m
Z
 ddlmZmZmZmZmZ defdZ G d d	e          Z G d
 de          ZdS )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                      dddS )Nenjson)languageformat r       f/var/www/html/ai-engine/env/lib/python3.11/site-packages/langchain_community/utilities/searx_search.py_get_default_paramsr      s    ///r   c                   |     e Zd ZU dZdZeed<   def fdZdefdZe	de
fd            Ze	de
fd	            Z xZS )
SearxResultsz,Dict like wrapper around search api results. _datadatac                     t          j        |          }t                                          |           | | _        dS )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   zSearxResults.__init__   s5    Jt$$	###r   r   c                     | j         S )z$Text representation of searx result.)r   r!   s    r   __str__zSearxResults.__str__   s
    zr   c                 ,    |                      d          S )zGSilence mypy for accessing this field.

        :meta private:
        resultsgetr%   s    r   r(   zSearxResults.results   s     xx	"""r   c                 ,    |                      d          S )z#Helper accessor on the json result.answersr)   r%   s    r   r,   zSearxResults.answers   s     xx	"""r   )__name__
__module____qualname____doc__r   str__annotations__r   r&   propertyr   r(   r,   __classcell__)r#   s   @r   r   r      s         66E3OOOS           # # # # X# # # # # X# # # # #r   r   c                      e Zd ZU dZ e            Zeed<   dZe	ed<   dZ
eed<    ee          Zeed<   d	Zee         ed
<   g Zeee	                  ed<   g Zeee	                  ed<   dZee	         ed<   dZeed<   d	Zee         ed<    ed          ededefd                        Z ed          ZdedefdZ dedefdZ!	 	 	 d!de	deee	                  deee	                  dee	         dede	fdZ"	 	 d"de	deee	                  dee	         dede	f
dZ#	 	 	 d!de	dedeee	                  deee	                  dee	         dedee         fdZ$	 	 d"de	dedeee	                  dee	         dedee         fd Z%d	S )#SearxSearchWrappera  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                    |                     di           }t                      }i |||d<   |                     d          }|rd                    |          |d         d<   |                     d          }|rd                    |          |d         d<   t          |dd          }|                    d          st          d| d	           d
|z   }n|                    d          rd|d<   ||d<   |S )z?Validate that custom searx params are merged with default ones.r;   r=   ,r>   r8   
SEARX_HOSThttpzRWarning: missing the url scheme on host                 ! assuming secure https:// zhttps://zhttp://Tr9   )r*   r   joinr   
startswithprint)clsrE   user_paramsdefaultr=   r>   r8   s          r   validate_paramsz"SearxSearchWrapper.validate_params   s,    jj2..%''5g55x**Y'' 	<*-((7*;*;F8Y'ZZ--
 	B-0XXj-A-AF8\*)&,MM
$$V,, 	&9+59 9 9   $j0JJ""9-- 	&!%F:)|r   forbid)extrac                     t          j        | j        | j        || j                   }|j        st          d|j                  t          |j                  }|| _	        |S )zActual request to searx API.r<   r;   verifySearx API returned an error: )
requestsr*   r8   r<   r9   ok
ValueErrortextr   r7   )r!   r;   
raw_resultress       r   _searx_api_queryz#SearxSearchWrapper._searx_api_query   sh    \OL}$	
 
 

 } 	O<joNNN:?++
r   c                   K   | j         st          j                    4 d {V }| j        |d}| j        rd|d<    |j        | j        fi |4 d {V }|j        st          d|j	                  t          |	                                 d {V           }|| _        d d d           d {V  n# 1 d {V swxY w Y   d d d           d {V  n# 1 d {V swxY w Y   n| j                             | j        | j        || j                   4 d {V 	 }|j        st          d|j	                  t          |	                                 d {V           }|| _        d d d           d {V  n# 1 d {V swxY w Y   |S )N)r<   r;   FsslrW   rU   )rB   aiohttpClientSessionr<   r9   r*   r8   rY   rZ   r[   r   r7   )r!   r;   sessionkwargsresponseresults         r   _asearx_api_queryz$SearxSearchWrapper._asearx_api_query	  sD      	&,.. * * * * * * *'#|$    = *$)F5M&7;tAA&AA * * * * * * *X#; Y()H(-XXX)*?*?*?*?*?*?@@F#)DL	* * * * * * * * * * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * **=(	 +   	& 	& 	& 	& 	& 	& 	& 	&
 { U$%DhmTTT%HMMOO&;&;&;&;&;&;<<%	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& 	& sI   0CAB0C0
B:	:C=B:	>C
C CAE77
FFqueryrd   c                    d|i}i | j         ||}| j        r0t          | j                  dk    r|dxx         d| j        z   z  cc<   t          |t                    r&t          |          dk    r|dxx         d|z   z  cc<   t          |t
                    r+t          |          dk    rd                    |          |d<   t          |t
                    r+t          |          dk    rd                    |          |d<   |                     |          }t          |j                  dk    r|j        d         }	nLt          |j	                  dk    r2d                    d |j	        d	| j
                 D                       }	nd
}	|	S )ao  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   rJ   rG   r=   r>   

c                 :    g | ]}|                     d d          S contentr   r)   .0rs     r   
<listcomp>z*SearxSearchWrapper.run.<locals>.<listcomp>d  &     U U U!y"!5!5 U U Ur   NNo good search result found)r;   r?   len
isinstancer1   listrK   r^   r,   r(   rA   )
r!   rh   r=   r>   r?   rd   _paramsr;   r]   torets
             r   runzSearxSearchWrapper.run%  s   P 
 6DK575f5 	3T%6!7!7!!;!;3KKK3!222KKKlC(( 	.S->->-B-B3KKK3--KKKgt$$ 	2W)9)9 # 1 1F9j$'' 	8C
OOa,?,?#&88J#7#7F< ##F++s{aKNEE !!KK U Us{8TV8?T U U UVVEE1Er   c                   K   d|i}i | j         ||}| j        r0t          | j                  dk    r|dxx         d| j        z   z  cc<   t          |t                    r&t          |          dk    r|dxx         d|z   z  cc<   t          |t
                    r+t          |          dk    rd                    |          |d<   |                     |           d{V }t          |j                  dk    r|j        d         }nLt          |j	                  dk    r2d                    d |j	        d| j
                 D                       }nd	}|S )
z Asynchronously version of `run`.rj   r   rJ   rG   r=   Nrk   c                 :    g | ]}|                     d d          S rm   r)   ro   s     r   rr   z+SearxSearchWrapper.arun.<locals>.<listcomp>  rs   r   rt   )r;   r?   ru   rv   r1   rw   rK   rg   r,   r(   rA   )	r!   rh   r=   r?   rd   rx   r;   r]   ry   s	            r   arunzSearxSearchWrapper.arunj  sx      
 6DK575f5 	3T%6!7!7!!;!;3KKK3!222KKKlC(( 	.S->->-B-B3KKK3--KKKgt$$ 	2W)9)9 # 1 1F9**622222222s{aKNEE !!KK U Us{8TV8?T U U UVVEE1Er   num_resultsc                    d|i}i | j         ||}| j        r0t          | j                  dk    r|dxx         d| j        z   z  cc<   t          |t                    r&t          |          dk    r|dxx         d|z   z  cc<   t          |t
                    r+t          |          dk    rd                    |          |d<   t          |t
                    r+t          |          dk    rd                    |          |d<   |                     |          j        d|         }	t          |	          dk    rdd	igS d
 |	D             S )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.
            }

        rj   r   rJ   rG   r=   r>   NResultNo good Search Result was foundc                 v    g | ]6}|                     d d          |d         |d         |d         |d         d7S rn   r   titleurlr=   category)snippetr   linkr=   r   r)   rp   rf   s     r   rr   z.SearxSearchWrapper.results.<locals>.<listcomp>  `     	
 	
 	
  "::i44u!),":. 	
 	
 	
r   )	r;   r?   ru   rv   r1   rw   rK   r^   r(   )
r!   rh   r~   r=   r>   r?   rd   rx   r;   r(   s
             r   r(   zSearxSearchWrapper.results  sw   > 
 6DK575f5 	3T%6!7!7!!;!;3KKK3!222KKKlC(( 	.S->->-B-B3KKK3--KKKgt$$ 	2W)9)9 # 1 1F9j$'' 	8C
OOa,?,?#&88J#7#7F< ''//7Ew<<1@ABB	
 	
 "	
 	
 	
 		
r   c                 $  K   d|i}i | j         ||}| j        r0t          | j                  dk    r|dxx         d| j        z   z  cc<   t          |t                    r&t          |          dk    r|dxx         d|z   z  cc<   t          |t
                    r+t          |          dk    rd                    |          |d<   |                     |           d{V j        d|         }t          |          dk    rddigS d	 |D             S )
zdAsynchronously query with json results.

        Uses aiohttp. See `results` for more info.
        rj   r   rJ   rG   r=   Nr   r   c                 v    g | ]6}|                     d d          |d         |d         |d         |d         d7S r   r)   r   s     r   rr   z/SearxSearchWrapper.aresults.<locals>.<listcomp>  r   r   )	r;   r?   ru   rv   r1   rw   rK   rg   r(   )	r!   rh   r~   r=   r?   rd   rx   r;   r(   s	            r   aresultszSearxSearchWrapper.aresults  sU      
 6DK575f5 	3T%6!7!7!!;!;3KKK3!222KKKlC(( 	.S->->-B-B3KKK3--KKKgt$$ 	2W)9)9 # 1 1F9//77777777@+Nw<<1@ABB	
 	
 "	
 	
 	
 		
r   )NNr   )Nr   )&r-   r.   r/   r0   r   r7   r   r2   r8   r1   r9   boolr
   r   r;   dictr<   r   r=   r   r>   r?   rA   intrB   r   r   classmethodr   rQ   r	   model_configr^   rg   rz   r}   r(   r   r   r   r   r6   r6      sb         6 (KMMG\)))JHd5)<===FD==="GXd^"""#%GXd3i %%%&(Jc#((("$L(3-$$$AsKKK $J$$$_(###T c    [ $#6 :  Lt     d |    > (,*.&(C CC $s)$C T#Y'	C
 smC C 
C C C CP (,&(	! !! $s)$! sm	!
 ! 
! ! ! !N (,*.&(7
 7
7
 7
 $s)$	7

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

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