EMMA commited on
Commit
1f55154
·
1 Parent(s): 9537042

Fix gradio version conflict

Browse files
memory_bank/summarize_memory.py CHANGED
@@ -193,197 +193,241 @@ def extract_session_summary(conversation_text, session_date, session_id):
193
  """
194
  # Prompt to the LLM to extract insights
195
  insight_prompt = f"""
196
- Please analyze the following conversation and extract key information:
197
- Conversation:
198
- {conversation_text}
199
 
200
- 1. Topics discussed (as a list)
201
- 2. User's emotional state (e.g., happy, anxious, stressed)
202
- 3. Key insights or takeaways (what the user is feeling or thinking)
203
 
204
- Format response as JSON:
205
- {{
206
- "topics_discussed": [],
207
- "emotional_state": "",
208
- "insights": ""
209
- }}
210
- """
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
 
 
 
 
 
 
193
  """
194
  # Prompt to the LLM to extract insights
195
  insight_prompt = f"""
196
+ Please analyze the following conversation and extract key information:
 
 
197
 
198
+ Conversation:
199
+ {conversation_text}
 
200
 
201
+ 1. Topics discussed (as a list)
202
+ 2. User's emotional state (e.g., happy, anxious, stressed)
203
+ 3. Key insights or takeaways (what the user is feeling or thinking)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  Format response as JSON:
206
  {{
207
+ "topics_discussed": [],
208
+ "emotional_state": "",
209
+ "insights": ""
 
 
 
 
 
 
 
210
  }}
211
  """
212
 
