o
    `+ iw                     @  sx  d dl mZ d dl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
mZmZmZmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZmZmZ d dlmZ d dlmZ d dlmZm Z m!Z! d dl"m#Z#m$Z$ e
r|d dl%Z%d dl&m'Z' d dl(m)Z) G dd deZ*G dd deZ+d(ddZ,d)ddZ-d*dd Z.d+d"d#Z/ee0e+ e*e0d$ e0d% f Z1G d&d' d'ee2e1f Z3dS ),    )annotationsN)Sequence)JSONDecodeError)sleep)TYPE_CHECKINGAnyCallableOptionalUnion)AgentActionAgentFinish)CallbackManager)dumpd)RunnableConfigRunnableSerializableensure_config)BaseTool)convert_to_openai_tool)	BaseModelFieldmodel_validator)Selfoverride)ThreadMessage)RequiredActionFunctionToolCallc                   @  s0   e Zd ZU dZded< ded< ed
ddZd	S )OpenAIAssistantFinishzuAgentFinish with run and thread metadata.

    Parameters:
        run_id: Run id.
        thread_id: Thread id.
    strrun_id	thread_idreturnboolc                 C     dS z]Check if the class is serializable by LangChain.

        Returns:
            False
        F clsr#   r#   r/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/langchain/agents/openai_assistant/base.pyis_lc_serializable,      z(OpenAIAssistantFinish.is_lc_serializableNr   r    __name__
__module____qualname____doc____annotations__classmethodr'   r#   r#   r#   r&   r   !   s   
 r   c                   @  s8   e Zd ZU dZded< ded< ded< eddd	Zd
S )OpenAIAssistantActionzAgentAction with info needed to submit custom tool output to existing run.

    Parameters:
        tool_call_id: Tool call id.
        run_id: Run id.
        thread_id: Thread id
    r   tool_call_idr   r   r   r    c                 C  r!   r"   r#   r$   r#   r#   r&   r'   C   r(   z(OpenAIAssistantAction.is_lc_serializableNr)   r*   r#   r#   r#   r&   r1   6   s   
 r1   r   openai.OpenAIc               
   C  ^   z	dd l } |  W S  ty } zd}t||d }~w ty. } zd}t||d }~ww Nr   zBUnable to import openai, please install with `pip install openai`.zuPlease make sure you are using a v1.1-compatible version of openai. You can install with `pip install "openai>=1.1"`.)openaiZOpenAIImportErrorAttributeErrorr6   emsgr#   r#   r&   _get_openai_clientM      


r<   openai.AsyncOpenAIc               
   C  r4   r5   )r6   AsyncOpenAIr7   r8   r9   r#   r#   r&   _get_openai_async_client]   r=   r@   tool:Union[dict[str, Any], type[BaseModel], Callable, BaseTool]r    c                 C  s"   d}t | tod| v o| d |v S )z<Determine if tool corresponds to OpenAI Assistants built-in.)Zcode_interpreterZfile_searchtype)
isinstancedict)rA   Zassistants_builtin_toolsr#   r#   r&   _is_assistants_builtin_toolm   s   

rF   dict[str, Any]c                 C  s   t | r| S t| S )zConvert a raw function/class to an OpenAI tool.

    Note that OpenAI assistants supports several built-in tools,
    such as "code_interpreter" and "file_search".
    )rF   r   )rA   r#   r#   r&   _get_assistants_tooly   s   rH   r   r   c                   @  s  e Zd ZU dZeedZded< 	 dZded< 	 ded< 	 d	Z	d
ed< 	 dZ
ded< 	 edddGddZedddHddZe	dIdJd$d%Zedd&dKd(d)Ze	dIdJd*d+ZdLd.d/ZdMd1d2ZdNd4d5ZdOd7d8ZdPd;d<ZdLd=d>ZdMd?d@ZdNdAdBZdOdCdDZdPdEdFZdS )QOpenAIAssistantRunnablea  Run an OpenAI Assistant.

    Example using OpenAI tools:
        .. code-block:: python

            from langchain_experimental.openai_assistant import OpenAIAssistantRunnable

            interpreter_assistant = OpenAIAssistantRunnable.create_assistant(
                name="langchain assistant",
                instructions="You are a personal math tutor. Write and run code to answer math questions.",
                tools=[{"type": "code_interpreter"}],
                model="gpt-4-1106-preview"
            )
            output = interpreter_assistant.invoke({"content": "What's 10 - 4 raised to the 2.7"})

    Example using custom tools and AgentExecutor:
        .. code-block:: python

            from langchain_experimental.openai_assistant import OpenAIAssistantRunnable
            from langchain.agents import AgentExecutor
            from langchain.tools import E2BDataAnalysisTool


            tools = [E2BDataAnalysisTool(api_key="...")]
            agent = OpenAIAssistantRunnable.create_assistant(
                name="langchain assistant e2b tool",
                instructions="You are a personal math tutor. Write and run code to answer math questions.",
                tools=tools,
                model="gpt-4-1106-preview",
                as_agent=True
            )

            agent_executor = AgentExecutor(agent=agent, tools=tools)
            agent_executor.invoke({"content": "What's 10 - 4 raised to the 2.7"})


    Example using custom tools and custom execution:
        .. code-block:: python

            from langchain_experimental.openai_assistant import OpenAIAssistantRunnable
            from langchain.agents import AgentExecutor
            from langchain_core.agents import AgentFinish
            from langchain.tools import E2BDataAnalysisTool


            tools = [E2BDataAnalysisTool(api_key="...")]
            agent = OpenAIAssistantRunnable.create_assistant(
                name="langchain assistant e2b tool",
                instructions="You are a personal math tutor. Write and run code to answer math questions.",
                tools=tools,
                model="gpt-4-1106-preview",
                as_agent=True
            )

            def execute_agent(agent, tools, input):
                tool_map = {tool.name: tool for tool in tools}
                response = agent.invoke(input)
                while not isinstance(response, AgentFinish):
                    tool_outputs = []
                    for action in response:
                        tool_output = tool_map[action.tool].invoke(action.tool_input)
                        tool_outputs.append({"output": tool_output, "tool_call_id": action.tool_call_id})
                    response = agent.invoke(
                        {
                            "tool_outputs": tool_outputs,
                            "run_id": action.run_id,
                            "thread_id": action.thread_id
                        }
                    )

                return response

            response = execute_agent(agent, tools, {"content": "What's 10 - 4 raised to the 2.7"})
            next_response = execute_agent(agent, tools, {"content": "now add 17.241", "thread_id": response.thread_id})

    )default_factoryr   clientNasync_clientr   assistant_idg     @@floatcheck_every_msFr    as_agentafter)moder   r   c                 C  s,   | j d u rdd l}| jj}|j|d| _ | S )Nr   )api_key)rL   r6   rK   rS   r?   )selfr6   rS   r#   r#   r&   validate_async_client   s
   
z-OpenAIAssistantRunnable.validate_async_client)rK   nameinstructionstoolsSequence[Union[BaseTool, dict]]model2Optional[Union[openai.OpenAI, openai.AzureOpenAI]]kwargsc                K  s@   |pt  }|jjj||dd |D |d}| d|j|d|S )a*  Create an OpenAI Assistant and instantiate the Runnable.

        Args:
            name: Assistant name.
            instructions: Assistant instructions.
            tools: Assistant tools. Can be passed in OpenAI format or as BaseTools.
            model: Assistant model to use.
            client: OpenAI or AzureOpenAI client.
                Will create a default OpenAI client if not specified.
            kwargs: Additional arguments.

        Returns:
            OpenAIAssistantRunnable configured to run using the created assistant.
        c                 S     g | ]}t |qS r#   rH   .0rA   r#   r#   r&   
<listcomp>      z<OpenAIAssistantRunnable.create_assistant.<locals>.<listcomp>rV   rW   rX   rZ   )rM   rK   Nr#   )r<   beta
assistantscreateid)r%   rV   rW   rX   rZ   rK   r\   	assistantr#   r#   r&   create_assistant   s   
z(OpenAIAssistantRunnable.create_assistantinputrE   configOptional[RunnableConfig]
OutputTypec              
   K  s  t |}tj|d|d|dd}|jt| ||dp#|  d}zq| jrC|drC| |d }| j	j
jjjdi |}nKd|vrdd	|d
 |d|ddg|dd}| ||}n*d|vr| j	j
jjj|d |d
 d	|dd}	| |}n| j	j
jjjdi |}| |j|j}W n ty }
 z||
  d}
~
ww z| |}W n ty }
 z
|j|
| d  d}
~
ww || |S )a  Invoke assistant.

        Args:
            input: Runnable input dict that can have:
                content: User message when starting a new run.
                thread_id: Existing thread to use.
                run_id: Existing run to use. Should only be supplied when providing
                    the tool output for a required action after an initial invocation.
                message_metadata: Metadata to associate with new message.
                thread_metadata: Metadata to associate with new thread. Only relevant
                    when new thread being created.
                instructions: Additional run instructions.
                model: Override Assistant model for this run.
                tools: Override Assistant tools for this run.
                parallel_tool_calls: Allow Assistant to set parallel_tool_calls
                    for this run.
                top_p: Override Assistant top_p for this run.
                temperature: Override Assistant temperature for this run.
                max_completion_tokens: Allow setting max_completion_tokens for this run.
                max_prompt_tokens: Allow setting max_prompt_tokens for this run.
                run_metadata: Metadata to associate with new run.
                attachments: A list of files attached to the message, and the
                    tools they should be added to.
            config: Runnable config. Defaults to None.

        Return:
            If self.as_agent, will return
                Union[List[OpenAIAssistantAction], OpenAIAssistantFinish].
                Otherwise, will return OpenAI types
                Union[List[ThreadMessage], List[RequiredActionFunctionToolCall]].
        	callbackstagsmetadataZinheritable_callbacksZinheritable_tagsZinheritable_metadatarun_namerV   intermediate_stepsr   usercontentmessage_metadataattachments)rolerv   rp   rx   thread_metadatamessagesrp   r   rv   ry   rp   Nrp   r#   )r   r   	configuregeton_chain_startr   get_namerP   _parse_intermediate_stepsrK   rd   threadsrunssubmit_tool_outputs_create_thread_and_runr|   rf   _create_run_wait_for_runrg   r   BaseExceptionon_chain_error_get_responserE   on_chain_endrT   rj   rk   r\   Zcallback_managerZrun_managertool_outputsrunthread_r:   responser#   r#   r&   invoke  sf   '

zOpenAIAssistantRunnable.invoke)rL   <Optional[Union[openai.AsyncOpenAI, openai.AsyncAzureOpenAI]]c          	        sL   |pt  }dd |D }|jjj||||dI dH }| d|j|d|S )a	  Async create an AsyncOpenAI Assistant and instantiate the Runnable.

        Args:
            name: Assistant name.
            instructions: Assistant instructions.
            tools: Assistant tools. Can be passed in OpenAI format or as BaseTools.
            model: Assistant model to use.
            async_client: AsyncOpenAI client.
                Will create default async_client if not specified.

        Returns:
            AsyncOpenAIAssistantRunnable configured to run using the created assistant.
        c                 S  r]   r#   r^   r_   r#   r#   r&   ra     rb   z=OpenAIAssistantRunnable.acreate_assistant.<locals>.<listcomp>rc   N)rM   rL   r#   )r@   rd   re   rf   rg   )	r%   rV   rW   rX   rZ   rL   r\   Zopenai_toolsrh   r#   r#   r&   acreate_assistants  s   
z)OpenAIAssistantRunnable.acreate_assistantc              
     s  |pi }t j|d|d|dd}|jt| ||dp$|  d}z| jrJ|drJ| |d I dH }| jj	j
jjdi |I dH }nSd	|vrjd
|d |ddg|dd}| ||I dH }n3d|vr| jj	j
jj|d	 |d d
|ddI dH }	| |I dH }n| jj	j
jjdi |I dH }| |j|jI dH }W n ty }
 z||
  d}
~
ww z| |}W n ty }
 z
|j|
| d  d}
~
ww || |S )a  Async invoke assistant.

        Args:
            input: Runnable input dict that can have:
                content: User message when starting a new run.
                thread_id: Existing thread to use.
                run_id: Existing run to use. Should only be supplied when providing
                    the tool output for a required action after an initial invocation.
                message_metadata: Metadata to associate with a new message.
                thread_metadata: Metadata to associate with new thread. Only relevant
                    when a new thread is created.
                instructions: Overrides the instructions of the assistant.
                additional_instructions: Appends additional instructions.
                model: Override Assistant model for this run.
                tools: Override Assistant tools for this run.
                parallel_tool_calls: Allow Assistant to set parallel_tool_calls
                    for this run.
                top_p: Override Assistant top_p for this run.
                temperature: Override Assistant temperature for this run.
                max_completion_tokens: Allow setting max_completion_tokens for this run.
                max_prompt_tokens: Allow setting max_prompt_tokens for this run.
                run_metadata: Metadata to associate with new run.
            config: Runnable config. Defaults to None.
            kwargs: Additional arguments.

        Return:
            If self.as_agent, will return
                Union[List[OpenAIAssistantAction], OpenAIAssistantFinish].
                Otherwise, will return OpenAI types
                Union[List[ThreadMessage], List[RequiredActionFunctionToolCall]].
        rn   ro   rp   rq   rr   rs   rt   Nr   ru   rv   rw   )ry   rv   rp   rz   r{   r   r}   r~   r#   )r   r   r   r   r   r   rP   _aparse_intermediate_stepsrL   rd   r   r   r   _acreate_thread_and_runr|   rf   _acreate_run_await_for_runrg   r   r   r   r   rE   r   r   r#   r#   r&   ainvoke  sn   '



zOpenAIAssistantRunnable.ainvokert   'list[tuple[OpenAIAssistantAction, str]]c                   s^   |d \}}|  |j|j}t  |jrdd |jjjD   fdd|D }||j|jdS )Nc                 S     h | ]}|j qS r#   rg   r`   Ztcr#   r#   r&   	<setcomp>      zDOpenAIAssistantRunnable._parse_intermediate_steps.<locals>.<setcomp>c                   *   g | ]\}}|j  v rt||j d qS )outputr2   r2   r   r`   actionr   Zrequired_tool_call_idsr#   r&   ra     
    
