
    k
i#                     :   d Z ddlmZmZ ddlmZmZ ddlmZm	Z	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 ddlmZmZ ddlmZ ddlmZ ddlm Z  de!de
de"e         e"e         z  de#fdZ$ e de           G d de                      Z%dS )a  This module provides a ValidationNode class that can be used to validate tool calls
in a langchain graph. It applies a pydantic schema to tool_calls in the models' outputs,
and returns a ToolMessage with the validated content. If the schema is not valid, it
returns a ToolMessage with the error message. The ValidationNode can be used in a
StateGraph with a "messages" key. If multiple tool calls are requested, they will be run in parallel.
    )CallableSequence)Anycast)	AIMessage
AnyMessageToolCallToolMessage)RunnableConfig)get_executor_for_config)BaseToolcreate_schema_from_function)is_basemodel_subclass)RunnableCallable)LangGraphDeprecatedSinceV10)	BaseModelValidationError)r   )r   )
deprecatederrorcallschemareturnc                 &    t          |            dS )z"Default error formatting function.z-

Respond after fixing all validation errors.)repr)r   r   r   s      C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/prebuilt/tool_validator.py_default_format_errorr   "   s     5kkJJJJ    zpValidationNode is deprecated. Please use `create_agent` from `langchain.agents` with custom tool error handling.)categoryc                       e Zd ZdZdddddeeee         z  ez           dee	e
ee         gef         dz  dedee         dz  d	df
 fd
Zdee         eeef         z  d	eeef         fdZdee         eeef         z  ded	efdZ xZS )ValidationNodea	  A node that validates all tools requests from the last `AIMessage`.

    It can be used either in `StateGraph` with a `'messages'` key.

    !!! note

        This node does not actually **run** the tools, it only validates the tool calls,
        which is useful for extraction and other use cases where you need to generate
        structured output that conforms to a complex schema without losing the original
        messages and tool IDs (for use in multi-turn conversations).

    Returns:
        (Union[Dict[str, List[ToolMessage]], Sequence[ToolMessage]]): A list of
            `ToolMessage` objects with the validated content or error messages.

    Example:
        ```python title="Example usage for re-prompting the model to generate a valid response:"
        from typing import Literal, Annotated
        from typing_extensions import TypedDict

        from langchain_anthropic import ChatAnthropic
        from pydantic import BaseModel, field_validator

        from langgraph.graph import END, START, StateGraph
        from langgraph.prebuilt import ValidationNode
        from langgraph.graph.message import add_messages

        class SelectNumber(BaseModel):
            a: int

            @field_validator("a")
            def a_must_be_meaningful(cls, v):
                if v != 37:
                    raise ValueError("Only 37 is allowed")
                return v

        builder = StateGraph(Annotated[list, add_messages])
        llm = ChatAnthropic(model="claude-3-5-haiku-latest").bind_tools([SelectNumber])
        builder.add_node("model", llm)
        builder.add_node("validation", ValidationNode([SelectNumber]))
        builder.add_edge(START, "model")

        def should_validate(state: list) -> Literal["validation", "__end__"]:
            if state[-1].tool_calls:
                return "validation"
            return END

        builder.add_conditional_edges("model", should_validate)

        def should_reprompt(state: list) -> Literal["model", "__end__"]:
            for msg in state[::-1]:
                # None of the tool calls were errors
                if msg.type == "ai":
                    return END
                if msg.additional_kwargs.get("is_error"):
                    return "model"
            return END

        builder.add_conditional_edges("validation", should_reprompt)

        graph = builder.compile()
        res = graph.invoke(("user", "Select a number, any number"))
        # Show the retry logic
        for msg in res:
            msg.pretty_print()
        ```
    N
validation)format_errornametagsschemasr"   r#   r$   r   c                   t                                          | j        d||d           |pt          | _        i | _        |D ]G}t          |t                    r|j        t          d|j
         d          t          |j        t                    rt          |j                  s t          d|j
         d|j         d          |j        | j        |j
        <   t          |t                    rJt          |t          t          f          r.t!          t          t                   |          | j        |j        <   t%          |          r!t'          d	|          }|| j        |j        <   )t          d
