
    ghZ                       d Z ddlmZ ddl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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mZ erdd
lmZ ddlmZ ddlm Z!  G d de          Z" G d de          Z#d5dZ$ G d de          Z% G d de          Z& G d de          Z' G d de
          Z(e G d d                      Z) G d  d!e
          Z*d6d%Z+d&d'd7d+Z,e G d, d-                      Z-d8d9d3Z.d8d9d4Z/dS ):zGraph used in Runnables.    )annotationsN)defaultdict)	dataclassfield)Enum)	TYPE_CHECKINGAnyCallable
NamedTupleOptionalProtocol	TypedDictUnionoverload)UUIDuuid4)_IgnoreUnserializableis_basemodel_subclass)Sequence)	BaseModelRunnablec                      e Zd ZdZddZdS )Stringifiablez7Protocol for objects that can be converted to a string.returnstrc                    dS )zConvert the object to a string.N selfs    [/var/www/FlaskApp/flask-venv/lib/python3.11/site-packages/langchain_core/runnables/graph.py__str__zStringifiable.__str__#   s          Nr   r   )__name__
__module____qualname____doc__r"   r   r#   r!   r   r       s.        AA. . . . . .r#   r   c                  *    e Zd ZU dZded<   	 ded<   dS )
LabelsDictz4Dictionary of labels for nodes and edges in a graph.zdict[str, str]nodesedgesNr%   r&   r'   r(   __annotations__r   r#   r!   r*   r*   '   s3         >>r#   r*   valuer   r   boolc                J    	 t          |            n# t          $ r Y dS w xY wdS )zCheck if a string is a valid UUID.

    Args:
        value: The string to check.

    Returns:
        True if the string is a valid UUID, False otherwise.
    FT)r   
ValueError)r/   s    r!   is_uuidr3   0   s;    U   uu4s    
  c                  T    e Zd ZU dZded<   ded<   dZded<   dZd	ed
<   dddddZdS )EdgezEdge in a graph.

    Parameters:
        source: The source node id.
        target: The target node id.
        data: Optional data associated with the edge. Defaults to None.
        conditional: Whether the edge is conditional. Defaults to False.
    r   sourcetargetNOptional[Stringifiable]dataFr0   conditionalr6   r7   Optional[str]r   c               X    t          |p| j        |p| j        | j        | j                  S )a/  Return a copy of the edge with optional new source and target nodes.

        Args:
            source: The new source node id. Defaults to None.
            target: The new target node id. Defaults to None.

        Returns:
            A copy of the edge with the new source and target nodes.
        r6   r7   r9   r:   )r5   r6   r7   r9   r:   )r    r6   r7   s      r!   copyz	Edge.copyO   s:     (T[(T[(	
 
 
 	
r#   )r6   r<   r7   r<   r   r5   )r%   r&   r'   r(   r.   r9   r:   r?   r   r#   r!   r5   r5   @   s{           KKKKKK$(D((((K *.t
 
 
 
 
 
 
 
r#   r5   c                  L    e Zd ZU dZded<   ded<   ded<   ded<   d	d	d
ddZd	S )NodezNode in a graph.

    Parameters:
        id: The unique identifier of the node.
        name: The name of the node.
        data: The data of the node.
        metadata: Optional metadata for the node. Defaults to None.
    r   idname*Union[type[BaseModel], RunnableType, None]r9   Optional[dict[str, Any]]metadataNrB   rC   r<   r   c               X    t          |p| j        |p| j        | j        | j                  S )a  Return a copy of the node with optional new id and name.

        Args:
            id: The new node id. Defaults to None.
            name: The new node name. Defaults to None.

        Returns:
            A copy of the node with the new id and name.
        )rB   rC   r9   rF   )rA   rB   rC   r9   rF   )r    rB   rC   s      r!   r?   z	Node.copyr   s8     }TW"]	
 
 
 	
r#   )rB   r<   rC   r<   r   rA   )r%   r&   r'   r(   r.   r?   r   r#   r!   rA   rA   c   so           GGGIII4444&&&&*.d 
 
 
 
 
 
 
 
