o
    Zhk:                     @  sT  d dl 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mZmZmZ d dlZd dlmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZ d dl m!Z! d dl"m#Z# erxd dl$m%Z% d dl&m'Z' d>ddZ(d?ddZ)d@d#d$Z*dAd&d'Z+G d(d) d)eZ,ed*d+d,d-					.		dBdCd<d=Z-dS )D    )annotationsN)defaultdict)TYPE_CHECKINGAnyCallableDictListOptionalTupleUnion)
deprecated)CallbackManagerForChainRun)BaseLanguageModel)JsonOutputFunctionsParser)BasePromptTemplateChatPromptTemplate)get_colored_text)Response)Chain)LLMChain)SequentialChainOpenAPISpec)	Parameteror   prefer_shortboolreturnOptional[str]c                 C  s,   t | dd }t | dd }|r|p|S |p|S )Nsummarydescription)getattr)r   r   r   r     r"   `/var/www/html/lang_env/lib/python3.10/site-packages/langchain/chains/openai_functions/openapi.py_get_description   s
   r$   urlstrpath_paramsdictc           
        s~  t d| }i }|D ]}|dd}|| }t|trY|d dkr5|d dkr+dnd}d|| }n}|d dkrS|d dkrF| d	nd}| d	|| }n_d|}nYt|tr|d dkrfd	nd  fd
d| D }	|d dkr~d}d}n|d dkrd}d}nd}d}|||	7 }n|d dkrd| }n|d dkrd| d	| }n|}|||< q
| j	di |S )Nz{(.*?)}z.;*r   .,;=c                   s   g | ]\}}  ||fqS r"   )join).0kvZkv_sepr"   r#   
<listcomp>3   s    z_format_url.<locals>.<listcomp> r"   )
refindalllstriprstrip
isinstancelistr/   r(   itemsformat)
r%   r'   Zexpected_path_param
new_paramsparamZclean_paramvalsepnew_valZkv_strsr"   r3   r#   _format_url"   s@   


rC   paramsList[Parameter]specr   c                 C  s   i }g }| D ]:}|j r||j }nt|j d j}||}|jr+|js+|j|_t|jdd||j	< |j
r@||j	 qd||dS )Nr   TZexclude_noneobject)type
propertiesrequired)Zparam_schema
get_schemar;   contentvaluesmedia_type_schemar    jsonloadsnamerK   append)rD   rF   rJ   rK   pschemarO   r"   r"   r#   _openapi_params_to_json_schemaI   s   
rV   %Tuple[List[Dict[str, Any]], Callable]c                   s"  zddl m} W n ty   tdw | jsg dd fS g }i  | jD ]}dd | |D }| |D ]}i }| ||}| }| |D ]
}	|	||	j	|	j
f< qHtt}
| D ]\}}|
|d  | q[d	d
ddd}| D ]\}}|
| rt|
| | ||< qt| |}|r|jri }|j D ]\}}|jr| |j}t|jdd||< qt|dkrt| d \}}|dkrdnd}|||< nt|dkrdt| i|d< || ||}|j|jd|dd}|| ||j|j d |d < q5q$		d#d$ fd!d"}||fS )%a4  Convert a valid OpenAPI spec to the JSON Schema format expected for OpenAI
        functions.

    Args:
        spec: OpenAPI spec to convert.

    Returns:
        Tuple of the OpenAI functions JSON schema and a default function for executing
            a request based on the OpenAI function schema.
    r   )APIOperationzeCould not import langchain_community.tools. Please install it with `pip install langchain-community`.c                   S  s   d S Nr"   r"   r"   r"   r#   <lambda>p   s    z+openapi_spec_to_openai_fn.<locals>.<lambda>c                 S  s   i | ]	}|j |jf|qS r"   )rR   param_in)r0   rT   r"   r"   r#   
