keyvan-Re commited on
Commit
882c22c
·
unverified ·
1 Parent(s): f832132

Update summarize_memory.py

Browse files
Files changed (1) hide show
  1. memory_bank/summarize_memory.py +160 -167
memory_bank/summarize_memory.py CHANGED
@@ -1,4 +1,5 @@
1
  # -*- coding: utf-8 -*-
 
2
  import sys
3
  import os
4
  import json
@@ -8,8 +9,6 @@ import argparse
8
  from typing import Dict, Any
9
  from openai import OpenAI
10
  import re
11
-
12
-
13
  import openai
14
 
15
  # Add memory bank path
@@ -55,7 +54,6 @@ class LLMClientSimple:
55
  while response is None and count < retry_times:
56
  try:
57
  request = copy.deepcopy(self.gen_config)
58
- # print(prompt)
59
 
60
  # System prompt setup based on language
61
  if language == 'cn':
@@ -73,22 +71,21 @@ class LLMClientSimple:
73
  {"role": "user", "content": f"{prompt}"}
74
  ]
75
 
76
- # فراخوانی متد جدید
77
  response = self.client.chat.completions.create(**request, messages=message)
78
- # print(prompt)
79
 
80
  except Exception as e:
81
  print(e)
82
- # بررسی متن خطا در نسخه جدید ممکن است کمی متفاوت باشد
83
  if 'context' in str(e).lower() or 'maximum' in str(e).lower():
84
  cut_length = 1800 - 200 * count
85
- print('max context length reached, cut to {}'.format(cut_length))
86
  prompt = prompt[-cut_length:]
87
  response = None
88
  count += 1
89
 
90
  if response:
91
- # خواندن محتوای پاسخ با استفاده از سینتکس شی‌گرا (Dot notation)
92
  task_desc = response.choices[0].message.content
93
  else:
94
  task_desc = ''
@@ -96,7 +93,7 @@ class LLMClientSimple:
96
  return task_desc
97
 
98
 
99
- # خط 94 — lazy initialization به جای module-level
100
  _llm_client = None
101
 
102
  def get_llm_client():
@@ -214,183 +211,179 @@ def extract_session_summary(conversation_text, session_date, session_id):
214
 
215
  response = get_llm_client().generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
216
 
217
-
218
- # پاکسازی کاراکترهای اضافی و تگ‌های مارک‌داون
219
- response = response.strip()
220
- if response.startswith("```json"):response = response[7:]
221
- elif response.startswith("```"):response = response[3:]
222
- if response.endswith("```"):response = response[:-3]
223
  response = response.strip()
224
- try:
225
- episodic_memory = json.loads(response)
226
- except json.JSONDecodeError:
227
- print("⚠️ Failed to parse episodic memory response!")
228
- episodic_memory = {
229
- "topics_discussed": ["N/A"],
230
- "emotional_state": "unknown",
231
- "insights": "No insights extracted."
232
- }
 
 
 
 
 
 
 
233
 
234
- # Add session metadata
235
- episodic_memory["session_date"] = session_date
236
- episodic_memory["session_id"] = session_id # Store session index
237
 
238
- return episodic_memory
239
 
240
 
241
  def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
242
- """
243
- Updates semantic memory based on the latest episodic memory.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
- Args:
246
- latest_episodic_memory (dict): The most recent episodic memory entry.
247
- existing_semantic_memory (dict): Current state of the user's semantic memory.
248
 
249
- Returns:
250
- dict: Updated semantic memory.
251
- """
252
- # Use the insights from episodic memory to infer stable traits and patterns
253
- semantic_prompt = f"""
254
- Please analyze the following session summary and infer long-term personality traits and stable characteristics:
255
- Session Summary:
256
- {json.dumps(latest_episodic_memory, indent=4)}
257
-
258
- Update the user's semantic memory with:
259
- 1. Evolving personality traits (Big Five).
260
- 2. Core values and recurring motivations.
261
- 3. Behavioral patterns and consistent emotional responses.
262
- 4. Frequent topics and recurring themes.
263
 
264
- Format response as JSON:
265
- {{
266
- "personality_traits": {{
267
- "openness": 0.0,
268
- "conscientiousness": 0.0,
269
- "extraversion": 0.0,
270
- "agreeableness": 0.0,
271
- "neuroticism": 0.0
272
- }},
273
- "core_values": [],
274
- "behavioral_patterns": [],
275
- "recurring_themes": []
276
- }}
277
- """
278
 
