o
    {qi,                     @  s   d Z ddlmZ ddlZddlZddlZddlmZ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mZ dd
lmZ ddlmZ ddlmZ e
ddddG dd deZdS )zCChain that interprets a prompt and executes python code to do math.    )annotationsN)AnyOptional)
deprecated)AsyncCallbackManagerForChainRunCallbackManagerForChainRun)BaseLanguageModel)BasePromptTemplate)
ConfigDictmodel_validator)ChainLLMChain)PROMPTz0.2.13zThis class 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.llm_math.base.LLMMathChain.htmlz1.0)ZsincemessageZremovalc                   @  s   e Zd ZU dZded< dZded< 	 eZded< 	 d	Zd
ed< dZ	d
ed< e
dddZedded7ddZed8ddZed8ddZd9dd Zd:d%d&Zd;d(d)Z	d<d=d,d-Z	d<d>d/d0Zed?d1d2Zeefd@d5d6ZdS )ALLMMathChaina  Chain that interprets a prompt and executes python code to do math.

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

        - Uses LLM tool calling features;
        - Support for both token-by-token and step-by-step streaming;
        - Support for checkpointing and memory of chat history;
        - Easier to modify or extend (e.g., with additional tools, structured responses, etc.)

        Install LangGraph with:

        .. code-block:: bash

            pip install -U langgraph

        .. code-block:: python

            import math
            from typing import Annotated, Sequence

            from langchain_core.messages import BaseMessage
            from langchain_core.runnables import RunnableConfig
            from langchain_core.tools import tool
            from langchain_openai import ChatOpenAI
            from langgraph.graph import END, StateGraph
            from langgraph.graph.message import add_messages
            from langgraph.prebuilt.tool_node import ToolNode
            import numexpr
            from typing_extensions import TypedDict

            @tool
            def calculator(expression: str) -> str:
                """Calculate expression using Python's numexpr library.

                Expression should be a single line mathematical expression
                that solves the problem.

                Examples:
                    "37593 * 67" for "37593 times 67"
                    "37593**(1/5)" for "37593^(1/5)"
                """
                local_dict = {"pi": math.pi, "e": math.e}
                return str(
                    numexpr.evaluate(
                        expression.strip(),
                        global_dict={},  # restrict access to globals
                        local_dict=local_dict,  # add common mathematical functions
                    )
                )

            llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
            tools = [calculator]
            llm_with_tools = llm.bind_tools(tools, tool_choice="any")

            class ChainState(TypedDict):
                """LangGraph state."""

                messages: Annotated[Sequence[BaseMessage], add_messages]

            async def acall_chain(state: ChainState, config: RunnableConfig):
                last_message = state["messages"][-1]
                response = await llm_with_tools.ainvoke(state["messages"], config)
                return {"messages": [response]}

            async def acall_model(state: ChainState, config: RunnableConfig):
                response = await llm.ainvoke(state["messages"], config)
                return {"messages": [response]}

            graph_builder = StateGraph(ChainState)
            graph_builder.add_node("call_tool", acall_chain)
            graph_builder.add_node("execute_tool", ToolNode(tools))
            graph_builder.add_node("call_model", acall_model)
            graph_builder.set_entry_point("call_tool")
            graph_builder.add_edge("call_tool", "execute_tool")
            graph_builder.add_edge("execute_tool", "call_model")
            graph_builder.add_edge("call_model", END)
            chain = graph_builder.compile()

        .. code-block:: python

            example_query = "What is 551368 divided by 82"

            events = chain.astream(
                {"messages": [("user", example_query)]},
                stream_mode="values",
            )
            async for event in events:
                event["messages"][-1].pretty_print()

        .. code-block:: none

            ================================ Human Message =================================

            What is 551368 divided by 82
            ================================== Ai Message ==================================
            Tool Calls:
            calculator (call_MEiGXuJjJ7wGU4aOT86QuGJS)
            Call ID: call_MEiGXuJjJ7wGU4aOT86QuGJS
            Args:
                expression: 551368 / 82
            ================================= Tool Message =================================
            Name: calculator

            6724.0
            ================================== Ai Message ==================================

            551368 divided by 82 equals 6724.

    Example:
        .. code-block:: python

            from langchain.chains import LLMMathChain
            from langchain_community.llms import OpenAI
            llm_math = LLMMathChain.from_llm(OpenAI())
    r   	llm_chainNzOptional[BaseLanguageModel]llmr	   promptquestionstr	input_keyanswer
