a
    agu                     @  s  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m	Z	m
Z
mZmZ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& erd 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dZ.ddddZ/dddddZ0dd dd!d"Z1eee- e,ed# ed$ f Z2G d%d& d&eee2f Z3dS )'    )annotationsN)JSONDecodeError)sleep)
TYPE_CHECKINGAnyCallableDictListOptionalSequenceTupleTypeUnion)AgentActionAgentFinish)CallbackManager)dumpd)RunnableConfigRunnableSerializableensure_config)BaseTool)convert_to_openai_tool)	BaseModelFieldmodel_validator)Self)ThreadMessage)RequiredActionFunctionToolCallc                   @  s4   e Zd ZU dZded< ded< ed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boolreturnc                 C  s   dS z]Check if the class is serializable by LangChain.

        Returns:
            False
        F clsr&   r&   t/var/www/html/cobodadashboardai.evdpl.com/venv/lib/python3.9/site-packages/langchain/agents/openai_assistant/base.pyis_lc_serializable0   s    z(OpenAIAssistantFinish.is_lc_serializableN__name__
__module____qualname____doc____annotations__classmethodr*   r&   r&   r&   r)   r   %   s
   
r   c                   @  s<   e Zd ZU dZded< ded< ded< ed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  s   dS r%   r&   r'   r&   r&   r)   r*   G   s    z(OpenAIAssistantAction.is_lc_serializableNr+   r&   r&   r&   r)   r2   :   s   
r2   zopenai.OpenAIr#   c               
   C  sr   zdd l } |  W S  ty@ } ztd|W Y d }~n6d }~0  tyl } ztd|W Y d }~n
d }~0 0 d S 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r5   er&   r&   r)   _get_openai_clientQ   s    
r:   zopenai.AsyncOpenAIc               
   C  sr   zdd l } |  W S  ty@ } ztd|W Y d }~n6d }~0  tyl } ztd|W Y d }~n
d }~0 0 d S r4   )r5   AsyncOpenAIr6   r7   r8   r&   r&   r)   _get_openai_async_clienta   s    
r<   z:Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]r"   )toolr$   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	retrievaltype)
isinstancedict)r=   Zassistants_builtin_toolsr&   r&   r)   _is_assistants_builtin_toolq   s    

rA   zDict[str, Any]c                 C  s   t | r| S t| S dS )zConvert a raw function/class to an OpenAI tool.

    Note that OpenAI assistants supports several built-in tools,
    such as "code_interpreter" and "retrieval."
    N)rA   r   )r=   r&   r&   r)   _get_assistants_tool}   s    rB   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ddddZeddddddddd dddZdBddddddd Zedd!ddddd"dd d#d$d%ZdCdddddd&d'Zd(dd)d*d+Zddd,d-d.Zdddd/d0d1Zddd2d3d4Zdddd5d6d7Zd(dd)d8d9Zddd,d:d;Zdddd/d<d=Zddd2d>d?Zdddd5d@dAZdS )D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)rF   r5   rE   rM   r;   )selfr5   rM   r&   r&   r)   validate_async_client   s
    
z-OpenAIAssistantRunnable.validate_async_client)rE   zSequence[Union[BaseTool, dict]]z2Optional[Union[openai.OpenAI, openai.AzureOpenAI]])nameinstructionstoolsmodelrE   kwargsr$   c                K  s@   |pt  }|jjj||dd |D |d}| f |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  s   g | ]}t |qS r&   rB   .0r=   r&   r&   r)   
<listcomp>      z<OpenAIAssistantRunnable.create_assistant.<locals>.<listcomp>rP   rQ   rR   rS   )rG   rE   )r:   beta
assistantscreateid)r(   rP   rQ   rR   rS   rE   rT   	assistantr&   r&   r)   create_assistant   s    
z(OpenAIAssistantRunnable.create_assistantr@   zOptional[RunnableConfig]
OutputType)inputconfigrT   r$   c              
   K  s  t |}tj|d|d|dd}|jt| ||dpF|  d}z| jr|dr| |d }| j	j
jjjf i |}nd|vrd	|d
 |ddg|dd}| ||}nTd|vr| j	j
jjj|d |d
 d	|dd}	| |}n| j	j
jjjf i |}| |j|j}W n4 tyZ }
 z||
 |
W Y d}
~
n
d}
~
0 0 z| |}W n< ty }
 z"|j|
| d |
W Y d}
~
nd}
~
0 0 || |S d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.
            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rP   intermediate_stepsr!   usercontentmessage_metadatarolerl   rf   thread_metadatamessagesrf   r    rl   ro   rf   Nrf   )r   r   	configuregeton_chain_startr   get_namerJ   _parse_intermediate_stepsrE   r[   threadsrunssubmit_tool_outputs_create_thread_and_runrr   r]   _create_run_wait_for_runr^   r!   BaseExceptionon_chain_error_get_responser@   on_chain_endrN   rb   rc   rT   Zcallback_managerZrun_managertool_outputsrunthread_r9   responser&   r&   r)   invoke  sX    !