r#   rA   c                  (    e Zd ZU dZded<   ded<   dS )BranchzBranch in a graph.

    Parameters:
        condition: A callable that returns a string representation of the condition.
        ends: Optional dictionary of end node ids for the branches. Defaults
            to None.
    zCallable[..., str]	conditionzOptional[dict[str, str]]endsNr-   r   r#   r!   rJ   rJ      s6           "!!!""""""r#   rJ   c                  B    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdS )
CurveStylez5Enum for different curve styles supported by Mermaid.basisbumpXbumpYcardinal
catmullRomlinear	monotoneX	monotoneYnaturalstep	stepAfter
stepBeforeN)r%   r&   r'   r(   BASISBUMP_XBUMP_YCARDINALCATMULL_ROMLINEAR
MONOTONE_X
MONOTONE_YNATURALSTEP
STEP_AFTERSTEP_BEFOREr   r#   r!   rN   rN      sP        ??EFFHKFJJGDJKKKr#   rN   c                  >    e Zd ZU dZdZded<   dZded<   dZded<   d	S )

NodeStylesaC  Schema for Hexadecimal color codes for different node types.

    Parameters:
        default: The default color code. Defaults to "fill:#f2f0ff,line-height:1.2".
        first: The color code for the first node. Defaults to "fill-opacity:0".
        last: The color code for the last node. Defaults to "fill:#bfb6fc".
    zfill:#f2f0ff,line-height:1.2r   defaultzfill-opacity:0firstzfill:#bfb6fclastN)r%   r&   r'   r(   ri   r.   rj   rk   r   r#   r!   rh   rh      sQ           2G1111!E!!!!Dr#   rh   c                      e Zd ZdZdZdZdS )MermaidDrawMethodz5Enum for different draw methods supported by Mermaid.	pyppeteerapiN)r%   r&   r'   r(   	PYPPETEERAPIr   r#   r!   rm   rm      s        ??I
CCCr#   rm   rB   r9   rD   c                    ddl m} t          |           r|| S t          ||          r|                                n|j        }|                    d          s|n	|dd         S )zConvert the data of a node to a string.

    Args:
        id: The node id.
        data: The node data.

    Returns:
        A string representation of the data.
    r   r   Nr      )langchain_core.runnables.baser   r3   
isinstanceget_namer%   
startswith)rB   r9   r   data_strs       r!   node_data_strry      st     7666662;; $,	",T8"<"<Ot}}$-H#..z::L88Lr#   Fwith_schemasnoder{   %dict[str, Union[str, dict[str, Any]]]c                  ddl m} ddlm}m} | j        i }n$t          | j        |          r8d| j                                        t          | j	        | j                  dd}nt          | j        |          r5d || j                  d         t          | j	        | j                  dd}nt          j        | j                  rWt          | j                  rC|r#d	| j                            t          
          dnd	t          | j	        | j                  d}ndt          | j	        | j                  d}| j        
