
    OKie                        S r SSKrSSKrSSKJrJrJr  SSKJr  SSK	J
r
JrJr  SSKJrJrJrJrJr  SSKJr  SSKJrJrJr  SS	KJr  SS
KJr  SSKJr  SSKJ r J!r!J"r"J#r#  SSK$J%r%J&r&  \\\   /\'4   r(Sr)Sr*Sr+Sr,\-\S   \.4   r/ \-\S   \'4   r0 \-\S   \'4   r1 \/\0-  \1-  r2 S\%S\(4S jr3 " S S\ \!\#   \"\#4   5      r4g)zSummarization middleware.    N)CallableIterableMapping)partial)AnyLiteralcast)	AIMessage
AnyMessageMessageLikeRepresentationRemoveMessageToolMessageHumanMessage)count_tokens_approximatelyget_buffer_stringtrim_messages)REMOVE_ALL_MESSAGES)Runtime)override)AgentMiddleware
AgentStateContextT	ResponseT)BaseChatModelinit_chat_modela
  <role>
Context Extraction Assistant
</role>

<primary_objective>
Your sole objective in this task is to extract the highest quality/most relevant context from the conversation history below.
</primary_objective>

<objective_information>
You're nearing the total number of input tokens you can accept, so you must extract the highest quality/most relevant pieces of information from your conversation history.
This context will then overwrite the conversation history presented below. Because of this, ensure the context you extract is only the most important information to continue working toward your overall goal.
</objective_information>

<instructions>
The conversation history below will be replaced with the context you extract in this step.
You want to ensure that you don't repeat any actions you've already completed, so the context you extract from the conversation history should be focused on the most important information to your overall goal.

You should structure your summary using the following sections. Each section acts as a checklist - you must populate it with relevant information or explicitly state "None" if there is nothing to report for that section:

## SESSION INTENT
What is the user's primary goal or request? What overall task are you trying to accomplish? This should be concise but complete enough to understand the purpose of the entire session.

## SUMMARY
Extract and record all of the most important context from the conversation history. Include important choices, conclusions, or strategies determined during this conversation. Include the reasoning behind key decisions. Document any rejected options and why they were not pursued.

## ARTIFACTS
What artifacts, files, or resources were created, modified, or accessed during this conversation? For file modifications, list specific file paths and briefly describe the changes made to each. This section prevents silent loss of artifact information.

## NEXT STEPS
What specific tasks remain to be completed to achieve the session intent? What should you do next?

</instructions>

The user will message you with the full message history from which you'll extract context to create a replacement. Carefully read through it all and think deeply about what information is most important to your overall goal and should be saved:

With all of this in mind, please carefully read over the entire conversation history, and extract the most important and relevant context to replace it so that you can free up space in the conversation history.
Respond ONLY with the extracted context. Do not include any additional information, or text before or after the extracted context.

<messages>
Messages to summarize:
{messages}
</messages>   i     fractiontokensmessagesmodelreturnc                 \    U R                   S:X  a  [        [        SSS9$ [        [        SS9$ )zATune parameters of approximate token counter based on model type.zanthropic-chatTgffffff
@)use_usage_metadata_scalingchars_per_tokenr%   )	_llm_typer   r   )r"   s    k/var/www/html/dynamic-report/venv/lib/python3.13/site-packages/langchain/agents/middleware/summarization.py_get_approximate_token_counterr*      s6    ** &4Y\
 	
 -$OO    c                     ^  \ rS rSrSrSS\4\\\S.S\	\
-  S\\\   -  S-  S\S	\S
\	S\S-  S\SS4U 4S jjjr\S\\   S\\   S\\	\4   S-  4S j5       r\S\\   S\\   S\\	\4   S-  4S j5       rS\\   S\S\4S jrS\\   S\S\4S jrS\\   S\4S jrS\\   S\S-  4S jrS\S-  4S jr\ S\S\	S\4S j5       r!\ S\	S\\"   4S j5       r#\ S\\   SS4S j5       r$\ S \\   S!\S\%\\   \\   4   4S" j5       r&S\\   S#\S\4S$ jr'\ S\\   S!\S\4S% j5       r(S&\\   S\	4S' jr)S&\\   S\	4S( jr*S\\   S\\   4S) jr+S*r,U =r-$ )+SummarizationMiddleware   a+  Summarizes conversation history when token limits are approached.

