
    g3fi$                   $   U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	m
Z
mZ ddlmZmZ ddlmZ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 ddlmZm Z  dd	l!m"Z"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/m0Z0 ddl1m2Z2m3Z3 ddl4m5Z5 ddl6m7Z7m8Z8 ddl9m:Z:m;Z;m<Z< erddl=m>Z> ddl?m@Z@ ddlAmBZB 	 ddlCmDZD dZE ej                  eH      ZIdWdZJeee" ed      f   ee2 ed      f   z  ee* ed      f   z  ee7 ed      f   z  ee/ ed      f   z  ee; ed       f   z  ee# ed!      f   z  ee3 ed"      f   z  ee+ ed#      f   z  ee8 ed$      f   z  ee0 ed%      f   z  ee< ed&      f   z   e eeJ      '      f   ZK	 	 	 	 dX	 	 	 	 	 	 	 	 	 dYd)ZLdZd*ZMd[d+ZNd\d,ZOe%ePeQ   z  eReQeQf   z  eQz  eSeQef   z  ZT	 	 	 	 	 d]	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d^d-ZUd_d.ZV	 	 	 	 d`d/ZW ed0      ZX ed1d2      ZY G d3 d4eeXeYf         ZZ	 	 	 	 dad5Z[e[dddddddd6	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dbd7       Z\e[d(d8	 	 	 	 	 dcd9       Z]e[d:dddddd;	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddd<       Z^e%eQz  eSeQef   z  Z_ ed=e_>      Z`ee`   Zaed?ddd@	 	 	 	 	 	 	 	 	 dedA       Zbed?ddd@	 	 	 	 	 	 	 	 	 dfdB       Zbd?ddd@	 	 	 	 	 	 	 	 	 dgdCZbdddD	 	 	 	 	 	 	 	 	 	 	 	 	 dhdEZcdddddF	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 didGZde2e3e"e#e7e8e;e<e/e0e*e+iZedHefdI<   eej                         D  ci c]  \  } }|| 
 c}} ZhdjdJZidkdKZjdldLZk	 	 	 	 	 	 dmdMZldndNZmdodOZndpdPZodQdRddS	 	 	 	 	 	 	 	 	 dqdTZpdrdUZqdVeqiZry# eF$ r dZEY w xY wc c}} w )sa8  Module contains utility functions for working with messages.

Some examples of what you can do with these functions include:

* Convert messages to strings (serialization)
* Convert messages from dicts to Message objects (deserialization)
* Filter messages from a list of messages based on name, type or id etc.
    )annotationsN)CallableIterableSequence)partialwraps)
TYPE_CHECKING	AnnotatedAnyConcatenateLiteral	ParamSpecProtocolTypeVarcastoverload)DiscriminatorFieldTag)	ErrorCodecreate_message)	AIMessageAIMessageChunk)BaseMessageBaseMessageChunk)convert_to_openai_data_block)ChatMessageChatMessageChunk)is_data_content_block)FunctionMessageFunctionMessageChunk)HumanMessageHumanMessageChunk)RemoveMessage)SystemMessageSystemMessageChunk)ToolCallToolMessageToolMessageChunk)BaseLanguageModelPromptValue)Runnable)TextSplitterTFc                   t        | t              r
d| v r| d   }n3t        | d      r| j                  }ndt        |        d}t	        |      t        |t
              s#dt        |      j                   }t	        |      |S )zCGet the type associated with the object for serialization purposes.typezfExpected either a dictionary with a 'type' key or an object with a 'type' attribute. Instead got type .z!Expected 'type' to be a str, got )
isinstancedicthasattrr0   	TypeErrorstr__name__)vresultmsgs      [/var/www/auto_recruiter/arenv/lib/python3.12/site-packages/langchain_core/messages/utils.py	_get_typer<   A   s    !Tv{6	F	99=a	D 	 nfc"1$v,2G2G1HInM    ai)taghumanchatsystemfunctiontoolr   r#   r   r&   r!   r)   )discriminator
c                0   g }| D ]  }t        |t              r|}nyt        |t              r|}nft        |t              rd}nSt        |t              rd}n@t        |t
              rd}n-t        |t              r|j                  }nd| }t        |      | d|j                   }t        |t              r>|j                  r||j                   z  }n!d|j                  v r||j                  d    z  }|j                  |        |j                  |      S )aN  Convert a sequence of messages to strings and concatenate them into one string.

    Args:
        messages: Messages to be converted to strings.
        human_prefix: The prefix to prepend to contents of `HumanMessage`s.
        ai_prefix: The prefix to prepend to contents of `AIMessage`.
        message_separator: The separator to use between messages.

    Returns:
        A single string concatenation of all input messages.

    Raises:
        ValueError: If an unsupported message type is encountered.

    Note:
        If a message is an `AIMessage` and contains both tool calls under `tool_calls`
        and a function call under `additional_kwargs["function_call"]`, only the tool
        calls will be appended to the string representation.

    Example:
        ```python
        from langchain_core import AIMessage, HumanMessage

        messages = [
            HumanMessage(content="Hi, how are you?"),
            AIMessage(content="Good, how are you?"),
        ]
        get_buffer_string(messages)
        # -> "Human: Hi, how are you?\nAI: Good, how are you?"
        ```
    SystemFunctionToolzGot unsupported message type: z: function_call)r2   r"   r   r%   r    r(   r   role
