o
    {qi:                     @  s>  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 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rrd dl!m"Z" d dl#m$Z$ d9ddZ%d:ddZ&d;dd Z'G d!d" d"eZ(ed#d$d%d&					'		d<d=d7d8Z)dS )>    )annotationsN)defaultdict)TYPE_CHECKINGAnyCallableOptionalUnion)
deprecated)CallbackManagerForChainRun)BaseLanguageModel)JsonOutputFunctionsParser)BasePromptTemplateChatPromptTemplate)get_colored_text)Response)Chain)LLMChain)SequentialChainOpenAPISpec)	Parameterurlstrpath_paramsdictreturnc           
        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  )join).0kvZkv_sepr"   p/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/langchain/chains/openai_functions/openapi.py
<listcomp>+   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"   r'   r(   _format_url   s@   


r8   paramslist[Parameter]specr   c                 C  s   i }g }| D ]:}|j r||j }ntt|j j}||}|jr+|js+|j|_t	|jdd||j
< |jr@||j
 qd||dS )NTZexclude_noneobject)type
propertiesrequired)Zparam_schema
get_schemanextitercontentvaluesmedia_type_schemadescriptionjsonloadsnamer@   append)r9   r;   r?   r@   pschemarF   r"   r"   r(   _openapi_params_to_json_schema@   s   
rN   %tuple[list[dict[str, Any]], Callable]c              
     s4  zddl m} W n ty } zd}t||d}~ww | js%g dd fS g }i  | jD ]}dd | |D }| |D ]}i }| ||}	| }
| |	D ]
}||
|j	|j
f< qPtt}|
 D ]\}}||d	  | qcd
dddd}| D ]\}}|| rt|| | ||< q|| |	}|r|jri }|j D ]\}}|jr| |j}t|jdd||< qt|d	krtt| \}}|dkrdnd}|||< nt|d	krdt| i|d< || ||}|j|jd|dd}|| ||j|j d |d < q=q,			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`.Nc                   S  s   d S Nr"   r"   r"   r"   r(   <lambda>h   s    z+openapi_spec_to_openai_fn.<locals>.<lambda>c                 S  s   i | ]	}|j |jf|qS r"   )rJ   param_in)r$   rL   r"   r"   r(   
<dictcomp>l   s    z-openapi_spec_to_openai_fn.<locals>.<dictcomp>   r9   headerscookiesr   )queryheadercookiepathTr<   zapplication/jsonrH   dataZanyOfr=   )r>   r?   )rJ   rG   
parameters)methodr   rJ      r   fn_argsr   Optional[dict]timeoutOptional[int]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 |	d|iS )Nr^   r   r   r\   rV   r9   rb   )	popr8   r/   r   rH   dumpsupdaterequestsrequest)
rJ   r`   rV   r9   rb   rd   r^   r   r   _kwargsZ_name_to_call_mapr"   r(   default_call_api   s    
z3openapi_spec_to_openai_fn.<locals>.default_call_api)NNr_   )rJ   r   r`   r   rV   ra   r9   ra   rb   rc   rd   r   r   r   )Zlangchain_community.toolsrP   ImportErrorpathsZget_parameters_for_pathZget_methods_for_pathZget_operationcopyZget_parameters_for_operationrJ   rS   r   r0   r1   rK   rN   Zget_request_body_for_operationrD   rF   rA   rH   rI   lenrB   rC   rE   Zfrom_openapi_specZoperation_idrG   base_urlr[   )r;   rP   emsg	functionsr[   r   r^   Zrequest_argsopZ	op_paramsr4   Zparams_by_typeZname_locrL   Zparam_loc_to_arg_nameZ	param_locZarg_namerequest_bodyZmedia_types
media_typeZmedia_type_objectrM   Zschema_dictkeyZapi_opfnrl   r"   rk   r(   openapi_spec_to_openai_fnQ   s   







8rz   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 rQ   )r   selfr"   r"   r(   
input_keys      zSimpleRequestChain.input_keysc                 C  r   rQ   )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	t
jjkrS|	j	 d|	j d	| d
|dd }
nz|	 }
W n tye   |	j}
Y nw | j|
iS )z2Run the logic of this chain and return the output.rJ   	argumentsgreen   )indentzCalling endpoint z with arguments:
z: z
For z Called with args: r9   r*   )r
   Zget_noop_managerr   re   r   rH   rf   Zon_textr|   status_coderh   codesokreasonget	Exceptiontextr~   )r   r   r   Z_run_managerrJ   argsZ_pretty_nameZ_pretty_args_textZapi_responser}   r"   r"   r(   _call   s*   




zSimpleRequestChain._call)r   r   rQ   )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_kwargsra   verboseboolrV   rd   r   r   c              
     s2  zddl m}	 W n ty }
 zd}t||
d}
~
ww t| trQ|	j|	j|	jfD ]}z|| } W  n ty:     tyB   Y q)w t| trQd|  }t	|t
| \} |s_d}t	||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}rt   F)Z	args_onlyr   )r   r   Z
llm_kwargsZoutput_parserr~   r   c                   s    | |dS )N)rV   r9   r"   )rJ   r   Zcall_api_fnrV   r9   r"   r(   rR     s    z#get_openapi_chain.<locals>.<lambda>)r|   r   r}   )chainsZinput_variablesZoutput_variablesr   r"   )%langchain_community.utilities.openapir   rm   r/   r   Zfrom_url	from_fileZ	from_textr   
ValueErrorrz   r   Zfrom_templater   r   r{   r   r   )r;   r   r   r   r   r   rV   r9   rd   r   rr   rs   
conversionZ
openai_fnsZ	llm_chainr"   r   r(   get_openapi_chain   sl   j



		r   )r   r   r   r   r   r   )r9   r:   r;   r   r   r   )r;   r   r   rO   )NNNNFNN)r;   r   r   r   r   r   r   r   r   ra   r   r   rV   ra   r9   ra   rd   r   r   r   )*
__future__r   rH   r+   collectionsr   typingr   r   r   r   r   rh   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   r8   rN   rz   r{   r   r"   r"   r"   r(   <module>   sH    

&
q.