This middleware monitors message token counts and automatically summarizes older
messages when a threshold is reached, preserving recent messages and maintaining
context continuity by ensuring AI/Tool message pairs remain together.
Nr!   )triggerkeeptoken_countersummary_prompttrim_tokens_to_summarizer"   r/   r0   r1   r2   r3   deprecated_kwargsr#   c                  > SU;   a)  US   n[         R                  " S[        SS9  Uc  Ub  SU4nSU;   a/  US   n[         R                  " S[        SS9  US	[        4:X  a  S	U4n[        TU ]  5         [        U[        5      (       a  [        U5      nXl	        Uc
  SU l
        / n	OZ[        U[        5      (       a*  U V
s/ s H  oR                  U
S
5      PM     nn
Xl
        Un	OU R                  US
5      nXl
        U/n	Xl        U R                  US5      U l        U[        L a4  [!        U R                  5      U l        [%        U R"                  SS9U l        OX@l        X@l        XPl        X`l        [-        S U R                   5       5      nU R                  S   S:X  a  SnU(       a  U R/                  5       c  Sn[1        U5      eggs  sn
f )aW  Initialize summarization middleware.

Args:
    model: The language model to use for generating summaries.
    trigger: One or more thresholds that trigger summarization.

        Provide a single
        [`ContextSize`][langchain.agents.middleware.summarization.ContextSize]
        tuple or a list of tuples, in which case summarization runs when any
        threshold is met.

        !!! example

            ```python
            # Trigger summarization when 50 messages is reached
            ("messages", 50)

            # Trigger summarization when 3000 tokens is reached
            ("tokens", 3000)

            # Trigger summarization either when 80% of model's max input tokens
            # is reached or when 100 messages is reached (whichever comes first)
            [("fraction", 0.8), ("messages", 100)]
            ```

            See [`ContextSize`][langchain.agents.middleware.summarization.ContextSize]
            for more details.
    keep: Context retention policy applied after summarization.

        Provide a [`ContextSize`][langchain.agents.middleware.summarization.ContextSize]
        tuple to specify how much history to preserve.

        Defaults to keeping the most recent `20` messages.

        Does not support multiple values like `trigger`.

        !!! example

            ```python
            # Keep the most recent 20 messages
            ("messages", 20)

            # Keep the most recent 3000 tokens
            ("tokens", 3000)

            # Keep the most recent 30% of the model's max input tokens
            ("fraction", 0.3)
            ```
    token_counter: Function to count tokens in messages.
    summary_prompt: Prompt template for generating summaries.
    trim_tokens_to_summarize: Maximum tokens to keep when preparing messages for
        the summarization call.

        Pass `None` to skip trimming entirely.
max_tokens_before_summaryzOmax_tokens_before_summary is deprecated. Use trigger=('tokens', value) instead.   )
stacklevelNr    messages_to_keepzEmessages_to_keep is deprecated. Use keep=('messages', value) instead.r!   r/   r0   Fr'   c              3   0   #    U  H  oS    S:H  v   M     g7f)r   r   N ).0	conditions     r)   	<genexpr>3SummarizationMiddleware.__init__.<locals>.<genexpr>  s     dKci|z9Kcs   r   r   Ta  Model profile information is required to use fractional token limits, and is unavailable for the specified model. Please use absolute token counts instead, or pass `

ChatModel(..., profile={"max_input_tokens": ...})`.

with a desired integer value of the model's maximum input tokens.)warningswarnDeprecationWarning_DEFAULT_MESSAGES_TO_KEEPsuper__init__
isinstancestrr   r"   r/   list_validate_context_size_trigger_conditionsr0   r   r*   r1   r   _partial_token_counterr2   r3   any_get_profile_limits
ValueError)selfr"   r/   r0   r1   r2   r3   r4   valuetrigger_conditionsitemvalidated_list	validatedrequires_profilemsg	__class__s                  r)   rE    SummarizationMiddleware.__init__   s   F '*;;%&ABEMMa"
 5#4#U+!22%&89EMMW"
 
$=>>"E*eS!!#E*E
?CGDL46&&W^_W^t99$	JW^N_)L!/33GYGI$L"+#5 //f=	66!?

!KD8?""u9D' "/*7',(@%d4KcKcdd99Q<:%# 8 8 : BT  S/! !C1 `s    Gstateruntimec                 @   US   nU R                  U5        U R                  U5      nU R                  X45      (       d  gU R                  U5      nUS::  a  gU R	                  X55      u  pgU R                  U5      nU R                  U5      n	S[        [        S9/U	QUQ0$ zProcess messages before model invocation, potentially triggering summarization.

Args:
    state: The agent state.
    runtime: The runtime environment.

Returns:
    An updated state with summarized messages if summarization was performed.
r!   Nr   )id)	_ensure_message_idsr1   _should_summarize_determine_cutoff_index_partition_messages_create_summary_build_new_messagesr   r   
rO   rY   rZ   r!   total_tokenscutoff_indexmessages_to_summarizepreserved_messagessummarynew_messagess
             r)   before_model$SummarizationMiddleware.before_model$  s     $  *))(3%%h==33H=1484L4LX4d1&&'<=//8 !45 $
 	
r+   c                 \  #    US   nU R                  U5        U R                  U5      nU R                  X45      (       d  gU R                  U5      nUS::  a  gU R	                  X55      u  pgU R                  U5      I Sh  vN nU R                  U5      n	S[        [        S9/U	QUQ0$  N)7fr\   )	r^   r1   r_   r`   ra   _acreate_summaryrc   r   r   rd   s
             r)   abefore_model%SummarizationMiddleware.abefore_modelJ  s      $  *))(3%%h==33H=1484L4LX4d1--.CDD//8 !45 $
 	
 Es   A>B, B**B,	thresholdc                 n   [        S [        U5       5       S5      n[        U[        5      (       a  UR                  bw  UR                  R                  SS5      =n(       aT  XB:  aO  UR                  R                  S5      =n(       a-  XPR                  R                  5       R                  S5      :X  a  gg)	zDCheck if reported token usage from last AIMessage exceeds threshold.c              3   T   #    U  H  n[        U[        5      (       d  M  Uv   M      g 7f)N)rF   r
   )r<   rV   s     r)   r>   USummarizationMiddleware._should_summarize_based_on_reported_tokens.<locals>.<genexpr>u  s     M.S*S)2LSS.s   (	(Nre   model_providerls_providerTF)	nextreversedrF   r
   usage_metadatagetresponse_metadatar"   _get_ls_params)rO   r!   rq   last_ai_messagereported_tokensmessage_providers         r)   *_should_summarize_based_on_reported_tokensBSummarizationMiddleware._should_summarize_based_on_reported_tokensp  s     MHX.M

 	22..:$3$B$B$F$F~WY$ZZZ,%4%F%F%J%JK[%\\!\ JJ$=$=$?$C$CM$RRr+   re   c                 x   U R                   (       d  gU R                    H  u  p4US:X  a  [        U5      U:  a    gUS:X  a  X$:  a    gUS:X  a  U R                  X5      (       a    gUS:X  d  MO  U R                  5       nUc  Md  [	        XT-  5      nUS::  a  SnX&:  a    gU R                  X5      (       d  M    g   g)zGDetermine whether summarization should run for the current token usage.Fr!   Tr    r   r      )rJ   lenr   rM   int)rO   r!   re   kindrP   max_input_tokensrq   s          r)   r_   )SummarizationMiddleware._should_summarize  s    ''33KDz!c(mu&<xL$9xD$S$S% % z!#'#;#;#= #+ 0 89	> !I,BB8WW) 4* r+   c                     U R                   u  p#US;   a,  U R                  U5      nUb  U$ U R                  U[        5      $ U R                  U[	        SU5      5      $ )z7Choose cutoff index respecting retention configuration.>   r    r   r   )r0   _find_token_based_cutoff_find_safe_cutoffrC   r	   )rO   r!   r   rP   token_based_cutoffs        r)   r`   /SummarizationMiddleware._determine_cutoff_index  sc    ii))!%!>!>x!H!-)) ))(4MNN%%hUE0BCCr+   c                 h   U(       d  gU R                   u  p#US:X  a"  U R                  5       nUc  g[        XC-  5      nOUS:X  a  [        U5      nOgUS::  a  SnU R                  U5      U::  a  gS[	        U5      pv[	        U5      n[	        U5      R                  5       S-   n	[        U	5       H3  n
Xg:  a    O-Xg-   S-  nU R                  XS 5      U::  a  UnUnM.  US-   nM5     U[	        U5      :X  a  UnU[	        U5      :  a  [	        U5      S:X  a  g[	        U5      S-
  nU R                  X5      $ )z2Find cutoff index based on target token retention.r   r   Nr    r   r7   )	r0   rM   r   r1   r   
bit_lengthrangerK   _find_safe_cutoff_point)rO   r!   r   rP   r   target_token_countleftrightcutoff_candidatemax_iterations_mids               r)   r   0SummarizationMiddleware._find_token_based_cutoff  sJ   ii:#779'!$%5%=!>X!$U"!"h'+== Xex=X113a7~&A}<A%C**8D>:>PP#& Qw ' s8},#s8},8}!"8}q0 ++HGGr+   c                      U R                   R                  n[        U[        5      (       d  gUR                  S5      n[        U[        5      (       d  gU$ ! [         a     gf = f)z6Retrieve max input token limit from the model profile.Nr   )r"   profileAttributeErrorrF   r   r{   r   )rO   r   r   s      r)   rM   +SummarizationMiddleware._get_profile_limits  sc    	jj((G '7++";;'9:*C00  		s   A 
A$#A$contextparameter_namec                     U u  p#US:X  a&  SUs=:  a  S::  d  O  SU SU S3n[        U5      e U $ US;   a  US::  a  U SU S3n[        U5      e U $ S	U S
U S3n[        U5      e)z&Validate context configuration tuples.r   r   r   zFractional z% values must be between 0 and 1, got .>   r    r!   z( thresholds must be greater than 0, got zUnsupported context size type z for )rN   )r   r   r   rP   rV   s        r)   rI   .SummarizationMiddleware._validate_context_size  s     :u>>#N#33XY^X__`a o% "  ++z'((PQVPWWXY o%   34&n=MQOCS/!r+   ri   c                 "    [        SU  3SS0S9/$ )Nz0Here is a summary of the conversation to date:

	lc_sourcesummarization)contentadditional_kwargsr   )ri   s    r)   rc   +SummarizationMiddleware._build_new_messages  s(     LWIV#."@
 	
r+   c                 z    U  H5  nUR                   b  M  [        [        R                  " 5       5      Ul         M7     g)zAEnsure all messages have unique IDs for the add_messages reducer.N)r]   rG   uuiduuid4)r!   rV   s     r)   r^   +SummarizationMiddleware._ensure_message_ids  s)     Cvv~TZZ\* r+   conversation_messagesrf   c                     U SU nXS nX#4$ )zAPartition messages into those to summarize and those to preserve.Nr;   )r   rf   rg   rh   s       r)   ra   +SummarizationMiddleware._partition_messages  s%     !6m| D2=A$88r+   r9   c                 `    [        U5      U::  a  g[        U5      U-
  nU R                  X5      $ )a^  Find safe cutoff point that preserves AI/Tool message pairs.

Returns the index where messages can be safely cut without separating
related AI and Tool messages. Returns `0` if no safe cutoff is found.

This is aggressive with summarization - if the target cutoff lands in the
middle of tool messages, we advance past all of them (summarizing more).
r   )r   r   )rO   r!   r9   target_cutoffs       r)   r   )SummarizationMiddleware._find_safe_cutoff  s4     x=,,H(88++HDDr+   c                    U[        U 5      :  d  [        X   [        5      (       d  U$ [        5       nUnU[        U 5      :  a~  [        X   [        5      (       ag  [	        SX   5      nUR
                  (       a  UR                  UR
                  5        US-  nU[        U 5      :  a  [        X   [        5      (       a  Mg  [        US-
  SS5       H  nX   n[        U[        5      (       d  M  UR                  (       d  M1  UR                   Vs1 s H+  owR                  S5      (       d  M  UR                  S5      iM-     nnX(-  (       d  M~  Us  $    U$ s  snf )a  Find a safe cutoff point that doesn't split AI/Tool message pairs.

If the message at `cutoff_index` is a `ToolMessage`, search backward for the
`AIMessage` containing the corresponding `tool_calls` and adjust the cutoff to
include it. This ensures tool call requests and responses stay together.

Falls back to advancing forward past `ToolMessage` objects only if no matching
`AIMessage` is found (edge case).
r   r   ru   r]   )r   rF   r   setr	   tool_call_idaddr   r
   
tool_callsr{   )	r!   rf   tool_call_idsidxtool_msgirV   tcai_tool_call_idss	            r)   r   /SummarizationMiddleware._find_safe_cutoff_point(  s    3x=(
8;QS^0_0_ #&%CM!j&L&LM8=9H$$!!("7"781HC	 CM!j&L&L |a'R0A+C#y))cnnn;>>>#Z>RVVTX\LBFF4L> #Z 33H 1 
 $[s   E.Erg   c                 P   U(       d  gU R                  U5      nU(       d  g[        U5      n U R                  R                  U R                  R                  US9R                  5       SSS00S9nUR                  R                  5       $ ! [         a  nSU< 3s S	nA$ S	nAff = f)
bGenerate summary for the given messages.

Args:
    messages_to_summarize: Messages to summarize.
!No previous conversation history.0Previous conversation was too long to summarize.r!   metadatar   r   configError generating summary: N)
_trim_messages_for_summaryr   r"   invoker2   formatrstriptextstrip	ExceptionrO   rg   trimmed_messagesformatted_messagesresponsees         r)   rb   'SummarizationMiddleware._create_summaryL  s     %6::;PQE //?@	6zz((##**4F*GNNP"[/$BC ) H ==&&(( 	6/u55	6s   AB 
B%B B% B%c                 l  #    U(       d  gU R                  U5      nU(       d  g[        U5      n U R                  R                  U R                  R                  US9R                  5       SSS00S9I Sh  vN nUR                  R                  5       $  N! [         a  nS	U< 3s SnA$ SnAff = f7f)
r   r   r   r   r   r   r   r   Nr   )
r   r   r"   ainvoker2   r   r   r   r   r   r   s         r)   rn   (SummarizationMiddleware._acreate_summaryf  s      %6::;PQE //?@	6!ZZ//##**4F*GNNP"[/$BC 0  H ==&&((	
  	6/u55	6sG   -B4AB 6B7B B4B 
B1!B,&B1'B4,B11B4c                      U R                   c  U$ [        S[        UU R                   U R                  SSSSS95      $ ! [         a    U[
        * S s $ f = f)z6Trim messages to fit within summary generation limits.Nzlist[AnyMessage]humanlastT)
max_tokensr1   start_onstrategyallow_partialinclude_system)r3   r	   r   r1   r   _DEFAULT_FALLBACK_MESSAGE_COUNT)rO   r!   s     r)   r   2SummarizationMiddleware._trim_messages_for_summary  st    	?,,4"#<<"&"4"4$#"&#'   	?<<=>>	?s   > ,> AA)rK   rJ   r0   r"   r2   r1   r/   r3   ).__name__
__module____qualname____firstlineno____doc__rC   r   DEFAULT_SUMMARY_PROMPT_DEFAULT_TRIM_TOKEN_LIMITrG   r   ContextSizerH   TokenCounterr   r   rE   r   r   r   r   dictrk   ro   r   floatboolr   r_   r`   r   rM   staticmethodrI   r   rc   r^   tuplera   r   r   rb   rn   r   __static_attributes____classcell__)rW   s   @r)   r-   r-      s    ;?')BC&@4/HA"]"A" tK0047	A"
 A" $A" A" #&*A" !A" 
A" A"F #
_#
/6x/@#
	c3h$	#
 #
J #
_#
/6x/@#
	c3h$	#
 #
JZ(5:	&$z*: # RV 8
DZ0@ 
DS 
D/Hj1A /HcDj /Hb S4Z  "  S [    
S 
T,-? 
 
 +d:&6 +4 + + 9#J/99 
tJj!11	29 9E$z*: Ec EVY E !$z*: !# !RU ! !F6T*5E 6# 646D<L 6QT 64?4
3C ?ZHX ? ?r+   r-   )5r   r   r@   collections.abcr   r   r   	functoolsr   typingr   r   r	   langchain_core.messagesr
   r   r   r   r   langchain_core.messages.humanr   langchain_core.messages.utilsr   r   r   langgraph.graph.messager   langgraph.runtimer   typing_extensionsr   !langchain.agents.middleware.typesr   r   r   r   langchain.chat_modelsr   r   r   r   r   rC   r   r   r   r   ContextFractionContextTokensContextMessagesr   r*   r-   r;   r+   r)   <module>r     s      7 7  % %  7 
 & & ^ ^ @";<=sBC) V    "$ 
+U23 gh',- 
+S01 -?8P- PL Py?oj.CXy.XY y?r+   