ValueErrortext
tool_callsadditional_kwargsappendjoin)	messageshuman_prefix	ai_prefixmessage_separatorstring_messagesmrL   r:   messages	            r;   get_buffer_stringrZ   e   s	   J O (a&D9%D=)D?+D;'D;'66D21#6CS/!F"QVVH%a#||all^, A$7$77a11/BCDw'5(8 !!/22r=   c                   | d   }|dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt	        di | d   S |dk(  rt        di | d   S |d	k(  rt        di | d   S |d
k(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S |dk(  rt        di | d   S d| }t        |      )Nr0   r@   datar>   rB   rA   rC   rD   remover   r#   r!   r)   r&   r   zGot unexpected message type:  )r"   r   r%   r   r    r(   r$   r   r#   r!   r)   r&   r   rM   )rY   type_r:   s      r;   _message_from_dictr`      sv   FOE.gfo..}+76?++/wv//-WV_--
111-WV_--/wv//  000## 376?33&&#6gfo66""2'&/22$$!4GFO44""2'&/22)%
1C
S/r=   c                >    | D cg c]  }t        |       c}S c c}w )zConvert a sequence of messages from dicts to `Message` objects.

    Args:
        messages: Sequence of messages (as dicts) to convert.

    Returns:
        list of messages (BaseMessages).

    )r`   )rS   rX   s     r;   messages_from_dictrb      s     ,44aq!444s   c                2   t        | t              s| S dg}t        | t              r|j                  ddg       t	        d | j
                  j                  d   di | j                  j                         D ci c]  \  }}||vs|| c}}      S c c}}w )zConvert a message chunk to a `Message`.

    Args:
        chunk: Message chunk to convert.

    Returns:
        Message.
    r0   tool_call_chunkschunk_positionr      r^   )	r2   r   r   extendr   	__class____mro____dict__items)chunkignore_keyskr8   s       r;   message_chunk_to_messagero      s     e-.(K%(.0@AB"" 	
 % 4 4 6O1!;:Nq!tO	
  Ps   7BBc                f   i }|||d<   |||d<   |r?|j                  dd      x}r||d<   ||d<   |j                  |j                  di              |||d<   |vg |d<   |D ]l  }	d|	v rR|	d   d	   }
t        |
t              rt	        j
                  |
d
      }
|d   j                  |	d   d   |
|	d   dd       Y|d   j                  |	       n | dv r8|j                  di       j                  dd
      x}r||d<   t        dd|i|}|S | dv r8|j                  di       j                  dd
      x}r||d<   t        dd|i|}|S | dv r4| dk(  r |j                  d      xs i |d<   d|d   d<   t        dd|i|}|S | dk(  rt        dd|i|}|S | dk(  r[|j                  di       j                  dd      }|j                  di       j                  dd      }|||d<   t        d||d|}|S | dk(  rt        di |}|S d|  d}t        |t        j                         }t#        |      )a  Create a message from a `Message` type and content string.

    Args:
        message_type: the type of the message (e.g., `'human'`, `'ai'`, etc.).
        content: the content string.
        name: the name of the message.
        tool_call_id: the tool call id.
        tool_calls: the tool calls.
        id: the id of the message.
        additional_kwargs: additional keyword arguments.

    Returns:
        a message of the appropriate type.

    Raises:
        ValueError: if the message type is not one of `'human'`, `'user'`, `'ai'`,
            `'assistant'`, `'function'`, `'tool'`, `'system'`, or
            `'developer'`.
    Nnametool_call_idresponse_metadatarP   idrO   rC   	argumentsF)strict	tool_call)rq   argsrt   r0   >   userr@   examplecontent>   r>   	assistant>   rB   	developerr}   __openai_role__rD   artifactstatus)r{   r   r]   zUnexpected message type: 'z_'. Use one of 'human', 'user', 'ai', 'assistant', 'function', 'tool', 'system', or 'developer'.rY   
error_coder^   )popupdater2   r6   jsonloadsrQ   getr"   r   r%   r    r(   r$   r   r   MESSAGE_COERCION_FAILURErM   )message_typer{   rq   rr   rO   rt   rP   kwargsrs   rw   rx   rz   rY   r   r   r:   s                   r;   !_create_message_from_message_typer      s   8  Fv!-~ 1 5 56I4 PPP*;F&'&7"#  !2!6!67JB!OP	~t!|# 	7IY& ,[9dC(::d59D|$++ )* 5f = $'o +	 |$++I6	7  ((jj!4b9==iOO7O 'F9+FGFvF6 N5 
,	,jj!4b9==iOO7O 'F96G6v6. N- 
0	0;&*0**5H*I*ORF&'=HF&'(9:::6:$ N# 
	#!<'<V<  N 
	::126:::tL/4884H%F8KgKFK N 
	!)&) N ) 7X Y 	 SY5W5WXor=   c                   t        | t              r| }|S t        | t              r2t        | t              rt	        d|       }|S 	 | \  }}t	        ||      }|S t        | t              rG| j                         }	 	 |j                  d      }|j                  d      xs d}t	        ||fi |}|S d
t        |        }t        |t        j                  	      }t        |      # t
        $ r}d}t        |      |d}~ww xY w# t        $ r |j                  d      }Y w xY w# t        $ r1}d|  }t        |t        j                  	      }t        |      |d}~ww xY w)a  Instantiate a `Message` from a variety of message formats.

    The message format can be one of the following:

    - `BaseMessagePromptTemplate`
    - `BaseMessage`
    - 2-tuple of (role string, template); e.g., (`'human'`, `'{user_input}'`)
    - dict: a message dict with role and content keys
    - string: shorthand for (`'human'`, template); e.g., `'{user_input}'`

    Args:
        message: a representation of a message in one of the supported formats.

    Returns:
        An instance of a message or a message template.

    Raises:
        NotImplementedError: if the message type is not supported.
        ValueError: if the message dict does not contain the required keys.

    r@   z5Message as a sequence must be (role string, template)NrL   r0   r{    z9Message dict must contain 'role' and 'content' keys, got r   zUnsupported message type: )r2   r   r   r6   r   rM   NotImplementedErrorr3   copyr   KeyErrorr   r   r   r0   )	rY   message_message_type_strtemplateer:   
msg_kwargsmsg_typemsg_contents	            r;   _convert_to_messager   O  s   , ';'D OC 
GX	&gs#8'JH> O;6-4* ( 99I8TH0 O/ 
GT	"\\^
	)2%>>&1 %..39rK 5k
%/
 O	 +4=/:SY5W5WX!#&&3  6M)#.A56  2%>>&12  	)MgYWC 	(J(JC S/q(	)sN   C" 9D 
D! "	C>+C99C>DD! DD! !	E*,EEc                    ddl m} t        | |      r| j                         S | D cg c]  }t	        |       c}S c c}w )zConvert a sequence of messages to a list of messages.

    Args:
        messages: Sequence of messages to convert.

    Returns:
        list of messages (BaseMessages).

    r   r+   )langchain_core.prompt_valuesr,   r2   to_messagesr   )rS   r,   rX   s      r;   convert_to_messagesr     s:     9(K(##%%,45q"555s   <_P_R_co)	covariantc                  l    e Zd Ze	 d	 	 	 	 	 	 	 dd       Ze	 	 	 	 	 	 	 	 dd       Z	 d	 	 	 	 	 	 	 ddZy)	_RunnableSupportCallableNc                     y Nr^   selfrS   rx   r   s       r;   __call__z!_RunnableSupportCallable.__call__  s	     @Cr=   c                     y r   r^   r   s       r;   r   z!_RunnableSupportCallable.__call__  s     r=   c                     y r   r^   r   s       r;   r   z!_RunnableSupportCallable.__call__  s	    
 HKr=   r   )rS   Nonerx   _P.argsr   	_P.kwargsreturnz4Runnable[Sequence[MessageLikeRepresentation], _R_co])rS   z1Sequence[MessageLikeRepresentation] | PromptValuerx   r   r   r   r   r   rS   z8Sequence[MessageLikeRepresentation] | PromptValue | Nonerx   r   r   r   r   z<_R_co | Runnable[Sequence[MessageLikeRepresentation], _R_co])r7   
__module____qualname__r   r   r^   r=   r;   r   r     s     CC C 	C
 
>C C C  	
 
  NRKJK K 	K
 
FKr=   r   c                V     t               	 d	 	 	 	 	 	 	 d fd       }t        d|      S )Nc                h    ddl m} |  | g|i |S  |t        fi |j                        S )Nr   )RunnableLambda)rq   )langchain_core.runnables.baser   r   r7   )rS   rx   r   r   funcs       r;   wrappedz"_runnable_support.<locals>.wrapped  s?     	A242622gd5f5DMMJJr=   #_RunnableSupportCallable[_P, _R_co]r   r   )r   r   )r   r   s   ` r;   _runnable_supportr     sY    
 4[MQ
KJ
K
K 
K 
F	
K 
K 5w??r=   )include_namesexclude_namesinclude_typesexclude_typesinclude_idsexclude_idsexclude_tool_callsc                  t        |       } g }| D ]  }	|r|	j                  |v s|rt        |	|      s|r|	j                  |v r3|du r-t	        |	t
              r|	j                  st	        |	t              rdt	        |t        t        t        f      rt	        |	t
              r|	j                  r|	j                  D 
