@@ -155,15 +155,27 @@ def format_header(header_type: str) -> str:
155
155
156
156
# Format messages with appropriate headers
157
157
formatted_messages = []
158
- for msg in to_summarize : # No need for slice when iterating full list
158
+ image_urls = [] # Track image URLs for the summary prompt
159
+
160
+ for msg in to_summarize :
159
161
if isinstance (msg , HumanMessage ):
160
- formatted_messages .append (format_header ("human" ) + msg .content )
162
+ # Now we know content is always a list
163
+ for item in msg .content :
164
+ if item .get ("type" ) == "text" :
165
+ text_content = item .get ("text" , "" )
166
+ if text_content :
167
+ formatted_messages .append (format_header ("human" ) + text_content )
168
+ elif item .get ("type" ) == "image_url" :
169
+ image_url = item .get ("image_url" , {}).get ("url" )
170
+ if image_url :
171
+ # We are not including any string data in the summary for image. The image will be present itself!
172
+ image_urls .append ({"type" : "image_url" , "image_url" : {"url" : image_url }})
161
173
elif isinstance (msg , AIMessage ):
162
174
# Check for summary message using additional_kwargs
163
175
if msg .additional_kwargs .get ("is_summary" ):
164
176
formatted_messages .append (format_header ("summary" ) + msg .content )
165
177
elif isinstance (msg .content , list ) and len (msg .content ) > 0 and isinstance (msg .content [0 ], dict ):
166
- for item in msg .content : # No need for slice when iterating full list
178
+ for item in msg .content :
167
179
if item .get ("type" ) == "text" :
168
180
formatted_messages .append (format_header ("ai" ) + item ["text" ])
169
181
elif item .get ("type" ) == "tool_use" :
@@ -173,16 +185,25 @@ def format_header(header_type: str) -> str:
173
185
elif isinstance (msg , ToolMessage ):
174
186
formatted_messages .append (format_header ("tool_response" ) + msg .content )
175
187
176
- conversation = "\n " .join (formatted_messages ) # No need for slice when joining full list
188
+ conversation = "\n " .join (formatted_messages )
177
189
178
190
summary_llm = LLM (
179
191
model_provider = "anthropic" ,
180
192
model_name = "claude-3-5-sonnet-latest" ,
181
193
temperature = 0.3 ,
182
194
)
183
195
184
- chain = ChatPromptTemplate .from_template (SUMMARIZE_CONVERSATION_PROMPT ) | summary_llm
185
- new_summary = chain .invoke ({"conversation" : conversation }).content
196
+ # Choose template based on whether we have images
197
+ summarizer_content = [{"type" : "text" , "text" : SUMMARIZE_CONVERSATION_PROMPT }]
198
+ for image_url in image_urls :
199
+ summarizer_content .append (image_url )
200
+
201
+ chain = ChatPromptTemplate ([("human" , summarizer_content )]) | summary_llm
202
+ new_summary = chain .invoke (
203
+ {
204
+ "conversation" : conversation ,
205
+ }
206
+ ).content
186
207
187
208
return {"messages" : {"type" : "summarize" , "summary" : new_summary , "tail" : tail , "head" : head }}
188
209
@@ -199,7 +220,7 @@ def should_continue(self, state: GraphState) -> Literal["tools", "summarize_conv
199
220
return "summarize_conversation"
200
221
201
222
# Summarize if the last message exceeds the max input tokens of the model - 10000 tokens
202
- elif isinstance (last_message , AIMessage ) and not just_summarized and curr_input_tokens > (max_input_tokens - 10000 ):
223
+ elif isinstance (last_message , AIMessage ) and not just_summarized and curr_input_tokens > (max_input_tokens - 30000 ):
203
224
return "summarize_conversation"
204
225
205
226
elif hasattr (last_message , "tool_calls" ) and last_message .tool_calls :
0 commit comments