zOpenAIAssistantRunnable.invoke)rF   z<Optional[Union[openai.AsyncOpenAI, openai.AsyncAzureOpenAI]])rP   rQ   rR   rS   rF   rT   r$   c          	        sJ   |pt  }dd |D }|jjj||||dI dH }| f |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  s   g | ]}t |qS r&   rU   rV   r&   r&   r)   rX     rY   z=OpenAIAssistantRunnable.acreate_assistant.<locals>.<listcomp>rZ   N)rG   rF   )r<   r[   r\   r]   r^   )	r(   rP   rQ   rR   rS   rF   rT   Zopenai_toolsr_   r&   r&   r)   acreate_assistanto  s    
z)OpenAIAssistantRunnable.acreate_assistantc              
     s  |pi }t j|d|d|dd}|jt| ||dpF|  d}z| jr|dr| |d I dH }| jj	j
jjf i |I dH }nd	|vrd
|d |ddg|dd}| ||I dH }nhd|vr| jj	j
jj|d	 |d d
|ddI dH }	| |I dH }n| jj	j
jjf i |I dH }| |j|jI dH }W n4 ty }
 z||
 |
W Y d}
~
n
d}
~
0 0 z| |}W n< ty }
 z"|j|
| d |
W Y d}
~
nd}
~
0 0 || |S d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]].
        rd   re   rf   rg   rh   ri   rj   Nr!   rk   rl   rm   rn   rp   rq   r    rs   rt   )r   ru   rv   rw   r   rx   rJ   _aparse_intermediate_stepsrF   r[   rz   r{   r|   _acreate_thread_and_runrr   r]   _acreate_run_await_for_runr^   r!   r   r   r   r@   r   r   r&   r&   r)   ainvoke  s`    #




zOpenAIAssistantRunnable.ainvokez'List[Tuple[OpenAIAssistantAction, str]])rj   r$   c                   sb   |d \}}|  |j|j}t  |jr<dd |jjjD   fdd|D }||j|jd}|S )Nc                 S  s   h | ]
}|j qS r&   r^   rW   Ztcr&   r&   r)   	<setcomp>  s   zDOpenAIAssistantRunnable._parse_intermediate_steps.<locals>.<setcomp>c                   s*   g | ]"\}}|j  v rt||j d qS )outputr3   r3   r   rW   actionr   Zrequired_tool_call_idsr&   r)   rX     s   
zEOpenAIAssistantRunnable._parse_intermediate_steps.<locals>.<listcomp>r   r    r!   r   r    r!   setrequired_actionr|   
tool_callsrN   rj   Zlast_actionZlast_outputr   r   r|   r&   r   r)   ry     s    
z1OpenAIAssistantRunnable._parse_intermediate_steps)rb   r$   c                 C  s6   dd |  D }| jjjjj|d fd| ji|S )Nc                 S  s   i | ]\}}|d v r||qS )
rQ   rS   rR   Zadditional_instructionsparallel_tool_callstop_ptemperaturemax_completion_tokensmax_prompt_tokensrun_metadatar&   rW   kvr&   r&   r)   
<dictcomp>  s
   z7OpenAIAssistantRunnable._create_run.<locals>.<dictcomp>r!   rG   )itemsrE   r[   rz   r{   r]   rG   rN   rb   paramsr&   r&   r)   r~     s    z#OpenAIAssistantRunnable._create_run)rb   r   r$   c                 C  s4   dd |  D }| jjjjf | j|d|}|S )Nc                 S  s   i | ]\}}|d v r||qS )	rQ   rS   rR   r   r   r   r   r   r   r&   r   r&   r&   r)   r      s
   zBOpenAIAssistantRunnable._create_thread_and_run.<locals>.<dictcomp>rG   r   )r   rE   r[   rz   create_and_runrG   rN   rb   r   r   r   r&   r&   r)   r}     s    z.OpenAIAssistantRunnable._create_thread_and_run)r   r$   c                   s  j dkrdd l t jjdd }t jjdd }|dkpT|dkoT|dk| jjjj	j
jdd}fdd	|D }| js|S d
d	 |D }t fdd|D rd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}	ztj|	jdd}
W n@ tyn } z&td|	j d|	j |W Y d }~n
d }~0 0 t|
dkrd|
v r|
d }
|t|	j|
|jdjjd q|S tj dd}tdj  d| dd S )N	completedr   .      ascorderc                   s   g | ]}|j  jkr|qS r&   r    r^   rW   msgr   r&   r)   rX   F  rY   z9OpenAIAssistantRunnable._get_response.<locals>.<listcomp>c                 S  s   g | ]}|j D ]}|qqS r&   rl   rW   r   Zmsg_contentr&   r&   r)   rX   I  s   c                 3  s6   | ].}rt | jjjjnt | jjjjV  qd S Nr?   typesr[   rz   ZTextContentBlockZMessageContentTextrW   rl   r5   version_gte_1_14r&   r)   	<genexpr>L  s   	
z8OpenAIAssistantRunnable._get_response.<locals>.<genexpr>
c                 s  s   | ]}|j jV  qd S r   textvaluer   r&   r&   r)   r   W  rY   r   r!   r     Zreturn_valueslogr    r!   requires_actionFstrict*Received invalid JSON function arguments:  for function __arg1r=   Z
tool_inputr3   r   r    r!      indentUnexpected run status: . Full run info:

)) statusr5   intversionVERSIONsplitrE   r[   rz   rr   listr!   rJ   alljoinr   r^   r   r|   r   functionjsonloads	argumentsr   
ValueErrorrP   lenappendr2   dumpsr@   rN   r   major_versionminor_versionrr   Znew_messagesZansweractionsZ	tool_callr   argsr9   Zrun_infor&   r5   r   r   r)   r   7  s    
	


z%OpenAIAssistantRunnable._get_response)r    r!   r$   c                 C  s@   d}|r<| j jjjj||d}|jdv }|rt| jd  q|S NT)r!   )in_progressZqueuedi  )rE   r[   rz   r{   retriever   r   rI   rN   r    r!   r   r   r&   r&   r)   r     s    
z%OpenAIAssistantRunnable._wait_for_runc                   sh   |d \}}|  |j|jI d H }t  |jrBdd |jjjD   fdd|D }||j|jd}|S )Nr   c                 S  s   h | ]
}|j qS r&   r   r   r&   r&   r)   r     s   zEOpenAIAssistantRunnable._aparse_intermediate_steps.<locals>.<setcomp>c                   s*   g | ]"\}}|j  v rt||j d qS r   r   r   r   r&   r)   rX     s   
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  s   i | ]\}}|d v r||qS r   r&   r   r&   r&   r)   r     s
   z8OpenAIAssistantRunnable._acreate_run.<locals>.<dictcomp>r!   rG   )r   rF   r[   rz   r{   r]   rG   r   r&   r&   r)   r     s    z$OpenAIAssistantRunnable._acreate_runc                   s:   dd |  D }| jjjjf | j|d|I d H }|S )Nc                 S  s   i | ]\}}|d v r||qS r   r&   r   r&   r&   r)   r     s
   zCOpenAIAssistantRunnable._acreate_thread_and_run.<locals>.<dictcomp>r   )r   rF   r[   rz   r   rG   r   r&   r&   r)   r     s    z/OpenAIAssistantRunnable._acreate_thread_and_runc                   s  j dkrdd l t jjdd }t jjdd }|dkpT|dkoT|dk| jjjj	j
jddI d H }fdd	|D }| js|S d
d	 |D }t fdd|D rd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}	ztj|	jdd}
W n@ tyt } z&td|	j d|	j |W Y d }~n
d }~0 0 t|
dkrd|
v r|
d }
|t|	j|
|jdjjd q|S tj dd}tdj  d| dd S )Nr   r   r   r   r   r   r   c                   s   g | ]}|j  jkr|qS r&   r   r   r   r&   r)   rX     rY   z:OpenAIAssistantRunnable._aget_response.<locals>.<listcomp>c                 S  s   g | ]}|j D ]}|qqS r&   r   r   r&   r&   r)   rX     s   c                 3  s6   | ].}rt | jjjjnt | jjjjV  qd S r   r   r   r   r&   r)   r     s   	
z9OpenAIAssistantRunnable._aget_response.<locals>.<genexpr>r   c                 s  s   | ]}|j jV  qd S r   r   r   r&   r&   r)   r     rY   r   r   r   r   Fr   r   r   r   r   r   r   r   r   r   ) r   r5   r   r   r   r   rF   r[   rz   rr   r   r!   rJ   r   r   r   r^   r   r|   r   r   r   r   r   r   r   rP   r   r   r2   r   r@   r   r&   r   r)   _aget_response  s    
	


z&OpenAIAssistantRunnable._aget_responsec                   sN   d}|rJ| j jjjj||dI d H }|jdv }|rt| jd I d H  q|S r   )	rF   r[   rz   r{   r   r   asyncior   rI   r   r&   r&   r)   r     s    
z&OpenAIAssistantRunnable._await_for_run)N)N)r,   r-   r.   r/   r   r:   rE   r0   rF   rI   rJ   r   rO   r1   r`   r   r   r   ry   r~   r}   r   r   r   r   r   r   r   r&   r&   r&   r)   rC      s8   
M " X
 $ ^K	KrC   )4
__future__r   r   r   r   timer   typingr   r   r   r   r	   r
   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   r5   Zopenai.types.beta.threadsr   Z<openai.types.beta.threads.required_action_function_tool_callr   r   r2   r:   r<   rA   rB   ra   rC   r&   r&   r&   r)   <module>   s>   0