cg c]  }
|
d   |vr|
 }}
|s|	j                  }t	        |	j                  t              rP|	j                  D cg c];  }t	        |t              r'|j                  d      dk7  s|j                  d      |vr|= }}|	j                  ||d      }	n t	        |	t              r|	j                  |v rj|s|s|r2|r|	j                  |v s"|rt        |	|      s|s|	j                  |v s|j!                  |	        |S c c}
w c c}w )a
  Filter messages based on `name`, `type` or `id`.

    Args:
        messages: Sequence Message-like objects to filter.
        include_names: Message names to include.
        exclude_names: Messages names to exclude.
        include_types: Message types to include. Can be specified as string names
            (e.g. `'system'`, `'human'`, `'ai'`, ...) or as `BaseMessage`
            classes (e.g. `SystemMessage`, `HumanMessage`, `AIMessage`, ...).

        exclude_types: Message types to exclude. Can be specified as string names
            (e.g. `'system'`, `'human'`, `'ai'`, ...) or as `BaseMessage`
            classes (e.g. `SystemMessage`, `HumanMessage`, `AIMessage`, ...).

        include_ids: Message IDs to include.
        exclude_ids: Message IDs to exclude.
        exclude_tool_calls: Tool call IDs to exclude.
            Can be one of the following:
            - `True`: All `AIMessage` objects with tool calls and all `ToolMessage`
                objects will be excluded.
            - a sequence of tool call IDs to exclude:
                - `ToolMessage` objects with the corresponding tool call ID will be
                    excluded.
                - The `tool_calls` in the AIMessage will be updated to exclude
                    matching tool calls. If all `tool_calls` are filtered from an
                    AIMessage, the whole message is excluded.

    Returns:
        A list of Messages that meets at least one of the `incl_*` conditions and none
        of the `excl_*` conditions. If not `incl_*` conditions are specified then
        anything that is not explicitly excluded will be included.

    Raises:
        ValueError: If two incompatible arguments are provided.

    Example:
        ```python
        from langchain_core.messages import (
            filter_messages,
            AIMessage,
            HumanMessage,
            SystemMessage,
        )

        messages = [
            SystemMessage("you're a good assistant."),
            HumanMessage("what's your name", id="foo", name="example_user"),
            AIMessage("steve-o", id="bar", name="example_assistant"),
            HumanMessage(
                "what's your favorite color",
                id="baz",
            ),
            AIMessage(
                "silicon blue",
                id="blah",
            ),
        ]

        filter_messages(
            messages,
            incl_names=("example_user", "example_assistant"),
            incl_types=("system",),
            excl_ids=("bar",),
        )
        ```

        ```python
        [
            SystemMessage("you're a good assistant."),
            HumanMessage("what's your name", id="foo", name="example_user"),
        ]
        ```
    Trt   r0   tool_use)rO   r{   )r   )r   rq   _is_message_typert   r2   r   rO   r(   listtuplesetr{   r3   r   
model_copyrr   rQ   )rS   r   r   r   r   r   r   r   filteredr:   rw   rO   r{   content_blocks                 r;   filter_messagesr     s   j #8,H"$H 4!sxx=8"23"F+ 5%Y'CNN#{+(4*<=#y)cnn &)^^! .@@ 
 
 "++ckk40 .1[[) *=$ ?,008JF,006>PP &G  nn*4I %  3,1A1AEW1W +#((m";"23"F+ 5OOC i4!l OMs   9GA G)chunk_separatorc               r   | sg S t        |       } g }| D ]  }|r|j                         nd}|s|j                  |       ,t        |t              st        ||j
                        s|j                  ||g       ft        |      }t        |      }|j                  r|j                  j                          t        |j                  t              rGt        |j                  t              r-|j                  r!|j                  r|xj                  |z  c_
        |j                  t        ||z                " |S )a	  Merge consecutive Messages of the same type.

    !!! note
        `ToolMessage` objects are not merged, as each has a distinct tool call id that
        can't be merged.

    Args:
        messages: Sequence Message-like objects to merge.
        chunk_separator: Specify the string to be inserted between message chunks.

    Returns:
        list of BaseMessages with consecutive runs of message types merged into single
        messages. By default, if two messages being merged both have string contents,
        the merged content is a concatenation of the two strings with a new-line
        separator.
        The separator inserted between message chunks can be controlled by specifying
        any string with `chunk_separator`. If at least one of the messages has a list
        of content blocks, the merged content is a list of content blocks.

    Example:
        ```python
        from langchain_core.messages import (
            merge_message_runs,
            AIMessage,
            HumanMessage,
            SystemMessage,
            ToolCall,
        )

        messages = [
            SystemMessage("you're a good assistant."),
            HumanMessage(
                "what's your favorite color",
                id="foo",
            ),
            HumanMessage(
                "wait your favorite food",
                id="bar",
            ),
            AIMessage(
                "my favorite colo",
                tool_calls=[
                    ToolCall(
                        name="blah_tool", args={"x": 2}, id="123", type="tool_call"
                    )
                ],
                id="baz",
            ),
            AIMessage(
                [{"type": "text", "text": "my favorite dish is lasagna"}],
                tool_calls=[
                    ToolCall(
                        name="blah_tool",
                        args={"x": -10},
                        id="456",
                        type="tool_call",
                    )
                ],
                id="blur",
            ),
        ]

        merge_message_runs(messages)
        ```

        ```python
        [
            SystemMessage("you're a good assistant."),
            HumanMessage(
                "what's your favorite color\\n"
                "wait your favorite food", id="foo",
            ),
            AIMessage(
                [
                    "my favorite colo",
                    {"type": "text", "text": "my favorite dish is lasagna"}
                ],
                tool_calls=[
                    ToolCall({
                        "name": "blah_tool",
                        "args": {"x": 2},
                        "id": "123",
                        "type": "tool_call"
                    }),
                    ToolCall({
                        "name": "blah_tool",
                        "args": {"x": -10},
                        "id": "456",
                        "type": "tool_call"
                    })
                ]
                id="baz"
            ),
        ]

        ```
    N)r   r   rQ   r2   r(   rh   rg   _msg_to_chunkrs   clearr{   r6   _chunk_to_msg)rS   r   mergedr:   last
last_chunk
curr_chunks          r;   merge_message_runsr   a  s   N 	"8,H "F B%vzz|4MM#[)C1PMM4+&&t,J&s+J++,,224:--s3z1137&&&&""o5"MM-
Z(?@A%B& Mr=   r   )strategyallow_partialend_onstart_oninclude_systemtext_splitterc          
     B   |r|dk(  rd}	t        |	      |r|dk(  rd}	t        |	      t        |       } t        |t              rB|t        v r