| j        |d<   |S )a8  Convert the data of a node to a JSON-serializable format.

    Args:
        node: The node to convert.
        with_schemas: Whether to include the schema of the data if
            it is a Pydantic model. Defaults to False.

    Returns:
        A dictionary with the type of the data and the data itself.
    r   )to_json_not_implemented)r   RunnableSerializableNrunnablerG   )typer9   rB   schema)schema_generatorunknownrF   ) langchain_core.load.serializabler   rt   r   r   r9   ru   lc_idry   rB   inspectisclassr   model_json_schemar   rF   )r|   r{   r   r   r   jsons         r!   node_data_jsonr      s    IHHHHHLLLLLLLLy!	DI3	4	4 "
ioo''%dgty99 
 
 
DIx	(	( 
--di88>%dgty99 
 
 
	#	# 
(=di(H(H 
 
 	33%: 4     !%dgty99  	 !$'4955
 
 } =ZKr#   c                     e Zd ZU dZ ee          Zded<    ee          Z	ded<   dddTdZ
dUdZdVdZ	 dWdddXdZdYdZ	 	 dZd[d#Zd$d%d\d)Zd]d*Zd^d,Zd^d-Zd_d.Zd_d/ZdVd0Zd_d1Ze	 	 d`dad6            Ze	 	 d`dbd8            Z	 	 	 dcddd:Zd;ej        dd<dd=dedFZej        dd<dej        dGdHdIdJddK
dfdSZdS )gGraphzGraph of nodes and edges.

    Parameters:
        nodes: Dictionary of nodes in the graph. Defaults to an empty dictionary.
        edges: List of edges in the graph. Defaults to an empty list.
    )default_factoryzdict[str, Node]r+   z
list[Edge]r,   Frz   r{   r0   r   dict[str, list[dict[str, Any]]]c               j   d t          | j                                                  D             g }| j        D ]O}|j                 |j                 d}|j        
|j        |d<   |j        rd|d<   |                    |           Pfd| j                                        D             |dS )	a   Convert the graph to a JSON-serializable format.

        Args:
            with_schemas: Whether to include the schemas of the nodes if they are
                Pydantic models. Defaults to False.

        Returns:
            A dictionary with the nodes and edges of the graph.
        c                Z    i | ](\  }}|j         t          |j                   r|n|j         )S r   )rB   r3   ).0ir|   s      r!   
<dictcomp>z!Graph.to_json.<locals>.<dictcomp>  sE     
 
 
4 G'$'**7QQ
 
 
r#   r;   Nr9   Tr:   c                P    g | ]"}d |j                  it          |          #S )rB   rz   )rB   r   )r   r|   stable_node_idsr{   s     r!   
<listcomp>z!Graph.to_json.<locals>.<listcomp>+  sN       
  /$'2$TEEE  r#   r+   r,   )		enumerater+   valuesr,   r6   r7   r9   r:   append)r    r{   r,   edge	edge_dictr   s    `   @r!   to_jsonzGraph.to_json  s    
 
$TZ%6%6%8%899
 
 
 ')J 		$ 		$D)$+6)$+6 I y$$(I	&! 0+/	-(LL####    
 !J--//   	
 	
 		
r#   c                *    t          | j                  S )z'Return whether the graph has any nodes.)r0   r+   r   s    r!   __bool__zGraph.__bool__5  s    DJr#   r   c                (    t                      j        S )zfReturn a new unique node identifier.

        It that can be used to add a node to the graph.
        )r   hexr   s    r!   next_idzGraph.next_id9  s    
 ww{r#   N)rF   r9   rD   rB   r<   rF   rE   rA   c          	         ||| j         v rd| d}t          |          |p|                                 }t          |||t	          ||                    }|| j         |j        <   |S )a|  Add a node to the graph and return it.

        Args:
            data: The data of the node.
            id: The id of the node. Defaults to None.
            metadata: Optional metadata for the node. Defaults to None.

        Returns:
            The node that was added to the graph.

        Raises:
            ValueError: If a node with the same id already exists.
        NzNode with id z already exists)rB   r9   rF   rC   )r+   r2   r   rA   ry   rB   )r    r9   rB   rF   msgr|   s         r!   add_nodezGraph.add_node@  sw    ( >bDJ..5"555CS//!!4<<>>rxmBPT>U>UVVV"
47r#   r|   Nonec                v    | j                             j                   fd| j        D             | _        dS )zyRemove a node from the graph and all edges connected to it.

        Args:
            node: The node to remove.
        c                >    g | ]}j         |j        |j        fv|S r   )rB   r6   r7   )r   r   r|   s     r!   r   z%Graph.remove_node.<locals>.<listcomp>c  s5     
 
 
474;:T+T+TD+T+T+Tr#   N)r+   poprB   r,   )r    r|   s    `r!   remove_nodezGraph.remove_node\  sK     	
tw
 
 
 
!Z
 
 