279
- response = get_llm_client().generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
 
280
 
281
- # استخراج امن JSON با استفاده از Regex
282
- try:
283
- # پیدا کردن محتوای بین اولین { و آخرین }
284
- json_match = re.search(r'\{.*\}', response, re.DOTALL)
285
- if json_match:
286
- json_str = json_match.group(0)
287
- new_semantic_data = json.loads(json_str)
288
- else:
289
- raise ValueError("No JSON object found in response.")
290
-
291
- except Exception as e:
292
- print(f"⚠️ Failed to parse semantic memory response! Error: {e}")
293
- print(f"LLM Response was:\n{response}") # چاپ خروجی خام برای خطایابی
294
- return existing_semantic_memory
295
-
296
- # Merge new data into semantic memory
297
- updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
298
-
299
- # Update or average personality traits
300
- for trait, value in new_semantic_data.get("personality_traits", {}).items():
301
- try:
302
- val_float = float(value)
303
- except (ValueError, TypeError):
304
- val_float = 0.0
305
-
306
- if trait in updated_semantic_memory.get("personality_traits", {}):
307
- existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
308
- updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
309
- else:
310
- updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
311
 
312
- # Combine core values, avoiding duplicates
313
- updated_semantic_memory["core_values"] = list(set(
314
- updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
315
- ))
316
 
317
- # Combine behavioral patterns
318
- updated_semantic_memory["behavioral_patterns"] = list(set(
319
- updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
320
- ))
321
 
322
- # Combine recurring themes
323
- updated_semantic_memory["recurring_themes"] = list(set(
324
- updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
325
- ))
326
 
327
- print("\n✅ Semantic memory updated successfully!")
328
- return updated_semantic_memory
 
 
 
 
329
 
 
 
 
 
 
330
 
331
- # --- Main Logic ---
 
 
332
 
333
- def summarize_memory(memory_dir, name=None, language='en'):
334
- boot_name = 'AI'
335
- gen_prompt_num = 1
336
-
337
- with open(memory_dir, 'r', encoding='utf8') as f:
338
- memory = json.loads(f.read())
339
-
340
- for k, v in memory.items():
341
- if name is not None and k != name:
342
- continue
343
-
344
- user_name = k
345
- print(f'Updating memory for user {user_name}')
346
-
347
- if v.get('history') is None:
348
- continue
349
-
350
- history = v['history']
351
-
352
- if v.get('summary') is None:
353
- memory[user_name]['summary'] = {}
354
- if v.get('personality') is None:
355
- memory[user_name]['personality'] = {}
356
- if v.get('issues') is None:
357
- memory[user_name]['issues'] = {}
358
-
359
- for date, content in history.items():
360
- # Check flags to see if update is needed
361
- his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
362
- person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
363
- problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
364
-
365
- hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
366
- issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
367
- person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
368
-
369
- if his_flag:
370
- his_summary = get_llm_client().generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
371
- memory[user_name]['summary'][date] = {'content': his_summary}
372
-
373
- if problem_flag:
374
- issues_summary = get_llm_client().generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
375
- memory[user_name]['issues'][date] = {'content': issues_summary}
376
- print(issues_summary)
377
-
378
- if person_flag:
379
- person_summary = get_llm_client().generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
380
- memory[user_name]['personality'][date] = person_summary
381
-
382
- overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
383
- overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
384
-
385
- memory[user_name]['overall_history'] = get_llm_client().generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
386
- memory[user_name]['overall_personality'] = get_llm_client().generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
387
 