t        |   n2dj                  d t        D              }
d| d|
 d}	t        |	      |t        d	      rj                  }n~t              rYt        t        t        j                        j                  j                                     j                  t         u rdfd
}n}ndt#               d}	t        |	      t$        rt        |t&              r|j(                  }n|rt+        d|      }nt,        }|dk(  rt/        | ||||rd|      S d|      S |dk(  rt1        | |||||||      S d|d}	t        |	      )aM.  Trim messages to be below a token count.

    `trim_messages` can be used to reduce the size of a chat history to a specified
    token or message count.

    In either case, if passing the trimmed chat history back into a chat model
    directly, the resulting chat history should usually satisfy the following
    properties:

    1. The resulting chat history should be valid. Most chat models expect that chat
        history starts with either (1) a `HumanMessage` or (2) a `SystemMessage`
        followed by a `HumanMessage`. To achieve this, set `start_on='human'`.
        In addition, generally a `ToolMessage` can only appear after an `AIMessage`
        that involved a tool call.
    2. It includes recent messages and drops old messages in the chat history.
        To achieve this set the `strategy='last'`.
    3. Usually, the new chat history should include the `SystemMessage` if it
        was present in the original chat history since the `SystemMessage` includes
        special instructions to the chat model. The `SystemMessage` is almost always
        the first message in the history if present. To achieve this set the
        `include_system=True`.

    !!! note
        The examples below show how to configure `trim_messages` to achieve a behavior
        consistent with the above properties.

    Args:
        messages: Sequence of Message-like objects to trim.
        max_tokens: Max token count of trimmed messages.
        token_counter: Function or llm for counting tokens in a `BaseMessage` or a
            list of `BaseMessage`.

            If a `BaseLanguageModel` is passed in then
            `BaseLanguageModel.get_num_tokens_from_messages()` will be used. Set to
            `len` to count the number of **messages** in the chat history.

            You can also use string shortcuts for convenience:

            - `'approximate'`: Uses `count_tokens_approximately` for fast, approximate
                token counts.

            !!! note

                `count_tokens_approximately` (or the shortcut `'approximate'`) is
                recommended for using `trim_messages` on the hot path, where exact token
                counting is not necessary.

        strategy: Strategy for trimming.

            - `'first'`: Keep the first `<= n_count` tokens of the messages.
            - `'last'`: Keep the last `<= n_count` tokens of the messages.
        allow_partial: Whether to split a message if only part of the message can be
            included.

            If `strategy='last'` then the last partial contents of a message are
            included. If `strategy='first'` then the first partial contents of a
            message are included.
        end_on: The message type to end on.

            If specified then every message after the last occurrence of this type is
            ignored. If `strategy='last'` then this is done before we attempt to get the
            last `max_tokens`. If `strategy='first'` then this is done after we get the
            first `max_tokens`. Can be specified as string names (e.g. `'system'`,
            `'human'`, `'ai'`, ...) or as `BaseMessage` classes (e.g. `SystemMessage`,
            `HumanMessage`, `AIMessage`, ...). Can be a single type or a list of types.

        start_on: The message type to start on.

            Should only be specified if `strategy='last'`. If specified then every
            message before the first occurrence of this type is ignored. This is done
            after we trim the initial messages to the last `max_tokens`. Does not apply
            to a `SystemMessage` at index 0 if `include_system=True`. Can be specified
            as string names (e.g. `'system'`, `'human'`, `'ai'`, ...) or as
            `BaseMessage` classes (e.g. `SystemMessage`, `HumanMessage`, `AIMessage`,
            ...). Can be a single type or a list of types.

        include_system: Whether to keep the `SystemMessage` if there is one at index
            `0`.

            Should only be specified if `strategy="last"`.
        text_splitter: Function or `langchain_text_splitters.TextSplitter` for
            splitting the string contents of a message.

            Only used if `allow_partial=True`. If `strategy='last'` then the last split
            tokens from a partial message will be included. if `strategy='first'` then
            the first split tokens from a partial message will be included. Token
            splitter assumes that separators are kept, so that split contents can be
            directly concatenated to recreate the original text. Defaults to splitting
            on newlines.

    Returns:
        List of trimmed `BaseMessage`.

    Raises:
        ValueError: if two incompatible arguments are specified or an unrecognized
            `strategy` is specified.

    Example:
        Trim chat history based on token count, keeping the `SystemMessage` if
        present, and ensuring that the chat history starts with a `HumanMessage` (or a
        `SystemMessage` followed by a `HumanMessage`).

        ```python
        from langchain_core.messages import (
            AIMessage,
            HumanMessage,
            BaseMessage,
            SystemMessage,
            trim_messages,
        )

        messages = [
            SystemMessage("you're a good assistant, you always respond with a joke."),
            HumanMessage("i wonder why it's called langchain"),
            AIMessage(
                'Well, I guess they thought "WordRope" and "SentenceString" just '
                "didn't have the same ring to it!"
            ),
            HumanMessage("and who is harrison chasing anyways"),
            AIMessage(
                "Hmmm let me think.\n\nWhy, he's probably chasing after the last "
                "cup of coffee in the office!"
            ),
            HumanMessage("what do you call a speechless parrot"),
        ]


        trim_messages(
            messages,
            max_tokens=45,
            strategy="last",
            token_counter=ChatOpenAI(model="gpt-4o"),
            # Most chat models expect that chat history starts with either:
            # (1) a HumanMessage or
            # (2) a SystemMessage followed by a HumanMessage
            start_on="human",
            # Usually, we want to keep the SystemMessage
            # if it's present in the original history.
            # The SystemMessage has special instructions for the model.
            include_system=True,
            allow_partial=False,
        )
        ```

        ```python
        [
            SystemMessage(
                content="you're a good assistant, you always respond with a joke."
            ),
            HumanMessage(content="what do you call a speechless parrot"),
        ]
        ```

        Trim chat history using approximate token counting with `'approximate'`:

        ```python
        trim_messages(
            messages,
            max_tokens=45,
            strategy="last",
            # Using the "approximate" shortcut for fast token counting
            token_counter="approximate",
            start_on="human",
            include_system=True,
        )

        # This is equivalent to using `count_tokens_approximately` directly
        from langchain_core.messages.utils import count_tokens_approximately

        trim_messages(
            messages,
            max_tokens=45,
            strategy="last",
            token_counter=count_tokens_approximately,
            start_on="human",
            include_system=True,
        )
        ```

        Trim chat history based on the message count, keeping the `SystemMessage` if
        present, and ensuring that the chat history starts with a HumanMessage (
        or a `SystemMessage` followed by a `HumanMessage`).

            trim_messages(
                messages,
                # When `len` is passed in as the token counter function,
                # max_tokens will count the number of messages in the chat history.
                max_tokens=4,
                strategy="last",
                # Passing in `len` as a token counter function will
                # count the number of messages in the chat history.
                token_counter=len,
                # Most chat models expect that chat history starts with either:
                # (1) a HumanMessage or
                # (2) a SystemMessage followed by a HumanMessage
                start_on="human",
                # Usually, we want to keep the SystemMessage
                # if it's present in the original history.
                # The SystemMessage has special instructions for the model.
                include_system=True,
                allow_partial=False,
            )

        ```python
        [
            SystemMessage(
                content="you're a good assistant, you always respond with a joke."
            ),
            HumanMessage(content="and who is harrison chasing anyways"),
            AIMessage(
                content="Hmmm let me think.\n\nWhy, he's probably chasing after "
                "the last cup of coffee in the office!"
            ),
            HumanMessage(content="what do you call a speechless parrot"),
        ]
        ```
        Trim chat history using a custom token counter function that counts the
        number of tokens in each message.

        ```python
        messages = [
            SystemMessage("This is a 4 token text. The full message is 10 tokens."),
            HumanMessage(
                "This is a 4 token text. The full message is 10 tokens.", id="first"
            ),
            AIMessage(
                [
                    {"type": "text", "text": "This is the FIRST 4 token block."},
                    {"type": "text", "text": "This is the SECOND 4 token block."},
                ],
                id="second",
            ),
            HumanMessage(
                "This is a 4 token text. The full message is 10 tokens.", id="third"
            ),
            AIMessage(
                "This is a 4 token text. The full message is 10 tokens.",
                id="fourth",
            ),
        ]


        def dummy_token_counter(messages: list[BaseMessage]) -> int:
            # treat each message like it adds 3 default tokens at the beginning
            # of the message and at the end of the message. 3 + 4 + 3 = 10 tokens
            # per message.

            default_content_len = 4
            default_msg_prefix_len = 3
            default_msg_suffix_len = 3

            count = 0
            for msg in messages:
                if isinstance(msg.content, str):
                    count += (
                        default_msg_prefix_len
                        + default_content_len
                        + default_msg_suffix_len
                    )
                if isinstance(msg.content, list):
                    count += (
                        default_msg_prefix_len
                        + len(msg.content) * default_content_len
                        + default_msg_suffix_len
                    )
            return count
        ```

        First 30 tokens, allowing partial messages:
        ```python
        trim_messages(
            messages,
            max_tokens=30,
            token_counter=dummy_token_counter,
            strategy="first",
            allow_partial=True,
        )
        ```

        ```python
        [
            SystemMessage("This is a 4 token text. The full message is 10 tokens."),
            HumanMessage(
                "This is a 4 token text. The full message is 10 tokens.",
                id="first",
            ),
            AIMessage(
                [{"type": "text", "text": "This is the FIRST 4 token block."}],
                id="second",
            ),
        ]
        ```
    firstz5start_on parameter is only valid with strategy='last'z;include_system parameter is only valid with strategy='last'z, c              3  (   K   | ]
  }d | d   yw)'Nr^   ).0keys     r;   	<genexpr>z trim_messages.<locals>.<genexpr>(  s      ,"!C5