zEOpenAIAssistantRunnable._parse_intermediate_steps.<locals>.<listcomp>r   r   r   r   r   r   setrequired_actionr   
tool_callsrT   rt   Zlast_actionZlast_outputr   r   r#   r   r&   r     s   
z1OpenAIAssistantRunnable._parse_intermediate_steps
input_dictc                 C  s6   dd |  D }| jjjjj|d fd| ji|S )Nc                 S     i | ]\}}|d v r||qS )
rW   rZ   rX   Zadditional_instructionsparallel_tool_callstop_ptemperaturemax_completion_tokensmax_prompt_tokensrun_metadatar#   r`   kvr#   r#   r&   
<dictcomp>      z7OpenAIAssistantRunnable._create_run.<locals>.<dictcomp>r   rM   )itemsrK   rd   r   r   rf   rM   rT   r   paramsr#   r#   r&   r     s   z#OpenAIAssistantRunnable._create_runr   c                 C  s0   dd |  D }| jjjjd| j|d|S )Nc                 S  r   )	rW   rZ   rX   r   r   r   r   r   r   r#   r   r#   r#   r&   r   *  r   zBOpenAIAssistantRunnable._create_thread_and_run.<locals>.<dictcomp>rM   r   r#   )r   rK   rd   r   create_and_runrM   rT   r   r   r   r#   r#   r&   r   )  s   z.OpenAIAssistantRunnable._create_thread_and_runr   c                   s  j dkrzdd l t jjdd }t jjdd }|dkp*|dko*|dk| jjjj	j
jdd}fdd	|D }| jsE|S d
d	 |D }dd	 |D }t fdd|D riddd |D }t|jj|ddjjdS j dkr| jsjjjS g }jjjD ]J}	|	j}
z
tj|
jdd}W n ty } zd|
j d|
j }t||d }~ww t|dkrd|v r|d }|t|
j||	jdjjd q|S tj dd}dj  d| }t|)N	completedr   .      ascorderc                      g | ]
}|j  jkr|qS r#   r   rg   r`   r;   r   r#   r&   ra   P      z9OpenAIAssistantRunnable._get_response.<locals>.<listcomp>c                 S     g | ]
}|j D ]}|qqS r#   rv   r`   r;   Zmsg_contentr#   r#   r&   ra   S  
    c                 S  r   r#   )rx   )r`   r;   
