
    KKi#                        S r SSKJrJr  SSKJrJr  SSKJrJ	r	J
r
Jr  SSKJr  SSKJr  SSKJrJr  SSKJr  SS	KJr  SS
KJr  SSKJrJr  SSKJr  SSKJr  SSKJ r   S\!S\
S\"\   \"\   -  S\#4S jr$\ " S\S9 " S S\5      5       r%g)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                     [        U 5       S3$ )z"Default error formatting function.z-

Respond after fixing all validation errors.)repr)r   r   r   s      c/var/www/html/dynamic-report/venv/lib/python3.13/site-packages/langgraph/prebuilt/tool_validator.py_default_format_errorr   "   s     5k]IJJ    zpValidationNode is deprecated. Please use `create_agent` from `langchain.agents` with custom tool error handling.)categoryc                      ^  \ rS rSrSrSSSS.S\\\\   -  \	-     S\	\
\\\   /\4   S-  S\S	\\   S-  S
S4
U 4S jjjrS\\   \\\4   -  S
\\\4   4S jrS\\   \\\4   -  S\S
\4S jrSrU =r$ )ValidationNode+   a2	  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U ]  U R                  SX4SS9  U=(       d    [        U l        0 U l        U GHp  n[        U[        5      (       a  UR                  c  [        SUR                   S35      e[        UR                  [        5      (       a  [        UR                  5      (       d&  [        SUR                   SUR                   S35      eUR                  U R
                  UR                  '   M  [        U[        5      (       aL  [        U[        [        45      (       a1  [!        [        [           U5      U R
                  UR"                  '   GM$  [%        U5      (       a'  ['        S	U5      nX`R
                  UR"                  '   GM[  [        S
[        U5       S35      e   g)at  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,   ValidationNode.__init__t   s~   . 	TuM)B-B;=F&(++%%-$},RS  $&& .v/A/ABB$%{{m+>v?Q?Q>RRSU  5;4F4F$$V[[1FD))jK0/ / 9=T)_f8U$$V__5&!!8vN
8B$$V__5 fgklrgsfttuv - r   inputc                     [        U[        5      (       a  SnUnO'UR                  S/ 5      =n(       a  SnO[        S5      eUS   n[        U[        5      (       d  [        S5      eX$4$ )z*Extract the last AIMessage from the input.listmessagesdictzNo message found in inputz Last message is not an AIMessage)r0   r>   getr2   r   )r8   r<   output_typer?   messages        r   _get_messageValidationNode._get_message   sm     eT"" K"H:r22X2 K899&rl'9--?@@##r   configc                   ^  T R                  U5      u  p4S[        S[        4U 4S jjn[        U5       n/ UR	                  XTR
                  5      QnUS:X  a  UsSSS5        $ SU0sSSS5        $ ! , (       d  f       g= f)z*Validate and run tool calls synchronously.r   r   c           
        > TR                   U S      n [        U[        5      (       a%  UR                  U S   5      nUR	                  5       nOR[        U[
        5      (       a%  UR                  U S   5      nUR                  5       nO[        S[        U5       S35      e[        UU S   [        [        U S   5      S9$ ! [        [        4 a<  n[        TR                  X@U5      U S   [        [        U S   5      SS0S	9s S nA$ S nAff = f)
Nr$   argszUnsupported schema type: z$. Expected BaseModel or BaseModelV1.id)contentr$   tool_call_idis_errorT)rL   r$   rM   additional_kwargs)r/   r4   r   model_validatemodel_dump_jsonr5   validatejsonr2   r3   r
   r   strr   ValidationErrorV1r.   )r   r   outputrL   er8   s        r   run_one%ValidationNode._func.<locals>.run_one   s   ))$v,7Ffi00#224<@F$446G44#__T&\:F$kkmG$3DL>Aef  ##f!%c4:!6 
 $%67 " ..q?f!%c4:!6'14&8	 s   B*C   D1DDDr>   Nr?   )rE   r	   r
   r   map
tool_calls)r8   r<   rG   rC   rD   rX   executoroutputss   `       r   r-   ValidationNode._func   sy      $007	( 	{ 	4 %V,BW.@.@ABGf$ -,
 #G, -,,s   %A0#A00
A>)r.   r/   )r6   
__module____qualname____firstlineno____doc__r   r   r3   r   r   BaseExceptionr	   rT   r>   r,   r   r@   r   tupler   rE   r   r-   __static_attributes____classcell__)r:   s   @r   r    r    +   s    
BR  !%2(T)_4x?@2 xiI3NO
	2 2 3i$2 
2 2h$*%S#X6$	sI~	$ %-*%S#X6%-@N%-	%- %-r   r    N)&rb   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.v1r5   rU   typing_extensionsr   rc   r3   rT   r   r     r   r   <module>rt      s    /
  D F ? : : / 0 < (KK
K Od;//K 		K v(n-% n-	n-r   