,s   z Invalid token_counter shortcut 'z'. Available shortcuts: r1   get_num_tokens_from_messagesc                ,    t        fd| D              S )Nc              3  .   K   | ]  } |        y wr   r^   )r   r:   actual_token_counters     r;   r   z<trim_messages.<locals>.list_token_counter.<locals>.<genexpr>?  s     I/4Is   )sum)rS   r   s    r;   list_token_counterz)trim_messages.<locals>.list_token_counter>  s    IIIIr=   z'token_counter' expected to be a model that implements 'get_num_tokens_from_messages()' or a function. Received object of type r   N
max_tokenstoken_counterr   partial_strategyr   r   )r   r   r   r   r   r   r   zUnrecognized strategy=z.. Supported strategies are 'last' and 'first'.rS   Sequence[BaseMessage]r   int)rM   r   r2   r6   _TOKEN_COUNTER_SHORTCUTSrR   r4   r   callablenextiterinspect	signature
parametersvalues
annotationr   r0   _HAS_LANGCHAIN_TEXT_SPLITTERSr.   
split_textr   _default_text_splitter_first_max_tokens_last_max_tokens)rS   r   r   r   r   r   r   r   r   r:   available_shortcutsr   text_splitter_fnr   s                @r;   trim_messagesr     s   l	 H'Eo(g-Ko"8,H -%44#;M#J "&)) ,&>, # 3=/ B((;'<A?  S/!  -#%CD1NN	&	'W&&';<GGNNPQjJ "6W()*!- 	
 o$M<)P(33	
M:17 !,*(5W
 	

 <@
 	
 6!,')*	
 		
 $($R
SC
S/r=   _T)boundstring)text_format
include_idpass_through_unknown_blocksc                    y r   r^   rS   r  r  r  s       r;   convert_to_openai_messagesr  p  s     r=   c                    y r   r^   r  s       r;   r  r  z  s     r=   c                  |dvrd|d}t        |      g }t        | t        t        t        f      x}r| g} t        |       } t        |       D 	]c  \  }}dt        |      i}	g }
|j                  r|j                  |	d<   t        |t              r$|j                  rt        |j                        |	d<   |j                  j                  d      r|j                  d   |	d<   t        |t              r|j                  |	d<   |r|j                   r|j                   |	d	<   |j"                  s|d
k(  rdng }n@t        |j"                  t              r%|d
k(  r|j"                  }nd|j"                  dg}n|d
k(  r@t%        d |j"                  D              r$dj'                  d |j"                  D              }ng }t        |j"                        D ]r  \  }t        t              r|j)                  dd       ,j                  d      dk(  rKdD cg c]	  }|vs| c}x}rd| d| d| d }t        |      |j)                  d   d   d       j                  d      dk(  rHdD cg c]	  }|vs| c}x}rd| d| d| d }t        |      |j)                  dd   d       t+              rZt-              }|j                  d      dk(  r(d|v r$d|d   vrt.        j1                  d       d|d   d<   |j)                  |       Lj                  d      dk(  sdv rj                  d       x}rZd!D cg c]	  }||vs| c}x}rd| d| d"| d }t        |      |j)                  dd#d$|d%    d&|d    d'|d(    id       щj                  d      x}rbd)D cg c]	  }||vs| c}x}rd| d| d*| d }t        |      t3        |d    d+         }|j)                  dd#d,|d-    d.| id       Fd| d| d/ }t        |      j                  d      dk(  rt        j                  d      t              rt        j                  di       j                  d0      t              rQj                  di       j                  d      t.        j1                  d       dd   d<   |j)                         j                  d      d1k(  rt        j                  d1      t              rqt        j                  d1i       j                  d(      t              rBt        j                  d1i       j                  d-      t              r|j)                         j                  d      d2k(  rd3D cg c]	  }|vs| c}x}rd| d| d4| d }t        |      t5        fd5t7        d6|      j                  D              r!|	j                  dg       |	d<   |	d   j)                  d7d	   d   t9        j:                  d8   d9:      d;d<       qj                  d      d=k(  rt5        fd>t7        d6|      j                  D              sd?D cg c]  }|vr|
 c}x}rd| d| d4| d }t        |      |	j                  dg       |	d<   |	d   j)                  d7j                  d@      j                  d      j                  dA      d;d<       |s=|j)                         Pj                  d      dBk(  rvdCD cg c]	  }|vs| c}x}rd| d| dD| d }t        |      t        dE   dF   j                  dG      rdHndIJ      }|
