
    @'h(              	           d Z ddl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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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e   f   de"fdZ# G d de       Z$y)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 or in a MessageGraph. If multiple tool calls are
requested, they will be run in parallel.
    )	AnyCallableDictOptionalSequenceTupleTypeUnioncast)	AIMessage
AnyMessageToolCallToolMessage)RunnableConfig)get_executor_for_config)BaseToolcreate_schema_from_function)is_basemodel_subclass)	BaseModelValidationError)r   )r   )RunnableCallableerrorcallschemareturnc                     t        |        dS )z"Default error formatting function.z-

Respond after fixing all validation errors.)repr)r   r   r   s      h/home/kushmeetdev/Regenta/Chatbot/venv/lib/python3.12/site-packages/langgraph/prebuilt/tool_validator.py_default_format_errorr   (   s     5k]IJJ    c                        e Zd ZdZdddddeeeee   e	f      de
e	eeee   gef      dede
ee      d	df
 fd
Zdeee   eeef   f   d	eeef   fdZdeee   eeef   f   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 or in MessageGraph.

    !!! 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).

    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.

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

    Examples:
        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()
        ================================ Human Message =================================
        Select a number, any number
        ================================== Ai Message ==================================
        [{'id': 'toolu_01JSjT9Pq8hGmTgmMPc6KnvM', 'input': {'a': 42}, 'name': 'SelectNumber', 'type': 'tool_use'}]
        Tool Calls:
        SelectNumber (toolu_01JSjT9Pq8hGmTgmMPc6KnvM)
        Call ID: toolu_01JSjT9Pq8hGmTgmMPc6KnvM
        Args:
            a: 42
        ================================= Tool Message =================================
        Name: SelectNumber
        ValidationError(model='SelectNumber', errors=[{'loc': ('a',), 'msg': 'Only 37 is allowed', 'type': 'value_error'}])
        Respond after fixing all validation errors.
        ================================== Ai Message ==================================
        [{'id': 'toolu_01PkxSVxNxc5wqwCPW1FiSmV', 'input': {'a': 37}, 'name': 'SelectNumber', 'type': 'tool_use'}]
        Tool Calls:
        SelectNumber (toolu_01PkxSVxNxc5wqwCPW1FiSmV)
        Call ID: toolu_01PkxSVxNxc5wqwCPW1FiSmV
        Args:
            a: 37
        ================================= Tool Message =================================
        Name: SelectNumber
        {"a": 37}

    N
validation)format_errornametagsschemasr$   r%   r&   r   c                   t         |   | j                  d ||d       |xs t        | _        i | _        |D ]O  }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              rFt        |t        t        f      r0t!        t"        t           |      | j
                  |j$                  <   t'        |      r't)        d|      }|| j
                  |j$                  <   :t        d	t        |       d       y )
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   r	   __name__callabler   )selfr'   r$   r%   r&   r   
base_model	__class__s          r   r-   zValidationNode.__init__   sq    	T4uM)B-B;= 	F&(+%%-$},RS  $&&.v/A/A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                     t        |t              rd}|}n"|j                  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)r1   r>   getr3   r   )r9   r<   output_typer?   messages        r   _get_messagezValidationNode._get_message   si     eT" K"H:r22X2 K899&rl'9-?@@G##r    configc                       j                  |      \  }}dt        dt        f fd}t        |      5 }g |j	                  ||j
                        }|dk(  r|cddd       S d|icddd       S # 1 sw Y   yxY w)z*Validate and run tool calls synchronously.r   r   c           
         j                   | d      }	 t        |t              r%|j                  | d         }|j	                         }nMt        |t
              r%|j                  | d         }|j                         }nt        dt        |       d      t        || d   t        t        | d               S # t        t        f$ r@}t        j                  || |      | 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)rK   r%   rL   additional_kwargs)r0   r5   r   model_validatemodel_dump_jsonr6   validatejsonr3   r4   r   r   strr   ValidationErrorV1r/   )r   r   outputrK   er9   s        r   run_onez%ValidationNode._func.<locals>.run_one   s   ))$v,7Ffi0#224<@F$446G4#__T&\:F$kkmG$3DL>Aef  ##f!%c4:!6 
 $%67 " ..q$?f!%c4:!6'14&8	 s   B#B9 9D5D=DDr>   Nr?   )rE   r   r   r   map
tool_calls)r9   r<   rF   rC   rD   rW   executoroutputss   `       r   r.   zValidationNode._func   s      $007W	( 	{ 	4 %V, 	-BWg.@.@ABGf$	- 	-
 #G,	- 	- 	-s   %A/"A//A8)r7   
__module____qualname____doc__r   r
   r   r	   r   r   r   BaseExceptionr   rS   r>   r-   r   r@   r   r   r   rE   r   r.   __classcell__)r;   s   @r   r"   r"   1   s    kf  $(%%$y/8 CDE% mXtI?DE
	% % tCy!% 
%N$4
+T#s(^;<$	sI~	$ %-4
+T#s(^;<%-FT%-	%-r    r"   N)%r^   typingr   r   r   r   r   r   r	   r
   r   langchain_core.messagesr   r   r   r   langchain_core.runnablesr   langchain_core.runnables.configr   langchain_core.toolsr   r   langchain_core.utils.pydanticr   pydanticr   r   pydantic.v1r6   rT   langgraph.utils.runnabler   r_   rS   r   r"    r    r   <module>rk      s   
 
 
  D F ? / 0 < 5KK
K $y/4#445K 		KJ-% J-r    