388
- with open(memory_dir, 'w', encoding='utf8') as f:
389
- print(f'Successfully updated memory for {name}')
390
- json.dump(memory, f, ensure_ascii=False)
391
- return memory
392
 
393
 
394
  if __name__ == '__main__':
395
- target_memory = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'memories', 'eng_memory_cases.json')
396
- summarize_memory(target_memory, language='en')
 
 
1
  # -*- coding: utf-8 -*-
2
+
3
  import sys
4
  import os
5
  import json
 
9
  from typing import Dict, Any
10
  from openai import OpenAI
11
  import re
 
 
12
  import openai
13
 
14
  # Add memory bank path
 
54
  while response is None and count < retry_times:
55
  try:
56
  request = copy.deepcopy(self.gen_config)
 
57
 
58
  # System prompt setup based on language
59
  if language == 'cn':
 
71
  {"role": "user", "content": f"{prompt}"}
72
  ]
73
 
74
+ # Call the API method
75
  response = self.client.chat.completions.create(**request, messages=message)
 
76
 
77
  except Exception as e:
78
  print(e)
79
+ # Check for context limit errors
80
  if 'context' in str(e).lower() or 'maximum' in str(e).lower():
81
  cut_length = 1800 - 200 * count
82
+ print('Max context length reached, cut to {}'.format(cut_length))
83
  prompt = prompt[-cut_length:]
84
  response = None
85
  count += 1
86
 
87
  if response:
88
+ # Get response content using dot notation
89
  task_desc = response.choices[0].message.content
90
  else:
91
  task_desc = ''
 
93
  return task_desc
94
 
95
 
96
+ # Lazy initialization instead of module-level
97
  _llm_client = None
98
 
99
  def get_llm_client():
 
211
 
212
  response = get_llm_client().generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
213
 
214
+ # Remove extra characters and markdown tags
 
 
 
 
 
215
  response = response.strip()