j=                  t?        |g|K             ډj                  d      dLk(  sdLv rFdLvrd| d| dM }t        |      |j)                  dt9        j:                  dL         d       8j                  d      dNk(  sdNv rZdNvsddN   vrd| d| dO| d| dP 
}t        |      dN   d   }t        |t              r|d   }|j)                  d|d       j                  d      dQk(  rydRD cg c]	  }|vs| c}x}rd| d| dS| d }t        |      ddT   vrdUdT    }t        |      t3        d(         }|j)                  dd#d$dT    d.| id       7j                  d      dVv s|r|j)                         _d| d| dW }t        |       |d
k(  r*t5        dX |D              sdj'                  dY |D              }||	dE<   |j"                  r|	dE   s|
r|j=                  |
       	P|j=                  |	g|
       	f |r|dZ   S |S c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w )[a  Convert LangChain messages into OpenAI message dicts.

    Args:
        messages: Message-like object or iterable of objects whose contents are
            in OpenAI, Anthropic, Bedrock Converse, or VertexAI formats.
        text_format: How to format string or text block contents:
            - `'string'`:
                If a message has a string content, this is left as a string. If
                a message has content blocks that are all of type `'text'`, these
                are joined with a newline to make a single string. If a message has
                content blocks and at least one isn't of type `'text'`, then
                all blocks are left as dicts.
            - `'block'`:
                If a message has a string content, this is turned into a list
                with a single content block of type `'text'`. If a message has
                content blocks these are left as is.
        include_id: Whether to include message IDs in the openai messages, if they
            are present in the source messages.
        pass_through_unknown_blocks: Whether to include content blocks with unknown
            formats in the output. If `False`, an error is raised if an unknown
            content block is encountered.

    Raises:
        ValueError: if an unrecognized `text_format` is specified, or if a message
            content block is missing expected keys.

    Returns:
        The return type depends on the input type:

        - dict:
            If a single message-like object is passed in, a single OpenAI message
            dict is returned.
        - list[dict]:
            If a sequence of message-like objects are passed in, a list of OpenAI
            message dicts is returned.

    Example:
        ```python
        from langchain_core.messages import (
            convert_to_openai_messages,
            AIMessage,
            SystemMessage,
            ToolMessage,
        )

        messages = [
            SystemMessage([{"type": "text", "text": "foo"}]),
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "whats in this"},
                    {
                        "type": "image_url",
                        "image_url": {"url": "data:image/png;base64,'/9j/4AAQSk'"},
                    },
                ],
            },
            AIMessage(
                "",
                tool_calls=[
                    {
                        "name": "analyze",
                        "args": {"baz": "buz"},
                        "id": "1",
                        "type": "tool_call",
                    }
                ],
            ),
            ToolMessage("foobar", tool_call_id="1", name="bar"),
            {"role": "assistant", "content": "thats nice"},
        ]
        oai_messages = convert_to_openai_messages(messages)
        # -> [
        #   {'role': 'system', 'content': 'foo'},
        #   {'role': 'user', 'content': [{'type': 'text', 'text': 'whats in this'}, {'type': 'image_url', 'image_url': {'url': "data:image/png;base64,'/9j/4AAQSk'"}}]},
        #   {'role': 'assistant', 'tool_calls': [{'type': 'function', 'id': '1','function': {'name': 'analyze', 'arguments': '{"baz": "buz"}'}}], 'content': ''},
        #   {'role': 'tool', 'name': 'bar', 'content': 'foobar'},
        #   {'role': 'assistant', 'content': 'thats nice'}
        # ]
        ```

    !!! version-added "Added in `langchain-core` 0.3.11"

    >   blockr   zUnrecognized text_format=z&, expected one of 'string' or 'block'.rL   rq   rO   refusalrr   rt   r   r   rN   )r0   rN   c              3  h   K   | ]*  }t        |t              xs |j                  d       dk(   , ywr0   rN   N)r2   r6   r   r   r	  s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s5      -
 uc"Aeii&76&AA-
s   02rF   c              3  J   K   | ]  }t        |t              r|n|d      ywrN   N)r2   r6   r  s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s*        $E3/U6]B s   !#r0   )rN   z'Unrecognized content block at messages[z
].content[z4] has 'type': 'text' but is missing expected key(s) z. Full content block:

	image_url)r  z9] has 'type': 'image_url' but is missing expected key(s) )r0   r  filefilenamezGenerating a fallback filename.LC_AUTOGENERATEDimagesource)
media_typer0   r\   z>] has 'type': 'image' but 'source' is missing expected key(s) urlzdata:r  ;,r\   )r  formatz:] has key 'image', but 'image' is missing expected key(s) byteszdata:image/r  z;base64,zX] has 'type': 'image' but does not have a 'source' or 'image' key. Full content block:

	file_datainput_audior   )rt   rq   inputz9] has 'type': 'tool_use', but is missing expected key(s) c              3  4   K   | ]  }|d    d    k(    yw)rt   Nr^   r   rw   r	  s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s&      % "$5;6s   r   rC   r  Fensure_asciirq   ru   r0   rt   rC   rK   c              3  L   K   | ]  }|d    j                  d      k(    yw)rt   call_idN)r   r   s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s+      % "$599Y+??s   !$)r&  rq   ru   r&  ru   tool_result)r{   tool_use_idz<] has 'type': 'tool_result', but is missing expected key(s) r{   r(  is_errorerrorsuccess)rr   r   )r  r   zJ] has 'type': 'json' but does not have a 'json' key. Full content block:

guard_contentz;] has 'type': 'guard_content' but does not have a messages[z5]['guard_content']['text'] key. Full content block:

media)	mime_typer\   z/] has 'type': 'media' but does not have key(s) r.  zaOpenAI messages can only support text and image data. Received content block with media of type: >   thinking	reasoningz_] does not match OpenAI, Anthropic, Bedrock Converse, or VertexAI format. Full content block:

c              3  ,   K   | ]  }|d    dk7    ywr  r^   r  s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s      3,1f'3s   c              3  &   K   | ]	  }|d      ywr  r^   r  s     r;   r   z-convert_to_openai_messages.<locals>.<genexpr>  s     #GeE&M#Gs   r   ) rM   r2   r   r3   r6   r   	enumerate_get_message_openai_rolerq   r   rO   _convert_to_openai_tool_callsrP   r   r(   rr   rt   r{   allrR   rQ   r   r   loggerinfo_bytes_to_b64_stranyr   r   dumpsrg   r  )rS   r  r  r  erroai_messages	is_singleirY   oai_msgtool_messagesr{   jrn   missingformatted_blockr  r  	b64_imager:   tool_messagerN   r	  s                         @r;   r  r    s   v --*k^+QRo!Lx+tS)ABByB:"8,H) r;
7!9'!BC  <<%llGFOgy)g.@.@$A'BTBT$UGL!$$((3!(!:!:9!EGIg{+&-&:&:GN#'**#JJGDM'83bG-h&!//$*GOODEH$ -
 -
 *
 ii  $__  G
 G%goo6 H*5eS)NNFE#BCYYv&&0.7"J1E>1"JJwJ(()s*QC 8>&i'@I  )o-NNE&M5=#QRYYv&+5.<"O1"OOwO(()s*QC 8>&i'@I  )o-NN$/).{); +51&B5&IO'++F3v="o5&of.EE$EF>P/
;NN?3ii'72w%7G!&8!44v4'E'"#RXA' 7 #,,-3j <K#*)+DUG!M   #-S/1(3$)*/|0D/EQ+1&>*:!F6N;K)M."
 #())G"444';'"#q~A' 7 #,,-3j <J#*)+DUG!M   #-S/1$5eHog6N$O	(3$)*5eHo5Fhyk(Z."	(()s*QC 81169  )o- IIf%/"599V#4d;"599VR#8#<#<[#I3Oyy,00<D$EF4Ffj1NN5) IIf%6"599]#;TB"599]B#?#C#CF#KSQ"599]B#?#C#CH#MsSNN5)YYv&*4#:#aun# w (()s*QC 8J&i'@I  )o- )-k7)C)N)N  18L"0M--44(2&+Dk,1&M15(-gU2&-"	 YYv&/9 )-k7)C)N)N  &F' ! ~ ' 7 #,,-3j <N#*)+DUG!M   #-S/107L"0M--44(2&+ii	&:,1IIf,=16;1G-"	 3u-YYv&-7#=#%# w (()s*QC 8M&i'@I  )o-#.i(%*=%9*/))J*?wY$L "((2)N
 ii'61foU*(()s*QC 81169  )o-NN$*$(JJuV}$= ii'?:RW?W'u4!)??(()s*QC 8(()s*QC 8;;@'	C  )o- 1&9D!$-#F|NNFD#ABYYv&'1.C"VqPU~1"VVwV(()s*QC 8@@Gy I1169  )o-eK&88  %k 235 
 )o- 1%- @INN$/ %%k0B/C8I;(W* IIf%)BB2NN5)$$%3j 4--2G5  %S/)QH*R h&s 35<3 0 ))#Gw#GG$	??79#5-. 9= 9:e	r;h	 Aa #K #P:'.'`#@'4#n #WsZ   	f?f?2	g<g
	g	g	7	gg	g$g g7	gg	g"g")r   r   c               h   t        |       } | s| S  ||       |k  r?|r;t        t        |             D ]$  }t        | d   |      s| j	                          # | S  | S dt        |       }}t        |       j                         }	t        |	      D ],  }||k\  r n%||z   dz   dz  }
 || d |
       |k  r|
}|
}(|
dz
  }. |}|r|t        |       k  rd}d}t        | |   j                  t               r| |   j                  d      }d}t        |j                        }|dk(  r#t        t        |j                              |_        t        d|      D ]:  }|j                  d d |_         |g | d | |      |k  s*g | d | |} |dz  }d} n |r(|dk(  r#t        t        |j                              |_        |s|s| |   j                  d      }d}d }t        j                  t              r|j                  }nt        |j                  t               ri|j                  r]|j                  D ]N  }t        |t              r|} n:t        |t              s(|j                  d	      d
k(  s=|j                  d
      } n |r|s|j                  d      } ||      } || d |       }|dk(  rt        t        |            }dt        |      }}t        |      j                         }	t        |	      D ]D  }||k\  r n=||z   dz   dz  }
dj                  |d |
       |_        | ||g      z   |k  r|
}@|
dz
  }F |dkD  rB|d | }|dk(  rt        t        |            }dj                  |      |_        g | d | |} |dz  }|r.t        |      D ]   }|dkD  rt        | |dz
     |      s|dz  }  n | d | S )Nr   rf      FT)deepr   r0   rN   r   )r   rangelenr   r   
bit_lengthr2   r{   r   reversedr6   r3   r   rR   )rS   r   r   r   r   r   _leftrightmax_iterationsmididxincluded_partialcopiedexcluded	num_blockrN   r	  split_textsbase_message_countcontent_splitss                        r;   r   r   #  s     H~H X*,3x=) 'f=LLN
  S]%D]--/N>" 5=e|aA%$3(J6DC!GE CC#h-/ hsm++T2}//T/:HFH,,-I6)#'1A1A(B#C 1i( #+#3#3CR#8  !<8DS>!<8!<=K:$3::H1HC'+$  $4$>#'1A1A(B#C #C=333> D(**C0''H,,d38H8H%-- E!%-$!%.599V3D3N$yy0 '222=H+D1%28DS>%B"#v-"&x'<"=K  [!1e!$[!1!<!<!>~. (Au}%<!+1C')ww{4C/@'AH$)M8*,EES" #a( !8%0$%7N'61)-h~.F)G')ww~'>H$:$3::H1HCs 	AQw/q0A6Jq		 DS>r=   )r   r   r   r   c                  t        |       } t        |       dk(  rg S |r:t        t        |             D ]#  }t        | d   |      s| j	                          # n d }	|r+t        |       dkD  rt        | d   t              r
| d   }	| dd  } | d d d   }
|}|	r ||	g      }t        d||z
        }t        |
||||rdnd |      }|d d d   }|	r|	g|}|S )Nr   rH  rf   r   r   )	r   rL  rK  r   r   r2   r%   maxr   )rS   r   r   r   r   r   r   r   rO  system_messagereversed_messagesremaining_tokenssystem_tokensreversed_resultr9   s                  r;   r   r     s
    H~H
8}	 s8}% 	A#HRL&9		 N#h-!+
8A;0V!!AB< !2 "%~&67q*}"<='####0dO TrT"F *6*Mr=   z/dict[type[BaseMessage], type[BaseMessageChunk]]_MSG_CHUNK_MAPc                   | j                   t        v r)t        | j                      di | j                  dh      S t        j                         D ],  \  }}t	        | |      s |di | j                  dh      c S  d| j                    dt        t        j                                }t        |t        j                        }t        |      )Nr0   excludezUnrecognized message class . Supported classes are r   r^   )rh   rc  
model_dumprk   r2   r   keysr   r   r   rM   )rY   msg_cls	chunk_clsr:   s       r;   r   r     s    N*g//0X73E3Evh3E3WXX,224 Egw'Dw116(1CDDE
 &g&7&7%88P##%&
'	)  1S1S
TC
S/r=   c           	        | j                   t        v r*t        | j                      di | j                  h d      S t        j                         D ]-  \  }}t	        | |      s |di | j                  h d      c S  d| j                    dt        t        j                                }t        |t        j                        }t        |      )N>   r0   re   rd   re  z!Unrecognized message chunk class rg  r   r^   )rh   _CHUNK_MSG_MAPrh  rk   r2   r   ri  r   r   r   rM   )rl   rk  rj  r:   s       r;   r   r     s    .(eoo. 
'UV
 	
 -224 	7eY' ""J #   ,EOO+<<T##%&
'	)  1S1S
TC
S/r=   c                f    | j                  d      }|d d D cg c]  }|dz   	 c}|dd  z   S c c}w )NrF   rH  )split)rN   splitsss      r;   r   r     s9    ZZF$Sbk*AH*VBC[88*s   .c                    t        |t        t        f      r|gn|}|D cg c]  }t        |t              s| }}t        d |D              }| j                  |v xs t        | |      S c c}w )Nc              3  B   K   | ]  }t        |t              s|  y wr   )r2   r0   )r   ts     r;   r   z#_is_message_type.<locals>.<genexpr>	  s     @aJq$,?@s   )r2   r6   r0   r   )rY   r_   typesrt  	types_strtypes_typess         r;   r   r     sf     "%#t5UG5E!8qZ3%78I8@5@@K<<9$H
7K(HH 9s
   A*A*c                J    t        j                  |       j                  d      S )Nzutf-8)base64	b64encodedecode)bytes_s    r;   r9  r9    s    F#**733r=   c                   t        | t              ryt        | t              ryt        | t              ryt        | t              rQ| j
                  j                  dd      }t        |t              s#dt        |      j                   }t        |      |S t        | t              ryt        | t              r| j                  S d| j                   d	}t        |      )