r#   r6   r7   r8   r:   r5   c                   |j         | j        vrd|j          d}t          |          |j         | j        vrd|j          d}t          |          t          |j         |j         ||          }| j                            |           |S )a  Add an edge to the graph and return it.

        Args:
            source: The source node of the edge.
            target: The target node of the edge.
            data: Optional data associated with the edge. Defaults to None.
            conditional: Whether the edge is conditional. Defaults to False.

        Returns:
            The edge that was added to the graph.

        Raises:
            ValueError: If the source or target node is not in the graph.
        zSource node z not in graphzTarget node r>   )rB   r+   r2   r5   r,   r   )r    r6   r7   r9   r:   r   r   s          r!   add_edgezGraph.add_edgeg  s    * 9DJ&&9999CS//!9DJ&&9999CS//!9VYT{
 
 
 	
$r#    )prefixgraphr   %tuple[Optional[Node], Optional[Node]]c               6   t          d |j                                        D                       rddfd| j                            fd|j                                        D                        | j                            fd|j        D                        |                                |                                }}|r$|	                     |j
                  	          nd
|r$|	                     |j
                  	          nd
fS )aS  Add all nodes and edges from another graph.

        Note this doesn't check for duplicates, nor does it connect the graphs.

        Args:
            graph: The graph to add.
            prefix: The prefix to add to the node ids. Defaults to "".

        Returns:
            A tuple of the first and last nodes of the subgraph.
        c              3  >   K   | ]}t          |j                  V  d S N)r3   rB   r   r|   s     r!   	<genexpr>zGraph.extend.<locals>.<genexpr>  s,      AADwtwAAAAAAr#   r   rB   r   r   c                    r d|  n| S )N:r   )rB   r   s    r!   prefixedzGraph.extend.<locals>.prefixed  s!    '-5f##r###25r#   c                h    i | ].\  }} |          |                      |                     /S rB   r?   )r   kvr   s      r!   r   z Graph.extend.<locals>.<dictcomp>  s=    QQQTQXXa[[!&&HHQKK&00QQQr#   c                v    g | ]5}|                      |j                   |j                             6S r;   r?   r6   r7   )r   r   r   s     r!   r   z Graph.extend.<locals>.<listcomp>  sQ        		$+!6!6xx?T?T	UU  r#   r   N)rB   r   r   r   )allr+   r   updateitemsr,   extend