<dictcomp>t   s    z-openapi_spec_to_openai_fn.<locals>.<dictcomp>   rD   headerscookiesr'   )queryheadercookiepathTrG   zapplication/jsonrP   dataZanyOfrH   )rI   rJ   )rR   r    
parameters)methodr%   rR   Nr&   fn_argsr(   Optional[dict]kwargsr   r   c           	        s    |  d } |  d }| di }t||}d|v r+t|d tr+t|d |d< i ||}|d urEd|v rA|d | n||d< |d urYd|v rU|d | n||d< tj||fi |S )Nrf   r%   r'   rd   r^   rD   )	poprC   r:   r(   rP   dumpsupdaterequestsrequest)	rR   rg   r^   rD   ri   rf   r%   r'   _kwargsZ_name_to_call_mapr"   r#   default_call_api   s    
z3openapi_spec_to_openai_fn.<locals>.default_call_api)NN)rR   r&   rg   r(   r^   rh   rD   rh   ri   r   r   r   )Zlangchain_community.toolsrX   ImportErrorpathsZget_parameters_for_pathZget_methods_for_pathZget_operationcopyZget_parameters_for_operationrR   r[   r   r;   r<   rS   rV   Zget_request_body_for_operationrM   rO   rL   rP   rQ   lenrN   Zfrom_openapi_specZoperation_idr    base_urlrc   )rF   rX   	functionsrc   r'   rf   Zrequest_argsopZ	op_paramsr?   Zparams_by_typeZname_locrT   Zparam_loc_to_arg_nameZ	param_locarg_namerequest_bodyZmedia_types
media_typeZmedia_type_objectrU   Zschema_dictkeyZapi_opfnrq   r"   rp   r#   openapi_spec_to_openai_fnZ   s   






7r~   c                   @  sb   e Zd ZU dZded< 	 dZded< 	 dZded< 	 edddZedddZ		ddddZ
dS )SimpleRequestChainz5Chain for making a simple request to an API endpoint.r   request_methodresponser&   
output_keyfunction	input_keyr   	List[str]c                 C     | j gS rY   )r   selfr"   r"   r#   
input_keys      zSimpleRequestChain.input_keysc                 C  r   rY   )r   r   r"   r"   r#   output_keys   r   zSimpleRequestChain.output_keysNinputsDict[str, Any]run_manager$Optional[CallbackManagerForChainRun]c                 C  s   |pt  }|| j d}|| j d}t|d}ttj|ddd}d| d| }|| | ||}	|	j	dkrV|	j	 d	|	j
 d
| d d|dd  }
nz|	 }
W n tyh   |	j}
Y nw | j|
iS )z2Run the logic of this chain and return the output.rR   	argumentsgreen   )indentzCalling endpoint z with arguments:
   z: z
For  zCalled with args: rD   r5   )r   Zget_noop_managerr   rj   r   rP   rk   Zon_textr   status_codereasonget	Exceptiontextr   )r   r   r   Z_run_managerrR   argsZ_pretty_nameZ_pretty_args_textZapi_responser   r"   r"   r#   _call   s*   





zSimpleRequestChain._call)r   r   rY   )r   r   r   r   r   r   )__name__
__module____qualname____doc____annotations__r   r   propertyr   r   r   r"   r"   r"   r#   r      s   
 r   z0.2.13zThis function is deprecated and will be removed in langchain 1.0. See API reference for replacement: https://api.python.langchain.com/en/latest/chains/langchain.chains.openai_functions.openapi.get_openapi_chain.htmlz1.0)ZsincemessageZremovalFUnion[OpenAPISpec, str]llmOptional[BaseLanguageModel]promptOptional[BasePromptTemplate]request_chainOptional[Chain]llm_chain_kwargsOptional[Dict]verboser^   ri   r   c                   s2  zddl m}	 W n ty }
 ztd|
d}
~
ww t| trS|	j|	j|	jfD ]}z|| } W  n ty> }
 z|