Nr|   ry   rD   r~   rB   z,Expected '__openai_role__' to be a str, got rC   zUnknown BaseMessage type r1   )r2   r   r"   r(   r%   rP   r   r6   r0   r7   r5   r    r   rL   rh   rM   )rY   rL   r:   s      r;   r4  r4    s    '9%'<(';''=)((,,->I$$@dATAT@UVCC. '?+';'||%g&7&7%8
:C
S/r=   c           
     v    | D cg c])  }d|d   |d   t        j                  |d   d      dd+ c}S c c}w )	NrC   rt   rq   rx   Fr!  r#  r$  )r   r;  )rO   rw   s     r;   r5  r5  '  sR     $
  D/!&)!ZZ	&(9N	

 
 
s   .6g      @g      @)chars_per_tokenextra_tokens_per_message
count_namec                  d}t        |       D ];  }d}t        |j                  t              r|t	        |j                        z  }n#t        |j                        }|t	        |      z  }t        |t              rIt        |j                  t              s/|j                  r#t        |j                        }|t	        |      z  }t        |t              r|t	        |j                        z  }t        |      }	|t	        |	      z  }|j                  r|r|t	        |j                        z  }|t        j                  ||z        z  }||z  }> t        j                  |      S )a  Approximate the total number of tokens in messages.

    The token count includes stringified message content, role, and (optionally) name.

    - For AI messages, the token count also includes stringified tool calls.
    - For tool messages, the token count also includes the tool call ID.

    Args:
        messages: List of messages to count tokens for.
        chars_per_token: Number of characters per token to use for the approximation.

            One token corresponds to ~4 chars for common English text.

            You can also specify `float` values for more fine-grained control.
            [See more here](https://platform.openai.com/tokenizer).
        extra_tokens_per_message: Number of extra tokens to add per message, e.g.
            special tokens, including beginning/end of message.

            You can also specify `float` values for more fine-grained control.
            [See more here](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb).
        count_name: Whether to include message names in the count.

    Returns:
        Approximate number of tokens in the messages.

    Note:
        This is a simple approximation that may not match the exact token count used by
        specific models. For accurate counts, use model-specific tokenizers.

    Warning:
        This function does not currently support counting image tokens.

    !!! version-added "Added in `langchain-core` 0.3.46"
    g        r   )r   r2   r{   r6   rL  reprr   r   rO   r(   rr   r4  rq   mathceil)
rS   r  r  r  token_countrY   message_charsr{   tool_calls_contentrL   s
             r;   count_tokens_approximatelyr  5  s3   R K&x0 "0goos+S11M 7??+GS\)M w	*w5""!%g&8&8!9S!344Mg{+S!5!566M'0T"<<JS..M
 	tyy!@AA 	//E"0J 99[!!r=   c                    t        |       S )zIWrapper for `count_tokens_approximately` that matches expected signature.)r  )rS   s    r;   _approximate_token_counterr    s    %h//r=   approximate)r8   r   r   r6   )HumanAIrF   )
rS   r   rT   r6   rU   r6   rV   r6   r   r6   )rY   r3   r   r   )rS   zSequence[dict]r   list[BaseMessage])rl   r   r   r   )NNNN)r   r6   r{   r6   rq   
str | Nonerr   r  rO   zlist[dict[str, Any]] | Nonert   r  rP   r   r   r   )rY   MessageLikeRepresentationr   r   )rS   1Iterable[MessageLikeRepresentation] | PromptValuer   r  )r   zSCallable[Concatenate[Sequence[MessageLikeRepresentation] | PromptValue, _P], _R_co]r   r   )rS   r  r   Sequence[str] | Noner   r  r   (Sequence[str | type[BaseMessage]] | Noner   r  r   r  r   r  r   zSequence[str] | bool | Noner   r  )rS   r  r   r6   r   r  )rS   r  r   r   r   znCallable[[list[BaseMessage]], int] | Callable[[BaseMessage], int] | BaseLanguageModel | Literal['approximate']r   zLiteral['first', 'last']r   boolr   Bstr | type[BaseMessage] | Sequence[str | type[BaseMessage]] | Noner   r  r   r  r   z0Callable[[str], list[str]] | TextSplitter | Noner   r  )
rS   _SingleMessager  Literal['string', 'block']r  r  r  r  r   r3   )
rS   _MultipleMessagesr  r  r  r  r  r  r   
list[dict])
rS   z?MessageLikeRepresentation | Sequence[MessageLikeRepresentation]r  r  r  r  r  r  r   zdict | list[dict])rS   r   r   r   r   "Callable[[list[BaseMessage]], int]r   Callable[[str], list[str]]r   zLiteral['first', 'last'] | Noner   r  r   r  )rS   r   r   r   r   r  r   r  r   r  r   r  r   r  r   r  r   r  )rY   r   r   r   )rl   r   r   r   )rN   r6   r   z	list[str])rY   r   r_   z;str | type[BaseMessage] | Sequence[str | type[BaseMessage]]r   r  )r|  r  r   r6   )rY   r   r   r6   )rO   zlist[ToolCall]r   r  )
rS   z#Iterable[MessageLikeRepresentation]r  floatr  r  r  r  r   r   r   )s__doc__
__future__r   ry  r   r   loggingr  collections.abcr   r   r   	functoolsr   r   typingr	   r
   r   r   r   r   r   r   r   r   pydanticr   r   r   langchain_core.exceptionsr   r   langchain_core.messages.air   r   langchain_core.messages.baser   r   0langchain_core.messages.block_translators.openair   langchain_core.messages.chatr   r   langchain_core.messages.contentr    langchain_core.messages.functionr    r!   langchain_core.messages.humanr"   r#    langchain_core.messages.modifierr$   langchain_core.messages.systemr%   r&   langchain_core.messages.toolr'   r(   r)   langchain_core.language_modelsr*   r   r,   r   r-   langchain_text_splittersr.   r   ImportError	getLoggerr7   r7  r<   
AnyMessagerZ   r`   rb   ro   r   r6   r   r3   r  r   r   r   r   r   r   r   r   r   r   r  r   r  r  r   r   rc  __annotations__rk   rm  r   r   r   r   r9  r4  r5  r  r  r   )rn   r8   s   00r;   <module>r     s   #      8 8 $   / . ? @ F G S I : L P P@86*5$(! 
		8	$$ i&'cg../0SV_,-. sx0012 !445	6
 SV_,-. (8 99:; !3+>#??@A  #*<"==>? "C,@$AAB	C $c.D&EEF
G  #*<"==>? 
i013
 H
  !	B3#B3B3 B3 	B3
 	B3J@
50 $s)eCHo-3d38nD  I #.2XXX X 	X
 ,X 	X X Xv9x6?66( t_4(KxE	2 K2@@ )	@*  +/*.>B>B(,(,6:L?L (L (	L
 <L <L &L &L 4L L L^   }?} } 	} }D  *0QUSW FJB?B B	B 'B B OB QB B DB B BJ s"T#s(^3T(RL  
 /7(, , 	
 "& 
 
 
 /7(, , 	
 "&  
 /7(,\M\ ,\ 	\
 "&\ \J 9=QUq#q q 6	q
 .q 6q Oq qt   SWQU4#4 4 6	4
 .4 4 4 Q4 O4 4p #~%!)!C?  $2#7#7#9:41a!Q$: *9
IIFI 
I4*" !&)O"1O" O" $	O"
 O" 	O"f0 - e:  *$)!*v4 ;s   ;M> 0N>N	N	