attachmentr#   r#   r&   ra   V  r   c                 3  8    | ]}rt | jjjjnt | jjjjV  qd S NrD   typesrd   r   ZTextContentBlockZMessageContentTextr`   rv   r6   version_gte_1_14r#   r&   	<genexpr>Y      	

z8OpenAIAssistantRunnable._get_response.<locals>.<genexpr>
c                 s      | ]}|j jV  qd S r   textvaluer   r#   r#   r&   r   d      )r   r   r   rx    Zreturn_valueslogr   r   requires_actionFstrict*Received invalid JSON function arguments:  for function __arg1rA   Z
tool_inputr2   r   r   r      indentUnexpected run status: . Full run info:

) statusr6   intversionVERSIONsplitrK   rd   r   r|   listr   rP   alljoinr   rg   r   r   r   functionjsonloads	argumentsr   rV   
ValueErrorlenappendr1   dumpsrE   )rT   r   major_versionminor_versionr|   new_messagesanswerrx   actions	tool_callr   argsr:   r;   run_infor#   r6   r   r   r&   r   @  s   
	



z%OpenAIAssistantRunnable._get_responser   r   c                 C  sB   d}|r| j jjjj||d}|jdv }|rt| jd  |s|S NT)r   )in_progressZqueuedi  )rK   rd   r   r   retriever   r   rO   rT   r   r   r  r   r#   r#   r&   r     s   
z%OpenAIAssistantRunnable._wait_for_runc                   s`   |d \}}|  |j|j}t  |jrdd |jjjD   fdd|D }||j|jdS )Nr   c                 S  r   r#   r   r   r#   r#   r&   r     r   zEOpenAIAssistantRunnable._aparse_intermediate_steps.<locals>.<setcomp>c                   r   r   r   r   r   r#   r&   ra     r   zFOpenAIAssistantRunnable._aparse_intermediate_steps.<locals>.<listcomp>r   r   r   r#   r   r&   r     s   
z2OpenAIAssistantRunnable._aparse_intermediate_stepsc                   s>   dd |  D }| jjjjj|d fd| ji|I d H S )Nc                 S  r   r   r#   r   r#   r#   r&   r     r   z8OpenAIAssistantRunnable._acreate_run.<locals>.<dictcomp>r   rM   )r   rL   rd   r   r   rf   rM   r   r#   r#   r&   r     s   z$OpenAIAssistantRunnable._acreate_runc                   s8   dd |  D }| jjjjd| j|d|I d H S )Nc                 S  r   r   r#   r   r#   r#   r&   r     r   zCOpenAIAssistantRunnable._acreate_thread_and_run.<locals>.<dictcomp>r   r#   )r   rL   rd   r   r   rM   r   r#   r#   r&   r     s   z/OpenAIAssistantRunnable._acreate_thread_and_runc                   s  j dkrvdd l t jjdd }t jjdd }|dkp+|dko+|dk| jjjj	j
jddI d H }fdd	|D }| jsI|S d
d	 |D }t fdd|D rfddd |D }t|jjddjjdS j dkr| jsjjjS g }jjjD ]J}|j}	z
tj|	jdd}
W n ty } zd|	j d|	j }t||d }~ww t|
dkrd|
v r|
d }
|t|	j|
|jdjjd q|S tj dd}dj  d| }t|)Nr   r   r   r   r   r   r   c                   r   r#   r   r   r   r#   r&   ra     r   z:OpenAIAssistantRunnable._aget_response.<locals>.<listcomp>c                 S  r   r#   r   r   r#   r#   r&   ra     r   c                 3  r   r   r   r   r   r#   r&   r     r   z9OpenAIAssistantRunnable._aget_response.<locals>.<genexpr>r   c                 s  r   r   r   r   r#   r#   r&   r     r   )r   r   r   r   r   r   Fr   r   r   r   r   r   r   r   r   ) r   r6   r   r   r   r   rL   rd   r   r|   r   r   rP   r   r   r   rg   r   r   r   r   r   r   r   r   rV   r  r  r  r1   r  rE   )rT   r   r  r  r|   r  r  r	  r
  r   r  r:   r;   r  r#   r  r&   _aget_response  s   
	




z&OpenAIAssistantRunnable._aget_responsec                   sR   d}|r'| j jjjj||dI d H }|jdv }|r%t| jd I d H  |s|S r  )	rL   rd   r   r   r  r   asyncior   rO   r  r#   r#   r&   r   (  s   
z&OpenAIAssistantRunnable._await_for_run)r   r   )rV   r   rW   r   rX   rY   rZ   r   rK   r[   r\   r   r   rI   r   )rj   rE   rk   rl   r\   r   r   rm   )rV   r   rW   r   rX   rY   rZ   r   rL   r   r\   r   r   rI   )rt   r   r   rE   )r   rE   r   r   )r   rE   r   rE   r   r   )r   r   r   r   )r   r   r   r   r   r   )r+   r,   r-   r.   r   r<   rK   r/   rL   rO   rP   r   rU   r0   ri   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r#   r#   r#   r&   rI      sH   
 M!`
#
c



O
	


KrI   )r   r3   )r   r>   )rA   rB   r   r    )rA   rB   r   rG   )4
__future__r   r  r   collections.abcr   r   timer   typingr   r   r   r	   r
   Zlangchain_core.agentsr   r   Zlangchain_core.callbacksr   Zlangchain_core.loadr   Zlangchain_core.runnablesr   r   r   Zlangchain_core.toolsr   Z%langchain_core.utils.function_callingr   Zpydanticr   r   r   Ztyping_extensionsr   r   r6   Zopenai.types.beta.threadsr   Z<openai.types.beta.threads.required_action_function_tool_callr   r   r1   r<   r@   rF   rH   r   rm   rE   rI   r#   r#   r#   r&   <module>   sB    