first_node	last_noder?   rB   )r    r   r   rj   rk   r   s     `  @r!   r   zGraph.extend  sT    AAEK,>,>,@,@AAAAA 	F	6 	6 	6 	6 	6 	6 	
QQQQU[=N=N=P=PQQQ	
 	
 	
 	
   !K  	
 	
 	
 &&((%//*;*;t16@EJJ((58,,J---D/3=DII$'**I+++
 	
r#   c                   t          t                    }| j                                        D ]'}||j                                     |j                   (d |                                D             d	fdt          fd| j                                        D             fd| j	        D                       S )
ztReturn a new graph with all nodes re-identified.

        Uses their unique, readable names where possible.
        c                ~    i | ]:\  }}t          |          D ]%\  }}|t          |          d k    r|n	| d|d z    &;S )   _)r   len)r   	node_namenode_idsr   node_ids        r!   r   zGraph.reid.<locals>.<dictcomp>  sw     
 
 
#	8'11
 
 7 #h--1"4"4YYY:P:PQ:P:P
 
 
 
r#   r   r   r   c                :    |          }t          |           r|S | S r   )r3   )r   labelunique_labelss     r!   _get_node_idz Graph.reid.<locals>._get_node_id  s'    !'*Ew Nr#   c                h    i | ].\  }} |          |                      |                     /S r   r   )r   rB   r|   r   s      r!   r   zGraph.reid.<locals>.<dictcomp>  sQ       B R  $))||B/?/?)"@"@  r#   c                v    g | ]5}|                      |j                   |j                             6S r   r   )r   r   r   s     r!   r   zGraph.reid.<locals>.<listcomp>  s\       
 	 		'<44'<44     r#   r   )r   r   r   r   )
r   listr+   r   rC   r   rB   r   r   r,   )r    node_name_to_idsr|   r   r   s      @@r!   reidz
Graph.reid  s   
 't,,J%%'' 	8 	8DTY'..tw7777
 
'7'='='?'?
 
 
	 	 	 	 	 	     $
 0 0 2 2     
 !J  
 
 
 	
r#   Optional[Node]c                     t          |           S )zFind the single node that is not a target of any edge.

        If there is no such node, or there are multiple, return None.
        When drawing the graph, this node would be the origin.
        )_first_noder   s    r!   r   zGraph.first_node  s     4   r#   c                     t          |           S )zFind the single node that is not a source of any edge.

        If there is no such node, or there are multiple, return None.
        When drawing the graph, this node would be the destination.
        )
_last_noder   s    r!   r   zGraph.last_node  s     $r#   c                    |                                  rRt          | j        g          r=t          fd| j        D                       dk    r|                                dS dS dS dS )zRemove the first node if it exists and has a single outgoing edge.

        i.e., if removing it would not leave the graph without a "first" node.
        excludec                4    h | ]}|j         j        k    |S r   )r6   rB   )r   er   s     r!   	<setcomp>z(Graph.trim_first_node.<locals>.<setcomp>  s'    HHH1ah*-.G.GQ.G.G.Gr#   r   N)r   r   rB   r   r,   r   )r    r   s    @r!   trim_first_nodezGraph.trim_first_node  s    
 __&&
	)D:=/:::	) HHHH
HHHIIQNNZ(((((	) 	) 	) 	) ONr#   c                    |                                  rRt          | j        g          r=t          fd| j        D                       dk    r|                                dS dS dS dS )zRemove the last node if it exists and has a single incoming edge.

        i.e., if removing it would not leave the graph without a "last" node.
        r   c                4    h | ]}|j         j        k    |S r   )r7   rB   )r   r   r   s     r!   r   z'Graph.trim_last_node.<locals>.<setcomp>  s'    GGG1ah),.F.FQ.F.F.Fr#   r   N)r   r   rB   r   r,   r   )r    r   s    @r!   trim_last_nodezGraph.trim_last_node  s    
 NN$$		(4),888	( GGGG
GGGHHAMMY'''''	( 	( 	( 	( NMr#   c                r    ddl m}  |d | j                                        D             | j                  S )z&Draw the graph as an ASCII art string.r   )
draw_asciic                (    i | ]}|j         |j        S r   rG   r   s     r!   r   z$Graph.draw_ascii.<locals>.<dictcomp>   s    @@@DTWdi@@@r#   )$langchain_core.runnables.graph_asciir   r+   r   r,   )r    r   s     r!   r   zGraph.draw_ascii  sL    CCCCCCz@@DJ,=,=,?,?@@@J
 
 	
r#   c                H    t          |                                            dS )z'Print the graph as an ASCII art string.N)printr   r   s    r!   print_asciizGraph.print_ascii  s     doo     r#   output_file_pathfontnamelabelsOptional[LabelsDict]c                    d S r   r   r    r   r   r   s       r!   draw_pngzGraph.draw_png  s	     sr#   bytesc                    d S r   r   r   s       r!   r   zGraph.draw_png  s	     r#   Union[bytes, None]c                    ddl m} d | j                                        D             } ||t	          i |||d         ni ||d         ni                                         | |          S )a  Draw the graph as a PNG image.

        Args:
            output_file_path: The path to save the image to. If None, the image
                is not saved. Defaults to None.
            fontname: The name of the font to use. Defaults to None.
            labels: Optional labels for nodes and edges in the graph. Defaults to None.

        Returns:
            The PNG image as bytes if output_file_path is None, None otherwise.
        r   )	PngDrawerc                (    i | ]}|j         |j        S r   rG   r   s     r!   r   z"Graph.draw_png.<locals>.<dictcomp>+  s    RRRdtw	RRRr#   Nr+   r,   r   )"langchain_core.runnables.graph_pngr   r+   r   r*   draw)r    r   r   r   r   default_node_labelss         r!   r   zGraph.draw_png  s    " 	A@@@@@RRdj>O>O>Q>QRRRy)*0*<vg" *0);fWoo  	
 	
 $t%
&
&		'r#   T	   )with_stylescurve_stylenode_colorswrap_label_n_wordsfrontmatter_configr  r  rN   r  Optional[NodeStyles]r  intr  c                   ddl m} |                                 }|                                }|                                }	 ||j        |j        |r|j        nd|	r|	j        nd|||||	  	        S )aq  Draw the graph as a Mermaid syntax string.

        Args:
            with_styles: Whether to include styles in the syntax. Defaults to True.
            curve_style: The style of the edges. Defaults to CurveStyle.LINEAR.
            node_colors: The colors of the nodes. Defaults to NodeStyles().
            wrap_label_n_words: The number of words to wrap the node labels at.
                Defaults to 9.
            frontmatter_config (dict[str, Any], optional): Mermaid frontmatter config.
                Can be used to customize theme and styles. Will be converted to YAML and
                added to the beginning of the mermaid graph. Defaults to None.

                See more here: https://mermaid.js.org/config/configuration.html.

                Example config:

                .. code-block:: python

                {
                    "config": {
                        "theme": "neutral",
                        "look": "handDrawn",
                        "themeVariables": { "primaryColor": "#e2e2e2"},
                    }
                }


        Returns:
            The Mermaid syntax string.
        r   )draw_mermaidN)	r+   r,   r   r   r  r  node_stylesr  r  )&langchain_core.runnables.graph_mermaidr
  r   r   r   r+   r,   rB   )
r    r  r  r  r  r  r
  r   r   r   s
             r!   r
  zGraph.draw_mermaid8  s    N 	HGGGGG		%%''
OO%%	|++(2<z}}&/9illT###11

 

 

 
	
r#   white
   r   g      ?)
r  r  r  r   draw_methodbackground_colorpaddingmax_retriesretry_delayr  r  rm   r  r  r  r  floatc       
   	     d    ddl m} |                     ||||
          } ||||||||	          S )a{  Draw the graph as a PNG image using Mermaid.

        Args:
            curve_style: The style of the edges. Defaults to CurveStyle.LINEAR.
            node_colors: The colors of the nodes. Defaults to NodeStyles().
            wrap_label_n_words: The number of words to wrap the node labels at.
                Defaults to 9.
            output_file_path: The path to save the image to. If None, the image
                is not saved. Defaults to None.
            draw_method: The method to use to draw the graph.
                Defaults to MermaidDrawMethod.API.
            background_color: The color of the background. Defaults to "white".
            padding: The padding around the graph. Defaults to 10.
            max_retries: The maximum number of retries (MermaidDrawMethod.API).
                Defaults to 1.
            retry_delay: The delay between retries (MermaidDrawMethod.API).
                Defaults to 1.0.
            frontmatter_config (dict[str, Any], optional): Mermaid frontmatter config.
                Can be used to customize theme and styles. Will be converted to YAML and
                added to the beginning of the mermaid graph. Defaults to None.

                See more here: https://mermaid.js.org/config/configuration.html.

                Example config:

                .. code-block:: python

                {
                    "config": {
                        "theme": "neutral",
                        "look": "handDrawn",
                        "themeVariables": { "primaryColor": "#e2e2e2"},
                    }
                }

        Returns:
            The PNG image as bytes.
        r   )draw_mermaid_png)r  r  r  r  )mermaid_syntaxr   r  r  r  r  r  )r  r  r
  )r    r  r  r  r   r  r  r  r  r  r  r  r  s                r!   r  zGraph.draw_mermaid_pngq  so    h 	LKKKKK**##11	 + 
 
  )-#-##
 
 
 	
r#   )r{   r0   r   r   )r   r0   r$   r   )r9   rD   rB   r<   rF   rE   r   rA   )r|   rA   r   r   )NF)
r6   rA   r7   rA   r9   r8   r:   r0   r   r5   )r   r   r   r   r   r   )r   r   )r   r   )r   r   )NN)r   r   r   r<   r   r   r   r   )r   r   r   r<   r   r   r   r   )NNN)r   r<   r   r<   r   r   r   r   )r  r0   r  rN   r  r  r  r  r  rE   r   r   )r  rN   r  r  r  r  r   r<   r  rm   r  r   r  r  r  r  r  r  r  rE   r   r   ) r%   r&   r'   r(   r   dictr+   r.   r   r,   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rN   r`   r
  rm   rq   r  r   r#   r!   r   r     s          #U4888E8888d333E3333.3 #
 #
 #
 #
 #
 #