d}
~
w tyF   Y q'w t| trSt	d|  t
| \} |s_t	d|petd}td||d|itd	d
d|d|pxi }|pt fdd|d}td||g|jdg|d|S )a  Create a chain for querying an API from a OpenAPI spec.

    Note: this class is deprecated. See below for a replacement implementation.
        The benefits of this implementation are:

        - Uses LLM tool calling features to encourage properly-formatted API requests;
        - Includes async support.

        .. code-block:: python

            from typing import Any

            from langchain.chains.openai_functions.openapi import openapi_spec_to_openai_fn
            from langchain_community.utilities.openapi import OpenAPISpec
            from langchain_core.prompts import ChatPromptTemplate
            from langchain_openai import ChatOpenAI

            # Define API spec. Can be JSON or YAML
            api_spec = """
            {
            "openapi": "3.1.0",
            "info": {
                "title": "JSONPlaceholder API",
                "version": "1.0.0"
            },
            "servers": [
                {
                "url": "https://jsonplaceholder.typicode.com"
                }
            ],
            "paths": {
                "/posts": {
                "get": {
                    "summary": "Get posts",
                    "parameters": [
                    {
                        "name": "_limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                        "type": "integer",
                        "example": 2
                        },
                        "description": "Limit the number of results"
                    }
                    ]
                }
                }
            }
            }
            """

            parsed_spec = OpenAPISpec.from_text(api_spec)
            openai_fns, call_api_fn = openapi_spec_to_openai_fn(parsed_spec)
            tools = [
                {"type": "function", "function": fn}
                for fn in openai_fns
            ]

            prompt = ChatPromptTemplate.from_template(
                "Use the provided APIs to respond to this user query:\n\n{query}"
            )
            llm = ChatOpenAI(model="gpt-4o-mini", temperature=0).bind_tools(tools)

            def _execute_tool(message) -> Any:
                if tool_calls := message.tool_calls:
                    tool_call = message.tool_calls[0]
                    response = call_api_fn(name=tool_call["name"], fn_args=tool_call["args"])
                    response.raise_for_status()
                    return response.json()
                else:
                    return message.content

            chain = prompt | llm | _execute_tool

        .. code-block:: python

            response = chain.invoke({"query": "Get me top two posts."})

    Args:
        spec: OpenAPISpec or url/file/text string corresponding to one.
        llm: language model, should be an OpenAI function-calling model, e.g.
            `ChatOpenAI(model="gpt-3.5-turbo-0613")`.
        prompt: Main prompt template to use.
        request_chain: Chain for taking the functions output and executing the request.
    r   r   zqCould not import langchain_community.utilities.openapi. Please install it with `pip install langchain-community`.Nz!Unable to parse spec from source zkMust provide an LLM for this chain.For example,
from langchain_openai import ChatOpenAI
llm = ChatOpenAI()
z>Use the provided API's to respond to this user query:

{query}rw   F)Z	args_onlyr   )r   r   Z
llm_kwargsZoutput_parserr   r   c                   s    | |dS )N)r^   rD   r"   )rR   r   Zcall_api_fnr^   rD   r"   r#   rZ     s    z#get_openapi_chain.<locals>.<lambda>)r   r   r   )chainsZinput_variablesZoutput_variablesr   r"   )%langchain_community.utilities.openapir   rr   r:   r&   Zfrom_url	from_fileZ	from_textr   
ValueErrorr~   r   Zfrom_templater   r   r   r   r   )rF   r   r   r   r   r   r^   rD   ri   r   e
conversionZ
openai_fnsZ	llm_chainr"   r   r#   get_openapi_chain   sp   j

	r   )r   r   r   r   r   r   )r%   r&   r'   r(   r   r&   )rD   rE   rF   r   r   r(   )rF   r   r   rW   )NNNNFNN)rF   r   r   r   r   r   r   r   r   r   r   r   r^   r   rD   r   ri   r   r   r   ).
__future__r   rP   r6   collectionsr   typingr   r   r   r   r   r	   r
   r   rm   Zlangchain_core._apir   Zlangchain_core.callbacksr   Zlangchain_core.language_modelsr   Z.langchain_core.output_parsers.openai_functionsr   Zlangchain_core.promptsr   r   Zlangchain_core.utils.inputr   r   Zlangchain.chains.baser   Zlangchain.chains.llmr   Zlangchain.chains.sequentialr   r   r   Zopenapi_pydanticr   r$   rC   rV   r~   r   r   r"   r"   r"   r#   <module>   sJ    (


'
n.