o
    Zh                     @   s   d Z ddlmZmZmZmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZmZmZ G dd deZG d	d
 d
e	ZG dd de	ZdS )zUtil that calls Google Search.    )AnyDictListOptional)CallbackManagerForToolRun)BaseTool)get_from_dict_or_env)	BaseModel
ConfigDictmodel_validatorc                
   @   s   e Zd ZU dZdZeed< dZee	 ed< dZ
ee	 ed< dZeed< dZeed	< ed
dZde	dedee fddZeddededefddZde	de	fddZ	dde	dedeee	e	f  dee fddZdS )GoogleSearchAPIWrapperuY  Wrapper for Google Search API.

    Adapted from: Instructions adapted from https://stackoverflow.com/questions/
    37083058/
    programmatically-searching-google-in-python-using-custom-search

    TODO: DOCS for using it
    1. Install google-api-python-client
    - If you don't already have a Google account, sign up.
    - If you have never created a Google APIs Console project,
    read the Managing Projects page and create a project in the Google API Console.
    - Install the library using pip install google-api-python-client

    2. Enable the Custom Search API
    - Navigate to the APIs & Services→Dashboard panel in Cloud Console.
    - Click Enable APIs and Services.
    - Search for Custom Search API and click on it.
    - Click Enable.
    URL for it: https://console.cloud.google.com/apis/library/customsearch.googleapis
    .com

    3. To create an API key:
    - Navigate to the APIs & Services → Credentials panel in Cloud Console.
    - Select Create credentials, then select API key from the drop-down menu.
    - The API key created dialog box displays your newly created key.
    - You now have an API_KEY

    Alternatively, you can just generate an API key here:
    https://developers.google.com/custom-search/docs/paid_element#api_key

    4. Setup Custom Search Engine so you can search the entire web
    - Create a custom search engine here: https://programmablesearchengine.google.com/.
    - In `What to search` to search, pick the `Search the entire Web` option.
    After search engine is created, you can click on it and find `Search engine ID`
      on the Overview page.

    Nsearch_enginegoogle_api_keygoogle_cse_id
   kFsiterestrictZforbid)extrasearch_termkwargsreturnc                 K   s@   | j  }| jr| }|jd|| jd| }|dg S )N)qZcxitems )r   cser   listr   executeget)selfr   r   r   resr   r   X/var/www/html/lang_env/lib/python3.10/site-packages/langchain_google_community/search.py_google_search_results<   s
   
z-GoogleSearchAPIWrapper._google_search_resultsbefore)modevaluesc                 C   sj   t |dd}||d< t |dd}||d< zddlm} W n ty'   tdw |dd	|d
}||d< |S )z?Validate that api key and python package exists in environment.r   ZGOOGLE_API_KEYr   ZGOOGLE_CSE_IDr   )buildzjgoogle-api-python-client is not installed. Please install it with `pip install langchain-google-community`Zcustomsearchv1)ZdeveloperKeyr   )r   Zgoogleapiclient.discoveryr%   ImportError)clsr$   r   r   r%   Zservicer   r   r    validate_environmentC   s    z+GoogleSearchAPIWrapper.validate_environmentqueryc                 C   sN   g }| j || jd}t|dkrdS |D ]}d|v r!||d  qd|S )z0Run query through GoogleSearch and parse result.)numr   &No good Google Search Result was foundsnippet )r!   r   lenappendjoin)r   r*   Zsnippetsresultsresultr   r   r    run]   s   
zGoogleSearchAPIWrapper.runnum_resultssearch_paramsc                 C   sr   g }| j |fd|i|pi }t|dkrddigS |D ]}|d |d d}d|v r1|d |d< || q|S )	a  Run query through GoogleSearch and return metadata.

        Args:
            query: The query to search for.
            num_results: The number of results to return.
            search_params: Parameters to be passed on search

        Returns:
            A list of dictionaries with the following keys:
                snippet - The description of the result.
                title - The title of the result.
                link - The link to the result.
        r+   r   Resultr,   titlelink)r8   r9   r-   )r!   r/   r0   )r   r*   r5   r6   Zmetadata_resultsr2   r3   Zmetadata_resultr   r   r    r2   i   s$   
zGoogleSearchAPIWrapper.resultsN)__name__
__module____qualname____doc__r   r   __annotations__r   r   strr   r   intr   boolr
   Zmodel_configr   dictr!   r   classmethodr   r)   r4   r2   r   r   r   r    r      s2   
 &r   c                   @   sP   e Zd ZU dZdZeed< dZeed< eed< 	dded	e	e
 d
efddZdS )GoogleSearchRunz(Tool that queries the Google search API.Zgoogle_searchnamezA wrapper around Google Search. Useful for when you need to answer questions about current events. Input should be a search query.descriptionapi_wrapperNr*   run_managerr   c                 C   s   | j |S zUse the tool.)rH   r4   r   r*   rI   r   r   r    _run   s   zGoogleSearchRun._runr:   )r;   r<   r=   r>   rF   r@   r?   rG   r   r   r   rL   r   r   r   r    rE      s   
 
rE   c                   @   s\   e Zd ZU dZdZeed< dZeed< dZe	ed< e
ed< 		dd
edee defddZd	S )GoogleSearchResultsz;Tool that queries the Google Search API and gets back json.Zgoogle_search_results_jsonrF   zA wrapper around Google Search. Useful for when you need to answer questions about current events. Input should be a search query. Output is a JSON array of the query resultsrG      r5   rH   Nr*   rI   r   c                 C   s   t | j|| jS rJ   )r@   rH   r2   r5   rK   r   r   r    rL      s   zGoogleSearchResults._runr:   )r;   r<   r=   r>   rF   r@   r?   rG   r5   rA   r   r   r   rL   r   r   r   r    rM      s   
 
rM   N)r>   typingr   r   r   r   Zlangchain_core.callbacksr   Zlangchain_core.toolsr   Zlangchain_core.utilsr   Zpydanticr	   r
   r   r   rE   rM   r   r   r   r    <module>   s     