U
    h!                     @   sv   d Z ddlZddlZddlmZmZmZmZ ddlZddl	m
Z
mZmZ ddlmZ G dd dZG dd	 d	e
ZdS )
zWChain that calls SerpAPI.

Heavily borrowed from https://github.com/ofirpress/self-ask
    N)AnyDictOptionalTuple)	BaseModelFieldroot_validator)get_from_dict_or_envc                   @   s.   e Zd ZdZddddZeddddZdS )	HiddenPrintszContext manager to hide prints.Nreturnc                 C   s   t j| _ttjdt _dS )zOpen file to pipe stdout to.wN)sysstdout_original_stdoutopenosdevnull)self r   I/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/utilities/serpapi.py	__enter__   s    zHiddenPrints.__enter__)_r   c                 G   s   t j  | jt _dS )z$Close file that stdout was piped to.N)r   r   closer   )r   r   r   r   r   __exit__   s    
zHiddenPrints.__exit__)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r
      s   r
   c                   @   s   e Zd ZU dZeed< eddddddZeed	< d
Z	e
e ed< d
Ze
ej ed< G dd dZeddeedddZeeedddZeeedddZeedddZeedddZeeeef dddZeeed d!d"Zd
S )#SerpAPIWrappera  Wrapper around SerpAPI.

    To use, you should have the ``google-search-results`` python package installed,
    and the environment variable ``SERPAPI_API_KEY`` set with your API key, or pass
    `serpapi_api_key` as a named parameter to the constructor.

    Example:
        .. code-block:: python

            from langchain_community.utilities import SerpAPIWrapper
            serpapi = SerpAPIWrapper()
    search_engineZgooglez
google.comusen)ZengineZgoogle_domainglZhl)defaultparamsNserpapi_api_key
aiosessionc                   @   s   e Zd ZdZdZdS )zSerpAPIWrapper.ConfigTZforbidN)r   r   r   Zarbitrary_types_allowedextrar   r   r   r   Config7   s   r)   T)pre)valuesr   c                 C   sN   t |dd}||d< zddlm} ||d< W n tk
rH   tdY nX |S )z?Validate that api key and python package exists in environment.r&   ZSERPAPI_API_KEYr   )GoogleSearchr    zdCould not import serpapi python package. Please install it with `pip install google-search-results`.)r	   Zserpapir,   ImportError)clsr+   r&   r,   r   r   r   validate_environment;   s      
z#SerpAPIWrapper.validate_environment)querykwargsr   c                    s   |  | |I dH S )z1Run query through SerpAPI and parse result async.N)_process_responsearesultsr   r0   r1   r   r   r   arunM   s    zSerpAPIWrapper.arunc                 K   s   |  | |S )z+Run query through SerpAPI and parse result.)r2   resultsr4   r   r   r   runQ   s    zSerpAPIWrapper.run)r0   r   c              	   C   s2   |  |}t  | |}| }W 5 Q R X |S )z4Run query through SerpAPI and return the raw result.)
get_paramsr
   r    get_dict)r   r0   r%   searchresr   r   r   r6   U   s
    

zSerpAPIWrapper.resultsc                    s   t ttttf f d fdd}| \}}jst 4 I dH <}|j||d4 I dH }| I dH }W 5 Q I dH R X W 5 Q I dH R X n8jj||d4 I dH }| I dH }W 5 Q I dH R X |S )zFUse aiohttp to run query through SerpAPI and return the results async.r   c                     s6     } d| d< jr"j| d< d| d< d}|| fS )NpythonsourceZserp_api_keyjsonoutputzhttps://serpapi.com/search)r8   r&   )r%   urlr0   r   r   r   construct_url_and_params`   s    

z9SerpAPIWrapper.aresults.<locals>.construct_url_and_paramsN)r%   )r   strr   r'   aiohttpClientSessiongetr>   )r   r0   rB   r@   r%   sessionresponser;   r   rA   r   r3   ]   s    $	
0zSerpAPIWrapper.aresultsc                 C   s   | j |d}| j|}|S )zGet parameters for SerpAPI.)Zapi_keyq)r&   r%   )r   r0   _paramsr%   r   r   r   r8   t   s
    
zSerpAPIWrapper.get_params)r;   r   c           	   	   C   sv  d|   krtd| d  d|   kr6| d | d< d|   k r| d }t|tr^|d }d|  krr|d S d|  kr|d S d|  kr|d S d	|  kr|d	 S i }| D ]2\}}t|ttfst|tr|d
s|||< qt|S npd|   kr| d dd S d|   kr.| d S d|   krD| d S d|   krZ| d S d|   krd| d   kr| d d S d|   krd| d d   kr| d dd S d|   kr| d S d|   krd| d   kr| d d S d|   kr(d| d   kr(| d d S d|   krjd| d d   krjtdd | d dd D S g }d|   kr,| d }d|kr|d nd }d!|  kr||d!  | D ]l\}}t|trt|tr|d"kr|	d#s|	d$s|d
s|| d%| d&| d' q| 
d(g D ]}d|  krZ||d  nvd	|  krx||d	  nXd)|  kr||d)  n:d*|  kr||d*  nd+|  kr8||d+  q8d,|   kr|| d,  d-| krt| d- tr|| d- 7 }d-|   krXt| d- trXd.| d-   krX|| d- d.  t|dkrnt|S d/S dS )0zProcess response from SerpAPI.errorzGot error from SerpAPI: Zanswer_box_list
answer_boxr   resultanswerZsnippetZsnippet_highlighted_wordshttpZevents_resultsN
   Zsports_resultsZtop_storiesZnews_resultsZjobs_resultsjobsZshopping_resultstitle   Zquestions_and_answersZpopular_destinationsdestinationsZ
top_sightsZsightsZimages_results	thumbnailc                 S   s   g | ]}|d  qS )rU   r   ).0itemr   r   r   
<listcomp>   s     z4SerpAPIWrapper._process_response.<locals>.<listcomp>knowledge_graph description)rR   r[   Z_stickZ_link z: .Zorganic_resultsZrich_snippetZrich_snippet_tablelinkZbuying_guideZlocal_resultsZplaceszNo good search result found)keys
ValueError
isinstancelistitemsdictrC   
startswithappendendswithrF   len)	r;   rL   rN   keyvalueZsnippetsrY   rR   Zorganic_resultr   r   r   r2   }   s    

 

 
 
z SerpAPIWrapper._process_response)r   r   r   r   r   __annotations__r   r%   rd   r&   r   rC   r'   rD   rE   r)   r   r   r/   r5   r7   r6   r3   r8   staticmethodr2   r   r   r   r   r      s*   
	r   )r   r   r   typingr   r   r   r   rD   Zlangchain_core.pydantic_v1r   r   r   Zlangchain_core.utilsr	   r
   r   r   r   r   r   <module>   s   