216
+ if response.startswith("
217
+ ```json"): response = response[7:]
218
+ elif response.startswith("
219
+ ```"): response = response[3:]
220
+ if response.endswith("
221
+ ```"): response = response[:-3]
222
+ response = response.strip()
223
+ try:
224
+ episodic_memory = json.loads(response)
225
+ except json.JSONDecodeError:
226
+ print("⚠️ Failed to parse episodic memory response!")
227
+ episodic_memory = {
228
+ "topics_discussed": ["N/A"],
229
+ "emotional_state": "unknown",
230
+ "insights": "No insights extracted."
231
+ }
232
 
233
+ # Add session metadata
234
+ episodic_memory["session_date"] = session_date
235
+ episodic_memory["session_id"] = session_id # Store session index
236
 
237
+ return episodic_memory
238
 
239
 
240
  def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
241
+ """
242
+ Updates semantic memory based on the latest episodic memory.
243
+ """
244
+ # Use the insights from episodic memory to infer stable traits and patterns
245
+ semantic_prompt = f"""
246
+ Please analyze the following session summary and infer long-term personality traits and stable characteristics:
247
+ Session Summary:
248
+ {json.dumps(latest_episodic_memory, indent=4)}
249
+
250
+ Update the user's semantic memory with:
251
+ 1. Evolving personality traits (Big Five).
252
+ 2. Core values and recurring motivations.
253
+ 3. Behavioral patterns and consistent emotional responses.
254
+ 4. Frequent topics and recurring themes.
255
+
256
+ Format response as JSON:
257
+ {{
258
+ "personality_traits": {{
259
+ "openness": 0.0,
260
+ "conscientiousness": 0.0,
261
+ "extraversion": 0.0,
262
+ "agreeableness": 0.0,
263
+ "neuroticism": 0.0
264
+ }},
265
+ "core_values": [],
266
+ "behavioral_patterns": [],
267
+ "recurring_themes": []
268
+ }}
269
+ """
270
+
271
+ response = get_llm_client().generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
272
+
273
+ # Safe JSON extraction using Regex
274
+ try:
275
+ # Find content between first { and last }
276
+ json_match = re.search(r'\{.*\}', response, re.DOTALL)
277
+ if json_match:
278
+ json_str = json_match.group(0)
279
+ new_semantic_data = json.loads(json_str)
280
+ else:
281
+ raise ValueError("No JSON object found in response.")
282
+
283
+ except Exception as e:
284
+ print(f"⚠️ Failed to parse semantic memory response! Error: {e}")
285
+ print(f"LLM Response was:\n{response}")
286
+ return existing_semantic_memory
287
+
288
+ # Merge new data into semantic memory
289
+ updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
290
+
291
+ # Update or average personality traits
292
+ for trait, value in new_semantic_data.get("personality_traits", {}).items():
293
+ try:
294
+ val_float = float(value)
295
+ except (ValueError, TypeError):
296
+ val_float = 0.0
297
+
298
+ if trait in updated_semantic_memory.get("personality_traits", {}):
299
+ existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
300
+ updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
301
+ else:
302
+ updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
303
+
304
+ # Combine core values, avoiding duplicates
305
+ updated_semantic_memory["core_values"] = list(set(
306
+ updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
307
+ ))
308
+
309
+ # Combine behavioral patterns
310
+ updated_semantic_memory["behavioral_patterns"] = list(set(
311
+ updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
312
+ ))
313
+
314
+ # Combine recurring themes
315
+ updated_semantic_memory["recurring_themes"] = list(set(
316
+ updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
317
+ ))
318
+
319
+ print("\n✅ Semantic memory updated successfully!")
320
+ return updated_semantic_memory
321
 
 
 
 
322
 
323
+ # --- Main Logic ---
 
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
+ def summarize_memory(memory_dir, name=None, language='en'):
326
+ boot_name = 'AI'
327
+ gen_prompt_num = 1
 
 
 
 
 
 
 
 
 
 
 
328
 
329
+ with open(memory_dir, 'r', encoding='utf8') as f:
330
+ memory = json.loads(f.read())
331
 
332
+ for k, v in memory.items():
333
+ if name is not None and k != name:
334
+ continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
+ user_name = k
337
+ print(f'Updating memory for user {user_name}')
 
 
338
 
339
+ if v.get('history') is None:
340
+ continue
 
 
341
 
342
+ history = v['history']
 
 
 
343
 
344
+ if v.get('summary') is None:
345
+ memory[user_name]['summary'] = {}
346
+ if v.get('personality') is None:
347
+ memory[user_name]['personality'] = {}
348
+ if v.get('issues') is None:
349
+ memory[user_name]['issues'] = {}
350
 
351
+ for date, content in history.items():
352
+ # Check flags to see if update is needed
353
+ his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
354
+ person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
355
+ problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
356
 
357
+ hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
358
+ issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
359
+ person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
360
 
361
+ if his_flag:
362
+ his_summary = get_llm_client().generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
363
+ memory[user_name]['summary'][date] = {'content': his_summary}
364
+
365
+ if problem_flag:
366
+ issues_summary = get_llm_client().generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
367
+ memory[user_name]['issues'][date] = {'content': issues_summary}
368
+ print(issues_summary)
369
+
370
+ if person_flag:
371
+ person_summary = get_llm_client().generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
372
+ memory[user_name]['personality'][date] = person_summary
373
+
374
+ overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
375
+ overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
376
+
377
+ memory[user_name]['overall_history'] = get_llm_client().generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
378
+ memory[user_name]['overall_personality'] = get_llm_client().generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
+ with open(memory_dir, 'w', encoding='utf8') as f:
381
+ print(f'Successfully updated memory for {name}')
382
+ json.dump(memory, f, ensure_ascii=False)
383
+ return memory
384
 
385
 
386
  if __name__ == '__main__':
387
+ target_memory = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'memories', 'eng_memory_cases.json')
388
+ summarize_memory(target_memory, language='en')
389
+