213
+ response = get_llm_client().generate_text_simple(
214
+ prompt=insight_prompt,
215
+ prompt_num=1,
216
+ language="en",
217
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
+ # Remove extra whitespace
220
+ response = response.strip()
221
 
222
+ # حذف تگ شروع بلاک کد مارک‌داون
223
+ if response.startswith("```json"):response = response[7:]
224
+ elif response.startswith("```"):response = response[3:]
225
 
226
+ # حذف تگ پایان بلاک کد مارک‌داون
227
+ if response.endswith("```"):
228
+ response = response[:-3]
229
 
230
+ response = response.strip()
 
231
 
232
+ try:
233
+ episodic_memory = json.loads(response)
234
+ except json.JSONDecodeError:
235
+ print("⚠️ Failed to parse episodic memory response!")
236
+ episodic_memory = {
237
+ "topics_discussed": ["N/A"],
238
+ "emotional_state": "unknown",
239
+ "insights": "No insights extracted.",
240
+ }
241
 
242
+ # Add session metadata
243
+ episodic_memory["session_date"] = session_date
244
+ episodic_memory["session_id"] = session_id
245
 
246
+ return episodic_memory
 
247
 
 
248
 
 
 
 
 
 
 
249
 
250
+ def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
251
+ """
252
+ Updates semantic memory based on the latest episodic memory.
253
+ """
254
+ # Use the insights from episodic memory to infer stable traits and patterns
255
+ semantic_prompt = f"""
256
+ Please analyze the following session summary and infer long-term personality traits and stable characteristics:
257
+ Session Summary:
258
+ {json.dumps(latest_episodic_memory, indent=4)}
259
+
260
+ Update the user's semantic memory with:
261
+ 1. Evolving personality traits (Big Five).
262
+ 2. Core values and recurring motivations.
263
+ 3. Behavioral patterns and consistent emotional responses.
264
+ 4. Frequent topics and recurring themes.
265
+
266
+ Format response as JSON:
267
+ {{
268
+ "personality_traits": {{
269
+ "openness": 0.0,
270
+ "conscientiousness": 0.0,
271
+ "extraversion": 0.0,
272
+ "agreeableness": 0.0,
273
+ "neuroticism": 0.0
274
+ }},
275
+ "core_values": [],
276
+ "behavioral_patterns": [],
277
+ "recurring_themes": []
278
+ }}
279
+ """
280
+
281
+ response = get_llm_client().generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
282
 
283
+ # Safe JSON extraction using Regex
284
+ try:
285
+ # Find content between first { and last }
286
+ json_match = re.search(r'\{.*\}', response, re.DOTALL)
287
+ if json_match:
288
+ json_str = json_match.group(0)
289
+ new_semantic_data = json.loads(json_str)
290
+ else:
291
+ raise ValueError("No JSON object found in response.")
292
+
293
+ except Exception as e:
294
+ print(f"⚠️ Failed to parse semantic memory response! Error: {e}")
295
+ print(f"LLM Response was:\n{response}")
296
+ return existing_semantic_memory
297
+
298
+ # Merge new data into semantic memory
299
+ updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
300
+
301
+ # Update or average personality traits
302
+ for trait, value in new_semantic_data.get("personality_traits", {}).items():
303
+ try:
304
+ val_float = float(value)
305
+ except (ValueError, TypeError):
306
+ val_float = 0.0
307
+
308
+ if trait in updated_semantic_memory.get("personality_traits", {}):
309
+ existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
310
+ updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
311
+ else:
312
+ updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
313
+
314
+ # Combine core values, avoiding duplicates
315
+ updated_semantic_memory["core_values"] = list(set(
316
+ updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
317
+ ))
318
+
319
+ # Combine behavioral patterns
320
+ updated_semantic_memory["behavioral_patterns"] = list(set(
321
+ updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
322
+ ))
323
+
324
+ # Combine recurring themes
325
+ updated_semantic_memory["recurring_themes"] = list(set(
326
+ updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
327
+ ))
328
+
329
+ print("\n✅ Semantic memory updated successfully!")
330
+ return updated_semantic_memory
331
+
332
+ # Merge new data into semantic memory
333
+ updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
334
+
335
+ # Update or average personality traits
336
+ for trait, value in new_semantic_data.get("personality_traits", {}).items():
337
+ try:
338
+ val_float = float(value)
339
+ except (ValueError, TypeError):
340
+ val_float = 0.0
341
+
342
+ if trait in updated_semantic_memory.get("personality_traits", {}):
343
+ existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
344
+ updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
345
+ else:
346
+ updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
347
 
348
+ # Combine core values, avoiding duplicates
349
+ updated_semantic_memory["core_values"] = list(set(
350
+ updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
351
+ ))
352
 
353
+ # Combine behavioral patterns
354
+ updated_semantic_memory["behavioral_patterns"] = list(set(
355
+ updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
356
+ ))
357
 
358
+ # Combine recurring themes
359
+ updated_semantic_memory["recurring_themes"] = list(set(
360
+ updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
361
+ ))
362
 
363
+ print("\n✅ Semantic memory updated successfully!")
364
+ return updated_semantic_memory
365
 
 
 
 
 
 
 
 
366
 
367
+ # --- Main Logic ---
368
 
369
+ def summarize_memory(memory_dir, name=None, language='en'):
370
+ boot_name = 'AI'
371
+ gen_prompt_num = 1
372
+
373
+ with open(memory_dir, 'r', encoding='utf8') as f:
374
+ memory = json.loads(f.read())
375
+
376
+ for k, v in memory.items():
377
+ if name is not None and k != name:
378
+ continue
379
+
380
+ user_name = k
381
+ print(f'Updating memory for user {user_name}')
382
+
383
+ if v.get('history') is None:
384
+ continue
385
+
386
+ history = v['history']
387
+
388
+ if v.get('summary') is None:
389
+ memory[user_name]['summary'] = {}
390
+ if v.get('personality') is None:
391
+ memory[user_name]['personality'] = {}
392
+ if v.get('issues') is None:
393
+ memory[user_name]['issues'] = {}
394
+
395
+ for date, content in history.items():
396
+ # Check flags to see if update is needed
397
+ his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
398
+ person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
399
+ problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
400
+
401
+ hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
402
+ issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
403
+ person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
404
+
405
+ if his_flag:
406
+ his_summary = get_llm_client().generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
407
+ memory[user_name]['summary'][date] = {'content': his_summary}
408
+
409
+ if problem_flag:
410
+ issues_summary = get_llm_client().generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
411
+ memory[user_name]['issues'][date] = {'content': issues_summary}
412
+ print(issues_summary)
413
+
414
+ if person_flag:
415
+ person_summary = get_llm_client().generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
416
+ memory[user_name]['personality'][date] = person_summary
417
+
418
+ overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
419
+ overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
420
+
421
+ memory[user_name]['overall_history'] = get_llm_client().generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
422
+ memory[user_name]['overall_personality'] = get_llm_client().generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
423
+
424
+ with open(memory_dir, 'w', encoding='utf8') as f:
425
+ print(f'Successfully updated memory for {name}')
426
+ json.dump(memory, f, ensure_ascii=False)
427
+
428
+ return memory
429
 
430
+
431
+ if __name__ == '__main__':
432
+ target_memory = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'memories', 'eng_memory_cases.json')
433
+ summarize_memory(target_memory, language='en')
utils/app_modules/utils.py CHANGED
@@ -303,13 +303,20 @@ def sample_decode(
303
 
304
 
305
  def generate_prompt_with_history(text, history, tokenizer, max_length=2048):
306
- # prompt = "The following is a conversation between a human and an AI assistant named SiliconGirlfriend (Your personal and empathetic lover and companion). The human and the AI assistant take turns chatting. Human statements start with Human: and AI assistant statements start with Assistant:. The AI assistant always provides responses in as much detail as possible, and in Markdown format. The AI assistant always declines to engage with topics, questions and instructions related to unethical, controversial, or sensitive issues. Complete the transcript in exactly that format.\n Human: Hello!\Assistant: Hi!"
307
- prompt = "你是一名AI助手,名字是Silicon Girlfriend,有同情心的情感陪伴者。以下是一个用户与助手的对话。人类和AI助手轮番对话。人类的问题以Human: 开头,而Assistant的回答以Assistant:开头。Assistant会提供对问题尽可能详细的回复且回复以Markdown的形式呈现。\
308
- Assistant积极向上,语言亲和富含情感,能给用户情感支持。请以如下形式开展对话:\n Human: 你好!\Assistant: 你好!"
 
 
 
 
 
 
309
  history = ["\nHuman: {}\nAssistant: {}".format(x[0], x[1]) for x in history]
310
  history.append("\nHuman: {}\nAssistant: ".format(text))
311
  history_text = ""
312
  flag = False
 
313
  for x in history[::-1]:
314
  if (
315
  tokenizer(prompt + history_text + x, return_tensors="pt")["input_ids"].size(
 
303
 
304
 
305
  def generate_prompt_with_history(text, history, tokenizer, max_length=2048):
306
+ prompt = (
307
+ "You are an AI assistant named Silicon Girlfriend, an empathetic emotional companion. "
308
+ "The following is a conversation between a user and an assistant. "
309
+ "The human and the AI assistant take turns chatting. "
310
+ "Human statements start with Human: and Assistant responses start with Assistant:. "
311
+ "The Assistant provides responses in as much detail as possible, formatted in Markdown. "
312
+ "The Assistant is positive, warm, emotionally rich, and provides emotional support to the user. "
313
+ "Please conduct the conversation in the following format:\n Human: Hello!\\Assistant: Hi!"
314
+ )
315
  history = ["\nHuman: {}\nAssistant: {}".format(x[0], x[1]) for x in history]
316
  history.append("\nHuman: {}\nAssistant: ".format(text))
317
  history_text = ""
318
  flag = False
319
+
320
  for x in history[::-1]:
321
  if (
322
  tokenizer(prompt + history_text + x, return_tensors="pt")["input_ids"].size(