t          |           d          dS )a  Initialize the ValidationNode.

        Args:
            schemas: A list of schemas to validate the tool calls with. These can be
                any of the following:
                - A pydantic BaseModel class
                - A BaseTool instance (the args_schema will be used)
                - A function (a schema will be created from the function signature)
            format_error: A function that takes an exception, a ToolCall, and a schema
                and returns a formatted error string. By default, it returns the
                exception repr and a message to respond after fixing validation errors.
            name: The name of the node.
            tags: A list of tags to add to the node.
        NF)r#   r$   tracezTool z& does not have an args_schema defined.zVValidation node only works with tools that have a pydantic BaseModel args_schema. Got z with args_schema: .
ValidationzPUnsupported input to ValidationNode. Expected BaseModel, tool or function. Got: )super__init___funcr   _format_errorschemas_by_name
isinstancer   args_schema
ValueErrorr#   typer   
issubclassr   BaseModelV1r   __name__callabler   )selfr%   r"   r#   r$   r   
base_model	__class__s          r   r+   zValidationNode.__init__t   s   . 	T4uMMM)B-B;= 	 	F&(++ %-$SSSS   $&  .v/ABB %U%{U U?E?QU U U   5;4F$V[11FD)) 
jK0/ / 
 9=T)_f8U8U$V_55&!! 8vNN
8B$V_55 vgklrgsgsvvv  -	 	r   inputc                     t          |t                    rd}|}n*|                    dg           x}rd}nt          d          |d         }t          |t                    st          d          ||fS )z*Extract the last AIMessage from the input.listmessagesdictzNo message found in inputz Last message is not an AIMessage)r/   r<   getr1   r   )r7   r:   output_typer=   messages        r   _get_messagezValidationNode._get_message   s     eT"" 	: K"HH:r222X 	: KK8999&rl'9-- 	A?@@@G##r   configc                                           |          \  }}dt          dt          f fd}t          |          5 }g |                    ||j                  }|dk    r|cddd           S d|icddd           S # 1 swxY w Y   dS )z*Validate and run tool calls synchronously.r   r   c           
         j         | d                  }	 t          |t                    r0|                    | d                   }|                                }net          |t
                    r0|                    | d                   }|                                }n t          dt          |           d          t          || d         t          t          | d                             S # t          t          f$ rS}t                              || |          | d         t          t          | d                   ddi	          cY d }~S d }~ww xY w)
Nr#   argszUnsupported schema type: z$. Expected BaseModel or BaseModelV1.id)contentr#   tool_call_idis_errorT)rI   r#   rJ   additional_kwargs)r.   r3   r   model_validatemodel_dump_jsonr4   validatejsonr1   r2   r
   r   strr   ValidationErrorV1r-   )r   r   outputrI   er7   s        r   run_onez%ValidationNode._func.<locals>.run_one   sq   )$v,7Ffi00 	#224<@@F$4466GG44 #__T&\::F$kkmmGG$fDLLfff   ##f!%c4:!6!6   
 $%67   " ..q$??f!%c4:!6!6'14&8	        s   CC1 1EAE
EEr<   Nr=   )rC   r	   r
   r   map
tool_calls)r7   r:   rD   rA   rB   rU   executoroutputss   `       r   r,   zValidationNode._func   s     $0077W	( 	{ 	 	 	 	 	 	4 %V,, 	-BWg.@AABGf$$	- 	- 	- 	- 	- 	- 	- 	-
 #G,	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	- 	-s   %A?/A??BB)r5   
__module____qualname____doc__r   r   r2   r   r   BaseExceptionr	   rQ   r<   r+   r   r>   r   tupler   rC   r   r,   __classcell__)r9   s   @r   r    r    +   sF       
B BR  !%2 2 2(T)_4x?@2 xiI3NO
	2 2 3i$2 
2 2 2 2 2 2h$*%S#X6$	sI~	$ $ $ $ %-*%S#X6%-@N%-	%- %- %- %- %- %- %- %-r   r    N)&r\   collections.abcr   r   typingr   r   langchain_core.messagesr   r   r	   r
   langchain_core.runnablesr   langchain_core.runnables.configr   langchain_core.toolsr   r   langchain_core.utils.pydanticr   langgraph._internal._runnabler   langgraph.warningsr   pydanticr   r   pydantic.v1r4   rR   typing_extensionsr   r]   r2   rQ   r   r     r   r   <module>rm      s    / . . . . . . .       
                 D C C C C C F F F F F F F F ? ? ? ? ? ? : : : : : : : : : : : : / / / / / / / / 0 0 0 0 0 0 < < < < < < ( ( ( ( ( (KK
K Od;//K 		K K K K v(  n- n- n- n- n-% n- n-	 n- n- n-r   