output_keyTZforbid)Zarbitrary_types_allowedextrabefore)modevaluesdictreturnr   c              
   C  s   zdd l }W n ty } zd}t||d }~ww d|v r?tjddd d|vr?|d d ur?|dt}t|d |d	|d< |S )
Nr   zXLLMMathChain requires the numexpr package. Please install it with `pip install numexpr`.r   zDirectly instantiating an LLMMathChain with an llm is deprecated. Please instantiate with llm_chain argument or using the from_llm class method.   )
stacklevelr   r   r   r   )numexprImportErrorwarningswarngetr   r   )clsr   r#   emsgr    r+   e/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/langchain/chains/llm_math/base.pyraise_deprecation   s"   
zLLMMathChain.raise_deprecation	list[str]c                 C     | j gS )z2Expect input key.

        :meta private:
        )r   selfr+   r+   r,   
input_keys      zLLMMathChain.input_keysc                 C  r/   )z3Expect output key.

        :meta private:
        )r   r0   r+   r+   r,   output_keys   r3   zLLMMathChain.output_keys
expressionc              
   C  sv   dd l }ztjtjd}t|j| i |d}W n ty3 } zd| d| d}t||d }~ww t	
dd|S )	Nr   )pir)   )Zglobal_dict
local_dictzLLMMathChain._evaluate("z") raised error: z4. Please try again with a valid numerical expressionz^\[|\]$ )r#   mathr6   r)   r   evaluatestrip	Exception
ValueErrorresub)r1   r5   r#   r7   outputr)   r*   r+   r+   r,   _evaluate_expression   s"   
z!LLMMathChain._evaluate_expression
llm_outputrun_managerr   dict[str, str]c                 C  s   |j |d| jd | }td|tj}|r7|d}| |}|j d| jd |j |d| jd d| }n|d	r?|}nd	|v rMd|	d	d
  }n	d| }t
|| j|iS Ngreen)colorverbosez^```text(.*?)```   z	
Answer: )rH   yellowzAnswer: zAnswer:zunknown format from LLM: on_textrH   r;   r>   searchDOTALLgrouprA   
startswithsplitr=   r   r1   rB   rC   Z
text_matchr5   r@   r   r*   r+   r+   r,   _process_llm_result   s    





z LLMMathChain._process_llm_resultr   c                   s   |j |d| jdI d H  | }td|tj}|rA|d}| |}|j d| jdI d H  |j |d| jdI d H  d| }n|d	rI|}nd	|v rWd|	d	d
  }n	d| }t
|| j|iS rE   rL   rS   r+   r+   r,   _aprocess_llm_result   s"   





z!LLMMathChain._aprocess_llm_resultinputs$Optional[CallbackManagerForChainRun]c                 C  sF   |pt  }||| j  | jj|| j dg| d}| ||S Nz	```output)r   stop	callbacks)r   get_noop_managerrM   r   r   Zpredict	get_childrT   r1   rV   rC   Z_run_managerrB   r+   r+   r,   _call  s   zLLMMathChain._call)Optional[AsyncCallbackManagerForChainRun]c                   sZ   |pt  }||| j I d H  | jj|| j dg| dI d H }| ||I d H S rX   )r   r[   rM   r   r   Zapredictr\   rU   r]   r+   r+   r,   _acall  s   zLLMMathChain._acallc                 C  s   dS )NZllm_math_chainr+   r0   r+   r+   r,   _chain_type+  s   zLLMMathChain._chain_typer   kwargsc                 K  s   t ||d}| dd|i|S )Nr"   r   r+   r   )r(   r   r   rb   r   r+   r+   r,   from_llm/  s   zLLMMathChain.from_llm)r   r   r   r   )r   r.   )r5   r   r   r   )rB   r   rC   r   r   rD   )rB   r   rC   r   r   rD   )N)rV   rD   rC   rW   r   rD   )rV   rD   rC   r_   r   rD   )r   r   )r   r   r   r	   rb   r   r   r   )__name__
__module____qualname____doc____annotations__r   r   r   r   r   r
   Zmodel_configr   classmethodr-   propertyr2   r4   rA   rT   rU   r^   r`   ra   rc   r+   r+   r+   r,   r      s@   
 
u


r   )rg   
__future__r   r9   r>   r%   typingr   r   Zlangchain_core._apir   Zlangchain_core.callbacksr   r   Zlangchain_core.language_modelsr   Zlangchain_core.promptsr	   Zpydanticr
   r   Zlangchain.chains.baser   Zlangchain.chains.llmr   Z langchain.chains.llm_math.promptr   r   r+   r+   r+   r,   <module>   s(    	