J           !
 .2     8	
 	
 	
 	
 )-!    D .0$
 $
 $
 $
 $
 $
L!
 !
 !
 !
F! ! ! !       ) ) ) )( ( ( (
 
 
 
! ! ! !  #''+	    X  #''+	    X +/"&'+	' ' ' ' 'F !","3,0"#7;7
 7
 7
 7
 7
 7
x #-"3,0"#*.):)> ' 7;D
 D
 D
 D
 D
 D
 D
 D
r#   r   r   r   r   Sequence[str]r   c                    fd| j         D             fd| j                                        D             }t          |          dk    r|d         ndS )zFind the single node that is not a target of any edge.

    Exclude nodes/sources with ids in the exclude list.
    If there is no such node, or there are multiple, return None.
    When drawing the graph, this node would be the origin.
    c                0    h | ]}|j         v|j        S r   r;   r   r   r   s     r!   r   z_first_node.<locals>.<setcomp>  '    QQQtdk6P6Pt{6P6P6Pr#   c                8    g | ]}|j         v|j         v|S r   r   )r   r|   r   targetss     r!   r   z_first_node.<locals>.<listcomp>  <       7'!!dgW&<&< 	&<&<&<r#   r   r   Nr,   r+   r   r   )r   r   foundr  s    ` @r!   r   r     {     RQQQu{QQQG    K&&((  E
 5zzQ588D0r#   c                    fd| j         D             fd| j                                        D             }t          |          dk    r|d         ndS )zFind the single node that is not a source of any edge.

    Exclude nodes/targets with ids in the exclude list.
    If there is no such node, or there are multiple, return None.
    When drawing the graph, this node would be the destination.
    c                0    h | ]}|j         v|j        S r   )r7   r6   r  s     r!   r   z_last_node.<locals>.<setcomp>  r  r#   c                8    g | ]}|j         v|j         v|S r   r   )r   r|   r   sourcess     r!   r   z_last_node.<locals>.<listcomp>  r   r#   r   r   Nr!  )r   r   r"  r'  s    ` @r!   r   r     r#  r#   )r/   r   r   r0   )rB   r   r9   rD   r   r   )r|   rA   r{   r0   r   r}   )r   )r   r   r   r  r   r   )0r(   
__future__r   r   collectionsr   dataclassesr   r   enumr   typingr   r	   r
   r   r   r   r   r   r   uuidr   r   langchain_core.utils.pydanticr   r   collections.abcr   pydanticr   rt   r   RunnableTyper   r*   r3   r5   rA   rJ   rN   rh   rm   ry   r   r   r   r   r   r#   r!   <module>r2     sf     " " " " " "  # # # # # # ( ( ( ( ( ( ( (      
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
         V V V V V V V V G((((((""""""FFFFFF. . . . .H . . .            
  
  
  
  
:  
  
  
F
 
 
 
 
: 
 
 
B
# 
# 
# 
# 
#Z 
# 
# 
#       "               M M M M& ).7 7 7 7 7 7t p
 p
 p
 p
 p
 p
 p
 p
f1 1 1 1 1 1 1 1 1 1 1 1r#   