EMMA commited on
Commit
367e76b
·
0 Parent(s):

Initial lightweight commit

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +9 -0
  2. .env +1 -0
  3. .gitattributes +5 -0
  4. .github/workflows/docker-publish.yml +27 -0
  5. .gitignore +6 -0
  6. Backup code/app_V1.py +727 -0
  7. Backup code/app_V11.py +944 -0
  8. Backup code/app_V12.py +964 -0
  9. Backup code/app_V13.py +973 -0
  10. Backup code/app_V14.py +1032 -0
  11. Backup code/app_V15.py +1031 -0
  12. Backup code/app_V2.py +751 -0
  13. Backup code/app_V3.py +751 -0
  14. Backup code/app_V4.py +855 -0
  15. Backup code/app_V5.py +881 -0
  16. Backup code/app_V6.py +854 -0
  17. Backup code/app_V7.py +901 -0
  18. Backup code/app_V8.py +907 -0
  19. Backup code/app_V9.py +934 -0
  20. Backup code/app_v10.py +848 -0
  21. Backup code/app_v17.py +1031 -0
  22. Backup code/memory_utils copy 2.py +276 -0
  23. Backup code/memory_utils copy.py +276 -0
  24. Backup code/memory_utils.py +246 -0
  25. Backup code/prompt_utils.py +215 -0
  26. Backup code/summarize_memory_v4.py +373 -0
  27. Backup code/summarize_memory_v5.py +381 -0
  28. Dockerfile +18 -0
  29. Emma/.gradio/certificate.pem +31 -0
  30. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/default__vector_store.json +1 -0
  31. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/docstore.json +1 -0
  32. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/graph_store.json +1 -0
  33. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/image__vector_store.json +1 -0
  34. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/index_store.json +1 -0
  35. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/default__vector_store.json +1 -0
  36. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/docstore.json +1 -0
  37. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/graph_store.json +1 -0
  38. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/image__vector_store.json +1 -0
  39. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/index_store.json +1 -0
  40. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/default__vector_store.json +0 -0
  41. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/docstore.json +1 -0
  42. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/graph_store.json +1 -0
  43. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/image__vector_store.json +1 -0
  44. Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/index_store.json +1 -0
  45. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/default__vector_store.json +1 -0
  46. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/docstore.json +1 -0
  47. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/graph_store.json +1 -0
  48. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/image__vector_store.json +1 -0
  49. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/index_store.json +1 -0
  50. Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/semantic_memory/default__vector_store.json +1 -0
.dockerignore ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # .dockerignore
2
+ Classification_Model/xlm_r_router_results/
3
+ **/xlm_r_router_results
4
+ Classification_Model/final_xlm_r_model_router/
5
+ **/final_xlm_r_model_router
6
+
7
+ .git/
8
+ __pycache__/
9
+
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ GAPGPT_API_KEY="sk-7kRI3ooFa8cd3Lwn7oQBjU1l7DgCp7UmlchaEWNt6d6utDKt"
.gitattributes ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ *.bin filter=lfs diff=lfs merge=lfs -text
2
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
3
+ *.pt filter=lfs diff=lfs merge=lfs -text
4
+ *.jpg filter=lfs diff=lfs merge=lfs -text
5
+ *.png filter=lfs diff=lfs merge=lfs -text
.github/workflows/docker-publish.yml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Build and Push Docker Image
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main # اگر نام برنچ اصلی شما چیز دیگری مثل master است، آن را تغییر دهید
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Check out the repo
14
+ uses: actions/checkout@v3
15
+
16
+ - name: Log in to Docker Hub
17
+ uses: docker/login-action@v2
18
+ with:
19
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
20
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
21
+
22
+ - name: Build and push Docker image
23
+ uses: docker/build-push-action@v4
24
+ with:
25
+ context: .
26
+ push: true
27
+ tags: ${{ secrets.DOCKERHUB_USERNAME }}/emma-assistant:latest
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .vscode/
4
+ .ipynb_checkpoints
5
+ Classification_Model/
6
+ wheels/
Backup code/app_V1.py ADDED
@@ -0,0 +1,727 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+
13
+ import gradio as gr
14
+ import nltk
15
+ import torch
16
+ import tiktoken
17
+
18
+ from openai import OpenAI as OpenAIClient
19
+ from llama_index.embeddings.openai import OpenAIEmbedding
20
+
21
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
22
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
23
+ from llama_index.core import Settings
24
+ from llama_index.core.indices.prompt_helper import PromptHelper
25
+
26
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
27
+ sys.path.append(prompt_path)
28
+
29
+ # Assuming these imports exist in your local environment
30
+ from utils.sys_args import data_args, model_args
31
+ from utils.app_modules.utils import *
32
+ from utils.app_modules.presets import *
33
+ from utils.app_modules.overwrites import *
34
+ from utils.prompt_utils import *
35
+ from utils.memory_utils import (
36
+ enter_name_llamaindex,
37
+ summarize_memory_event_personality,
38
+ save_local_memory,
39
+ extract_session_summary,
40
+ extract_semantic_memory,
41
+ )
42
+
43
+ # Ensure NLTK data path
44
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
45
+
46
+ tokenizer = tiktoken.get_encoding("cl100k_base")
47
+
48
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
49
+ openai_client_cache = {}
50
+
51
+ import torch
52
+ import torch.nn.functional as F
53
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
54
+
55
+
56
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
57
+
58
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
59
+
60
+ try:
61
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
62
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model.eval()
64
+ print("Local classifier loaded successfully.")
65
+ except Exception as e:
66
+ print(f"Error loading local classifier: {e}")
67
+
68
+
69
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
70
+ if not api_key:
71
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
72
+ if api_key not in openai_client_cache:
73
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
74
+ return openai_client_cache[api_key]
75
+
76
+
77
+ os_name = platform.system()
78
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
79
+ stop_stream = False
80
+
81
+
82
+ def signal_handler(signal_number, frame):
83
+ global stop_stream
84
+ stop_stream = True
85
+
86
+
87
+ VECTOR_SEARCH_TOP_K = 2
88
+
89
+ # Update this path to your actual file location
90
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
91
+
92
+
93
+ def read_apis(path):
94
+ api_keys_local = []
95
+ if os.path.exists(path):
96
+ with open(path, 'r', encoding='utf8') as f:
97
+ for line in f:
98
+ line = line.strip()
99
+ if line:
100
+ api_keys_local.append(line)
101
+ return api_keys_local
102
+
103
+
104
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
105
+
106
+ # Ensure directory exists
107
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
108
+
109
+ if not os.path.exists(memory_dir):
110
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
111
+
112
+ global memory
113
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
114
+ language = 'en'
115
+ user_keyword = generate_user_keyword()[language]
116
+ ai_keyword = generate_ai_keyword()[language]
117
+ boot_name = boot_name_dict[language]
118
+ boot_actual_name = boot_actual_name_dict[language]
119
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
120
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
121
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
122
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
123
+
124
+ api_keys = read_apis(api_path)
125
+ # Fallback if file is empty or missing for testing purposes
126
+ if not api_keys:
127
+ print(f"Warning: No API keys found in {api_path}.")
128
+
129
+ new_conversation = False
130
+ chatgpt_config = {
131
+ "model": "gpt-4o",
132
+ "temperature": 1,
133
+ "max_tokens": 1024,
134
+ "top_p": 0.95,
135
+ "frequency_penalty": 0.4,
136
+ "presence_penalty": 0.2,
137
+ "n": 1,
138
+ }
139
+
140
+ deactivated_keys = []
141
+ logging.basicConfig(
142
+ level=logging.DEBUG,
143
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
144
+ )
145
+
146
+
147
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
148
+ """
149
+ Handles the chat request to OpenAI.
150
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
151
+ """
152
+ retry_times, count = 5, 0
153
+ response = None
154
+
155
+ while response is None and count < retry_times:
156
+ try:
157
+ request = copy.deepcopy(gpt_config)
158
+
159
+ # Initial system and greeting messages
160
+ if data_args.language == 'en':
161
+ message = [
162
+ {"role": "system", "content": system.strip()},
163
+ {"role": "user", "content": "Hi!"},
164
+ {"role": "assistant",
165
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
166
+ ]
167
+ else:
168
+ message = [
169
+ {"role": "system", "content": system.strip()},
170
+ {"role": "user", "content": "Hi"},
171
+ {"role": "assistant",
172
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
173
+ ]
174
+
175
+ # --- FIX: Handle History as List of Dicts ---
176
+ if history:
177
+ # Verify if history is old format (list of lists) or new (list of dicts)
178
+ if isinstance(history[0], list):
179
+ # Convert old format temporarily if encountered
180
+ for q, a in history:
181
+ message.append({"role": "user", "content": str(q)})
182
+ message.append({"role": "assistant", "content": str(a)})
183
+ elif isinstance(history[0], dict):
184
+ # New format
185
+ for msg in history:
186
+ if msg.get('role') in ['user', 'assistant']:
187
+ message.append(msg)
188
+
189
+ # Add the current prompt
190
+ message.append({"role": "user", "content": f"{prompt}"})
191
+
192
+ if not api_keys:
193
+ return "Error: No API Keys available."
194
+
195
+ client = get_gapgpt_client(api_keys[api_index])
196
+
197
+ # New OpenAI 1.x Syntax
198
+ response = client.chat.completions.create(messages=message, **request)
199
+
200
+ except Exception as e:
201
+ print(f"Chat Error: {e}")
202
+ if 'This key is associated with a deactivated account' in str(e):
203
+ deactivated_keys.append(api_keys[api_index])
204
+
205
+ if api_keys:
206
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
207
+ loop_check = 0
208
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
209
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
210
+ loop_check += 1
211
+ count += 1
212
+
213
+ if response:
214
+ response = response.choices[0].message.content
215
+ else:
216
+ response = ''
217
+ return response
218
+
219
+
220
+ def classify_query_local(text):
221
+
222
+
223
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
224
+ id2label_map = {
225
+ 0: "episodic_memory",
226
+ 1: "semantic_memory",
227
+ 2: "semantic-episodic",
228
+ 3: "unknown"
229
+ }
230
+
231
+ try:
232
+
233
+ inputs = _tokenizer(
234
+ text,
235
+ return_tensors="pt",
236
+ truncation=True,
237
+ padding=True,
238
+ max_length=512
239
+ )
240
+
241
+
242
+
243
+ with torch.no_grad():
244
+ outputs = _classifier_model(**inputs)
245
+
246
+
247
+ logits = outputs.logits
248
+ probabilities = F.softmax(logits, dim=-1)
249
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
250
+
251
+
252
+ category = id2label_map.get(predicted_class_id, "unknown")
253
+
254
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
255
+ return category
256
+
257
+ except Exception as e:
258
+ print(f"Error in local classification: {e}")
259
+ return "unknown"
260
+
261
+
262
+
263
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
264
+ response = None
265
+ count = 0
266
+ local_deactivated = []
267
+ print("text********:", text)
268
+
269
+ system_prompt = """
270
+ You are an AI that classifies user queries into one of the following memory types:
271
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
272
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
273
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
274
+
275
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
276
+ """.strip()
277
+
278
+ if not api_keys:
279
+ return "unknown"
280
+
281
+ while response is None and count < retry_times:
282
+ try:
283
+ client = get_gapgpt_client(api_keys[api_index])
284
+
285
+ # New OpenAI 1.x Syntax
286
+ response = client.chat.completions.create(
287
+ messages=[
288
+ {"role": "system", "content": system_prompt},
289
+ {"role": "user", "content": text.strip()},
290
+ ],
291
+ **copy.deepcopy(gpt_config),
292
+ )
293
+ except Exception as e:
294
+ print(f"Classify Error: {e}")
295
+ if "This key is associated with a deactivated account" in str(e):
296
+ local_deactivated.append(api_keys[api_index])
297
+
298
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
299
+ while api_keys[api_index] in local_deactivated:
300
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
301
+ count += 1
302
+
303
+ if response:
304
+ category = response.choices[0].message.content.strip().lower()
305
+ # Basic cleanup
306
+ if "semantic_memory" in category: category = "semantic_memory"
307
+ elif "semantic-episodic" in category: category = "semantic-episodic"
308
+ elif "episodic_memory" in category: category = "episodic_memory"
309
+ else: category = "unknown"
310
+ else:
311
+ category = "unknown"
312
+
313
+ return category
314
+
315
+
316
+ def predict_new(
317
+ text,
318
+ history,
319
+ top_p,
320
+ temperature,
321
+ max_length_tokens,
322
+ max_context_length_tokens,
323
+ user_name,
324
+ user_memory,
325
+ user_memory_index,
326
+ service_context,
327
+ api_index,
328
+ semantic_memory_text,
329
+ query_category,
330
+ ):
331
+ chatgpt_cfg = {
332
+ "model": "gpt-4o",
333
+ "temperature": temperature,
334
+ "max_tokens": max_length_tokens,
335
+ "top_p": top_p,
336
+ "frequency_penalty": 0.4,
337
+ "presence_penalty": 0.2,
338
+ "n": 1,
339
+ }
340
+
341
+ if text == "":
342
+ # Return same history if empty input
343
+ return history, history, "Empty context."
344
+
345
+ # Ensure history is initialized
346
+ if history is None:
347
+ history = []
348
+
349
+ system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
350
+ history=history,
351
+ query=text, # Changed name to match prompt_utils
352
+ user_memory=user_memory,
353
+ user_name=user_name,
354
+ user_memory_index=user_memory_index,
355
+ service_context=service_context,
356
+ api_keys=api_keys,
357
+ api_index=api_index,
358
+ meta_prompt=meta_prompt,
359
+ new_user_meta_prompt=new_user_meta_prompt,
360
+ data_args=data_args,
361
+ boot_actual_name=boot_actual_name,
362
+ semantic_memory_text=semantic_memory_text,
363
+ query_category=query_category,
364
+ meta_prompt_semantic=meta_prompt_semantic,
365
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
366
+ )
367
+
368
+ # Handle context window slicing manually if needed,
369
+ # though usually OpenAI manages this, or we slice the list of dicts.
370
+ current_history_for_llm = history
371
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
372
+ current_history_for_llm = history[-(data_args.max_history * 2):]
373
+
374
+ response = chatgpt_chat(
375
+ prompt=text,
376
+ system=system_prompt,
377
+ history=current_history_for_llm,
378
+ gpt_config=chatgpt_cfg,
379
+ api_index=api_index,
380
+ )
381
+
382
+ torch.cuda.empty_cache()
383
+
384
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
385
+ new_history = history + [
386
+ {"role": "user", "content": text},
387
+ {"role": "assistant", "content": response}
388
+ ]
389
+
390
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
391
+ # OR we convert strictly for saving if your legacy code needs it.
392
+ # For now, assuming we pass the object as is or convert for save)
393
+ if user_name:
394
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
395
+ # or pass a converted version. Let's try passing the new format.
396
+ save_local_memory(memory, new_history, user_name, data_args)
397
+
398
+ # Return: (Chatbot View, State History, Textbox Reset)
399
+ return new_history, new_history, "Generating..."
400
+
401
+
402
+ import gradio as gr
403
+ import time
404
+
405
+ def create_gradio_interface(service_context, api_keys):
406
+ with gr.Blocks(title="EMMA") as demo:
407
+
408
+ gr.HTML("""
409
+ <style>
410
+ .center-content {
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+ /* -- استایل‌های فرم ورود -- */
417
+ .login-box {
418
+ max-width: 400px !important;
419
+ margin: 0 auto !important;
420
+ width: 100% !important;
421
+ }
422
+ .login-btn, .login-btn:hover {
423
+ background-color: #3498db !important;
424
+ background-image: none !important;
425
+ color: white !important;
426
+ border: none !important;
427
+ }
428
+ /* -- استایل‌های محیط چت -- */
429
+ .chat-box {
430
+ max-width: 800px !important;
431
+ margin: 0 auto !important;
432
+ width: 100% !important;
433
+ }
434
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
435
+ .mobile-button, .mobile-button:hover {
436
+ background-color: #3498db !important;
437
+ background-image: none !important;
438
+ color: white !important;
439
+ border: none !important;
440
+ }
441
+ .gr-textbox textarea {
442
+ font-size: 16px;
443
+ }
444
+ .gr-chatbot {
445
+ font-size: 15px;
446
+ }
447
+ </style>
448
+ """)
449
+
450
+ state = gr.State({
451
+ "history": [],
452
+ "user_name": None,
453
+ "memory": memory,
454
+ "data_args": data_args,
455
+ "service_context": service_context,
456
+ "api_keys": api_keys,
457
+ "api_index": 0,
458
+ "semantic_memory_text": "",
459
+ "new_conversation": True,
460
+ "initialized": False
461
+ })
462
+
463
+ # ==========================================
464
+ # 1. LOGIN PAGE
465
+ # ==========================================
466
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
467
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
468
+
469
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
470
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
471
+ login_status = gr.Textbox(visible=False, label="Status")
472
+
473
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
474
+
475
+ with gr.Column(visible=False) as registration_fields:
476
+ gr.Markdown("### ✨ New User Registration")
477
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
478
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
479
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
480
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
481
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
482
+
483
+ # ==========================================
484
+ # 2. CHAT PAGE
485
+ # ==========================================
486
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
487
+ with gr.Column(elem_classes=["chat-box"]):
488
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
489
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
490
+
491
+ with gr.Group():
492
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
493
+
494
+ with gr.Row():
495
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
496
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
497
+
498
+ with gr.Row(equal_height=True):
499
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
500
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
501
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
502
+
503
+ # -------------------------------------------------------
504
+ # Internal Functions (کامل شده)
505
+ # -------------------------------------------------------
506
+ def handle_login_check(name, state):
507
+ if not name.strip():
508
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
509
+
510
+ if name in memory:
511
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
512
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
513
+
514
+ new_state = state.copy()
515
+ new_state["user_name"] = name
516
+ new_state["memory"] = memory
517
+ new_state["initialized"] = True
518
+ new_state["semantic_memory_text"] = semantic_memory
519
+ new_state["history"] = []
520
+
521
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
522
+
523
+ return (
524
+ gr.update(visible=False),
525
+ gr.update(visible=False),
526
+ gr.update(visible=True),
527
+ gr.update(visible=False, value=""),
528
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
529
+ gr.update(value=welcome_msg),
530
+ new_state
531
+ )
532
+ else:
533
+ return (
534
+ gr.update(visible=True),
535
+ gr.update(visible=True),
536
+ gr.update(visible=False),
537
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
538
+ gr.update(),
539
+ gr.update(),
540
+ state
541
+ )
542
+
543
+ def handle_register(name, age, gender, occupation, residence, state):
544
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
545
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
546
+
547
+ new_state = state.copy()
548
+ new_state["user_name"] = name
549
+ new_state["memory"] = memory
550
+ new_state["initialized"] = True
551
+ new_state["semantic_memory_text"] = semantic_memory
552
+ new_state["history"] = []
553
+
554
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
555
+
556
+ return (
557
+ gr.update(visible=False),
558
+ gr.update(visible=False),
559
+ gr.update(visible=True),
560
+ gr.update(visible=False, value=""),
561
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
562
+ gr.update(value=welcome_msg),
563
+ new_state
564
+ )
565
+
566
+ def switch_user(state):
567
+ if state["initialized"] and state["user_name"] in state["memory"]:
568
+ if state["memory"][state["user_name"]]["sessions"]:
569
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
570
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
571
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
572
+
573
+ new_state = state.copy()
574
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
575
+
576
+ return (
577
+ gr.update(visible=True),
578
+ gr.update(visible=False),
579
+ gr.update(visible=False),
580
+ gr.update(value="Logged out successfully.", visible=True),
581
+ gr.update(value=""),
582
+ new_state,
583
+ gr.update(value=[])
584
+ )
585
+
586
+ def handle_chat(user_message, state):
587
+ if not user_message.strip():
588
+ return gr.update(), state.get("history", []), state
589
+
590
+ user_name = state.get("user_name")
591
+ user_memory = state.get("memory")
592
+ service_context = state.get("service_context")
593
+ api_index = state.get("api_index", 0)
594
+ semantic_memory_text = state.get("semantic_memory_text", "")
595
+
596
+ # دسته‌بندی پرامپت با تابعی که در کدهای شما وجود دارد
597
+ query_category = classify_query_local(user_message)
598
+
599
+ # ارسال به تابع predict_new شما
600
+ new_history, _, status_msg = predict_new(
601
+ text=user_message,
602
+ history=state.get("history", []),
603
+ top_p=0.95,
604
+ temperature=1.0,
605
+ max_length_tokens=1024,
606
+ max_context_length_tokens=4096,
607
+ user_name=user_name,
608
+ user_memory=user_memory,
609
+ user_memory_index=None,
610
+ service_context=service_context,
611
+ api_index=api_index,
612
+ semantic_memory_text=semantic_memory_text,
613
+ query_category=query_category
614
+ )
615
+
616
+ state["history"] = new_history
617
+ return "", new_history, state
618
+
619
+ def clear_history(state):
620
+ state["history"] = []
621
+ return [], state
622
+
623
+ # -------------------------------------------------------
624
+ # Event Bindings (اتصال دکمه‌ها به توابع)
625
+ # -------------------------------------------------------
626
+ check_user_btn.click(
627
+ handle_login_check,
628
+ inputs=[username_input, state],
629
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
630
+ )
631
+
632
+ register_btn.click(
633
+ handle_register,
634
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
635
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
636
+ )
637
+
638
+ switch_user_btn.click(
639
+ switch_user,
640
+ inputs=[state],
641
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
642
+ )
643
+
644
+ submit_btn.click(
645
+ handle_chat,
646
+ inputs=[user_input, state],
647
+ outputs=[user_input, chatbot, state]
648
+ )
649
+
650
+ user_input.submit(
651
+ handle_chat,
652
+ inputs=[user_input, state],
653
+ outputs=[user_input, chatbot, state]
654
+ )
655
+
656
+ clear_btn.click(
657
+ clear_history,
658
+ inputs=[state],
659
+ outputs=[chatbot, state]
660
+ )
661
+
662
+ new_session_btn.click(
663
+ clear_history,
664
+ inputs=[state],
665
+ outputs=[chatbot, state]
666
+ )
667
+
668
+ return demo
669
+
670
+ def main():
671
+ """Main function to initialize and launch the interface."""
672
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
673
+
674
+ if not gapgpt_api_key:
675
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
676
+ else:
677
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
678
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
679
+
680
+ # تنظیم LLM (مدل زبانی)
681
+ llm = LlamaIndexOpenAI(
682
+ model="gpt-4o",
683
+ temperature=1,
684
+ max_tokens=1024,
685
+ top_p=0.95,
686
+ frequency_penalty=0.4,
687
+ presence_penalty=0.2,
688
+ api_key=gapgpt_api_key,
689
+ api_base=GAPGPT_BASE_URL,
690
+ )
691
+
692
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
693
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
694
+ embed_model = OpenAIEmbedding(
695
+ api_key=gapgpt_api_key,
696
+ api_base=GAPGPT_BASE_URL,
697
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
698
+ )
699
+
700
+ # اعمال تنظیمات سراسری
701
+ Settings.llm = llm
702
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
703
+
704
+ Settings.prompt_helper = PromptHelper(
705
+ context_window=4096,
706
+ num_output=256,
707
+ chunk_overlap_ratio=20 / 4096,
708
+ tokenizer=tokenizer,
709
+ )
710
+
711
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
712
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
713
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
714
+ if 'api_keys' not in locals():
715
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
716
+
717
+ demo = create_gradio_interface(Settings, api_keys)
718
+ demo.launch(
719
+ server_name="127.0.0.1",
720
+ server_port=7860,
721
+ share=True
722
+ )
723
+
724
+
725
+ if __name__ == "__main__":
726
+ signal.signal(signal.SIGINT, signal_handler)
727
+ main()
Backup code/app_V11.py ADDED
@@ -0,0 +1,944 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+
332
+
333
+ ):
334
+ chatgpt_cfg = {
335
+ "model": "gpt-4o",
336
+ "temperature": temperature,
337
+ "max_tokens": max_length_tokens,
338
+ "top_p": top_p,
339
+ "frequency_penalty": 0.4,
340
+ "presence_penalty": 0.2,
341
+ "n": 1,
342
+ }
343
+
344
+ if text == "":
345
+ # Return same history if empty input
346
+ return history, history, "Empty context."
347
+
348
+ # Ensure history is initialized
349
+ if history is None:
350
+ history = []
351
+
352
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
353
+ history=history,
354
+ query=text, # Changed name to match prompt_utils
355
+ user_memory=user_memory,
356
+ user_name=user_name,
357
+ user_memory_index=user_memory_index,
358
+ service_context=service_context,
359
+ api_keys=api_keys,
360
+ api_index=api_index,
361
+ meta_prompt=meta_prompt,
362
+ new_user_meta_prompt=new_user_meta_prompt,
363
+ data_args=data_args,
364
+ boot_actual_name=boot_actual_name,
365
+ semantic_memory_text=semantic_memory_text,
366
+ query_category=query_category,
367
+ meta_prompt_semantic=meta_prompt_semantic,
368
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
369
+ )
370
+
371
+ # Handle context window slicing manually if needed,
372
+ # though usually OpenAI manages this, or we slice the list of dicts.
373
+ current_history_for_llm = history
374
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
375
+ current_history_for_llm = history[-(data_args.max_history * 2):]
376
+
377
+ response = chatgpt_chat(
378
+ prompt=text,
379
+ system=system_prompt,
380
+ history=current_history_for_llm,
381
+ gpt_config=chatgpt_cfg,
382
+ api_index=api_index,
383
+ )
384
+
385
+ torch.cuda.empty_cache()
386
+
387
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
388
+ new_history = history + [
389
+ {"role": "user", "content": text},
390
+ {"role": "assistant", "content": response}
391
+ ]
392
+
393
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
394
+ # OR we convert strictly for saving if your legacy code needs it.
395
+ # For now, assuming we pass the object as is or convert for save)
396
+ if user_name:
397
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
398
+ # or pass a converted version. Let's try passing the new format.
399
+ save_local_memory(memory, new_history, user_name, data_args)
400
+
401
+ # Return: (Chatbot View, State History, Textbox Reset)
402
+ return new_history, new_history, "Generating..."
403
+
404
+
405
+
406
+ def create_gradio_interface(service_context, api_keys):
407
+
408
+
409
+ # ابتدا متغیر CSS را تعریف کنید
410
+ custom_css = """
411
+ /* استایل دکمه ارسال (Send) */
412
+ .send-btn {
413
+ border: 3px solid #0066cc !important;
414
+ border-radius: 12px !important;
415
+ background-color: white !important;
416
+ color: black !important;
417
+ font-weight: bold !important;
418
+ font-size: 16px !important;
419
+ transition: all 0.3s ease !important;
420
+ }
421
+ .send-btn:hover {
422
+ background-color: #0066cc !important;
423
+ color: white !important;
424
+ }
425
+
426
+ /* استایل نوار پایین و دکمه‌های آن */
427
+ .bottom-actions-row {
428
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
429
+ border-radius: 8px !important;
430
+ padding: 5px !important;
431
+ margin-top: 10px !important;
432
+ }
433
+
434
+ .action-btn {
435
+ border: none !important;
436
+ background: transparent !important;
437
+ color: black !important;
438
+ font-weight: bold !important;
439
+ box-shadow: none !important;
440
+ transition: all 0.3s ease !important;
441
+ }
442
+
443
+ .action-btn:hover {
444
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
445
+ border-radius: 8px !important;
446
+ }
447
+ /* مخفی کردن آیکون/مربع نارنجی پیش‌فرض Gradio */
448
+ .progress-level svg, .progress-level img {
449
+ display: none !important;
450
+ }
451
+
452
+ /* ایجاد یک دایره چرخان (Spinner) استاندارد */
453
+ .progress-level::before {
454
+ content: "";
455
+ display: inline-block;
456
+ width: 20px;
457
+ height: 20px;
458
+ border: 3px solid #e5e7eb; /* رنگ پس‌زمینه دایره */
459
+ border-radius: 50%;
460
+ border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
461
+ animation: spin 1s linear infinite;
462
+ margin-right: 8px;
463
+ vertical-align: middle;
464
+ }
465
+
466
+ /* انیمیشن چرخش */
467
+ @keyframes spin {
468
+ 0% { transform: rotate(0deg); }
469
+ 100% { transform: rotate(360deg); }
470
+ }
471
+
472
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
473
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
474
+ /*
475
+ .progress-text {
476
+ display: none !important;
477
+ }
478
+ */
479
+
480
+ """
481
+
482
+ with gr.Blocks(title="EMMA") as demo:
483
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
484
+ gr.HTML(f"<style>{custom_css}</style>")
485
+
486
+ # بقیه کدهای شما...
487
+
488
+
489
+ state = gr.State({
490
+ "history": [],
491
+ "user_name": None,
492
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
493
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
494
+ "service_context": service_context,
495
+ "api_keys": api_keys,
496
+ "api_index": 0,
497
+ "semantic_memory_text": "",
498
+ "new_conversation": True,
499
+ "initialized": False
500
+ })
501
+
502
+
503
+
504
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
505
+ with gr.Row():
506
+
507
+ # ==========================================
508
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
509
+ # ==========================================
510
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
511
+ with gr.Sidebar(open=True) as login_page:
512
+
513
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
514
+
515
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
516
+ login_status = gr.Textbox(visible=False, label="Status")
517
+
518
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
519
+
520
+ with gr.Column(visible=False) as registration_fields:
521
+ gr.Markdown("### ✨ New User Registration")
522
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
523
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
524
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
525
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
526
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
527
+
528
+
529
+ # ==========================================
530
+ # 2. CHAT PAGE (ستون سمت راست)
531
+ # ==========================================
532
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
533
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
534
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
535
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
536
+
537
+ with gr.Group():
538
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
539
+
540
+ with gr.Row():
541
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
542
+ # اختصاص کلاس send-btn به دکمه Send
543
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
544
+
545
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
546
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
547
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
548
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
549
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
550
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
551
+
552
+ # -------------------------------------------------------
553
+ # Internal Functions
554
+ # -------------------------------------------------------
555
+ def handle_login_check(name, state):
556
+ if not name.strip():
557
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
558
+
559
+ if name in memory:
560
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
561
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
562
+
563
+ new_state = state.copy()
564
+ new_state["user_name"] = name
565
+ new_state["memory"] = memory
566
+ new_state["initialized"] = True
567
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
568
+ new_state["semantic_memory_index"] = semantic_memory
569
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
570
+ new_state["episodic_memory_index"] = episodic_memory
571
+ new_state["history"] = []
572
+
573
+
574
+
575
+
576
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
577
+
578
+ return (
579
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
580
+ gr.update(visible=False),
581
+ gr.update(visible=True),
582
+ gr.update(visible=False, value=""),
583
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
584
+ gr.update(value=welcome_msg),
585
+ new_state
586
+ )
587
+ else:
588
+ return (
589
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
590
+ gr.update(visible=True),
591
+ gr.update(visible=False),
592
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
593
+ gr.update(),
594
+ gr.update(),
595
+ state
596
+ )
597
+
598
+ def handle_register(name, age, gender, occupation, residence, state):
599
+ name = str(name).strip()
600
+
601
+ if not name:
602
+ raise gr.Error("Please enter a valid user name.")
603
+
604
+ # Registration is only for new users.
605
+ if name in memory:
606
+ raise gr.Error(
607
+ f"User '{name}' already exists. Please use the login form."
608
+ )
609
+
610
+ # Create the user before trying to build or load their indices.
611
+ memory[name] = {
612
+ "profile": {
613
+ "age": age,
614
+ "gender": gender,
615
+ "occupation": occupation,
616
+ "residence": residence,
617
+ },
618
+ "sessions": [],
619
+ "episodic_memory": [],
620
+ "semantic_memory": {},
621
+ }
622
+
623
+ try:
624
+ (
625
+ _,
626
+ user_memory,
627
+ sessions_memory,
628
+ episodic_memory,
629
+ semantic_memory,
630
+ ) = enter_name_llamaindex(
631
+ name=name,
632
+ memory=memory,
633
+ data_args=data_args,
634
+ update_memory_index=True,
635
+ )
636
+ except Exception:
637
+ # Avoid leaving a partially registered user in memory.
638
+ memory.pop(name, None)
639
+ raise
640
+
641
+ new_state = dict(state or {})
642
+ new_state.update(
643
+ {
644
+ "user_name": name,
645
+ "memory": memory,
646
+ "initialized": True,
647
+ "history": [],
648
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
649
+ "user_memory_index": sessions_memory,
650
+ "episodic_memory_index": episodic_memory,
651
+ "semantic_memory_index": semantic_memory,
652
+ }
653
+ )
654
+
655
+ welcome_msg = f"Welcome {name}! Registration complete."
656
+
657
+ return (
658
+ gr.update(open=False),
659
+ gr.update(visible=False),
660
+ gr.update(visible=True),
661
+ gr.update(visible=False, value=""),
662
+ gr.update(
663
+ value=(
664
+ "<h2 style='text-align: center; color: #333;'>"
665
+ f"🧠 EMMA: Session for {name}</h2>"
666
+ )
667
+ ),
668
+ gr.update(value=welcome_msg),
669
+ new_state,
670
+ )
671
+
672
+ def switch_user(state):
673
+ if state["initialized"] and state["user_name"] in state["memory"]:
674
+ if state["memory"][state["user_name"]]["sessions"]:
675
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
676
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
677
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
678
+ # ==========================================
679
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
680
+ # ==========================================
681
+ try:
682
+ user_mem = state["memory"][state["user_name"]]
683
+ existing_semantic = user_mem.get("semantic_memory", {})
684
+
685
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
686
+
687
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
688
+ except Exception as e:
689
+ print(f"Error updating semantic memory on logout: {e}")
690
+ # ==========================================
691
+
692
+ new_state = state.copy()
693
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
694
+
695
+
696
+ return (
697
+ gr.update(open=True), # 1. باز شدن سایدبار (login_page)
698
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام (registration_fields)
699
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
700
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
701
+ gr.update(value=""), # 5. پاک کردن نام کاربری
702
+ new_state, # 6. استیت جدید
703
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
704
+ gr.update(value=""), # 8. پاک کردن age_input
705
+ gr.update(value=""), # 9. پاک کردن gender_input
706
+ gr.update(value=""), # 10. پاک کردن occupation_input
707
+ gr.update(value="") # 11. پاک کردن residence_input
708
+ )
709
+
710
+ def handle_chat(user_message, state):
711
+ if not user_message.strip():
712
+ print("[handle_chat] empty message")
713
+ print("[handle_chat] state =", state)
714
+ return gr.update(), state.get("history", []), state
715
+
716
+ print("[handle_chat] user_message =", repr(user_message))
717
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
718
+ print("[handle_chat] user_name =", state.get("user_name"))
719
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
720
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
721
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
722
+ print("[handle_chat] api_index =", state.get("api_index", 0))
723
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
724
+ print("[handle_chat] history len =", len(state.get("history", [])))
725
+
726
+ user_name = state.get("user_name")
727
+ user_memory_index = state.get("user_memory_index")
728
+ user_memory = state.get("user_memory", {})
729
+ user_memory_index = state.get("user_memory_index")
730
+ semantic_memory_text = state.get("semantic_memory_text", {})
731
+ service_context = state.get("service_context")
732
+ api_index = state.get("api_index", 0)
733
+ semantic_memory_text = state.get("semantic_memory_text", "")
734
+
735
+ query_category = classify_query_local(user_message)
736
+ print("[handle_chat] query_category =", query_category)
737
+
738
+ new_history, _, status_msg = predict_new(
739
+ text=user_message,
740
+ history=state.get("history", []),
741
+ top_p=0.95,
742
+ temperature=1.0,
743
+ max_length_tokens=1024,
744
+ max_context_length_tokens=4096,
745
+ user_name=user_name,
746
+ user_memory=user_memory,
747
+ user_memory_index=user_memory_index,
748
+ service_context=service_context,
749
+ api_index=api_index,
750
+ semantic_memory_text=semantic_memory_text,
751
+ query_category=query_category,
752
+
753
+ )
754
+
755
+ print("[handle_chat] status_msg =", status_msg)
756
+ print("[handle_chat] new_history len =", len(new_history))
757
+
758
+ state["history"] = new_history
759
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
760
+
761
+ return "", new_history, state
762
+
763
+ def clear_history(state):
764
+ state["history"] = []
765
+ return [], state
766
+
767
+ def handle_new_session(state):
768
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
769
+ user_name = state.get("user_name")
770
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
771
+ print("Error: User not logged in or memory missing.")
772
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
773
+ return [], state
774
+
775
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
776
+ user_data = state["memory"][user_name]
777
+
778
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
779
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
780
+ last_session = user_data["sessions"][-1]
781
+
782
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
783
+ if len(last_session.get("conversation", [])) > 0:
784
+ session_date = last_session.get("date", "")
785
+ session_id = last_session.get("session_id", 0)
786
+
787
+ # پاس دادن هر ۳ آرگومان به تابع
788
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
789
+
790
+ if "episodic_memory" not in user_data:
791
+ user_data["episodic_memory"] = []
792
+ user_data["episodic_memory"].append(ep_summary)
793
+
794
+ # ==========================================
795
+ # به‌روزرسانی حافظه سمانتیک
796
+ # ==========================================
797
+ try:
798
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
799
+ existing_semantic = user_data.get("semantic_memory", {})
800
+
801
+ # فراخوانی تابع با هر دو آرگومان
802
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
803
+
804
+ # ذخیره دیتای جدید
805
+ user_data["semantic_memory"] = updated_semantic
806
+ except Exception as e:
807
+ print(f"Error updating semantic memory: {e}")
808
+ # ==========================================
809
+
810
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
811
+ new_session_id = len(user_data.get("sessions", []))
812
+
813
+ new_session = {
814
+ "session_id": new_session_id,
815
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
816
+ "conversation": []
817
+ }
818
+
819
+ if "sessions" not in user_data:
820
+ user_data["sessions"] = []
821
+
822
+ user_data["sessions"].append(new_session)
823
+
824
+ # پاک کردن تاریخچه چت در state
825
+ state["history"] = []
826
+
827
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
828
+ return [], state
829
+
830
+ check_user_btn.click(
831
+ handle_login_check,
832
+ inputs=[username_input, state],
833
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
834
+ show_progress="hidden"
835
+ )
836
+
837
+ register_btn.click(
838
+ handle_register,
839
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
840
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
841
+ show_progress="hidden"
842
+ )
843
+
844
+ switch_user_btn.click(
845
+ switch_user,
846
+ inputs=[state],
847
+ # اضافه کردن فیلدهای ثبت‌نام به خروجی‌ها
848
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input],
849
+ show_progress="hidden"
850
+ )
851
+
852
+
853
+ submit_btn.click(
854
+ handle_chat,
855
+ inputs=[user_input, state],
856
+ outputs=[user_input, chatbot, state],
857
+ show_progress="hidden"
858
+ )
859
+
860
+ user_input.submit(
861
+ handle_chat,
862
+ inputs=[user_input, state],
863
+ outputs=[user_input, chatbot, state],
864
+ show_progress="hidden"
865
+ )
866
+
867
+ clear_btn.click(
868
+ clear_history,
869
+ inputs=[state],
870
+ outputs=[chatbot, state],
871
+ show_progress="hidden"
872
+ )
873
+
874
+ # تغییر از clear_history به handle_new_session
875
+ new_session_btn.click(
876
+ handle_new_session,
877
+ inputs=[state],
878
+ outputs=[chatbot, state],
879
+ show_progress="hidden"
880
+
881
+
882
+ )
883
+
884
+ return demo
885
+
886
+
887
+ def main():
888
+ """Main function to initialize and launch the interface."""
889
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
890
+
891
+ if not gapgpt_api_key:
892
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
893
+ else:
894
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
895
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
896
+
897
+ # تنظیم LLM (مدل زبانی)
898
+ llm = LlamaIndexOpenAI(
899
+ model="gpt-4o",
900
+ temperature=1,
901
+ max_tokens=1024,
902
+ top_p=0.95,
903
+ frequency_penalty=0.4,
904
+ presence_penalty=0.2,
905
+ api_key=gapgpt_api_key,
906
+ api_base=GAPGPT_BASE_URL,
907
+ )
908
+
909
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
910
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
911
+ embed_model = OpenAIEmbedding(
912
+ api_key=gapgpt_api_key,
913
+ api_base=GAPGPT_BASE_URL,
914
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
915
+ )
916
+
917
+ # اعمال تنظیمات سراسری
918
+ Settings.llm = llm
919
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
920
+
921
+ Settings.prompt_helper = PromptHelper(
922
+ context_window=4096,
923
+ num_output=256,
924
+ chunk_overlap_ratio=20 / 4096,
925
+ tokenizer=tokenizer,
926
+ )
927
+
928
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
929
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
930
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
931
+ if 'api_keys' not in locals():
932
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
933
+
934
+ demo = create_gradio_interface(Settings, api_keys)
935
+ demo.launch(
936
+ server_name="127.0.0.1",
937
+ server_port=7860,
938
+ share=True
939
+ )
940
+
941
+
942
+ if __name__ == "__main__":
943
+ signal.signal(signal.SIGINT, signal_handler)
944
+ main()
Backup code/app_V12.py ADDED
@@ -0,0 +1,964 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ user_profile=None
332
+
333
+
334
+ ):
335
+ chatgpt_cfg = {
336
+ "model": "gpt-4o",
337
+ "temperature": temperature,
338
+ "max_tokens": max_length_tokens,
339
+ "top_p": top_p,
340
+ "frequency_penalty": 0.4,
341
+ "presence_penalty": 0.2,
342
+ "n": 1,
343
+ }
344
+
345
+ if text == "":
346
+ # Return same history if empty input
347
+ return history, history, "Empty context."
348
+
349
+ # Ensure history is initialized
350
+ if history is None:
351
+ history = []
352
+
353
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
354
+ history=history,
355
+ query=text, # Changed name to match prompt_utils
356
+ user_memory=user_memory,
357
+ user_name=user_name,
358
+ user_memory_index=user_memory_index,
359
+ service_context=service_context,
360
+ api_keys=api_keys,
361
+ api_index=api_index,
362
+ meta_prompt=meta_prompt,
363
+ new_user_meta_prompt=new_user_meta_prompt,
364
+ data_args=data_args,
365
+ boot_actual_name=boot_actual_name,
366
+ semantic_memory_text=semantic_memory_text,
367
+ query_category=query_category,
368
+ meta_prompt_semantic=meta_prompt_semantic,
369
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
370
+ )
371
+
372
+ # ==========================================
373
+ # اضافه کردن پروفایل به System Prompt
374
+ # ==========================================
375
+ if user_profile:
376
+ profile_str = (
377
+ f"\n\n[User Profile Information]:\n"
378
+ f"- Age: {user_profile.get('age', 'Unknown')}\n"
379
+ f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
380
+ f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
381
+ f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
382
+ f"Use this context subtly when talking to the user."
383
+ )
384
+ system_prompt += profile_str
385
+ # ==========================================
386
+
387
+ # Handle context window slicing manually if needed,
388
+ # though usually OpenAI manages this, or we slice the list of dicts.
389
+ current_history_for_llm = history
390
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
391
+ current_history_for_llm = history[-(data_args.max_history * 2):]
392
+
393
+ response = chatgpt_chat(
394
+ prompt=text,
395
+ system=system_prompt,
396
+ history=current_history_for_llm,
397
+ gpt_config=chatgpt_cfg,
398
+ api_index=api_index,
399
+ )
400
+
401
+ torch.cuda.empty_cache()
402
+
403
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
404
+ new_history = history + [
405
+ {"role": "user", "content": text},
406
+ {"role": "assistant", "content": response}
407
+ ]
408
+
409
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
410
+ # OR we convert strictly for saving if your legacy code needs it.
411
+ # For now, assuming we pass the object as is or convert for save)
412
+ if user_name:
413
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
414
+ # or pass a converted version. Let's try passing the new format.
415
+ save_local_memory(memory, new_history, user_name, data_args)
416
+
417
+ # Return: (Chatbot View, State History, Textbox Reset)
418
+ return new_history, new_history, "Generating..."
419
+
420
+
421
+
422
+ def create_gradio_interface(service_context, api_keys):
423
+
424
+
425
+ # ابتدا متغیر CSS را تعریف کنید
426
+ custom_css = """
427
+ /* استایل دکمه ارسال (Send) */
428
+ .send-btn {
429
+ border: 3px solid #0066cc !important;
430
+ border-radius: 12px !important;
431
+ background-color: white !important;
432
+ color: black !important;
433
+ font-weight: bold !important;
434
+ font-size: 16px !important;
435
+ transition: all 0.3s ease !important;
436
+ }
437
+ .send-btn:hover {
438
+ background-color: #0066cc !important;
439
+ color: white !important;
440
+ }
441
+
442
+ /* استایل نوار پایین و دکمه‌های آن */
443
+ .bottom-actions-row {
444
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
445
+ border-radius: 8px !important;
446
+ padding: 5px !important;
447
+ margin-top: 10px !important;
448
+ }
449
+
450
+ .action-btn {
451
+ border: none !important;
452
+ background: transparent !important;
453
+ color: black !important;
454
+ font-weight: bold !important;
455
+ box-shadow: none !important;
456
+ transition: all 0.3s ease !important;
457
+ }
458
+
459
+ .action-btn:hover {
460
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
461
+ border-radius: 8px !important;
462
+ }
463
+ /* مخفی کردن آیکون/مربع نارنجی پیش‌فرض Gradio */
464
+ .progress-level svg, .progress-level img {
465
+ display: none !important;
466
+ }
467
+
468
+ /* ایجاد یک دایره چرخان (Spinner) استاندارد */
469
+ .progress-level::before {
470
+ content: "";
471
+ display: inline-block;
472
+ width: 20px;
473
+ height: 20px;
474
+ border: 3px solid #e5e7eb; /* رنگ پس‌زمینه دایره */
475
+ border-radius: 50%;
476
+ border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
477
+ animation: spin 1s linear infinite;
478
+ margin-right: 8px;
479
+ vertical-align: middle;
480
+ }
481
+
482
+ /* انیمیشن چرخش */
483
+ @keyframes spin {
484
+ 0% { transform: rotate(0deg); }
485
+ 100% { transform: rotate(360deg); }
486
+ }
487
+
488
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
489
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
490
+ /*
491
+ .progress-text {
492
+ display: none !important;
493
+ }
494
+ */
495
+
496
+ """
497
+
498
+ with gr.Blocks(title="EMMA") as demo:
499
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
500
+ gr.HTML(f"<style>{custom_css}</style>")
501
+
502
+ # بقیه کدهای شما...
503
+
504
+
505
+ state = gr.State({
506
+ "history": [],
507
+ "user_name": None,
508
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
509
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
510
+ "service_context": service_context,
511
+ "api_keys": api_keys,
512
+ "api_index": 0,
513
+ "semantic_memory_text": "",
514
+ "new_conversation": True,
515
+ "initialized": False
516
+ })
517
+
518
+
519
+
520
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
521
+ with gr.Row():
522
+
523
+ # ==========================================
524
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
525
+ # ==========================================
526
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
527
+ with gr.Sidebar(open=True) as login_page:
528
+
529
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
530
+
531
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
532
+ login_status = gr.Textbox(visible=False, label="Status")
533
+
534
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
535
+
536
+ with gr.Column(visible=False) as registration_fields:
537
+ gr.Markdown("### ✨ New User Registration")
538
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
539
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
540
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
541
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
542
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
543
+
544
+
545
+ # ==========================================
546
+ # 2. CHAT PAGE (ستون سمت راست)
547
+ # ==========================================
548
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
549
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
550
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
551
+ #system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
552
+
553
+ with gr.Group():
554
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
555
+
556
+ with gr.Row():
557
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
558
+ # اختصاص کلاس send-btn به دکمه Send
559
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
560
+
561
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
562
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
563
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
564
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
565
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
566
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
567
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
568
+
569
+ # -------------------------------------------------------
570
+ # Internal Functions
571
+ # -------------------------------------------------------
572
+ def handle_login_check(name, state):
573
+ if not name.strip():
574
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
575
+
576
+ if name in memory:
577
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
578
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
579
+
580
+ new_state = state.copy()
581
+ new_state["user_name"] = name
582
+ new_state["memory"] = memory
583
+ new_state["initialized"] = True
584
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
585
+ new_state["semantic_memory_index"] = semantic_memory
586
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
587
+ new_state["episodic_memory_index"] = episodic_memory
588
+ new_state["history"] = []
589
+
590
+
591
+
592
+
593
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
594
+
595
+ return (
596
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
597
+ gr.update(visible=False),
598
+ gr.update(visible=True),
599
+ gr.update(visible=False, value=""),
600
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
601
+ gr.update(value=welcome_msg),
602
+ new_state
603
+ )
604
+ else:
605
+ return (
606
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
607
+ gr.update(visible=True),
608
+ gr.update(visible=False),
609
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
610
+ gr.update(),
611
+ gr.update(),
612
+ state
613
+ )
614
+
615
+ def handle_register(name, age, gender, occupation, residence, state):
616
+ name = str(name).strip()
617
+
618
+ if not name:
619
+ raise gr.Error("Please enter a valid user name.")
620
+
621
+ # Registration is only for new users.
622
+ if name in memory:
623
+ raise gr.Error(
624
+ f"User '{name}' already exists. Please use the login form."
625
+ )
626
+
627
+ # Create the user before trying to build or load their indices.
628
+ memory[name] = {
629
+ "profile": {
630
+ "age": age,
631
+ "gender": gender,
632
+ "occupation": occupation,
633
+ "residence": residence,
634
+ },
635
+ "sessions": [],
636
+ "episodic_memory": [],
637
+ "semantic_memory": {},
638
+ }
639
+
640
+ try:
641
+ (
642
+ _,
643
+ user_memory,
644
+ sessions_memory,
645
+ episodic_memory,
646
+ semantic_memory,
647
+ ) = enter_name_llamaindex(
648
+ name=name,
649
+ memory=memory,
650
+ data_args=data_args,
651
+ update_memory_index=True,
652
+ )
653
+ except Exception:
654
+ # Avoid leaving a partially registered user in memory.
655
+ memory.pop(name, None)
656
+ raise
657
+
658
+ new_state = dict(state or {})
659
+ new_state.update(
660
+ {
661
+ "user_name": name,
662
+ "memory": memory,
663
+ "initialized": True,
664
+ "history": [],
665
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
666
+ "user_memory_index": sessions_memory,
667
+ "episodic_memory_index": episodic_memory,
668
+ "semantic_memory_index": semantic_memory,
669
+ }
670
+ )
671
+
672
+ welcome_msg = f"Welcome {name}! Registration complete."
673
+
674
+ return (
675
+ gr.update(open=False),
676
+ gr.update(visible=False),
677
+ gr.update(visible=True),
678
+ gr.update(visible=False, value=""),
679
+ gr.update(
680
+ value=(
681
+ "<h2 style='text-align: center; color: #333;'>"
682
+ f"🧠 EMMA: Session for {name}</h2>"
683
+ )
684
+ ),
685
+ gr.update(value=welcome_msg),
686
+ new_state,
687
+ )
688
+
689
+ def switch_user(state):
690
+ if state["initialized"] and state["user_name"] in state["memory"]:
691
+ if state["memory"][state["user_name"]]["sessions"]:
692
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
693
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
694
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
695
+ # ==========================================
696
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
697
+ # ==========================================
698
+ try:
699
+ user_mem = state["memory"][state["user_name"]]
700
+ existing_semantic = user_mem.get("semantic_memory", {})
701
+
702
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
703
+
704
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
705
+ except Exception as e:
706
+ print(f"Error updating semantic memory on logout: {e}")
707
+ # ==========================================
708
+
709
+ new_state = state.copy()
710
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
711
+
712
+ return (
713
+ gr.update(open=True), # 1. باز شدن سایدبار
714
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام
715
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
716
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
717
+ gr.update(value=""), # 5. پاک کردن نام کاربری
718
+ new_state, # 6. استیت جدید
719
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
720
+ gr.update(value=""), # 8. پاک کردن age_input
721
+ gr.update(value=""), # 9. پاک کردن gender_input
722
+ gr.update(value=""), # 10. پاک کردن occupation_input
723
+ gr.update(value=""), # 11. پاک کردن residence_input
724
+ gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
725
+ )
726
+
727
+
728
+ def handle_chat(user_message, state):
729
+ if not user_message.strip():
730
+ print("[handle_chat] empty message")
731
+ print("[handle_chat] state =", state)
732
+ return gr.update(), state.get("history", []), state
733
+
734
+ print("[handle_chat] user_message =", repr(user_message))
735
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
736
+ print("[handle_chat] user_name =", state.get("user_name"))
737
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
738
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
739
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
740
+ print("[handle_chat] api_index =", state.get("api_index", 0))
741
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
742
+ print("[handle_chat] history len =", len(state.get("history", [])))
743
+
744
+ user_name = state.get("user_name")
745
+ user_memory_index = state.get("user_memory_index")
746
+ user_memory = state.get("user_memory", {})
747
+ user_memory_index = state.get("user_memory_index")
748
+ semantic_memory_text = state.get("semantic_memory_text", {})
749
+ service_context = state.get("service_context")
750
+ api_index = state.get("api_index", 0)
751
+ semantic_memory_text = state.get("semantic_memory_text", "")
752
+
753
+ query_category = classify_query_local(user_message)
754
+ print("[handle_chat] query_category =", query_category)
755
+
756
+ new_history, _, status_msg = predict_new(
757
+ text=user_message,
758
+ history=state.get("history", []),
759
+ top_p=0.95,
760
+ temperature=1.0,
761
+ max_length_tokens=1024,
762
+ max_context_length_tokens=4096,
763
+ user_name=user_name,
764
+ user_memory=user_memory,
765
+ user_memory_index=user_memory_index,
766
+ service_context=service_context,
767
+ api_index=api_index,
768
+ semantic_memory_text=semantic_memory_text,
769
+ query_category=query_category,
770
+
771
+ )
772
+
773
+ print("[handle_chat] status_msg =", status_msg)
774
+ print("[handle_chat] new_history len =", len(new_history))
775
+
776
+ state["history"] = new_history
777
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
778
+
779
+ return "", new_history, state
780
+
781
+ def clear_history(state):
782
+ state["history"] = []
783
+ return [], state
784
+
785
+ def handle_new_session(state):
786
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
787
+ user_name = state.get("user_name")
788
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
789
+ print("Error: User not logged in or memory missing.")
790
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
791
+ return [], state, gr.update() # خروجی سوم اضافه شد
792
+
793
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
794
+ user_data = state["memory"][user_name]
795
+
796
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
797
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
798
+ last_session = user_data["sessions"][-1]
799
+
800
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
801
+ if len(last_session.get("conversation", [])) > 0:
802
+ session_date = last_session.get("date", "")
803
+ session_id = last_session.get("session_id", 0)
804
+
805
+ # پاس دادن هر ۳ آرگومان به تابع
806
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
807
+
808
+ if "episodic_memory" not in user_data:
809
+ user_data["episodic_memory"] = []
810
+ user_data["episodic_memory"].append(ep_summary)
811
+
812
+ # ==========================================
813
+ # به‌روزرسانی حافظه سمانتیک
814
+ # ==========================================
815
+ try:
816
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
817
+ existing_semantic = user_data.get("semantic_memory", {})
818
+
819
+ # فراخوانی تابع با هر دو آرگومان
820
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
821
+
822
+ # ذخیره دیتای جدید
823
+ user_data["semantic_memory"] = updated_semantic
824
+ except Exception as e:
825
+ print(f"Error updating semantic memory: {e}")
826
+ # ==========================================
827
+
828
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
829
+ new_session_id = len(user_data.get("sessions", []))
830
+
831
+ new_session = {
832
+ "session_id": new_session_id,
833
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
834
+ "conversation": []
835
+ }
836
+
837
+ if "sessions" not in user_data:
838
+ user_data["sessions"] = []
839
+
840
+ user_data["sessions"].append(new_session)
841
+
842
+ # پاک کردن تاریخچه چت در state
843
+ state["history"] = []
844
+
845
+ # محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
846
+ session_number = len(user_data["sessions"])
847
+ new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
848
+
849
+ # بازگرداندن خروجی جدید برای active_header
850
+ return [], state, gr.update(value=new_header_text)
851
+
852
+ check_user_btn.click(
853
+ handle_login_check,
854
+ inputs=[username_input, state],
855
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
856
+ show_progress="hidden"
857
+ )
858
+
859
+ register_btn.click(
860
+ handle_register,
861
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
862
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
863
+ show_progress="hidden"
864
+ )
865
+
866
+ switch_user_btn.click(
867
+ switch_user,
868
+ inputs=[state],
869
+ # system_msg به انتهای لیست خروجی‌ها اضافه شد
870
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
871
+ show_progress="hidden"
872
+ )
873
+
874
+
875
+ submit_btn.click(
876
+ handle_chat,
877
+ inputs=[user_input, state],
878
+ outputs=[user_input, chatbot, state],
879
+ show_progress="hidden"
880
+ )
881
+
882
+ user_input.submit(
883
+ handle_chat,
884
+ inputs=[user_input, state],
885
+ outputs=[user_input, chatbot, state],
886
+ show_progress="hidden"
887
+ )
888
+
889
+ clear_btn.click(
890
+ clear_history,
891
+ inputs=[state],
892
+ outputs=[chatbot, state],
893
+ show_progress="hidden"
894
+ )
895
+
896
+ # تغییر از clear_history به handle_new_session
897
+ new_session_btn.click(
898
+ handle_new_session,
899
+ inputs=[state],
900
+ outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
901
+ show_progress="hidden"
902
+ )
903
+
904
+ return demo
905
+
906
+
907
+ def main():
908
+ """Main function to initialize and launch the interface."""
909
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
910
+
911
+ if not gapgpt_api_key:
912
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
913
+ else:
914
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
915
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
916
+
917
+ # تنظیم LLM (مدل زبانی)
918
+ llm = LlamaIndexOpenAI(
919
+ model="gpt-4o",
920
+ temperature=1,
921
+ max_tokens=1024,
922
+ top_p=0.95,
923
+ frequency_penalty=0.4,
924
+ presence_penalty=0.2,
925
+ api_key=gapgpt_api_key,
926
+ api_base=GAPGPT_BASE_URL,
927
+ )
928
+
929
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
930
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
931
+ embed_model = OpenAIEmbedding(
932
+ api_key=gapgpt_api_key,
933
+ api_base=GAPGPT_BASE_URL,
934
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
935
+ )
936
+
937
+ # اعمال تنظیمات سراسری
938
+ Settings.llm = llm
939
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
940
+
941
+ Settings.prompt_helper = PromptHelper(
942
+ context_window=4096,
943
+ num_output=256,
944
+ chunk_overlap_ratio=20 / 4096,
945
+ tokenizer=tokenizer,
946
+ )
947
+
948
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
949
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
950
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
951
+ if 'api_keys' not in locals():
952
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
953
+
954
+ demo = create_gradio_interface(Settings, api_keys)
955
+ demo.launch(
956
+ server_name="127.0.0.1",
957
+ server_port=7860,
958
+ share=True
959
+ )
960
+
961
+
962
+ if __name__ == "__main__":
963
+ signal.signal(signal.SIGINT, signal_handler)
964
+ main()
Backup code/app_V13.py ADDED
@@ -0,0 +1,973 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ user_profile=None
332
+
333
+
334
+ ):
335
+ chatgpt_cfg = {
336
+ "model": "gpt-4o",
337
+ "temperature": temperature,
338
+ "max_tokens": max_length_tokens,
339
+ "top_p": top_p,
340
+ "frequency_penalty": 0.4,
341
+ "presence_penalty": 0.2,
342
+ "n": 1,
343
+ }
344
+
345
+ if text == "":
346
+ # Return same history if empty input
347
+ return history, history, "Empty context."
348
+
349
+ # Ensure history is initialized
350
+ if history is None:
351
+ history = []
352
+
353
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
354
+ history=history,
355
+ query=text, # Changed name to match prompt_utils
356
+ user_memory=user_memory,
357
+ user_name=user_name,
358
+ user_memory_index=user_memory_index,
359
+ service_context=service_context,
360
+ api_keys=api_keys,
361
+ api_index=api_index,
362
+ meta_prompt=meta_prompt,
363
+ new_user_meta_prompt=new_user_meta_prompt,
364
+ data_args=data_args,
365
+ boot_actual_name=boot_actual_name,
366
+ semantic_memory_text=semantic_memory_text,
367
+ query_category=query_category,
368
+ meta_prompt_semantic=meta_prompt_semantic,
369
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
370
+ )
371
+
372
+ # ==========================================
373
+ # اضافه کردن پروفایل به System Prompt
374
+ # ==========================================
375
+ if user_profile:
376
+ profile_str = (
377
+ f"\n\n[User Profile Information]:\n"
378
+ f"- Age: {user_profile.get('age', 'Unknown')}\n"
379
+ f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
380
+ f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
381
+ f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
382
+ f"Use this context subtly when talking to the user."
383
+ )
384
+ system_prompt += profile_str
385
+ # ==========================================
386
+
387
+ # Handle context window slicing manually if needed,
388
+ # though usually OpenAI manages this, or we slice the list of dicts.
389
+ current_history_for_llm = history
390
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
391
+ current_history_for_llm = history[-(data_args.max_history * 2):]
392
+
393
+ response = chatgpt_chat(
394
+ prompt=text,
395
+ system=system_prompt,
396
+ history=current_history_for_llm,
397
+ gpt_config=chatgpt_cfg,
398
+ api_index=api_index,
399
+ )
400
+
401
+ torch.cuda.empty_cache()
402
+
403
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
404
+ new_history = history + [
405
+ {"role": "user", "content": text},
406
+ {"role": "assistant", "content": response}
407
+ ]
408
+
409
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
410
+ # OR we convert strictly for saving if your legacy code needs it.
411
+ # For now, assuming we pass the object as is or convert for save)
412
+ if user_name:
413
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
414
+ # or pass a converted version. Let's try passing the new format.
415
+ save_local_memory(memory, new_history, user_name, data_args)
416
+
417
+ # Return: (Chatbot View, State History, Textbox Reset)
418
+ return new_history, new_history, "Generating..."
419
+
420
+
421
+
422
+ def create_gradio_interface(service_context, api_keys):
423
+
424
+
425
+ # ابتدا متغیر CSS را تعریف کنید
426
+ custom_css = """
427
+ /* استایل دکمه ارسال (Send) */
428
+ .send-btn {
429
+ border: 3px solid #0066cc !important;
430
+ border-radius: 12px !important;
431
+ background-color: white !important;
432
+ color: black !important;
433
+ font-weight: bold !important;
434
+ font-size: 16px !important;
435
+ transition: all 0.3s ease !important;
436
+ }
437
+ .send-btn:hover {
438
+ background-color: #0066cc !important;
439
+ color: white !important;
440
+ }
441
+
442
+ /* استایل نوار پایین و دکمه‌های آن */
443
+ .bottom-actions-row {
444
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
445
+ border-radius: 8px !important;
446
+ padding: 5px !important;
447
+ margin-top: 10px !important;
448
+ }
449
+
450
+ .action-btn {
451
+ border: none !important;
452
+ background: transparent !important;
453
+ color: black !important;
454
+ font-weight: bold !important;
455
+ box-shadow: none !important;
456
+ transition: all 0.3s ease !important;
457
+ }
458
+
459
+ .action-btn:hover {
460
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
461
+ border-radius: 8px !important;
462
+ }
463
+ /* مخفی کردن آیکون/مربع نارنجی پیش‌فرض Gradio */
464
+ .progress-level svg, .progress-level img {
465
+ display: none !important;
466
+ }
467
+
468
+ /* ایجاد یک دایره چرخان (Spinner) استاندارد */
469
+ .progress-level::before {
470
+ content: "";
471
+ display: inline-block;
472
+ width: 20px;
473
+ height: 20px;
474
+ border: 3px solid #e5e7eb; /* رنگ پس‌زمینه دایره */
475
+ border-radius: 50%;
476
+ border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
477
+ animation: spin 1s linear infinite;
478
+ margin-right: 8px;
479
+ vertical-align: middle;
480
+ }
481
+
482
+ /* انیمیشن چرخش */
483
+ @keyframes spin {
484
+ 0% { transform: rotate(0deg); }
485
+ 100% { transform: rotate(360deg); }
486
+ }
487
+
488
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
489
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
490
+ /*
491
+ .progress-text {
492
+ display: none !important;
493
+ }
494
+ */
495
+
496
+ """
497
+
498
+ with gr.Blocks(title="EMMA") as demo:
499
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
500
+ gr.HTML(f"<style>{custom_css}</style>")
501
+
502
+ # بقیه کدهای شما...
503
+
504
+
505
+ state = gr.State({
506
+ "history": [],
507
+ "user_name": None,
508
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
509
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
510
+ "service_context": service_context,
511
+ "api_keys": api_keys,
512
+ "api_index": 0,
513
+ "semantic_memory_text": "",
514
+ "new_conversation": True,
515
+ "initialized": False
516
+ })
517
+
518
+
519
+
520
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
521
+ with gr.Row():
522
+
523
+ # ==========================================
524
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
525
+ # ==========================================
526
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
527
+ with gr.Sidebar(open=True) as login_page:
528
+
529
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
530
+
531
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
532
+ login_status = gr.Textbox(visible=False, label="Status")
533
+
534
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
535
+
536
+ with gr.Column(visible=False) as registration_fields:
537
+ gr.Markdown("### ✨ New User Registration")
538
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
539
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
540
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
541
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
542
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
543
+
544
+
545
+ # ==========================================
546
+ # 2. CHAT PAGE (ستون سمت راست)
547
+ # ==========================================
548
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
549
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
550
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
551
+ #system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
552
+
553
+ with gr.Group():
554
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
555
+
556
+ with gr.Row():
557
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
558
+ # اختصاص کلاس send-btn به دکمه Send
559
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
560
+
561
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
562
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
563
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
564
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
565
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
566
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
567
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
568
+
569
+ # -------------------------------------------------------
570
+ # Internal Functions
571
+ # -------------------------------------------------------
572
+ def handle_login_check(name, state):
573
+ if not name.strip():
574
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
575
+
576
+ if name in memory:
577
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
578
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
579
+
580
+ new_state = state.copy()
581
+ new_state["user_name"] = name
582
+ new_state["memory"] = memory
583
+ new_state["initialized"] = True
584
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
585
+ new_state["semantic_memory_index"] = semantic_memory
586
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
587
+ new_state["episodic_memory_index"] = episodic_memory
588
+ new_state["history"] = []
589
+
590
+
591
+
592
+
593
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
594
+
595
+ return (
596
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
597
+ gr.update(visible=False),
598
+ gr.update(visible=True),
599
+ gr.update(visible=False, value=""),
600
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
601
+ gr.update(value=welcome_msg),
602
+ new_state
603
+ )
604
+ else:
605
+ return (
606
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
607
+ gr.update(visible=True),
608
+ gr.update(visible=False),
609
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
610
+ gr.update(),
611
+ gr.update(),
612
+ state
613
+ )
614
+
615
+ def handle_register(name, age, gender, occupation, residence, state):
616
+ name = str(name).strip()
617
+
618
+ if not name:
619
+ raise gr.Error("Please enter a valid user name.")
620
+
621
+ # Registration is only for new users.
622
+ if name in memory:
623
+ raise gr.Error(
624
+ f"User '{name}' already exists. Please use the login form."
625
+ )
626
+
627
+ # Create the user before trying to build or load their indices.
628
+ memory[name] = {
629
+ "profile": {
630
+ "age": age,
631
+ "gender": gender,
632
+ "occupation": occupation,
633
+ "residence": residence,
634
+ },
635
+ "sessions": [],
636
+ "episodic_memory": [],
637
+ "semantic_memory": {},
638
+ }
639
+
640
+ try:
641
+ (
642
+ _,
643
+ user_memory,
644
+ sessions_memory,
645
+ episodic_memory,
646
+ semantic_memory,
647
+ ) = enter_name_llamaindex(
648
+ name=name,
649
+ memory=memory,
650
+ data_args=data_args,
651
+ update_memory_index=True,
652
+ )
653
+ except Exception:
654
+ # Avoid leaving a partially registered user in memory.
655
+ memory.pop(name, None)
656
+ raise
657
+
658
+ new_state = dict(state or {})
659
+ new_state.update(
660
+ {
661
+ "user_name": name,
662
+ "memory": memory,
663
+ "initialized": True,
664
+ "history": [],
665
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
666
+ "user_memory_index": sessions_memory,
667
+ "episodic_memory_index": episodic_memory,
668
+ "semantic_memory_index": semantic_memory,
669
+ }
670
+ )
671
+
672
+ welcome_msg = f"Welcome {name}! Registration complete."
673
+
674
+ return (
675
+ gr.update(open=False),
676
+ gr.update(visible=False),
677
+ gr.update(visible=True),
678
+ gr.update(visible=False, value=""),
679
+ gr.update(
680
+ value=(
681
+ "<h2 style='text-align: center; color: #333;'>"
682
+ f"🧠 EMMA: Session for {name}</h2>"
683
+ )
684
+ ),
685
+ gr.update(value=welcome_msg),
686
+ new_state,
687
+ )
688
+
689
+ def switch_user(state):
690
+ if state["initialized"] and state["user_name"] in state["memory"]:
691
+ if state["memory"][state["user_name"]]["sessions"]:
692
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
693
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
694
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
695
+ # ==========================================
696
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
697
+ # ==========================================
698
+ try:
699
+ user_mem = state["memory"][state["user_name"]]
700
+ existing_semantic = user_mem.get("semantic_memory", {})
701
+
702
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
703
+
704
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
705
+ except Exception as e:
706
+ print(f"Error updating semantic memory on logout: {e}")
707
+ # ==========================================
708
+
709
+ new_state = state.copy()
710
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
711
+
712
+ return (
713
+ gr.update(open=True), # 1. باز شدن سایدبار
714
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام
715
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
716
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
717
+ gr.update(value=""), # 5. پاک کردن نام کاربری
718
+ new_state, # 6. استیت جدید
719
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
720
+ gr.update(value=""), # 8. پاک کردن age_input
721
+ gr.update(value=""), # 9. پاک کردن gender_input
722
+ gr.update(value=""), # 10. پاک کردن occupation_input
723
+ gr.update(value=""), # 11. پاک کردن residence_input
724
+ gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
725
+ )
726
+
727
+
728
+ def handle_chat(user_message, state):
729
+ if not user_message.strip():
730
+ print("[handle_chat] empty message")
731
+ print("[handle_chat] state =", state)
732
+ return gr.update(), state.get("history", []), state
733
+
734
+ print("[handle_chat] user_message =", repr(user_message))
735
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
736
+ print("[handle_chat] user_name =", state.get("user_name"))
737
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
738
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
739
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
740
+ print("[handle_chat] api_index =", state.get("api_index", 0))
741
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
742
+ print("[handle_chat] history len =", len(state.get("history", [])))
743
+
744
+ user_name = state.get("user_name")
745
+ user_memory_index = state.get("user_memory_index")
746
+ user_memory = state.get("user_memory", {})
747
+ user_memory_index = state.get("user_memory_index")
748
+ semantic_memory_text = state.get("semantic_memory_text", {})
749
+ service_context = state.get("service_context")
750
+ api_index = state.get("api_index", 0)
751
+ semantic_memory_text = state.get("semantic_memory_text", "")
752
+
753
+ # ==========================================
754
+ # استخراج پروفایل کاربر از حافظه
755
+ # ==========================================
756
+ user_profile = {}
757
+ if user_name and state.get("memory") and user_name in state["memory"]:
758
+ user_profile = state["memory"][user_name].get("profile", {})
759
+ # ==========================================
760
+
761
+ query_category = classify_query_local(user_message)
762
+ print("[handle_chat] query_category =", query_category)
763
+
764
+ new_history, _, status_msg = predict_new(
765
+ text=user_message,
766
+ history=state.get("history", []),
767
+ top_p=0.95,
768
+ temperature=1.0,
769
+ max_length_tokens=1024,
770
+ max_context_length_tokens=4096,
771
+ user_name=user_name,
772
+ user_memory=user_memory,
773
+ user_memory_index=user_memory_index,
774
+ service_context=service_context,
775
+ api_index=api_index,
776
+ semantic_memory_text=semantic_memory_text,
777
+ query_category=query_category,
778
+ user_profile=user_profile
779
+
780
+ )
781
+
782
+ print("[handle_chat] status_msg =", status_msg)
783
+ print("[handle_chat] new_history len =", len(new_history))
784
+
785
+ state["history"] = new_history
786
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
787
+
788
+ return "", new_history, state
789
+
790
+ def clear_history(state):
791
+ state["history"] = []
792
+ return [], state
793
+
794
+ def handle_new_session(state):
795
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
796
+ user_name = state.get("user_name")
797
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
798
+ print("Error: User not logged in or memory missing.")
799
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
800
+ return [], state, gr.update() # خروجی سوم اضافه شد
801
+
802
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
803
+ user_data = state["memory"][user_name]
804
+
805
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
806
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
807
+ last_session = user_data["sessions"][-1]
808
+
809
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
810
+ if len(last_session.get("conversation", [])) > 0:
811
+ session_date = last_session.get("date", "")
812
+ session_id = last_session.get("session_id", 0)
813
+
814
+ # پاس دادن هر ۳ آرگومان به تابع
815
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
816
+
817
+ if "episodic_memory" not in user_data:
818
+ user_data["episodic_memory"] = []
819
+ user_data["episodic_memory"].append(ep_summary)
820
+
821
+ # ==========================================
822
+ # به‌روزرسانی حافظه سمانتیک
823
+ # ==========================================
824
+ try:
825
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
826
+ existing_semantic = user_data.get("semantic_memory", {})
827
+
828
+ # فراخوانی تابع با هر دو آرگومان
829
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
830
+
831
+ # ذخیره دیتای جدید
832
+ user_data["semantic_memory"] = updated_semantic
833
+ except Exception as e:
834
+ print(f"Error updating semantic memory: {e}")
835
+ # ==========================================
836
+
837
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
838
+ new_session_id = len(user_data.get("sessions", []))
839
+
840
+ new_session = {
841
+ "session_id": new_session_id,
842
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
843
+ "conversation": []
844
+ }
845
+
846
+ if "sessions" not in user_data:
847
+ user_data["sessions"] = []
848
+
849
+ user_data["sessions"].append(new_session)
850
+
851
+ # پاک کردن تاریخچه چت در state
852
+ state["history"] = []
853
+
854
+ # محاسبه شماره جلسه فعلی (چون از 0 ش��وع میشود، +1 میکنیم)
855
+ session_number = len(user_data["sessions"])
856
+ new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
857
+
858
+ # بازگرداندن خروجی جدید برای active_header
859
+ return [], state, gr.update(value=new_header_text)
860
+
861
+ check_user_btn.click(
862
+ handle_login_check,
863
+ inputs=[username_input, state],
864
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
865
+ show_progress="hidden"
866
+ )
867
+
868
+ register_btn.click(
869
+ handle_register,
870
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
871
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
872
+ show_progress="hidden"
873
+ )
874
+
875
+ switch_user_btn.click(
876
+ switch_user,
877
+ inputs=[state],
878
+ # system_msg به انتهای لیست خروجی‌ها اضافه شد
879
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
880
+ show_progress="hidden"
881
+ )
882
+
883
+
884
+ submit_btn.click(
885
+ handle_chat,
886
+ inputs=[user_input, state],
887
+ outputs=[user_input, chatbot, state],
888
+ show_progress="hidden"
889
+ )
890
+
891
+ user_input.submit(
892
+ handle_chat,
893
+ inputs=[user_input, state],
894
+ outputs=[user_input, chatbot, state],
895
+ show_progress="hidden"
896
+ )
897
+
898
+ clear_btn.click(
899
+ clear_history,
900
+ inputs=[state],
901
+ outputs=[chatbot, state],
902
+ show_progress="hidden"
903
+ )
904
+
905
+ # تغییر از clear_history به handle_new_session
906
+ new_session_btn.click(
907
+ handle_new_session,
908
+ inputs=[state],
909
+ outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
910
+ show_progress="hidden"
911
+ )
912
+
913
+ return demo
914
+
915
+
916
+ def main():
917
+ """Main function to initialize and launch the interface."""
918
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
919
+
920
+ if not gapgpt_api_key:
921
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
922
+ else:
923
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
924
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
925
+
926
+ # تنظیم LLM (مدل زبانی)
927
+ llm = LlamaIndexOpenAI(
928
+ model="gpt-4o",
929
+ temperature=1,
930
+ max_tokens=1024,
931
+ top_p=0.95,
932
+ frequency_penalty=0.4,
933
+ presence_penalty=0.2,
934
+ api_key=gapgpt_api_key,
935
+ api_base=GAPGPT_BASE_URL,
936
+ )
937
+
938
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
939
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
940
+ embed_model = OpenAIEmbedding(
941
+ api_key=gapgpt_api_key,
942
+ api_base=GAPGPT_BASE_URL,
943
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
944
+ )
945
+
946
+ # اعمال تنظیمات سراسری
947
+ Settings.llm = llm
948
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
949
+
950
+ Settings.prompt_helper = PromptHelper(
951
+ context_window=4096,
952
+ num_output=256,
953
+ chunk_overlap_ratio=20 / 4096,
954
+ tokenizer=tokenizer,
955
+ )
956
+
957
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
958
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
959
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
960
+ if 'api_keys' not in locals():
961
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
962
+
963
+ demo = create_gradio_interface(Settings, api_keys)
964
+ demo.launch(
965
+ server_name="127.0.0.1",
966
+ server_port=7860,
967
+ share=True
968
+ )
969
+
970
+
971
+ if __name__ == "__main__":
972
+ signal.signal(signal.SIGINT, signal_handler)
973
+ main()
Backup code/app_V14.py ADDED
@@ -0,0 +1,1032 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ user_profile=None
332
+
333
+
334
+ ):
335
+ chatgpt_cfg = {
336
+ "model": "gpt-4o",
337
+ "temperature": temperature,
338
+ "max_tokens": max_length_tokens,
339
+ "top_p": top_p,
340
+ "frequency_penalty": 0.4,
341
+ "presence_penalty": 0.2,
342
+ "n": 1,
343
+ }
344
+
345
+ if text == "":
346
+ # Return same history if empty input
347
+ return history, history, "Empty context."
348
+
349
+ # Ensure history is initialized
350
+ if history is None:
351
+ history = []
352
+
353
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
354
+ history=history,
355
+ query=text, # Changed name to match prompt_utils
356
+ user_memory=user_memory,
357
+ user_name=user_name,
358
+ user_memory_index=user_memory_index,
359
+ service_context=service_context,
360
+ api_keys=api_keys,
361
+ api_index=api_index,
362
+ meta_prompt=meta_prompt,
363
+ new_user_meta_prompt=new_user_meta_prompt,
364
+ data_args=data_args,
365
+ boot_actual_name=boot_actual_name,
366
+ semantic_memory_text=semantic_memory_text,
367
+ query_category=query_category,
368
+ meta_prompt_semantic=meta_prompt_semantic,
369
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
370
+ )
371
+
372
+ # ==========================================
373
+ # اضافه کردن پروفایل به System Prompt
374
+ # ==========================================
375
+ if user_profile:
376
+ profile_str = (
377
+ f"\n\n[User Profile Information]:\n"
378
+ f"- Age: {user_profile.get('age', 'Unknown')}\n"
379
+ f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
380
+ f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
381
+ f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
382
+ f"Use this context subtly when talking to the user."
383
+ )
384
+ system_prompt += profile_str
385
+ # ==========================================
386
+
387
+ # Handle context window slicing manually if needed,
388
+ # though usually OpenAI manages this, or we slice the list of dicts.
389
+ current_history_for_llm = history
390
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
391
+ current_history_for_llm = history[-(data_args.max_history * 2):]
392
+
393
+ response = chatgpt_chat(
394
+ prompt=text,
395
+ system=system_prompt,
396
+ history=current_history_for_llm,
397
+ gpt_config=chatgpt_cfg,
398
+ api_index=api_index,
399
+ )
400
+
401
+ torch.cuda.empty_cache()
402
+
403
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
404
+ new_history = history + [
405
+ {"role": "user", "content": text},
406
+ {"role": "assistant", "content": response}
407
+ ]
408
+
409
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
410
+ # OR we convert strictly for saving if your legacy code needs it.
411
+ # For now, assuming we pass the object as is or convert for save)
412
+ if user_name:
413
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
414
+ # or pass a converted version. Let's try passing the new format.
415
+ save_local_memory(memory, new_history, user_name, data_args)
416
+
417
+ # Return: (Chatbot View, State History, Textbox Reset)
418
+ return new_history, new_history, "Generating..."
419
+
420
+
421
+
422
+ def create_gradio_interface(service_context, api_keys):
423
+
424
+
425
+ # ابتدا متغیر CSS را تعریف کنید
426
+ custom_css = """
427
+ /* استایل دکمه ارسال (Send) */
428
+ .send-btn {
429
+ border: 3px solid #0066cc !important;
430
+ border-radius: 12px !important;
431
+ background-color: white !important;
432
+ color: black !important;
433
+ font-weight: bold !important;
434
+ font-size: 16px !important;
435
+ transition: all 0.3s ease !important;
436
+ }
437
+ .send-btn:hover {
438
+ background-color: #0066cc !important;
439
+ color: white !important;
440
+ }
441
+
442
+ /* استایل نوار پایین و دکمه‌های آن */
443
+ .bottom-actions-row {
444
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
445
+ border-radius: 8px !important;
446
+ padding: 5px !important;
447
+ margin-top: 10px !important;
448
+ }
449
+
450
+ .action-btn {
451
+ border: none !important;
452
+ background: transparent !important;
453
+ color: black !important;
454
+ font-weight: bold !important;
455
+ box-shadow: none !important;
456
+ transition: all 0.3s ease !important;
457
+ }
458
+
459
+ .action-btn:hover {
460
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
461
+ border-radius: 8px !important;
462
+ }
463
+ /* ========================================== */
464
+ /* لودینگ تمام‌صفحه و غیرفعال‌سازی تعاملات */
465
+ /* ========================================== */
466
+
467
+ /* مخفی کردن نوار پیشرفت پیش‌فرض Gradio */
468
+ .progress-level, .progress-text, .progress-level svg, .progress-level img {
469
+ display: none !important;
470
+ }
471
+
472
+ /* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایل‌ها روی body اعمال می‌شود */
473
+ body:has(.progress-level) {
474
+ pointer-events: none !important; /* غیرفعال کردن تمام کلیک‌ها */
475
+ }
476
+
477
+ /* ایجاد هاله نیمه‌شفاف روی کل صفحه */
478
+ body:has(.progress-level)::after {
479
+ content: "";
480
+ position: fixed;
481
+ top: 0; left: 0;
482
+ width: 100vw; height: 100vh;
483
+ background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمه‌شفاف */
484
+ z-index: 9998;
485
+ pointer-events: all; /* برای گرفتن کلیک‌ها و جلوگیری از عبور آن‌ها */
486
+ cursor: wait;
487
+ }
488
+
489
+ /* ایجاد اسپینر لودینگ در مرکز صفحه */
490
+ body:has(.progress-level)::before {
491
+ content: "";
492
+ position: fixed;
493
+ top: 50%; left: 50%;
494
+ transform: translate(-50%, -50%);
495
+ width: 60px; height: 60px;
496
+ border: 6px solid #e5e7eb;
497
+ border-top-color: #0066cc;
498
+ border-radius: 50%;
499
+ animation: spin 1s linear infinite;
500
+ z-index: 9999;
501
+ }
502
+
503
+ @keyframes spin {
504
+ 0% { transform: translate(-50%, -50%) rotate(0deg); }
505
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
506
+ }
507
+
508
+
509
+ /* انیمیشن چرخش */
510
+ @keyframes spin {
511
+ 0% { transform: rotate(0deg); }
512
+ 100% { transform: rotate(360deg); }
513
+ }
514
+
515
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
516
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
517
+ /*
518
+ .progress-text {
519
+ display: none !important;
520
+ }
521
+ */
522
+ /* انیمیشن سه نقطه در حال تایپ */
523
+ .typing-dots::after {
524
+ content: '';
525
+ animation: typing 1.5s infinite;
526
+ }
527
+ @keyframes typing {
528
+ 0% { content: ''; }
529
+ 25% { content: ' .'; }
530
+ 50% { content: ' . .'; }
531
+ 75% { content: ' . . .'; }
532
+ 100% { content: ''; }
533
+ }
534
+
535
+
536
+ """
537
+
538
+ with gr.Blocks(title="EMMA") as demo:
539
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
540
+ gr.HTML(f"<style>{custom_css}</style>")
541
+
542
+ # بقیه کدهای شما...
543
+
544
+
545
+ state = gr.State({
546
+ "history": [],
547
+ "user_name": None,
548
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
549
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
550
+ "service_context": service_context,
551
+ "api_keys": api_keys,
552
+ "api_index": 0,
553
+ "semantic_memory_text": "",
554
+ "new_conversation": True,
555
+ "initialized": False
556
+ })
557
+
558
+
559
+
560
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
561
+ with gr.Row():
562
+
563
+ # ==========================================
564
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
565
+ # ==========================================
566
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
567
+ with gr.Sidebar(open=True) as login_page:
568
+
569
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
570
+
571
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
572
+ login_status = gr.Textbox(visible=False, label="Status")
573
+
574
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
575
+
576
+ with gr.Column(visible=False) as registration_fields:
577
+ gr.Markdown("### ✨ New User Registration")
578
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
579
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
580
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
581
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
582
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
583
+
584
+
585
+ # ==========================================
586
+ # 2. CHAT PAGE (ستون سمت راست)
587
+ # ==========================================
588
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
589
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
590
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
591
+ #system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
592
+
593
+ with gr.Group():
594
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
595
+
596
+ with gr.Row():
597
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
598
+ # اختصاص کلاس send-btn به دکمه Send
599
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
600
+
601
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
602
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
603
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
604
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
605
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
606
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
607
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
608
+
609
+ # -------------------------------------------------------
610
+ # Internal Functions
611
+ # -------------------------------------------------------
612
+ def handle_login_check(name, state):
613
+ if not name.strip():
614
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
615
+
616
+ if name in memory:
617
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
618
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
619
+
620
+ new_state = state.copy()
621
+ new_state["user_name"] = name
622
+ new_state["memory"] = memory
623
+ new_state["initialized"] = True
624
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
625
+ new_state["semantic_memory_index"] = semantic_memory
626
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
627
+ new_state["episodic_memory_index"] = episodic_memory
628
+ new_state["history"] = []
629
+
630
+
631
+
632
+
633
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
634
+
635
+ return (
636
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
637
+ gr.update(visible=False),
638
+ gr.update(visible=True),
639
+ gr.update(visible=False, value=""),
640
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
641
+ gr.update(value=welcome_msg),
642
+ new_state
643
+ )
644
+ else:
645
+ return (
646
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
647
+ gr.update(visible=True),
648
+ gr.update(visible=False),
649
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
650
+ gr.update(),
651
+ gr.update(),
652
+ state
653
+ )
654
+
655
+ def handle_register(name, age, gender, occupation, residence, state):
656
+ name = str(name).strip()
657
+
658
+ if not name:
659
+ raise gr.Error("Please enter a valid user name.")
660
+
661
+ # Registration is only for new users.
662
+ if name in memory:
663
+ raise gr.Error(
664
+ f"User '{name}' already exists. Please use the login form."
665
+ )
666
+
667
+ # Create the user before trying to build or load their indices.
668
+ memory[name] = {
669
+ "profile": {
670
+ "age": age,
671
+ "gender": gender,
672
+ "occupation": occupation,
673
+ "residence": residence,
674
+ },
675
+ "sessions": [],
676
+ "episodic_memory": [],
677
+ "semantic_memory": {},
678
+ }
679
+
680
+ try:
681
+ (
682
+ _,
683
+ user_memory,
684
+ sessions_memory,
685
+ episodic_memory,
686
+ semantic_memory,
687
+ ) = enter_name_llamaindex(
688
+ name=name,
689
+ memory=memory,
690
+ data_args=data_args,
691
+ update_memory_index=True,
692
+ )
693
+ except Exception:
694
+ # Avoid leaving a partially registered user in memory.
695
+ memory.pop(name, None)
696
+ raise
697
+
698
+ new_state = dict(state or {})
699
+ new_state.update(
700
+ {
701
+ "user_name": name,
702
+ "memory": memory,
703
+ "initialized": True,
704
+ "history": [],
705
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
706
+ "user_memory_index": sessions_memory,
707
+ "episodic_memory_index": episodic_memory,
708
+ "semantic_memory_index": semantic_memory,
709
+ }
710
+ )
711
+
712
+ welcome_msg = f"Welcome {name}! Registration complete."
713
+
714
+ return (
715
+ gr.update(open=False),
716
+ gr.update(visible=False),
717
+ gr.update(visible=True),
718
+ gr.update(visible=False, value=""),
719
+ gr.update(
720
+ value=(
721
+ "<h2 style='text-align: center; color: #333;'>"
722
+ f"🧠 EMMA: Session for {name}</h2>"
723
+ )
724
+ ),
725
+ gr.update(value=welcome_msg),
726
+ new_state,
727
+ )
728
+
729
+ def switch_user(state):
730
+ if state["initialized"] and state["user_name"] in state["memory"]:
731
+ if state["memory"][state["user_name"]]["sessions"]:
732
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
733
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
734
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
735
+ # ==========================================
736
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
737
+ # ==========================================
738
+ try:
739
+ user_mem = state["memory"][state["user_name"]]
740
+ existing_semantic = user_mem.get("semantic_memory", {})
741
+
742
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
743
+
744
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
745
+ except Exception as e:
746
+ print(f"Error updating semantic memory on logout: {e}")
747
+ # ==========================================
748
+
749
+ new_state = state.copy()
750
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
751
+
752
+ return (
753
+ gr.update(open=True), # 1. باز شدن سایدبار
754
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام
755
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
756
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
757
+ gr.update(value=""), # 5. پاک کردن نام کاربری
758
+ new_state, # 6. استیت جدید
759
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
760
+ gr.update(value=""), # 8. پاک کردن age_input
761
+ gr.update(value=""), # 9. پاک کردن gender_input
762
+ gr.update(value=""), # 10. پاک کردن occupation_input
763
+ gr.update(value=""), # 11. پاک کردن residence_input
764
+ gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
765
+ )
766
+
767
+
768
+ def handle_chat(user_message, state):
769
+ if not user_message.strip():
770
+ print("[handle_chat] empty message")
771
+ print("[handle_chat] state =", state)
772
+ # تبدیل return به yield
773
+ yield gr.update(), state.get("history", []), state
774
+ return
775
+
776
+ print("[handle_chat] user_message =", repr(user_message))
777
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
778
+ print("[handle_chat] user_name =", state.get("user_name"))
779
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
780
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
781
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
782
+ print("[handle_chat] api_index =", state.get("api_index", 0))
783
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
784
+ print("[handle_chat] history len =", len(state.get("history", [])))
785
+
786
+ # ==========================================
787
+ # ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
788
+ # ==========================================
789
+ current_history = state.get("history", [])
790
+ temp_history = current_history + [
791
+ {"role": "user", "content": user_message},
792
+ {"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
793
+ ]
794
+
795
+ # باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI می‌فرستیم
796
+ yield gr.update(value=""), temp_history, state
797
+
798
+
799
+ # ادامه پردازش‌های اصلی تابع شما
800
+ user_name = state.get("user_name")
801
+ user_memory_index = state.get("user_memory_index")
802
+ user_memory = state.get("user_memory", {})
803
+ user_memory_index = state.get("user_memory_index")
804
+ semantic_memory_text = state.get("semantic_memory_text", {})
805
+ service_context = state.get("service_context")
806
+ api_index = state.get("api_index", 0)
807
+ semantic_memory_text = state.get("semantic_memory_text", "")
808
+
809
+ # ==========================================
810
+ # استخراج پروفایل کاربر از حافظه
811
+ # ==========================================
812
+ user_profile = {}
813
+ if user_name and state.get("memory") and user_name in state["memory"]:
814
+ user_profile = state["memory"][user_name].get("profile", {})
815
+ # ==========================================
816
+
817
+ query_category = classify_query_local(user_message)
818
+ print("[handle_chat] query_category =", query_category)
819
+
820
+ # ارسال current_history به مدل (بدون انیمیشن موقت)
821
+ new_history, _, status_msg = predict_new(
822
+ text=user_message,
823
+ history=current_history,
824
+ top_p=0.95,
825
+ temperature=1.0,
826
+ max_length_tokens=1024,
827
+ max_context_length_tokens=4096,
828
+ user_name=user_name,
829
+ user_memory=user_memory,
830
+ user_memory_index=user_memory_index,
831
+ service_context=service_context,
832
+ api_index=api_index,
833
+ semantic_memory_text=semantic_memory_text,
834
+ query_category=query_category,
835
+ user_profile=user_profile
836
+ )
837
+
838
+ print("[handle_chat] status_msg =", status_msg)
839
+ print("[handle_chat] new_history len =", len(new_history))
840
+
841
+ state["history"] = new_history
842
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
843
+
844
+ # ==========================================
845
+ # ۳. جایگزینی پیام لودینگ با پاسخ نهایی
846
+ # ==========================================
847
+ yield gr.update(), new_history, state
848
+
849
+ def clear_history(state):
850
+ state["history"] = []
851
+ return [], state
852
+
853
+ def handle_new_session(state):
854
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
855
+ user_name = state.get("user_name")
856
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
857
+ print("Error: User not logged in or memory missing.")
858
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
859
+ return [], state, gr.update() # خروجی سوم اضافه شد
860
+
861
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
862
+ user_data = state["memory"][user_name]
863
+
864
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
865
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
866
+ last_session = user_data["sessions"][-1]
867
+
868
+ # فقط در صورتی حافظه را استخراج کن که ��لسه قبلی خالی نباشد
869
+ if len(last_session.get("conversation", [])) > 0:
870
+ session_date = last_session.get("date", "")
871
+ session_id = last_session.get("session_id", 0)
872
+
873
+ # پاس دادن هر ۳ آرگومان به تابع
874
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
875
+
876
+ if "episodic_memory" not in user_data:
877
+ user_data["episodic_memory"] = []
878
+ user_data["episodic_memory"].append(ep_summary)
879
+
880
+ # ==========================================
881
+ # به‌روزرسانی حافظه سمانتیک
882
+ # ==========================================
883
+ try:
884
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
885
+ existing_semantic = user_data.get("semantic_memory", {})
886
+
887
+ # فراخوانی تابع با هر دو آرگومان
888
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
889
+
890
+ # ذخیره دیتای جدید
891
+ user_data["semantic_memory"] = updated_semantic
892
+ except Exception as e:
893
+ print(f"Error updating semantic memory: {e}")
894
+ # ==========================================
895
+
896
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
897
+ new_session_id = len(user_data.get("sessions", []))
898
+
899
+ new_session = {
900
+ "session_id": new_session_id,
901
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
902
+ "conversation": []
903
+ }
904
+
905
+ if "sessions" not in user_data:
906
+ user_data["sessions"] = []
907
+
908
+ user_data["sessions"].append(new_session)
909
+
910
+ # پاک کردن تاریخچه چت در state
911
+ state["history"] = []
912
+
913
+ # محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
914
+ session_number = len(user_data["sessions"])
915
+ new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
916
+
917
+ # بازگرداندن خروجی جدید برای active_header
918
+ return [], state, gr.update(value=new_header_text)
919
+
920
+ check_user_btn.click(
921
+ handle_login_check,
922
+ inputs=[username_input, state],
923
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
924
+ # show_progress="hidden"
925
+ )
926
+
927
+ register_btn.click(
928
+ handle_register,
929
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
930
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
931
+ # show_progress="hidden"
932
+ )
933
+
934
+ switch_user_btn.click(
935
+ switch_user,
936
+ inputs=[state],
937
+ # system_msg به انتهای لیست خروجی‌ها اضافه شد
938
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
939
+ # show_progress="hidden"
940
+ )
941
+
942
+
943
+ submit_btn.click(
944
+ handle_chat,
945
+ inputs=[user_input, state],
946
+ outputs=[user_input, chatbot, state],
947
+ # show_progress="hidden"
948
+ )
949
+
950
+ user_input.submit(
951
+ handle_chat,
952
+ inputs=[user_input, state],
953
+ outputs=[user_input, chatbot, state],
954
+ # show_progress="hidden"
955
+ )
956
+
957
+ clear_btn.click(
958
+ clear_history,
959
+ inputs=[state],
960
+ outputs=[chatbot, state],
961
+ # show_progress="hidden"
962
+ )
963
+
964
+ # تغییر از clear_history به handle_new_session
965
+ new_session_btn.click(
966
+ handle_new_session,
967
+ inputs=[state],
968
+ outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
969
+ # show_progress="hidden"
970
+ )
971
+
972
+ return demo
973
+
974
+
975
+ def main():
976
+ """Main function to initialize and launch the interface."""
977
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
978
+
979
+ if not gapgpt_api_key:
980
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
981
+ else:
982
+ # تغییر مهم ۱: ست کردن متغیر محیطی ��رای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
983
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
984
+
985
+ # تنظیم LLM (مدل زبانی)
986
+ llm = LlamaIndexOpenAI(
987
+ model="gpt-4o",
988
+ temperature=1,
989
+ max_tokens=1024,
990
+ top_p=0.95,
991
+ frequency_penalty=0.4,
992
+ presence_penalty=0.2,
993
+ api_key=gapgpt_api_key,
994
+ api_base=GAPGPT_BASE_URL,
995
+ )
996
+
997
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
998
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
999
+ embed_model = OpenAIEmbedding(
1000
+ api_key=gapgpt_api_key,
1001
+ api_base=GAPGPT_BASE_URL,
1002
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
1003
+ )
1004
+
1005
+ # اعمال تنظیمات سراسری
1006
+ Settings.llm = llm
1007
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
1008
+
1009
+ Settings.prompt_helper = PromptHelper(
1010
+ context_window=4096,
1011
+ num_output=256,
1012
+ chunk_overlap_ratio=20 / 4096,
1013
+ tokenizer=tokenizer,
1014
+ )
1015
+
1016
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
1017
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
1018
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
1019
+ if 'api_keys' not in locals():
1020
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
1021
+
1022
+ demo = create_gradio_interface(Settings, api_keys)
1023
+ demo.launch(
1024
+ server_name="127.0.0.1",
1025
+ server_port=7860,
1026
+ share=True
1027
+ )
1028
+
1029
+
1030
+ if __name__ == "__main__":
1031
+ signal.signal(signal.SIGINT, signal_handler)
1032
+ main()
Backup code/app_V15.py ADDED
@@ -0,0 +1,1031 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Classification_Model", "final_xlm_r_model_router")
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "api_key_list.txt")
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "memories", "update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ user_profile=None
332
+
333
+
334
+ ):
335
+ chatgpt_cfg = {
336
+ "model": "gpt-4o",
337
+ "temperature": temperature,
338
+ "max_tokens": max_length_tokens,
339
+ "top_p": top_p,
340
+ "frequency_penalty": 0.4,
341
+ "presence_penalty": 0.2,
342
+ "n": 1,
343
+ }
344
+
345
+ if text == "":
346
+ # Return same history if empty input
347
+ return history, history, "Empty context."
348
+
349
+ # Ensure history is initialized
350
+ if history is None:
351
+ history = []
352
+
353
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
354
+ history=history,
355
+ query=text, # Changed name to match prompt_utils
356
+ user_memory=user_memory,
357
+ user_name=user_name,
358
+ user_memory_index=user_memory_index,
359
+ service_context=service_context,
360
+ api_keys=api_keys,
361
+ api_index=api_index,
362
+ meta_prompt=meta_prompt,
363
+ new_user_meta_prompt=new_user_meta_prompt,
364
+ data_args=data_args,
365
+ boot_actual_name=boot_actual_name,
366
+ semantic_memory_text=semantic_memory_text,
367
+ query_category=query_category,
368
+ meta_prompt_semantic=meta_prompt_semantic,
369
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
370
+ )
371
+
372
+ # ==========================================
373
+ # اضافه کردن پروفایل به System Prompt
374
+ # ==========================================
375
+ if user_profile:
376
+ profile_str = (
377
+ f"\n\n[User Profile Information]:\n"
378
+ f"- Age: {user_profile.get('age', 'Unknown')}\n"
379
+ f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
380
+ f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
381
+ f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
382
+ f"Use this context subtly when talking to the user."
383
+ )
384
+ system_prompt += profile_str
385
+ # ==========================================
386
+
387
+ # Handle context window slicing manually if needed,
388
+ # though usually OpenAI manages this, or we slice the list of dicts.
389
+ current_history_for_llm = history
390
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
391
+ current_history_for_llm = history[-(data_args.max_history * 2):]
392
+
393
+ response = chatgpt_chat(
394
+ prompt=text,
395
+ system=system_prompt,
396
+ history=current_history_for_llm,
397
+ gpt_config=chatgpt_cfg,
398
+ api_index=api_index,
399
+ )
400
+
401
+ torch.cuda.empty_cache()
402
+
403
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
404
+ new_history = history + [
405
+ {"role": "user", "content": text},
406
+ {"role": "assistant", "content": response}
407
+ ]
408
+
409
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
410
+ # OR we convert strictly for saving if your legacy code needs it.
411
+ # For now, assuming we pass the object as is or convert for save)
412
+ if user_name:
413
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
414
+ # or pass a converted version. Let's try passing the new format.
415
+ save_local_memory(memory, new_history, user_name, data_args)
416
+
417
+ # Return: (Chatbot View, State History, Textbox Reset)
418
+ return new_history, new_history, "Generating..."
419
+
420
+
421
+
422
+ def create_gradio_interface(service_context, api_keys):
423
+
424
+
425
+ # ابتدا متغیر CSS را تعریف کنید
426
+ custom_css = """
427
+ /* استایل دکمه ارسال (Send) */
428
+ .send-btn {
429
+ border: 3px solid #0066cc !important;
430
+ border-radius: 12px !important;
431
+ background-color: white !important;
432
+ color: black !important;
433
+ font-weight: bold !important;
434
+ font-size: 16px !important;
435
+ transition: all 0.3s ease !important;
436
+ }
437
+ .send-btn:hover {
438
+ background-color: #0066cc !important;
439
+ color: white !important;
440
+ }
441
+
442
+ /* استایل نوار پایین و دکمه‌های آن */
443
+ .bottom-actions-row {
444
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
445
+ border-radius: 8px !important;
446
+ padding: 5px !important;
447
+ margin-top: 10px !important;
448
+ }
449
+
450
+ .action-btn {
451
+ border: none !important;
452
+ background: transparent !important;
453
+ color: black !important;
454
+ font-weight: bold !important;
455
+ box-shadow: none !important;
456
+ transition: all 0.3s ease !important;
457
+ }
458
+
459
+ .action-btn:hover {
460
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
461
+ border-radius: 8px !important;
462
+ }
463
+ /* ========================================== */
464
+ /* لودینگ تمام‌صفحه و غیرفعال‌سازی تعاملات */
465
+ /* ========================================== */
466
+
467
+ /* مخفی کردن نوار پیشرفت پیش‌فرض Gradio */
468
+ .progress-level, .progress-text, .progress-level svg, .progress-level img {
469
+ display: none !important;
470
+ }
471
+
472
+ /* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایل‌ها روی body اعمال می‌شود */
473
+ body:has(.progress-level) {
474
+ pointer-events: none !important; /* غیرفعال کردن تمام کلیک‌ها */
475
+ }
476
+
477
+ /* ایجاد هاله نیمه‌شفاف روی کل صفحه */
478
+ body:has(.progress-level)::after {
479
+ content: "";
480
+ position: fixed;
481
+ top: 0; left: 0;
482
+ width: 100vw; height: 100vh;
483
+ background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمه‌شفاف */
484
+ z-index: 9998;
485
+ pointer-events: all; /* برای گرفتن کلیک‌ها و جلوگیری از عبور آن‌ها */
486
+ cursor: wait;
487
+ }
488
+
489
+ /* ایجاد اسپینر لودینگ در مرکز صفحه */
490
+ body:has(.progress-level)::before {
491
+ content: "";
492
+ position: fixed;
493
+ top: 50%; left: 50%;
494
+ transform: translate(-50%, -50%);
495
+ width: 60px; height: 60px;
496
+ border: 6px solid #e5e7eb;
497
+ border-top-color: #0066cc;
498
+ border-radius: 50%;
499
+ animation: spin 1s linear infinite;
500
+ z-index: 9999;
501
+ }
502
+
503
+ @keyframes spin {
504
+ 0% { transform: translate(-50%, -50%) rotate(0deg); }
505
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
506
+ }
507
+
508
+
509
+ /* انیمیشن چرخش */
510
+ @keyframes spin {
511
+ 0% { transform: rotate(0deg); }
512
+ 100% { transform: rotate(360deg); }
513
+ }
514
+
515
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
516
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
517
+ /*
518
+ .progress-text {
519
+ display: none !important;
520
+ }
521
+ */
522
+ /* انیمیشن سه نقطه در حال تایپ */
523
+ .typing-dots::after {
524
+ content: '';
525
+ animation: typing 1.5s infinite;
526
+ }
527
+ @keyframes typing {
528
+ 0% { content: ''; }
529
+ 25% { content: ' .'; }
530
+ 50% { content: ' . .'; }
531
+ 75% { content: ' . . .'; }
532
+ 100% { content: ''; }
533
+ }
534
+
535
+
536
+ """
537
+
538
+ with gr.Blocks(title="EMMA") as demo:
539
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
540
+ gr.HTML(f"<style>{custom_css}</style>")
541
+
542
+ # بقیه کدهای شما...
543
+
544
+
545
+ state = gr.State({
546
+ "history": [],
547
+ "user_name": None,
548
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
549
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
550
+ "service_context": service_context,
551
+ "api_keys": api_keys,
552
+ "api_index": 0,
553
+ "semantic_memory_text": "",
554
+ "new_conversation": True,
555
+ "initialized": False
556
+ })
557
+
558
+
559
+
560
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
561
+ with gr.Row():
562
+
563
+ # ==========================================
564
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
565
+ # ==========================================
566
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
567
+ with gr.Sidebar(open=True) as login_page:
568
+
569
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
570
+
571
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
572
+ login_status = gr.Textbox(visible=False, label="Status")
573
+
574
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
575
+
576
+ with gr.Column(visible=False) as registration_fields:
577
+ gr.Markdown("### ✨ New User Registration")
578
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
579
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
580
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
581
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
582
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
583
+
584
+
585
+ # ==========================================
586
+ # 2. CHAT PAGE (ستون سمت راست)
587
+ # ==========================================
588
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
589
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
590
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
591
+ #system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
592
+
593
+ with gr.Group():
594
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
595
+
596
+ with gr.Row():
597
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
598
+ # اختصاص کلاس send-btn به دکمه Send
599
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
600
+
601
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
602
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
603
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
604
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
605
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
606
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
607
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
608
+
609
+ # -------------------------------------------------------
610
+ # Internal Functions
611
+ # -------------------------------------------------------
612
+ def handle_login_check(name, state):
613
+ if not name.strip():
614
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
615
+
616
+ if name in memory:
617
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
618
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
619
+
620
+ new_state = state.copy()
621
+ new_state["user_name"] = name
622
+ new_state["memory"] = memory
623
+ new_state["initialized"] = True
624
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
625
+ new_state["semantic_memory_index"] = semantic_memory
626
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
627
+ new_state["episodic_memory_index"] = episodic_memory
628
+ new_state["history"] = []
629
+
630
+
631
+
632
+
633
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
634
+
635
+ return (
636
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
637
+ gr.update(visible=False),
638
+ gr.update(visible=True),
639
+ gr.update(visible=False, value=""),
640
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
641
+ gr.update(value=welcome_msg),
642
+ new_state
643
+ )
644
+ else:
645
+ return (
646
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
647
+ gr.update(visible=True),
648
+ gr.update(visible=False),
649
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
650
+ gr.update(),
651
+ gr.update(),
652
+ state
653
+ )
654
+
655
+ def handle_register(name, age, gender, occupation, residence, state):
656
+ name = str(name).strip()
657
+
658
+ if not name:
659
+ raise gr.Error("Please enter a valid user name.")
660
+
661
+ # Registration is only for new users.
662
+ if name in memory:
663
+ raise gr.Error(
664
+ f"User '{name}' already exists. Please use the login form."
665
+ )
666
+
667
+ # Create the user before trying to build or load their indices.
668
+ memory[name] = {
669
+ "profile": {
670
+ "age": age,
671
+ "gender": gender,
672
+ "occupation": occupation,
673
+ "residence": residence,
674
+ },
675
+ "sessions": [],
676
+ "episodic_memory": [],
677
+ "semantic_memory": {},
678
+ }
679
+
680
+ try:
681
+ (
682
+ _,
683
+ user_memory,
684
+ sessions_memory,
685
+ episodic_memory,
686
+ semantic_memory,
687
+ ) = enter_name_llamaindex(
688
+ name=name,
689
+ memory=memory,
690
+ data_args=data_args,
691
+ update_memory_index=True,
692
+ )
693
+ except Exception:
694
+ # Avoid leaving a partially registered user in memory.
695
+ memory.pop(name, None)
696
+ raise
697
+
698
+ new_state = dict(state or {})
699
+ new_state.update(
700
+ {
701
+ "user_name": name,
702
+ "memory": memory,
703
+ "initialized": True,
704
+ "history": [],
705
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
706
+ "user_memory_index": sessions_memory,
707
+ "episodic_memory_index": episodic_memory,
708
+ "semantic_memory_index": semantic_memory,
709
+ }
710
+ )
711
+
712
+ welcome_msg = f"Welcome {name}! Registration complete."
713
+
714
+ return (
715
+ gr.update(open=False),
716
+ gr.update(visible=False),
717
+ gr.update(visible=True),
718
+ gr.update(visible=False, value=""),
719
+ gr.update(
720
+ value=(
721
+ "<h2 style='text-align: center; color: #333;'>"
722
+ f"🧠 EMMA: Session for {name}</h2>"
723
+ )
724
+ ),
725
+ gr.update(value=welcome_msg),
726
+ new_state,
727
+ )
728
+
729
+ def switch_user(state):
730
+ if state["initialized"] and state["user_name"] in state["memory"]:
731
+ if state["memory"][state["user_name"]]["sessions"]:
732
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
733
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
734
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
735
+ # ==========================================
736
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
737
+ # ==========================================
738
+ try:
739
+ user_mem = state["memory"][state["user_name"]]
740
+ existing_semantic = user_mem.get("semantic_memory", {})
741
+
742
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
743
+
744
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
745
+ except Exception as e:
746
+ print(f"Error updating semantic memory on logout: {e}")
747
+ # ==========================================
748
+
749
+ new_state = state.copy()
750
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
751
+
752
+ return (
753
+ gr.update(open=True), # 1. باز شدن سایدبار
754
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام
755
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
756
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
757
+ gr.update(value=""), # 5. پاک کردن نام کاربری
758
+ new_state, # 6. استیت جدید
759
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
760
+ gr.update(value=""), # 8. پاک کردن age_input
761
+ gr.update(value=""), # 9. پاک کردن gender_input
762
+ gr.update(value=""), # 10. پاک کردن occupation_input
763
+ gr.update(value=""), # 11. پاک کردن residence_input
764
+ gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
765
+ )
766
+
767
+
768
+ def handle_chat(user_message, state):
769
+ if not user_message.strip():
770
+ print("[handle_chat] empty message")
771
+ print("[handle_chat] state =", state)
772
+ # تبدیل return به yield
773
+ yield gr.update(), state.get("history", []), state
774
+ return
775
+
776
+ print("[handle_chat] user_message =", repr(user_message))
777
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
778
+ print("[handle_chat] user_name =", state.get("user_name"))
779
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
780
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
781
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
782
+ print("[handle_chat] api_index =", state.get("api_index", 0))
783
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
784
+ print("[handle_chat] history len =", len(state.get("history", [])))
785
+
786
+ # ==========================================
787
+ # ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
788
+ # ==========================================
789
+ current_history = state.get("history", [])
790
+ temp_history = current_history + [
791
+ {"role": "user", "content": user_message},
792
+ {"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
793
+ ]
794
+
795
+ # باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI می‌فرستیم
796
+ yield gr.update(value=""), temp_history, state
797
+
798
+
799
+ # ادامه پردازش‌های اصلی تابع شما
800
+ user_name = state.get("user_name")
801
+ user_memory_index = state.get("user_memory_index")
802
+ user_memory = state.get("user_memory", {})
803
+ user_memory_index = state.get("user_memory_index")
804
+ semantic_memory_text = state.get("semantic_memory_text", {})
805
+ service_context = state.get("service_context")
806
+ api_index = state.get("api_index", 0)
807
+ semantic_memory_text = state.get("semantic_memory_text", "")
808
+
809
+ # ==========================================
810
+ # استخراج پروفایل کاربر از حافظه
811
+ # ==========================================
812
+ user_profile = {}
813
+ if user_name and state.get("memory") and user_name in state["memory"]:
814
+ user_profile = state["memory"][user_name].get("profile", {})
815
+ # ==========================================
816
+
817
+ query_category = classify_query_local(user_message)
818
+ print("[handle_chat] query_category =", query_category)
819
+
820
+ # ارسال current_history به مدل (بدون انیمیشن موقت)
821
+ new_history, _, status_msg = predict_new(
822
+ text=user_message,
823
+ history=current_history,
824
+ top_p=0.95,
825
+ temperature=1.0,
826
+ max_length_tokens=1024,
827
+ max_context_length_tokens=4096,
828
+ user_name=user_name,
829
+ user_memory=user_memory,
830
+ user_memory_index=user_memory_index,
831
+ service_context=service_context,
832
+ api_index=api_index,
833
+ semantic_memory_text=semantic_memory_text,
834
+ query_category=query_category,
835
+ user_profile=user_profile
836
+ )
837
+
838
+ print("[handle_chat] status_msg =", status_msg)
839
+ print("[handle_chat] new_history len =", len(new_history))
840
+
841
+ state["history"] = new_history
842
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
843
+
844
+ # ==========================================
845
+ # ۳. جایگزینی پیام لودینگ با پاسخ نهایی
846
+ # ==========================================
847
+ yield gr.update(), new_history, state
848
+
849
+ def clear_history(state):
850
+ state["history"] = []
851
+ return [], state
852
+
853
+ def handle_new_session(state):
854
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
855
+ user_name = state.get("user_name")
856
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
857
+ print("Error: User not logged in or memory missing.")
858
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
859
+ return [], state, gr.update() # خروجی سوم اضافه شد
860
+
861
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
862
+ user_data = state["memory"][user_name]
863
+
864
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
865
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
866
+ last_session = user_data["sessions"][-1]
867
+
868
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
869
+ if len(last_session.get("conversation", [])) > 0:
870
+ session_date = last_session.get("date", "")
871
+ session_id = last_session.get("session_id", 0)
872
+
873
+ # پاس دادن هر ۳ آرگومان به تابع
874
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
875
+
876
+ if "episodic_memory" not in user_data:
877
+ user_data["episodic_memory"] = []
878
+ user_data["episodic_memory"].append(ep_summary)
879
+
880
+ # ==========================================
881
+ # به‌روزرسانی حافظه سمانتیک
882
+ # ==========================================
883
+ try:
884
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
885
+ existing_semantic = user_data.get("semantic_memory", {})
886
+
887
+ # فراخوانی تابع با هر دو آرگومان
888
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
889
+
890
+ # ذخیره دیتای جدید
891
+ user_data["semantic_memory"] = updated_semantic
892
+ except Exception as e:
893
+ print(f"Error updating semantic memory: {e}")
894
+ # ==========================================
895
+
896
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
897
+ new_session_id = len(user_data.get("sessions", []))
898
+
899
+ new_session = {
900
+ "session_id": new_session_id,
901
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
902
+ "conversation": []
903
+ }
904
+
905
+ if "sessions" not in user_data:
906
+ user_data["sessions"] = []
907
+
908
+ user_data["sessions"].append(new_session)
909
+
910
+ # پاک کردن تاریخچه چت در state
911
+ state["history"] = []
912
+
913
+ # محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
914
+ session_number = len(user_data["sessions"])
915
+ new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
916
+
917
+ # بازگرداندن خروجی جدید برای active_header
918
+ return [], state, gr.update(value=new_header_text)
919
+
920
+ check_user_btn.click(
921
+ handle_login_check,
922
+ inputs=[username_input, state],
923
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
924
+ # show_progress="hidden"
925
+ )
926
+
927
+ register_btn.click(
928
+ handle_register,
929
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
930
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
931
+ # show_progress="hidden"
932
+ )
933
+
934
+ switch_user_btn.click(
935
+ switch_user,
936
+ inputs=[state],
937
+ # system_msg به انتهای لیست خروجی‌ها اضافه شد
938
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
939
+ # show_progress="hidden"
940
+ )
941
+
942
+
943
+ submit_btn.click(
944
+ handle_chat,
945
+ inputs=[user_input, state],
946
+ outputs=[user_input, chatbot, state],
947
+ # show_progress="hidden"
948
+ )
949
+
950
+ user_input.submit(
951
+ handle_chat,
952
+ inputs=[user_input, state],
953
+ outputs=[user_input, chatbot, state],
954
+ # show_progress="hidden"
955
+ )
956
+
957
+ clear_btn.click(
958
+ clear_history,
959
+ inputs=[state],
960
+ outputs=[chatbot, state],
961
+ # show_progress="hidden"
962
+ )
963
+
964
+ # تغییر از clear_history به handle_new_session
965
+ new_session_btn.click(
966
+ handle_new_session,
967
+ inputs=[state],
968
+ outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
969
+ # show_progress="hidden"
970
+ )
971
+
972
+ return demo
973
+
974
+
975
+ def main():
976
+ """Main function to initialize and launch the interface."""
977
+ global api_keys
978
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
979
+
980
+ if not gapgpt_api_key:
981
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
982
+ else:
983
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
984
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
985
+ # ← این خط اضافه شد
986
+ if gapgpt_api_key not in api_keys:
987
+ api_keys.insert(0, gapgpt_api_key)
988
+
989
+ # تنظیم LLM (مدل زبانی)
990
+ llm = LlamaIndexOpenAI(
991
+ model="gpt-4o",
992
+ temperature=1,
993
+ max_tokens=1024,
994
+ top_p=0.95,
995
+ frequency_penalty=0.4,
996
+ presence_penalty=0.2,
997
+ api_key=gapgpt_api_key,
998
+ api_base=GAPGPT_BASE_URL,
999
+ )
1000
+
1001
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
1002
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
1003
+ embed_model = OpenAIEmbedding(
1004
+ api_key=gapgpt_api_key,
1005
+ api_base=GAPGPT_BASE_URL,
1006
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
1007
+ )
1008
+
1009
+ # اعمال تنظیمات سراسری
1010
+ Settings.llm = llm
1011
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
1012
+
1013
+ Settings.prompt_helper = PromptHelper(
1014
+ context_window=4096,
1015
+ num_output=256,
1016
+ chunk_overlap_ratio=20 / 4096,
1017
+ tokenizer=tokenizer,
1018
+ )
1019
+
1020
+
1021
+ demo = create_gradio_interface(Settings, api_keys)
1022
+ demo.launch(
1023
+ server_name="0.0.0.0",
1024
+ server_port=7860,
1025
+ share=False # در محیط داکر معمولاً share روی False تنظیم می‌شود مگر اینکه تونل نیاز داشته باشید
1026
+ )
1027
+
1028
+
1029
+ if __name__ == "__main__":
1030
+ signal.signal(signal.SIGINT, signal_handler)
1031
+ main()
Backup code/app_V2.py ADDED
@@ -0,0 +1,751 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+
13
+ import gradio as gr
14
+ import nltk
15
+ import torch
16
+ import tiktoken
17
+
18
+ from openai import OpenAI as OpenAIClient
19
+ from llama_index.embeddings.openai import OpenAIEmbedding
20
+
21
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
22
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
23
+ from llama_index.core import Settings
24
+ from llama_index.core.indices.prompt_helper import PromptHelper
25
+
26
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
27
+ sys.path.append(prompt_path)
28
+
29
+ # Assuming these imports exist in your local environment
30
+ from utils.sys_args import data_args, model_args
31
+ from utils.app_modules.utils import *
32
+ from utils.app_modules.presets import *
33
+ from utils.app_modules.overwrites import *
34
+ from utils.prompt_utils import *
35
+ from utils.memory_utils import (
36
+ enter_name_llamaindex,
37
+ summarize_memory_event_personality,
38
+ save_local_memory,
39
+ extract_session_summary,
40
+ extract_semantic_memory,
41
+ )
42
+
43
+ # Ensure NLTK data path
44
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
45
+
46
+ tokenizer = tiktoken.get_encoding("cl100k_base")
47
+
48
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
49
+ openai_client_cache = {}
50
+
51
+ import torch
52
+ import torch.nn.functional as F
53
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
54
+
55
+
56
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
57
+
58
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
59
+
60
+ try:
61
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
62
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model.eval()
64
+ print("Local classifier loaded successfully.")
65
+ except Exception as e:
66
+ print(f"Error loading local classifier: {e}")
67
+
68
+
69
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
70
+ if not api_key:
71
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
72
+ if api_key not in openai_client_cache:
73
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
74
+ return openai_client_cache[api_key]
75
+
76
+
77
+ os_name = platform.system()
78
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
79
+ stop_stream = False
80
+
81
+
82
+ def signal_handler(signal_number, frame):
83
+ global stop_stream
84
+ stop_stream = True
85
+
86
+
87
+ VECTOR_SEARCH_TOP_K = 2
88
+
89
+ # Update this path to your actual file location
90
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
91
+
92
+
93
+ def read_apis(path):
94
+ api_keys_local = []
95
+ if os.path.exists(path):
96
+ with open(path, 'r', encoding='utf8') as f:
97
+ for line in f:
98
+ line = line.strip()
99
+ if line:
100
+ api_keys_local.append(line)
101
+ return api_keys_local
102
+
103
+
104
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
105
+
106
+ # Ensure directory exists
107
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
108
+
109
+ if not os.path.exists(memory_dir):
110
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
111
+
112
+ global memory
113
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
114
+ language = 'en'
115
+ user_keyword = generate_user_keyword()[language]
116
+ ai_keyword = generate_ai_keyword()[language]
117
+ boot_name = boot_name_dict[language]
118
+ boot_actual_name = boot_actual_name_dict[language]
119
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
120
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
121
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
122
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
123
+
124
+ api_keys = read_apis(api_path)
125
+ # Fallback if file is empty or missing for testing purposes
126
+ if not api_keys:
127
+ print(f"Warning: No API keys found in {api_path}.")
128
+
129
+ new_conversation = False
130
+ chatgpt_config = {
131
+ "model": "gpt-4o",
132
+ "temperature": 1,
133
+ "max_tokens": 1024,
134
+ "top_p": 0.95,
135
+ "frequency_penalty": 0.4,
136
+ "presence_penalty": 0.2,
137
+ "n": 1,
138
+ }
139
+
140
+ deactivated_keys = []
141
+ logging.basicConfig(
142
+ level=logging.DEBUG,
143
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
144
+ )
145
+
146
+
147
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
148
+ """
149
+ Handles the chat request to OpenAI.
150
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
151
+ """
152
+ retry_times, count = 5, 0
153
+ response = None
154
+
155
+ while response is None and count < retry_times:
156
+ try:
157
+ request = copy.deepcopy(gpt_config)
158
+
159
+ # Initial system and greeting messages
160
+ if data_args.language == 'en':
161
+ message = [
162
+ {"role": "system", "content": system.strip()},
163
+ {"role": "user", "content": "Hi!"},
164
+ {"role": "assistant",
165
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
166
+ ]
167
+ else:
168
+ message = [
169
+ {"role": "system", "content": system.strip()},
170
+ {"role": "user", "content": "Hi"},
171
+ {"role": "assistant",
172
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
173
+ ]
174
+
175
+ # --- FIX: Handle History as List of Dicts ---
176
+ if history:
177
+ # Verify if history is old format (list of lists) or new (list of dicts)
178
+ if isinstance(history[0], list):
179
+ # Convert old format temporarily if encountered
180
+ for q, a in history:
181
+ message.append({"role": "user", "content": str(q)})
182
+ message.append({"role": "assistant", "content": str(a)})
183
+ elif isinstance(history[0], dict):
184
+ # New format
185
+ for msg in history:
186
+ if msg.get('role') in ['user', 'assistant']:
187
+ message.append(msg)
188
+
189
+ # Add the current prompt
190
+ message.append({"role": "user", "content": f"{prompt}"})
191
+
192
+ if not api_keys:
193
+ return "Error: No API Keys available."
194
+
195
+ client = get_gapgpt_client(api_keys[api_index])
196
+
197
+ # New OpenAI 1.x Syntax
198
+ response = client.chat.completions.create(messages=message, **request)
199
+
200
+ except Exception as e:
201
+ print(f"Chat Error: {e}")
202
+ if 'This key is associated with a deactivated account' in str(e):
203
+ deactivated_keys.append(api_keys[api_index])
204
+
205
+ if api_keys:
206
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
207
+ loop_check = 0
208
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
209
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
210
+ loop_check += 1
211
+ count += 1
212
+
213
+ if response:
214
+ response = response.choices[0].message.content
215
+ else:
216
+ response = ''
217
+ return response
218
+
219
+
220
+ def classify_query_local(text):
221
+
222
+
223
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
224
+ id2label_map = {
225
+ 0: "episodic_memory",
226
+ 1: "semantic_memory",
227
+ 2: "semantic-episodic",
228
+ 3: "unknown"
229
+ }
230
+
231
+ try:
232
+
233
+ inputs = _tokenizer(
234
+ text,
235
+ return_tensors="pt",
236
+ truncation=True,
237
+ padding=True,
238
+ max_length=512
239
+ )
240
+
241
+
242
+
243
+ with torch.no_grad():
244
+ outputs = _classifier_model(**inputs)
245
+
246
+
247
+ logits = outputs.logits
248
+ probabilities = F.softmax(logits, dim=-1)
249
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
250
+
251
+
252
+ category = id2label_map.get(predicted_class_id, "unknown")
253
+
254
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
255
+ return category
256
+
257
+ except Exception as e:
258
+ print(f"Error in local classification: {e}")
259
+ return "unknown"
260
+
261
+
262
+
263
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
264
+ response = None
265
+ count = 0
266
+ local_deactivated = []
267
+ print("text********:", text)
268
+
269
+ system_prompt = """
270
+ You are an AI that classifies user queries into one of the following memory types:
271
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
272
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
273
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
274
+
275
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
276
+ """.strip()
277
+
278
+ if not api_keys:
279
+ return "unknown"
280
+
281
+ while response is None and count < retry_times:
282
+ try:
283
+ client = get_gapgpt_client(api_keys[api_index])
284
+
285
+ # New OpenAI 1.x Syntax
286
+ response = client.chat.completions.create(
287
+ messages=[
288
+ {"role": "system", "content": system_prompt},
289
+ {"role": "user", "content": text.strip()},
290
+ ],
291
+ **copy.deepcopy(gpt_config),
292
+ )
293
+ except Exception as e:
294
+ print(f"Classify Error: {e}")
295
+ if "This key is associated with a deactivated account" in str(e):
296
+ local_deactivated.append(api_keys[api_index])
297
+
298
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
299
+ while api_keys[api_index] in local_deactivated:
300
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
301
+ count += 1
302
+
303
+ if response:
304
+ category = response.choices[0].message.content.strip().lower()
305
+ # Basic cleanup
306
+ if "semantic_memory" in category: category = "semantic_memory"
307
+ elif "semantic-episodic" in category: category = "semantic-episodic"
308
+ elif "episodic_memory" in category: category = "episodic_memory"
309
+ else: category = "unknown"
310
+ else:
311
+ category = "unknown"
312
+
313
+ return category
314
+
315
+
316
+ def predict_new(
317
+ text,
318
+ history,
319
+ top_p,
320
+ temperature,
321
+ max_length_tokens,
322
+ max_context_length_tokens,
323
+ user_name,
324
+ user_memory,
325
+ user_memory_index,
326
+ service_context,
327
+ api_index,
328
+ semantic_memory_text,
329
+ query_category,
330
+ ):
331
+ chatgpt_cfg = {
332
+ "model": "gpt-4o",
333
+ "temperature": temperature,
334
+ "max_tokens": max_length_tokens,
335
+ "top_p": top_p,
336
+ "frequency_penalty": 0.4,
337
+ "presence_penalty": 0.2,
338
+ "n": 1,
339
+ }
340
+
341
+ if text == "":
342
+ # Return same history if empty input
343
+ return history, history, "Empty context."
344
+
345
+ # Ensure history is initialized
346
+ if history is None:
347
+ history = []
348
+
349
+ system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
350
+ history=history,
351
+ query=text, # Changed name to match prompt_utils
352
+ user_memory=user_memory,
353
+ user_name=user_name,
354
+ user_memory_index=user_memory_index,
355
+ service_context=service_context,
356
+ api_keys=api_keys,
357
+ api_index=api_index,
358
+ meta_prompt=meta_prompt,
359
+ new_user_meta_prompt=new_user_meta_prompt,
360
+ data_args=data_args,
361
+ boot_actual_name=boot_actual_name,
362
+ semantic_memory_text=semantic_memory_text,
363
+ query_category=query_category,
364
+ meta_prompt_semantic=meta_prompt_semantic,
365
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
366
+ )
367
+
368
+ # Handle context window slicing manually if needed,
369
+ # though usually OpenAI manages this, or we slice the list of dicts.
370
+ current_history_for_llm = history
371
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
372
+ current_history_for_llm = history[-(data_args.max_history * 2):]
373
+
374
+ response = chatgpt_chat(
375
+ prompt=text,
376
+ system=system_prompt,
377
+ history=current_history_for_llm,
378
+ gpt_config=chatgpt_cfg,
379
+ api_index=api_index,
380
+ )
381
+
382
+ torch.cuda.empty_cache()
383
+
384
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
385
+ new_history = history + [
386
+ {"role": "user", "content": text},
387
+ {"role": "assistant", "content": response}
388
+ ]
389
+
390
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
391
+ # OR we convert strictly for saving if your legacy code needs it.
392
+ # For now, assuming we pass the object as is or convert for save)
393
+ if user_name:
394
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
395
+ # or pass a converted version. Let's try passing the new format.
396
+ save_local_memory(memory, new_history, user_name, data_args)
397
+
398
+ # Return: (Chatbot View, State History, Textbox Reset)
399
+ return new_history, new_history, "Generating..."
400
+
401
+
402
+ import gradio as gr
403
+ import time
404
+
405
+ import gradio as gr
406
+
407
+ def create_gradio_interface(service_context, api_keys):
408
+ with gr.Blocks(title="EMMA") as demo:
409
+
410
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
411
+ gr.HTML("""
412
+ <style>
413
+ .center-content {
414
+ display: flex;
415
+ flex-direction: column;
416
+ align-items: center;
417
+ justify-content: center;
418
+ }
419
+ /* -- استایل‌های فرم ورود -- */
420
+ .login-box {
421
+ max-width: 400px !important;
422
+ margin: 0 auto !important;
423
+ width: 100% !important;
424
+ }
425
+ .login-btn, .login-btn:hover {
426
+ background-color: #3498db !important;
427
+ background-image: none !important;
428
+ color: white !important;
429
+ border: none !important;
430
+ }
431
+ /* -- استایل‌های محیط چت -- */
432
+ .chat-box {
433
+ max-width: 800px !important;
434
+ margin: 0 auto !important;
435
+ width: 100% !important;
436
+ }
437
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
438
+ .mobile-button, .mobile-button:hover {
439
+ background-color: #3498db !important;
440
+ background-image: none !important;
441
+ color: white !important;
442
+ border: none !important;
443
+ }
444
+ .gr-textbox textarea {
445
+ font-size: 16px;
446
+ }
447
+ .gr-chatbot {
448
+ font-size: 15px;
449
+ }
450
+
451
+ /* --- انیمیشن کشویی لاگین --- */
452
+ .slide-up {
453
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
454
+ }
455
+
456
+ @keyframes slideUpAnimation {
457
+ 0% {
458
+ transform: translateY(0);
459
+ opacity: 1;
460
+ max-height: 1000px;
461
+ }
462
+ 100% {
463
+ transform: translateY(-100%);
464
+ opacity: 0;
465
+ max-height: 0px;
466
+ overflow: hidden;
467
+ margin: 0 !important;
468
+ padding: 0 !important;
469
+ border: none !important;
470
+ }
471
+ }
472
+ </style>
473
+ """)
474
+
475
+ state = gr.State({
476
+ "history": [],
477
+ "user_name": None,
478
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
479
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
480
+ "service_context": service_context,
481
+ "api_keys": api_keys,
482
+ "api_index": 0,
483
+ "semantic_memory_text": "",
484
+ "new_conversation": True,
485
+ "initialized": False
486
+ })
487
+
488
+ # ==========================================
489
+ # 1. LOGIN PAGE
490
+ # ==========================================
491
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
492
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
493
+
494
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
495
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
496
+ login_status = gr.Textbox(visible=False, label="Status")
497
+
498
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
499
+
500
+ with gr.Column(visible=False) as registration_fields:
501
+ gr.Markdown("### ✨ New User Registration")
502
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
503
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
504
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
505
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
506
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
507
+
508
+ # ==========================================
509
+ # 2. CHAT PAGE
510
+ # ==========================================
511
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
512
+ with gr.Column(elem_classes=["chat-box"]):
513
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
514
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
515
+
516
+ with gr.Group():
517
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
518
+
519
+ with gr.Row():
520
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
521
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
522
+
523
+ with gr.Row(equal_height=True):
524
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
525
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
526
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
527
+
528
+ # -------------------------------------------------------
529
+ # Internal Functions
530
+ # -------------------------------------------------------
531
+ def handle_login_check(name, state):
532
+ if not name.strip():
533
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
534
+
535
+ if name in memory:
536
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
537
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
538
+
539
+ new_state = state.copy()
540
+ new_state["user_name"] = name
541
+ new_state["memory"] = memory
542
+ new_state["initialized"] = True
543
+ new_state["semantic_memory_text"] = semantic_memory
544
+ new_state["history"] = []
545
+
546
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
547
+
548
+ return (
549
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
550
+ gr.update(visible=False),
551
+ gr.update(visible=True),
552
+ gr.update(visible=False, value=""),
553
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
554
+ gr.update(value=welcome_msg),
555
+ new_state
556
+ )
557
+ else:
558
+ return (
559
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
560
+ gr.update(visible=True),
561
+ gr.update(visible=False),
562
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
563
+ gr.update(),
564
+ gr.update(),
565
+ state
566
+ )
567
+
568
+ def handle_register(name, age, gender, occupation, residence, state):
569
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
570
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
571
+
572
+ new_state = state.copy()
573
+ new_state["user_name"] = name
574
+ new_state["memory"] = memory
575
+ new_state["initialized"] = True
576
+ new_state["semantic_memory_text"] = semantic_memory
577
+ new_state["history"] = []
578
+
579
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
580
+
581
+ return (
582
+ gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
583
+ gr.update(visible=False),
584
+ gr.update(visible=True),
585
+ gr.update(visible=False, value=""),
586
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
587
+ gr.update(value=welcome_msg),
588
+ new_state
589
+ )
590
+
591
+ def switch_user(state):
592
+ if state["initialized"] and state["user_name"] in state["memory"]:
593
+ if state["memory"][state["user_name"]]["sessions"]:
594
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
595
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
596
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
597
+
598
+ new_state = state.copy()
599
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
600
+
601
+ return (
602
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
603
+ gr.update(visible=False),
604
+ gr.update(visible=False),
605
+ gr.update(value="Logged out successfully.", visible=True),
606
+ gr.update(value=""),
607
+ new_state,
608
+ gr.update(value=[])
609
+ )
610
+
611
+ def handle_chat(user_message, state):
612
+ if not user_message.strip():
613
+ return gr.update(), state.get("history", []), state
614
+
615
+ user_name = state.get("user_name")
616
+ user_memory = state.get("memory")
617
+ service_context = state.get("service_context")
618
+ api_index = state.get("api_index", 0)
619
+ semantic_memory_text = state.get("semantic_memory_text", "")
620
+
621
+ query_category = classify_query_local(user_message)
622
+
623
+ new_history, _, status_msg = predict_new(
624
+ text=user_message,
625
+ history=state.get("history", []),
626
+ top_p=0.95,
627
+ temperature=1.0,
628
+ max_length_tokens=1024,
629
+ max_context_length_tokens=4096,
630
+ user_name=user_name,
631
+ user_memory=user_memory,
632
+ user_memory_index=None,
633
+ service_context=service_context,
634
+ api_index=api_index,
635
+ semantic_memory_text=semantic_memory_text,
636
+ query_category=query_category
637
+ )
638
+
639
+ state["history"] = new_history
640
+ return "", new_history, state
641
+
642
+ def clear_history(state):
643
+ state["history"] = []
644
+ return [], state
645
+
646
+ # -------------------------------------------------------
647
+ # Event Bindings
648
+ # -------------------------------------------------------
649
+ check_user_btn.click(
650
+ handle_login_check,
651
+ inputs=[username_input, state],
652
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
653
+ )
654
+
655
+ register_btn.click(
656
+ handle_register,
657
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
658
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
659
+ )
660
+
661
+ switch_user_btn.click(
662
+ switch_user,
663
+ inputs=[state],
664
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
665
+ )
666
+
667
+ submit_btn.click(
668
+ handle_chat,
669
+ inputs=[user_input, state],
670
+ outputs=[user_input, chatbot, state]
671
+ )
672
+
673
+ user_input.submit(
674
+ handle_chat,
675
+ inputs=[user_input, state],
676
+ outputs=[user_input, chatbot, state]
677
+ )
678
+
679
+ clear_btn.click(
680
+ clear_history,
681
+ inputs=[state],
682
+ outputs=[chatbot, state]
683
+ )
684
+
685
+ new_session_btn.click(
686
+ clear_history,
687
+ inputs=[state],
688
+ outputs=[chatbot, state]
689
+ )
690
+
691
+ return demo
692
+
693
+
694
+ def main():
695
+ """Main function to initialize and launch the interface."""
696
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
697
+
698
+ if not gapgpt_api_key:
699
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
700
+ else:
701
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
702
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
703
+
704
+ # تنظیم LLM (مدل زبانی)
705
+ llm = LlamaIndexOpenAI(
706
+ model="gpt-4o",
707
+ temperature=1,
708
+ max_tokens=1024,
709
+ top_p=0.95,
710
+ frequency_penalty=0.4,
711
+ presence_penalty=0.2,
712
+ api_key=gapgpt_api_key,
713
+ api_base=GAPGPT_BASE_URL,
714
+ )
715
+
716
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
717
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
718
+ embed_model = OpenAIEmbedding(
719
+ api_key=gapgpt_api_key,
720
+ api_base=GAPGPT_BASE_URL,
721
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
722
+ )
723
+
724
+ # اعمال تنظیمات سراسری
725
+ Settings.llm = llm
726
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
727
+
728
+ Settings.prompt_helper = PromptHelper(
729
+ context_window=4096,
730
+ num_output=256,
731
+ chunk_overlap_ratio=20 / 4096,
732
+ tokenizer=tokenizer,
733
+ )
734
+
735
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
736
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
737
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
738
+ if 'api_keys' not in locals():
739
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
740
+
741
+ demo = create_gradio_interface(Settings, api_keys)
742
+ demo.launch(
743
+ server_name="127.0.0.1",
744
+ server_port=7860,
745
+ share=True
746
+ )
747
+
748
+
749
+ if __name__ == "__main__":
750
+ signal.signal(signal.SIGINT, signal_handler)
751
+ main()
Backup code/app_V3.py ADDED
@@ -0,0 +1,751 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+
13
+ import gradio as gr
14
+ import nltk
15
+ import torch
16
+ import tiktoken
17
+
18
+ from openai import OpenAI as OpenAIClient
19
+ from llama_index.embeddings.openai import OpenAIEmbedding
20
+
21
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
22
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
23
+ from llama_index.core import Settings
24
+ from llama_index.core.indices.prompt_helper import PromptHelper
25
+
26
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
27
+ sys.path.append(prompt_path)
28
+
29
+ # Assuming these imports exist in your local environment
30
+ from utils.sys_args import data_args, model_args
31
+ from utils.app_modules.utils import *
32
+ from utils.app_modules.presets import *
33
+ from utils.app_modules.overwrites import *
34
+ from utils.prompt_utils import *
35
+ from utils.memory_utils import (
36
+ enter_name_llamaindex,
37
+ summarize_memory_event_personality,
38
+ save_local_memory,
39
+ extract_session_summary,
40
+ extract_semantic_memory,
41
+ )
42
+
43
+ # Ensure NLTK data path
44
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
45
+
46
+ tokenizer = tiktoken.get_encoding("cl100k_base")
47
+
48
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
49
+ openai_client_cache = {}
50
+
51
+ import torch
52
+ import torch.nn.functional as F
53
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
54
+
55
+
56
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
57
+
58
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
59
+
60
+ try:
61
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
62
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model.eval()
64
+ print("Local classifier loaded successfully.")
65
+ except Exception as e:
66
+ print(f"Error loading local classifier: {e}")
67
+
68
+
69
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
70
+ if not api_key:
71
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
72
+ if api_key not in openai_client_cache:
73
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
74
+ return openai_client_cache[api_key]
75
+
76
+
77
+ os_name = platform.system()
78
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
79
+ stop_stream = False
80
+
81
+
82
+ def signal_handler(signal_number, frame):
83
+ global stop_stream
84
+ stop_stream = True
85
+
86
+
87
+ VECTOR_SEARCH_TOP_K = 2
88
+
89
+ # Update this path to your actual file location
90
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
91
+
92
+
93
+ def read_apis(path):
94
+ api_keys_local = []
95
+ if os.path.exists(path):
96
+ with open(path, 'r', encoding='utf8') as f:
97
+ for line in f:
98
+ line = line.strip()
99
+ if line:
100
+ api_keys_local.append(line)
101
+ return api_keys_local
102
+
103
+
104
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
105
+
106
+ # Ensure directory exists
107
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
108
+
109
+ if not os.path.exists(memory_dir):
110
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
111
+
112
+ global memory
113
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
114
+ language = 'en'
115
+ user_keyword = generate_user_keyword()[language]
116
+ ai_keyword = generate_ai_keyword()[language]
117
+ boot_name = boot_name_dict[language]
118
+ boot_actual_name = boot_actual_name_dict[language]
119
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
120
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
121
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
122
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
123
+
124
+ api_keys = read_apis(api_path)
125
+ # Fallback if file is empty or missing for testing purposes
126
+ if not api_keys:
127
+ print(f"Warning: No API keys found in {api_path}.")
128
+
129
+ new_conversation = False
130
+ chatgpt_config = {
131
+ "model": "gpt-4o",
132
+ "temperature": 1,
133
+ "max_tokens": 1024,
134
+ "top_p": 0.95,
135
+ "frequency_penalty": 0.4,
136
+ "presence_penalty": 0.2,
137
+ "n": 1,
138
+ }
139
+
140
+ deactivated_keys = []
141
+ logging.basicConfig(
142
+ level=logging.DEBUG,
143
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
144
+ )
145
+
146
+
147
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
148
+ """
149
+ Handles the chat request to OpenAI.
150
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
151
+ """
152
+ retry_times, count = 5, 0
153
+ response = None
154
+
155
+ while response is None and count < retry_times:
156
+ try:
157
+ request = copy.deepcopy(gpt_config)
158
+
159
+ # Initial system and greeting messages
160
+ if data_args.language == 'en':
161
+ message = [
162
+ {"role": "system", "content": system.strip()},
163
+ {"role": "user", "content": "Hi!"},
164
+ {"role": "assistant",
165
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
166
+ ]
167
+ else:
168
+ message = [
169
+ {"role": "system", "content": system.strip()},
170
+ {"role": "user", "content": "Hi"},
171
+ {"role": "assistant",
172
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
173
+ ]
174
+
175
+ # --- FIX: Handle History as List of Dicts ---
176
+ if history:
177
+ # Verify if history is old format (list of lists) or new (list of dicts)
178
+ if isinstance(history[0], list):
179
+ # Convert old format temporarily if encountered
180
+ for q, a in history:
181
+ message.append({"role": "user", "content": str(q)})
182
+ message.append({"role": "assistant", "content": str(a)})
183
+ elif isinstance(history[0], dict):
184
+ # New format
185
+ for msg in history:
186
+ if msg.get('role') in ['user', 'assistant']:
187
+ message.append(msg)
188
+
189
+ # Add the current prompt
190
+ message.append({"role": "user", "content": f"{prompt}"})
191
+
192
+ if not api_keys:
193
+ return "Error: No API Keys available."
194
+
195
+ client = get_gapgpt_client(api_keys[api_index])
196
+
197
+ # New OpenAI 1.x Syntax
198
+ response = client.chat.completions.create(messages=message, **request)
199
+
200
+ except Exception as e:
201
+ print(f"Chat Error: {e}")
202
+ if 'This key is associated with a deactivated account' in str(e):
203
+ deactivated_keys.append(api_keys[api_index])
204
+
205
+ if api_keys:
206
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
207
+ loop_check = 0
208
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
209
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
210
+ loop_check += 1
211
+ count += 1
212
+
213
+ if response:
214
+ response = response.choices[0].message.content
215
+ else:
216
+ response = ''
217
+ return response
218
+
219
+
220
+ def classify_query_local(text):
221
+
222
+
223
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
224
+ id2label_map = {
225
+ 0: "episodic_memory",
226
+ 1: "semantic_memory",
227
+ 2: "semantic-episodic",
228
+ 3: "unknown"
229
+ }
230
+
231
+ try:
232
+
233
+ inputs = _tokenizer(
234
+ text,
235
+ return_tensors="pt",
236
+ truncation=True,
237
+ padding=True,
238
+ max_length=512
239
+ )
240
+
241
+
242
+
243
+ with torch.no_grad():
244
+ outputs = _classifier_model(**inputs)
245
+
246
+
247
+ logits = outputs.logits
248
+ probabilities = F.softmax(logits, dim=-1)
249
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
250
+
251
+
252
+ category = id2label_map.get(predicted_class_id, "unknown")
253
+
254
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
255
+ return category
256
+
257
+ except Exception as e:
258
+ print(f"Error in local classification: {e}")
259
+ return "unknown"
260
+
261
+
262
+
263
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
264
+ response = None
265
+ count = 0
266
+ local_deactivated = []
267
+ print("text********:", text)
268
+
269
+ system_prompt = """
270
+ You are an AI that classifies user queries into one of the following memory types:
271
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
272
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
273
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
274
+
275
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
276
+ """.strip()
277
+
278
+ if not api_keys:
279
+ return "unknown"
280
+
281
+ while response is None and count < retry_times:
282
+ try:
283
+ client = get_gapgpt_client(api_keys[api_index])
284
+
285
+ # New OpenAI 1.x Syntax
286
+ response = client.chat.completions.create(
287
+ messages=[
288
+ {"role": "system", "content": system_prompt},
289
+ {"role": "user", "content": text.strip()},
290
+ ],
291
+ **copy.deepcopy(gpt_config),
292
+ )
293
+ except Exception as e:
294
+ print(f"Classify Error: {e}")
295
+ if "This key is associated with a deactivated account" in str(e):
296
+ local_deactivated.append(api_keys[api_index])
297
+
298
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
299
+ while api_keys[api_index] in local_deactivated:
300
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
301
+ count += 1
302
+
303
+ if response:
304
+ category = response.choices[0].message.content.strip().lower()
305
+ # Basic cleanup
306
+ if "semantic_memory" in category: category = "semantic_memory"
307
+ elif "semantic-episodic" in category: category = "semantic-episodic"
308
+ elif "episodic_memory" in category: category = "episodic_memory"
309
+ else: category = "unknown"
310
+ else:
311
+ category = "unknown"
312
+
313
+ return category
314
+
315
+
316
+ def predict_new(
317
+ text,
318
+ history,
319
+ top_p,
320
+ temperature,
321
+ max_length_tokens,
322
+ max_context_length_tokens,
323
+ user_name,
324
+ user_memory,
325
+ user_memory_index,
326
+ service_context,
327
+ api_index,
328
+ semantic_memory_text,
329
+ query_category,
330
+ ):
331
+ chatgpt_cfg = {
332
+ "model": "gpt-4o",
333
+ "temperature": temperature,
334
+ "max_tokens": max_length_tokens,
335
+ "top_p": top_p,
336
+ "frequency_penalty": 0.4,
337
+ "presence_penalty": 0.2,
338
+ "n": 1,
339
+ }
340
+
341
+ if text == "":
342
+ # Return same history if empty input
343
+ return history, history, "Empty context."
344
+
345
+ # Ensure history is initialized
346
+ if history is None:
347
+ history = []
348
+
349
+ system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
350
+ history=history,
351
+ query=text, # Changed name to match prompt_utils
352
+ user_memory=user_memory,
353
+ user_name=user_name,
354
+ user_memory_index=user_memory_index,
355
+ service_context=service_context,
356
+ api_keys=api_keys,
357
+ api_index=api_index,
358
+ meta_prompt=meta_prompt,
359
+ new_user_meta_prompt=new_user_meta_prompt,
360
+ data_args=data_args,
361
+ boot_actual_name=boot_actual_name,
362
+ semantic_memory_text=semantic_memory_text,
363
+ query_category=query_category,
364
+ meta_prompt_semantic=meta_prompt_semantic,
365
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
366
+ )
367
+
368
+ # Handle context window slicing manually if needed,
369
+ # though usually OpenAI manages this, or we slice the list of dicts.
370
+ current_history_for_llm = history
371
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
372
+ current_history_for_llm = history[-(data_args.max_history * 2):]
373
+
374
+ response = chatgpt_chat(
375
+ prompt=text,
376
+ system=system_prompt,
377
+ history=current_history_for_llm,
378
+ gpt_config=chatgpt_cfg,
379
+ api_index=api_index,
380
+ )
381
+
382
+ torch.cuda.empty_cache()
383
+
384
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
385
+ new_history = history + [
386
+ {"role": "user", "content": text},
387
+ {"role": "assistant", "content": response}
388
+ ]
389
+
390
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
391
+ # OR we convert strictly for saving if your legacy code needs it.
392
+ # For now, assuming we pass the object as is or convert for save)
393
+ if user_name:
394
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
395
+ # or pass a converted version. Let's try passing the new format.
396
+ save_local_memory(memory, new_history, user_name, data_args)
397
+
398
+ # Return: (Chatbot View, State History, Textbox Reset)
399
+ return new_history, new_history, "Generating..."
400
+
401
+
402
+ import gradio as gr
403
+ import time
404
+
405
+ import gradio as gr
406
+
407
+ def create_gradio_interface(service_context, api_keys):
408
+ with gr.Blocks(title="EMMA") as demo:
409
+
410
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
411
+ gr.HTML("""
412
+ <style>
413
+ .center-content {
414
+ display: flex;
415
+ flex-direction: column;
416
+ align-items: center;
417
+ justify-content: center;
418
+ }
419
+ /* -- استایل‌های فرم ورود -- */
420
+ .login-box {
421
+ max-width: 400px !important;
422
+ margin: 0 auto !important;
423
+ width: 100% !important;
424
+ }
425
+ .login-btn, .login-btn:hover {
426
+ background-color: #3498db !important;
427
+ background-image: none !important;
428
+ color: white !important;
429
+ border: none !important;
430
+ }
431
+ /* -- استایل‌های محیط چت -- */
432
+ .chat-box {
433
+ max-width: 800px !important;
434
+ margin: 0 auto !important;
435
+ width: 100% !important;
436
+ }
437
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
438
+ .mobile-button, .mobile-button:hover {
439
+ background-color: #3498db !important;
440
+ background-image: none !important;
441
+ color: white !important;
442
+ border: none !important;
443
+ }
444
+ .gr-textbox textarea {
445
+ font-size: 16px;
446
+ }
447
+ .gr-chatbot {
448
+ font-size: 15px;
449
+ }
450
+
451
+ /* --- انیمیشن کشویی لاگین --- */
452
+ .slide-up {
453
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
454
+ }
455
+
456
+ @keyframes slideUpAnimation {
457
+ 0% {
458
+ transform: translateY(0);
459
+ opacity: 1;
460
+ max-height: 1000px;
461
+ }
462
+ 100% {
463
+ transform: translateY(-100%);
464
+ opacity: 0;
465
+ max-height: 0px;
466
+ overflow: hidden;
467
+ margin: 0 !important;
468
+ padding: 0 !important;
469
+ border: none !important;
470
+ }
471
+ }
472
+ </style>
473
+ """)
474
+
475
+ state = gr.State({
476
+ "history": [],
477
+ "user_name": None,
478
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
479
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
480
+ "service_context": service_context,
481
+ "api_keys": api_keys,
482
+ "api_index": 0,
483
+ "semantic_memory_text": "",
484
+ "new_conversation": True,
485
+ "initialized": False
486
+ })
487
+
488
+ # ==========================================
489
+ # 1. LOGIN PAGE
490
+ # ==========================================
491
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
492
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
493
+
494
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
495
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
496
+ login_status = gr.Textbox(visible=False, label="Status")
497
+
498
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
499
+
500
+ with gr.Column(visible=False) as registration_fields:
501
+ gr.Markdown("### ✨ New User Registration")
502
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
503
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
504
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
505
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
506
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
507
+
508
+ # ==========================================
509
+ # 2. CHAT PAGE
510
+ # ==========================================
511
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
512
+ with gr.Column(elem_classes=["chat-box"]):
513
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
514
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
515
+
516
+ with gr.Group():
517
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
518
+
519
+ with gr.Row():
520
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
521
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
522
+
523
+ with gr.Row(equal_height=True):
524
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
525
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
526
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
527
+
528
+ # -------------------------------------------------------
529
+ # Internal Functions
530
+ # -------------------------------------------------------
531
+ def handle_login_check(name, state):
532
+ if not name.strip():
533
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
534
+
535
+ if name in memory:
536
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
537
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
538
+
539
+ new_state = state.copy()
540
+ new_state["user_name"] = name
541
+ new_state["memory"] = memory
542
+ new_state["initialized"] = True
543
+ new_state["semantic_memory_text"] = semantic_memory
544
+ new_state["history"] = []
545
+
546
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
547
+
548
+ return (
549
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
550
+ gr.update(visible=False),
551
+ gr.update(visible=True),
552
+ gr.update(visible=False, value=""),
553
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
554
+ gr.update(value=welcome_msg),
555
+ new_state
556
+ )
557
+ else:
558
+ return (
559
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
560
+ gr.update(visible=True),
561
+ gr.update(visible=False),
562
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
563
+ gr.update(),
564
+ gr.update(),
565
+ state
566
+ )
567
+
568
+ def handle_register(name, age, gender, occupation, residence, state):
569
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
570
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
571
+
572
+ new_state = state.copy()
573
+ new_state["user_name"] = name
574
+ new_state["memory"] = memory
575
+ new_state["initialized"] = True
576
+ new_state["semantic_memory_text"] = semantic_memory
577
+ new_state["history"] = []
578
+
579
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
580
+
581
+ return (
582
+ gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
583
+ gr.update(visible=False),
584
+ gr.update(visible=True),
585
+ gr.update(visible=False, value=""),
586
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
587
+ gr.update(value=welcome_msg),
588
+ new_state
589
+ )
590
+
591
+ def switch_user(state):
592
+ if state["initialized"] and state["user_name"] in state["memory"]:
593
+ if state["memory"][state["user_name"]]["sessions"]:
594
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
595
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
596
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
597
+
598
+ new_state = state.copy()
599
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
600
+
601
+ return (
602
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
603
+ gr.update(visible=False),
604
+ gr.update(visible=False),
605
+ gr.update(value="Logged out successfully.", visible=True),
606
+ gr.update(value=""),
607
+ new_state,
608
+ gr.update(value=[])
609
+ )
610
+
611
+ def handle_chat(user_message, state):
612
+ if not user_message.strip():
613
+ return gr.update(), state.get("history", []), state
614
+
615
+ user_name = state.get("user_name")
616
+ user_memory = state.get("memory")
617
+ service_context = state.get("service_context")
618
+ api_index = state.get("api_index", 0)
619
+ semantic_memory_text = state.get("semantic_memory_text", "")
620
+
621
+ query_category = classify_query_local(user_message)
622
+
623
+ new_history, _, status_msg = predict_new(
624
+ text=user_message,
625
+ history=state.get("history", []),
626
+ top_p=0.95,
627
+ temperature=1.0,
628
+ max_length_tokens=1024,
629
+ max_context_length_tokens=4096,
630
+ user_name=user_name,
631
+ user_memory=user_memory,
632
+ user_memory_index=None,
633
+ service_context=service_context,
634
+ api_index=api_index,
635
+ semantic_memory_text=semantic_memory_text,
636
+ query_category=query_category
637
+ )
638
+
639
+ state["history"] = new_history
640
+ return "", new_history, state
641
+
642
+ def clear_history(state):
643
+ state["history"] = []
644
+ return [], state
645
+
646
+ # -------------------------------------------------------
647
+ # Event Bindings
648
+ # -------------------------------------------------------
649
+ check_user_btn.click(
650
+ handle_login_check,
651
+ inputs=[username_input, state],
652
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
653
+ )
654
+
655
+ register_btn.click(
656
+ handle_register,
657
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
658
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
659
+ )
660
+
661
+ switch_user_btn.click(
662
+ switch_user,
663
+ inputs=[state],
664
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
665
+ )
666
+
667
+ submit_btn.click(
668
+ handle_chat,
669
+ inputs=[user_input, state],
670
+ outputs=[user_input, chatbot, state]
671
+ )
672
+
673
+ user_input.submit(
674
+ handle_chat,
675
+ inputs=[user_input, state],
676
+ outputs=[user_input, chatbot, state]
677
+ )
678
+
679
+ clear_btn.click(
680
+ clear_history,
681
+ inputs=[state],
682
+ outputs=[chatbot, state]
683
+ )
684
+
685
+ new_session_btn.click(
686
+ clear_history,
687
+ inputs=[state],
688
+ outputs=[chatbot, state]
689
+ )
690
+
691
+ return demo
692
+
693
+
694
+ def main():
695
+ """Main function to initialize and launch the interface."""
696
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
697
+
698
+ if not gapgpt_api_key:
699
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
700
+ else:
701
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
702
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
703
+
704
+ # تنظیم LLM (مدل زبانی)
705
+ llm = LlamaIndexOpenAI(
706
+ model="gpt-4o",
707
+ temperature=1,
708
+ max_tokens=1024,
709
+ top_p=0.95,
710
+ frequency_penalty=0.4,
711
+ presence_penalty=0.2,
712
+ api_key=gapgpt_api_key,
713
+ api_base=GAPGPT_BASE_URL,
714
+ )
715
+
716
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
717
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
718
+ embed_model = OpenAIEmbedding(
719
+ api_key=gapgpt_api_key,
720
+ api_base=GAPGPT_BASE_URL,
721
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
722
+ )
723
+
724
+ # اعمال تنظیمات سراسری
725
+ Settings.llm = llm
726
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
727
+
728
+ Settings.prompt_helper = PromptHelper(
729
+ context_window=4096,
730
+ num_output=256,
731
+ chunk_overlap_ratio=20 / 4096,
732
+ tokenizer=tokenizer,
733
+ )
734
+
735
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
736
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
737
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
738
+ if 'api_keys' not in locals():
739
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
740
+
741
+ demo = create_gradio_interface(Settings, api_keys)
742
+ demo.launch(
743
+ server_name="127.0.0.1",
744
+ server_port=7860,
745
+ share=True
746
+ )
747
+
748
+
749
+ if __name__ == "__main__":
750
+ signal.signal(signal.SIGINT, signal_handler)
751
+ main()
Backup code/app_V4.py ADDED
@@ -0,0 +1,855 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+
13
+ import gradio as gr
14
+ import nltk
15
+ import torch
16
+ import tiktoken
17
+
18
+ from openai import OpenAI as OpenAIClient
19
+ from llama_index.embeddings.openai import OpenAIEmbedding
20
+
21
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
22
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
23
+ from llama_index.core import Settings
24
+ from llama_index.core.indices.prompt_helper import PromptHelper
25
+
26
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
27
+ sys.path.append(prompt_path)
28
+
29
+ # Assuming these imports exist in your local environment
30
+ from utils.sys_args import data_args, model_args
31
+ from utils.app_modules.utils import *
32
+ from utils.app_modules.presets import *
33
+ from utils.app_modules.overwrites import *
34
+ from utils.prompt_utils import *
35
+ from utils.memory_utils import (
36
+ enter_name_llamaindex,
37
+ summarize_memory_event_personality,
38
+ save_local_memory,
39
+ extract_session_summary,
40
+ extract_semantic_memory,
41
+ )
42
+
43
+ # Ensure NLTK data path
44
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
45
+
46
+ tokenizer = tiktoken.get_encoding("cl100k_base")
47
+
48
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
49
+ openai_client_cache = {}
50
+
51
+ import torch
52
+ import torch.nn.functional as F
53
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
54
+
55
+
56
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
57
+
58
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
59
+
60
+ try:
61
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
62
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model.eval()
64
+ print("Local classifier loaded successfully.")
65
+ except Exception as e:
66
+ print(f"Error loading local classifier: {e}")
67
+
68
+
69
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
70
+ if not api_key:
71
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
72
+ if api_key not in openai_client_cache:
73
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
74
+ return openai_client_cache[api_key]
75
+
76
+
77
+ os_name = platform.system()
78
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
79
+ stop_stream = False
80
+
81
+
82
+ def signal_handler(signal_number, frame):
83
+ global stop_stream
84
+ stop_stream = True
85
+
86
+
87
+ VECTOR_SEARCH_TOP_K = 2
88
+
89
+ # Update this path to your actual file location
90
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
91
+
92
+
93
+ def read_apis(path):
94
+ api_keys_local = []
95
+ if os.path.exists(path):
96
+ with open(path, 'r', encoding='utf8') as f:
97
+ for line in f:
98
+ line = line.strip()
99
+ if line:
100
+ api_keys_local.append(line)
101
+ return api_keys_local
102
+
103
+
104
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
105
+
106
+ # Ensure directory exists
107
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
108
+
109
+ if not os.path.exists(memory_dir):
110
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
111
+
112
+ global memory
113
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
114
+ language = 'en'
115
+ user_keyword = generate_user_keyword()[language]
116
+ ai_keyword = generate_ai_keyword()[language]
117
+ boot_name = boot_name_dict[language]
118
+ boot_actual_name = boot_actual_name_dict[language]
119
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
120
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
121
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
122
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
123
+
124
+ api_keys = read_apis(api_path)
125
+ # Fallback if file is empty or missing for testing purposes
126
+ if not api_keys:
127
+ print(f"Warning: No API keys found in {api_path}.")
128
+
129
+ new_conversation = False
130
+ chatgpt_config = {
131
+ "model": "gpt-4o",
132
+ "temperature": 1,
133
+ "max_tokens": 1024,
134
+ "top_p": 0.95,
135
+ "frequency_penalty": 0.4,
136
+ "presence_penalty": 0.2,
137
+ "n": 1,
138
+ }
139
+
140
+ deactivated_keys = []
141
+ logging.basicConfig(
142
+ level=logging.DEBUG,
143
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
144
+ )
145
+
146
+
147
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
148
+ """
149
+ Handles the chat request to OpenAI.
150
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
151
+ """
152
+ retry_times, count = 5, 0
153
+ response = None
154
+
155
+ while response is None and count < retry_times:
156
+ try:
157
+ request = copy.deepcopy(gpt_config)
158
+
159
+ # Initial system and greeting messages
160
+ if data_args.language == 'en':
161
+ message = [
162
+ {"role": "system", "content": system.strip()},
163
+ {"role": "user", "content": "Hi!"},
164
+ {"role": "assistant",
165
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
166
+ ]
167
+ else:
168
+ message = [
169
+ {"role": "system", "content": system.strip()},
170
+ {"role": "user", "content": "Hi"},
171
+ {"role": "assistant",
172
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
173
+ ]
174
+
175
+ # --- FIX: Handle History as List of Dicts ---
176
+ if history:
177
+ # Verify if history is old format (list of lists) or new (list of dicts)
178
+ if isinstance(history[0], list):
179
+ # Convert old format temporarily if encountered
180
+ for q, a in history:
181
+ message.append({"role": "user", "content": str(q)})
182
+ message.append({"role": "assistant", "content": str(a)})
183
+ elif isinstance(history[0], dict):
184
+ # New format
185
+ for msg in history:
186
+ if msg.get('role') in ['user', 'assistant']:
187
+ message.append(msg)
188
+
189
+ # Add the current prompt
190
+ message.append({"role": "user", "content": f"{prompt}"})
191
+
192
+ if not api_keys:
193
+ return "Error: No API Keys available."
194
+
195
+ client = get_gapgpt_client(api_keys[api_index])
196
+
197
+ # New OpenAI 1.x Syntax
198
+ response = client.chat.completions.create(messages=message, **request)
199
+
200
+ except Exception as e:
201
+ print(f"Chat Error: {e}")
202
+ if 'This key is associated with a deactivated account' in str(e):
203
+ deactivated_keys.append(api_keys[api_index])
204
+
205
+ if api_keys:
206
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
207
+ loop_check = 0
208
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
209
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
210
+ loop_check += 1
211
+ count += 1
212
+
213
+ if response:
214
+ response = response.choices[0].message.content
215
+ else:
216
+ response = ''
217
+ return response
218
+
219
+
220
+ def classify_query_local(text):
221
+
222
+
223
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
224
+ id2label_map = {
225
+ 0: "episodic_memory",
226
+ 1: "semantic_memory",
227
+ 2: "semantic-episodic",
228
+ 3: "unknown"
229
+ }
230
+
231
+ try:
232
+
233
+ inputs = _tokenizer(
234
+ text,
235
+ return_tensors="pt",
236
+ truncation=True,
237
+ padding=True,
238
+ max_length=512
239
+ )
240
+
241
+
242
+
243
+ with torch.no_grad():
244
+ outputs = _classifier_model(**inputs)
245
+
246
+
247
+ logits = outputs.logits
248
+ probabilities = F.softmax(logits, dim=-1)
249
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
250
+
251
+
252
+ category = id2label_map.get(predicted_class_id, "unknown")
253
+
254
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
255
+ return category
256
+
257
+ except Exception as e:
258
+ print(f"Error in local classification: {e}")
259
+ return "unknown"
260
+
261
+
262
+
263
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
264
+ response = None
265
+ count = 0
266
+ local_deactivated = []
267
+ print("text********:", text)
268
+
269
+ system_prompt = """
270
+ You are an AI that classifies user queries into one of the following memory types:
271
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
272
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
273
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
274
+
275
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
276
+ """.strip()
277
+
278
+ if not api_keys:
279
+ return "unknown"
280
+
281
+ while response is None and count < retry_times:
282
+ try:
283
+ client = get_gapgpt_client(api_keys[api_index])
284
+
285
+ # New OpenAI 1.x Syntax
286
+ response = client.chat.completions.create(
287
+ messages=[
288
+ {"role": "system", "content": system_prompt},
289
+ {"role": "user", "content": text.strip()},
290
+ ],
291
+ **copy.deepcopy(gpt_config),
292
+ )
293
+ except Exception as e:
294
+ print(f"Classify Error: {e}")
295
+ if "This key is associated with a deactivated account" in str(e):
296
+ local_deactivated.append(api_keys[api_index])
297
+
298
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
299
+ while api_keys[api_index] in local_deactivated:
300
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
301
+ count += 1
302
+
303
+ if response:
304
+ category = response.choices[0].message.content.strip().lower()
305
+ # Basic cleanup
306
+ if "semantic_memory" in category: category = "semantic_memory"
307
+ elif "semantic-episodic" in category: category = "semantic-episodic"
308
+ elif "episodic_memory" in category: category = "episodic_memory"
309
+ else: category = "unknown"
310
+ else:
311
+ category = "unknown"
312
+
313
+ return category
314
+
315
+
316
+ def predict_new(
317
+ text,
318
+ history,
319
+ top_p,
320
+ temperature,
321
+ max_length_tokens,
322
+ max_context_length_tokens,
323
+ user_name,
324
+ user_memory,
325
+ user_memory_index,
326
+ service_context,
327
+ api_index,
328
+ semantic_memory_text,
329
+ query_category,
330
+ ):
331
+ chatgpt_cfg = {
332
+ "model": "gpt-4o",
333
+ "temperature": temperature,
334
+ "max_tokens": max_length_tokens,
335
+ "top_p": top_p,
336
+ "frequency_penalty": 0.4,
337
+ "presence_penalty": 0.2,
338
+ "n": 1,
339
+ }
340
+
341
+ if text == "":
342
+ # Return same history if empty input
343
+ return history, history, "Empty context."
344
+
345
+ # Ensure history is initialized
346
+ if history is None:
347
+ history = []
348
+
349
+ system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
350
+ history=history,
351
+ query=text, # Changed name to match prompt_utils
352
+ user_memory=user_memory,
353
+ user_name=user_name,
354
+ user_memory_index=user_memory_index,
355
+ service_context=service_context,
356
+ api_keys=api_keys,
357
+ api_index=api_index,
358
+ meta_prompt=meta_prompt,
359
+ new_user_meta_prompt=new_user_meta_prompt,
360
+ data_args=data_args,
361
+ boot_actual_name=boot_actual_name,
362
+ semantic_memory_text=semantic_memory_text,
363
+ query_category=query_category,
364
+ meta_prompt_semantic=meta_prompt_semantic,
365
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
366
+ )
367
+
368
+ # Handle context window slicing manually if needed,
369
+ # though usually OpenAI manages this, or we slice the list of dicts.
370
+ current_history_for_llm = history
371
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
372
+ current_history_for_llm = history[-(data_args.max_history * 2):]
373
+
374
+ response = chatgpt_chat(
375
+ prompt=text,
376
+ system=system_prompt,
377
+ history=current_history_for_llm,
378
+ gpt_config=chatgpt_cfg,
379
+ api_index=api_index,
380
+ )
381
+
382
+ torch.cuda.empty_cache()
383
+
384
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
385
+ new_history = history + [
386
+ {"role": "user", "content": text},
387
+ {"role": "assistant", "content": response}
388
+ ]
389
+
390
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
391
+ # OR we convert strictly for saving if your legacy code needs it.
392
+ # For now, assuming we pass the object as is or convert for save)
393
+ if user_name:
394
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
395
+ # or pass a converted version. Let's try passing the new format.
396
+ save_local_memory(memory, new_history, user_name, data_args)
397
+
398
+ # Return: (Chatbot View, State History, Textbox Reset)
399
+ return new_history, new_history, "Generating..."
400
+
401
+
402
+ import gradio as gr
403
+ import time
404
+
405
+ import gradio as gr
406
+
407
+ def create_gradio_interface(service_context, api_keys):
408
+ with gr.Blocks(title="EMMA") as demo:
409
+
410
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
411
+ gr.HTML("""
412
+ <style>
413
+ .center-content {
414
+ display: flex;
415
+ flex-direction: column;
416
+ align-items: center;
417
+ justify-content: center;
418
+ }
419
+ /* -- استایل‌های فرم ورود -- */
420
+ .login-box {
421
+ max-width: 400px !important;
422
+ margin: 0 auto !important;
423
+ width: 100% !important;
424
+ }
425
+ .login-btn, .login-btn:hover {
426
+ background-color: #3498db !important;
427
+ background-image: none !important;
428
+ color: white !important;
429
+ border: none !important;
430
+ }
431
+ /* -- استایل‌های محیط چت -- */
432
+ .chat-box {
433
+ max-width: 800px !important;
434
+ margin: 0 auto !important;
435
+ width: 100% !important;
436
+ }
437
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
438
+ .mobile-button, .mobile-button:hover {
439
+ background-color: #3498db !important;
440
+ background-image: none !important;
441
+ color: white !important;
442
+ border: none !important;
443
+ }
444
+ .gr-textbox textarea {
445
+ font-size: 16px;
446
+ }
447
+ .gr-chatbot {
448
+ font-size: 15px;
449
+ }
450
+
451
+ /* --- انیمیشن کشویی لاگین --- */
452
+ .slide-up {
453
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
454
+ }
455
+
456
+ @keyframes slideUpAnimation {
457
+ 0% {
458
+ transform: translateY(0);
459
+ opacity: 1;
460
+ max-height: 1000px;
461
+ }
462
+ 100% {
463
+ transform: translateY(-100%);
464
+ opacity: 0;
465
+ max-height: 0px;
466
+ overflow: hidden;
467
+ margin: 0 !important;
468
+ padding: 0 !important;
469
+ border: none !important;
470
+ }
471
+ }
472
+ </style>
473
+ """)
474
+
475
+ state = gr.State({
476
+ "history": [],
477
+ "user_name": None,
478
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
479
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
480
+ "service_context": service_context,
481
+ "api_keys": api_keys,
482
+ "api_index": 0,
483
+ "semantic_memory_text": "",
484
+ "new_conversation": True,
485
+ "initialized": False
486
+ })
487
+
488
+ # ==========================================
489
+ # 1. LOGIN PAGE
490
+ # ==========================================
491
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
492
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
493
+
494
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
495
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
496
+ login_status = gr.Textbox(visible=False, label="Status")
497
+
498
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
499
+
500
+ with gr.Column(visible=False) as registration_fields:
501
+ gr.Markdown("### ✨ New User Registration")
502
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
503
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
504
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
505
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
506
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
507
+
508
+ # ==========================================
509
+ # 2. CHAT PAGE
510
+ # ==========================================
511
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
512
+ with gr.Column(elem_classes=["chat-box"]):
513
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
514
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
515
+
516
+ with gr.Group():
517
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
518
+
519
+ with gr.Row():
520
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
521
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
522
+
523
+ with gr.Row(equal_height=True):
524
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
525
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
526
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
527
+
528
+ # -------------------------------------------------------
529
+ # Internal Functions
530
+ # -------------------------------------------------------
531
+ def handle_login_check(name, state):
532
+ if not name.strip():
533
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
534
+
535
+ if name in memory:
536
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
537
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
538
+
539
+ new_state = state.copy()
540
+ new_state["user_name"] = name
541
+ new_state["memory"] = memory
542
+ new_state["initialized"] = True
543
+ new_state["semantic_memory_text"] = semantic_memory
544
+ new_state["history"] = []
545
+
546
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
547
+
548
+ return (
549
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
550
+ gr.update(visible=False),
551
+ gr.update(visible=True),
552
+ gr.update(visible=False, value=""),
553
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
554
+ gr.update(value=welcome_msg),
555
+ new_state
556
+ )
557
+ else:
558
+ return (
559
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
560
+ gr.update(visible=True),
561
+ gr.update(visible=False),
562
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
563
+ gr.update(),
564
+ gr.update(),
565
+ state
566
+ )
567
+
568
+ def handle_register(name, age, gender, occupation, residence, state):
569
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
570
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
571
+
572
+ new_state = state.copy()
573
+ new_state["user_name"] = name
574
+ new_state["memory"] = memory
575
+ new_state["initialized"] = True
576
+ new_state["semantic_memory_text"] = semantic_memory
577
+ new_state["history"] = []
578
+
579
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
580
+
581
+ return (
582
+ gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
583
+ gr.update(visible=False),
584
+ gr.update(visible=True),
585
+ gr.update(visible=False, value=""),
586
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
587
+ gr.update(value=welcome_msg),
588
+ new_state
589
+ )
590
+
591
+ def switch_user(state):
592
+ if state["initialized"] and state["user_name"] in state["memory"]:
593
+ if state["memory"][state["user_name"]]["sessions"]:
594
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
595
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
596
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
597
+
598
+ new_state = state.copy()
599
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
600
+
601
+ return (
602
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
603
+ gr.update(visible=False),
604
+ gr.update(visible=False),
605
+ gr.update(value="Logged out successfully.", visible=True),
606
+ gr.update(value=""),
607
+ new_state,
608
+ gr.update(value=[])
609
+ )
610
+
611
+ def handle_chat(user_message, state):
612
+ if not user_message.strip():
613
+ return gr.update(), state.get("history", []), state
614
+
615
+ user_name = state.get("user_name")
616
+ user_memory = state.get("memory")
617
+ service_context = state.get("service_context")
618
+ api_index = state.get("api_index", 0)
619
+ semantic_memory_text = state.get("semantic_memory_text", "")
620
+
621
+ query_category = classify_query_local(user_message)
622
+
623
+ new_history, _, status_msg = predict_new(
624
+ text=user_message,
625
+ history=state.get("history", []),
626
+ top_p=0.95,
627
+ temperature=1.0,
628
+ max_length_tokens=1024,
629
+ max_context_length_tokens=4096,
630
+ user_name=user_name,
631
+ user_memory=user_memory,
632
+ user_memory_index=None,
633
+ service_context=service_context,
634
+ api_index=api_index,
635
+ semantic_memory_text=semantic_memory_text,
636
+ query_category=query_category
637
+ )
638
+
639
+ state["history"] = new_history
640
+ return "", new_history, state
641
+
642
+ def clear_history(state):
643
+ state["history"] = []
644
+ return [], state
645
+
646
+ def handle_new_session(state):
647
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
648
+ user_name = state.get("user_name")
649
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
650
+ print("Error: User not logged in or memory missing.")
651
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
652
+ return [], state
653
+
654
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
655
+ user_data = state["memory"][user_name]
656
+
657
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
658
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
659
+ last_session = user_data["sessions"][-1]
660
+
661
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
662
+ if len(last_session.get("conversation", [])) > 0:
663
+ session_date = last_session.get("date", "")
664
+ session_id = last_session.get("session_id", 0)
665
+
666
+ # پاس دادن هر ۳ آرگومان به تابع
667
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
668
+
669
+ if "episodic_memory" not in user_data:
670
+ user_data["episodic_memory"] = []
671
+ user_data["episodic_memory"].append(ep_summary)
672
+
673
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
674
+ new_session_id = len(user_data.get("sessions", []))
675
+
676
+ new_session = {
677
+ "session_id": new_session_id,
678
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
679
+ "conversation": []
680
+ }
681
+
682
+ if "sessions" not in user_data:
683
+ user_data["sessions"] = []
684
+
685
+ user_data["sessions"].append(new_session)
686
+
687
+ # پاک کردن تاریخچه چت در state
688
+ state["history"] = []
689
+
690
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
691
+ return [], state
692
+
693
+
694
+ # اگر state خالی است یا کلید user_data را ندارد
695
+ if not state or "user_data" not in state:
696
+ print("Error: user_data not found in state.")
697
+ # مقادیر بازگشتی را بر اساس خروجی‌های تابع خود تنظیم کنید
698
+ # مثلاً برگرداندن state فعلی و یک لیست خالی برای چت‌باکس
699
+ return state, []
700
+
701
+ # دریافت امن اطلاعات کاربر
702
+ user_data = state["user_data"]
703
+
704
+ # --- بخش اول: استخراج حافظه از جلسه قبلی (قبل از ساخت جلسه جدید) ---
705
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
706
+ last_session = user_data["sessions"][-1]
707
+
708
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد (کاربر حرفی زده باشد)
709
+ if len(last_session.get("conversation", [])) > 0:
710
+
711
+ # استخراج حافظه اپیزودیک از مکالمات جلسه قبل
712
+ ep_summary = extract_session_summary(last_session["conversation"])
713
+
714
+ # اضافه کردن تاریخ و ID همان جلسه به حافظه اپیزودیک استخراج شده
715
+ ep_summary["session_date"] = last_session["date"]
716
+ ep_summary["session_id"] = last_session.get("session_id", 0)
717
+
718
+ # ذخیره در لیست حافظه اپیزودیک
719
+ if "episodic_memory" not in user_data:
720
+ user_data["episodic_memory"] = []
721
+ user_data["episodic_memory"].append(ep_summary)
722
+
723
+ # (اگر حافظه سمانتیک هم دارید، اینجا آپدیت کنید)
724
+
725
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
726
+
727
+ # محاسبه ID جدید (بر اساس تعداد جلسات فعلی)
728
+ new_session_id = len(user_data.get("sessions", []))
729
+
730
+ new_session = {
731
+ "session_id": new_session_id, # <--- مشکل اختصاص نیافتن ID اینجا حل می‌شود
732
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
733
+ "conversation": []
734
+ }
735
+
736
+ if "sessions" not in user_data:
737
+ user_data["sessions"] = []
738
+
739
+ user_data["sessions"].append(new_session)
740
+
741
+ # پاک کردن تاریخچه چت در رابط کاربری (Gradio)
742
+ state["history"] = []
743
+
744
+ return state
745
+
746
+
747
+ # -------------------------------------------------------
748
+ # Event Bindings
749
+ # -------------------------------------------------------
750
+ check_user_btn.click(
751
+ handle_login_check,
752
+ inputs=[username_input, state],
753
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
754
+ )
755
+
756
+ register_btn.click(
757
+ handle_register,
758
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
759
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
760
+ )
761
+
762
+ switch_user_btn.click(
763
+ switch_user,
764
+ inputs=[state],
765
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
766
+ )
767
+
768
+ submit_btn.click(
769
+ handle_chat,
770
+ inputs=[user_input, state],
771
+ outputs=[user_input, chatbot, state]
772
+ )
773
+
774
+ user_input.submit(
775
+ handle_chat,
776
+ inputs=[user_input, state],
777
+ outputs=[user_input, chatbot, state]
778
+ )
779
+
780
+ clear_btn.click(
781
+ clear_history,
782
+ inputs=[state],
783
+ outputs=[chatbot, state]
784
+ )
785
+
786
+ # تغییر از clear_history به handle_new_session
787
+ new_session_btn.click(
788
+ handle_new_session,
789
+ inputs=[state],
790
+ outputs=[chatbot, state]
791
+
792
+
793
+ )
794
+
795
+ return demo
796
+
797
+
798
+ def main():
799
+ """Main function to initialize and launch the interface."""
800
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
801
+
802
+ if not gapgpt_api_key:
803
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
804
+ else:
805
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
806
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
807
+
808
+ # تنظیم LLM (مدل زبانی)
809
+ llm = LlamaIndexOpenAI(
810
+ model="gpt-4o",
811
+ temperature=1,
812
+ max_tokens=1024,
813
+ top_p=0.95,
814
+ frequency_penalty=0.4,
815
+ presence_penalty=0.2,
816
+ api_key=gapgpt_api_key,
817
+ api_base=GAPGPT_BASE_URL,
818
+ )
819
+
820
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
821
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
822
+ embed_model = OpenAIEmbedding(
823
+ api_key=gapgpt_api_key,
824
+ api_base=GAPGPT_BASE_URL,
825
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
826
+ )
827
+
828
+ # اعمال تنظیمات سراسری
829
+ Settings.llm = llm
830
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
831
+
832
+ Settings.prompt_helper = PromptHelper(
833
+ context_window=4096,
834
+ num_output=256,
835
+ chunk_overlap_ratio=20 / 4096,
836
+ tokenizer=tokenizer,
837
+ )
838
+
839
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
840
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
841
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
842
+ if 'api_keys' not in locals():
843
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
844
+
845
+ demo = create_gradio_interface(Settings, api_keys)
846
+ demo.launch(
847
+ server_name="127.0.0.1",
848
+ server_port=7860,
849
+ share=True
850
+ )
851
+
852
+
853
+ if __name__ == "__main__":
854
+ signal.signal(signal.SIGINT, signal_handler)
855
+ main()
Backup code/app_V5.py ADDED
@@ -0,0 +1,881 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ ):
332
+ chatgpt_cfg = {
333
+ "model": "gpt-4o",
334
+ "temperature": temperature,
335
+ "max_tokens": max_length_tokens,
336
+ "top_p": top_p,
337
+ "frequency_penalty": 0.4,
338
+ "presence_penalty": 0.2,
339
+ "n": 1,
340
+ }
341
+
342
+ if text == "":
343
+ # Return same history if empty input
344
+ return history, history, "Empty context."
345
+
346
+ # Ensure history is initialized
347
+ if history is None:
348
+ history = []
349
+
350
+ system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
351
+ history=history,
352
+ query=text, # Changed name to match prompt_utils
353
+ user_memory=user_memory,
354
+ user_name=user_name,
355
+ user_memory_index=user_memory_index,
356
+ service_context=service_context,
357
+ api_keys=api_keys,
358
+ api_index=api_index,
359
+ meta_prompt=meta_prompt,
360
+ new_user_meta_prompt=new_user_meta_prompt,
361
+ data_args=data_args,
362
+ boot_actual_name=boot_actual_name,
363
+ semantic_memory_text=semantic_memory_text,
364
+ query_category=query_category,
365
+ meta_prompt_semantic=meta_prompt_semantic,
366
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
367
+ )
368
+
369
+ # Handle context window slicing manually if needed,
370
+ # though usually OpenAI manages this, or we slice the list of dicts.
371
+ current_history_for_llm = history
372
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
373
+ current_history_for_llm = history[-(data_args.max_history * 2):]
374
+
375
+ response = chatgpt_chat(
376
+ prompt=text,
377
+ system=system_prompt,
378
+ history=current_history_for_llm,
379
+ gpt_config=chatgpt_cfg,
380
+ api_index=api_index,
381
+ )
382
+
383
+ torch.cuda.empty_cache()
384
+
385
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
386
+ new_history = history + [
387
+ {"role": "user", "content": text},
388
+ {"role": "assistant", "content": response}
389
+ ]
390
+
391
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
392
+ # OR we convert strictly for saving if your legacy code needs it.
393
+ # For now, assuming we pass the object as is or convert for save)
394
+ if user_name:
395
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
396
+ # or pass a converted version. Let's try passing the new format.
397
+ save_local_memory(memory, new_history, user_name, data_args)
398
+
399
+ # Return: (Chatbot View, State History, Textbox Reset)
400
+ return new_history, new_history, "Generating..."
401
+
402
+
403
+
404
+ def create_gradio_interface(service_context, api_keys):
405
+ with gr.Blocks(title="EMMA") as demo:
406
+
407
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
408
+ gr.HTML("""
409
+ <style>
410
+ .center-content {
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+ /* -- استایل‌های فرم ورود -- */
417
+ .login-box {
418
+ max-width: 400px !important;
419
+ margin: 0 auto !important;
420
+ width: 100% !important;
421
+ }
422
+ .login-btn, .login-btn:hover {
423
+ background-color: #3498db !important;
424
+ background-image: none !important;
425
+ color: white !important;
426
+ border: none !important;
427
+ }
428
+ /* -- استایل‌های محیط چت -- */
429
+ .chat-box {
430
+ max-width: 800px !important;
431
+ margin: 0 auto !important;
432
+ width: 100% !important;
433
+ }
434
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
435
+ .mobile-button, .mobile-button:hover {
436
+ background-color: #3498db !important;
437
+ background-image: none !important;
438
+ color: white !important;
439
+ border: none !important;
440
+ }
441
+ .gr-textbox textarea {
442
+ font-size: 16px;
443
+ }
444
+ .gr-chatbot {
445
+ font-size: 15px;
446
+ }
447
+
448
+ /* --- انیمیشن کشویی لاگین --- */
449
+ .slide-up {
450
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
451
+ }
452
+
453
+ @keyframes slideUpAnimation {
454
+ 0% {
455
+ transform: translateY(0);
456
+ opacity: 1;
457
+ max-height: 1000px;
458
+ }
459
+ 100% {
460
+ transform: translateY(-100%);
461
+ opacity: 0;
462
+ max-height: 0px;
463
+ overflow: hidden;
464
+ margin: 0 !important;
465
+ padding: 0 !important;
466
+ border: none !important;
467
+ }
468
+ }
469
+ </style>
470
+ """)
471
+
472
+ state = gr.State({
473
+ "history": [],
474
+ "user_name": None,
475
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
476
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
477
+ "service_context": service_context,
478
+ "api_keys": api_keys,
479
+ "api_index": 0,
480
+ "semantic_memory_text": "",
481
+ "new_conversation": True,
482
+ "initialized": False
483
+ })
484
+
485
+ # ==========================================
486
+ # 1. LOGIN PAGE
487
+ # ==========================================
488
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
489
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
490
+
491
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
492
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
493
+ login_status = gr.Textbox(visible=False, label="Status")
494
+
495
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
496
+
497
+ with gr.Column(visible=False) as registration_fields:
498
+ gr.Markdown("### ✨ New User Registration")
499
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
500
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
501
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
502
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
503
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
504
+
505
+ # ==========================================
506
+ # 2. CHAT PAGE
507
+ # ==========================================
508
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
509
+ with gr.Column(elem_classes=["chat-box"]):
510
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
511
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
512
+
513
+ with gr.Group():
514
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
515
+
516
+ with gr.Row():
517
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
518
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
519
+
520
+ with gr.Row(equal_height=True):
521
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
522
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
523
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
524
+
525
+ # -------------------------------------------------------
526
+ # Internal Functions
527
+ # -------------------------------------------------------
528
+ def handle_login_check(name, state):
529
+ if not name.strip():
530
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
531
+
532
+ if name in memory:
533
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
534
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
535
+
536
+ new_state = state.copy()
537
+ new_state["user_name"] = name
538
+ new_state["memory"] = memory
539
+ new_state["initialized"] = True
540
+ new_state["semantic_memory_text"] = semantic_memory
541
+ new_state["history"] = []
542
+
543
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
544
+
545
+ return (
546
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
547
+ gr.update(visible=False),
548
+ gr.update(visible=True),
549
+ gr.update(visible=False, value=""),
550
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
551
+ gr.update(value=welcome_msg),
552
+ new_state
553
+ )
554
+ else:
555
+ return (
556
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
557
+ gr.update(visible=True),
558
+ gr.update(visible=False),
559
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
560
+ gr.update(),
561
+ gr.update(),
562
+ state
563
+ )
564
+
565
+ def handle_register(name, age, gender, occupation, residence, state):
566
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
567
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
568
+
569
+ new_state = state.copy()
570
+ new_state["user_name"] = name
571
+ new_state["memory"] = memory
572
+ new_state["initialized"] = True
573
+ new_state["semantic_memory_text"] = semantic_memory
574
+ new_state["history"] = []
575
+
576
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
577
+
578
+ return (
579
+ gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
580
+ gr.update(visible=False),
581
+ gr.update(visible=True),
582
+ gr.update(visible=False, value=""),
583
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
584
+ gr.update(value=welcome_msg),
585
+ new_state
586
+ )
587
+
588
+ def switch_user(state):
589
+ if state["initialized"] and state["user_name"] in state["memory"]:
590
+ if state["memory"][state["user_name"]]["sessions"]:
591
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
592
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
593
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
594
+ # ==========================================
595
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
596
+ # ==========================================
597
+ try:
598
+ user_mem = state["memory"][state["user_name"]]
599
+ existing_semantic = user_mem.get("semantic_memory", {})
600
+
601
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
602
+
603
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
604
+ except Exception as e:
605
+ print(f"Error updating semantic memory on logout: {e}")
606
+ # ==========================================
607
+
608
+ new_state = state.copy()
609
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
610
+
611
+ return (
612
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
613
+ gr.update(visible=False),
614
+ gr.update(visible=False),
615
+ gr.update(value="Logged out successfully.", visible=True),
616
+ gr.update(value=""),
617
+ new_state,
618
+ gr.update(value=[])
619
+ )
620
+
621
+ def handle_chat(user_message, state):
622
+ if not user_message.strip():
623
+ return gr.update(), state.get("history", []), state
624
+
625
+ user_name = state.get("user_name")
626
+ user_memory = state.get("memory")
627
+ service_context = state.get("service_context")
628
+ api_index = state.get("api_index", 0)
629
+ semantic_memory_text = state.get("semantic_memory_text", "")
630
+
631
+ query_category = classify_query_local(user_message)
632
+
633
+ new_history, _, status_msg = predict_new(
634
+ text=user_message,
635
+ history=state.get("history", []),
636
+ top_p=0.95,
637
+ temperature=1.0,
638
+ max_length_tokens=1024,
639
+ max_context_length_tokens=4096,
640
+ user_name=user_name,
641
+ user_memory=user_memory,
642
+ user_memory_index=None,
643
+ service_context=service_context,
644
+ api_index=api_index,
645
+ semantic_memory_text=semantic_memory_text,
646
+ query_category=query_category
647
+ )
648
+
649
+ state["history"] = new_history
650
+ return "", new_history, state
651
+
652
+ def clear_history(state):
653
+ state["history"] = []
654
+ return [], state
655
+
656
+ def handle_new_session(state):
657
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
658
+ user_name = state.get("user_name")
659
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
660
+ print("Error: User not logged in or memory missing.")
661
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
662
+ return [], state
663
+
664
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
665
+ user_data = state["memory"][user_name]
666
+
667
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
668
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
669
+ last_session = user_data["sessions"][-1]
670
+
671
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
672
+ if len(last_session.get("conversation", [])) > 0:
673
+ session_date = last_session.get("date", "")
674
+ session_id = last_session.get("session_id", 0)
675
+
676
+ # پاس دادن هر ۳ آرگومان به تابع
677
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
678
+
679
+ if "episodic_memory" not in user_data:
680
+ user_data["episodic_memory"] = []
681
+ user_data["episodic_memory"].append(ep_summary)
682
+
683
+ # ==========================================
684
+ # به‌روزرسانی حافظه سمانتیک
685
+ # ==========================================
686
+ try:
687
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
688
+ existing_semantic = user_data.get("semantic_memory", {})
689
+
690
+ # فراخوانی تابع با هر دو آرگومان
691
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
692
+
693
+ # ذخیره دیتای جدید
694
+ user_data["semantic_memory"] = updated_semantic
695
+ except Exception as e:
696
+ print(f"Error updating semantic memory: {e}")
697
+ # ==========================================
698
+
699
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
700
+ new_session_id = len(user_data.get("sessions", []))
701
+
702
+ new_session = {
703
+ "session_id": new_session_id,
704
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
705
+ "conversation": []
706
+ }
707
+
708
+ if "sessions" not in user_data:
709
+ user_data["sessions"] = []
710
+
711
+ user_data["sessions"].append(new_session)
712
+
713
+ # پاک کردن تاریخچه چت در state
714
+ state["history"] = []
715
+
716
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
717
+ return [], state
718
+
719
+
720
+ # اگر state خالی است یا کلید user_data را ندارد
721
+ if not state or "user_data" not in state:
722
+ print("Error: user_data not found in state.")
723
+ # مقادیر بازگشتی را بر اساس خروجی‌های تابع خود تنظیم کنید
724
+ # مثلاً برگرداندن state فعلی و یک لیست خالی برای چت‌باکس
725
+ return state, []
726
+
727
+ # دریافت امن اطلاعات کاربر
728
+ user_data = state["user_data"]
729
+
730
+ # --- بخش اول: استخراج حافظه از جلسه قبلی (قبل از ساخت جلسه جدید) ---
731
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
732
+ last_session = user_data["sessions"][-1]
733
+
734
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد (کاربر حرفی زده باشد)
735
+ if len(last_session.get("conversation", [])) > 0:
736
+
737
+ # استخراج حافظه اپیزودیک از مکالمات جلسه قبل
738
+ ep_summary = extract_session_summary(last_session["conversation"])
739
+
740
+ # اضافه کردن تاریخ و ID همان جلسه به حافظه اپیزودیک استخراج شده
741
+ ep_summary["session_date"] = last_session["date"]
742
+ ep_summary["session_id"] = last_session.get("session_id", 0)
743
+
744
+ # ذخیره در لیست حافظه اپیزودیک
745
+ if "episodic_memory" not in user_data:
746
+ user_data["episodic_memory"] = []
747
+ user_data["episodic_memory"].append(ep_summary)
748
+
749
+ # (اگر حافظه سمانتیک هم دارید، اینجا آپدیت کنید)
750
+
751
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
752
+
753
+ # محاسبه ID جدید (بر اساس تعداد جلسات فعلی)
754
+ new_session_id = len(user_data.get("sessions", []))
755
+
756
+ new_session = {
757
+ "session_id": new_session_id, # <--- مشکل اختصاص نیافتن ID اینجا حل می‌شود
758
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
759
+ "conversation": []
760
+ }
761
+
762
+ if "sessions" not in user_data:
763
+ user_data["sessions"] = []
764
+
765
+ user_data["sessions"].append(new_session)
766
+
767
+ # پاک کردن تاریخچه چت در رابط کاربری (Gradio)
768
+ state["history"] = []
769
+
770
+ return state
771
+
772
+
773
+ # -------------------------------------------------------
774
+ # Event Bindings
775
+ # -------------------------------------------------------
776
+ check_user_btn.click(
777
+ handle_login_check,
778
+ inputs=[username_input, state],
779
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
780
+ )
781
+
782
+ register_btn.click(
783
+ handle_register,
784
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
785
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
786
+ )
787
+
788
+ switch_user_btn.click(
789
+ switch_user,
790
+ inputs=[state],
791
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
792
+ )
793
+
794
+ submit_btn.click(
795
+ handle_chat,
796
+ inputs=[user_input, state],
797
+ outputs=[user_input, chatbot, state]
798
+ )
799
+
800
+ user_input.submit(
801
+ handle_chat,
802
+ inputs=[user_input, state],
803
+ outputs=[user_input, chatbot, state]
804
+ )
805
+
806
+ clear_btn.click(
807
+ clear_history,
808
+ inputs=[state],
809
+ outputs=[chatbot, state]
810
+ )
811
+
812
+ # تغییر از clear_history به handle_new_session
813
+ new_session_btn.click(
814
+ handle_new_session,
815
+ inputs=[state],
816
+ outputs=[chatbot, state]
817
+
818
+
819
+ )
820
+
821
+ return demo
822
+
823
+
824
+ def main():
825
+ """Main function to initialize and launch the interface."""
826
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
827
+
828
+ if not gapgpt_api_key:
829
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
830
+ else:
831
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
832
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
833
+
834
+ # تنظیم LLM (مدل زبانی)
835
+ llm = LlamaIndexOpenAI(
836
+ model="gpt-4o",
837
+ temperature=1,
838
+ max_tokens=1024,
839
+ top_p=0.95,
840
+ frequency_penalty=0.4,
841
+ presence_penalty=0.2,
842
+ api_key=gapgpt_api_key,
843
+ api_base=GAPGPT_BASE_URL,
844
+ )
845
+
846
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
847
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
848
+ embed_model = OpenAIEmbedding(
849
+ api_key=gapgpt_api_key,
850
+ api_base=GAPGPT_BASE_URL,
851
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌ک��د
852
+ )
853
+
854
+ # اعمال تنظیمات سراسری
855
+ Settings.llm = llm
856
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
857
+
858
+ Settings.prompt_helper = PromptHelper(
859
+ context_window=4096,
860
+ num_output=256,
861
+ chunk_overlap_ratio=20 / 4096,
862
+ tokenizer=tokenizer,
863
+ )
864
+
865
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
866
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
867
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
868
+ if 'api_keys' not in locals():
869
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
870
+
871
+ demo = create_gradio_interface(Settings, api_keys)
872
+ demo.launch(
873
+ server_name="127.0.0.1",
874
+ server_port=7860,
875
+ share=True
876
+ )
877
+
878
+
879
+ if __name__ == "__main__":
880
+ signal.signal(signal.SIGINT, signal_handler)
881
+ main()
Backup code/app_V6.py ADDED
@@ -0,0 +1,854 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ ):
332
+ chatgpt_cfg = {
333
+ "model": "gpt-4o",
334
+ "temperature": temperature,
335
+ "max_tokens": max_length_tokens,
336
+ "top_p": top_p,
337
+ "frequency_penalty": 0.4,
338
+ "presence_penalty": 0.2,
339
+ "n": 1,
340
+ }
341
+
342
+ if text == "":
343
+ # Return same history if empty input
344
+ return history, history, "Empty context."
345
+
346
+ # Ensure history is initialized
347
+ if history is None:
348
+ history = []
349
+
350
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
351
+ history=history,
352
+ query=text, # Changed name to match prompt_utils
353
+ user_memory=user_memory,
354
+ user_name=user_name,
355
+ user_memory_index=user_memory_index,
356
+ service_context=service_context,
357
+ api_keys=api_keys,
358
+ api_index=api_index,
359
+ meta_prompt=meta_prompt,
360
+ new_user_meta_prompt=new_user_meta_prompt,
361
+ data_args=data_args,
362
+ boot_actual_name=boot_actual_name,
363
+ semantic_memory_text=semantic_memory_text,
364
+ query_category=query_category,
365
+ meta_prompt_semantic=meta_prompt_semantic,
366
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
367
+ )
368
+
369
+ # Handle context window slicing manually if needed,
370
+ # though usually OpenAI manages this, or we slice the list of dicts.
371
+ current_history_for_llm = history
372
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
373
+ current_history_for_llm = history[-(data_args.max_history * 2):]
374
+
375
+ response = chatgpt_chat(
376
+ prompt=text,
377
+ system=system_prompt,
378
+ history=current_history_for_llm,
379
+ gpt_config=chatgpt_cfg,
380
+ api_index=api_index,
381
+ )
382
+
383
+ torch.cuda.empty_cache()
384
+
385
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
386
+ new_history = history + [
387
+ {"role": "user", "content": text},
388
+ {"role": "assistant", "content": response}
389
+ ]
390
+
391
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
392
+ # OR we convert strictly for saving if your legacy code needs it.
393
+ # For now, assuming we pass the object as is or convert for save)
394
+ if user_name:
395
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
396
+ # or pass a converted version. Let's try passing the new format.
397
+ save_local_memory(memory, new_history, user_name, data_args)
398
+
399
+ # Return: (Chatbot View, State History, Textbox Reset)
400
+ return new_history, new_history, "Generating..."
401
+
402
+
403
+
404
+ def create_gradio_interface(service_context, api_keys):
405
+ with gr.Blocks(title="EMMA") as demo:
406
+
407
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
408
+ gr.HTML("""
409
+ <style>
410
+ .center-content {
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+ /* -- استایل‌های فرم ورود -- */
417
+ .login-box {
418
+ max-width: 400px !important;
419
+ margin: 0 auto !important;
420
+ width: 100% !important;
421
+ }
422
+ .login-btn, .login-btn:hover {
423
+ background-color: #3498db !important;
424
+ background-image: none !important;
425
+ color: white !important;
426
+ border: none !important;
427
+ }
428
+ /* -- استایل‌های محیط چت -- */
429
+ .chat-box {
430
+ max-width: 800px !important;
431
+ margin: 0 auto !important;
432
+ width: 100% !important;
433
+ }
434
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
435
+ .mobile-button, .mobile-button:hover {
436
+ background-color: #3498db !important;
437
+ background-image: none !important;
438
+ color: white !important;
439
+ border: none !important;
440
+ }
441
+ .gr-textbox textarea {
442
+ font-size: 16px;
443
+ }
444
+ .gr-chatbot {
445
+ font-size: 15px;
446
+ }
447
+
448
+ /* --- انیمیشن کشویی لاگین --- */
449
+ .slide-up {
450
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
451
+ }
452
+
453
+ @keyframes slideUpAnimation {
454
+ 0% {
455
+ transform: translateY(0);
456
+ opacity: 1;
457
+ max-height: 1000px;
458
+ }
459
+ 100% {
460
+ transform: translateY(-100%);
461
+ opacity: 0;
462
+ max-height: 0px;
463
+ overflow: hidden;
464
+ margin: 0 !important;
465
+ padding: 0 !important;
466
+ border: none !important;
467
+ }
468
+ }
469
+ </style>
470
+ """)
471
+
472
+ state = gr.State({
473
+ "history": [],
474
+ "user_name": None,
475
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
476
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
477
+ "service_context": service_context,
478
+ "api_keys": api_keys,
479
+ "api_index": 0,
480
+ "semantic_memory_text": "",
481
+ "new_conversation": True,
482
+ "initialized": False
483
+ })
484
+
485
+ # ==========================================
486
+ # 1. LOGIN PAGE
487
+ # ==========================================
488
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
489
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
490
+
491
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
492
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
493
+ login_status = gr.Textbox(visible=False, label="Status")
494
+
495
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
496
+
497
+ with gr.Column(visible=False) as registration_fields:
498
+ gr.Markdown("### ✨ New User Registration")
499
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
500
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
501
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
502
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
503
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
504
+
505
+ # ==========================================
506
+ # 2. CHAT PAGE
507
+ # ==========================================
508
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
509
+ with gr.Column(elem_classes=["chat-box"]):
510
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
511
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
512
+
513
+ with gr.Group():
514
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
515
+
516
+ with gr.Row():
517
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
518
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
519
+
520
+ with gr.Row(equal_height=True):
521
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
522
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
523
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
524
+
525
+ # -------------------------------------------------------
526
+ # Internal Functions
527
+ # -------------------------------------------------------
528
+ def handle_login_check(name, state):
529
+ if not name.strip():
530
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
531
+
532
+ if name in memory:
533
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
534
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
535
+
536
+ new_state = state.copy()
537
+ new_state["user_name"] = name
538
+ new_state["memory"] = memory
539
+ new_state["initialized"] = True
540
+ new_state["semantic_memory_text"] = semantic_memory
541
+ new_state["history"] = []
542
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
543
+
544
+ # در handle_login_check و handle_register اضافه کنید:
545
+ print(f"[DEBUG] Login/Register for {name}")
546
+ print(f"[DEBUG] sessions_memory: {sessions_memory}")
547
+ print(f"[DEBUG] semantic_memory: {semantic_memory}")
548
+ print(f"[DEBUG] new_state: {new_state}")
549
+
550
+
551
+
552
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
553
+
554
+ return (
555
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
556
+ gr.update(visible=False),
557
+ gr.update(visible=True),
558
+ gr.update(visible=False, value=""),
559
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
560
+ gr.update(value=welcome_msg),
561
+ new_state
562
+ )
563
+ else:
564
+ return (
565
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
566
+ gr.update(visible=True),
567
+ gr.update(visible=False),
568
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
569
+ gr.update(),
570
+ gr.update(),
571
+ state
572
+ )
573
+
574
+ def handle_register(name, age, gender, occupation, residence, state):
575
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
576
+ memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
577
+
578
+ new_state = state.copy()
579
+ new_state["user_name"] = name
580
+ new_state["memory"] = memory
581
+ new_state["initialized"] = True
582
+ new_state["semantic_memory_text"] = semantic_memory
583
+ new_state["history"] = []
584
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
585
+
586
+
587
+ welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
588
+
589
+ return (
590
+ gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
591
+ gr.update(visible=False),
592
+ gr.update(visible=True),
593
+ gr.update(visible=False, value=""),
594
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
595
+ gr.update(value=welcome_msg),
596
+ new_state
597
+ )
598
+
599
+ def switch_user(state):
600
+ if state["initialized"] and state["user_name"] in state["memory"]:
601
+ if state["memory"][state["user_name"]]["sessions"]:
602
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
603
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
604
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
605
+ # ==========================================
606
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
607
+ # ==========================================
608
+ try:
609
+ user_mem = state["memory"][state["user_name"]]
610
+ existing_semantic = user_mem.get("semantic_memory", {})
611
+
612
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
613
+
614
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
615
+ except Exception as e:
616
+ print(f"Error updating semantic memory on logout: {e}")
617
+ # ==========================================
618
+
619
+ new_state = state.copy()
620
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
621
+
622
+ return (
623
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
624
+ gr.update(visible=False),
625
+ gr.update(visible=False),
626
+ gr.update(value="Logged out successfully.", visible=True),
627
+ gr.update(value=""),
628
+ new_state,
629
+ gr.update(value=[])
630
+ )
631
+
632
+ def handle_chat(user_message, state):
633
+ if not user_message.strip():
634
+ print("[handle_chat] empty message")
635
+ print("[handle_chat] state =", state)
636
+ return gr.update(), state.get("history", []), state
637
+
638
+ print("[handle_chat] user_message =", repr(user_message))
639
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
640
+ print("[handle_chat] user_name =", state.get("user_name"))
641
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
642
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
643
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
644
+ print("[handle_chat] api_index =", state.get("api_index", 0))
645
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
646
+ print("[handle_chat] history len =", len(state.get("history", [])))
647
+
648
+ user_name = state.get("user_name")
649
+ user_memory_index = state.get("user_memory_index")
650
+ user_memory = state.get("memory")
651
+ service_context = state.get("service_context")
652
+ api_index = state.get("api_index", 0)
653
+ semantic_memory_text = state.get("semantic_memory_text", "")
654
+
655
+ query_category = classify_query_local(user_message)
656
+ print("[handle_chat] query_category =", query_category)
657
+
658
+ new_history, _, status_msg = predict_new(
659
+ text=user_message,
660
+ history=state.get("history", []),
661
+ top_p=0.95,
662
+ temperature=1.0,
663
+ max_length_tokens=1024,
664
+ max_context_length_tokens=4096,
665
+ user_name=user_name,
666
+ user_memory=user_memory,
667
+ user_memory_index=user_memory_index,
668
+ service_context=service_context,
669
+ api_index=api_index,
670
+ semantic_memory_text=semantic_memory_text,
671
+ query_category=query_category
672
+ )
673
+
674
+ print("[handle_chat] status_msg =", status_msg)
675
+ print("[handle_chat] new_history len =", len(new_history))
676
+
677
+ state["history"] = new_history
678
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
679
+
680
+ return "", new_history, state
681
+
682
+ def clear_history(state):
683
+ state["history"] = []
684
+ return [], state
685
+
686
+ def handle_new_session(state):
687
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
688
+ user_name = state.get("user_name")
689
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
690
+ print("Error: User not logged in or memory missing.")
691
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
692
+ return [], state
693
+
694
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
695
+ user_data = state["memory"][user_name]
696
+
697
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
698
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
699
+ last_session = user_data["sessions"][-1]
700
+
701
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
702
+ if len(last_session.get("conversation", [])) > 0:
703
+ session_date = last_session.get("date", "")
704
+ session_id = last_session.get("session_id", 0)
705
+
706
+ # پاس دادن هر ۳ آرگومان به تابع
707
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
708
+
709
+ if "episodic_memory" not in user_data:
710
+ user_data["episodic_memory"] = []
711
+ user_data["episodic_memory"].append(ep_summary)
712
+
713
+ # ==========================================
714
+ # به‌روزرسانی حافظه سمانتیک
715
+ # ==========================================
716
+ try:
717
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
718
+ existing_semantic = user_data.get("semantic_memory", {})
719
+
720
+ # فراخوانی تابع با هر دو آرگومان
721
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
722
+
723
+ # ذخیره دیتای جدید
724
+ user_data["semantic_memory"] = updated_semantic
725
+ except Exception as e:
726
+ print(f"Error updating semantic memory: {e}")
727
+ # ==========================================
728
+
729
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
730
+ new_session_id = len(user_data.get("sessions", []))
731
+
732
+ new_session = {
733
+ "session_id": new_session_id,
734
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
735
+ "conversation": []
736
+ }
737
+
738
+ if "sessions" not in user_data:
739
+ user_data["sessions"] = []
740
+
741
+ user_data["sessions"].append(new_session)
742
+
743
+ # پاک کردن تاریخچه چت در state
744
+ state["history"] = []
745
+
746
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
747
+ return [], state
748
+
749
+ check_user_btn.click(
750
+ handle_login_check,
751
+ inputs=[username_input, state],
752
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
753
+ )
754
+
755
+ register_btn.click(
756
+ handle_register,
757
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
758
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
759
+ )
760
+
761
+ switch_user_btn.click(
762
+ switch_user,
763
+ inputs=[state],
764
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
765
+ )
766
+
767
+ submit_btn.click(
768
+ handle_chat,
769
+ inputs=[user_input, state],
770
+ outputs=[user_input, chatbot, state]
771
+ )
772
+
773
+ user_input.submit(
774
+ handle_chat,
775
+ inputs=[user_input, state],
776
+ outputs=[user_input, chatbot, state]
777
+ )
778
+
779
+ clear_btn.click(
780
+ clear_history,
781
+ inputs=[state],
782
+ outputs=[chatbot, state]
783
+ )
784
+
785
+ # تغییر از clear_history به handle_new_session
786
+ new_session_btn.click(
787
+ handle_new_session,
788
+ inputs=[state],
789
+ outputs=[chatbot, state]
790
+
791
+
792
+ )
793
+
794
+ return demo
795
+
796
+
797
+ def main():
798
+ """Main function to initialize and launch the interface."""
799
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
800
+
801
+ if not gapgpt_api_key:
802
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
803
+ else:
804
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
805
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
806
+
807
+ # تنظیم LLM (مدل زبانی)
808
+ llm = LlamaIndexOpenAI(
809
+ model="gpt-4o",
810
+ temperature=1,
811
+ max_tokens=1024,
812
+ top_p=0.95,
813
+ frequency_penalty=0.4,
814
+ presence_penalty=0.2,
815
+ api_key=gapgpt_api_key,
816
+ api_base=GAPGPT_BASE_URL,
817
+ )
818
+
819
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
820
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
821
+ embed_model = OpenAIEmbedding(
822
+ api_key=gapgpt_api_key,
823
+ api_base=GAPGPT_BASE_URL,
824
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
825
+ )
826
+
827
+ # اعمال تنظیمات سراسری
828
+ Settings.llm = llm
829
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
830
+
831
+ Settings.prompt_helper = PromptHelper(
832
+ context_window=4096,
833
+ num_output=256,
834
+ chunk_overlap_ratio=20 / 4096,
835
+ tokenizer=tokenizer,
836
+ )
837
+
838
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
839
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
840
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
841
+ if 'api_keys' not in locals():
842
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
843
+
844
+ demo = create_gradio_interface(Settings, api_keys)
845
+ demo.launch(
846
+ server_name="127.0.0.1",
847
+ server_port=7860,
848
+ share=True
849
+ )
850
+
851
+
852
+ if __name__ == "__main__":
853
+ signal.signal(signal.SIGINT, signal_handler)
854
+ main()
Backup code/app_V7.py ADDED
@@ -0,0 +1,901 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ ):
332
+ chatgpt_cfg = {
333
+ "model": "gpt-4o",
334
+ "temperature": temperature,
335
+ "max_tokens": max_length_tokens,
336
+ "top_p": top_p,
337
+ "frequency_penalty": 0.4,
338
+ "presence_penalty": 0.2,
339
+ "n": 1,
340
+ }
341
+
342
+ if text == "":
343
+ # Return same history if empty input
344
+ return history, history, "Empty context."
345
+
346
+ # Ensure history is initialized
347
+ if history is None:
348
+ history = []
349
+
350
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
351
+ history=history,
352
+ query=text, # Changed name to match prompt_utils
353
+ user_memory=user_memory,
354
+ user_name=user_name,
355
+ user_memory_index=user_memory_index,
356
+ service_context=service_context,
357
+ api_keys=api_keys,
358
+ api_index=api_index,
359
+ meta_prompt=meta_prompt,
360
+ new_user_meta_prompt=new_user_meta_prompt,
361
+ data_args=data_args,
362
+ boot_actual_name=boot_actual_name,
363
+ semantic_memory_text=semantic_memory_text,
364
+ query_category=query_category,
365
+ meta_prompt_semantic=meta_prompt_semantic,
366
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
367
+ )
368
+
369
+ # Handle context window slicing manually if needed,
370
+ # though usually OpenAI manages this, or we slice the list of dicts.
371
+ current_history_for_llm = history
372
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
373
+ current_history_for_llm = history[-(data_args.max_history * 2):]
374
+
375
+ response = chatgpt_chat(
376
+ prompt=text,
377
+ system=system_prompt,
378
+ history=current_history_for_llm,
379
+ gpt_config=chatgpt_cfg,
380
+ api_index=api_index,
381
+ )
382
+
383
+ torch.cuda.empty_cache()
384
+
385
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
386
+ new_history = history + [
387
+ {"role": "user", "content": text},
388
+ {"role": "assistant", "content": response}
389
+ ]
390
+
391
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
392
+ # OR we convert strictly for saving if your legacy code needs it.
393
+ # For now, assuming we pass the object as is or convert for save)
394
+ if user_name:
395
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
396
+ # or pass a converted version. Let's try passing the new format.
397
+ save_local_memory(memory, new_history, user_name, data_args)
398
+
399
+ # Return: (Chatbot View, State History, Textbox Reset)
400
+ return new_history, new_history, "Generating..."
401
+
402
+
403
+
404
+ def create_gradio_interface(service_context, api_keys):
405
+ with gr.Blocks(title="EMMA") as demo:
406
+
407
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
408
+ gr.HTML("""
409
+ <style>
410
+ .center-content {
411
+ display: flex;
412
+ flex-direction: column;
413
+ align-items: center;
414
+ justify-content: center;
415
+ }
416
+ /* -- استایل‌های فرم ورود -- */
417
+ .login-box {
418
+ max-width: 400px !important;
419
+ margin: 0 auto !important;
420
+ width: 100% !important;
421
+ }
422
+ .login-btn, .login-btn:hover {
423
+ background-color: #3498db !important;
424
+ background-image: none !important;
425
+ color: white !important;
426
+ border: none !important;
427
+ }
428
+ /* -- استایل‌های محیط چت -- */
429
+ .chat-box {
430
+ max-width: 800px !important;
431
+ margin: 0 auto !important;
432
+ width: 100% !important;
433
+ }
434
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
435
+ .mobile-button, .mobile-button:hover {
436
+ background-color: #3498db !important;
437
+ background-image: none !important;
438
+ color: white !important;
439
+ border: none !important;
440
+ }
441
+ .gr-textbox textarea {
442
+ font-size: 16px;
443
+ }
444
+ .gr-chatbot {
445
+ font-size: 15px;
446
+ }
447
+
448
+ /* --- انیمیشن کشویی لاگین --- */
449
+ .slide-up {
450
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
451
+ }
452
+
453
+ @keyframes slideUpAnimation {
454
+ 0% {
455
+ transform: translateY(0);
456
+ opacity: 1;
457
+ max-height: 1000px;
458
+ }
459
+ 100% {
460
+ transform: translateY(-100%);
461
+ opacity: 0;
462
+ max-height: 0px;
463
+ overflow: hidden;
464
+ margin: 0 !important;
465
+ padding: 0 !important;
466
+ border: none !important;
467
+ }
468
+ }
469
+ </style>
470
+ """)
471
+
472
+ state = gr.State({
473
+ "history": [],
474
+ "user_name": None,
475
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
476
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
477
+ "service_context": service_context,
478
+ "api_keys": api_keys,
479
+ "api_index": 0,
480
+ "semantic_memory_text": "",
481
+ "new_conversation": True,
482
+ "initialized": False
483
+ })
484
+
485
+ # ==========================================
486
+ # 1. LOGIN PAGE
487
+ # ==========================================
488
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
489
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
490
+
491
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
492
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
493
+ login_status = gr.Textbox(visible=False, label="Status")
494
+
495
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
496
+
497
+ with gr.Column(visible=False) as registration_fields:
498
+ gr.Markdown("### ✨ New User Registration")
499
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
500
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
501
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
502
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
503
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
504
+
505
+ # ==========================================
506
+ # 2. CHAT PAGE
507
+ # ==========================================
508
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
509
+ with gr.Column(elem_classes=["chat-box"]):
510
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
511
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
512
+
513
+ with gr.Group():
514
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
515
+
516
+ with gr.Row():
517
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
518
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
519
+
520
+ with gr.Row(equal_height=True):
521
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
522
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
523
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
524
+
525
+ # -------------------------------------------------------
526
+ # Internal Functions
527
+ # -------------------------------------------------------
528
+ def handle_login_check(name, state):
529
+ if not name.strip():
530
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
531
+
532
+ if name in memory:
533
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
534
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
535
+
536
+ new_state = state.copy()
537
+ new_state["user_name"] = name
538
+ new_state["memory"] = memory
539
+ new_state["initialized"] = True
540
+ new_state["semantic_memory_text"] = semantic_memory
541
+ new_state["history"] = []
542
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
543
+
544
+
545
+
546
+
547
+
548
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
549
+
550
+ return (
551
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
552
+ gr.update(visible=False),
553
+ gr.update(visible=True),
554
+ gr.update(visible=False, value=""),
555
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
556
+ gr.update(value=welcome_msg),
557
+ new_state
558
+ )
559
+ else:
560
+ return (
561
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
562
+ gr.update(visible=True),
563
+ gr.update(visible=False),
564
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
565
+ gr.update(),
566
+ gr.update(),
567
+ state
568
+ )
569
+
570
+ def handle_register(name, age, gender, occupation, residence, state):
571
+ name = str(name).strip()
572
+
573
+ if not name:
574
+ raise gr.Error("Please enter a valid user name.")
575
+
576
+ # Registration is only for new users.
577
+ if name in memory:
578
+ raise gr.Error(
579
+ f"User '{name}' already exists. Please use the login form."
580
+ )
581
+
582
+ # Create the user before trying to build or load their indices.
583
+ memory[name] = {
584
+ "profile": {
585
+ "age": age,
586
+ "gender": gender,
587
+ "occupation": occupation,
588
+ "residence": residence,
589
+ },
590
+ "sessions": [],
591
+ "episodic_memory": [],
592
+ "semantic_memory": {},
593
+ }
594
+
595
+ try:
596
+ (
597
+ _,
598
+ user_memory,
599
+ sessions_memory,
600
+ episodic_memory,
601
+ semantic_memory,
602
+ ) = enter_name_llamaindex(
603
+ name=name,
604
+ memory=memory,
605
+ data_args=data_args,
606
+ update_memory_index=True,
607
+ )
608
+ except Exception:
609
+ # Avoid leaving a partially registered user in memory.
610
+ memory.pop(name, None)
611
+ raise
612
+
613
+ new_state = dict(state or {})
614
+ new_state.update(
615
+ {
616
+ "user_name": name,
617
+ "memory": memory,
618
+ "initialized": True,
619
+ "history": [],
620
+ "semantic_memory_text": semantic_memory,
621
+ "user_memory_index": sessions_memory,
622
+ "episodic_memory_index": episodic_memory,
623
+ "semantic_memory_index": semantic_memory,
624
+ }
625
+ )
626
+
627
+ welcome_msg = f"Welcome {name}! Registration complete."
628
+
629
+ return (
630
+ gr.update(
631
+ elem_classes=["center-content", "slide-up"]
632
+ ),
633
+ gr.update(visible=False),
634
+ gr.update(visible=True),
635
+ gr.update(visible=False, value=""),
636
+ gr.update(
637
+ value=(
638
+ "<h2 style='text-align: center; color: #333;'>"
639
+ f"🧠 EMMA: Session for {name}</h2>"
640
+ )
641
+ ),
642
+ gr.update(value=welcome_msg),
643
+ new_state,
644
+ )
645
+
646
+ def switch_user(state):
647
+ if state["initialized"] and state["user_name"] in state["memory"]:
648
+ if state["memory"][state["user_name"]]["sessions"]:
649
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
650
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
651
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
652
+ # ==========================================
653
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
654
+ # ==========================================
655
+ try:
656
+ user_mem = state["memory"][state["user_name"]]
657
+ existing_semantic = user_mem.get("semantic_memory", {})
658
+
659
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
660
+
661
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
662
+ except Exception as e:
663
+ print(f"Error updating semantic memory on logout: {e}")
664
+ # ==========================================
665
+
666
+ new_state = state.copy()
667
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
668
+
669
+ return (
670
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
671
+ gr.update(visible=False),
672
+ gr.update(visible=False),
673
+ gr.update(value="Logged out successfully.", visible=True),
674
+ gr.update(value=""),
675
+ new_state,
676
+ gr.update(value=[])
677
+ )
678
+
679
+ def handle_chat(user_message, state):
680
+ if not user_message.strip():
681
+ print("[handle_chat] empty message")
682
+ print("[handle_chat] state =", state)
683
+ return gr.update(), state.get("history", []), state
684
+
685
+ print("[handle_chat] user_message =", repr(user_message))
686
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
687
+ print("[handle_chat] user_name =", state.get("user_name"))
688
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
689
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
690
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
691
+ print("[handle_chat] api_index =", state.get("api_index", 0))
692
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
693
+ print("[handle_chat] history len =", len(state.get("history", [])))
694
+
695
+ user_name = state.get("user_name")
696
+ user_memory_index = state.get("user_memory_index")
697
+ user_memory = state.get("memory")
698
+ service_context = state.get("service_context")
699
+ api_index = state.get("api_index", 0)
700
+ semantic_memory_text = state.get("semantic_memory_text", "")
701
+
702
+ query_category = classify_query_local(user_message)
703
+ print("[handle_chat] query_category =", query_category)
704
+
705
+ new_history, _, status_msg = predict_new(
706
+ text=user_message,
707
+ history=state.get("history", []),
708
+ top_p=0.95,
709
+ temperature=1.0,
710
+ max_length_tokens=1024,
711
+ max_context_length_tokens=4096,
712
+ user_name=user_name,
713
+ user_memory=user_memory,
714
+ user_memory_index=user_memory_index,
715
+ service_context=service_context,
716
+ api_index=api_index,
717
+ semantic_memory_text=semantic_memory_text,
718
+ query_category=query_category
719
+ )
720
+
721
+ print("[handle_chat] status_msg =", status_msg)
722
+ print("[handle_chat] new_history len =", len(new_history))
723
+
724
+ state["history"] = new_history
725
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
726
+
727
+ return "", new_history, state
728
+
729
+ def clear_history(state):
730
+ state["history"] = []
731
+ return [], state
732
+
733
+ def handle_new_session(state):
734
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
735
+ user_name = state.get("user_name")
736
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
737
+ print("Error: User not logged in or memory missing.")
738
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
739
+ return [], state
740
+
741
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
742
+ user_data = state["memory"][user_name]
743
+
744
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
745
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
746
+ last_session = user_data["sessions"][-1]
747
+
748
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
749
+ if len(last_session.get("conversation", [])) > 0:
750
+ session_date = last_session.get("date", "")
751
+ session_id = last_session.get("session_id", 0)
752
+
753
+ # پاس دادن هر ۳ آرگومان به تابع
754
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
755
+
756
+ if "episodic_memory" not in user_data:
757
+ user_data["episodic_memory"] = []
758
+ user_data["episodic_memory"].append(ep_summary)
759
+
760
+ # ==========================================
761
+ # به‌روزرسانی حافظه سمانتیک
762
+ # ==========================================
763
+ try:
764
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
765
+ existing_semantic = user_data.get("semantic_memory", {})
766
+
767
+ # فراخوانی تابع با هر دو آرگومان
768
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
769
+
770
+ # ذخیره دیتای جدید
771
+ user_data["semantic_memory"] = updated_semantic
772
+ except Exception as e:
773
+ print(f"Error updating semantic memory: {e}")
774
+ # ==========================================
775
+
776
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
777
+ new_session_id = len(user_data.get("sessions", []))
778
+
779
+ new_session = {
780
+ "session_id": new_session_id,
781
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
782
+ "conversation": []
783
+ }
784
+
785
+ if "sessions" not in user_data:
786
+ user_data["sessions"] = []
787
+
788
+ user_data["sessions"].append(new_session)
789
+
790
+ # پاک کردن تاریخچه چت در state
791
+ state["history"] = []
792
+
793
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
794
+ return [], state
795
+
796
+ check_user_btn.click(
797
+ handle_login_check,
798
+ inputs=[username_input, state],
799
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
800
+ )
801
+
802
+ register_btn.click(
803
+ handle_register,
804
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
805
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
806
+ )
807
+
808
+ switch_user_btn.click(
809
+ switch_user,
810
+ inputs=[state],
811
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
812
+ )
813
+
814
+ submit_btn.click(
815
+ handle_chat,
816
+ inputs=[user_input, state],
817
+ outputs=[user_input, chatbot, state]
818
+ )
819
+
820
+ user_input.submit(
821
+ handle_chat,
822
+ inputs=[user_input, state],
823
+ outputs=[user_input, chatbot, state]
824
+ )
825
+
826
+ clear_btn.click(
827
+ clear_history,
828
+ inputs=[state],
829
+ outputs=[chatbot, state]
830
+ )
831
+
832
+ # تغییر از clear_history به handle_new_session
833
+ new_session_btn.click(
834
+ handle_new_session,
835
+ inputs=[state],
836
+ outputs=[chatbot, state]
837
+
838
+
839
+ )
840
+
841
+ return demo
842
+
843
+
844
+ def main():
845
+ """Main function to initialize and launch the interface."""
846
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
847
+
848
+ if not gapgpt_api_key:
849
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
850
+ else:
851
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
852
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
853
+
854
+ # تنظیم LLM (مدل زبانی)
855
+ llm = LlamaIndexOpenAI(
856
+ model="gpt-4o",
857
+ temperature=1,
858
+ max_tokens=1024,
859
+ top_p=0.95,
860
+ frequency_penalty=0.4,
861
+ presence_penalty=0.2,
862
+ api_key=gapgpt_api_key,
863
+ api_base=GAPGPT_BASE_URL,
864
+ )
865
+
866
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
867
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
868
+ embed_model = OpenAIEmbedding(
869
+ api_key=gapgpt_api_key,
870
+ api_base=GAPGPT_BASE_URL,
871
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
872
+ )
873
+
874
+ # اعمال تنظیمات سراسری
875
+ Settings.llm = llm
876
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
877
+
878
+ Settings.prompt_helper = PromptHelper(
879
+ context_window=4096,
880
+ num_output=256,
881
+ chunk_overlap_ratio=20 / 4096,
882
+ tokenizer=tokenizer,
883
+ )
884
+
885
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
886
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
887
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
888
+ if 'api_keys' not in locals():
889
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
890
+
891
+ demo = create_gradio_interface(Settings, api_keys)
892
+ demo.launch(
893
+ server_name="127.0.0.1",
894
+ server_port=7860,
895
+ share=True
896
+ )
897
+
898
+
899
+ if __name__ == "__main__":
900
+ signal.signal(signal.SIGINT, signal_handler)
901
+ main()
Backup code/app_V8.py ADDED
@@ -0,0 +1,907 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+
332
+
333
+ ):
334
+ chatgpt_cfg = {
335
+ "model": "gpt-4o",
336
+ "temperature": temperature,
337
+ "max_tokens": max_length_tokens,
338
+ "top_p": top_p,
339
+ "frequency_penalty": 0.4,
340
+ "presence_penalty": 0.2,
341
+ "n": 1,
342
+ }
343
+
344
+ if text == "":
345
+ # Return same history if empty input
346
+ return history, history, "Empty context."
347
+
348
+ # Ensure history is initialized
349
+ if history is None:
350
+ history = []
351
+
352
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
353
+ history=history,
354
+ query=text, # Changed name to match prompt_utils
355
+ user_memory=user_memory,
356
+ user_name=user_name,
357
+ user_memory_index=user_memory_index,
358
+ service_context=service_context,
359
+ api_keys=api_keys,
360
+ api_index=api_index,
361
+ meta_prompt=meta_prompt,
362
+ new_user_meta_prompt=new_user_meta_prompt,
363
+ data_args=data_args,
364
+ boot_actual_name=boot_actual_name,
365
+ semantic_memory_text=semantic_memory_text,
366
+ query_category=query_category,
367
+ meta_prompt_semantic=meta_prompt_semantic,
368
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
369
+ )
370
+
371
+ # Handle context window slicing manually if needed,
372
+ # though usually OpenAI manages this, or we slice the list of dicts.
373
+ current_history_for_llm = history
374
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
375
+ current_history_for_llm = history[-(data_args.max_history * 2):]
376
+
377
+ response = chatgpt_chat(
378
+ prompt=text,
379
+ system=system_prompt,
380
+ history=current_history_for_llm,
381
+ gpt_config=chatgpt_cfg,
382
+ api_index=api_index,
383
+ )
384
+
385
+ torch.cuda.empty_cache()
386
+
387
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
388
+ new_history = history + [
389
+ {"role": "user", "content": text},
390
+ {"role": "assistant", "content": response}
391
+ ]
392
+
393
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
394
+ # OR we convert strictly for saving if your legacy code needs it.
395
+ # For now, assuming we pass the object as is or convert for save)
396
+ if user_name:
397
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
398
+ # or pass a converted version. Let's try passing the new format.
399
+ save_local_memory(memory, new_history, user_name, data_args)
400
+
401
+ # Return: (Chatbot View, State History, Textbox Reset)
402
+ return new_history, new_history, "Generating..."
403
+
404
+
405
+
406
+ def create_gradio_interface(service_context, api_keys):
407
+ with gr.Blocks(title="EMMA") as demo:
408
+
409
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
410
+ gr.HTML("""
411
+ <style>
412
+ .center-content {
413
+ display: flex;
414
+ flex-direction: column;
415
+ align-items: center;
416
+ justify-content: center;
417
+ }
418
+ /* -- استایل‌های فرم ورود -- */
419
+ .login-box {
420
+ max-width: 400px !important;
421
+ margin: 0 auto !important;
422
+ width: 100% !important;
423
+ }
424
+ .login-btn, .login-btn:hover {
425
+ background-color: #3498db !important;
426
+ background-image: none !important;
427
+ color: white !important;
428
+ border: none !important;
429
+ }
430
+ /* -- استایل‌های محیط چت -- */
431
+ .chat-box {
432
+ max-width: 800px !important;
433
+ margin: 0 auto !important;
434
+ width: 100% !important;
435
+ }
436
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
437
+ .mobile-button, .mobile-button:hover {
438
+ background-color: #3498db !important;
439
+ background-image: none !important;
440
+ color: white !important;
441
+ border: none !important;
442
+ }
443
+ .gr-textbox textarea {
444
+ font-size: 16px;
445
+ }
446
+ .gr-chatbot {
447
+ font-size: 15px;
448
+ }
449
+
450
+ /* --- انیمیشن کشویی لاگین --- */
451
+ .slide-up {
452
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
453
+ }
454
+
455
+ @keyframes slideUpAnimation {
456
+ 0% {
457
+ transform: translateY(0);
458
+ opacity: 1;
459
+ max-height: 1000px;
460
+ }
461
+ 100% {
462
+ transform: translateY(-100%);
463
+ opacity: 0;
464
+ max-height: 0px;
465
+ overflow: hidden;
466
+ margin: 0 !important;
467
+ padding: 0 !important;
468
+ border: none !important;
469
+ }
470
+ }
471
+ </style>
472
+ """)
473
+
474
+ state = gr.State({
475
+ "history": [],
476
+ "user_name": None,
477
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
478
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
479
+ "service_context": service_context,
480
+ "api_keys": api_keys,
481
+ "api_index": 0,
482
+ "semantic_memory_text": "",
483
+ "new_conversation": True,
484
+ "initialized": False
485
+ })
486
+
487
+ # ==========================================
488
+ # 1. LOGIN PAGE
489
+ # ==========================================
490
+ with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
491
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
492
+
493
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
494
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
495
+ login_status = gr.Textbox(visible=False, label="Status")
496
+
497
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
498
+
499
+ with gr.Column(visible=False) as registration_fields:
500
+ gr.Markdown("### ✨ New User Registration")
501
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
502
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
503
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
504
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
505
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
506
+
507
+ # ==========================================
508
+ # 2. CHAT PAGE
509
+ # ==========================================
510
+ with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
511
+ with gr.Column(elem_classes=["chat-box"]):
512
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
513
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
514
+
515
+ with gr.Group():
516
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
517
+
518
+ with gr.Row():
519
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
520
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
521
+
522
+ with gr.Row(equal_height=True):
523
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
524
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
525
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
526
+
527
+ # -------------------------------------------------------
528
+ # Internal Functions
529
+ # -------------------------------------------------------
530
+ def handle_login_check(name, state):
531
+ if not name.strip():
532
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
533
+
534
+ if name in memory:
535
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
536
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
537
+
538
+ new_state = state.copy()
539
+ new_state["user_name"] = name
540
+ new_state["memory"] = memory
541
+ new_state["initialized"] = True
542
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
543
+ new_state["semantic_memory_index"] = semantic_memory
544
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
545
+ new_state["episodic_memory_index"] = episodic_memory
546
+ new_state["history"] = []
547
+
548
+
549
+
550
+
551
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
552
+
553
+ return (
554
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
555
+ gr.update(visible=False),
556
+ gr.update(visible=True),
557
+ gr.update(visible=False, value=""),
558
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
559
+ gr.update(value=welcome_msg),
560
+ new_state
561
+ )
562
+ else:
563
+ return (
564
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
565
+ gr.update(visible=True),
566
+ gr.update(visible=False),
567
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
568
+ gr.update(),
569
+ gr.update(),
570
+ state
571
+ )
572
+
573
+ def handle_register(name, age, gender, occupation, residence, state):
574
+ name = str(name).strip()
575
+
576
+ if not name:
577
+ raise gr.Error("Please enter a valid user name.")
578
+
579
+ # Registration is only for new users.
580
+ if name in memory:
581
+ raise gr.Error(
582
+ f"User '{name}' already exists. Please use the login form."
583
+ )
584
+
585
+ # Create the user before trying to build or load their indices.
586
+ memory[name] = {
587
+ "profile": {
588
+ "age": age,
589
+ "gender": gender,
590
+ "occupation": occupation,
591
+ "residence": residence,
592
+ },
593
+ "sessions": [],
594
+ "episodic_memory": [],
595
+ "semantic_memory": {},
596
+ }
597
+
598
+ try:
599
+ (
600
+ _,
601
+ user_memory,
602
+ sessions_memory,
603
+ episodic_memory,
604
+ semantic_memory,
605
+ ) = enter_name_llamaindex(
606
+ name=name,
607
+ memory=memory,
608
+ data_args=data_args,
609
+ update_memory_index=True,
610
+ )
611
+ except Exception:
612
+ # Avoid leaving a partially registered user in memory.
613
+ memory.pop(name, None)
614
+ raise
615
+
616
+ new_state = dict(state or {})
617
+ new_state.update(
618
+ {
619
+ "user_name": name,
620
+ "memory": memory,
621
+ "initialized": True,
622
+ "history": [],
623
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
624
+ "user_memory_index": sessions_memory,
625
+ "episodic_memory_index": episodic_memory,
626
+ "semantic_memory_index": semantic_memory,
627
+ }
628
+ )
629
+
630
+ welcome_msg = f"Welcome {name}! Registration complete."
631
+
632
+ return (
633
+ gr.update(
634
+ elem_classes=["center-content", "slide-up"]
635
+ ),
636
+ gr.update(visible=False),
637
+ gr.update(visible=True),
638
+ gr.update(visible=False, value=""),
639
+ gr.update(
640
+ value=(
641
+ "<h2 style='text-align: center; color: #333;'>"
642
+ f"🧠 EMMA: Session for {name}</h2>"
643
+ )
644
+ ),
645
+ gr.update(value=welcome_msg),
646
+ new_state,
647
+ )
648
+
649
+ def switch_user(state):
650
+ if state["initialized"] and state["user_name"] in state["memory"]:
651
+ if state["memory"][state["user_name"]]["sessions"]:
652
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
653
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
654
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
655
+ # ==========================================
656
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
657
+ # ==========================================
658
+ try:
659
+ user_mem = state["memory"][state["user_name"]]
660
+ existing_semantic = user_mem.get("semantic_memory", {})
661
+
662
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
663
+
664
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
665
+ except Exception as e:
666
+ print(f"Error updating semantic memory on logout: {e}")
667
+ # ==========================================
668
+
669
+ new_state = state.copy()
670
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
671
+
672
+ return (
673
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
674
+ gr.update(visible=False),
675
+ gr.update(visible=False),
676
+ gr.update(value="Logged out successfully.", visible=True),
677
+ gr.update(value=""),
678
+ new_state,
679
+ gr.update(value=[])
680
+ )
681
+
682
+ def handle_chat(user_message, state):
683
+ if not user_message.strip():
684
+ print("[handle_chat] empty message")
685
+ print("[handle_chat] state =", state)
686
+ return gr.update(), state.get("history", []), state
687
+
688
+ print("[handle_chat] user_message =", repr(user_message))
689
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
690
+ print("[handle_chat] user_name =", state.get("user_name"))
691
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
692
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
693
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
694
+ print("[handle_chat] api_index =", state.get("api_index", 0))
695
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
696
+ print("[handle_chat] history len =", len(state.get("history", [])))
697
+
698
+ user_name = state.get("user_name")
699
+ user_memory_index = state.get("user_memory_index")
700
+ user_memory = state.get("user_memory", {})
701
+ user_memory_index = state.get("user_memory_index")
702
+ semantic_memory_text = state.get("semantic_memory_text", {})
703
+ service_context = state.get("service_context")
704
+ api_index = state.get("api_index", 0)
705
+ semantic_memory_text = state.get("semantic_memory_text", "")
706
+
707
+ query_category = classify_query_local(user_message)
708
+ print("[handle_chat] query_category =", query_category)
709
+
710
+ new_history, _, status_msg = predict_new(
711
+ text=user_message,
712
+ history=state.get("history", []),
713
+ top_p=0.95,
714
+ temperature=1.0,
715
+ max_length_tokens=1024,
716
+ max_context_length_tokens=4096,
717
+ user_name=user_name,
718
+ user_memory=user_memory,
719
+ user_memory_index=user_memory_index,
720
+ service_context=service_context,
721
+ api_index=api_index,
722
+ semantic_memory_text=semantic_memory_text,
723
+ query_category=query_category,
724
+
725
+ )
726
+
727
+ print("[handle_chat] status_msg =", status_msg)
728
+ print("[handle_chat] new_history len =", len(new_history))
729
+
730
+ state["history"] = new_history
731
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
732
+
733
+ return "", new_history, state
734
+
735
+ def clear_history(state):
736
+ state["history"] = []
737
+ return [], state
738
+
739
+ def handle_new_session(state):
740
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
741
+ user_name = state.get("user_name")
742
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
743
+ print("Error: User not logged in or memory missing.")
744
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
745
+ return [], state
746
+
747
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
748
+ user_data = state["memory"][user_name]
749
+
750
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
751
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
752
+ last_session = user_data["sessions"][-1]
753
+
754
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
755
+ if len(last_session.get("conversation", [])) > 0:
756
+ session_date = last_session.get("date", "")
757
+ session_id = last_session.get("session_id", 0)
758
+
759
+ # پاس دادن هر ۳ آرگومان به تابع
760
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
761
+
762
+ if "episodic_memory" not in user_data:
763
+ user_data["episodic_memory"] = []
764
+ user_data["episodic_memory"].append(ep_summary)
765
+
766
+ # ==========================================
767
+ # به‌روزرسانی حافظه سمانتیک
768
+ # ==========================================
769
+ try:
770
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
771
+ existing_semantic = user_data.get("semantic_memory", {})
772
+
773
+ # فراخوانی تابع با هر دو آرگومان
774
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
775
+
776
+ # ذخیره دیتای جدید
777
+ user_data["semantic_memory"] = updated_semantic
778
+ except Exception as e:
779
+ print(f"Error updating semantic memory: {e}")
780
+ # ==========================================
781
+
782
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
783
+ new_session_id = len(user_data.get("sessions", []))
784
+
785
+ new_session = {
786
+ "session_id": new_session_id,
787
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
788
+ "conversation": []
789
+ }
790
+
791
+ if "sessions" not in user_data:
792
+ user_data["sessions"] = []
793
+
794
+ user_data["sessions"].append(new_session)
795
+
796
+ # پاک کردن تاریخچه چت در state
797
+ state["history"] = []
798
+
799
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
800
+ return [], state
801
+
802
+ check_user_btn.click(
803
+ handle_login_check,
804
+ inputs=[username_input, state],
805
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
806
+ )
807
+
808
+ register_btn.click(
809
+ handle_register,
810
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
811
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
812
+ )
813
+
814
+ switch_user_btn.click(
815
+ switch_user,
816
+ inputs=[state],
817
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
818
+ )
819
+
820
+ submit_btn.click(
821
+ handle_chat,
822
+ inputs=[user_input, state],
823
+ outputs=[user_input, chatbot, state]
824
+ )
825
+
826
+ user_input.submit(
827
+ handle_chat,
828
+ inputs=[user_input, state],
829
+ outputs=[user_input, chatbot, state]
830
+ )
831
+
832
+ clear_btn.click(
833
+ clear_history,
834
+ inputs=[state],
835
+ outputs=[chatbot, state]
836
+ )
837
+
838
+ # تغییر از clear_history به handle_new_session
839
+ new_session_btn.click(
840
+ handle_new_session,
841
+ inputs=[state],
842
+ outputs=[chatbot, state]
843
+
844
+
845
+ )
846
+
847
+ return demo
848
+
849
+
850
+ def main():
851
+ """Main function to initialize and launch the interface."""
852
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
853
+
854
+ if not gapgpt_api_key:
855
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
856
+ else:
857
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
858
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
859
+
860
+ # تنظیم LLM (مدل زبانی)
861
+ llm = LlamaIndexOpenAI(
862
+ model="gpt-4o",
863
+ temperature=1,
864
+ max_tokens=1024,
865
+ top_p=0.95,
866
+ frequency_penalty=0.4,
867
+ presence_penalty=0.2,
868
+ api_key=gapgpt_api_key,
869
+ api_base=GAPGPT_BASE_URL,
870
+ )
871
+
872
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
873
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
874
+ embed_model = OpenAIEmbedding(
875
+ api_key=gapgpt_api_key,
876
+ api_base=GAPGPT_BASE_URL,
877
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
878
+ )
879
+
880
+ # اعمال تنظیمات سراسری
881
+ Settings.llm = llm
882
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
883
+
884
+ Settings.prompt_helper = PromptHelper(
885
+ context_window=4096,
886
+ num_output=256,
887
+ chunk_overlap_ratio=20 / 4096,
888
+ tokenizer=tokenizer,
889
+ )
890
+
891
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
892
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
893
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
894
+ if 'api_keys' not in locals():
895
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
896
+
897
+ demo = create_gradio_interface(Settings, api_keys)
898
+ demo.launch(
899
+ server_name="127.0.0.1",
900
+ server_port=7860,
901
+ share=True
902
+ )
903
+
904
+
905
+ if __name__ == "__main__":
906
+ signal.signal(signal.SIGINT, signal_handler)
907
+ main()
Backup code/app_V9.py ADDED
@@ -0,0 +1,934 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+
332
+
333
+ ):
334
+ chatgpt_cfg = {
335
+ "model": "gpt-4o",
336
+ "temperature": temperature,
337
+ "max_tokens": max_length_tokens,
338
+ "top_p": top_p,
339
+ "frequency_penalty": 0.4,
340
+ "presence_penalty": 0.2,
341
+ "n": 1,
342
+ }
343
+
344
+ if text == "":
345
+ # Return same history if empty input
346
+ return history, history, "Empty context."
347
+
348
+ # Ensure history is initialized
349
+ if history is None:
350
+ history = []
351
+
352
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
353
+ history=history,
354
+ query=text, # Changed name to match prompt_utils
355
+ user_memory=user_memory,
356
+ user_name=user_name,
357
+ user_memory_index=user_memory_index,
358
+ service_context=service_context,
359
+ api_keys=api_keys,
360
+ api_index=api_index,
361
+ meta_prompt=meta_prompt,
362
+ new_user_meta_prompt=new_user_meta_prompt,
363
+ data_args=data_args,
364
+ boot_actual_name=boot_actual_name,
365
+ semantic_memory_text=semantic_memory_text,
366
+ query_category=query_category,
367
+ meta_prompt_semantic=meta_prompt_semantic,
368
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
369
+ )
370
+
371
+ # Handle context window slicing manually if needed,
372
+ # though usually OpenAI manages this, or we slice the list of dicts.
373
+ current_history_for_llm = history
374
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
375
+ current_history_for_llm = history[-(data_args.max_history * 2):]
376
+
377
+ response = chatgpt_chat(
378
+ prompt=text,
379
+ system=system_prompt,
380
+ history=current_history_for_llm,
381
+ gpt_config=chatgpt_cfg,
382
+ api_index=api_index,
383
+ )
384
+
385
+ torch.cuda.empty_cache()
386
+
387
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
388
+ new_history = history + [
389
+ {"role": "user", "content": text},
390
+ {"role": "assistant", "content": response}
391
+ ]
392
+
393
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
394
+ # OR we convert strictly for saving if your legacy code needs it.
395
+ # For now, assuming we pass the object as is or convert for save)
396
+ if user_name:
397
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
398
+ # or pass a converted version. Let's try passing the new format.
399
+ save_local_memory(memory, new_history, user_name, data_args)
400
+
401
+ # Return: (Chatbot View, State History, Textbox Reset)
402
+ return new_history, new_history, "Generating..."
403
+
404
+
405
+
406
+ def create_gradio_interface(service_context, api_keys):
407
+ with gr.Blocks(title="EMMA") as demo:
408
+
409
+ # 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
410
+ gr.HTML("""
411
+ <style>
412
+ .center-content {
413
+ display: flex;
414
+ flex-direction: column;
415
+ align-items: center;
416
+ justify-content: center;
417
+ }
418
+ /* -- استایل‌های فرم ورود -- */
419
+ .login-box {
420
+ max-width: 400px !important;
421
+ margin: 0 auto !important;
422
+ width: 100% !important;
423
+ }
424
+ .login-btn, .login-btn:hover {
425
+ background-color: #3498db !important;
426
+ background-image: none !important;
427
+ color: white !important;
428
+ border: none !important;
429
+ }
430
+ /* -- استایل‌های محیط چت -- */
431
+ .chat-box {
432
+ max-width: 800px !important;
433
+ margin: 0 auto !important;
434
+ width: 100% !important;
435
+ }
436
+ /* -- دکمه‌های محیط چت (آبی رنگ) -- */
437
+ .mobile-button, .mobile-button:hover {
438
+ background-color: #3498db !important;
439
+ background-image: none !important;
440
+ color: white !important;
441
+ border: none !important;
442
+ }
443
+ .gr-textbox textarea {
444
+ font-size: 16px;
445
+ }
446
+ .gr-chatbot {
447
+ font-size: 15px;
448
+ }
449
+
450
+ /* --- انیمیشن کشویی لاگین --- */
451
+ .slide-up {
452
+ animation: slideUpAnimation 0.8s ease-in-out forwards !important;
453
+ }
454
+
455
+ @keyframes slideUpAnimation {
456
+ 0% {
457
+ transform: translateY(0);
458
+ opacity: 1;
459
+ max-height: 1000px;
460
+ }
461
+ 100% {
462
+ transform: translateY(-100%);
463
+ opacity: 0;
464
+ max-height: 0px;
465
+ overflow: hidden;
466
+ margin: 0 !important;
467
+ padding: 0 !important;
468
+ border: none !important;
469
+ }
470
+ }
471
+ </style>
472
+ """)
473
+
474
+ state = gr.State({
475
+ "history": [],
476
+ "user_name": None,
477
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
478
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
479
+ "service_context": service_context,
480
+ "api_keys": api_keys,
481
+ "api_index": 0,
482
+ "semantic_memory_text": "",
483
+ "new_conversation": True,
484
+ "initialized": False
485
+ })
486
+
487
+
488
+
489
+ # تابعی برای مدیریت کلیک دکمه ثبت نام
490
+ def handle_registration():
491
+ # کدهای مربوط به ذخیره کاربر در دیتابیس را اینجا قرار می‌دهید
492
+ # سپس پنل ثبت‌نام را مخفی می‌کنیم و یک پیام به سیستم می‌فرستیم
493
+ return gr.update(visible=False), "Registration successful!"
494
+
495
+ with gr.Blocks() as demo:
496
+ with gr.Row():
497
+
498
+ # ==========================================
499
+ # 1. LOGIN PAGE (ستون سمت چپ)
500
+ # ==========================================
501
+ with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]) as login_page:
502
+
503
+ # استفاده از Accordion برای ایجاد حالت کشویی
504
+ with gr.Accordion("🔐 Login & Registration Menu", open=True) as login_accordion:
505
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
506
+
507
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
508
+ login_status = gr.Textbox(visible=False, label="Status")
509
+
510
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
511
+
512
+ with gr.Column(visible=False) as registration_fields:
513
+ gr.Markdown("### ✨ New User Registration")
514
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
515
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
516
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
517
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
518
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
519
+
520
+ # ==========================================
521
+ # 2. CHAT PAGE (ستون سمت راست)
522
+ # ==========================================
523
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
524
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
525
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
526
+
527
+ with gr.Group():
528
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
529
+
530
+ with gr.Row():
531
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
532
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
533
+
534
+ with gr.Row(equal_height=True):
535
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
536
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
537
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
538
+
539
+ # ==========================================
540
+ # رویدادها (Events)
541
+ # ==========================================
542
+
543
+ # 1. محو کردن بخش ثبت نام بعد از کلیک
544
+ register_btn.click(
545
+ fn=handle_registration,
546
+ inputs=[], # فیلدهای ورودی مثل نام و سن را اینجا اضافه کنید
547
+ outputs=[registration_fields, system_msg] # فرم ثبت‌نام را آپدیت (مخفی) می‌کند
548
+ )
549
+
550
+ # نکته: برای نمایش اولیه بخش ثبت نام، باید دکمه check_user_btn اینطور عمل کند:
551
+ # check_user_btn.click(fn=check_user, inputs=username_input, outputs=registration_fields)
552
+ # تا خروجی gr.update(visible=True) بدهد.
553
+
554
+ # -------------------------------------------------------
555
+ # Internal Functions
556
+ # -------------------------------------------------------
557
+ def handle_login_check(name, state):
558
+ if not name.strip():
559
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
560
+
561
+ if name in memory:
562
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
563
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
564
+
565
+ new_state = state.copy()
566
+ new_state["user_name"] = name
567
+ new_state["memory"] = memory
568
+ new_state["initialized"] = True
569
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
570
+ new_state["semantic_memory_index"] = semantic_memory
571
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
572
+ new_state["episodic_memory_index"] = episodic_memory
573
+ new_state["history"] = []
574
+
575
+
576
+
577
+
578
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
579
+
580
+ return (
581
+ gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
582
+ gr.update(visible=False),
583
+ gr.update(visible=True),
584
+ gr.update(visible=False, value=""),
585
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
586
+ gr.update(value=welcome_msg),
587
+ new_state
588
+ )
589
+ else:
590
+ return (
591
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
592
+ gr.update(visible=True),
593
+ gr.update(visible=False),
594
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
595
+ gr.update(),
596
+ gr.update(),
597
+ state
598
+ )
599
+
600
+ def handle_register(name, age, gender, occupation, residence, state):
601
+ name = str(name).strip()
602
+
603
+ if not name:
604
+ raise gr.Error("Please enter a valid user name.")
605
+
606
+ # Registration is only for new users.
607
+ if name in memory:
608
+ raise gr.Error(
609
+ f"User '{name}' already exists. Please use the login form."
610
+ )
611
+
612
+ # Create the user before trying to build or load their indices.
613
+ memory[name] = {
614
+ "profile": {
615
+ "age": age,
616
+ "gender": gender,
617
+ "occupation": occupation,
618
+ "residence": residence,
619
+ },
620
+ "sessions": [],
621
+ "episodic_memory": [],
622
+ "semantic_memory": {},
623
+ }
624
+
625
+ try:
626
+ (
627
+ _,
628
+ user_memory,
629
+ sessions_memory,
630
+ episodic_memory,
631
+ semantic_memory,
632
+ ) = enter_name_llamaindex(
633
+ name=name,
634
+ memory=memory,
635
+ data_args=data_args,
636
+ update_memory_index=True,
637
+ )
638
+ except Exception:
639
+ # Avoid leaving a partially registered user in memory.
640
+ memory.pop(name, None)
641
+ raise
642
+
643
+ new_state = dict(state or {})
644
+ new_state.update(
645
+ {
646
+ "user_name": name,
647
+ "memory": memory,
648
+ "initialized": True,
649
+ "history": [],
650
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
651
+ "user_memory_index": sessions_memory,
652
+ "episodic_memory_index": episodic_memory,
653
+ "semantic_memory_index": semantic_memory,
654
+ }
655
+ )
656
+
657
+ welcome_msg = f"Welcome {name}! Registration complete."
658
+
659
+ return (
660
+ gr.update(
661
+ elem_classes=["center-content", "slide-up"]
662
+ ),
663
+ gr.update(visible=False),
664
+ gr.update(visible=True),
665
+ gr.update(visible=False, value=""),
666
+ gr.update(
667
+ value=(
668
+ "<h2 style='text-align: center; color: #333;'>"
669
+ f"🧠 EMMA: Session for {name}</h2>"
670
+ )
671
+ ),
672
+ gr.update(value=welcome_msg),
673
+ new_state,
674
+ )
675
+
676
+ def switch_user(state):
677
+ if state["initialized"] and state["user_name"] in state["memory"]:
678
+ if state["memory"][state["user_name"]]["sessions"]:
679
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
680
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
681
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
682
+ # ==========================================
683
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
684
+ # ==========================================
685
+ try:
686
+ user_mem = state["memory"][state["user_name"]]
687
+ existing_semantic = user_mem.get("semantic_memory", {})
688
+
689
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
690
+
691
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
692
+ except Exception as e:
693
+ print(f"Error updating semantic memory on logout: {e}")
694
+ # ==========================================
695
+
696
+ new_state = state.copy()
697
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
698
+
699
+ return (
700
+ gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
701
+ gr.update(visible=False),
702
+ gr.update(visible=False),
703
+ gr.update(value="Logged out successfully.", visible=True),
704
+ gr.update(value=""),
705
+ new_state,
706
+ gr.update(value=[])
707
+ )
708
+
709
+ def handle_chat(user_message, state):
710
+ if not user_message.strip():
711
+ print("[handle_chat] empty message")
712
+ print("[handle_chat] state =", state)
713
+ return gr.update(), state.get("history", []), state
714
+
715
+ print("[handle_chat] user_message =", repr(user_message))
716
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
717
+ print("[handle_chat] user_name =", state.get("user_name"))
718
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
719
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
720
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
721
+ print("[handle_chat] api_index =", state.get("api_index", 0))
722
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
723
+ print("[handle_chat] history len =", len(state.get("history", [])))
724
+
725
+ user_name = state.get("user_name")
726
+ user_memory_index = state.get("user_memory_index")
727
+ user_memory = state.get("user_memory", {})
728
+ user_memory_index = state.get("user_memory_index")
729
+ semantic_memory_text = state.get("semantic_memory_text", {})
730
+ service_context = state.get("service_context")
731
+ api_index = state.get("api_index", 0)
732
+ semantic_memory_text = state.get("semantic_memory_text", "")
733
+
734
+ query_category = classify_query_local(user_message)
735
+ print("[handle_chat] query_category =", query_category)
736
+
737
+ new_history, _, status_msg = predict_new(
738
+ text=user_message,
739
+ history=state.get("history", []),
740
+ top_p=0.95,
741
+ temperature=1.0,
742
+ max_length_tokens=1024,
743
+ max_context_length_tokens=4096,
744
+ user_name=user_name,
745
+ user_memory=user_memory,
746
+ user_memory_index=user_memory_index,
747
+ service_context=service_context,
748
+ api_index=api_index,
749
+ semantic_memory_text=semantic_memory_text,
750
+ query_category=query_category,
751
+
752
+ )
753
+
754
+ print("[handle_chat] status_msg =", status_msg)
755
+ print("[handle_chat] new_history len =", len(new_history))
756
+
757
+ state["history"] = new_history
758
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
759
+
760
+ return "", new_history, state
761
+
762
+ def clear_history(state):
763
+ state["history"] = []
764
+ return [], state
765
+
766
+ def handle_new_session(state):
767
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
768
+ user_name = state.get("user_name")
769
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
770
+ print("Error: User not logged in or memory missing.")
771
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
772
+ return [], state
773
+
774
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
775
+ user_data = state["memory"][user_name]
776
+
777
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
778
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
779
+ last_session = user_data["sessions"][-1]
780
+
781
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
782
+ if len(last_session.get("conversation", [])) > 0:
783
+ session_date = last_session.get("date", "")
784
+ session_id = last_session.get("session_id", 0)
785
+
786
+ # پاس دادن هر ۳ آرگومان به تابع
787
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
788
+
789
+ if "episodic_memory" not in user_data:
790
+ user_data["episodic_memory"] = []
791
+ user_data["episodic_memory"].append(ep_summary)
792
+
793
+ # ==========================================
794
+ # به‌روزرسانی حافظه سمانتیک
795
+ # ==========================================
796
+ try:
797
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
798
+ existing_semantic = user_data.get("semantic_memory", {})
799
+
800
+ # فراخوانی تابع با هر دو آرگومان
801
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
802
+
803
+ # ذخیره دیتای جدید
804
+ user_data["semantic_memory"] = updated_semantic
805
+ except Exception as e:
806
+ print(f"Error updating semantic memory: {e}")
807
+ # ==========================================
808
+
809
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
810
+ new_session_id = len(user_data.get("sessions", []))
811
+
812
+ new_session = {
813
+ "session_id": new_session_id,
814
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
815
+ "conversation": []
816
+ }
817
+
818
+ if "sessions" not in user_data:
819
+ user_data["sessions"] = []
820
+
821
+ user_data["sessions"].append(new_session)
822
+
823
+ # پاک کردن تاریخچه چت در state
824
+ state["history"] = []
825
+
826
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
827
+ return [], state
828
+
829
+ check_user_btn.click(
830
+ handle_login_check,
831
+ inputs=[username_input, state],
832
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
833
+ )
834
+
835
+ register_btn.click(
836
+ handle_register,
837
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
838
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
839
+ )
840
+
841
+ switch_user_btn.click(
842
+ switch_user,
843
+ inputs=[state],
844
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
845
+ )
846
+
847
+ submit_btn.click(
848
+ handle_chat,
849
+ inputs=[user_input, state],
850
+ outputs=[user_input, chatbot, state]
851
+ )
852
+
853
+ user_input.submit(
854
+ handle_chat,
855
+ inputs=[user_input, state],
856
+ outputs=[user_input, chatbot, state]
857
+ )
858
+
859
+ clear_btn.click(
860
+ clear_history,
861
+ inputs=[state],
862
+ outputs=[chatbot, state]
863
+ )
864
+
865
+ # تغییر از clear_history به handle_new_session
866
+ new_session_btn.click(
867
+ handle_new_session,
868
+ inputs=[state],
869
+ outputs=[chatbot, state]
870
+
871
+
872
+ )
873
+
874
+ return demo
875
+
876
+
877
+ def main():
878
+ """Main function to initialize and launch the interface."""
879
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
880
+
881
+ if not gapgpt_api_key:
882
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
883
+ else:
884
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
885
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
886
+
887
+ # تنظیم LLM (مدل زبانی)
888
+ llm = LlamaIndexOpenAI(
889
+ model="gpt-4o",
890
+ temperature=1,
891
+ max_tokens=1024,
892
+ top_p=0.95,
893
+ frequency_penalty=0.4,
894
+ presence_penalty=0.2,
895
+ api_key=gapgpt_api_key,
896
+ api_base=GAPGPT_BASE_URL,
897
+ )
898
+
899
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
900
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
901
+ embed_model = OpenAIEmbedding(
902
+ api_key=gapgpt_api_key,
903
+ api_base=GAPGPT_BASE_URL,
904
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
905
+ )
906
+
907
+ # اعمال تنظیمات سراسری
908
+ Settings.llm = llm
909
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
910
+
911
+ Settings.prompt_helper = PromptHelper(
912
+ context_window=4096,
913
+ num_output=256,
914
+ chunk_overlap_ratio=20 / 4096,
915
+ tokenizer=tokenizer,
916
+ )
917
+
918
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
919
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
920
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
921
+ if 'api_keys' not in locals():
922
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
923
+
924
+ demo = create_gradio_interface(Settings, api_keys)
925
+ demo.launch(
926
+ server_name="127.0.0.1",
927
+ server_port=7860,
928
+ share=True
929
+ )
930
+
931
+
932
+ if __name__ == "__main__":
933
+ signal.signal(signal.SIGINT, signal_handler)
934
+ main()
Backup code/app_v10.py ADDED
@@ -0,0 +1,848 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+
332
+
333
+ ):
334
+ chatgpt_cfg = {
335
+ "model": "gpt-4o",
336
+ "temperature": temperature,
337
+ "max_tokens": max_length_tokens,
338
+ "top_p": top_p,
339
+ "frequency_penalty": 0.4,
340
+ "presence_penalty": 0.2,
341
+ "n": 1,
342
+ }
343
+
344
+ if text == "":
345
+ # Return same history if empty input
346
+ return history, history, "Empty context."
347
+
348
+ # Ensure history is initialized
349
+ if history is None:
350
+ history = []
351
+
352
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
353
+ history=history,
354
+ query=text, # Changed name to match prompt_utils
355
+ user_memory=user_memory,
356
+ user_name=user_name,
357
+ user_memory_index=user_memory_index,
358
+ service_context=service_context,
359
+ api_keys=api_keys,
360
+ api_index=api_index,
361
+ meta_prompt=meta_prompt,
362
+ new_user_meta_prompt=new_user_meta_prompt,
363
+ data_args=data_args,
364
+ boot_actual_name=boot_actual_name,
365
+ semantic_memory_text=semantic_memory_text,
366
+ query_category=query_category,
367
+ meta_prompt_semantic=meta_prompt_semantic,
368
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
369
+ )
370
+
371
+ # Handle context window slicing manually if needed,
372
+ # though usually OpenAI manages this, or we slice the list of dicts.
373
+ current_history_for_llm = history
374
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
375
+ current_history_for_llm = history[-(data_args.max_history * 2):]
376
+
377
+ response = chatgpt_chat(
378
+ prompt=text,
379
+ system=system_prompt,
380
+ history=current_history_for_llm,
381
+ gpt_config=chatgpt_cfg,
382
+ api_index=api_index,
383
+ )
384
+
385
+ torch.cuda.empty_cache()
386
+
387
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
388
+ new_history = history + [
389
+ {"role": "user", "content": text},
390
+ {"role": "assistant", "content": response}
391
+ ]
392
+
393
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
394
+ # OR we convert strictly for saving if your legacy code needs it.
395
+ # For now, assuming we pass the object as is or convert for save)
396
+ if user_name:
397
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
398
+ # or pass a converted version. Let's try passing the new format.
399
+ save_local_memory(memory, new_history, user_name, data_args)
400
+
401
+ # Return: (Chatbot View, State History, Textbox Reset)
402
+ return new_history, new_history, "Generating..."
403
+
404
+
405
+
406
+ def create_gradio_interface(service_context, api_keys):
407
+ with gr.Blocks(title="EMMA") as demo:
408
+
409
+
410
+ state = gr.State({
411
+ "history": [],
412
+ "user_name": None,
413
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
414
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
415
+ "service_context": service_context,
416
+ "api_keys": api_keys,
417
+ "api_index": 0,
418
+ "semantic_memory_text": "",
419
+ "new_conversation": True,
420
+ "initialized": False
421
+ })
422
+
423
+
424
+
425
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
426
+ with gr.Row():
427
+
428
+ # ==========================================
429
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
430
+ # ==========================================
431
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
432
+ with gr.Sidebar(open=True) as login_page:
433
+
434
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
435
+
436
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
437
+ login_status = gr.Textbox(visible=False, label="Status")
438
+
439
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
440
+
441
+ with gr.Column(visible=False) as registration_fields:
442
+ gr.Markdown("### ✨ New User Registration")
443
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
444
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
445
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
446
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
447
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
448
+
449
+
450
+ # ==========================================
451
+ # 2. CHAT PAGE (ستون سمت راست)
452
+ # ==========================================
453
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
454
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
455
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
456
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
457
+
458
+ with gr.Group():
459
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
460
+
461
+ with gr.Row():
462
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
463
+ submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
464
+
465
+ with gr.Row(equal_height=True):
466
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
467
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
468
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
469
+
470
+ # -------------------------------------------------------
471
+ # Internal Functions
472
+ # -------------------------------------------------------
473
+ def handle_login_check(name, state):
474
+ if not name.strip():
475
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
476
+
477
+ if name in memory:
478
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
479
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
480
+
481
+ new_state = state.copy()
482
+ new_state["user_name"] = name
483
+ new_state["memory"] = memory
484
+ new_state["initialized"] = True
485
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
486
+ new_state["semantic_memory_index"] = semantic_memory
487
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
488
+ new_state["episodic_memory_index"] = episodic_memory
489
+ new_state["history"] = []
490
+
491
+
492
+
493
+
494
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
495
+
496
+ return (
497
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
498
+ gr.update(visible=False),
499
+ gr.update(visible=True),
500
+ gr.update(visible=False, value=""),
501
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
502
+ gr.update(value=welcome_msg),
503
+ new_state
504
+ )
505
+ else:
506
+ return (
507
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
508
+ gr.update(visible=True),
509
+ gr.update(visible=False),
510
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
511
+ gr.update(),
512
+ gr.update(),
513
+ state
514
+ )
515
+
516
+ def handle_register(name, age, gender, occupation, residence, state):
517
+ name = str(name).strip()
518
+
519
+ if not name:
520
+ raise gr.Error("Please enter a valid user name.")
521
+
522
+ # Registration is only for new users.
523
+ if name in memory:
524
+ raise gr.Error(
525
+ f"User '{name}' already exists. Please use the login form."
526
+ )
527
+
528
+ # Create the user before trying to build or load their indices.
529
+ memory[name] = {
530
+ "profile": {
531
+ "age": age,
532
+ "gender": gender,
533
+ "occupation": occupation,
534
+ "residence": residence,
535
+ },
536
+ "sessions": [],
537
+ "episodic_memory": [],
538
+ "semantic_memory": {},
539
+ }
540
+
541
+ try:
542
+ (
543
+ _,
544
+ user_memory,
545
+ sessions_memory,
546
+ episodic_memory,
547
+ semantic_memory,
548
+ ) = enter_name_llamaindex(
549
+ name=name,
550
+ memory=memory,
551
+ data_args=data_args,
552
+ update_memory_index=True,
553
+ )
554
+ except Exception:
555
+ # Avoid leaving a partially registered user in memory.
556
+ memory.pop(name, None)
557
+ raise
558
+
559
+ new_state = dict(state or {})
560
+ new_state.update(
561
+ {
562
+ "user_name": name,
563
+ "memory": memory,
564
+ "initialized": True,
565
+ "history": [],
566
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
567
+ "user_memory_index": sessions_memory,
568
+ "episodic_memory_index": episodic_memory,
569
+ "semantic_memory_index": semantic_memory,
570
+ }
571
+ )
572
+
573
+ welcome_msg = f"Welcome {name}! Registration complete."
574
+
575
+ return (
576
+ gr.update(open=False),
577
+ gr.update(visible=False),
578
+ gr.update(visible=True),
579
+ gr.update(visible=False, value=""),
580
+ gr.update(
581
+ value=(
582
+ "<h2 style='text-align: center; color: #333;'>"
583
+ f"🧠 EMMA: Session for {name}</h2>"
584
+ )
585
+ ),
586
+ gr.update(value=welcome_msg),
587
+ new_state,
588
+ )
589
+
590
+ def switch_user(state):
591
+ if state["initialized"] and state["user_name"] in state["memory"]:
592
+ if state["memory"][state["user_name"]]["sessions"]:
593
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
594
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
595
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
596
+ # ==========================================
597
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
598
+ # ==========================================
599
+ try:
600
+ user_mem = state["memory"][state["user_name"]]
601
+ existing_semantic = user_mem.get("semantic_memory", {})
602
+
603
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
604
+
605
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
606
+ except Exception as e:
607
+ print(f"Error updating semantic memory on logout: {e}")
608
+ # ==========================================
609
+
610
+ new_state = state.copy()
611
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
612
+
613
+ return (
614
+ gr.update(open=True), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
615
+ gr.update(visible=False),
616
+ gr.update(visible=False),
617
+ gr.update(value="Logged out successfully.", visible=True),
618
+ gr.update(value=""),
619
+ new_state,
620
+ gr.update(value=[])
621
+ )
622
+
623
+ def handle_chat(user_message, state):
624
+ if not user_message.strip():
625
+ print("[handle_chat] empty message")
626
+ print("[handle_chat] state =", state)
627
+ return gr.update(), state.get("history", []), state
628
+
629
+ print("[handle_chat] user_message =", repr(user_message))
630
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
631
+ print("[handle_chat] user_name =", state.get("user_name"))
632
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
633
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
634
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
635
+ print("[handle_chat] api_index =", state.get("api_index", 0))
636
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
637
+ print("[handle_chat] history len =", len(state.get("history", [])))
638
+
639
+ user_name = state.get("user_name")
640
+ user_memory_index = state.get("user_memory_index")
641
+ user_memory = state.get("user_memory", {})
642
+ user_memory_index = state.get("user_memory_index")
643
+ semantic_memory_text = state.get("semantic_memory_text", {})
644
+ service_context = state.get("service_context")
645
+ api_index = state.get("api_index", 0)
646
+ semantic_memory_text = state.get("semantic_memory_text", "")
647
+
648
+ query_category = classify_query_local(user_message)
649
+ print("[handle_chat] query_category =", query_category)
650
+
651
+ new_history, _, status_msg = predict_new(
652
+ text=user_message,
653
+ history=state.get("history", []),
654
+ top_p=0.95,
655
+ temperature=1.0,
656
+ max_length_tokens=1024,
657
+ max_context_length_tokens=4096,
658
+ user_name=user_name,
659
+ user_memory=user_memory,
660
+ user_memory_index=user_memory_index,
661
+ service_context=service_context,
662
+ api_index=api_index,
663
+ semantic_memory_text=semantic_memory_text,
664
+ query_category=query_category,
665
+
666
+ )
667
+
668
+ print("[handle_chat] status_msg =", status_msg)
669
+ print("[handle_chat] new_history len =", len(new_history))
670
+
671
+ state["history"] = new_history
672
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
673
+
674
+ return "", new_history, state
675
+
676
+ def clear_history(state):
677
+ state["history"] = []
678
+ return [], state
679
+
680
+ def handle_new_session(state):
681
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
682
+ user_name = state.get("user_name")
683
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
684
+ print("Error: User not logged in or memory missing.")
685
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
686
+ return [], state
687
+
688
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
689
+ user_data = state["memory"][user_name]
690
+
691
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
692
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
693
+ last_session = user_data["sessions"][-1]
694
+
695
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
696
+ if len(last_session.get("conversation", [])) > 0:
697
+ session_date = last_session.get("date", "")
698
+ session_id = last_session.get("session_id", 0)
699
+
700
+ # پاس دادن هر ۳ آرگومان به تابع
701
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
702
+
703
+ if "episodic_memory" not in user_data:
704
+ user_data["episodic_memory"] = []
705
+ user_data["episodic_memory"].append(ep_summary)
706
+
707
+ # ==========================================
708
+ # به‌روزرسانی حافظه سمانتیک
709
+ # ==========================================
710
+ try:
711
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
712
+ existing_semantic = user_data.get("semantic_memory", {})
713
+
714
+ # فراخوانی تابع با هر دو آرگومان
715
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
716
+
717
+ # ذخیره دیتای جدید
718
+ user_data["semantic_memory"] = updated_semantic
719
+ except Exception as e:
720
+ print(f"Error updating semantic memory: {e}")
721
+ # ==========================================
722
+
723
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
724
+ new_session_id = len(user_data.get("sessions", []))
725
+
726
+ new_session = {
727
+ "session_id": new_session_id,
728
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
729
+ "conversation": []
730
+ }
731
+
732
+ if "sessions" not in user_data:
733
+ user_data["sessions"] = []
734
+
735
+ user_data["sessions"].append(new_session)
736
+
737
+ # پاک کردن تاریخچه چت در state
738
+ state["history"] = []
739
+
740
+ # برگرداندن مقادیر با ترتیب درست برای خروجی‌های Gradio: [chatbot, state]
741
+ return [], state
742
+
743
+ check_user_btn.click(
744
+ handle_login_check,
745
+ inputs=[username_input, state],
746
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
747
+ )
748
+
749
+ register_btn.click(
750
+ handle_register,
751
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
752
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
753
+ )
754
+
755
+ switch_user_btn.click(
756
+ switch_user,
757
+ inputs=[state],
758
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
759
+ )
760
+
761
+ submit_btn.click(
762
+ handle_chat,
763
+ inputs=[user_input, state],
764
+ outputs=[user_input, chatbot, state]
765
+ )
766
+
767
+ user_input.submit(
768
+ handle_chat,
769
+ inputs=[user_input, state],
770
+ outputs=[user_input, chatbot, state]
771
+ )
772
+
773
+ clear_btn.click(
774
+ clear_history,
775
+ inputs=[state],
776
+ outputs=[chatbot, state]
777
+ )
778
+
779
+ # تغییر از clear_history به handle_new_session
780
+ new_session_btn.click(
781
+ handle_new_session,
782
+ inputs=[state],
783
+ outputs=[chatbot, state]
784
+
785
+
786
+ )
787
+
788
+ return demo
789
+
790
+
791
+ def main():
792
+ """Main function to initialize and launch the interface."""
793
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
794
+
795
+ if not gapgpt_api_key:
796
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
797
+ else:
798
+ # تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
799
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
800
+
801
+ # تنظیم LLM (مدل زبانی)
802
+ llm = LlamaIndexOpenAI(
803
+ model="gpt-4o",
804
+ temperature=1,
805
+ max_tokens=1024,
806
+ top_p=0.95,
807
+ frequency_penalty=0.4,
808
+ presence_penalty=0.2,
809
+ api_key=gapgpt_api_key,
810
+ api_base=GAPGPT_BASE_URL,
811
+ )
812
+
813
+ # تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
814
+ # اگر سرویس دهنده شما از امبدینگ پشتیبانی نمی‌کند، این بخش نیاز به تغییر به مدل لوکال دارد
815
+ embed_model = OpenAIEmbedding(
816
+ api_key=gapgpt_api_key,
817
+ api_base=GAPGPT_BASE_URL,
818
+ model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی می‌کند
819
+ )
820
+
821
+ # اعمال تنظیمات سراسری
822
+ Settings.llm = llm
823
+ Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را می‌گیرد
824
+
825
+ Settings.prompt_helper = PromptHelper(
826
+ context_window=4096,
827
+ num_output=256,
828
+ chunk_overlap_ratio=20 / 4096,
829
+ tokenizer=tokenizer,
830
+ )
831
+
832
+ # توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
833
+ # اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمی‌شود حذف کنید.
834
+ # فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
835
+ if 'api_keys' not in locals():
836
+ api_keys = {} # یا هر مقداری که کد شما انتظار دارد
837
+
838
+ demo = create_gradio_interface(Settings, api_keys)
839
+ demo.launch(
840
+ server_name="127.0.0.1",
841
+ server_port=7860,
842
+ share=True
843
+ )
844
+
845
+
846
+ if __name__ == "__main__":
847
+ signal.signal(signal.SIGINT, signal_handler)
848
+ main()
Backup code/app_v17.py ADDED
@@ -0,0 +1,1031 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+
3
+ import os
4
+ import sys
5
+ import json
6
+ import time
7
+ import copy
8
+ import shutil
9
+ import signal
10
+ import logging
11
+ import platform
12
+ import re
13
+
14
+ import gradio as gr
15
+ import nltk
16
+ import torch
17
+ import tiktoken
18
+
19
+ from openai import OpenAI as OpenAIClient
20
+ from llama_index.embeddings.openai import OpenAIEmbedding
21
+
22
+ # from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
23
+ from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
24
+ from llama_index.core import Settings
25
+ from llama_index.core.indices.prompt_helper import PromptHelper
26
+
27
+ prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
28
+ sys.path.append(prompt_path)
29
+
30
+ # Assuming these imports exist in your local environment
31
+ from utils.sys_args import data_args, model_args
32
+ from utils.app_modules.utils import *
33
+ from utils.app_modules.presets import *
34
+ from utils.app_modules.overwrites import *
35
+ from utils.prompt_utils import *
36
+ from utils.memory_utils import (
37
+ enter_name_llamaindex,
38
+ summarize_memory_event_personality,
39
+ save_local_memory,
40
+ extract_session_summary,
41
+ extract_semantic_memory,
42
+ )
43
+
44
+ # Ensure NLTK data path
45
+ nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
46
+
47
+ tokenizer = tiktoken.get_encoding("cl100k_base")
48
+
49
+ GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
50
+ openai_client_cache = {}
51
+
52
+ import torch
53
+ import torch.nn.functional as F
54
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
55
+
56
+
57
+ LOCAL_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Classification_Model", "final_xlm_r_model_router")
58
+
59
+ print(f"Loading model from: {LOCAL_MODEL_PATH}")
60
+
61
+ try:
62
+ _tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
63
+ _classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
64
+ _classifier_model.eval()
65
+ print("Local classifier loaded successfully.")
66
+ except Exception as e:
67
+ print(f"Error loading local classifier: {e}")
68
+
69
+
70
+ def get_gapgpt_client(api_key: str) -> OpenAIClient:
71
+ if not api_key:
72
+ raise ValueError("API key is missing while attempting to create a GapGPT client.")
73
+ if api_key not in openai_client_cache:
74
+ openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
75
+ return openai_client_cache[api_key]
76
+
77
+
78
+ os_name = platform.system()
79
+ clear_command = 'cls' if os_name == 'Windows' else 'clear'
80
+ stop_stream = False
81
+
82
+
83
+ def signal_handler(signal_number, frame):
84
+ global stop_stream
85
+ stop_stream = True
86
+
87
+
88
+ VECTOR_SEARCH_TOP_K = 2
89
+
90
+ # Update this path to your actual file location
91
+ api_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "api_key_list.txt")
92
+
93
+
94
+ def read_apis(path):
95
+ api_keys_local = []
96
+ if os.path.exists(path):
97
+ with open(path, 'r', encoding='utf8') as f:
98
+ for line in f:
99
+ line = line.strip()
100
+ if line:
101
+ api_keys_local.append(line)
102
+ return api_keys_local
103
+
104
+
105
+ memory_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "memories", "update_memory_0512_eng.json")
106
+
107
+ # Ensure directory exists
108
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
109
+
110
+ if not os.path.exists(memory_dir):
111
+ json.dump({}, open(memory_dir, "w", encoding="utf-8"))
112
+
113
+ global memory
114
+ memory = json.load(open(memory_dir, "r", encoding="utf-8"))
115
+ language = 'en'
116
+ user_keyword = generate_user_keyword()[language]
117
+ ai_keyword = generate_ai_keyword()[language]
118
+ boot_name = boot_name_dict[language]
119
+ boot_actual_name = boot_actual_name_dict[language]
120
+ meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
121
+ meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
122
+ meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
123
+ new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
124
+
125
+ api_keys = read_apis(api_path)
126
+ # Fallback if file is empty or missing for testing purposes
127
+ if not api_keys:
128
+ print(f"Warning: No API keys found in {api_path}.")
129
+
130
+ new_conversation = False
131
+ chatgpt_config = {
132
+ "model": "gpt-4o",
133
+ "temperature": 1,
134
+ "max_tokens": 1024,
135
+ "top_p": 0.95,
136
+ "frequency_penalty": 0.4,
137
+ "presence_penalty": 0.2,
138
+ "n": 1,
139
+ }
140
+
141
+ deactivated_keys = []
142
+ logging.basicConfig(
143
+ level=logging.DEBUG,
144
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
145
+ )
146
+
147
+
148
+ def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
149
+ """
150
+ Handles the chat request to OpenAI.
151
+ History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
152
+ """
153
+ retry_times, count = 5, 0
154
+ response = None
155
+
156
+ while response is None and count < retry_times:
157
+ try:
158
+ request = copy.deepcopy(gpt_config)
159
+
160
+ # Initial system and greeting messages
161
+ if data_args.language == 'en':
162
+ message = [
163
+ {"role": "system", "content": system.strip()},
164
+ {"role": "user", "content": "Hi!"},
165
+ {"role": "assistant",
166
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
167
+ ]
168
+ else:
169
+ message = [
170
+ {"role": "system", "content": system.strip()},
171
+ {"role": "user", "content": "Hi"},
172
+ {"role": "assistant",
173
+ "content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
174
+ ]
175
+
176
+ # --- FIX: Handle History as List of Dicts ---
177
+ if history:
178
+ # Verify if history is old format (list of lists) or new (list of dicts)
179
+ if isinstance(history[0], list):
180
+ # Convert old format temporarily if encountered
181
+ for q, a in history:
182
+ message.append({"role": "user", "content": str(q)})
183
+ message.append({"role": "assistant", "content": str(a)})
184
+ elif isinstance(history[0], dict):
185
+ # New format
186
+ for msg in history:
187
+ if msg.get('role') in ['user', 'assistant']:
188
+ message.append(msg)
189
+
190
+ # Add the current prompt
191
+ message.append({"role": "user", "content": f"{prompt}"})
192
+
193
+ if not api_keys:
194
+ return "Error: No API Keys available."
195
+
196
+ client = get_gapgpt_client(api_keys[api_index])
197
+
198
+ # New OpenAI 1.x Syntax
199
+ response = client.chat.completions.create(messages=message, **request)
200
+
201
+ except Exception as e:
202
+ print(f"Chat Error: {e}")
203
+ if 'This key is associated with a deactivated account' in str(e):
204
+ deactivated_keys.append(api_keys[api_index])
205
+
206
+ if api_keys:
207
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
208
+ loop_check = 0
209
+ while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
210
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
211
+ loop_check += 1
212
+ count += 1
213
+
214
+ if response:
215
+ response = response.choices[0].message.content
216
+ else:
217
+ response = ''
218
+ return response
219
+
220
+
221
+ def classify_query_local(text):
222
+
223
+
224
+ # 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
225
+ id2label_map = {
226
+ 0: "episodic_memory",
227
+ 1: "semantic_memory",
228
+ 2: "semantic-episodic",
229
+ 3: "unknown"
230
+ }
231
+
232
+ try:
233
+
234
+ inputs = _tokenizer(
235
+ text,
236
+ return_tensors="pt",
237
+ truncation=True,
238
+ padding=True,
239
+ max_length=512
240
+ )
241
+
242
+
243
+
244
+ with torch.no_grad():
245
+ outputs = _classifier_model(**inputs)
246
+
247
+
248
+ logits = outputs.logits
249
+ probabilities = F.softmax(logits, dim=-1)
250
+ predicted_class_id = torch.argmax(probabilities, dim=-1).item()
251
+
252
+
253
+ category = id2label_map.get(predicted_class_id, "unknown")
254
+
255
+ print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
256
+ return category
257
+
258
+ except Exception as e:
259
+ print(f"Error in local classification: {e}")
260
+ return "unknown"
261
+
262
+
263
+
264
+ def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
265
+ response = None
266
+ count = 0
267
+ local_deactivated = []
268
+ print("text********:", text)
269
+
270
+ system_prompt = """
271
+ You are an AI that classifies user queries into one of the following memory types:
272
+ - 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
273
+ - 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
274
+ - 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
275
+
276
+ Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
277
+ """.strip()
278
+
279
+ if not api_keys:
280
+ return "unknown"
281
+
282
+ while response is None and count < retry_times:
283
+ try:
284
+ client = get_gapgpt_client(api_keys[api_index])
285
+
286
+ # New OpenAI 1.x Syntax
287
+ response = client.chat.completions.create(
288
+ messages=[
289
+ {"role": "system", "content": system_prompt},
290
+ {"role": "user", "content": text.strip()},
291
+ ],
292
+ **copy.deepcopy(gpt_config),
293
+ )
294
+ except Exception as e:
295
+ print(f"Classify Error: {e}")
296
+ if "This key is associated with a deactivated account" in str(e):
297
+ local_deactivated.append(api_keys[api_index])
298
+
299
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
300
+ while api_keys[api_index] in local_deactivated:
301
+ api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
302
+ count += 1
303
+
304
+ if response:
305
+ category = response.choices[0].message.content.strip().lower()
306
+ # Basic cleanup
307
+ if "semantic_memory" in category: category = "semantic_memory"
308
+ elif "semantic-episodic" in category: category = "semantic-episodic"
309
+ elif "episodic_memory" in category: category = "episodic_memory"
310
+ else: category = "unknown"
311
+ else:
312
+ category = "unknown"
313
+
314
+ return category
315
+
316
+
317
+ def predict_new(
318
+ text,
319
+ history,
320
+ top_p,
321
+ temperature,
322
+ max_length_tokens,
323
+ max_context_length_tokens,
324
+ user_name,
325
+ user_memory,
326
+ user_memory_index,
327
+ service_context,
328
+ api_index,
329
+ semantic_memory_text,
330
+ query_category,
331
+ user_profile=None
332
+
333
+
334
+ ):
335
+ chatgpt_cfg = {
336
+ "model": "gpt-4o",
337
+ "temperature": temperature,
338
+ "max_tokens": max_length_tokens,
339
+ "top_p": top_p,
340
+ "frequency_penalty": 0.4,
341
+ "presence_penalty": 0.2,
342
+ "n": 1,
343
+ }
344
+
345
+ if text == "":
346
+ # Return same history if empty input
347
+ return history, history, "Empty context."
348
+
349
+ # Ensure history is initialized
350
+ if history is None:
351
+ history = []
352
+
353
+ system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
354
+ history=history,
355
+ query=text, # Changed name to match prompt_utils
356
+ user_memory=user_memory,
357
+ user_name=user_name,
358
+ user_memory_index=user_memory_index,
359
+ service_context=service_context,
360
+ api_keys=api_keys,
361
+ api_index=api_index,
362
+ meta_prompt=meta_prompt,
363
+ new_user_meta_prompt=new_user_meta_prompt,
364
+ data_args=data_args,
365
+ boot_actual_name=boot_actual_name,
366
+ semantic_memory_text=semantic_memory_text,
367
+ query_category=query_category,
368
+ meta_prompt_semantic=meta_prompt_semantic,
369
+ meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
370
+ )
371
+
372
+ # ==========================================
373
+ # اضافه کردن پروفایل به System Prompt
374
+ # ==========================================
375
+ if user_profile:
376
+ profile_str = (
377
+ f"\n\n[User Profile Information]:\n"
378
+ f"- Age: {user_profile.get('age', 'Unknown')}\n"
379
+ f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
380
+ f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
381
+ f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
382
+ f"Use this context subtly when talking to the user."
383
+ )
384
+ system_prompt += profile_str
385
+ # ==========================================
386
+
387
+ # Handle context window slicing manually if needed,
388
+ # though usually OpenAI manages this, or we slice the list of dicts.
389
+ current_history_for_llm = history
390
+ if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
391
+ current_history_for_llm = history[-(data_args.max_history * 2):]
392
+
393
+ response = chatgpt_chat(
394
+ prompt=text,
395
+ system=system_prompt,
396
+ history=current_history_for_llm,
397
+ gpt_config=chatgpt_cfg,
398
+ api_index=api_index,
399
+ )
400
+
401
+ torch.cuda.empty_cache()
402
+
403
+ # --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
404
+ new_history = history + [
405
+ {"role": "user", "content": text},
406
+ {"role": "assistant", "content": response}
407
+ ]
408
+
409
+ # Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
410
+ # OR we convert strictly for saving if your legacy code needs it.
411
+ # For now, assuming we pass the object as is or convert for save)
412
+ if user_name:
413
+ # If save_local_memory expects list of lists, we might need to adapt it inside that function
414
+ # or pass a converted version. Let's try passing the new format.
415
+ save_local_memory(memory, new_history, user_name, data_args)
416
+
417
+ # Return: (Chatbot View, State History, Textbox Reset)
418
+ return new_history, new_history, "Generating..."
419
+
420
+
421
+
422
+ def create_gradio_interface(service_context, api_keys):
423
+
424
+
425
+ # ابتدا متغیر CSS را تعریف کنید
426
+ custom_css = """
427
+ /* استایل دکمه ارسال (Send) */
428
+ .send-btn {
429
+ border: 3px solid #0066cc !important;
430
+ border-radius: 12px !important;
431
+ background-color: white !important;
432
+ color: black !important;
433
+ font-weight: bold !important;
434
+ font-size: 16px !important;
435
+ transition: all 0.3s ease !important;
436
+ }
437
+ .send-btn:hover {
438
+ background-color: #0066cc !important;
439
+ color: white !important;
440
+ }
441
+
442
+ /* استایل نوار پایین و دکمه‌های آن */
443
+ .bottom-actions-row {
444
+ background-color: #e5e7eb !important; /* رنگ خاکستری پس‌زمینه */
445
+ border-radius: 8px !important;
446
+ padding: 5px !important;
447
+ margin-top: 10px !important;
448
+ }
449
+
450
+ .action-btn {
451
+ border: none !important;
452
+ background: transparent !important;
453
+ color: black !important;
454
+ font-weight: bold !important;
455
+ box-shadow: none !important;
456
+ transition: all 0.3s ease !important;
457
+ }
458
+
459
+ .action-btn:hover {
460
+ background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
461
+ border-radius: 8px !important;
462
+ }
463
+ /* ========================================== */
464
+ /* لودینگ تمام‌صفحه و غیرفعال‌سازی تعاملات */
465
+ /* ========================================== */
466
+
467
+ /* مخفی کردن نوار پیشرفت پیش‌فرض Gradio */
468
+ .progress-level, .progress-text, .progress-level svg, .progress-level img {
469
+ display: none !important;
470
+ }
471
+
472
+ /* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایل‌ها روی body اعمال می‌شود */
473
+ body:has(.progress-level) {
474
+ pointer-events: none !important; /* غیرفعال کردن تمام کلیک‌ها */
475
+ }
476
+
477
+ /* ایجاد هاله نیمه‌شفاف روی کل صفحه */
478
+ body:has(.progress-level)::after {
479
+ content: "";
480
+ position: fixed;
481
+ top: 0; left: 0;
482
+ width: 100vw; height: 100vh;
483
+ background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمه‌شفاف */
484
+ z-index: 9998;
485
+ pointer-events: all; /* برای گرفتن کلیک‌ها و جلوگیری از عبور آن‌ها */
486
+ cursor: wait;
487
+ }
488
+
489
+ /* ایجاد اسپینر لودینگ در مرکز صفحه */
490
+ body:has(.progress-level)::before {
491
+ content: "";
492
+ position: fixed;
493
+ top: 50%; left: 50%;
494
+ transform: translate(-50%, -50%);
495
+ width: 60px; height: 60px;
496
+ border: 6px solid #e5e7eb;
497
+ border-top-color: #0066cc;
498
+ border-radius: 50%;
499
+ animation: spin 1s linear infinite;
500
+ z-index: 9999;
501
+ }
502
+
503
+ @keyframes spin {
504
+ 0% { transform: translate(-50%, -50%) rotate(0deg); }
505
+ 100% { transform: translate(-50%, -50%) rotate(360deg); }
506
+ }
507
+
508
+
509
+ /* انیمیشن چرخش */
510
+ @keyframes spin {
511
+ 0% { transform: rotate(0deg); }
512
+ 100% { transform: rotate(360deg); }
513
+ }
514
+
515
+ /* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
516
+ /* اگر می‌خواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
517
+ /*
518
+ .progress-text {
519
+ display: none !important;
520
+ }
521
+ */
522
+ /* انیمیشن سه نقطه در حال تایپ */
523
+ .typing-dots::after {
524
+ content: '';
525
+ animation: typing 1.5s infinite;
526
+ }
527
+ @keyframes typing {
528
+ 0% { content: ''; }
529
+ 25% { content: ' .'; }
530
+ 50% { content: ' . .'; }
531
+ 75% { content: ' . . .'; }
532
+ 100% { content: ''; }
533
+ }
534
+
535
+
536
+ """
537
+
538
+ with gr.Blocks(title="EMMA") as demo:
539
+ # حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
540
+ gr.HTML(f"<style>{custom_css}</style>")
541
+
542
+ # بقیه کدهای شما...
543
+
544
+
545
+ state = gr.State({
546
+ "history": [],
547
+ "user_name": None,
548
+ "memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
549
+ "data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
550
+ "service_context": service_context,
551
+ "api_keys": api_keys,
552
+ "api_index": 0,
553
+ "semantic_memory_text": "",
554
+ "new_conversation": True,
555
+ "initialized": False
556
+ })
557
+
558
+
559
+
560
+ # فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
561
+ with gr.Row():
562
+
563
+ # ==========================================
564
+ # 1. LOGIN PAGE (سایدبار سمت چپ)
565
+ # ==========================================
566
+ # استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
567
+ with gr.Sidebar(open=True) as login_page:
568
+
569
+ gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
570
+
571
+ username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
572
+ login_status = gr.Textbox(visible=False, label="Status")
573
+
574
+ check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
575
+
576
+ with gr.Column(visible=False) as registration_fields:
577
+ gr.Markdown("### ✨ New User Registration")
578
+ age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
579
+ gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
580
+ occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
581
+ residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
582
+ register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
583
+
584
+
585
+ # ==========================================
586
+ # 2. CHAT PAGE (ستون سمت راست)
587
+ # ==========================================
588
+ # مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
589
+ with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
590
+ active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
591
+ #system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
592
+
593
+ with gr.Group():
594
+ chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
595
+
596
+ with gr.Row():
597
+ user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
598
+ # اختصاص کلاس send-btn به دکمه Send
599
+ submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
600
+
601
+ # اختصاص کلاس bottom-actions-row به ردیف دکمه‌های پایین
602
+ with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
603
+ # اختصاص کلاس action-btn به دکمه‌های عملیاتی
604
+ clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
605
+ new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
606
+ switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
607
+ system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
608
+
609
+ # -------------------------------------------------------
610
+ # Internal Functions
611
+ # -------------------------------------------------------
612
+ def handle_login_check(name, state):
613
+ if not name.strip():
614
+ return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
615
+
616
+ if name in memory:
617
+ hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
618
+ user_memory = summarize_memory_event_personality(data_args, memory, name)
619
+
620
+ new_state = state.copy()
621
+ new_state["user_name"] = name
622
+ new_state["memory"] = memory
623
+ new_state["initialized"] = True
624
+ new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
625
+ new_state["semantic_memory_index"] = semantic_memory
626
+ new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
627
+ new_state["episodic_memory_index"] = episodic_memory
628
+ new_state["history"] = []
629
+
630
+
631
+
632
+
633
+ welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
634
+
635
+ return (
636
+ gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
637
+ gr.update(visible=False),
638
+ gr.update(visible=True),
639
+ gr.update(visible=False, value=""),
640
+ gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
641
+ gr.update(value=welcome_msg),
642
+ new_state
643
+ )
644
+ else:
645
+ return (
646
+ gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
647
+ gr.update(visible=True),
648
+ gr.update(visible=False),
649
+ gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
650
+ gr.update(),
651
+ gr.update(),
652
+ state
653
+ )
654
+
655
+ def handle_register(name, age, gender, occupation, residence, state):
656
+ name = str(name).strip()
657
+
658
+ if not name:
659
+ raise gr.Error("Please enter a valid user name.")
660
+
661
+ # Registration is only for new users.
662
+ if name in memory:
663
+ raise gr.Error(
664
+ f"User '{name}' already exists. Please use the login form."
665
+ )
666
+
667
+ # Create the user before trying to build or load their indices.
668
+ memory[name] = {
669
+ "profile": {
670
+ "age": age,
671
+ "gender": gender,
672
+ "occupation": occupation,
673
+ "residence": residence,
674
+ },
675
+ "sessions": [],
676
+ "episodic_memory": [],
677
+ "semantic_memory": {},
678
+ }
679
+
680
+ try:
681
+ (
682
+ _,
683
+ user_memory,
684
+ sessions_memory,
685
+ episodic_memory,
686
+ semantic_memory,
687
+ ) = enter_name_llamaindex(
688
+ name=name,
689
+ memory=memory,
690
+ data_args=data_args,
691
+ update_memory_index=True,
692
+ )
693
+ except Exception:
694
+ # Avoid leaving a partially registered user in memory.
695
+ memory.pop(name, None)
696
+ raise
697
+
698
+ new_state = dict(state or {})
699
+ new_state.update(
700
+ {
701
+ "user_name": name,
702
+ "memory": memory,
703
+ "initialized": True,
704
+ "history": [],
705
+ "semantic_memory_text": user_memory.get("semantic_memory", {}),
706
+ "user_memory_index": sessions_memory,
707
+ "episodic_memory_index": episodic_memory,
708
+ "semantic_memory_index": semantic_memory,
709
+ }
710
+ )
711
+
712
+ welcome_msg = f"Welcome {name}! Registration complete."
713
+
714
+ return (
715
+ gr.update(open=False),
716
+ gr.update(visible=False),
717
+ gr.update(visible=True),
718
+ gr.update(visible=False, value=""),
719
+ gr.update(
720
+ value=(
721
+ "<h2 style='text-align: center; color: #333;'>"
722
+ f"🧠 EMMA: Session for {name}</h2>"
723
+ )
724
+ ),
725
+ gr.update(value=welcome_msg),
726
+ new_state,
727
+ )
728
+
729
+ def switch_user(state):
730
+ if state["initialized"] and state["user_name"] in state["memory"]:
731
+ if state["memory"][state["user_name"]]["sessions"]:
732
+ previous_session = state["memory"][state["user_name"]]["sessions"][-1]
733
+ summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
734
+ state["memory"][state["user_name"]]["episodic_memory"].append(summary)
735
+ # ==========================================
736
+ # به‌روزرسانی حافظه سمانتیک زمان خروج
737
+ # ==========================================
738
+ try:
739
+ user_mem = state["memory"][state["user_name"]]
740
+ existing_semantic = user_mem.get("semantic_memory", {})
741
+
742
+ updated_semantic = extract_semantic_memory(summary, existing_semantic)
743
+
744
+ state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
745
+ except Exception as e:
746
+ print(f"Error updating semantic memory on logout: {e}")
747
+ # ==========================================
748
+
749
+ new_state = state.copy()
750
+ new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
751
+
752
+ return (
753
+ gr.update(open=True), # 1. باز شدن سایدبار
754
+ gr.update(visible=False), # 2. بسته شدن فرم ثبت‌نام
755
+ gr.update(visible=False), # 3. مخفی شدن صفحه چت
756
+ gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
757
+ gr.update(value=""), # 5. پاک کردن نام کاربری
758
+ new_state, # 6. استیت جدید
759
+ gr.update(value=[]), # 7. پاک کردن چت‌بات
760
+ gr.update(value=""), # 8. پاک کردن age_input
761
+ gr.update(value=""), # 9. پاک کردن gender_input
762
+ gr.update(value=""), # 10. پاک کردن occupation_input
763
+ gr.update(value=""), # 11. پاک کردن residence_input
764
+ gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
765
+ )
766
+
767
+
768
+ def handle_chat(user_message, state):
769
+ if not user_message.strip():
770
+ print("[handle_chat] empty message")
771
+ print("[handle_chat] state =", state)
772
+ # تبدیل return به yield
773
+ yield gr.update(), state.get("history", []), state
774
+ return
775
+
776
+ print("[handle_chat] user_message =", repr(user_message))
777
+ print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
778
+ print("[handle_chat] user_name =", state.get("user_name"))
779
+ print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
780
+ print("[handle_chat] memory exists =", state.get("memory") is not None)
781
+ print("[handle_chat] service_context exists =", state.get("service_context") is not None)
782
+ print("[handle_chat] api_index =", state.get("api_index", 0))
783
+ print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
784
+ print("[handle_chat] history len =", len(state.get("history", [])))
785
+
786
+ # ==========================================
787
+ # ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
788
+ # ==========================================
789
+ current_history = state.get("history", [])
790
+ temp_history = current_history + [
791
+ {"role": "user", "content": user_message},
792
+ {"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
793
+ ]
794
+
795
+ # باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI می‌فرستیم
796
+ yield gr.update(value=""), temp_history, state
797
+
798
+
799
+ # ادامه پردازش‌های اصلی تابع شما
800
+ user_name = state.get("user_name")
801
+ user_memory_index = state.get("user_memory_index")
802
+ user_memory = state.get("user_memory", {})
803
+ user_memory_index = state.get("user_memory_index")
804
+ semantic_memory_text = state.get("semantic_memory_text", {})
805
+ service_context = state.get("service_context")
806
+ api_index = state.get("api_index", 0)
807
+ semantic_memory_text = state.get("semantic_memory_text", "")
808
+
809
+ # ==========================================
810
+ # استخراج پروفایل کاربر از حافظه
811
+ # ==========================================
812
+ user_profile = {}
813
+ if user_name and state.get("memory") and user_name in state["memory"]:
814
+ user_profile = state["memory"][user_name].get("profile", {})
815
+ # ==========================================
816
+
817
+ query_category = classify_query_local(user_message)
818
+ print("[handle_chat] query_category =", query_category)
819
+
820
+ # ارسال current_history به مدل (بدون انیمیشن موقت)
821
+ new_history, _, status_msg = predict_new(
822
+ text=user_message,
823
+ history=current_history,
824
+ top_p=0.95,
825
+ temperature=1.0,
826
+ max_length_tokens=1024,
827
+ max_context_length_tokens=4096,
828
+ user_name=user_name,
829
+ user_memory=user_memory,
830
+ user_memory_index=user_memory_index,
831
+ service_context=service_context,
832
+ api_index=api_index,
833
+ semantic_memory_text=semantic_memory_text,
834
+ query_category=query_category,
835
+ user_profile=user_profile
836
+ )
837
+
838
+ print("[handle_chat] status_msg =", status_msg)
839
+ print("[handle_chat] new_history len =", len(new_history))
840
+
841
+ state["history"] = new_history
842
+ print("[handle_chat] updated state history len =", len(state.get("history", [])))
843
+
844
+ # ==========================================
845
+ # ۳. جایگزینی پیام لودینگ با پاسخ نهایی
846
+ # ==========================================
847
+ yield gr.update(), new_history, state
848
+
849
+ def clear_history(state):
850
+ state["history"] = []
851
+ return [], state
852
+
853
+ def handle_new_session(state):
854
+ # بررسی اینکه آیا کاربر لاگین کرده است یا خیر
855
+ user_name = state.get("user_name")
856
+ if not user_name or "memory" not in state or user_name not in state["memory"]:
857
+ print("Error: User not logged in or memory missing.")
858
+ # خروجی اول برای chatbot (خالی) و خروجی دوم برای state
859
+ return [], state, gr.update() # خروجی سوم اضافه شد
860
+
861
+ # دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
862
+ user_data = state["memory"][user_name]
863
+
864
+ # --- بخش اول: استخراج حافظه از جلسه قبلی ---
865
+ if user_data.get("sessions") and len(user_data["sessions"]) > 0:
866
+ last_session = user_data["sessions"][-1]
867
+
868
+ # فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
869
+ if len(last_session.get("conversation", [])) > 0:
870
+ session_date = last_session.get("date", "")
871
+ session_id = last_session.get("session_id", 0)
872
+
873
+ # پاس دادن هر ۳ آرگومان به تابع
874
+ ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
875
+
876
+ if "episodic_memory" not in user_data:
877
+ user_data["episodic_memory"] = []
878
+ user_data["episodic_memory"].append(ep_summary)
879
+
880
+ # ==========================================
881
+ # به‌روزرسانی حافظه سمانتیک
882
+ # ==========================================
883
+ try:
884
+ # دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی می‌دهیم)
885
+ existing_semantic = user_data.get("semantic_memory", {})
886
+
887
+ # فراخوانی تابع با هر دو آرگومان
888
+ updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
889
+
890
+ # ذخیره دیتای جدید
891
+ user_data["semantic_memory"] = updated_semantic
892
+ except Exception as e:
893
+ print(f"Error updating semantic memory: {e}")
894
+ # ==========================================
895
+
896
+ # --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
897
+ new_session_id = len(user_data.get("sessions", []))
898
+
899
+ new_session = {
900
+ "session_id": new_session_id,
901
+ "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
902
+ "conversation": []
903
+ }
904
+
905
+ if "sessions" not in user_data:
906
+ user_data["sessions"] = []
907
+
908
+ user_data["sessions"].append(new_session)
909
+
910
+ # پاک کردن تاریخچه چت در state
911
+ state["history"] = []
912
+
913
+ # محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
914
+ session_number = len(user_data["sessions"])
915
+ new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
916
+
917
+ # بازگرداندن خروجی جدید برای active_header
918
+ return [], state, gr.update(value=new_header_text)
919
+
920
+ check_user_btn.click(
921
+ handle_login_check,
922
+ inputs=[username_input, state],
923
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
924
+ # show_progress="hidden"
925
+ )
926
+
927
+ register_btn.click(
928
+ handle_register,
929
+ inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
930
+ outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
931
+ # show_progress="hidden"
932
+ )
933
+
934
+ switch_user_btn.click(
935
+ switch_user,
936
+ inputs=[state],
937
+ # system_msg به انتهای لیست خروجی‌ها اضافه شد
938
+ outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
939
+ # show_progress="hidden"
940
+ )
941
+
942
+
943
+ submit_btn.click(
944
+ handle_chat,
945
+ inputs=[user_input, state],
946
+ outputs=[user_input, chatbot, state],
947
+ # show_progress="hidden"
948
+ )
949
+
950
+ user_input.submit(
951
+ handle_chat,
952
+ inputs=[user_input, state],
953
+ outputs=[user_input, chatbot, state],
954
+ # show_progress="hidden"
955
+ )
956
+
957
+ clear_btn.click(
958
+ clear_history,
959
+ inputs=[state],
960
+ outputs=[chatbot, state],
961
+ # show_progress="hidden"
962
+ )
963
+
964
+ # تغییر از clear_history به handle_new_session
965
+ new_session_btn.click(
966
+ handle_new_session,
967
+ inputs=[state],
968
+ outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
969
+ # show_progress="hidden"
970
+ )
971
+
972
+ return demo
973
+
974
+
975
+ def main():
976
+ """Main function to initialize and launch the interface."""
977
+ global api_keys
978
+ gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
979
+
980
+ if not gapgpt_api_key:
981
+ print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
982
+ else:
983
+ # ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانه‌های وابسته
984
+ os.environ["OPENAI_API_KEY"] = gapgpt_api_key
985
+ # حتماً Base URL را هم به متغیرهای محیطی اضافه کنید
986
+ os.environ["OPENAI_API_BASE"] = GAPGPT_BASE_URL
987
+ os.environ["OPENAI_BASE_URL"] = GAPGPT_BASE_URL
988
+
989
+ if gapgpt_api_key not in api_keys:
990
+ api_keys.insert(0, gapgpt_api_key)
991
+
992
+ # تنظیم LLM (مدل زبانی) - این بخش برای چت است و درست کار می‌کند
993
+ llm = LlamaIndexOpenAI(
994
+ model="gpt-4o",
995
+ temperature=1,
996
+ max_tokens=1024,
997
+ top_p=0.95,
998
+ frequency_penalty=0.4,
999
+ presence_penalty=0.2,
1000
+ api_key=gapgpt_api_key,
1001
+ api_base=GAPGPT_BASE_URL,
1002
+ )
1003
+
1004
+ # تغییر بسیار مهم: مدل را به ada-002 تغییر دهید تا ثبت نام کاربر جدید کار کند
1005
+ embed_model = OpenAIEmbedding(
1006
+ api_key=gapgpt_api_key,
1007
+ api_base=GAPGPT_BASE_URL,
1008
+ model="text-embedding-ada-002" # <--- این خط تغییر کرد
1009
+ )
1010
+
1011
+ # اعمال تنظیمات سراسری
1012
+ Settings.llm = llm
1013
+ Settings.embed_model = embed_model
1014
+
1015
+ Settings.prompt_helper = PromptHelper(
1016
+ context_window=4096,
1017
+ num_output=256,
1018
+ chunk_overlap_ratio=20 / 4096,
1019
+ tokenizer=tokenizer,
1020
+ )
1021
+
1022
+ demo = create_gradio_interface(Settings, api_keys)
1023
+ demo.launch(
1024
+ server_name="0.0.0.0",
1025
+ server_port=7860,
1026
+ share=False
1027
+ )
1028
+
1029
+ if __name__ == "__main__":
1030
+ signal.signal(signal.SIGINT, signal_handler)
1031
+ main()
Backup code/memory_utils copy 2.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import datetime
6
+ import shutil
7
+ import gradio as gr
8
+ from pprint import pprint
9
+ import traceback
10
+
11
+ # LlamaIndex Imports
12
+ from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
13
+
14
+ # Local Imports setup
15
+ # Assuming this file is in 'utils/', we step back to find 'memory_bank'
16
+ bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
17
+ sys.path.append(bank_path)
18
+
19
+ # Import functions from sibling/child modules
20
+ # Ensure these files exist in the appended path
21
+ try:
22
+ from build_memory_index import build_memory_index
23
+ from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
24
+ except ImportError:
25
+ # Fallback or placeholder if running independently for testing
26
+ print("Warning: Could not import memory build/summary modules.")
27
+ def build_memory_index(*args, **kwargs): pass
28
+ def summarize_memory(*args, **kwargs): return {}
29
+ def extract_session_summary(*args, **kwargs): return {}
30
+ def extract_semantic_memory(*args, **kwargs): return {}
31
+
32
+ # --- Global Config for Paths ---
33
+ # Keeping the specific path requested by user
34
+ MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
35
+
36
+
37
+ def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
38
+ """
39
+ Legacy/Basic function to load user memory and initialize vector store.
40
+ """
41
+ cur_date = datetime.date.today().strftime("%Y-%m-%d")
42
+ user_memory_index = None
43
+
44
+ # Handle Gradio States
45
+ if isinstance(data_args, gr.State): data_args = data_args.value
46
+ if isinstance(memory, gr.State): memory = memory.value
47
+ if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
48
+
49
+ memory_dir = MEMORY_FILE_PATH
50
+
51
+ if name in memory.keys():
52
+ user_memory = memory[name]
53
+ memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
54
+ os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
55
+
56
+ if (not os.path.exists(memory_index_path)) or update_memory_index:
57
+ print(f'Initializing memory index {memory_index_path}...')
58
+
59
+ if os.path.exists(memory_index_path):
60
+ shutil.rmtree(memory_index_path)
61
+ # Initialize using the local QA object
62
+ memory_index_path, _ = local_memory_qa.init_memory_vector_store(
63
+ filepath=memory_dir,
64
+ vs_path=memory_index_path,
65
+ user_name=name,
66
+ cur_date=cur_date
67
+ )
68
+
69
+ user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
70
+ msg = f"Welcome back, {name}!"
71
+ return msg, user_memory, memory, name, user_memory_index
72
+ else:
73
+ memory[name] = {}
74
+ memory[name].update({"name": name})
75
+ msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
76
+ return msg, memory[name], memory, name, user_memory_index
77
+
78
+
79
+ def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
80
+ """
81
+ Load the user's session, episodic, and semantic memory indices.
82
+ Compatible with LlamaIndex v0.10+.
83
+ """
84
+ sessions_memory = None
85
+ episodic_memory = None
86
+ semantic_memory = None
87
+
88
+ print(f"[DEBUG] enter_name_llamaindex called with name={name!r}")
89
+
90
+ if name not in memory:
91
+ print(f"[DEBUG] user {name!r} not found in memory")
92
+ return "User not found.", None, None, None, None
93
+
94
+ user_memory = memory[name]
95
+
96
+ # Build one canonical absolute base path so build/load use the same location.
97
+ base_path = os.path.abspath(
98
+ os.path.join(
99
+ data_args.memory_basic_dir,
100
+ "..",
101
+ "memories",
102
+ "memory_index",
103
+ "llamaindex",
104
+ name,
105
+ )
106
+ )
107
+
108
+ sessions_path = os.path.join(base_path, "sessions")
109
+ episodic_path = os.path.join(base_path, "episodic_memory")
110
+ semantic_path = os.path.join(base_path, "semantic_memory")
111
+
112
+ print(f"[DEBUG] base_path: {base_path}")
113
+ print(f"[DEBUG] sessions_path: {sessions_path}")
114
+ print(f"[DEBUG] episodic_path: {episodic_path}")
115
+ print(f"[DEBUG] semantic_path: {semantic_path}")
116
+
117
+ indices_exist = (
118
+ os.path.isdir(sessions_path)
119
+ and os.path.isdir(episodic_path)
120
+ and os.path.isdir(semantic_path)
121
+ )
122
+
123
+ print(f"[DEBUG] indices_exist: {indices_exist}")
124
+ print(f"[DEBUG] update_memory_index: {update_memory_index}")
125
+
126
+ if update_memory_index or not indices_exist:
127
+ print(f"[DEBUG] Initializing memory indices for {name}...")
128
+
129
+ # Important: build_memory_index must persist to these same absolute paths.
130
+ build_memory_index(memory, data_args, name=name)
131
+
132
+ print("[DEBUG] After build:")
133
+ print(f"[DEBUG] sessions_path exists: {os.path.isdir(sessions_path)}")
134
+ print(f"[DEBUG] episodic_path exists: {os.path.isdir(episodic_path)}")
135
+ print(f"[DEBUG] semantic_path exists: {os.path.isdir(semantic_path)}")
136
+
137
+ def load_index_safe(index_name, index_path):
138
+ if not os.path.isdir(index_path):
139
+ print(f"[DEBUG] {index_name} path does not exist: {index_path}")
140
+ return None
141
+
142
+ try:
143
+ storage_context = StorageContext.from_defaults(
144
+ persist_dir=index_path
145
+ )
146
+ index = load_index_from_storage(storage_context)
147
+ print(
148
+ f"[DEBUG] {index_name} loaded: "
149
+ f"{type(index).__name__}, is_none={index is None}"
150
+ )
151
+ return index
152
+ except Exception as exc:
153
+ print(f"[ERROR] Could not load {index_name}: {exc}")
154
+ traceback.print_exc()
155
+ return None
156
+
157
+ sessions_memory = load_index_safe("sessions_memory", sessions_path)
158
+ episodic_memory = load_index_safe("episodic_memory", episodic_path)
159
+ semantic_memory = load_index_safe("semantic_memory", semantic_path)
160
+
161
+ print("[DEBUG] RETURN VALUES:")
162
+ print(f" hello_msg: Welcome back, {name}!")
163
+ print(f" user_memory type: {type(user_memory).__name__}")
164
+ print(f" sessions_memory type: {type(sessions_memory).__name__}")
165
+ print(f" episodic_memory type: {type(episodic_memory).__name__}")
166
+ print(f" semantic_memory type: {type(semantic_memory).__name__}")
167
+
168
+ return (
169
+ f"Welcome back, {name}!",
170
+ user_memory,
171
+ sessions_memory,
172
+ episodic_memory,
173
+ semantic_memory,
174
+ )
175
+
176
+
177
+ def summarize_memory_event_personality(data_args, memory, user_name):
178
+ """
179
+ Summarizes the memory and returns the user-specific memory dict.
180
+ """
181
+ if isinstance(data_args, gr.State): data_args = data_args.value
182
+ if isinstance(memory, gr.State): memory = memory.value
183
+
184
+ memory_dir = MEMORY_FILE_PATH
185
+
186
+ # Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
187
+ memory = summarize_memory(memory_dir, user_name, language=data_args.language)
188
+ user_memory = memory[user_name] if user_name in memory.keys() else {}
189
+ return user_memory
190
+
191
+
192
+ def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
193
+ """
194
+ Saves user-model conversations into memory and adds episodic memory for each session.
195
+ Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
196
+ """
197
+ if isinstance(data_args, gr.State): data_args = data_args.value
198
+ if isinstance(memory, gr.State): memory = memory.value
199
+
200
+ memory_dir = MEMORY_FILE_PATH
201
+
202
+ # 1. Initialize user memory with ALL required structures FIRST
203
+ if user_name not in memory:
204
+ memory[user_name] = {
205
+ "sessions": [],
206
+ "episodic_memory": [],
207
+ "semantic_memory": {}
208
+ }
209
+
210
+ # 2. Ensure all sub-structures exist and are correct type
211
+ memory[user_name].setdefault("sessions", [])
212
+ memory[user_name].setdefault("episodic_memory", [])
213
+ memory[user_name].setdefault("semantic_memory", {})
214
+
215
+ # 3. Now safely check types
216
+ if not isinstance(memory[user_name]["semantic_memory"], dict):
217
+ memory[user_name]["semantic_memory"] = {}
218
+
219
+ # Create new session or update existing one
220
+ if new_conversation or not memory[user_name]["sessions"]:
221
+ if new_conversation and memory[user_name]["sessions"]:
222
+ # Logic to summarize previous session before starting new one could go here
223
+ pass
224
+
225
+ # Create new session
226
+ session = {
227
+ "session_id": len(memory[user_name]["sessions"]),
228
+ "date": time.strftime("%Y-%m-%d", time.localtime()),
229
+ "conversation": []
230
+ }
231
+ memory[user_name]["sessions"].append(session)
232
+
233
+ current_session = memory[user_name]["sessions"][-1]
234
+
235
+ # --- Modified section to fix KeyError: 0 and handle History formats ---
236
+ if not new_conversation and history:
237
+ last_item = history[-1]
238
+
239
+ # Case 1: New Format (List of Dicts)
240
+ # In this format, history is linear. The last item is bot response, second to last is user query.
241
+ if isinstance(last_item, dict):
242
+ if len(history) >= 2:
243
+ user_query = history[-2].get('content', '')
244
+ bot_response = history[-1].get('content', '')
245
+
246
+ # Verify roles to ensure correct pairing
247
+ if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
248
+ current_session["conversation"].append({
249
+ 'query': user_query,
250
+ 'response': bot_response
251
+ })
252
+
253
+ # Case 2: Old Format (List of Lists/Tuples)
254
+ elif isinstance(last_item, (list, tuple)):
255
+ current_session["conversation"].append({
256
+ 'query': last_item[0],
257
+ 'response': last_item[1]
258
+ })
259
+ # ----------------------------------------------------------------------
260
+
261
+ # Optional: Update semantic memory in real-time
262
+ memory[user_name]["semantic_memory"] = extract_semantic_memory(
263
+ memory[user_name]["semantic_memory"],
264
+ current_session["conversation"]
265
+ )
266
+
267
+ semantic_memory_text = memory[user_name]["semantic_memory"]
268
+
269
+ # Save to file
270
+ # Ensure memory directory exists
271
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
272
+
273
+ with open(memory_dir, "w", encoding="utf-8") as f:
274
+ json.dump(memory, f, ensure_ascii=False, indent=4)
275
+
276
+ return memory, semantic_memory_text
Backup code/memory_utils copy.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import datetime
6
+ import shutil
7
+ import gradio as gr
8
+ from pprint import pprint
9
+ import traceback
10
+
11
+ # LlamaIndex Imports
12
+ from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
13
+
14
+ # Local Imports setup
15
+ # Assuming this file is in 'utils/', we step back to find 'memory_bank'
16
+ bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
17
+ sys.path.append(bank_path)
18
+
19
+ # Import functions from sibling/child modules
20
+ # Ensure these files exist in the appended path
21
+ try:
22
+ from build_memory_index import build_memory_index
23
+ from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
24
+ except ImportError:
25
+ # Fallback or placeholder if running independently for testing
26
+ print("Warning: Could not import memory build/summary modules.")
27
+ def build_memory_index(*args, **kwargs): pass
28
+ def summarize_memory(*args, **kwargs): return {}
29
+ def extract_session_summary(*args, **kwargs): return {}
30
+ def extract_semantic_memory(*args, **kwargs): return {}
31
+
32
+ # --- Global Config for Paths ---
33
+ # Keeping the specific path requested by user
34
+ MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
35
+
36
+
37
+ def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
38
+ """
39
+ Legacy/Basic function to load user memory and initialize vector store.
40
+ """
41
+ cur_date = datetime.date.today().strftime("%Y-%m-%d")
42
+ user_memory_index = None
43
+
44
+ # Handle Gradio States
45
+ if isinstance(data_args, gr.State): data_args = data_args.value
46
+ if isinstance(memory, gr.State): memory = memory.value
47
+ if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
48
+
49
+ memory_dir = MEMORY_FILE_PATH
50
+
51
+ if name in memory.keys():
52
+ user_memory = memory[name]
53
+ memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
54
+ os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
55
+
56
+ if (not os.path.exists(memory_index_path)) or update_memory_index:
57
+ print(f'Initializing memory index {memory_index_path}...')
58
+
59
+ if os.path.exists(memory_index_path):
60
+ shutil.rmtree(memory_index_path)
61
+ # Initialize using the local QA object
62
+ memory_index_path, _ = local_memory_qa.init_memory_vector_store(
63
+ filepath=memory_dir,
64
+ vs_path=memory_index_path,
65
+ user_name=name,
66
+ cur_date=cur_date
67
+ )
68
+
69
+ user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
70
+ msg = f"Welcome back, {name}!"
71
+ return msg, user_memory, memory, name, user_memory_index
72
+ else:
73
+ memory[name] = {}
74
+ memory[name].update({"name": name})
75
+ msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
76
+ return msg, memory[name], memory, name, user_memory_index
77
+
78
+
79
+ def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
80
+ """
81
+ Load the user's session, episodic, and semantic memory indices.
82
+ Compatible with LlamaIndex v0.10+.
83
+ """
84
+ sessions_memory = None
85
+ episodic_memory = None
86
+ semantic_memory = None
87
+
88
+ print(f"[DEBUG] enter_name_llamaindex called with name={name!r}")
89
+
90
+ if name not in memory:
91
+ print(f"[DEBUG] user {name!r} not found in memory")
92
+ return "User not found.", None, None, None, None
93
+
94
+ user_memory = memory[name]
95
+
96
+ # Build one canonical absolute base path so build/load use the same location.
97
+ base_path = os.path.abspath(
98
+ os.path.join(
99
+ data_args.memory_basic_dir,
100
+ "..",
101
+ "memories",
102
+ "memory_index",
103
+ "llamaindex",
104
+ name,
105
+ )
106
+ )
107
+
108
+ sessions_path = os.path.join(base_path, "sessions")
109
+ episodic_path = os.path.join(base_path, "episodic_memory")
110
+ semantic_path = os.path.join(base_path, "semantic_memory")
111
+
112
+ print(f"[DEBUG] base_path: {base_path}")
113
+ print(f"[DEBUG] sessions_path: {sessions_path}")
114
+ print(f"[DEBUG] episodic_path: {episodic_path}")
115
+ print(f"[DEBUG] semantic_path: {semantic_path}")
116
+
117
+ indices_exist = (
118
+ os.path.isdir(sessions_path)
119
+ and os.path.isdir(episodic_path)
120
+ and os.path.isdir(semantic_path)
121
+ )
122
+
123
+ print(f"[DEBUG] indices_exist: {indices_exist}")
124
+ print(f"[DEBUG] update_memory_index: {update_memory_index}")
125
+
126
+ if update_memory_index or not indices_exist:
127
+ print(f"[DEBUG] Initializing memory indices for {name}...")
128
+
129
+ # Important: build_memory_index must persist to these same absolute paths.
130
+ build_memory_index(memory, data_args, name=name)
131
+
132
+ print("[DEBUG] After build:")
133
+ print(f"[DEBUG] sessions_path exists: {os.path.isdir(sessions_path)}")
134
+ print(f"[DEBUG] episodic_path exists: {os.path.isdir(episodic_path)}")
135
+ print(f"[DEBUG] semantic_path exists: {os.path.isdir(semantic_path)}")
136
+
137
+ def load_index_safe(index_name, index_path):
138
+ if not os.path.isdir(index_path):
139
+ print(f"[DEBUG] {index_name} path does not exist: {index_path}")
140
+ return None
141
+
142
+ try:
143
+ storage_context = StorageContext.from_defaults(
144
+ persist_dir=index_path
145
+ )
146
+ index = load_index_from_storage(storage_context)
147
+ print(
148
+ f"[DEBUG] {index_name} loaded: "
149
+ f"{type(index).__name__}, is_none={index is None}"
150
+ )
151
+ return index
152
+ except Exception as exc:
153
+ print(f"[ERROR] Could not load {index_name}: {exc}")
154
+ traceback.print_exc()
155
+ return None
156
+
157
+ sessions_memory = load_index_safe("sessions_memory", sessions_path)
158
+ episodic_memory = load_index_safe("episodic_memory", episodic_path)
159
+ semantic_memory = load_index_safe("semantic_memory", semantic_path)
160
+
161
+ print("[DEBUG] RETURN VALUES:")
162
+ print(f" hello_msg: Welcome back, {name}!")
163
+ print(f" user_memory type: {type(user_memory).__name__}")
164
+ print(f" sessions_memory type: {type(sessions_memory).__name__}")
165
+ print(f" episodic_memory type: {type(episodic_memory).__name__}")
166
+ print(f" semantic_memory type: {type(semantic_memory).__name__}")
167
+
168
+ return (
169
+ f"Welcome back, {name}!",
170
+ user_memory,
171
+ sessions_memory,
172
+ episodic_memory,
173
+ semantic_memory,
174
+ )
175
+
176
+
177
+ def summarize_memory_event_personality(data_args, memory, user_name):
178
+ """
179
+ Summarizes the memory and returns the user-specific memory dict.
180
+ """
181
+ if isinstance(data_args, gr.State): data_args = data_args.value
182
+ if isinstance(memory, gr.State): memory = memory.value
183
+
184
+ memory_dir = MEMORY_FILE_PATH
185
+
186
+ # Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
187
+ memory = summarize_memory(memory_dir, user_name, language=data_args.language)
188
+ user_memory = memory[user_name] if user_name in memory.keys() else {}
189
+ return user_memory
190
+
191
+
192
+ def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
193
+ """
194
+ Saves user-model conversations into memory and adds episodic memory for each session.
195
+ Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
196
+ """
197
+ if isinstance(data_args, gr.State): data_args = data_args.value
198
+ if isinstance(memory, gr.State): memory = memory.value
199
+
200
+ memory_dir = MEMORY_FILE_PATH
201
+
202
+ # 1. Initialize user memory with ALL required structures FIRST
203
+ if user_name not in memory:
204
+ memory[user_name] = {
205
+ "sessions": [],
206
+ "episodic_memory": [],
207
+ "semantic_memory": {}
208
+ }
209
+
210
+ # 2. Ensure all sub-structures exist and are correct type
211
+ memory[user_name].setdefault("sessions", [])
212
+ memory[user_name].setdefault("episodic_memory", [])
213
+ memory[user_name].setdefault("semantic_memory", {})
214
+
215
+ # 3. Now safely check types
216
+ if not isinstance(memory[user_name]["semantic_memory"], dict):
217
+ memory[user_name]["semantic_memory"] = {}
218
+
219
+ # Create new session or update existing one
220
+ if new_conversation or not memory[user_name]["sessions"]:
221
+ if new_conversation and memory[user_name]["sessions"]:
222
+ # Logic to summarize previous session before starting new one could go here
223
+ pass
224
+
225
+ # Create new session
226
+ session = {
227
+ "session_id": len(memory[user_name]["sessions"]),
228
+ "date": time.strftime("%Y-%m-%d", time.localtime()),
229
+ "conversation": []
230
+ }
231
+ memory[user_name]["sessions"].append(session)
232
+
233
+ current_session = memory[user_name]["sessions"][-1]
234
+
235
+ # --- Modified section to fix KeyError: 0 and handle History formats ---
236
+ if not new_conversation and history:
237
+ last_item = history[-1]
238
+
239
+ # Case 1: New Format (List of Dicts)
240
+ # In this format, history is linear. The last item is bot response, second to last is user query.
241
+ if isinstance(last_item, dict):
242
+ if len(history) >= 2:
243
+ user_query = history[-2].get('content', '')
244
+ bot_response = history[-1].get('content', '')
245
+
246
+ # Verify roles to ensure correct pairing
247
+ if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
248
+ current_session["conversation"].append({
249
+ 'query': user_query,
250
+ 'response': bot_response
251
+ })
252
+
253
+ # Case 2: Old Format (List of Lists/Tuples)
254
+ elif isinstance(last_item, (list, tuple)):
255
+ current_session["conversation"].append({
256
+ 'query': last_item[0],
257
+ 'response': last_item[1]
258
+ })
259
+ # ----------------------------------------------------------------------
260
+
261
+ # Optional: Update semantic memory in real-time
262
+ memory[user_name]["semantic_memory"] = extract_semantic_memory(
263
+ memory[user_name]["semantic_memory"],
264
+ current_session["conversation"]
265
+ )
266
+
267
+ semantic_memory_text = memory[user_name]["semantic_memory"]
268
+
269
+ # Save to file
270
+ # Ensure memory directory exists
271
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
272
+
273
+ with open(memory_dir, "w", encoding="utf-8") as f:
274
+ json.dump(memory, f, ensure_ascii=False, indent=4)
275
+
276
+ return memory, semantic_memory_text
Backup code/memory_utils.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import json
4
+ import time
5
+ import datetime
6
+ import shutil
7
+ import gradio as gr
8
+ from pprint import pprint
9
+
10
+ # LlamaIndex Imports
11
+ from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
12
+
13
+ # Local Imports setup
14
+ # Assuming this file is in 'utils/', we step back to find 'memory_bank'
15
+ bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
16
+ sys.path.append(bank_path)
17
+
18
+ # Import functions from sibling/child modules
19
+ # Ensure these files exist in the appended path
20
+ try:
21
+ from build_memory_index import build_memory_index
22
+ from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
23
+ except ImportError:
24
+ # Fallback or placeholder if running independently for testing
25
+ print("Warning: Could not import memory build/summary modules.")
26
+ def build_memory_index(*args, **kwargs): pass
27
+ def summarize_memory(*args, **kwargs): return {}
28
+ def extract_session_summary(*args, **kwargs): return {}
29
+ def extract_semantic_memory(*args, **kwargs): return {}
30
+
31
+ # --- Global Config for Paths ---
32
+ # Keeping the specific path requested by user
33
+ MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
34
+
35
+
36
+ def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
37
+ """
38
+ Legacy/Basic function to load user memory and initialize vector store.
39
+ """
40
+ cur_date = datetime.date.today().strftime("%Y-%m-%d")
41
+ user_memory_index = None
42
+
43
+ # Handle Gradio States
44
+ if isinstance(data_args, gr.State): data_args = data_args.value
45
+ if isinstance(memory, gr.State): memory = memory.value
46
+ if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
47
+
48
+ memory_dir = MEMORY_FILE_PATH
49
+
50
+ if name in memory.keys():
51
+ user_memory = memory[name]
52
+ memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
53
+ os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
54
+
55
+ if (not os.path.exists(memory_index_path)) or update_memory_index:
56
+ print(f'Initializing memory index {memory_index_path}...')
57
+
58
+ if os.path.exists(memory_index_path):
59
+ shutil.rmtree(memory_index_path)
60
+ # Initialize using the local QA object
61
+ memory_index_path, _ = local_memory_qa.init_memory_vector_store(
62
+ filepath=memory_dir,
63
+ vs_path=memory_index_path,
64
+ user_name=name,
65
+ cur_date=cur_date
66
+ )
67
+
68
+ user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
69
+ msg = f"Welcome back, {name}!"
70
+ return msg, user_memory, memory, name, user_memory_index
71
+ else:
72
+ memory[name] = {}
73
+ memory[name].update({"name": name})
74
+ msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
75
+ return msg, memory[name], memory, name, user_memory_index
76
+
77
+
78
+ def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
79
+ """
80
+ Loads user memory and separate indices for each memory type (sessions, episodic, semantic).
81
+ Compatible with LlamaIndex v0.10+
82
+ """
83
+ sessions_memory = None
84
+ episodic_memory = None
85
+ semantic_memory = None
86
+
87
+ if name in memory.keys():
88
+ user_memory = memory[name]
89
+
90
+ # Set the base path
91
+ base_path = os.path.join(data_args.memory_basic_dir, f'../memories/memory_index/llamaindex/{name}')
92
+
93
+ # Define paths (باید به پوشه‌ها اشاره کنند، نه فایل)
94
+ sessions_path = f"{base_path}/sessions" # یا نام دقیق پوشه شما
95
+ episodic_path = f"{base_path}/episodic_memory"
96
+ semantic_path = f"{base_path}/semantic_memory"
97
+
98
+ # Check if directories exist to decide on rebuilding
99
+ indices_exist = (
100
+ os.path.isdir(sessions_path) and
101
+ os.path.isdir(episodic_path) and
102
+ os.path.isdir(semantic_path)
103
+ )
104
+
105
+ # If indices do not exist or need updating, rebuild them
106
+ if update_memory_index or not indices_exist:
107
+ print(f'Initializing memory indices for {name}...')
108
+ build_memory_index(memory, data_args, name=name)
109
+
110
+ # --- Modified Section: Loading with new LlamaIndex method ---
111
+
112
+ # 1. Load Sessions Memory
113
+ if os.path.exists(sessions_path):
114
+ try:
115
+ storage_context = StorageContext.from_defaults(persist_dir=sessions_path)
116
+ sessions_memory = load_index_from_storage(storage_context)
117
+ print(f' → Loaded sessions memory index for {name}.')
118
+ except Exception as e:
119
+ print(f"Warning: Could not load sessions memory: {e}")
120
+
121
+ # 2. Load Episodic Memory
122
+ if os.path.exists(episodic_path):
123
+ try:
124
+ storage_context = StorageContext.from_defaults(persist_dir=episodic_path)
125
+ episodic_memory = load_index_from_storage(storage_context)
126
+ print(f' → Loaded episodic memory index for {name}.')
127
+ except Exception as e:
128
+ print(f"Warning: Could not load episodic memory: {e}")
129
+
130
+ # 3. Load Semantic Memory
131
+ if os.path.exists(semantic_path):
132
+ try:
133
+ storage_context = StorageContext.from_defaults(persist_dir=semantic_path)
134
+ semantic_memory = load_index_from_storage(storage_context)
135
+ print(f' → Loaded semantic memory index for {name}.')
136
+ except Exception as e:
137
+ print(f"Warning: Could not load semantic memory: {e}")
138
+
139
+ return f"Welcome back, {name}!", user_memory, sessions_memory, episodic_memory, semantic_memory
140
+
141
+ else:
142
+ # New User Initialization
143
+ memory[name] = {"name": name}
144
+ return f"Welcome, new user {name}! I'll remember your name for next time.", memory[name], None, None, None
145
+
146
+
147
+ def summarize_memory_event_personality(data_args, memory, user_name):
148
+ """
149
+ Summarizes the memory and returns the user-specific memory dict.
150
+ """
151
+ if isinstance(data_args, gr.State): data_args = data_args.value
152
+ if isinstance(memory, gr.State): memory = memory.value
153
+
154
+ memory_dir = MEMORY_FILE_PATH
155
+
156
+ # Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
157
+ memory = summarize_memory(memory_dir, user_name, language=data_args.language)
158
+ user_memory = memory[user_name] if user_name in memory.keys() else {}
159
+ return user_memory
160
+
161
+
162
+ def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
163
+ """
164
+ Saves user-model conversations into memory and adds episodic memory for each session.
165
+ Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
166
+ """
167
+ if isinstance(data_args, gr.State): data_args = data_args.value
168
+ if isinstance(memory, gr.State): memory = memory.value
169
+
170
+ memory_dir = MEMORY_FILE_PATH
171
+
172
+ # 1. Initialize user memory with ALL required structures FIRST
173
+ if user_name not in memory:
174
+ memory[user_name] = {
175
+ "sessions": [],
176
+ "episodic_memory": [],
177
+ "semantic_memory": {}
178
+ }
179
+
180
+ # 2. Ensure all sub-structures exist and are correct type
181
+ memory[user_name].setdefault("sessions", [])
182
+ memory[user_name].setdefault("episodic_memory", [])
183
+ memory[user_name].setdefault("semantic_memory", {})
184
+
185
+ # 3. Now safely check types
186
+ if not isinstance(memory[user_name]["semantic_memory"], dict):
187
+ memory[user_name]["semantic_memory"] = {}
188
+
189
+ # Create new session or update existing one
190
+ if new_conversation or not memory[user_name]["sessions"]:
191
+ if new_conversation and memory[user_name]["sessions"]:
192
+ # Logic to summarize previous session before starting new one could go here
193
+ pass
194
+
195
+ # Create new session
196
+ session = {
197
+ "session_id": len(memory[user_name]["sessions"]),
198
+ "date": time.strftime("%Y-%m-%d", time.localtime()),
199
+ "conversation": []
200
+ }
201
+ memory[user_name]["sessions"].append(session)
202
+
203
+ current_session = memory[user_name]["sessions"][-1]
204
+
205
+ # --- Modified section to fix KeyError: 0 and handle History formats ---
206
+ if not new_conversation and history:
207
+ last_item = history[-1]
208
+
209
+ # Case 1: New Format (List of Dicts)
210
+ # In this format, history is linear. The last item is bot response, second to last is user query.
211
+ if isinstance(last_item, dict):
212
+ if len(history) >= 2:
213
+ user_query = history[-2].get('content', '')
214
+ bot_response = history[-1].get('content', '')
215
+
216
+ # Verify roles to ensure correct pairing
217
+ if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
218
+ current_session["conversation"].append({
219
+ 'query': user_query,
220
+ 'response': bot_response
221
+ })
222
+
223
+ # Case 2: Old Format (List of Lists/Tuples)
224
+ elif isinstance(last_item, (list, tuple)):
225
+ current_session["conversation"].append({
226
+ 'query': last_item[0],
227
+ 'response': last_item[1]
228
+ })
229
+ # ----------------------------------------------------------------------
230
+
231
+ # Optional: Update semantic memory in real-time
232
+ # memory[user_name]["semantic_memory"] = extract_semantic_memory(
233
+ # memory[user_name]["semantic_memory"],
234
+ # current_session["conversation"]
235
+ # )
236
+
237
+ semantic_memory_text = memory[user_name]["semantic_memory"]
238
+
239
+ # Save to file
240
+ # Ensure memory directory exists
241
+ os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
242
+
243
+ with open(memory_dir, "w", encoding="utf-8") as f:
244
+ json.dump(memory, f, ensure_ascii=False, indent=4)
245
+
246
+ return memory, semantic_memory_text
Backup code/prompt_utils.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ from llama_index.core import Settings
3
+ from llama_index.embeddings.openai import OpenAIEmbedding
4
+ from llama_index.llms.openai import OpenAI
5
+
6
+ Settings.llm = OpenAI(api_key="GAPGPT_API_KEY", api_base="https://api.gapgpt.app/v1", model="gpt-3.5-turbo")
7
+ Settings.embed_model = OpenAIEmbedding(api_key="GAPGPT_API_KEY", api_base="https://api.gapgpt.app/v1", model="text-embedding-ada-002")
8
+
9
+ boot_name_dict = {'en':'AI Companion'}
10
+ boot_actual_name_dict = {'en':'Emma'}
11
+ def output_prompt(history, user_name, boot_name):
12
+ prompt = f""
13
+ for dialog in history:
14
+ if isinstance(dialog, dict):
15
+ query = dialog.get('query', '')
16
+ response = dialog.get('response', '')
17
+ else:
18
+ query, response = dialog
19
+ prompt += f"\n\n{user_name}:{query}"
20
+ prompt += f"\n\n{boot_name}:{response}"
21
+ return prompt
22
+
23
+ def generate_meta_prompt_dict_chatgpt():
24
+ meta_prompt_dict = {'cn':"""
25
+ You play the role of an AI assistant in the field of psychology for this user ({user_name}).
26
+ Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
27
+ Use the following user-specific details to inform your response:
28
+
29
+ - **User's Psychological Profile:** {}
30
+ - **Summary of Past Interactions:** {}
31
+ - **Relevant Past Conversations:** {related_memory_content}
32
+
33
+ The user has asked:
34
+
35
+ Please provide an insightful and appropriate response considering their personal history.
36
+ """,
37
+ 'en':"""
38
+ You play the role of an AI assistant in the field of psychology for this user ({user_name}).
39
+ Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
40
+ Use the following user-specific details to inform your response:
41
+
42
+ - **User's Psychological Profile:** {personality}
43
+ - **Summary of Past Interactions:** {history_summary}
44
+ - **Relevant Past Conversations:** {related_memory_content}
45
+
46
+ The user has asked:
47
+
48
+ Please provide an insightful and appropriate response considering their personal history.
49
+ """,}
50
+ return meta_prompt_dict
51
+ def generate_meta_prompt_dict_semantic_chatgpt():
52
+ meta_prompt_dict = {'cn':"""
53
+ """,
54
+
55
+ 'en':"""
56
+
57
+ You play the role of an AI assistant in the field of psychology for this user ({user_name}).
58
+ Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
59
+ Use the following user-specific semantic memory{semantic_memory_text} to tailor your response:
60
+ """,}
61
+ return meta_prompt_dict
62
+
63
+ def generate_meta_prompt_dict_semantic_episodic_chatgpt():
64
+ meta_prompt_dict = {'cn':"""
65
+ You play the role of an AI assistant in the field of psychology for this user ({user_name}).
66
+ Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
67
+ Use the following user-specific details to inform your response:
68
+
69
+ - **User's Psychological Profile:** {}
70
+ - **Summary of Past Interactions:** {}
71
+ - **Relevant Past Conversations:** {related_memory_content}
72
+
73
+ The user has asked:
74
+
75
+ Please provide an insightful and appropriate response considering their personal history.
76
+ """,
77
+
78
+ 'en': """
79
+ You are an AI assistant specializing in psychology, assisting the user ({user_name}) in a supportive, scientifically grounded, and empathetic manner.
80
+
81
+ Use the following memory sections to personalize your response:
82
+
83
+ - **User's Long-Term Traits and Psychological Characteristics (Semantic Memory):**
84
+ {semantic_memory_text}
85
+
86
+ - **Important Past Interactions or Events (Episodic Memory):**
87
+ {related_memory_content}
88
+
89
+ Respond by considering both the long-term traits and recent events of the user, offering personalized, emotionally intelligent support. Keep your response helpful, psychologically informed, and sensitive to the user's unique situation.
90
+ """,}
91
+ return meta_prompt_dict
92
+
93
+ def generate_new_user_meta_prompt_dict_chatgpt():
94
+ meta_prompt_dict = {'cn':"""
95
+ Now you will play the role of an companion AI Companion for user {user_name}, and your name is {boot_actual_name}. You should be able to: (1) provide warm companionship to chat users; (2) you are also an excellent psychological counselor, and when users confide in you about their difficulties and seek help, you can provide them with warm and helpful responses.
96
+ """,
97
+ 'en':"""
98
+ Now you will play the role of an companion AI Companion for user {user_name}, and your name is {boot_actual_name}. You should be able to: (1) provide warm companionship to chat users; (2) you are also an excellent psychological counselor, and when users confide in you about their difficulties and seek help, you can provide them with warm and helpful responses.
99
+ """}
100
+ return meta_prompt_dict
101
+
102
+ def generate_user_keyword():
103
+ return {'cn': '[|User|]', 'en': '[|User|]'}
104
+
105
+ def generate_ai_keyword():
106
+ return {'cn': '[|AI|]', 'en': '[|AI|]'}
107
+
108
+
109
+ def build_prompt_with_search_memory_llamaindex(
110
+ history,
111
+ query,
112
+ user_memory,
113
+ user_name,
114
+ user_memory_index,
115
+ service_context,
116
+ api_keys,
117
+ api_index,
118
+ meta_prompt,
119
+ new_user_meta_prompt,
120
+ data_args,
121
+ boot_actual_name,
122
+ semantic_memory_text,
123
+ query_category,
124
+ meta_prompt_semantic,
125
+ meta_prompt_semantic_episodic
126
+ ):
127
+
128
+ memory_search_query = query
129
+ related_memos = ""
130
+
131
+ print("memory_search_query:", memory_search_query)
132
+ #print("Total nodes in index:", len(user_memory_index.docstore.docs))
133
+
134
+ if user_memory_index:
135
+ retried_times = 2
136
+ count = 0
137
+
138
+ while not related_memos and count < retried_times:
139
+ try:
140
+ # تغییر اول: استفاده از as_retriever به جای as_query_engine
141
+ retriever = user_memory_index.as_retriever(
142
+ similarity_top_k=3,
143
+ )
144
+
145
+ # تغییر دوم: استفاده از متد retrieve
146
+ nodes = retriever.retrieve(memory_search_query)
147
+
148
+ # تغییر سوم: استخراج متن از گره‌های پیدا شده
149
+ if nodes:
150
+ related_memos = "\n\n".join([n.node.text for n in nodes])
151
+ else:
152
+ related_memos = ""
153
+
154
+ except Exception as e:
155
+ print(f"Error querying index (attempt {count+1}/{retried_times}): {e}")
156
+
157
+ try:
158
+ api_index = (api_index + 1) % len(api_keys)
159
+ openai.api_key = api_keys[api_index]
160
+ except:
161
+ pass
162
+
163
+ related_memos = ""
164
+
165
+ count += 1
166
+
167
+ # Process history
168
+ print("related_memos found:", len(related_memos) if related_memos else 0)
169
+
170
+ history_summary = ""
171
+ if "overall_history" in user_memory:
172
+ history_summary = f"The summary of your past memories with the user is: {user_memory['overall_history']}"
173
+
174
+ personality = user_memory.get("overall_personality", "")
175
+ print("query_category:", query_category)
176
+
177
+ # Construct the prompt
178
+ if query_category == "semantic_memory":
179
+ prompt = meta_prompt_semantic.format(
180
+ user_name=user_name,
181
+ semantic_memory_text=semantic_memory_text
182
+ )
183
+
184
+ elif query_category == "semantic-episodic":
185
+ prompt = meta_prompt_semantic_episodic.format(
186
+ user_name=user_name,
187
+ history_summary=history_summary,
188
+ related_memory_content=f"\n{str(related_memos).strip()}\n" if related_memos else "None",
189
+ personality=personality,
190
+ boot_actual_name=boot_actual_name,
191
+ semantic_memory_text=semantic_memory_text
192
+ )
193
+
194
+ elif query_category == "episodic_memory":
195
+ if related_memos:
196
+ prompt = meta_prompt.format(
197
+ user_name=user_name,
198
+ history_summary=history_summary,
199
+ related_memory_content=f"\n{str(related_memos).strip()}\n",
200
+ personality=personality,
201
+ boot_actual_name=boot_actual_name
202
+ )
203
+ else:
204
+ prompt = new_user_meta_prompt.format(
205
+ user_name=user_name,
206
+ boot_actual_name=boot_actual_name
207
+ )
208
+
209
+ else:
210
+ prompt = new_user_meta_prompt.format(
211
+ user_name=user_name,
212
+ boot_actual_name=boot_actual_name
213
+ )
214
+
215
+ return prompt, related_memos
Backup code/summarize_memory_v4.py ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ import sys
3
+ import os
4
+ import json
5
+ import time
6
+ import copy
7
+ import argparse
8
+ from typing import Dict, Any
9
+ from openai import OpenAI
10
+
11
+ import openai
12
+
13
+ # Add memory bank path
14
+ sys.path.append('../memory_bank')
15
+
16
+ # Configuration for OpenAI API
17
+ CHATGPT_CONFIG = {
18
+ "model": "gpt-4o",
19
+ "temperature": 0.7,
20
+ "max_tokens": 400,
21
+ "top_p": 1.0,
22
+ "frequency_penalty": 0.4,
23
+ "presence_penalty": 0.2,
24
+ "stop": ["<|im_end|>", "¬Human"]
25
+ }
26
+
27
+ # Default memory directory
28
+ MEMORY_DIR = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
29
+
30
+
31
+ class LLMClientSimple:
32
+ def __init__(self, gen_config=None):
33
+ # ایجاد کلاینت جدید با سینتکس نسخه ۱ به بالا
34
+ # اگر برای GapGPT نیاز به base_url دارید، آن را اینجا اضافه کنید
35
+ self.client = OpenAI(
36
+ api_key=os.getenv("GAPGPT_API_KEY"),
37
+ base_url=os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
38
+ )
39
+ self.disable_tqdm = False
40
+ self.gen_config = gen_config
41
+
42
+ def generate_text_simple(self, prompt, prompt_num, language='en'):
43
+ self.gen_config['n'] = prompt_num
44
+ retry_times, count = 5, 0
45
+ response = None
46
+
47
+ while response is None and count < retry_times:
48
+ try:
49
+ request = copy.deepcopy(self.gen_config)
50
+ # print(prompt)
51
+
52
+ # System prompt setup based on language
53
+ if language == 'cn':
54
+ message = [
55
+ {"role": "system", "content": "The following is a transcript of a conversation between a human and a smart, psychology-savvy AI assistant."},
56
+ {"role": "user", "content": "Hello! Please help me summarize the conversation"},
57
+ {"role": "system", "content": "OK, I'll try to help you."},
58
+ {"role": "user", "content": f"{prompt}"}
59
+ ]
60
+ else:
61
+ message = [
62
+ {"role": "system", "content": "Below is a transcript of a conversation between a human and an AI assistant that is intelligent and knowledgeable in psychology."},
63
+ {"role": "user", "content": "Hello! Please help me summarize the content of the conversation."},
64
+ {"role": "system", "content": "Sure, I will do my best to assist you."},
65
+ {"role": "user", "content": f"{prompt}"}
66
+ ]
67
+
68
+ # فراخوانی متد جدید
69
+ response = self.client.chat.completions.create(**request, messages=message)
70
+ # print(prompt)
71
+
72
+ except Exception as e:
73
+ print(e)
74
+ # بررسی متن خطا در نسخه جدید ممکن است کمی متفاوت باشد
75
+ if 'context' in str(e).lower() or 'maximum' in str(e).lower():
76
+ cut_length = 1800 - 200 * count
77
+ print('max context length reached, cut to {}'.format(cut_length))
78
+ prompt = prompt[-cut_length:]
79
+ response = None
80
+ count += 1
81
+
82
+ if response:
83
+ # خواندن محتوای پاسخ با استفاده از سینتکس شی‌گرا (Dot notation)
84
+ task_desc = response.choices[0].message.content
85
+ else:
86
+ task_desc = ''
87
+
88
+ return task_desc
89
+
90
+
91
+ # Initialize the client
92
+ llm_client = LLMClientSimple(CHATGPT_CONFIG)
93
+
94
+
95
+ # --- Prompt Generation Functions ---
96
+
97
+ def summarize_content_prompt(content, user_name, boot_name, language='en'):
98
+ # Base prompt adjusted based on psychology
99
+ prompt = 'Please summarize the following dialogue from a psychological perspective, focusing on the user\'s emotional state, key concerns, and potential therapeutic insights. Dialogue content:\n'
100
+
101
+ for dialog in content:
102
+ query = dialog['query']
103
+ response = dialog['response']
104
+ prompt += f"\n{user_name}: {query.strip()}"
105
+ prompt += f"\n{boot_name}: {response.strip()}"
106
+
107
+ prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
108
+ return prompt
109
+
110
+
111
+ def summarize_user_issues_prompt(content, user_name, boot_name, language='en'):
112
+ """
113
+ Analyze the conversation from a psychological perspective, identify user problems and their causes,
114
+ and organize them into a structured JSON format.
115
+ """
116
+ prompt = (
117
+ "Please analyze the following dialogue from a psychological perspective. Identify the user's key "
118
+ "problems and the underlying causes behind them. Structure the results in a clear and concise way. "
119
+ "Dialogue content:\n"
120
+ )
121
+
122
+ for dialog in content:
123
+ query = dialog['query']
124
+ response = dialog['response']
125
+ prompt += f"\n{user_name}: {query.strip()}"
126
+ prompt += f"\n{boot_name}: {response.strip()}"
127
+
128
+ prompt += '\n\nPlease list the user’s problems and their causes in JSON format, like this:\n'
129
+ prompt += '{\n "problems": [\n {\n "problem": "<problem_1>",\n "cause": "<cause_1>"\n },\n {\n "problem": "<problem_2>",\n "cause": "<cause_2>"\n }\n ]\n}'
130
+
131
+ return prompt
132
+
133
+
134
+ def summarize_overall_prompt(content, language='en'):
135
+ prompt = 'Please summarize the following events in a high-level manner, and try to be as concise as possible, summarizing and retaining the core key information:\n' if language == 'cn' else "Please provide a highly concise summary of the following event, capturing the essential key information as succinctly as possible. Summarize the event:\n"
136
+
137
+ for date, summary_dict in content:
138
+ summary = summary_dict['content']
139
+ prompt += (f"\nTime {date} The event that occurred was {summary.strip()}" if language == 'cn' else f"At {date}, the events are {summary.strip()}")
140
+
141
+ prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
142
+ return prompt
143
+
144
+
145
+ def summarize_overall_personality(content, language='en'):
146
+ prompt = 'Below are the personality traits and moods of users in multiple conversations, as well as the appropriate response strategies at the time:\n' if language == 'cn' else "The following are the user's exhibited personality traits and emotions throughout multiple dialogues, along with appropriate response strategies for the current situation:"
147
+
148
+ for date, summary in content:
149
+ prompt += (f"\n in time {date} The analysis is {summary.strip()}" if language == 'cn' else f"At {date}, the analysis shows {summary.strip()}")
150
+
151
+ prompt += ('\nPlease give a general summary of the users personality and the most appropriate response strategy for the AI lover, and try to be concise and highly summarized. The summary is:' if language == 'cn' else "Please provide a highly concise and general summary of the user's personality and the most appropriate response strategy for the AI lover, summarized as:")
152
+ return prompt
153
+
154
+
155
+ def summarize_person_prompt(content, user_name, boot_name, language):
156
+ prompt = f"Based on the following dialogue, analyze {user_name}'s emotional state, cognitive patterns, and potential psychological needs. Suggest therapeutic strategies for the AI to respond empathetically and effectively. Dialogue content:\n"
157
+
158
+ for dialog in content:
159
+ query = dialog['query']
160
+ response = dialog['response']
161
+ prompt += f"\n{user_name}: {query.strip()}"
162
+ prompt += f"\n{boot_name}: {response.strip()}"
163
+
164
+ prompt += (f'\n{user_name} personality traits, mood, {boot_name} The response strategy is:' if language == 'cn' else f"\n{user_name}'s personality traits, emotions, and {boot_name}'s response strategy are:")
165
+ return prompt
166
+
167
+
168
+ # --- Memory Extraction Functions ---
169
+
170
+ def extract_session_summary(conversation_text, session_date, session_id):
171
+ """
172
+ Extracts session-level insights and creates an episodic memory entry.
173
+
174
+ Args:
175
+ conversation_text (str): The full conversation from the session.
176
+ session_date (str): The date of the session.
177
+ session_id (int): The index of the session.
178
+
179
+ Returns:
180
+ dict: Extracted episodic memory entry.
181
+ """
182
+ # Prompt to the LLM to extract insights
183
+ insight_prompt = f"""
184
+ Please analyze the following conversation and extract key information:
185
+ Conversation:
186
+ {conversation_text}
187
+
188
+ 1. Topics discussed (as a list)
189
+ 2. User's emotional state (e.g., happy, anxious, stressed)
190
+ 3. Key insights or takeaways (what the user is feeling or thinking)
191
+
192
+ Format response as JSON:
193
+ {{
194
+ "topics_discussed": [],
195
+ "emotional_state": "",
196
+ "insights": ""
197
+ }}
198
+ """
199
+
200
+ response = llm_client.generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
201
+
202
+ # پاکسازی کاراکترهای اضافی و تگ‌های مارک‌داون
203
+ response = response.strip()
204
+ if response.startswith("```json"):response = response[7:]
205
+ elif response.startswith("```"):response = response[3:]
206
+ if response.endswith("```"):response = response[:-3]
207
+ response = response.strip()
208
+ try:
209
+ episodic_memory = json.loads(response)
210
+ except json.JSONDecodeError:
211
+ print("⚠️ Failed to parse episodic memory response!")
212
+ episodic_memory = {
213
+ "topics_discussed": ["N/A"],
214
+ "emotional_state": "unknown",
215
+ "insights": "No insights extracted."
216
+ }
217
+
218
+ # Add session metadata
219
+ episodic_memory["session_date"] = session_date
220
+ episodic_memory["session_id"] = session_id # Store session index
221
+
222
+ return episodic_memory
223
+
224
+
225
+ def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
226
+ """
227
+ Updates semantic memory based on the latest episodic memory.
228
+
229
+ Args:
230
+ latest_episodic_memory (dict): The most recent episodic memory entry.
231
+ existing_semantic_memory (dict): Current state of the user's semantic memory.
232
+
233
+ Returns:
234
+ dict: Updated semantic memory.
235
+ """
236
+ # Use the insights from episodic memory to infer stable traits and patterns
237
+ semantic_prompt = f"""
238
+ Please analyze the following session summary and infer long-term personality traits and stable characteristics:
239
+ Session Summary:
240
+ {json.dumps(latest_episodic_memory, indent=4)}
241
+
242
+ Update the user's semantic memory with:
243
+ 1. Evolving personality traits (Big Five).
244
+ 2. Core values and recurring motivations.
245
+ 3. Behavioral patterns and consistent emotional responses.
246
+ 4. Frequent topics and recurring themes.
247
+
248
+ Format response as JSON:
249
+ {{
250
+ "personality_traits": {{
251
+ "openness": 0.0,
252
+ "conscientiousness": 0.0,
253
+ "extraversion": 0.0,
254
+ "agreeableness": 0.0,
255
+ "neuroticism": 0.0
256
+ }},
257
+ "core_values": [],
258
+ "behavioral_patterns": [],
259
+ "recurring_themes": []
260
+ }}
261
+ """
262
+
263
+ response = llm_client.generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
264
+
265
+ # پاکسازی کاراکترهای اضافی و تگ‌های مارک‌داون
266
+ response = response.strip()
267
+ if response.startswith("```json"):response = response[7:]
268
+ elif response.startswith("```"):response = response[3:]
269
+ if response.endswith("```"):response = response[:-3]
270
+ response = response.strip()
271
+
272
+ # Parse the response
273
+ try:
274
+ new_semantic_data = json.loads(response)
275
+ except json.JSONDecodeError:
276
+ print("⚠️ Failed to parse semantic memory response!")
277
+ return existing_semantic_memory
278
+
279
+ # Merge new data into semantic memory
280
+ updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
281
+
282
+ # Update or average personality traits
283
+ for trait, value in new_semantic_data["personality_traits"].items():
284
+ if trait in updated_semantic_memory.get("personality_traits", {}):
285
+ existing_value = updated_semantic_memory["personality_traits"][trait]
286
+ updated_semantic_memory["personality_traits"][trait] = round((existing_value + value) / 2, 2)
287
+ else:
288
+ updated_semantic_memory.setdefault("personality_traits", {})[trait] = value
289
+
290
+ # Combine core values, avoiding duplicates
291
+ updated_semantic_memory["core_values"] = list(set(
292
+ updated_semantic_memory.get("core_values", []) + new_semantic_data["core_values"]
293
+ ))
294
+
295
+ # Combine behavioral patterns
296
+ updated_semantic_memory["behavioral_patterns"] = list(set(
297
+ updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data["behavioral_patterns"]
298
+ ))
299
+
300
+ # Combine recurring themes
301
+ updated_semantic_memory["recurring_themes"] = list(set(
302
+ updated_semantic_memory.get("recurring_themes", []) + new_semantic_data["recurring_themes"]
303
+ ))
304
+
305
+ print("\n✅ Semantic memory updated successfully!")
306
+ return updated_semantic_memory
307
+
308
+
309
+ # --- Main Logic ---
310
+
311
+ def summarize_memory(memory_dir, name=None, language='en'):
312
+ boot_name = 'AI'
313
+ gen_prompt_num = 1
314
+
315
+ with open(memory_dir, 'r', encoding='utf8') as f:
316
+ memory = json.loads(f.read())
317
+
318
+ for k, v in memory.items():
319
+ if name is not None and k != name:
320
+ continue
321
+
322
+ user_name = k
323
+ print(f'Updating memory for user {user_name}')
324
+
325
+ if v.get('history') is None:
326
+ continue
327
+
328
+ history = v['history']
329
+
330
+ if v.get('summary') is None:
331
+ memory[user_name]['summary'] = {}
332
+ if v.get('personality') is None:
333
+ memory[user_name]['personality'] = {}
334
+ if v.get('issues') is None:
335
+ memory[user_name]['issues'] = {}
336
+
337
+ for date, content in history.items():
338
+ # Check flags to see if update is needed
339
+ his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
340
+ person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
341
+ problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
342
+
343
+ hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
344
+ issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
345
+ person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
346
+
347
+ if his_flag:
348
+ his_summary = llm_client.generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
349
+ memory[user_name]['summary'][date] = {'content': his_summary}
350
+
351
+ if problem_flag:
352
+ issues_summary = llm_client.generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
353
+ memory[user_name]['issues'][date] = {'content': issues_summary}
354
+ print(issues_summary)
355
+
356
+ if person_flag:
357
+ person_summary = llm_client.generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
358
+ memory[user_name]['personality'][date] = person_summary
359
+
360
+ overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
361
+ overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
362
+
363
+ memory[user_name]['overall_history'] = llm_client.generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
364
+ memory[user_name]['overall_personality'] = llm_client.generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
365
+
366
+ with open(memory_dir, 'w', encoding='utf8') as f:
367
+ print(f'Successfully updated memory for {name}')
368
+ json.dump(memory, f, ensure_ascii=False)
369
+ return memory
370
+
371
+
372
+ if __name__ == '__main__':
373
+ summarize_memory('../memories/eng_memory_cases.json', language='en')
Backup code/summarize_memory_v5.py ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ import sys
3
+ import os
4
+ import json
5
+ import time
6
+ import copy
7
+ 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
16
+ sys.path.append('../memory_bank')
17
+
18
+ # Configuration for OpenAI API
19
+ CHATGPT_CONFIG = {
20
+ "model": "gpt-4o",
21
+ "temperature": 0.7,
22
+ "max_tokens": 400,
23
+ "top_p": 1.0,
24
+ "frequency_penalty": 0.4,
25
+ "presence_penalty": 0.2,
26
+ "stop": ["<|im_end|>", "¬Human"]
27
+ }
28
+
29
+ # Default memory directory
30
+ MEMORY_DIR = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
31
+
32
+
33
+ class LLMClientSimple:
34
+ def __init__(self, gen_config=None):
35
+ # ایجاد کلاینت جدید با سینتکس نسخه ۱ به بالا
36
+ # اگر برای GapGPT نیاز به base_url دارید، آن را اینجا اضافه کنید
37
+ self.client = OpenAI(
38
+ api_key=os.getenv("GAPGPT_API_KEY"),
39
+ base_url=os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
40
+ )
41
+ self.disable_tqdm = False
42
+ self.gen_config = gen_config
43
+
44
+ def generate_text_simple(self, prompt, prompt_num, language='en'):
45
+ self.gen_config['n'] = prompt_num
46
+ retry_times, count = 5, 0
47
+ response = None
48
+
49
+ while response is None and count < retry_times:
50
+ try:
51
+ request = copy.deepcopy(self.gen_config)
52
+ # print(prompt)
53
+
54
+ # System prompt setup based on language
55
+ if language == 'cn':
56
+ message = [
57
+ {"role": "system", "content": "The following is a transcript of a conversation between a human and a smart, psychology-savvy AI assistant."},
58
+ {"role": "user", "content": "Hello! Please help me summarize the conversation"},
59
+ {"role": "system", "content": "OK, I'll try to help you."},
60
+ {"role": "user", "content": f"{prompt}"}
61
+ ]
62
+ else:
63
+ message = [
64
+ {"role": "system", "content": "Below is a transcript of a conversation between a human and an AI assistant that is intelligent and knowledgeable in psychology."},
65
+ {"role": "user", "content": "Hello! Please help me summarize the content of the conversation."},
66
+ {"role": "system", "content": "Sure, I will do my best to assist you."},
67
+ {"role": "user", "content": f"{prompt}"}
68
+ ]
69
+
70
+ # فراخوانی متد جدید
71
+ response = self.client.chat.completions.create(**request, messages=message)
72
+ # print(prompt)
73
+
74
+ except Exception as e:
75
+ print(e)
76
+ # بررسی متن خطا در نسخه جدید ممکن است کمی متفاوت باشد
77
+ if 'context' in str(e).lower() or 'maximum' in str(e).lower():
78
+ cut_length = 1800 - 200 * count
79
+ print('max context length reached, cut to {}'.format(cut_length))
80
+ prompt = prompt[-cut_length:]
81
+ response = None
82
+ count += 1
83
+
84
+ if response:
85
+ # خواندن محتوای پاسخ با استفاده از سینتکس شی‌گرا (Dot notation)
86
+ task_desc = response.choices[0].message.content
87
+ else:
88
+ task_desc = ''
89
+
90
+ return task_desc
91
+
92
+
93
+ # Initialize the client
94
+ llm_client = LLMClientSimple(CHATGPT_CONFIG)
95
+
96
+
97
+ # --- Prompt Generation Functions ---
98
+
99
+ def summarize_content_prompt(content, user_name, boot_name, language='en'):
100
+ # Base prompt adjusted based on psychology
101
+ prompt = 'Please summarize the following dialogue from a psychological perspective, focusing on the user\'s emotional state, key concerns, and potential therapeutic insights. Dialogue content:\n'
102
+
103
+ for dialog in content:
104
+ query = dialog['query']
105
+ response = dialog['response']
106
+ prompt += f"\n{user_name}: {query.strip()}"
107
+ prompt += f"\n{boot_name}: {response.strip()}"
108
+
109
+ prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
110
+ return prompt
111
+
112
+
113
+ def summarize_user_issues_prompt(content, user_name, boot_name, language='en'):
114
+ """
115
+ Analyze the conversation from a psychological perspective, identify user problems and their causes,
116
+ and organize them into a structured JSON format.
117
+ """
118
+ prompt = (
119
+ "Please analyze the following dialogue from a psychological perspective. Identify the user's key "
120
+ "problems and the underlying causes behind them. Structure the results in a clear and concise way. "
121
+ "Dialogue content:\n"
122
+ )
123
+
124
+ for dialog in content:
125
+ query = dialog['query']
126
+ response = dialog['response']
127
+ prompt += f"\n{user_name}: {query.strip()}"
128
+ prompt += f"\n{boot_name}: {response.strip()}"
129
+
130
+ prompt += '\n\nPlease list the user’s problems and their causes in JSON format, like this:\n'
131
+ prompt += '{\n "problems": [\n {\n "problem": "<problem_1>",\n "cause": "<cause_1>"\n },\n {\n "problem": "<problem_2>",\n "cause": "<cause_2>"\n }\n ]\n}'
132
+
133
+ return prompt
134
+
135
+
136
+ def summarize_overall_prompt(content, language='en'):
137
+ prompt = 'Please summarize the following events in a high-level manner, and try to be as concise as possible, summarizing and retaining the core key information:\n' if language == 'cn' else "Please provide a highly concise summary of the following event, capturing the essential key information as succinctly as possible. Summarize the event:\n"
138
+
139
+ for date, summary_dict in content:
140
+ summary = summary_dict['content']
141
+ prompt += (f"\nTime {date} The event that occurred was {summary.strip()}" if language == 'cn' else f"At {date}, the events are {summary.strip()}")
142
+
143
+ prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
144
+ return prompt
145
+
146
+
147
+ def summarize_overall_personality(content, language='en'):
148
+ prompt = 'Below are the personality traits and moods of users in multiple conversations, as well as the appropriate response strategies at the time:\n' if language == 'cn' else "The following are the user's exhibited personality traits and emotions throughout multiple dialogues, along with appropriate response strategies for the current situation:"
149
+
150
+ for date, summary in content:
151
+ prompt += (f"\n in time {date} The analysis is {summary.strip()}" if language == 'cn' else f"At {date}, the analysis shows {summary.strip()}")
152
+
153
+ prompt += ('\nPlease give a general summary of the users personality and the most appropriate response strategy for the AI lover, and try to be concise and highly summarized. The summary is:' if language == 'cn' else "Please provide a highly concise and general summary of the user's personality and the most appropriate response strategy for the AI lover, summarized as:")
154
+ return prompt
155
+
156
+
157
+ def summarize_person_prompt(content, user_name, boot_name, language):
158
+ prompt = f"Based on the following dialogue, analyze {user_name}'s emotional state, cognitive patterns, and potential psychological needs. Suggest therapeutic strategies for the AI to respond empathetically and effectively. Dialogue content:\n"
159
+
160
+ for dialog in content:
161
+ query = dialog['query']
162
+ response = dialog['response']
163
+ prompt += f"\n{user_name}: {query.strip()}"
164
+ prompt += f"\n{boot_name}: {response.strip()}"
165
+
166
+ prompt += (f'\n{user_name} personality traits, mood, {boot_name} The response strategy is:' if language == 'cn' else f"\n{user_name}'s personality traits, emotions, and {boot_name}'s response strategy are:")
167
+ return prompt
168
+
169
+
170
+ # --- Memory Extraction Functions ---
171
+
172
+ def extract_session_summary(conversation_text, session_date, session_id):
173
+ """
174
+ Extracts session-level insights and creates an episodic memory entry.
175
+
176
+ Args:
177
+ conversation_text (str): The full conversation from the session.
178
+ session_date (str): The date of the session.
179
+ session_id (int): The index of the session.
180
+
181
+ Returns:
182
+ dict: Extracted episodic memory entry.
183
+ """
184
+ # Prompt to the LLM to extract insights
185
+ insight_prompt = f"""
186
+ Please analyze the following conversation and extract key information:
187
+ Conversation:
188
+ {conversation_text}
189
+
190
+ 1. Topics discussed (as a list)
191
+ 2. User's emotional state (e.g., happy, anxious, stressed)
192
+ 3. Key insights or takeaways (what the user is feeling or thinking)
193
+
194
+ Format response as JSON:
195
+ {{
196
+ "topics_discussed": [],
197
+ "emotional_state": "",
198
+ "insights": ""
199
+ }}
200
+ """
201
+
202
+ response = llm_client.generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
203
+
204
+ # پاکسازی کاراکترهای اضافی و تگ‌های مارک‌داون
205
+ response = response.strip()
206
+ if response.startswith("```json"):response = response[7:]
207
+ elif response.startswith("```"):response = response[3:]
208
+ if response.endswith("```"):response = response[:-3]
209
+ response = response.strip()
210
+ try:
211
+ episodic_memory = json.loads(response)
212
+ except json.JSONDecodeError:
213
+ print("⚠️ Failed to parse episodic memory response!")
214
+ episodic_memory = {
215
+ "topics_discussed": ["N/A"],
216
+ "emotional_state": "unknown",
217
+ "insights": "No insights extracted."
218
+ }
219
+
220
+ # Add session metadata
221
+ episodic_memory["session_date"] = session_date
222
+ episodic_memory["session_id"] = session_id # Store session index
223
+
224
+ return episodic_memory
225
+
226
+
227
+ def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
228
+ """
229
+ Updates semantic memory based on the latest episodic memory.
230
+
231
+ Args:
232
+ latest_episodic_memory (dict): The most recent episodic memory entry.
233
+ existing_semantic_memory (dict): Current state of the user's semantic memory.
234
+
235
+ Returns:
236
+ dict: Updated semantic memory.
237
+ """
238
+ # Use the insights from episodic memory to infer stable traits and patterns
239
+ semantic_prompt = f"""
240
+ Please analyze the following session summary and infer long-term personality traits and stable characteristics:
241
+ Session Summary:
242
+ {json.dumps(latest_episodic_memory, indent=4)}
243
+
244
+ Update the user's semantic memory with:
245
+ 1. Evolving personality traits (Big Five).
246
+ 2. Core values and recurring motivations.
247
+ 3. Behavioral patterns and consistent emotional responses.
248
+ 4. Frequent topics and recurring themes.
249
+
250
+ Format response as JSON:
251
+ {{
252
+ "personality_traits": {{
253
+ "openness": 0.0,
254
+ "conscientiousness": 0.0,
255
+ "extraversion": 0.0,
256
+ "agreeableness": 0.0,
257
+ "neuroticism": 0.0
258
+ }},
259
+ "core_values": [],
260
+ "behavioral_patterns": [],
261
+ "recurring_themes": []
262
+ }}
263
+ """
264
+
265
+ response = llm_client.generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
266
+
267
+ # استخراج امن JSON با استفاده از Regex
268
+ try:
269
+ # پیدا کردن محتوای بین اولین { و آخرین }
270
+ json_match = re.search(r'\{.*\}', response, re.DOTALL)
271
+ if json_match:
272
+ json_str = json_match.group(0)
273
+ new_semantic_data = json.loads(json_str)
274
+ else:
275
+ raise ValueError("No JSON object found in response.")
276
+
277
+ except Exception as e:
278
+ print(f"⚠️ Failed to parse semantic memory response! Error: {e}")
279
+ print(f"LLM Response was:\n{response}") # چاپ خروجی خام برای خطایابی
280
+ return existing_semantic_memory
281
+
282
+ # Merge new data into semantic memory
283
+ updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
284
+
285
+ # Update or average personality traits
286
+ for trait, value in new_semantic_data.get("personality_traits", {}).items():
287
+ try:
288
+ val_float = float(value)
289
+ except (ValueError, TypeError):
290
+ val_float = 0.0
291
+
292
+ if trait in updated_semantic_memory.get("personality_traits", {}):
293
+ existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
294
+ updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
295
+ else:
296
+ updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
297
+
298
+ # Combine core values, avoiding duplicates
299
+ updated_semantic_memory["core_values"] = list(set(
300
+ updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
301
+ ))
302
+
303
+ # Combine behavioral patterns
304
+ updated_semantic_memory["behavioral_patterns"] = list(set(
305
+ updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
306
+ ))
307
+
308
+ # Combine recurring themes
309
+ updated_semantic_memory["recurring_themes"] = list(set(
310
+ updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
311
+ ))
312
+
313
+ print("\n✅ Semantic memory updated successfully!")
314
+ return updated_semantic_memory
315
+
316
+
317
+ # --- Main Logic ---
318
+
319
+ def summarize_memory(memory_dir, name=None, language='en'):
320
+ boot_name = 'AI'
321
+ gen_prompt_num = 1
322
+
323
+ with open(memory_dir, 'r', encoding='utf8') as f:
324
+ memory = json.loads(f.read())
325
+
326
+ for k, v in memory.items():
327
+ if name is not None and k != name:
328
+ continue
329
+
330
+ user_name = k
331
+ print(f'Updating memory for user {user_name}')
332
+
333
+ if v.get('history') is None:
334
+ continue
335
+
336
+ history = v['history']
337
+
338
+ if v.get('summary') is None:
339
+ memory[user_name]['summary'] = {}
340
+ if v.get('personality') is None:
341
+ memory[user_name]['personality'] = {}
342
+ if v.get('issues') is None:
343
+ memory[user_name]['issues'] = {}
344
+
345
+ for date, content in history.items():
346
+ # Check flags to see if update is needed
347
+ his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
348
+ person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
349
+ problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
350
+
351
+ hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
352
+ issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
353
+ person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
354
+
355
+ if his_flag:
356
+ his_summary = llm_client.generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
357
+ memory[user_name]['summary'][date] = {'content': his_summary}
358
+
359
+ if problem_flag:
360
+ issues_summary = llm_client.generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
361
+ memory[user_name]['issues'][date] = {'content': issues_summary}
362
+ print(issues_summary)
363
+
364
+ if person_flag:
365
+ person_summary = llm_client.generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
366
+ memory[user_name]['personality'][date] = person_summary
367
+
368
+ overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
369
+ overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
370
+
371
+ memory[user_name]['overall_history'] = llm_client.generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
372
+ memory[user_name]['overall_personality'] = llm_client.generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
373
+
374
+ with open(memory_dir, 'w', encoding='utf8') as f:
375
+ print(f'Successfully updated memory for {name}')
376
+ json.dump(memory, f, ensure_ascii=False)
377
+ return memory
378
+
379
+
380
+ if __name__ == '__main__':
381
+ summarize_memory('../memories/eng_memory_cases.json', language='en')
Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ COPY wheels/ /wheels/
7
+
8
+ RUN pip install \
9
+ --no-cache-dir \
10
+ --no-index \
11
+ --find-links=/wheels \
12
+ -r requirements.txt
13
+
14
+ COPY . .
15
+
16
+ EXPOSE 7860
17
+
18
+ CMD ["python", "app.py"]
Emma/.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
3
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
5
+ WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
6
+ ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
7
+ MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
8
+ h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
9
+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
10
+ A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
11
+ T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
12
+ B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
13
+ B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
14
+ KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
15
+ OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
16
+ jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
17
+ qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
18
+ rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
19
+ HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
20
+ hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
21
+ ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
22
+ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
23
+ NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
24
+ ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
25
+ TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
26
+ jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
27
+ oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
28
+ 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
29
+ mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
30
+ emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
31
+ -----END CERTIFICATE-----
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/default__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": [-0.054931640625, -0.02520751953125, 0.037078857421875, -0.0305023193359375, 0.034637451171875, 0.0411376953125, 0.01110076904296875, 0.0251007080078125, 0.046966552734375, 0.0552978515625, 0.033721923828125, -0.0107879638671875, -0.0300750732421875, -0.0250396728515625, 0.01258087158203125, 0.012481689453125, -0.00882720947265625, 0.0281524658203125, -0.042327880859375, 0.052154541015625, 0.024017333984375, -0.0105133056640625, -0.0004830360412597656, -0.0036449432373046875, -0.0379638671875, -0.01457977294921875, 0.003505706787109375, 0.01454925537109375, 0.004550933837890625, -0.01016998291015625, 0.016815185546875, -0.02203369140625, -0.016387939453125, 0.0116424560546875, -0.0156097412109375, 0.0236663818359375, -0.0017337799072265625, -0.02197265625, -0.028076171875, -0.00971221923828125, 0.020294189453125, -0.0253448486328125, -0.00411224365234375, 0.03350830078125, -0.04608154296875, -0.032135009765625, -0.0535888671875, -0.0216217041015625, 0.033843994140625, 0.04034423828125, -0.03643798828125, 0.00566864013671875, -0.00656890869140625, 0.024871826171875, -0.00942230224609375, -0.004886627197265625, -0.0081024169921875, 0.0120849609375, 0.0112152099609375, -0.002902984619140625, 0.02862548828125, -0.006313323974609375, 0.0447998046875, 0.037841796875, 0.007534027099609375, -0.033355712890625, -0.00177001953125, 0.004486083984375, 0.021209716796875, 0.0032138824462890625, 0.02606201171875, 0.03466796875, 0.005649566650390625, 0.00010776519775390625, 0.04705810546875, 0.006740570068359375, -0.002140045166015625, -0.02313232421875, -0.0657958984375, -0.08209228515625, 0.001438140869140625, 0.042144775390625, -0.0283660888671875, -0.007312774658203125, -0.0130767822265625, -0.011566162109375, -0.058624267578125, 0.0013074874877929688, 0.003505706787109375, -0.0044708251953125, -0.0137481689453125, -0.0323486328125, -0.019439697265625, 0.0090179443359375, 0.03912353515625, -0.0297698974609375, 0.01306915283203125, -0.001644134521484375, -0.0273284912109375, 0.0286712646484375, -0.0054779052734375, -0.0267791748046875, -0.0168304443359375, 0.035186767578125, 0.0013751983642578125, 0.0310516357421875, 0.035797119140625, -0.032073974609375, -0.0662841796875, -0.016754150390625, -0.018035888671875, -0.0266876220703125, -0.024200439453125, 0.0141448974609375, -0.047821044921875, -0.0018749237060546875, -0.0675048828125, 0.0014486312866210938, 0.0017156600952148438, -0.010955810546875, -0.061065673828125, 0.01116943359375, -0.0062255859375, 0.0153656005859375, 0.003269195556640625, -0.0147705078125, -0.007770538330078125, -0.03277587890625, -0.037261962890625, -0.0229034423828125, 0.039306640625, 0.0310516357421875, 0.01513671875, -0.062225341796875, -0.0599365234375, -0.03570556640625, -0.0010204315185546875, 0.063232421875, -0.0198516845703125, -0.043243408203125, -0.019287109375, -0.01702880859375, -0.01410675048828125, 0.04656982421875, -0.03118896484375, 0.007114410400390625, 0.0230865478515625, 0.05706787109375, 0.0011510848999023438, -0.00873565673828125, 0.0189361572265625, 0.011444091796875, -0.038177490234375, 0.003955841064453125, 0.013092041015625, -0.016815185546875, -0.0018167495727539062, 0.0193023681640625, 0.01378631591796875, -0.0233306884765625, -0.01220703125, 0.0005774497985839844, -0.0161590576171875, 0.00555419921875, -0.0263671875, 0.03973388671875, 0.023040771484375, -0.01412200927734375, -0.07073974609375, -0.09661865234375, 0.005504608154296875, -0.046966552734375, -0.0202789306640625, -0.0110321044921875, -0.0273590087890625, -0.045989990234375, 0.01287841796875, 0.001583099365234375, -0.014739990234375, 0.00970458984375, -0.0013179779052734375, -0.01436614990234375, -0.07598876953125, 0.029022216796875, -0.0418701171875, -0.058349609375, -0.00270843505859375, -0.008758544921875, 0.02044677734375, -0.0064849853515625, 0.007244110107421875, 0.031829833984375, 0.036590576171875, 0.031890869140625, 0.050933837890625, -0.0679931640625, 0.03326416015625, 0.00800323486328125, -0.003330230712890625, 0.015960693359375, 0.0150146484375, 0.0242156982421875, 0.044097900390625, 0.0229339599609375, 0.00921630859375, -0.01265716552734375, 0.003078460693359375, -0.0157623291015625, -0.06280517578125, 0.007007598876953125, 0.038726806640625, 0.01214599609375, 0.0291290283203125, 0.027313232421875, -0.032470703125, -0.00453948974609375, -0.059600830078125, 0.00556182861328125, 0.00991058349609375, 0.002185821533203125, 0.021453857421875, 0.0181121826171875, 0.038177490234375, -0.0128173828125, 0.003292083740234375, 0.0699462890625, 0.0215606689453125, -0.0272216796875, 0.003932952880859375, -0.005397796630859375, 0.01123809814453125, -0.00635528564453125, -0.02386474609375, 0.0002313852310180664, 0.0285797119140625, -0.017974853515625, 0.055572509765625, -0.0022296905517578125, -0.0076904296875, 0.017730712890625, -0.0010900497436523438, -0.007129669189453125, 0.0147705078125, 0.0638427734375, 0.01482391357421875, -0.00930023193359375, -0.01532745361328125, -0.06341552734375, -0.03338623046875, 0.02398681640625, 0.0055389404296875, 0.015869140625, -0.02362060546875, -0.038238525390625, -0.01412200927734375, -0.06463623046875, -0.0218658447265625, -0.0222625732421875, -0.0224761962890625, -0.04864501953125, 0.0762939453125, -0.0116729736328125, 0.00174713134765625, 0.018890380859375, -0.052001953125, -0.06561279296875, 0.0123138427734375, -0.0017070770263671875, -0.0169830322265625, -0.0496826171875, 0.0087127685546875, 0.003437042236328125, 0.02532958984375, 0.003200531005859375, -0.053619384765625, -0.0181121826171875, 0.0194854736328125, -0.0002827644348144531, -0.02484130859375, -0.0235443115234375, 0.0165252685546875, -0.01568603515625, -0.0235443115234375, 0.038482666015625, -0.01519775390625, 0.0091705322265625, 0.00988006591796875, 0.01526641845703125, 0.0279388427734375, -0.0007257461547851562, 0.006549835205078125, -0.055328369140625, 0.043914794921875, 0.010345458984375, -0.01160430908203125, 0.01032257080078125, 0.029052734375, 0.01172637939453125, 0.0004963874816894531, -0.0023193359375, 0.05224609375, -0.06488037109375, 0.0201416015625, 0.018310546875, 0.044891357421875, 0.0123138427734375, 0.027252197265625, -0.0214996337890625, 0.026458740234375, -0.0246429443359375, -0.00786590576171875, -0.01678466796875, 0.0230865478515625, -0.01031494140625, -0.04852294921875, 0.01512908935546875, 0.054901123046875, 0.01465606689453125, 0.0277252197265625, -0.0374755859375, -0.024505615234375, -0.045867919921875, 0.038909912109375, 0.0165557861328125, 8.994340896606445e-05, 0.011474609375, -0.004909515380859375, 0.0176239013671875, -0.0166015625, -0.0301971435546875, -0.07037353515625, -0.026641845703125, -0.015594482421875, 0.042327880859375, -0.0040435791015625, -0.038787841796875, -0.04840087890625, -0.025177001953125, -0.001430511474609375, 0.024932861328125, -0.056732177734375, -0.045074462890625, -0.03277587890625, -0.05279541015625, -0.0020503997802734375, 0.00447845458984375, -0.0391845703125, -0.0072174072265625, -0.01082611083984375, 0.00972747802734375, 0.0208587646484375, -0.00572967529296875, 0.019683837890625, -0.006412506103515625, -0.038818359375, -0.0164031982421875, 0.013671875, 0.022247314453125, -0.05303955078125, 0.006317138671875, 0.00839996337890625, 0.0019626617431640625, 0.015594482421875, 0.0115814208984375, 0.043487548828125, 0.01128387451171875, -0.08782958984375, -0.048583984375, 0.0006170272827148438, -0.0357666015625, 0.0191497802734375, -0.05804443359375, 0.00897216796875, -0.03253173828125, -0.0261383056640625, 0.018280029296875, -0.013763427734375, 0.030487060546875, -0.0003170967102050781, 0.09124755859375, 0.007648468017578125, -0.0119171142578125, -0.0248260498046875, -0.0233917236328125, 0.02484130859375, 0.023223876953125, -0.04638671875, 0.004497528076171875, -0.052581787109375, -0.00972747802734375, -0.0029315948486328125, -0.0123138427734375, -0.040924072265625, -0.0088348388671875, -0.031982421875, -0.0176849365234375, -0.016632080078125, 0.0174560546875, 0.024993896484375, -0.01214599609375, -0.0286712646484375, 0.00749969482421875, -0.0022068023681640625, -0.0209808349609375, -0.005283355712890625, 0.037445068359375, -0.03594970703125, 0.0068206787109375, 0.03460693359375, -0.00835418701171875, 0.0240936279296875, -0.01806640625, 0.0296783447265625, -0.03521728515625, -0.003940582275390625, -0.020721435546875, 0.01079559326171875, 0.05126953125, 0.034393310546875, 0.044647216796875, 0.00931549072265625, -0.0419921875, -0.0034961700439453125, 0.01128387451171875, -0.006893157958984375, 0.006320953369140625, 0.05279541015625, -0.02142333984375, 0.05975341796875, -0.043365478515625, -0.011688232421875, 0.050567626953125, 0.0306549072265625, -0.01079559326171875, 0.024627685546875, -0.03509521484375, 0.0010538101196289062, 0.03631591796875, -0.03265380859375, -0.003444671630859375, 0.018707275390625, 0.0020427703857421875, -0.03955078125, -0.031524658203125, -0.07269287109375, 0.0151519775390625, -0.024749755859375, -0.052825927734375, 0.039794921875, -0.0133056640625, -0.01271820068359375, -0.060546875, 0.0038204193115234375, 0.0086669921875, -0.054229736328125, -0.04022216796875, -0.0287017822265625, -0.01546478271484375, 0.022247314453125, -0.0250396728515625, -0.034576416015625, -0.0010843276977539062, 0.01148223876953125, 0.0469970703125, 0.047576904296875, -0.00046515464782714844, -0.020843505859375, -0.0247802734375, 0.0059661865234375, 0.03033447265625, 0.01398468017578125, 0.0004336833953857422, 0.0040435791015625, 0.006450653076171875, -0.0216217041015625, 0.031646728515625, -0.0156707763671875, 0.0074005126953125, 0.0126190185546875, -0.01052093505859375, -0.01554107666015625, 0.0206451416015625, -0.0098419189453125, 0.0220184326171875, 0.05084228515625, 0.034515380859375, -0.0208740234375, 0.02996826171875, 0.006175994873046875, 0.0292816162109375, -0.025848388671875, -0.00830078125, 0.016876220703125, -0.018218994140625, -0.007320404052734375, 0.016937255859375, -0.0164337158203125, -0.032470703125, -0.0068206787109375, -0.0435791015625, -0.017913818359375, -0.0015134811401367188, 0.04156494140625, 0.048309326171875, -0.01043701171875, -0.0002624988555908203, -0.040069580078125, -0.00959014892578125, 0.0179443359375, -0.009002685546875, 0.024932861328125, 0.03955078125, -0.01776123046875, -0.0181732177734375, -0.002086639404296875, 0.0255279541015625, 0.004474639892578125, 0.0028934478759765625, -0.0156402587890625, 0.0159912109375, -0.0014085769653320312, -0.0214080810546875, 0.010284423828125, 0.0024566650390625, -0.020721435546875, -0.02606201171875, 0.01708984375, -0.043182373046875, -0.01739501953125, -0.01442718505859375, 0.02679443359375, -0.0019121170043945312, 0.0263214111328125, 0.02398681640625, -0.06805419921875, -0.00699615478515625, 0.006587982177734375, -0.0293121337890625, -0.03656005859375, 0.019134521484375, 0.043182373046875, 0.054534912109375, -0.00209808349609375, 0.023101806640625, 0.007122039794921875, -0.002658843994140625, 0.00438690185546875, 0.0374755859375, -0.01459503173828125, 0.0241241455078125, 0.007049560546875, -0.0261993408203125, 0.04534912109375, 0.01139068603515625, 0.0246429443359375, -0.02496337890625, 0.006320953369140625, -0.04107666015625, -0.0282440185546875, -0.00724029541015625, 0.0215606689453125, -0.04217529296875, 0.055023193359375, 0.018096923828125, -0.01044464111328125, 0.0195159912109375, 0.0129241943359375, 0.02593994140625, -0.01287078857421875, 0.0193328857421875, 0.0123138427734375, -0.001644134521484375, 0.0019178390502929688, -0.01207733154296875, 0.0014820098876953125, -0.003997802734375, -0.004291534423828125, 0.002162933349609375, 0.00946044921875, -0.0244903564453125, -0.037353515625, -0.02581787109375, -0.0135955810546875, 0.0589599609375, -0.03253173828125, 0.032928466796875, 0.0577392578125, -0.0014467239379882812, 0.0141448974609375, 0.00023698806762695312, 0.0369873046875, -0.00977325439453125, 0.0226898193359375, 0.0214691162109375, 0.01027679443359375, 0.023193359375, -0.019805908203125, -0.00830841064453125, -0.024993896484375, 0.016845703125, 0.037109375, -0.0018911361694335938, -0.057464599609375, -0.01361083984375, 0.025787353515625, 0.041015625, -0.002197265625, 0.0305938720703125, -0.01258087158203125, 0.00713348388671875, 0.002681732177734375, 0.01369476318359375, 0.018035888671875, -0.051544189453125, -0.00809478759765625, 0.00429534912109375, 0.0089874267578125, 0.0024280548095703125, 0.04412841796875, -0.04083251953125, -0.00908660888671875, -0.006381988525390625, -0.0361328125, -0.00994110107421875, 0.0291900634765625, 0.03704833984375, -0.00789642333984375, -0.032196044921875, 0.01302337646484375, 0.005519866943359375, -0.01434326171875, -0.0004317760467529297, 0.005405426025390625, -0.0026454925537109375, -0.0131683349609375, 0.0279541015625, 0.0008616447448730469, 0.01450347900390625, -0.0017385482788085938, -0.0200958251953125, 0.0260772705078125, -0.0185394287109375, 0.022979736328125, -0.039031982421875, 0.0211639404296875, -0.0129547119140625, -0.0200958251953125, -0.01419830322265625, -0.0391845703125, -0.007625579833984375, -0.0232391357421875, -0.06561279296875, 0.007282257080078125, -0.0034885406494140625, 0.0262908935546875, -0.0220947265625, 0.033203125, 0.004711151123046875, -0.035491943359375, 0.00875091552734375, -0.0158233642578125, 0.013275146484375, 0.00461578369140625, -0.034393310546875, -0.0200958251953125, 0.037139892578125, -0.0111236572265625, -0.0198516845703125, 0.024383544921875, 0.054473876953125, -0.054931640625, -0.01311492919921875, 0.0149383544921875, 0.01374053955078125, 0.01776123046875, -0.002239227294921875, -0.006763458251953125, -0.017913818359375, -0.01039886474609375, 0.006351470947265625, -0.02398681640625, 0.020599365234375, -0.01557159423828125, -0.0010166168212890625, 0.00670623779296875, -0.01081085205078125, 0.060272216796875, -0.01995849609375, 0.0052337646484375, 0.0248565673828125, 0.005584716796875, 0.0278167724609375, 0.004909515380859375, 0.009613037109375, 0.030731201171875, 0.0179443359375, -0.003520965576171875, 0.01171875, -0.007442474365234375, -0.023101806640625, -0.03924560546875, -0.01383209228515625, -0.0052337646484375, 0.0160369873046875, -0.0223388671875, 0.01390838623046875, 0.0214080810546875, -0.005828857421875, 0.03814697265625, -0.02984619140625, -0.0279998779296875, 0.0117950439453125, -0.01288604736328125, 0.0343017578125, -0.00830841064453125, -0.004638671875, -0.011993408203125, 0.014434814453125, 0.03619384765625, -0.0152130126953125, 0.02984619140625, 0.0220794677734375, -0.02874755859375, 0.038848876953125, -0.0092926025390625, 0.0005102157592773438, -0.016815185546875, 0.02093505859375, -0.0088653564453125, -0.00127410888671875, -0.01116943359375, 0.017730712890625, 0.00998687744140625, -0.03326416015625, 0.0077972412109375, 0.020294189453125, -0.034820556640625, 0.03240966796875, -0.0241546630859375, 0.01214599609375, 0.03515625, -0.042755126953125, 0.006427764892578125, -0.01354217529296875, 0.05230712890625, -0.00923919677734375, 0.0069732666015625, 0.0289764404296875, -0.019561767578125, -0.007534027099609375, -0.0130767822265625, 0.01220703125, -0.00032210350036621094, -0.018707275390625, 0.047637939453125, 0.0009469985961914062, 0.00310516357421875, 0.01035308837890625, 0.00086212158203125, -0.0005550384521484375, 0.0243377685546875, 0.04510498046875, 0.02996826171875, 0.0264892578125, -0.0019330978393554688, -0.00562286376953125, -0.01617431640625, 0.0251007080078125, -0.036834716796875, -0.0019893646240234375, -0.017822265625, 8.052587509155273e-05, -0.005615234375, 0.00659942626953125, 0.061309814453125, 0.00043892860412597656, 0.0221405029296875, 0.0174407958984375, -0.04736328125, 0.033966064453125, 0.032745361328125, 0.01323699951171875, 0.004852294921875, -0.03485107421875, -0.006313323974609375, -0.00125885009765625, -0.020294189453125, -0.0328369140625, -0.0298004150390625, -0.0293121337890625, 0.0018672943115234375, -0.00247955322265625, 0.0310821533203125, -0.0113525390625, -0.00937652587890625, -0.00832366943359375, -0.0231170654296875, -0.1217041015625, 0.030029296875, 0.0361328125, -0.0267486572265625, 0.0240631103515625, -0.0140380859375, 0.006755828857421875, 0.03076171875, -0.020416259765625, -0.03668212890625, 0.01453399658203125, -0.0537109375, -0.004825592041015625, -0.02484130859375, -0.0033512115478515625, -0.031768798828125, 0.005588531494140625, -0.004703521728515625, -0.0291900634765625, 0.0156402587890625, -0.055419921875, 0.0175933837890625, -0.01525115966796875, 0.047515869140625, -0.044952392578125, 0.002223968505859375, -0.0389404296875, 0.0113372802734375, 0.009246826171875, 0.00826263427734375, 0.0228729248046875, -0.029876708984375, -0.0157623291015625, 0.0209808349609375, 0.006237030029296875, -0.002902984619140625, -0.0268096923828125, 0.00919342041015625, 0.001434326171875, -0.005886077880859375, 0.0208740234375, 0.0054473876953125, 0.0386962890625, 0.0187530517578125, 0.0306549072265625, -0.00318145751953125, 0.0192108154296875, 0.026611328125, 0.007160186767578125, -0.021942138671875, -0.02392578125, 0.02008056640625, 0.0104217529296875, -0.042633056640625, 0.0228424072265625, 0.037109375, -0.01641845703125, -0.0201568603515625, 0.03179931640625, -0.0123138427734375, -0.0031223297119140625, -0.0016345977783203125, -0.0096435546875, -0.0097198486328125, -0.01555633544921875, 0.0019664764404296875, -0.00400543212890625, -0.00661468505859375, 0.015838623046875, -0.0163726806640625, -0.0555419921875, -0.0013875961303710938, 0.00856781005859375, -0.0220794677734375, -0.011444091796875, 0.005588531494140625, 0.0294036865234375, 0.0162353515625, -0.0164947509765625, 0.019500732421875, 0.0228424072265625, -0.0183563232421875, 0.03326416015625, 0.0034942626953125, 0.00234222412109375, 0.006916046142578125, 0.0255279541015625, 0.005939483642578125, -0.03973388671875, 0.029510498046875, 0.03369140625, -0.007404327392578125, -0.01898193359375, 0.007640838623046875, -0.0291900634765625, 0.028533935546875, 0.0092926025390625, 0.0227203369140625, 0.02374267578125, 0.0179443359375, -0.01212310791015625, -0.0108184814453125, -0.002346038818359375, -0.007648468017578125, -0.026611328125, -0.00769805908203125, 0.007770538330078125, 0.01155853271484375, 0.0011816024780273438, 0.02508544921875, -0.0167999267578125, 0.040069580078125, 0.012420654296875, 0.01177215576171875, 0.007598876953125, 0.01702880859375, 0.0262603759765625, -0.00652313232421875, 0.0001894235610961914, -0.029876708984375, 0.00726318359375, 0.015960693359375, 0.007411956787109375, 0.030792236328125, -0.01239013671875, 0.04620361328125, 0.022735595703125, -0.01161956787109375, -0.0174560546875, 0.03826904296875, 0.0164794921875, 0.01549530029296875, -0.0239105224609375, 0.01503753662109375, 0.0174407958984375, -0.0025386810302734375, 0.041259765625, -0.01548004150390625, 0.00455474853515625, 0.041168212890625, 0.0176239013671875, 0.0101776123046875, 0.0191802978515625, -0.0017881393432617188, -0.01123809814453125, 0.018096923828125, -0.0374755859375, -0.0073699951171875, -0.0064697265625, 0.0298309326171875, 0.01230621337890625, -0.0311431884765625, 0.004425048828125, 0.0335693359375, 0.0252532958984375, 0.038421630859375, -0.014129638671875, -0.01387786865234375, -0.01812744140625, 0.034942626953125, -0.02520751953125, 0.0341796875, 0.02667236328125, 0.0005617141723632812, 0.044921875, -0.004840850830078125, -0.033935546875, -0.0220489501953125, -0.00640869140625, 0.034088134765625, -0.0362548828125, 0.0174407958984375, 0.0061492919921875, 0.01458740234375, 0.015899658203125, 0.0379638671875, -0.01131439208984375, 0.006542205810546875, -0.00179290771484375, 0.0085296630859375, 0.01146697998046875, 0.02093505859375, 0.0021457672119140625, 0.0177459716796875, 0.0672607421875, 0.01468658447265625, -0.031890869140625, 0.0136260986328125, -0.04779052734375, 0.0026302337646484375, 0.0019102096557617188, 0.04449462890625, 0.05194091796875, 0.06732177734375, -0.009490966796875, -0.027923583984375, 0.00867462158203125, 0.003345489501953125, -0.029510498046875, -0.01165771484375, -0.01531219482421875, 0.031646728515625, 0.02099609375, -0.01568603515625, 0.049530029296875, 0.0262908935546875, -0.032928466796875, 0.01187896728515625, 0.0062713623046875, -9.238719940185547e-06, -0.016815185546875, -0.0018978118896484375, -0.019317626953125, -0.04046630859375, -0.04296875, 0.026824951171875, -0.017120361328125, -0.00214385986328125, 0.0194549560546875, -0.010955810546875, -0.01617431640625, 0.0010461807250976562, -0.00955963134765625, -0.00347137451171875, -0.0132904052734375, 0.0218658447265625, -0.0227508544921875, 0.00012195110321044922, 0.01279449462890625, 0.0077056884765625, 0.024383544921875, -0.02777099609375, -0.0026092529296875, 0.00518798828125, 0.0030803680419921875, 0.006565093994140625, 0.0123138427734375, -0.0185394287109375, 0.0156707763671875, -0.030487060546875, 0.04388427734375, 0.00988006591796875, -0.0008020401000976562, -0.037322998046875, -0.019439697265625, -0.0211944580078125, 0.0019931793212890625, 0.01406097412109375, 0.03717041015625, -0.00634765625, -0.0227813720703125, -0.01506805419921875, 0.022796630859375, -0.03271484375, 0.0189056396484375, 0.01306915283203125, -0.0037250518798828125, 0.0143585205078125, 0.0012950897216796875, 0.0230255126953125, -0.020904541015625, 0.00643157958984375, -0.0168609619140625, -0.040435791015625, -0.0086822509765625, -0.00458526611328125, 0.00226593017578125, -0.01910400390625, 0.0156402587890625, 0.03167724609375, -0.0200653076171875, 0.038482666015625, 0.0156707763671875, -0.001010894775390625, 0.00226593017578125, -0.0160675048828125, -0.005401611328125, -0.020050048828125, 0.03759765625, 0.0189208984375, -0.023223876953125, -0.026641845703125, 0.03863525390625, -0.00939178466796875, 0.0207366943359375, -0.004604339599609375, -0.043182373046875, -0.04156494140625, 0.0026073455810546875, 0.005069732666015625, 0.002468109130859375, -0.0006465911865234375, 0.0242767333984375, 0.0013246536254882812, -0.0384521484375, 0.039886474609375, -0.006633758544921875, 0.0305938720703125, 0.0297698974609375, -0.03045654296875, -0.006866455078125, -0.031158447265625, 0.02008056640625, 0.0022068023681640625, -0.0126495361328125, 0.04388427734375, -0.00724029541015625, -0.01548004150390625, -0.0037822723388671875, -0.0004825592041015625, -0.0222015380859375, -0.01904296875, 0.0048980712890625, 0.0205078125, 0.002590179443359375, 0.0094146728515625, 0.046478271484375, -0.018096923828125, -0.007762908935546875, -0.003841400146484375, -0.01641845703125, 0.017852783203125, 0.007122039794921875, -0.009552001953125, -0.016448974609375, -0.005054473876953125, 0.0200347900390625, -0.026641845703125, -0.00911712646484375, -0.007320404052734375, -0.039947509765625, -0.020599365234375, 0.0007290840148925781, 0.0194854736328125, 0.00876617431640625, 0.038421630859375, 0.007167816162109375, 0.007171630859375, -0.0340576171875, -0.026611328125, -0.0125579833984375, -0.03851318359375, -0.0004596710205078125, -0.00670623779296875, 0.0117950439453125, -0.0301361083984375, -0.01837158203125, 0.019683837890625, 0.019805908203125, 0.0229339599609375, 0.0889892578125, 0.003894805908203125, -0.023193359375, 0.034759521484375, -0.0269775390625, 0.00244903564453125, -0.010528564453125, 0.0013494491577148438, -0.0479736328125, 0.01141357421875, -0.0226593017578125, 0.036773681640625, 0.022491455078125, 0.029937744140625, 0.0013170242309570312, 0.039703369140625, -0.0226593017578125, 0.032318115234375, 0.01236724853515625, -0.0050201416015625, 0.0130462646484375, 0.0092620849609375, 0.037750244140625, -0.02874755859375, -0.00965118408203125, 0.009246826171875, 0.04437255859375, -0.01319122314453125, -0.0023288726806640625, 0.0015544891357421875, 0.006256103515625, -0.05596923828125, 0.00444793701171875, 0.01346588134765625, -0.0163726806640625, 0.01898193359375, -0.00807952880859375, 0.035552978515625, -0.0055084228515625, 0.016021728515625, 0.030853271484375, -0.006847381591796875, 0.0298004150390625, -0.0180206298828125, 0.0024700164794921875, 0.0175628662109375, -0.015594482421875, 0.0145111083984375, -0.00841522216796875, 0.01450347900390625, 0.0009632110595703125, 0.0280609130859375, -0.0400390625, -0.0222625732421875, -0.0361328125, 0.005054473876953125, -0.000438690185546875, 0.03033447265625, 0.0282440185546875, 0.0084075927734375, -0.027374267578125, 0.01467132568359375, -0.00655364990234375, 0.03228759765625, 0.031829833984375, -0.048736572265625, -0.0032367706298828125, -0.00531768798828125, -0.023468017578125, 0.01317596435546875, 0.02252197265625, 0.01544189453125, -0.0088958740234375, -0.010498046875, 0.00019824504852294922, 0.0309600830078125, 0.0161590576171875, 0.0203399658203125, 0.037872314453125, -0.00226593017578125, 0.0159454345703125, -0.002368927001953125, -0.01079559326171875, -0.02008056640625, 0.0036487579345703125, -0.00968170166015625, -0.0003581047058105469, 0.039459228515625, -0.0180816650390625, 0.007720947265625, -0.00916290283203125, 0.00469207763671875, 0.01071929931640625, 0.0292510986328125, 0.0095672607421875, 0.01287841796875, -0.0232391357421875, -0.0013170242309570312, 0.0258026123046875, -0.0199432373046875, 0.041290283203125, 0.002376556396484375, -0.04132080078125, 0.0032939910888671875, -0.00467681884765625, -0.0164337158203125, -0.0262451171875, -0.001743316650390625, -0.056640625, -0.022247314453125, 0.00786590576171875, 0.0318603515625, 0.017852783203125, -0.00933074951171875, -0.004825592041015625, -0.015411376953125, -0.024383544921875, -0.026611328125, -0.0113677978515625, -0.046875, 0.0416259765625, -0.005565643310546875, -0.0033817291259765625, -0.0218963623046875, -0.0014104843139648438, 0.005580902099609375, 0.0132598876953125, -0.0112457275390625, -0.0268096923828125, -0.002349853515625, -0.01174163818359375, 0.0201568603515625, 0.016082763671875, -0.0269012451171875, 0.02288818359375, 0.00519561767578125, 0.005401611328125, -0.043853759765625, -0.0175323486328125, 0.0024662017822265625, -0.00428009033203125, 0.0172576904296875, -0.0174560546875, -0.030059814453125, 0.0283050537109375, -0.0023059844970703125, 0.00604248046875, -0.0287322998046875, 0.032470703125, 0.0340576171875, -0.0025653839111328125, -0.038421630859375, 0.02655029296875, 0.042572021484375, 0.01052093505859375, -0.005970001220703125, 0.0198974609375, -0.053131103515625, 0.0037593841552734375, -0.00858306884765625, 0.0012407302856445312, 0.0085296630859375, -0.034149169921875, -0.011749267578125, 0.0243377685546875, 0.01104736328125, -0.0015096664428710938, 0.01076507568359375, 0.0034465789794921875, 0.016510009765625, 0.00899505615234375, -0.0256500244140625, 0.023284912109375, 0.031494140625, 0.052490234375, -0.00299072265625, 0.0168304443359375, 0.0002148151397705078, -0.03076171875, 0.0002372264862060547, -0.00557708740234375, -0.0316162109375, -0.0038166046142578125, -0.0035953521728515625, 0.014495849609375, -0.0018768310546875, 0.0293121337890625, -0.0074005126953125, 0.0144195556640625, -0.0181121826171875, -0.020477294921875, -0.00804901123046875, 0.006809234619140625, -0.015594482421875, 0.0269317626953125, 0.04052734375, -0.0032138824462890625, 0.01983642578125, -0.0293121337890625, 0.024261474609375, -0.00284576416015625, -0.04925537109375, -0.06500244140625, 0.0245361328125, 0.01079559326171875, 0.0479736328125, -0.03155517578125, -0.036102294921875, 0.0026721954345703125, 0.013427734375, 0.002651214599609375, 0.0107879638671875, 0.007598876953125, -0.01178741455078125, 0.0101776123046875, 0.007152557373046875, -0.0249786376953125, 0.0277099609375, -0.0190887451171875, -0.01364898681640625, 0.004566192626953125, -0.004619598388671875, 0.0089569091796875, -0.0479736328125, 0.01456451416015625, 0.00484466552734375, 0.032806396484375, 0.006717681884765625, 0.0188751220703125, -0.0343017578125, 0.058746337890625, -0.0159759521484375, -0.0169219970703125, -0.03326416015625, 0.0210723876953125, 0.011016845703125, -0.03369140625, 0.0003204345703125, -0.003993988037109375, -0.0273284912109375, 0.01103973388671875, -0.006931304931640625, -0.00217437744140625, 0.009735107421875, 0.0042266845703125, 0.0228729248046875, -0.0013265609741210938, -0.0101165771484375, -0.0213623046875, 0.00923919677734375, -0.0176849365234375, 0.0338134765625, 0.01459503173828125, -0.01071929931640625, -0.035980224609375, 0.01251220703125, -0.0108184814453125, 0.0013952255249023438, -0.0222015380859375, -0.0390625, -0.0236358642578125, -0.0111083984375, -0.00807952880859375, -0.002101898193359375, 0.0289154052734375, 0.01442718505859375, -0.021728515625, -0.012786865234375, -0.043609619140625, 0.0216827392578125, -0.02899169921875, 0.029449462890625, -0.02532958984375, -0.03369140625, -0.014129638671875, 0.01160430908203125, 0.00330352783203125, 0.005031585693359375, 0.0030727386474609375, -0.004428863525390625, -0.0355224609375, 0.036865234375, -0.018463134765625, 0.0009975433349609375, 0.005962371826171875, -0.0116729736328125, -0.0164642333984375, 0.005481719970703125, 0.06842041015625, -0.01390838623046875, 0.0247650146484375, 0.0306549072265625, -0.0235748291015625, -0.01165008544921875, 0.0252532958984375, 0.017974853515625, -0.0030384063720703125, -0.01372528076171875, 0.0016460418701171875, 0.03515625, -0.00933837890625, -0.0272369384765625, 0.00634002685546875, -0.0162811279296875, 0.011016845703125, -0.006999969482421875, 0.0084686279296875, 0.0083160400390625, -0.017578125, -0.0009016990661621094, -0.006259918212890625, 0.01007080078125, 0.0008511543273925781, 0.0029315948486328125, 0.018585205078125, -0.00858306884765625, 0.005641937255859375, 0.0010890960693359375, -0.003620147705078125, 0.0014934539794921875, 0.0106201171875, -0.00811767578125, 0.03424072265625, 0.00383758544921875, 0.01275634765625, 0.010101318359375, 0.0036296844482421875, 0.00637054443359375, -0.005092620849609375, -0.0019702911376953125, 0.041015625, -0.0193328857421875, -0.01491546630859375, -0.002170562744140625, 0.0167236328125, 0.0161895751953125, 0.0086669921875, 0.004405975341796875, 0.004619598388671875, -0.0034942626953125, -0.027435302734375, -0.0194244384765625, 0.024688720703125, -0.0117645263671875, -0.01027679443359375, 0.035308837890625, 0.043975830078125, -0.0218048095703125, -0.0027790069580078125, 0.0235443115234375, -0.004062652587890625, 0.0255126953125, -0.0097198486328125, 0.0010595321655273438, 0.0031871795654296875, 0.01111602783203125, 0.019805908203125, 0.02685546875, -0.0134124755859375, 0.022735595703125, -0.02545166015625, -0.021820068359375, 0.0236968994140625, 0.006500244140625, -0.0268402099609375, -0.007404327392578125, 0.02032470703125, -0.0221710205078125, -0.011810302734375, 0.030914306640625, 0.00800323486328125, -0.0007004737854003906, -0.0013952255249023438, -0.0200347900390625, 0.002346038818359375, -0.0092620849609375, -0.0104217529296875, -0.00467681884765625, -0.009765625, -0.0294189453125, 0.0338134765625, -0.0399169921875, 0.0289154052734375, 0.01226806640625, 0.0017671585083007812, -0.038665771484375, 0.0006999969482421875, 0.0064849853515625, -0.0179595947265625], "5692100e-6f1f-48eb-95e5-e02bb96eecb3": [-0.0308685302734375, -0.034637451171875, 0.007659912109375, 0.0012655258178710938, 0.00787353515625, 0.01068115234375, 0.003086090087890625, 0.048187255859375, 0.0289459228515625, 0.05548095703125, 0.02923583984375, -0.025848388671875, -0.0187225341796875, -0.042327880859375, -0.005161285400390625, 0.034088134765625, -0.008941650390625, 0.04534912109375, -0.03094482421875, 0.0242156982421875, 0.047027587890625, 0.0275726318359375, -0.0181427001953125, 0.007293701171875, -0.0208892822265625, 0.0090484619140625, 0.0011243820190429688, 0.005584716796875, -0.0124664306640625, -0.0159912109375, -0.004913330078125, -0.022247314453125, 0.012176513671875, 0.00836944580078125, -0.0153350830078125, 0.038238525390625, -0.01364898681640625, -0.00948333740234375, -0.00433349609375, -0.01065826416015625, 0.01453399658203125, -0.033477783203125, 0.0097503662109375, 0.0293731689453125, -0.022705078125, 0.002841949462890625, -0.038055419921875, -0.0018558502197265625, 0.0413818359375, 0.00555419921875, -0.0433349609375, 0.022979736328125, 0.0212249755859375, 0.0204620361328125, 0.0273895263671875, -0.0120086669921875, 0.00046539306640625, 0.0282135009765625, -0.0242156982421875, 0.03515625, 0.0655517578125, -0.0272216796875, 0.011566162109375, 0.01235198974609375, 0.00807952880859375, -0.034698486328125, 0.006977081298828125, -0.00669097900390625, 0.01959228515625, 0.0057830810546875, 0.062225341796875, 0.0272674560546875, -0.0013208389282226562, -0.01354217529296875, 0.007843017578125, -0.00897216796875, 0.030731201171875, -0.009063720703125, -0.041473388671875, -0.0794677734375, 0.0176544189453125, 0.03131103515625, -0.0287628173828125, -0.00539398193359375, -0.03466796875, -0.039337158203125, -0.07171630859375, 0.003200531005859375, -0.0157470703125, -0.024078369140625, -0.032684326171875, -0.024078369140625, -0.03704833984375, 0.0201568603515625, 0.04888916015625, -0.0273895263671875, 0.0234832763671875, 0.028900146484375, -0.01220703125, -0.01000213623046875, -0.024261474609375, -0.0199432373046875, -0.060791015625, 0.0014801025390625, 0.006099700927734375, 0.01438140869140625, 0.035125732421875, -0.02716064453125, -0.058013916015625, 0.02154541015625, -0.0548095703125, 0.027435302734375, -0.001232147216796875, 0.047943115234375, -0.05657958984375, -0.023895263671875, -0.0614013671875, -0.01142120361328125, -0.01448822021484375, 0.01149749755859375, -0.04241943359375, 0.006824493408203125, -0.02001953125, 0.032623291015625, -0.0086212158203125, -0.02008056640625, 0.01300048828125, -0.008819580078125, -0.044677734375, -0.021087646484375, 0.03765869140625, -0.0052642822265625, 0.0227203369140625, -0.04083251953125, -0.050506591796875, -0.04595947265625, -0.0028171539306640625, 0.042327880859375, -0.0163116455078125, -0.0015697479248046875, 0.016326904296875, -0.01366424560546875, -0.01528167724609375, 0.036224365234375, -0.0231170654296875, -0.01421356201171875, -0.006763458251953125, 0.052642822265625, -0.051544189453125, 0.0236358642578125, 0.04986572265625, 0.031341552734375, -0.033447265625, 0.01250457763671875, 0.0037708282470703125, -0.001617431640625, 0.0128173828125, 0.0035800933837890625, -0.00286102294921875, -0.032989501953125, -0.006298065185546875, -0.046783447265625, 0.0018444061279296875, -0.022979736328125, 0.036895751953125, 0.042449951171875, 0.01276397705078125, -0.00677490234375, -0.0287322998046875, -0.0770263671875, -0.0294189453125, -0.04132080078125, -0.025634765625, 0.04901123046875, -0.0352783203125, -0.0452880859375, 0.0408935546875, -0.0124664306640625, -0.01131439208984375, 0.0270233154296875, -0.0169525146484375, 0.01544189453125, -0.03875732421875, 0.0003695487976074219, -0.042144775390625, -0.0435791015625, -0.01195526123046875, -0.03387451171875, 0.041473388671875, -0.0010852813720703125, 0.0161895751953125, 0.028350830078125, 0.0232086181640625, -0.0016603469848632812, 0.047271728515625, -0.056976318359375, 0.042144775390625, -0.00734710693359375, -0.046356201171875, 0.0523681640625, -0.002193450927734375, -0.0031528472900390625, 0.03277587890625, -0.0016326904296875, 0.03704833984375, -0.059356689453125, 0.0253448486328125, 0.006378173828125, -0.04302978515625, 0.0543212890625, 0.0287933349609375, 0.004638671875, 0.053680419921875, 0.020355224609375, -0.022125244140625, 0.050079345703125, -0.033905029296875, 0.001697540283203125, 0.003086090087890625, 0.0265045166015625, -0.007122039794921875, 0.0233306884765625, 0.07537841796875, -0.027618408203125, 0.00548553466796875, 0.0213775634765625, 0.05047607421875, 0.0012865066528320312, 0.0059967041015625, -0.04986572265625, 0.0102081298828125, -0.026123046875, -0.0020656585693359375, -0.0265655517578125, 0.0299835205078125, -0.030029296875, 0.052825927734375, 0.0033740997314453125, -0.00244903564453125, 0.007709503173828125, 0.001491546630859375, 0.00994110107421875, 0.027557373046875, 0.066650390625, 0.046295166015625, 0.020843505859375, -0.03741455078125, -0.0947265625, 0.002460479736328125, 0.01708984375, 0.03448486328125, 0.0040130615234375, 0.05389404296875, -0.01800537109375, -0.0254364013671875, -0.04119873046875, 0.007541656494140625, -0.044891357421875, -0.01303863525390625, -0.0201568603515625, 0.04541015625, -0.0245513916015625, 0.036590576171875, 0.019775390625, -0.03369140625, -0.054595947265625, -0.004924774169921875, 0.018310546875, -0.01335906982421875, -0.04974365234375, -0.0216522216796875, -0.009979248046875, 0.0157012939453125, 0.0279083251953125, -0.054901123046875, -0.01081085205078125, 0.009613037109375, 0.053619384765625, -0.0255126953125, 0.027435302734375, 0.00853729248046875, 0.03460693359375, -0.00815582275390625, 0.0293426513671875, 0.021148681640625, 0.03680419921875, 0.00720977783203125, -0.01329803466796875, -0.016387939453125, 0.004489898681640625, -0.003032684326171875, -0.0236663818359375, 0.0278778076171875, 0.0361328125, -0.01139068603515625, -0.017852783203125, 0.0203094482421875, 0.001415252685546875, -0.00151824951171875, -0.01132965087890625, 0.049041748046875, -0.027801513671875, -0.0178375244140625, 0.038482666015625, 0.024169921875, 0.0123443603515625, 0.049163818359375, 0.0219268798828125, 0.030731201171875, -0.051177978515625, 0.0003409385681152344, 0.0283660888671875, 0.04193115234375, 0.0102691650390625, -0.06732177734375, 0.0231170654296875, 0.0543212890625, 0.033935546875, 0.023590087890625, -0.034393310546875, -0.04852294921875, -0.01221466064453125, 0.040863037109375, -0.0172576904296875, -0.01030731201171875, -0.01361083984375, 0.032684326171875, 0.020904541015625, -0.0152130126953125, -0.0210113525390625, -0.03228759765625, -0.042724609375, -0.014617919921875, 0.0298614501953125, 0.0465087890625, -0.03948974609375, -0.0154571533203125, -0.0240478515625, -0.010101318359375, 0.0010461807250976562, -0.037628173828125, -0.040313720703125, -0.060455322265625, -0.01184844970703125, 0.015350341796875, 0.01462554931640625, -0.0079803466796875, -0.0096435546875, 0.0015668869018554688, 0.0228424072265625, 0.03033447265625, 0.033172607421875, -0.0017976760864257812, -0.00635528564453125, -0.034912109375, -0.03277587890625, 0.0012969970703125, 0.005153656005859375, -0.024993896484375, 0.003875732421875, 0.0016736984252929688, -0.0245361328125, 0.0111541748046875, 0.01149749755859375, 0.0550537109375, -0.016632080078125, -0.05078125, -0.040985107421875, -0.01081085205078125, -0.06591796875, 0.017059326171875, -0.0455322265625, 0.041717529296875, -0.043121337890625, -0.0340576171875, 0.0244903564453125, -0.0106964111328125, 0.022705078125, 0.005596160888671875, 0.08660888671875, 0.056671142578125, -0.032867431640625, -0.048919677734375, -0.040069580078125, 0.0020694732666015625, 0.0293731689453125, -0.0112762451171875, -0.037933349609375, -0.00391387939453125, -0.021331787109375, 0.0188751220703125, -0.0252532958984375, -0.05242919921875, -0.03765869140625, -0.00995635986328125, 0.0158843994140625, -0.02752685546875, 0.049102783203125, 0.0232086181640625, -0.0533447265625, -0.01187896728515625, 0.050506591796875, -0.0115814208984375, 0.01467132568359375, -0.013641357421875, 0.0110015869140625, -0.034210205078125, 0.008270263671875, 0.0119476318359375, 0.001590728759765625, 0.05401611328125, -0.061614990234375, 0.0163421630859375, -0.0050811767578125, 0.0093536376953125, -0.029998779296875, 0.059234619140625, -0.0088348388671875, 0.0458984375, 0.036102294921875, 0.0207977294921875, -0.033843994140625, -0.0038604736328125, 0.034088134765625, -0.0200042724609375, 0.044158935546875, 0.0264892578125, -0.0200042724609375, 0.058563232421875, -0.056915283203125, 0.01224517822265625, 0.01555633544921875, 0.0094146728515625, -0.0196685791015625, 0.004497528076171875, -0.01464080810546875, 0.002307891845703125, 0.0634765625, -0.048553466796875, -0.031280517578125, -0.0031032562255859375, -0.007762908935546875, -0.056396484375, -0.0180816650390625, -0.047119140625, 0.04437255859375, -0.0301666259765625, -0.0462646484375, 0.005359649658203125, -0.0229949951171875, 0.00860595703125, -0.027496337890625, 0.00832366943359375, 0.019439697265625, -0.044158935546875, -0.050689697265625, -0.0003840923309326172, -0.0099945068359375, 0.02587890625, -0.03240966796875, -0.019073486328125, 0.0027256011962890625, -0.026580810546875, 0.044586181640625, 0.01904296875, -0.0101776123046875, -0.01526641845703125, -0.0230712890625, -0.013092041015625, 0.040679931640625, 0.0119171142578125, 0.0120086669921875, 0.02001953125, 0.01320648193359375, -0.052520751953125, 0.0157623291015625, -0.014404296875, -0.0269927978515625, -0.0147705078125, 0.011016845703125, 0.0310821533203125, 0.0355224609375, 0.01364898681640625, 0.034332275390625, 0.05841064453125, 0.006633758544921875, 0.0094146728515625, -0.0014591217041015625, 0.03729248046875, 0.014617919921875, 0.00765228271484375, -0.00431060791015625, 0.0516357421875, -0.0160369873046875, 0.0162506103515625, 0.031494140625, 0.004638671875, -0.01241302490234375, 0.01186370849609375, -0.0455322265625, -0.004390716552734375, 0.0280609130859375, 0.011749267578125, 0.059661865234375, 0.01187896728515625, -0.0179443359375, -0.052642822265625, 0.00012362003326416016, 0.002399444580078125, -0.00878143310546875, -0.01084136962890625, -0.021881103515625, -0.0282135009765625, 0.005153656005859375, 0.01015472412109375, 0.0204010009765625, 0.01158905029296875, 0.007274627685546875, -0.023284912109375, -0.00537872314453125, -0.0159912109375, -0.007404327392578125, 0.014068603515625, 0.0029773712158203125, -0.038909912109375, -0.0127410888671875, 0.0034084320068359375, -0.0047607421875, -0.006763458251953125, -0.0181427001953125, 0.0189361572265625, -0.0178985595703125, 0.0202178955078125, 0.02374267578125, -0.062286376953125, 0.0234375, -0.0052642822265625, -0.03265380859375, -0.01244354248046875, 0.006072998046875, 0.02581787109375, 0.037384033203125, 0.02288818359375, 0.0185546875, -0.0003085136413574219, 0.00794219970703125, 0.01215362548828125, 0.02496337890625, -0.042510986328125, 0.008331298828125, -0.00023829936981201172, -0.034271240234375, 0.040618896484375, -0.0218963623046875, 0.004856109619140625, 0.00882720947265625, -0.00806427001953125, -0.03985595703125, -0.0005011558532714844, 0.0068206787109375, -0.0169525146484375, -0.04425048828125, 0.057525634765625, 0.03363037109375, -0.046295166015625, 0.02337646484375, 0.0074310302734375, 0.03167724609375, -0.03143310546875, 0.03009033203125, -0.020294189453125, -0.01239013671875, -0.01111602783203125, -0.028839111328125, 0.03131103515625, -0.02325439453125, 0.00787353515625, 0.00890350341796875, 0.0031604766845703125, -0.015716552734375, -0.01494598388671875, -0.0270843505859375, -0.0062713623046875, 0.04638671875, -0.0301971435546875, 0.005649566650390625, 0.0556640625, -0.0206298828125, 0.0110626220703125, 0.0008006095886230469, 0.016265869140625, -0.017730712890625, 0.017730712890625, 0.038177490234375, 0.0228424072265625, 0.00457000732421875, -0.0310211181640625, -0.0201416015625, -0.028045654296875, 0.00785064697265625, 0.0273895263671875, -0.01206207275390625, -0.08062744140625, -0.0207366943359375, 0.0179443359375, 0.0018339157104492188, -0.0030345916748046875, 0.0008177757263183594, -0.0027065277099609375, 0.02081298828125, -0.007720947265625, 0.03411865234375, -0.004558563232421875, -0.07183837890625, -0.035308837890625, -0.01030731201171875, 0.02447509765625, -0.0181884765625, 0.056182861328125, -0.0244598388671875, 0.0004050731658935547, 2.7418136596679688e-05, -0.022247314453125, -0.0008873939514160156, 0.0160369873046875, 0.036529541015625, -0.021881103515625, -0.00969696044921875, -0.007389068603515625, -0.00936126708984375, 0.01317596435546875, 0.0032253265380859375, -0.004909515380859375, -0.044708251953125, -0.03363037109375, 0.0132904052734375, -0.0236053466796875, 0.00969696044921875, -0.031646728515625, -0.0222625732421875, 0.034698486328125, -0.0173187255859375, 0.0204010009765625, -0.04510498046875, 0.0217132568359375, -0.003673553466796875, -0.05206298828125, -0.01551055908203125, -0.028350830078125, 0.0117950439453125, -0.0025634765625, -0.028350830078125, 0.0081787109375, -0.0128021240234375, 0.036468505859375, -0.01715087890625, 0.0151824951171875, -0.00536346435546875, -0.0252227783203125, 0.008697509765625, -0.03851318359375, 0.0205078125, -0.0011911392211914062, -0.005611419677734375, 0.00795745849609375, 0.0462646484375, -0.000583648681640625, -0.0156402587890625, 0.033294677734375, 0.03216552734375, -0.06634521484375, -0.038543701171875, 0.020233154296875, 0.00458526611328125, 0.011627197265625, -0.005832672119140625, -0.02105712890625, -0.0253753662109375, 0.0005822181701660156, 0.0009107589721679688, -0.0012712478637695312, 0.0021800994873046875, -0.0230560302734375, 0.00457763671875, 0.005519866943359375, 0.0188751220703125, 0.031463623046875, -0.02532958984375, 0.0191802978515625, 0.00392913818359375, -0.005535125732421875, 0.021240234375, -0.0308074951171875, 0.041717529296875, 0.00844573974609375, 0.041168212890625, -0.01377105712890625, 0.038543701171875, 0.02069091796875, -0.005992889404296875, -0.027862548828125, 0.0082855224609375, -0.01715087890625, 0.003749847412109375, -0.00928497314453125, -0.006046295166015625, -0.00904083251953125, 0.01250457763671875, 0.0291748046875, 0.0008344650268554688, -0.040435791015625, -0.0002567768096923828, -0.01369476318359375, 0.0595703125, -0.00626373291015625, -0.0018186569213867188, 0.0095977783203125, 0.01263427734375, 0.042022705078125, -0.0400390625, -0.0015506744384765625, 0.013580322265625, -0.005451202392578125, 0.0019083023071289062, -0.01296234130859375, -0.01386260986328125, -0.0030975341796875, 0.0192718505859375, 0.00525665283203125, 0.0022602081298828125, 0.0055999755859375, 0.05224609375, 0.00621795654296875, -0.026641845703125, -0.005435943603515625, 0.0226898193359375, -0.028106689453125, 0.0299835205078125, -0.034698486328125, -0.02783203125, 0.01995849609375, -0.03851318359375, 0.0012798309326171875, -0.0155029296875, 0.04400634765625, -0.0246429443359375, -0.0045166015625, 0.043426513671875, -0.02069091796875, 0.0157928466796875, -0.00518798828125, 0.0128326416015625, -0.00031948089599609375, -0.0093231201171875, 0.0302886962890625, 0.033447265625, -0.02410888671875, 0.0095062255859375, -0.0157318115234375, -0.00799560546875, 0.03363037109375, 0.0310211181640625, -0.004077911376953125, 0.039154052734375, -0.005077362060546875, 0.01076507568359375, 0.009674072265625, 0.020294189453125, -0.01155853271484375, -0.00592041015625, -0.009521484375, -0.03521728515625, -0.0159912109375, 0.0192718505859375, 0.0516357421875, -0.01885986328125, 0.01568603515625, 0.01508331298828125, -0.031982421875, -0.00986480712890625, 0.0169525146484375, 0.00015926361083984375, 0.0214691162109375, -0.0267486572265625, 0.01499176025390625, 0.004589080810546875, 0.01235198974609375, -0.04241943359375, -0.030029296875, -0.038482666015625, -0.01131439208984375, 0.0220947265625, 0.017791748046875, -0.030364990234375, -0.020050048828125, 0.01407623291015625, -0.0171966552734375, -0.0791015625, 0.01149749755859375, 0.034393310546875, -0.0243377685546875, 0.0157623291015625, -0.022705078125, -0.00836181640625, 0.00556182861328125, 0.0030059814453125, -0.0283050537109375, 0.01366424560546875, -0.010894775390625, -0.007293701171875, -0.018798828125, -0.012237548828125, -0.051971435546875, 0.007541656494140625, -0.00316619873046875, 0.0033206939697265625, 0.00012969970703125, -0.035736083984375, 0.0242919921875, -0.0222930908203125, 0.05908203125, -0.0207672119140625, -0.00202178955078125, -0.03863525390625, 0.00485992431640625, 0.01568603515625, 0.0033016204833984375, -0.00830841064453125, 0.0195159912109375, -0.00463104248046875, 0.0157012939453125, 0.010467529296875, -0.01317596435546875, -0.0117950439453125, 0.006473541259765625, -0.00687408447265625, 0.006557464599609375, 0.05010986328125, 0.024932861328125, 0.056854248046875, 0.0201568603515625, 0.03277587890625, -0.0153045654296875, 0.0146942138671875, 0.03466796875, 0.0233917236328125, -0.007236480712890625, -0.033050537109375, 0.0106048583984375, 0.0206146240234375, -0.053802490234375, -0.01385498046875, 0.0391845703125, -0.01506805419921875, -0.043731689453125, 0.00931549072265625, 0.01739501953125, -0.01232147216796875, -0.0173797607421875, -0.0134429931640625, 0.0090484619140625, 0.0034313201904296875, 0.0013332366943359375, -0.0013561248779296875, -0.003360748291015625, -0.00835418701171875, 0.0021114349365234375, -0.042724609375, 0.00841522216796875, -0.0017747879028320312, -0.0250091552734375, -0.011627197265625, 0.022216796875, 0.01509857177734375, 0.022735595703125, -0.0005631446838378906, 0.00849151611328125, 0.017333984375, -0.01116180419921875, 0.040924072265625, 0.0186309814453125, 0.00669097900390625, 0.01971435546875, 0.02191162109375, 0.00498199462890625, -0.027557373046875, 0.01059722900390625, 0.02667236328125, -0.0237884521484375, -0.0127105712890625, 0.0131988525390625, -0.00974273681640625, 0.033447265625, 0.005321502685546875, 0.018798828125, 0.05133056640625, -0.00029468536376953125, 0.00025463104248046875, 0.0025482177734375, -0.024322509765625, -0.0254364013671875, -0.0022907257080078125, -0.0198974609375, -0.00556182861328125, 0.00884246826171875, -0.01073455810546875, 0.005008697509765625, -0.0194244384765625, 0.007598876953125, 0.0167236328125, 0.01023101806640625, -0.00649261474609375, -0.01351165771484375, 0.04876708984375, 0.0015048980712890625, -0.02288818359375, -0.0202178955078125, 0.0148468017578125, 0.052154541015625, 0.00333404541015625, 0.0293731689453125, 0.00928497314453125, 0.0296478271484375, 0.0278472900390625, -0.013031005859375, -0.0236053466796875, -0.005382537841796875, 0.017791748046875, 0.0012683868408203125, -0.0196075439453125, -0.02606201171875, 0.0215301513671875, 0.0140228271484375, 0.0166168212890625, 0.00121307373046875, 0.00853729248046875, 0.0308685302734375, 0.00597381591796875, 0.0160675048828125, 0.017303466796875, -0.038299560546875, -0.004192352294921875, 0.0097808837890625, 0.00675201416015625, -0.0238189697265625, 0.01099395751953125, 0.00353240966796875, 0.01036834716796875, -0.018768310546875, -0.007965087890625, 0.048858642578125, 0.03668212890625, 0.04229736328125, 0.0016641616821289062, 0.0041656494140625, -0.053375244140625, 0.003681182861328125, -0.0208740234375, 0.00905609130859375, 0.0362548828125, 0.0008144378662109375, -0.002674102783203125, 0.0025730133056640625, -0.060882568359375, 0.0008025169372558594, -0.0027751922607421875, 0.032623291015625, -0.007785797119140625, 0.00844573974609375, 0.01229095458984375, -0.006084442138671875, 0.01363372802734375, 0.05487060546875, -0.010986328125, 0.005523681640625, 0.00493621826171875, 0.0083160400390625, 0.00897979736328125, 0.025054931640625, 0.0217742919921875, 0.00907135009765625, 0.056671142578125, -0.0017108917236328125, 0.00016033649444580078, -0.0235137939453125, -0.052947998046875, -0.0263824462890625, 0.0175323486328125, 0.005290985107421875, 0.0213623046875, 0.06243896484375, -0.024810791015625, -0.031494140625, 0.0172882080078125, 0.0017194747924804688, -0.044158935546875, -0.0032863616943359375, -0.008514404296875, 0.0252532958984375, 0.01558685302734375, -0.0103302001953125, 0.0214691162109375, 0.0239105224609375, -0.047393798828125, -0.006656646728515625, -0.026336669921875, -0.019195556640625, -0.033172607421875, -0.0027713775634765625, -0.0230712890625, -0.040496826171875, -0.0268707275390625, 0.00457000732421875, 0.025054931640625, -0.002445220947265625, -0.0163421630859375, -0.0193634033203125, 0.018768310546875, 0.0094146728515625, -0.0208740234375, 0.0528564453125, -0.019683837890625, 0.031494140625, -0.0287322998046875, -0.0028018951416015625, 0.00449371337890625, 0.016082763671875, 0.02301025390625, -0.0051727294921875, 0.0196075439453125, -0.005771636962890625, 0.025115966796875, -0.01181793212890625, 0.0005049705505371094, -0.03582763671875, 0.0033111572265625, 0.001819610595703125, 0.041656494140625, 0.0156097412109375, -0.0026721954345703125, -0.053619384765625, 0.00011795759201049805, -0.038116455078125, -0.00139617919921875, 0.0193328857421875, 0.020599365234375, -0.0017786026000976562, -0.022003173828125, -0.01551055908203125, 0.01439666748046875, -0.035614013671875, -0.019256591796875, 0.0093536376953125, 0.0227813720703125, 0.0158233642578125, -0.00399017333984375, -0.009368896484375, -0.01959228515625, -0.0010137557983398438, 0.00998687744140625, -0.06396484375, 0.0014276504516601562, 0.004604339599609375, -0.0084381103515625, -0.01373291015625, 0.03399658203125, 0.02947998046875, -0.0380859375, 0.017303466796875, 0.0033817291259765625, 0.005527496337890625, 0.03546142578125, -0.024871826171875, -0.00505828857421875, -0.03533935546875, 0.033447265625, 0.043060302734375, -0.026123046875, -0.00437164306640625, 0.03070068359375, -0.0092315673828125, 0.031890869140625, -0.006591796875, -0.0557861328125, -0.0280303955078125, 0.007904052734375, 0.01328277587890625, 0.01016998291015625, -0.002651214599609375, 0.007335662841796875, -0.0008420944213867188, -0.0117950439453125, 0.00750732421875, -0.01055145263671875, 0.0273590087890625, 0.034912109375, -0.035247802734375, -0.014251708984375, -0.01369476318359375, 0.02142333984375, 0.0296783447265625, 0.004169464111328125, 0.032928466796875, 0.001483917236328125, -0.0180816650390625, -0.007457733154296875, -0.0093231201171875, -0.011199951171875, -0.01020050048828125, 0.032440185546875, 0.018951416015625, 0.0002779960632324219, 0.0214080810546875, 0.0201568603515625, -0.0172119140625, 0.007244110107421875, 0.00557708740234375, 0.0002484321594238281, 0.019012451171875, -0.005451202392578125, 0.0166473388671875, 0.00678253173828125, 0.0174407958984375, 0.029144287109375, -0.0266876220703125, -0.00882720947265625, -0.0024566650390625, 0.004852294921875, -0.024566650390625, -0.00968170166015625, 0.01654052734375, 0.005702972412109375, -0.02801513671875, -0.0144195556640625, 0.026153564453125, -0.0103607177734375, -0.0110626220703125, -0.0148468017578125, -0.00522613525390625, 0.0034084320068359375, 0.014007568359375, -0.007843017578125, -0.005237579345703125, -0.004119873046875, -0.0003867149353027344, -0.0066375732421875, -0.004261016845703125, 0.07122802734375, 0.006977081298828125, -0.0103912353515625, 0.0273895263671875, -0.00792694091796875, -0.0269927978515625, -0.0171051025390625, 0.007965087890625, -0.038604736328125, 0.0157928466796875, -0.01499176025390625, 0.00156402587890625, -0.0022640228271484375, 0.00382232666015625, -0.014251708984375, 0.004741668701171875, 0.020782470703125, 0.0217437744140625, -0.001983642578125, -0.00885772705078125, -0.01117706298828125, 0.0367431640625, 0.019622802734375, -0.0133514404296875, -0.024139404296875, 0.01184844970703125, 0.035675048828125, -0.024566650390625, -0.0005464553833007812, -0.00489044189453125, -0.0256500244140625, -0.005191802978515625, -0.020599365234375, 0.0016155242919921875, -0.0302276611328125, 0.0213775634765625, -0.00836181640625, 0.0227203369140625, 0.002941131591796875, 0.002956390380859375, 0.0211334228515625, -0.00812530517578125, 0.0181732177734375, -0.0055999755859375, 5.650520324707031e-05, -0.0113372802734375, -0.00846099853515625, -0.00240325927734375, -0.0321044921875, 0.005512237548828125, 0.031890869140625, 0.0245208740234375, -0.0308380126953125, -0.0002949237823486328, -0.0173797607421875, -0.00476837158203125, -0.0116424560546875, 0.0330810546875, 0.01062774658203125, 0.00782012939453125, -0.01079559326171875, 0.0176849365234375, -0.005889892578125, 0.0190582275390625, 0.03802490234375, -0.027374267578125, 0.00685882568359375, -0.0024890899658203125, -0.061279296875, -0.0030498504638671875, -0.04095458984375, -0.0025043487548828125, -0.02069091796875, -0.006244659423828125, 0.0017728805541992188, 0.0233154296875, 0.031982421875, 0.0030536651611328125, 0.029998779296875, -0.014556884765625, 0.002841949462890625, 0.0180511474609375, -0.01276397705078125, -0.0214385986328125, -0.001079559326171875, -0.0310821533203125, -0.016693115234375, 0.0250091552734375, 0.0005946159362792969, 0.0182342529296875, -0.0047760009765625, 0.0087432861328125, -0.0051727294921875, 0.0256500244140625, 0.009918212890625, 0.0216522216796875, -0.0011892318725585938, 0.0170440673828125, 0.018096923828125, -0.021881103515625, 0.0260162353515625, 0.0105133056640625, -0.0161590576171875, 0.02777099609375, -0.026611328125, -0.0267181396484375, -0.020660400390625, 0.0035610198974609375, -0.0184173583984375, 0.004161834716796875, 0.0011529922485351562, 0.0056304931640625, 0.0214996337890625, -0.0005021095275878906, -0.00440216064453125, -0.025909423828125, -0.01047515869140625, -0.05340576171875, -0.033294677734375, -0.040557861328125, 0.041748046875, 0.00036025047302246094, 0.0025177001953125, -0.0059814453125, -0.00455474853515625, 0.035125732421875, 0.01153564453125, -0.0193634033203125, -0.039520263671875, -0.0234222412109375, -0.01336669921875, 0.012359619140625, 0.006053924560546875, -0.00201416015625, -0.0091400146484375, 0.007793426513671875, 0.005290985107421875, -0.0301971435546875, -0.0036334991455078125, 0.0158538818359375, -0.0100860595703125, 0.005397796630859375, -0.01171875, -0.0010519027709960938, 0.00856781005859375, -0.044189453125, 0.0159149169921875, -0.011810302734375, 0.03289794921875, 0.0107879638671875, 0.01074981689453125, -0.0196685791015625, 0.00562286376953125, 0.031890869140625, -0.0060577392578125, -0.018402099609375, 0.015167236328125, -0.036956787109375, -0.0221099853515625, 0.0237579345703125, -0.01396942138671875, 0.00485992431640625, -0.032867431640625, -0.044342041015625, 0.0302886962890625, -0.006622314453125, 0.004974365234375, 0.0035915374755859375, 0.0037364959716796875, 0.0382080078125, -0.0016508102416992188, -0.05010986328125, -0.01334381103515625, 0.0175018310546875, 0.06317138671875, 0.00537872314453125, 0.01308441162109375, 0.0225677490234375, -0.005035400390625, 0.002582550048828125, 0.005084991455078125, -0.00955963134765625, 0.0034770965576171875, -0.024566650390625, 0.002918243408203125, -0.01192474365234375, 0.0335693359375, -0.00518035888671875, 0.021697998046875, 0.00484466552734375, -0.021636962890625, -0.0273284912109375, -0.0139007568359375, -0.0016422271728515625, 0.00760650634765625, 0.0261993408203125, 0.0167388916015625, -0.0017232894897460938, -0.0276641845703125, -0.00147247314453125, -0.0162811279296875, -0.05377197265625, -0.0233306884765625, 0.0080413818359375, -0.0218048095703125, 0.055816650390625, -0.05169677734375, -0.042266845703125, -0.003520965576171875, 0.0164337158203125, 0.0214385986328125, -0.0019083023071289062, 0.0174407958984375, -0.0111541748046875, 0.031707763671875, 0.01506805419921875, -0.0174407958984375, 0.007312774658203125, -0.0265655517578125, -0.019683837890625, 0.0347900390625, 0.0031528472900390625, 0.0004901885986328125, -0.07196044921875, 0.0232391357421875, 0.02435302734375, -0.0067901611328125, 0.002841949462890625, 0.0028018951416015625, -0.030670166015625, 0.049468994140625, -0.017059326171875, 0.00036835670471191406, -0.0098114013671875, 0.00844573974609375, 0.025726318359375, -0.0158843994140625, 0.01465606689453125, 9.739398956298828e-05, -0.0238800048828125, -0.010833740234375, 0.0128631591796875, -0.00844573974609375, 0.005832672119140625, -0.0244293212890625, 0.0170440673828125, -0.0040130615234375, 0.0175018310546875, 0.00450897216796875, 0.0158843994140625, -0.0234832763671875, 0.01421356201171875, -0.00289154052734375, -0.027984619140625, -0.01345062255859375, -0.00273895263671875, -0.03265380859375, -0.01464080810546875, -0.00429534912109375, -0.02032470703125, -0.017852783203125, -0.0016021728515625, 0.020355224609375, 0.01143646240234375, 0.0189208984375, 0.00991058349609375, -0.026702880859375, -0.027252197265625, -0.0318603515625, 0.013824462890625, -0.0186920166015625, 0.03466796875, -0.0218963623046875, -0.03009033203125, -0.0308380126953125, -0.0014162063598632812, 0.01111602783203125, 0.01261138916015625, 0.012908935546875, -0.0147705078125, -0.0148468017578125, 0.01540374755859375, -0.0222320556640625, 0.018035888671875, 0.01268768310546875, -0.01904296875, -0.00891876220703125, -0.01253509521484375, 0.043731689453125, 0.003570556640625, 0.0240936279296875, 0.006664276123046875, -0.007022857666015625, -0.0014190673828125, 0.0016641616821289062, 0.036102294921875, 0.01593017578125, -0.01091766357421875, -0.01194000244140625, 0.01186370849609375, -0.024169921875, -0.0161590576171875, 0.005161285400390625, -0.0219573974609375, -0.00024175643920898438, -0.0023059844970703125, 0.01290130615234375, 0.01291656494140625, -0.00696563720703125, -0.0012035369873046875, 0.01206207275390625, -0.007167816162109375, -0.0007696151733398438, 0.00391387939453125, 0.02099609375, -0.0026645660400390625, 0.0117950439453125, 0.0128936767578125, -0.0269927978515625, 0.0126495361328125, 0.01029205322265625, 0.00018286705017089844, 0.037200927734375, 0.0287322998046875, 0.038330078125, 0.01678466796875, -0.01227569580078125, 0.0018682479858398438, -0.0195465087890625, 0.01250457763671875, 0.0305328369140625, -0.017242431640625, -0.0125579833984375, 0.002468109130859375, 0.00801849365234375, 0.0160369873046875, 0.01378631591796875, 0.035858154296875, -0.00521087646484375, -0.005428314208984375, -0.027313232421875, -0.004917144775390625, 0.02447509765625, -0.018035888671875, -0.004566192626953125, 0.02349853515625, 0.016021728515625, -0.035552978515625, -0.0134124755859375, 0.0174560546875, -0.005039215087890625, 0.031982421875, -0.00518035888671875, -0.003940582275390625, 0.0021648406982421875, 0.0233917236328125, 0.03143310546875, -0.0230712890625, -0.016021728515625, -0.01027679443359375, -0.059173583984375, -0.023834228515625, 0.002216339111328125, 0.01448822021484375, -0.041778564453125, 0.01629638671875, 0.029510498046875, 0.01276397705078125, 0.01203155517578125, 0.0401611328125, -0.0206298828125, -0.01215362548828125, -0.0006728172302246094, -0.0265350341796875, -0.01541900634765625, 0.00010961294174194336, 0.01387786865234375, -0.019866943359375, -0.01287841796875, -0.0157470703125, 0.044342041015625, -0.032073974609375, 0.023193359375, 0.0158538818359375, 0.01149749755859375, 0.0112152099609375, 0.00412750244140625, -0.042724609375, -0.015899658203125], "caa2ef46-a962-4005-a550-132f2f557db5": [-0.0216064453125, -0.0303192138671875, 0.0212860107421875, -0.0007805824279785156, 0.0321044921875, -0.0017957687377929688, 0.00867462158203125, 0.036865234375, 0.03076171875, 0.06231689453125, 0.006114959716796875, -0.051910400390625, -0.015899658203125, -0.060882568359375, -0.0294036865234375, 0.0061798095703125, -0.042938232421875, 0.025390625, -0.0232696533203125, -0.008758544921875, 0.035369873046875, 0.04156494140625, -0.032379150390625, 0.007335662841796875, -0.0181121826171875, -0.0145721435546875, -0.004070281982421875, 0.01389312744140625, -0.01195526123046875, -0.004364013671875, 0.010528564453125, -0.0237579345703125, -0.01611328125, 0.006877899169921875, -0.019561767578125, 0.0435791015625, -0.0159454345703125, -0.0291748046875, 0.0161285400390625, -0.0084228515625, -0.0011339187622070312, -0.0239715576171875, 0.0207366943359375, 0.0274810791015625, -0.01995849609375, 0.0006866455078125, -0.0225677490234375, -0.001773834228515625, 0.0169219970703125, 0.0225830078125, -0.05401611328125, 0.03338623046875, 0.01277923583984375, 0.01183319091796875, -0.00737762451171875, 0.006702423095703125, 0.01568603515625, 0.00261688232421875, -0.0004482269287109375, 0.0305938720703125, 0.0469970703125, -0.0148468017578125, 0.01331329345703125, 0.0203399658203125, -0.0038700103759765625, -0.039459228515625, 0.0154266357421875, 0.027008056640625, 0.0145263671875, -0.01183319091796875, 0.055389404296875, 0.0305938720703125, -0.037017822265625, -0.0239715576171875, 0.0072021484375, -0.005504608154296875, 0.021514892578125, -0.007659912109375, -0.03973388671875, -0.060546875, -0.00788116455078125, 0.014862060546875, -0.026397705078125, -0.0355224609375, -0.02581787109375, -0.01064300537109375, -0.051666259765625, -0.01395416259765625, -0.0228271484375, -0.032562255859375, -0.02740478515625, 0.0026302337646484375, -0.00782012939453125, 0.0081329345703125, 0.060089111328125, -0.0099945068359375, 0.034881591796875, 0.0178070068359375, 0.00957489013671875, 0.0024814605712890625, -0.034942626953125, -0.0347900390625, -0.07464599609375, 0.0231170654296875, 0.0128173828125, 0.01441192626953125, 0.0439453125, -0.04400634765625, -0.048828125, 0.01318359375, -0.078125, 0.017120361328125, -0.0195770263671875, 0.016845703125, -0.0404052734375, -0.0310211181640625, -0.045928955078125, -0.0032939910888671875, -0.0193939208984375, -0.01099395751953125, -0.062164306640625, 0.0031528472900390625, -0.00873565673828125, 0.02618408203125, -0.0167694091796875, -0.030731201171875, 0.022430419921875, -0.0134429931640625, -0.046905517578125, -0.0247650146484375, -0.004001617431640625, 0.0183258056640625, 0.026824951171875, -0.0433349609375, -0.032073974609375, -0.04241943359375, 0.0063323974609375, 0.033111572265625, -0.0309600830078125, -0.01529693603515625, 0.01000213623046875, -0.0222320556640625, -0.0164031982421875, 0.043182373046875, -0.0310821533203125, -0.01427459716796875, -0.0142364501953125, 0.026214599609375, -0.04559326171875, 0.038421630859375, 0.0299530029296875, 0.0369873046875, -0.036041259765625, 0.003612518310546875, -0.0027332305908203125, 0.0267486572265625, 0.0047607421875, 0.015960693359375, -0.01490020751953125, -0.0284271240234375, -0.0262603759765625, -0.0285186767578125, -0.00286102294921875, -0.03143310546875, -0.001232147216796875, 0.05865478515625, 0.0175933837890625, -0.003658294677734375, -0.03973388671875, -0.06512451171875, -0.022613525390625, -0.03558349609375, -0.038482666015625, 0.044097900390625, -0.01468658447265625, -0.048828125, 0.0271453857421875, 0.0157318115234375, -0.01079559326171875, 0.007259368896484375, -0.01137542724609375, 0.0264129638671875, -0.039642333984375, 0.0010919570922851562, -0.03228759765625, -0.048828125, -0.01837158203125, -0.0263671875, 0.01323699951171875, 0.005828857421875, 0.0171356201171875, 0.0201873779296875, 0.048492431640625, 0.0265655517578125, 0.05145263671875, -0.058746337890625, 0.054229736328125, -0.0298919677734375, -0.023895263671875, 0.028076171875, 0.0217437744140625, 0.00029277801513671875, 0.0235443115234375, -0.00011008977890014648, 0.036956787109375, -0.05694580078125, 0.016204833984375, 0.0208740234375, -0.0628662109375, 0.0435791015625, 0.044219970703125, -0.01873779296875, 0.05322265625, 0.026885986328125, -0.039306640625, 0.025848388671875, -0.0303802490234375, 0.003143310546875, -0.0244598388671875, 0.01451873779296875, -0.00732421875, 0.0248260498046875, 0.067138671875, -0.0226287841796875, -0.00970458984375, 0.0313720703125, 0.037567138671875, -0.00565338134765625, -0.0037689208984375, -0.0357666015625, 0.00734710693359375, -0.0174102783203125, -0.0168304443359375, -0.0198974609375, 0.03466796875, -0.03173828125, 0.059967041015625, 0.0028324127197265625, 0.01544952392578125, 0.00624847412109375, 0.007080078125, -0.007488250732421875, 0.06121826171875, 0.06280517578125, 0.0220489501953125, 0.01739501953125, -0.0265960693359375, -0.09033203125, 0.033660888671875, 0.0250091552734375, 0.0182952880859375, -0.022247314453125, 0.06170654296875, -0.006412506103515625, -0.035400390625, -0.03558349609375, -0.0018024444580078125, -0.006343841552734375, -0.0132293701171875, -0.03216552734375, 0.0574951171875, 0.002368927001953125, 0.0145721435546875, 0.0158538818359375, -0.03985595703125, -0.07208251953125, -0.0104522705078125, 0.01727294921875, -0.01708984375, -0.033935546875, -0.023468017578125, -0.0092620849609375, 0.0193634033203125, 0.038360595703125, -0.054046630859375, -0.01213836669921875, -0.00923919677734375, 0.0219879150390625, -0.0282135009765625, 0.053131103515625, 0.0079193115234375, 0.045166015625, -0.0246734619140625, 0.0305938720703125, 0.018646240234375, 0.038726806640625, -0.0220489501953125, -0.007965087890625, -0.0176544189453125, -0.0170135498046875, -0.01013946533203125, -0.0282745361328125, 0.0455322265625, 0.030609130859375, -0.00824737548828125, -0.00426483154296875, 0.03839111328125, 0.01934814453125, 0.0004978179931640625, 0.0084075927734375, 0.0640869140625, -0.0462646484375, 0.0178070068359375, 0.033905029296875, 0.01531982421875, 0.0197906494140625, 0.0146026611328125, 0.035064697265625, 0.038726806640625, -0.0250701904296875, 0.00911712646484375, 0.05548095703125, 0.0221405029296875, 0.01360321044921875, -0.049957275390625, -0.0225372314453125, 0.0660400390625, 0.01427459716796875, 0.0367431640625, -0.042755126953125, -0.045806884765625, -0.00589752197265625, 0.0413818359375, -0.017425537109375, -0.0266571044921875, -0.012847900390625, 0.047119140625, 0.012542724609375, -0.02880859375, -0.02105712890625, -0.037139892578125, -0.040802001953125, -0.020904541015625, 0.015625, 0.03082275390625, -0.003322601318359375, -0.032684326171875, -0.0167388916015625, -0.0179595947265625, 0.00389862060546875, -0.035614013671875, -0.042694091796875, -0.08734130859375, -0.007190704345703125, 0.0186614990234375, 0.018402099609375, 0.0030975341796875, 0.003444671630859375, 0.006500244140625, 0.022796630859375, 0.0233917236328125, 0.0216827392578125, 0.007049560546875, 0.00771331787109375, -0.0467529296875, -0.045928955078125, -0.00518798828125, 0.00954437255859375, -0.036651611328125, 7.706880569458008e-05, 0.0003190040588378906, -0.025543212890625, 0.007190704345703125, 0.0272064208984375, 0.03118896484375, -0.028961181640625, -0.0472412109375, -0.03985595703125, -0.01052093505859375, -0.040863037109375, 0.01033782958984375, -0.051300048828125, 0.039520263671875, -0.03204345703125, -0.034576416015625, 0.03326416015625, -0.0174102783203125, 0.038177490234375, 0.01097869873046875, 0.06585693359375, 0.058502197265625, -0.02886962890625, -0.052825927734375, -0.04815673828125, -0.01898193359375, 0.0261688232421875, -0.01007080078125, -0.0090789794921875, -0.0208892822265625, -0.02020263671875, 0.02166748046875, -0.04736328125, -0.03826904296875, -0.0372314453125, -0.01264190673828125, 0.024658203125, -0.005207061767578125, 0.043914794921875, 0.024261474609375, -0.03009033203125, -0.0164642333984375, 0.0357666015625, -0.01447296142578125, 0.0292816162109375, -0.00988006591796875, -0.0009112358093261719, -0.026153564453125, 0.0124359130859375, 0.0242462158203125, 0.0264129638671875, 0.05523681640625, -0.04888916015625, 0.0305328369140625, -0.0233001708984375, -0.01316070556640625, -0.0198974609375, 0.0259552001953125, -0.011627197265625, 0.053253173828125, 0.042633056640625, 0.00827789306640625, -0.047515869140625, -0.0035839080810546875, 0.029144287109375, 0.004413604736328125, 0.06695556640625, 0.00879669189453125, -0.00322723388671875, 0.08135986328125, -0.058563232421875, -0.0014495849609375, 0.01549530029296875, 0.0144500732421875, -0.0259857177734375, 0.0086517333984375, -0.0113677978515625, -0.006038665771484375, 0.052093505859375, -0.037567138671875, -0.016693115234375, 0.00528717041015625, -0.0255889892578125, -0.059783935546875, -0.0394287109375, -0.0250091552734375, 0.037811279296875, -0.0310516357421875, -0.0272674560546875, 0.0258636474609375, -0.0233612060546875, 0.00914764404296875, -0.052581787109375, -0.0023670196533203125, 0.037628173828125, -0.03289794921875, -0.043670654296875, 0.005771636962890625, -0.01235198974609375, 0.01343536376953125, -0.018890380859375, 0.0123291015625, -0.012237548828125, -0.02716064453125, 0.03265380859375, 0.01085662841796875, 0.0019969940185546875, -0.01369476318359375, -0.0054168701171875, -0.0389404296875, 0.03265380859375, -0.00878143310546875, 0.0153350830078125, 0.033416748046875, -0.0045623779296875, -0.039581298828125, 0.0031871795654296875, 0.01319122314453125, -0.015045166015625, -0.041534423828125, -0.005428314208984375, 0.0248260498046875, 0.05059814453125, 0.0197601318359375, 0.061981201171875, 0.056549072265625, 0.013702392578125, 0.0140228271484375, -0.01107025146484375, 0.053802490234375, 0.01702880859375, 0.030059814453125, -0.007049560546875, 0.05108642578125, -0.0182037353515625, 0.046173095703125, 0.0281524658203125, 0.020843505859375, -0.0157623291015625, 0.0013036727905273438, -0.037506103515625, -0.020355224609375, 0.029754638671875, 0.01202392578125, 0.06524658203125, -0.0119781494140625, -0.0034770965576171875, -0.0382080078125, -0.0014333724975585938, 0.00899505615234375, -0.0181427001953125, 0.006565093994140625, -0.0225982666015625, -0.0148468017578125, -0.007659912109375, 0.0093841552734375, 0.02606201171875, 0.02801513671875, 0.01187896728515625, -0.015106201171875, -0.01861572265625, -0.01529693603515625, -0.014678955078125, 0.0172882080078125, -0.010406494140625, -0.032501220703125, -0.02093505859375, -0.00923919677734375, 0.0028514862060546875, -0.00577545166015625, -0.0258941650390625, 0.022705078125, -0.004802703857421875, 0.032012939453125, 0.0041656494140625, -0.05853271484375, 0.017547607421875, -0.00562286376953125, -0.01325225830078125, -0.0305633544921875, 0.0118408203125, 0.0205078125, 0.038482666015625, 0.034088134765625, 0.0087890625, -0.00429534912109375, 0.0210418701171875, -0.0108642578125, 0.0011205673217773438, -0.0286102294921875, 0.0122528076171875, 0.01476287841796875, -0.0099334716796875, 0.0303497314453125, -0.02105712890625, 0.0215911865234375, 0.002410888671875, 0.007480621337890625, -0.054534912109375, 0.0008296966552734375, 0.024688720703125, -0.02825927734375, -0.0245361328125, 0.043304443359375, 0.024017333984375, -0.042877197265625, 0.0013628005981445312, 0.016815185546875, 0.029632568359375, -0.001255035400390625, 0.017730712890625, -0.040069580078125, -0.00830841064453125, -0.007450103759765625, -0.040252685546875, 0.0173797607421875, -0.01357269287109375, 0.0093231201171875, 0.0189361572265625, 0.004291534423828125, -0.0017337799072265625, -0.00917816162109375, -0.043304443359375, -0.00649261474609375, 0.06536865234375, -0.00508880615234375, 0.0169830322265625, 0.0290679931640625, 0.01403045654296875, 0.007106781005859375, 0.007770538330078125, 0.01007080078125, -0.01322174072265625, 0.034698486328125, 0.018310546875, 0.00907135009765625, 0.0019083023071289062, -0.04071044921875, -0.00460052490234375, -0.010894775390625, 0.03729248046875, 0.0186920166015625, -0.004772186279296875, -0.06982421875, 0.006317138671875, 0.007049560546875, -0.0028324127197265625, -0.0131072998046875, -0.00861358642578125, -0.00185394287109375, 0.033721923828125, 0.0018014907836914062, 0.020599365234375, -0.006927490234375, -0.06658935546875, -0.025360107421875, -0.03594970703125, 0.0010395050048828125, -0.01415252685546875, 0.05914306640625, -0.0277252197265625, 0.01104736328125, 0.0236968994140625, -0.032745361328125, 0.00673675537109375, 0.0197601318359375, 0.02142333984375, -0.0310516357421875, -0.009613037109375, -0.01493072509765625, 0.00160980224609375, 0.0030155181884765625, 0.025909423828125, -0.006511688232421875, -0.037322998046875, -0.013458251953125, 0.00479888916015625, -0.0174713134765625, 0.0228424072265625, -0.01248931884765625, -0.033416748046875, 0.0170745849609375, -0.0169830322265625, 0.0028133392333984375, -0.044189453125, 0.009246826171875, 0.0032482147216796875, -0.041107177734375, -0.025360107421875, -0.03363037109375, 0.01276397705078125, -0.022552490234375, -0.048248291015625, 0.0034637451171875, 0.010528564453125, 0.04290771484375, -0.0167999267578125, -0.007511138916015625, 0.0009794235229492188, -0.03631591796875, -0.002994537353515625, -0.035125732421875, -0.0081787109375, 0.0059814453125, -0.00021922588348388672, 0.01325225830078125, 0.04693603515625, -0.008544921875, -0.00841522216796875, 0.040283203125, 0.017425537109375, -0.063720703125, -0.0223846435546875, 0.032073974609375, 0.00861358642578125, -0.00753021240234375, -0.01739501953125, -0.0012407302856445312, -0.0167694091796875, 0.0165863037109375, -0.00820159912109375, -0.01222991943359375, 0.01450347900390625, -0.02545166015625, -0.01425933837890625, 0.0197601318359375, -0.002696990966796875, 0.037994384765625, -0.016815185546875, 0.0259857177734375, 0.007305145263671875, -0.0025196075439453125, 0.0251922607421875, -0.036346435546875, 0.0389404296875, 0.01433563232421875, 0.0309600830078125, -0.007171630859375, 0.041717529296875, 0.01290130615234375, 0.00830078125, -0.04107666015625, 0.0012569427490234375, -0.005748748779296875, 0.003681182861328125, -0.006084442138671875, -0.0031642913818359375, -0.0121612548828125, 0.018707275390625, 0.00835418701171875, 0.009124755859375, -0.05126953125, -0.00673675537109375, 0.0016193389892578125, 0.06622314453125, -0.00168609619140625, 0.0016841888427734375, -0.00417327880859375, 0.01103973388671875, 0.03143310546875, -0.0311279296875, 0.0003688335418701172, -0.0002593994140625, 0.005680084228515625, -0.00034499168395996094, -0.01678466796875, -0.03515625, -0.0191192626953125, 0.02557373046875, -0.004627227783203125, 0.006114959716796875, 0.008941650390625, 0.041534423828125, -0.00452423095703125, -0.0273284912109375, -0.00010216236114501953, 0.01517486572265625, -0.057342529296875, 0.021484375, -0.037322998046875, -0.031768798828125, 0.02606201171875, -0.02850341796875, 0.007843017578125, -0.003841400146484375, 0.03204345703125, -0.0216522216796875, -0.0025634765625, 0.054779052734375, -0.033447265625, 0.006473541259765625, -0.001125335693359375, 0.01334381103515625, -0.02044677734375, -0.01285552978515625, 0.02056884765625, 0.03314208984375, -0.0253143310546875, 0.01403045654296875, -0.0204620361328125, 0.00589752197265625, 0.0226287841796875, 0.01013946533203125, -0.0036525726318359375, 0.036468505859375, 0.0052490234375, 0.002666473388671875, 0.0150909423828125, 0.01155853271484375, -0.006443023681640625, 0.00037026405334472656, -0.0109405517578125, -0.046875, -0.02410888671875, 0.01129150390625, 0.057037353515625, -0.0170745849609375, 0.038055419921875, 0.007843017578125, -0.016143798828125, -0.0165557861328125, 0.01090240478515625, 0.0117340087890625, 0.0165252685546875, -0.0225372314453125, 0.0116424560546875, -0.0002428293228149414, 0.00943756103515625, -0.01690673828125, -0.0172882080078125, -0.036651611328125, -0.020660400390625, 0.01369476318359375, 0.004810333251953125, -0.030792236328125, -0.01258087158203125, 0.014892578125, -0.0033111572265625, -0.09405517578125, -0.0061492919921875, 0.02789306640625, -0.0303497314453125, 0.0127105712890625, -0.029571533203125, -0.004665374755859375, 0.0208587646484375, -0.0009226799011230469, -0.036376953125, 0.01422119140625, 0.0038700103759765625, 0.0010995864868164062, -0.03363037109375, -0.001888275146484375, -0.043212890625, -0.0005393028259277344, -0.00366973876953125, 0.031768798828125, -0.0113677978515625, -0.0421142578125, 0.026885986328125, -0.0299835205078125, 0.046966552734375, -0.01165771484375, -0.003681182861328125, -0.0252532958984375, 0.04010009765625, -0.0077972412109375, -0.0032367706298828125, -0.02679443359375, 0.00849151611328125, 0.01441192626953125, 0.0509033203125, -0.016815185546875, -0.0028972625732421875, -0.01200103759765625, 0.015655517578125, -0.01983642578125, 0.00972747802734375, 0.03839111328125, 0.00481414794921875, 0.07208251953125, 0.003978729248046875, 0.0084228515625, -0.01611328125, 0.0197601318359375, 0.0245208740234375, 0.0162200927734375, -0.00820159912109375, -0.0217437744140625, 0.02777099609375, 0.0223541259765625, -0.047393798828125, -0.0252838134765625, 0.043853759765625, -0.0077056884765625, -0.006969451904296875, 0.00836944580078125, 0.01491546630859375, -0.008056640625, -0.032318115234375, -0.0113067626953125, 0.0099639892578125, 0.0086517333984375, 0.0026645660400390625, 0.02947998046875, 0.02081298828125, 0.004795074462890625, -0.01039886474609375, -0.057708740234375, -0.0033626556396484375, -0.011962890625, -0.0165252685546875, 0.0099334716796875, 0.00501251220703125, 0.00959014892578125, 0.033294677734375, 0.019866943359375, 0.01104736328125, 0.03173828125, -0.0092010498046875, 0.0237579345703125, 0.018218994140625, -0.015380859375, 0.01806640625, 0.0197296142578125, -0.002544403076171875, -0.03729248046875, -0.0023555755615234375, 0.0279693603515625, -0.035186767578125, -0.01409912109375, 0.005298614501953125, -0.0271453857421875, 0.0352783203125, 0.0034046173095703125, 0.0175323486328125, 0.055633544921875, -0.003467559814453125, 0.0027980804443359375, -0.004146575927734375, -0.03912353515625, -0.01471710205078125, 0.004749298095703125, -0.00788116455078125, -0.0127716064453125, 0.0207061767578125, 0.01177215576171875, 0.0022449493408203125, 0.002597808837890625, 0.01474761962890625, 0.003948211669921875, 0.001857757568359375, 0.016021728515625, 0.00948333740234375, 0.04705810546875, -0.021820068359375, -0.026458740234375, -0.021759033203125, 0.0144500732421875, 0.0300445556640625, -0.00444793701171875, 0.016510009765625, 0.0055999755859375, 0.017730712890625, 0.01126861572265625, -0.01116943359375, -0.0140380859375, -0.002086639404296875, 0.02032470703125, 0.00870513916015625, -0.023529052734375, -0.01412200927734375, -0.00327301025390625, 0.0156097412109375, 0.029571533203125, -0.0076751708984375, 0.005207061767578125, 0.0252838134765625, 0.01129150390625, 0.0011386871337890625, -0.0088043212890625, -0.044921875, -0.028167724609375, 0.0078887939453125, 0.0257415771484375, -0.0140228271484375, -0.0027713775634765625, 0.00818634033203125, -0.0166473388671875, -0.0207061767578125, 0.005706787109375, 0.056121826171875, 0.03375244140625, 0.05218505859375, 0.007568359375, 0.0080718994140625, -0.046875, 0.004520416259765625, -0.0226898193359375, 0.00608062744140625, 0.020263671875, 0.01409149169921875, 0.006679534912109375, -0.0038661956787109375, -0.041473388671875, 0.0056610107421875, -0.0120849609375, 0.042633056640625, -0.002227783203125, 0.00543975830078125, 0.018829345703125, -0.0012912750244140625, 0.01525115966796875, 0.03759765625, 0.0184173583984375, -0.00785064697265625, 0.0087890625, 0.010528564453125, 0.011688232421875, 0.019683837890625, 0.019744873046875, 0.0140838623046875, 0.054595947265625, 0.0080108642578125, -0.0107879638671875, -0.0093841552734375, -0.050323486328125, -0.0257568359375, 0.0316162109375, -0.0094451904296875, 0.023162841796875, 0.03350830078125, -0.0214691162109375, -0.0372314453125, 0.0306396484375, 0.0115814208984375, -0.055145263671875, -0.01171112060546875, -0.0258026123046875, 0.037017822265625, 0.01027679443359375, 0.00043082237243652344, 0.013671875, 0.0263519287109375, -0.03729248046875, -0.02508544921875, -0.01219940185546875, -0.03759765625, -0.042938232421875, -0.01262664794921875, -0.0298614501953125, -0.046112060546875, -0.02593994140625, 0.023406982421875, 0.00757598876953125, 0.0105743408203125, -0.0369873046875, -0.013092041015625, 0.02203369140625, 0.010955810546875, -0.0309906005859375, 0.0340576171875, -0.00812530517578125, 0.032928466796875, -0.0247039794921875, -0.004657745361328125, 0.0014181137084960938, 0.0134735107421875, 0.02471923828125, -0.03192138671875, 0.032440185546875, 0.0006923675537109375, 0.0252227783203125, -0.01015472412109375, 0.0185089111328125, -0.035980224609375, 0.0244903564453125, 0.0070037841796875, 0.03472900390625, 0.00948333740234375, 0.001514434814453125, -0.03900146484375, 0.01001739501953125, -0.021820068359375, -0.01227569580078125, 0.00821685791015625, 0.005809783935546875, -0.004253387451171875, -0.004974365234375, -0.0138397216796875, 0.0195159912109375, -0.0212554931640625, -0.0008687973022460938, 0.0019626617431640625, 0.033416748046875, 0.01556396484375, -0.0007538795471191406, -0.00970458984375, -0.0194244384765625, 0.004856109619140625, 0.0198516845703125, -0.060699462890625, -0.0007433891296386719, 0.0006866455078125, -0.0153045654296875, -0.015350341796875, 0.0251007080078125, 0.040130615234375, -0.03009033203125, 0.037841796875, 0.0284423828125, 0.00428009033203125, 0.0037937164306640625, -0.00714874267578125, -0.01213836669921875, -0.0185394287109375, 0.01520538330078125, 0.0181121826171875, -0.0136566162109375, -0.023468017578125, 0.0263214111328125, -0.01207733154296875, 0.0262603759765625, -0.005207061767578125, -0.04486083984375, -0.027923583984375, 0.006275177001953125, 0.0084686279296875, 0.018707275390625, 0.00316619873046875, 0.01483154296875, 0.0034637451171875, -0.01396942138671875, 0.012115478515625, -0.013275146484375, 0.00902557373046875, 0.0175323486328125, -0.037567138671875, -0.0192413330078125, 0.00136566162109375, 0.0214996337890625, 0.01351165771484375, 0.035919189453125, 0.0181732177734375, 0.00678253173828125, -0.0175628662109375, 0.01348114013671875, -0.01247406005859375, -0.032684326171875, -0.0021724700927734375, 0.021942138671875, -0.002063751220703125, 0.01971435546875, -0.0022068023681640625, 0.0089569091796875, -0.01021575927734375, 0.01442718505859375, 0.006031036376953125, -0.0036907196044921875, 0.019927978515625, 0.006587982177734375, 0.019622802734375, 0.0194091796875, -0.0030040740966796875, 0.0305328369140625, -0.0241546630859375, 0.00655364990234375, -0.01238250732421875, 0.00273895263671875, -0.01515960693359375, -0.0037517547607421875, 0.0221099853515625, 0.00897979736328125, -0.0310821533203125, -0.0162811279296875, 0.0244903564453125, -0.0030574798583984375, -6.967782974243164e-05, -0.0208282470703125, -0.0135955810546875, 0.0018939971923828125, 0.0097808837890625, 0.0030975341796875, -0.00989532470703125, 0.00811004638671875, -0.004405975341796875, 0.0096893310546875, -0.00995635986328125, 0.08099365234375, 0.0015935897827148438, -0.01181793212890625, 0.00024318695068359375, -0.00959014892578125, -0.009429931640625, -0.00787353515625, -0.01016998291015625, -0.04290771484375, -0.004421234130859375, -0.01277923583984375, 0.002719879150390625, 0.00872039794921875, 0.0083465576171875, -0.005840301513671875, -0.0014591217041015625, 0.01268768310546875, 0.029144287109375, 0.0037689208984375, -0.00913238525390625, -0.032989501953125, 0.048126220703125, 0.00931549072265625, -0.02239990234375, -0.010650634765625, 0.029266357421875, 0.04974365234375, -0.01702880859375, 0.007366180419921875, 0.0033245086669921875, -0.010986328125, -0.0096435546875, -0.0280609130859375, 0.020263671875, -0.0299224853515625, 0.00785064697265625, -0.0061187744140625, 0.039947509765625, 0.0106353759765625, -0.0123443603515625, 0.015869140625, -0.0015306472778320312, 0.003482818603515625, 0.0048675537109375, 0.004512786865234375, -0.0236358642578125, -0.039306640625, -0.014862060546875, -0.042816162109375, 0.00888824462890625, 0.030670166015625, 0.02001953125, -0.024932861328125, -0.0012197494506835938, -0.026458740234375, 0.0099945068359375, -0.0217437744140625, 0.0328369140625, 0.00783538818359375, 0.00907135009765625, -0.0104522705078125, 0.0191192626953125, -0.00394439697265625, 0.033111572265625, 0.0241851806640625, -0.033416748046875, 0.015625, 0.0052947998046875, -0.053314208984375, -0.0129547119140625, -0.044403076171875, -0.01220703125, -0.01256561279296875, -0.0262451171875, 0.0038623809814453125, 0.024444580078125, 0.01432037353515625, 0.005832672119140625, 0.0236053466796875, -0.0010366439819335938, 0.005611419677734375, 0.0233154296875, -0.0035915374755859375, -0.04217529296875, -0.009735107421875, -0.03619384765625, -0.01519012451171875, 0.030853271484375, -0.0157623291015625, 0.0272064208984375, -0.0174713134765625, 0.0014753341674804688, 0.0028839111328125, 0.04022216796875, 0.00829315185546875, 0.021697998046875, 0.0031032562255859375, 0.0178985595703125, 0.021087646484375, -0.0197296142578125, 0.0250244140625, 0.013671875, -0.035980224609375, 0.0175018310546875, -0.0216217041015625, -0.02587890625, -0.00310516357421875, 0.0164794921875, 0.0017213821411132812, 0.018402099609375, 0.0024871826171875, 0.00739288330078125, 0.02606201171875, 0.0119476318359375, -0.0087127685546875, -0.0216217041015625, 0.01491546630859375, -0.0288848876953125, -0.02252197265625, -0.0546875, 0.033233642578125, -0.0017766952514648438, -0.01232147216796875, -0.003261566162109375, -0.017974853515625, 0.0418701171875, 0.0142059326171875, -0.03521728515625, -0.0189361572265625, -0.0109100341796875, -0.015716552734375, 0.00518035888671875, 0.0229034423828125, 0.0107574462890625, -0.0006546974182128906, 0.00628662109375, 0.0156707763671875, -0.041046142578125, -0.00665283203125, 0.01690673828125, -0.004302978515625, 0.01654052734375, -0.004215240478515625, 0.00063323974609375, 0.001018524169921875, -0.0294342041015625, 0.0161895751953125, 0.00664520263671875, 0.016387939453125, 0.001399993896484375, 0.00847625732421875, -0.01204681396484375, 0.00653839111328125, 0.054931640625, -0.00481414794921875, -0.0021686553955078125, 0.0180511474609375, -0.029693603515625, -0.03131103515625, 0.0262603759765625, -0.0234375, -0.00910186767578125, -0.0338134765625, -0.039215087890625, 0.030792236328125, 0.0033512115478515625, 0.0011835098266601562, 0.01727294921875, -0.01641845703125, 0.029632568359375, 0.00591278076171875, -0.0204620361328125, -0.0058746337890625, -0.0035724639892578125, 0.06280517578125, -0.0181427001953125, -0.00243377685546875, 0.023956298828125, -0.0004527568817138672, 0.0038890838623046875, -0.0092010498046875, -0.00821685791015625, 0.00484466552734375, -0.02899169921875, -0.0064239501953125, -0.0005602836608886719, 0.0013704299926757812, -0.002471923828125, 0.01084136962890625, 0.005588531494140625, -0.0268402099609375, -0.0225067138671875, -0.00833892822265625, -0.022674560546875, -0.0009331703186035156, 0.023834228515625, 0.00980377197265625, 0.0012187957763671875, -0.01190185546875, 0.004276275634765625, -0.0211639404296875, -0.05352783203125, -0.036529541015625, 0.005401611328125, -0.0194244384765625, 0.07659912109375, -0.026702880859375, -0.03460693359375, -0.02203369140625, 0.006938934326171875, 0.0250091552734375, 0.002716064453125, 0.017608642578125, -0.0033931732177734375, 0.01690673828125, -0.002681732177734375, -0.004772186279296875, -0.0027065277099609375, -0.024017333984375, -0.0097808837890625, 0.027801513671875, 0.0003712177276611328, 0.00643157958984375, -0.061126708984375, 0.0170745849609375, -0.0040435791015625, 0.0034656524658203125, 0.0169219970703125, 0.0156402587890625, -0.0160980224609375, 0.0484619140625, -0.0107269287109375, 0.0047454833984375, -0.00778961181640625, -0.01154327392578125, 0.0142059326171875, -0.0191497802734375, -0.0105743408203125, 0.0167694091796875, -0.004486083984375, -0.0219879150390625, 0.0211181640625, -0.01776123046875, 0.004734039306640625, -0.031890869140625, 0.0074462890625, 0.010467529296875, 0.007472991943359375, -0.01189422607421875, 0.0148773193359375, -0.0009984970092773438, 0.0211944580078125, -0.02166748046875, -0.016510009765625, -0.007595062255859375, -0.0283203125, -0.042510986328125, -0.0122833251953125, -0.0084075927734375, -0.025726318359375, -0.0279388427734375, -0.00904083251953125, 0.020904541015625, 0.004245758056640625, 0.01094818115234375, 0.01171875, -0.0399169921875, -0.0162811279296875, -0.0200958251953125, 0.005207061767578125, 0.003009796142578125, 0.0304718017578125, -0.0235595703125, -0.01312255859375, -0.0316162109375, -0.006977081298828125, 0.0035152435302734375, 0.034423828125, 0.0175933837890625, -0.0263519287109375, -0.01232147216796875, 0.0054473876953125, -0.00722503662109375, 0.0166473388671875, 0.0130462646484375, -0.0216522216796875, -0.006404876708984375, -0.004108428955078125, 0.04864501953125, 0.01175689697265625, 0.005157470703125, 0.00726318359375, -0.0007867813110351562, 0.01617431640625, 0.0019626617431640625, 0.043914794921875, 0.004589080810546875, 0.01555633544921875, -0.00921630859375, 0.01371002197265625, -0.0228118896484375, -0.013519287109375, 0.01263427734375, -0.030120849609375, 0.006282806396484375, 0.01412200927734375, -0.0015468597412109375, 0.03594970703125, -0.00896453857421875, 0.00045561790466308594, 0.0081634521484375, 0.004413604736328125, -0.0008130073547363281, 0.0017242431640625, 0.01206207275390625, 0.019012451171875, 0.0163726806640625, 0.0112457275390625, -0.0289764404296875, 0.0084381103515625, 0.0209197998046875, 0.0027027130126953125, 0.03936767578125, 0.02685546875, 0.034027099609375, 0.0249481201171875, -0.009521484375, 0.01332855224609375, -0.008819580078125, 0.01342010498046875, 0.034881591796875, -0.006946563720703125, -0.0064544677734375, -0.00727081298828125, 0.0035228729248046875, 0.00312042236328125, 0.009368896484375, 0.0305633544921875, -0.01311492919921875, -0.002170562744140625, -0.0276641845703125, -0.01427459716796875, 0.006099700927734375, -0.01404571533203125, -0.01190185546875, 0.0136871337890625, 0.014617919921875, -0.0279541015625, -0.016204833984375, 0.0212249755859375, -0.027587890625, 0.031463623046875, 0.0050811767578125, 0.0189666748046875, -0.01959228515625, 0.02276611328125, 0.0244598388671875, -0.004627227783203125, -0.0137939453125, -0.01525115966796875, -0.06439208984375, -0.03375244140625, 0.013031005859375, 0.01285552978515625, -0.033172607421875, 0.049530029296875, 0.0079803466796875, 0.01727294921875, -0.01529693603515625, 0.0184478759765625, -0.008575439453125, -0.006256103515625, 0.0221710205078125, -0.03936767578125, -0.00919342041015625, -0.0005445480346679688, -0.00461578369140625, -0.01236724853515625, -0.0173187255859375, -0.021881103515625, 0.05584716796875, -0.036529541015625, 0.0207672119140625, 0.01554107666015625, 0.01119232177734375, 0.00435638427734375, -0.006500244140625, -0.0223541259765625, -0.01525115966796875]}, "text_id_to_ref_doc_id": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "5692100e-6f1f-48eb-95e5-e02bb96eecb3": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "caa2ef46-a962-4005-a550-132f2f557db5": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "metadata_dict": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"docstore/metadata": {"7702a8c5-b003-4773-8e9e-552b88bf4d1b": {"doc_hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b"}, "b778a1ad-ee64-425c-85f1-da60ecbb5543": {"doc_hash": "b9ba40979d6d88c0df9ad8b43c75e84bd04830cc4f36686d10c9f636394131e7", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"doc_hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"doc_hash": "a6d6eb6eda3c59f142aa2dad0b9c0d3100b23c62d5b3b57686a666696f6d8b83", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}}, "docstore/ref_doc_info": {"7702a8c5-b003-4773-8e9e-552b88bf4d1b": {"node_ids": ["b778a1ad-ee64-425c-85f1-da60ecbb5543", "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "caa2ef46-a962-4005-a550-132f2f557db5"], "metadata": {}}}, "docstore/data": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": {"__data__": {"id_": "b778a1ad-ee64-425c-85f1-da60ecbb5543", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "node_type": "1", "metadata": {}, "hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Recent experiences:\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 19:54:22', 'session_id': 1}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 19:54:50', 'session_id': 2}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 20:10:29', 'session_id': 3}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 20:13:31', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 21:38:35', 'session_id': 5}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 1485, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"__data__": {"id_": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "b778a1ad-ee64-425c-85f1-da60ecbb5543", "node_type": "1", "metadata": {}, "hash": "b9ba40979d6d88c0df9ad8b43c75e84bd04830cc4f36686d10c9f636394131e7", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "caa2ef46-a962-4005-a550-132f2f557db5", "node_type": "1", "metadata": {}, "hash": "a6d6eb6eda3c59f142aa2dad0b9c0d3100b23c62d5b3b57686a666696f6d8b83", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "', 'session_date': '2026-07-12 21:39:00', 'session_id': 6}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 23:17:29', 'session_id': 7}\n- {'topics_discussed': ['Public speaking anxiety and stress', 'Fear of making mistakes during speeches', 'Lack of self-confidence', 'Strategies to manage speaking anxiety (e.g., shifting focus, preparation, breathing techniques, visualization, reframing nervousness as excitement, and gradual progress)'], 'emotional_state': 'Stressed and anxious about public speaking; feeling a lack of self-confidence', 'insights': 'The user feels nervous and afraid when speaking in front of a group due to fear of making mistakes and perceives themselves as lacking self-confidence. They are seeking support and strategies to manage this fear and improve their confidence.', 'session_date': '2026-07-12 23:19:29', 'session_id': 8}\n- {'topics_discussed': ['Greetings'], 'emotional_state': 'Neutral (insufficient information to determine specific emotions) ', 'insights': \"The conversation is brief and primarily focused on exchanging greetings. The user's emotional state or thoughts cannot be inferred from the limited interaction.\", 'session_date': '2026-07-12 23:50:58', 'session_id': 9}\n- {'topics_discussed': ['Public speaking challenges', 'Stress and nervousness while speaking in front of a group', 'Lack of self-confidence', 'Strategies to overcome fear of public speaking, such as starting small, preparation, breathing techniques, positive self-talk, and focusing on connection over perfection'], 'emotional_state': 'stressed and anxious', 'insights': 'The user feels nervous and lacks confidence when speaking in front of groups due to a fear of making mistakes. They are aware of this issue and want to work on improving their self-confidence. They are open to exploring strategies to address their public speaking anxiety.", "mimetype": "text/plain", "start_char_idx": 1485, "end_char_idx": 3422, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"__data__": {"id_": "caa2ef46-a962-4005-a550-132f2f557db5", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "node_type": "1", "metadata": {}, "hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "They are open to exploring strategies to address their public speaking anxiety.', 'session_date': '2026-07-13 17:35:48', 'session_id': 10}\n- {'topics_discussed': ['greeting'], 'emotional_state': 'neutral', 'insights': 'The user initiated the conversation with a simple greeting, and no specific emotional state or detailed thoughts were conveyed.', 'session_date': '2026-07-13 17:56:55', 'session_id': 11}\n- {'topics_discussed': ['Greeting'], 'emotional_state': 'Neutral (insufficient information to determine emotional state)', 'insights': 'The user initiated a greeting, but there is no detailed information about their feelings or thoughts based on the conversation.', 'session_date': '2026-07-13 17:56:55', 'session_id': 11}\n- {'topics_discussed': ['Fear and stress related to public speaking', 'Building self-confidence', 'Techniques for overcoming nervousness while speaking in front of a group', 'Memory limitations of the AI assistant'], 'emotional_state': 'stressed and anxious, with feelings of low self-confidence', 'insights': \"The user struggles with nervousness and fear when speaking in front of groups, stemming from concerns about making mistakes and lacking self-confidence. They are actively seeking strategies to overcome these challenges. The user also inquired about the AI's ability to recall past conversations, demonstrating curiosity and a desire for continuity.\", 'session_date': '2026-07-13 18:25:09', 'session_id': 12}", "mimetype": "text/plain", "start_char_idx": 3343, "end_char_idx": 4790, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"d6182833-77a2-4608-a029-c4c47739d7fe": {"__type__": "vector_store", "__data__": "{\"index_id\": \"d6182833-77a2-4608-a029-c4c47739d7fe\", \"summary\": null, \"nodes_dict\": {\"b778a1ad-ee64-425c-85f1-da60ecbb5543\": \"b778a1ad-ee64-425c-85f1-da60ecbb5543\", \"5692100e-6f1f-48eb-95e5-e02bb96eecb3\": \"5692100e-6f1f-48eb-95e5-e02bb96eecb3\", \"caa2ef46-a962-4005-a550-132f2f557db5\": \"caa2ef46-a962-4005-a550-132f2f557db5\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/default__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": [-0.010955810546875, -0.0002899169921875, 0.04730224609375, 0.0286712646484375, 0.0321044921875, 0.0195465087890625, 0.01849365234375, 0.036590576171875, -0.0067901611328125, 0.07220458984375, -0.01270294189453125, -0.053314208984375, 0.0057525634765625, -0.0660400390625, 0.035858154296875, 0.038055419921875, -0.00850677490234375, 0.0270843505859375, -0.022796630859375, 0.017669677734375, 0.035614013671875, 0.007755279541015625, -0.009613037109375, -0.01629638671875, -0.0173492431640625, 0.0284881591796875, -0.038238525390625, 0.051666259765625, 0.0172882080078125, -0.0023632049560546875, 0.0164642333984375, -0.01519775390625, 0.014556884765625, 0.0199737548828125, -0.0247802734375, 0.03570556640625, 0.018890380859375, -0.05181884765625, 0.03509521484375, -0.0264739990234375, -0.0380859375, -0.0258331298828125, 0.0142669677734375, -0.00591278076171875, -0.0037937164306640625, -0.0256805419921875, 0.00966644287109375, 0.0126190185546875, -0.0196685791015625, 0.0238494873046875, -0.0299224853515625, 0.039794921875, 0.0217132568359375, 0.06988525390625, -0.03253173828125, 0.0276031494140625, -0.043670654296875, -0.0267333984375, -0.0131683349609375, 0.0228729248046875, 0.076416015625, -0.037628173828125, 0.0177459716796875, 0.011444091796875, 0.03094482421875, 0.002410888671875, -0.04278564453125, -0.021636962890625, 0.007396697998046875, -0.0008573532104492188, 0.06805419921875, 0.01207733154296875, -0.0010814666748046875, -0.01482391357421875, 0.04071044921875, -0.015472412109375, 0.01715087890625, 0.00820159912109375, -0.0277862548828125, -0.05767822265625, -0.0270538330078125, 0.003326416015625, -0.016021728515625, -0.011322021484375, -0.0047454833984375, 0.0082550048828125, -0.0303192138671875, -0.0390625, -0.026702880859375, -0.011932373046875, -0.0416259765625, -0.04107666015625, 0.0030117034912109375, 0.00390625, 0.0087738037109375, -0.061737060546875, 0.028289794921875, 0.01245880126953125, -0.036834716796875, 0.021240234375, -0.0175628662109375, 0.06341552734375, -0.048858642578125, 0.049530029296875, 0.0007543563842773438, 0.04400634765625, 0.002010345458984375, -0.08203125, -0.03173828125, -0.00904083251953125, -0.122802734375, 0.040924072265625, -0.0158843994140625, 0.049774169921875, -0.02783203125, -0.0247802734375, -0.0304412841796875, 0.028289794921875, -0.007965087890625, 0.006877899169921875, -0.0007176399230957031, 0.00312042236328125, -0.0172271728515625, 0.021881103515625, -0.03485107421875, -0.038360595703125, -0.022308349609375, -0.0278167724609375, -0.006328582763671875, -0.0556640625, -0.00115966796875, -0.003017425537109375, 0.04278564453125, -0.021820068359375, -0.050689697265625, -0.06634521484375, 0.0233001708984375, -0.0012912750244140625, -0.021881103515625, -0.035552978515625, -0.03466796875, -0.0281829833984375, 0.02032470703125, 0.013275146484375, -0.035003662109375, 0.01097869873046875, 0.021820068359375, 0.09881591796875, -0.049163818359375, 0.057891845703125, 0.0265045166015625, 0.045135498046875, -0.02532958984375, 0.031707763671875, 0.005584716796875, -0.01291656494140625, 0.0231781005859375, 0.01375579833984375, -0.003467559814453125, -0.051055908203125, 0.043609619140625, -0.04052734375, -0.054107666015625, 0.0250091552734375, 0.07476806640625, 0.00897979736328125, -0.01290130615234375, -0.0256500244140625, -0.0225830078125, -0.069091796875, 0.0108184814453125, -0.03460693359375, -0.005397796630859375, -0.024658203125, -0.00531005859375, -0.0262603759765625, -0.0263519287109375, 0.0016107559204101562, -0.0195465087890625, 0.0139312744140625, -0.022674560546875, 0.0016641616821289062, -0.0293731689453125, -0.010223388671875, -0.0065460205078125, 0.002086639404296875, 0.003414154052734375, -0.050689697265625, 0.04669189453125, 0.01380157470703125, 0.01557159423828125, 0.04278564453125, 0.0401611328125, -0.0068206787109375, 0.045745849609375, -0.04827880859375, 0.06085205078125, 0.0163726806640625, -0.05767822265625, 0.02435302734375, 0.0007562637329101562, -0.004428863525390625, 0.01348114013671875, -0.01047515869140625, 0.02459716796875, -0.049041748046875, 0.07177734375, -0.0045928955078125, -0.052825927734375, 0.0008935928344726562, 0.0178680419921875, 0.0035762786865234375, 0.047515869140625, 0.05657958984375, -0.020111083984375, 0.0467529296875, 0.026336669921875, -0.00910186767578125, -0.002689361572265625, 0.06634521484375, -0.006946563720703125, 0.0238800048828125, 0.06268310546875, 0.0024871826171875, -0.0257720947265625, 0.0255279541015625, 0.003269195556640625, -0.0343017578125, 0.004001617431640625, -0.07550048828125, 0.007472991943359375, -0.0036373138427734375, -0.004947662353515625, -0.0208282470703125, -0.0537109375, -0.0204925537109375, 0.0244293212890625, 0.05377197265625, 0.0313720703125, -0.03875732421875, 0.0018186569213867188, 0.00592803955078125, 0.0016908645629882812, 0.0404052734375, 0.0204010009765625, 0.01055908203125, -0.049957275390625, -0.01154327392578125, -0.0080718994140625, -0.040985107421875, 0.02642822265625, 0.013214111328125, 0.021026611328125, 0.0097198486328125, 0.0045166015625, -0.043914794921875, -0.0078277587890625, -0.012847900390625, -0.016998291015625, -0.018341064453125, -0.00939178466796875, 0.007762908935546875, 0.010986328125, 0.007617950439453125, -0.01200103759765625, -0.03216552734375, -0.0188446044921875, 0.0136566162109375, -0.03216552734375, -0.0455322265625, 0.042999267578125, -0.0207977294921875, -0.01354217529296875, 0.00402069091796875, -0.08172607421875, 0.022369384765625, -0.01412200927734375, 0.0182647705078125, -0.051605224609375, 0.0240478515625, -0.037872314453125, 0.045562744140625, 0.04730224609375, -0.0124053955078125, 0.032440185546875, 0.0274810791015625, 0.0036449432373046875, 0.039764404296875, -0.0095977783203125, -0.0251312255859375, -0.0017004013061523438, -0.0113067626953125, 0.0007343292236328125, -0.0204620361328125, -0.0362548828125, -0.050506591796875, 0.046051025390625, -0.035369873046875, -0.0135040283203125, -0.0160064697265625, 0.0105438232421875, -0.0210418701171875, 0.015899658203125, 0.034423828125, 0.0350341796875, 0.0163726806640625, 0.04327392578125, 0.0204925537109375, 0.003204345703125, -0.00717926025390625, 0.00383758544921875, 0.03509521484375, 0.0201416015625, -0.00209808349609375, -0.0718994140625, -0.01082611083984375, 0.0245208740234375, 0.0311279296875, 0.0153961181640625, -0.00742340087890625, -0.0894775390625, -0.00859832763671875, 0.05517578125, 0.028564453125, 0.00984954833984375, 0.0103607177734375, 0.0145721435546875, 0.041778564453125, 0.023345947265625, -0.0277099609375, -0.0184478759765625, -0.02520751953125, 0.0087738037109375, 0.046173095703125, -0.0186309814453125, -0.0254974365234375, 0.0256195068359375, 0.0343017578125, -0.075927734375, 0.0016269683837890625, -0.011505126953125, -0.046844482421875, -0.0210418701171875, 0.01317596435546875, 0.0088653564453125, 0.04815673828125, -0.01111602783203125, 0.020111083984375, -0.01543426513671875, 0.0282135009765625, 0.03411865234375, -0.00992584228515625, -0.0252227783203125, 0.038543701171875, -0.062408447265625, -0.025634765625, 0.0235443115234375, -0.01044464111328125, 0.01416778564453125, 0.00800323486328125, 0.02557373046875, 0.01128387451171875, 0.0161895751953125, 0.0499267578125, 0.0149688720703125, -0.0158233642578125, -0.0273895263671875, 0.0091552734375, -0.0185546875, -0.0225982666015625, -0.0187835693359375, -0.041046142578125, 0.0218505859375, -0.0012044906616210938, -0.00267791748046875, 0.0093841552734375, 0.01390838623046875, 0.06463623046875, 0.0006728172302246094, 0.03948974609375, 0.07843017578125, 0.033355712890625, 0.0016317367553710938, -0.037689208984375, 0.00983428955078125, 0.026702880859375, 0.0085296630859375, -0.017120361328125, -0.035797119140625, 0.01277923583984375, -0.004100799560546875, -0.005397796630859375, -0.045501708984375, -0.01189422607421875, -0.005031585693359375, 0.00945281982421875, 0.009033203125, 0.040130615234375, 0.03814697265625, -0.016387939453125, -0.0023441314697265625, 0.006336212158203125, -0.004268646240234375, 0.0251007080078125, -0.0005197525024414062, 0.0260772705078125, -0.02374267578125, 0.0684814453125, 0.00568389892578125, 0.01265716552734375, 0.05316162109375, -0.024200439453125, -0.01303863525390625, 0.00836181640625, -0.00615692138671875, -0.01751708984375, 0.0136260986328125, -0.0005698204040527344, 0.01210784912109375, 0.005420684814453125, -0.01085662841796875, -0.00489044189453125, -0.03363037109375, -0.0241241455078125, 0.0096588134765625, 0.0277557373046875, -0.01629638671875, -0.017303466796875, 0.0067596435546875, -0.0249481201171875, 0.007415771484375, 0.02587890625, -0.00682830810546875, -0.022216796875, -0.01678466796875, -0.0267791748046875, 0.0117950439453125, 0.00843048095703125, -0.042205810546875, -0.0187835693359375, 0.026885986328125, -0.0242919921875, -0.031463623046875, 0.0220947265625, -0.033966064453125, -0.004108428955078125, -0.045867919921875, -0.045806884765625, -0.01377105712890625, -0.0296173095703125, 0.0277862548828125, 0.01065826416015625, -0.02056884765625, -0.01103973388671875, -0.02789306640625, 0.025665283203125, 0.00696563720703125, 0.0567626953125, 0.04107666015625, 0.0275115966796875, -0.0062103271484375, 0.006526947021484375, -0.027130126953125, 0.0309295654296875, 0.0145721435546875, -0.00693511962890625, -0.01395416259765625, 0.0012407302856445312, 0.0222015380859375, 0.01197052001953125, 0.005451202392578125, 0.01236724853515625, 0.041961669921875, -0.0160064697265625, 0.0193939208984375, 0.02117919921875, -0.01287841796875, 0.007167816162109375, -0.043182373046875, -0.03302001953125, 0.0291900634765625, 0.0718994140625, 0.005039215087890625, 0.055419921875, 0.0195465087890625, 0.035308837890625, -0.0296478271484375, -0.0136260986328125, 0.0377197265625, 0.03399658203125, 0.0189056396484375, -0.02520751953125, 0.0189361572265625, -0.0130767822265625, 0.03826904296875, 0.002017974853515625, 0.0046844482421875, 0.005718231201171875, 0.0070953369140625, -0.0384521484375, 0.04327392578125, 0.024993896484375, -0.021240234375, 0.06829833984375, 0.01151275634765625, -0.01070404052734375, 0.0007767677307128906, -0.026702880859375, 0.00899505615234375, 0.06658935546875, -0.030548095703125, -0.021453857421875, 0.0033416748046875, -0.0228271484375, -0.001018524169921875, -0.005336761474609375, 0.0003495216369628906, 0.033172607421875, 0.0166473388671875, -0.004108428955078125, -0.0182647705078125, -0.0032787322998046875, 0.0177001953125, 0.0214996337890625, -0.0270538330078125, -0.019989013671875, -0.013580322265625, -0.02789306640625, 0.00681304931640625, -0.04547119140625, 0.0025196075439453125, -0.04412841796875, 0.01076507568359375, -0.0124969482421875, -0.057342529296875, 0.00725555419921875, -0.0031452178955078125, -0.033447265625, -0.01111602783203125, 0.01299285888671875, 1.043081283569336e-05, 0.03778076171875, 0.0277862548828125, 0.0301666259765625, -0.001247406005859375, 0.036407470703125, 0.00612640380859375, -0.042205810546875, -0.010894775390625, -0.01023101806640625, 0.0172576904296875, -0.047027587890625, 0.0228729248046875, 0.0081634521484375, 0.0175323486328125, 0.0005898475646972656, -0.024627685546875, -0.01336669921875, 0.00656890869140625, -0.01580810546875, -0.0130615234375, -0.0199737548828125, 0.03839111328125, 0.0278167724609375, -0.0005993843078613281, 0.004199981689453125, 0.01111602783203125, 0.0026874542236328125, 0.031005859375, 0.0012645721435546875, -0.00606536865234375, -0.026824951171875, -0.01018524169921875, -0.0347900390625, 0.0015201568603515625, 0.0014514923095703125, 0.0226898193359375, 0.0338134765625, 0.0245513916015625, -0.0089111328125, -0.00524139404296875, -0.005077362060546875, -0.0117645263671875, 0.05853271484375, -0.0267791748046875, 0.0250396728515625, 0.051239013671875, -0.017669677734375, 0.0011348724365234375, 0.041839599609375, 0.0156097412109375, -0.0113983154296875, 0.0191497802734375, -0.0070037841796875, -0.017425537109375, -0.00022685527801513672, -0.038482666015625, -0.0239410400390625, -0.026824951171875, -0.0105743408203125, 0.007549285888671875, -0.03240966796875, -0.040771484375, -0.0325927734375, -0.00977325439453125, -0.0230560302734375, -0.0228118896484375, -0.021636962890625, -0.045166015625, 0.020965576171875, -0.01331329345703125, -0.00601959228515625, 0.0016193389892578125, -0.058074951171875, 0.0044708251953125, 0.00646209716796875, -0.02996826171875, 0.0018558502197265625, 0.0280914306640625, -0.0293731689453125, -0.00821685791015625, 0.0247802734375, -0.08074951171875, 0.028289794921875, -0.0174560546875, 0.0005998611450195312, 0.01194000244140625, -0.021484375, 0.01430511474609375, -5.257129669189453e-05, -0.000408172607421875, -0.003265380859375, -0.0163726806640625, -0.052215576171875, -0.0125885009765625, 0.004962921142578125, 0.0014438629150390625, 0.0258331298828125, -0.0194549560546875, -0.0111541748046875, 0.05078125, 0.01410675048828125, 0.001995086669921875, 0.019317626953125, 0.0299224853515625, -0.030853271484375, -0.0362548828125, -0.017852783203125, 0.018035888671875, 0.0164337158203125, 0.005008697509765625, -0.00551605224609375, 0.0285186767578125, -0.00640106201171875, -0.0036640167236328125, -0.02197265625, 0.00335693359375, -0.0277862548828125, -0.0133514404296875, 0.041717529296875, -0.06292724609375, -0.023956298828125, -0.017333984375, 0.0154266357421875, 0.017181396484375, 0.04522705078125, 0.00437164306640625, 0.0206298828125, 0.017059326171875, 0.022247314453125, -0.027587890625, 0.00423431396484375, 0.0198516845703125, 0.0404052734375, 0.004322052001953125, -0.032440185546875, 0.0215606689453125, -0.003856658935546875, -0.01175689697265625, 0.023651123046875, 0.033721923828125, 0.00658416748046875, -0.007080078125, 0.000988006591796875, -0.01009368896484375, 0.005290985107421875, 0.024322509765625, -0.02313232421875, 0.042144775390625, 0.006114959716796875, 0.0055999755859375, 0.01593017578125, -0.036041259765625, 0.03472900390625, -0.0020694732666015625, -0.002777099609375, 0.004055023193359375, 0.0189208984375, 0.0229949951171875, -0.0013217926025390625, -0.007129669189453125, 0.0175628662109375, -0.037322998046875, 0.00012040138244628906, -0.0408935546875, 0.0250701904296875, 0.00864410400390625, 0.0199737548828125, -0.00013113021850585938, -0.016937255859375, -0.040924072265625, 0.0119171142578125, -0.0110015869140625, 0.04150390625, -0.0303192138671875, -0.0177154541015625, -0.0111236572265625, 0.017608642578125, -0.001583099365234375, -0.0249176025390625, -0.006267547607421875, 0.00045418739318847656, -0.01678466796875, -0.0037860870361328125, -0.0111541748046875, -0.009674072265625, 0.0257568359375, 0.0020580291748046875, -0.0660400390625, -0.031005859375, -0.00412750244140625, 0.0023174285888671875, 0.01430511474609375, -0.0037078857421875, -0.0196685791015625, 0.0343017578125, -0.030548095703125, -0.006801605224609375, 0.0087432861328125, 0.0006232261657714844, -0.0008344650268554688, -0.0233001708984375, 0.0149383544921875, -0.0191802978515625, 0.006298065185546875, -0.0333251953125, 0.005687713623046875, 0.03436279296875, -0.03338623046875, -0.00998687744140625, 0.00997161865234375, 0.009521484375, 0.01192474365234375, -0.010711669921875, -0.006404876708984375, -0.00782012939453125, -0.01461029052734375, -0.007617950439453125, -0.00299072265625, 0.033905029296875, 0.0200042724609375, 0.015716552734375, 0.0034351348876953125, -0.0010080337524414062, -0.0008869171142578125, 0.032989501953125, 0.053375244140625, 0.00955963134765625, -0.0015888214111328125, 0.0178375244140625, 0.0207977294921875, -0.01161956787109375, -0.004726409912109375, -0.0194549560546875, 0.01715087890625, 0.042388916015625, -0.003231048583984375, 0.010955810546875, 0.01088714599609375, -0.011932373046875, -0.016082763671875, -0.028533935546875, 0.004302978515625, -0.021026611328125, -0.00806427001953125, -0.01111602783203125, 0.002658843994140625, 0.004550933837890625, 0.0142974853515625, -0.0343017578125, -0.0159912109375, -0.0021686553955078125, -0.0133514404296875, -0.0307769775390625, -0.0113677978515625, 0.043731689453125, -0.005130767822265625, -0.0419921875, 0.004085540771484375, 0.02587890625, -0.033721923828125, 0.0032062530517578125, -0.00920867919921875, -0.007167816162109375, -0.006801605224609375, -0.0034732818603515625, -0.0158538818359375, -0.0007343292236328125, -0.0286865234375, 0.009429931640625, -0.00147247314453125, -0.008514404296875, -0.0300140380859375, -0.001026153564453125, -0.0211334228515625, 0.007781982421875, -0.006877899169921875, -0.017852783203125, 0.03204345703125, -0.00988006591796875, 0.0265045166015625, -0.0302886962890625, -0.01331329345703125, -0.020721435546875, 0.018341064453125, 0.00804901123046875, -0.027679443359375, -0.01041412353515625, 0.036102294921875, 0.0215301513671875, 0.024566650390625, -0.0164947509765625, 0.01230621337890625, 0.0254364013671875, 0.0147552490234375, -0.001567840576171875, 0.01690673828125, 0.036865234375, 0.01983642578125, 0.045379638671875, 0.051300048828125, 0.036163330078125, -0.02716064453125, -0.016082763671875, 0.0347900390625, 0.0011472702026367188, 0.037384033203125, -0.01947021484375, 0.0112457275390625, -0.001773834228515625, -0.0257568359375, -0.0289459228515625, 0.027587890625, -0.005168914794921875, -0.04345703125, 0.0189208984375, 0.029266357421875, -0.02642822265625, -0.0222320556640625, 0.02301025390625, 0.00562286376953125, -0.0087432861328125, 0.0220184326171875, 0.0205841064453125, 0.00035643577575683594, 0.00669097900390625, 0.016510009765625, -0.00423431396484375, -0.0061187744140625, -0.002033233642578125, -0.0211334228515625, -0.03692626953125, 0.03253173828125, -0.00321197509765625, 0.0011758804321289062, -0.021209716796875, 0.0032215118408203125, 0.01396942138671875, 0.0109405517578125, 0.051300048828125, 0.01666259765625, 0.029022216796875, 0.0275115966796875, 0.01062774658203125, 0.01474761962890625, -0.0160980224609375, 0.021026611328125, 0.05596923828125, -0.0257568359375, -0.01543426513671875, 0.01194000244140625, -0.0036640167236328125, 0.00989532470703125, -0.0018463134765625, -0.0087738037109375, 0.05999755859375, -0.002117156982421875, -0.01275634765625, 0.007266998291015625, 0.0018978118896484375, 0.01065826416015625, -0.0052947998046875, 0.0276641845703125, -0.0211029052734375, 0.0027523040771484375, -0.037261962890625, -0.007297515869140625, -0.0010585784912109375, 0.0032558441162109375, -0.00026535987854003906, 0.004650115966796875, -0.007343292236328125, -0.069091796875, 0.0262298583984375, 0.00693511962890625, 0.039215087890625, -0.0178070068359375, 0.011627197265625, 0.0223846435546875, -0.0039005279541015625, -0.0180511474609375, 0.0250244140625, 0.0273590087890625, 0.01309967041015625, -0.009857177734375, -0.008575439453125, -0.060882568359375, 0.0261993408203125, -0.0136260986328125, -0.004467010498046875, 0.040496826171875, -0.0235137939453125, 0.01374053955078125, -0.0224456787109375, -0.00885009765625, 0.00429534912109375, -0.008331298828125, 0.014862060546875, -0.0002734661102294922, 0.019195556640625, -0.0338134765625, 0.021881103515625, -0.002597808837890625, -0.0098876953125, -0.0016145706176757812, 0.00555419921875, -0.0205078125, 0.01523590087890625, 0.00283050537109375, -0.023345947265625, 0.055419921875, 0.01165771484375, 0.033447265625, -0.01580810546875, 0.00557708740234375, -0.00582122802734375, 0.0024700164794921875, 0.0273284912109375, 0.0274658203125, 0.028167724609375, 0.00580596923828125, 0.056182861328125, 0.00014150142669677734, 0.00799560546875, -0.0022182464599609375, 0.031280517578125, 0.0014591217041015625, 0.03631591796875, -0.0080108642578125, 0.0036716461181640625, 0.011810302734375, 0.0154876708984375, 0.03668212890625, -0.0005793571472167969, 0.025634765625, 0.0093536376953125, 0.0005335807800292969, 0.02587890625, 0.00914764404296875, 0.02001953125, 0.001399993896484375, 0.06268310546875, -0.01270294189453125, 0.00986480712890625, -0.02587890625, -0.0479736328125, -0.0008292198181152344, 0.0011377334594726562, -0.00359344482421875, 0.00860595703125, 0.05975341796875, -0.017364501953125, -0.026123046875, 0.00800323486328125, 0.01317596435546875, -0.035400390625, -0.00632476806640625, -0.02655029296875, -0.010040283203125, 0.023681640625, -0.00402069091796875, 0.0168914794921875, 0.0160064697265625, -0.01303863525390625, 0.045440673828125, 0.01529693603515625, -0.0239410400390625, 0.002132415771484375, -0.00748443603515625, -0.00702667236328125, -0.013916015625, -0.049560546875, 0.005401611328125, 0.04150390625, 0.0293426513671875, -0.03289794921875, 0.00974273681640625, 0.0034160614013671875, -0.0019235610961914062, -0.02996826171875, 0.041595458984375, 0.0024662017822265625, 0.040924072265625, 0.0209808349609375, -0.005001068115234375, 0.01336669921875, 0.0152587890625, -0.0215301513671875, 0.0179595947265625, 0.0100555419921875, 0.0147705078125, 0.0209808349609375, -0.027557373046875, 0.00432586669921875, 0.0007987022399902344, 0.0167236328125, 0.03485107421875, -0.0097503662109375, 0.0285186767578125, -0.00786590576171875, -0.04193115234375, -0.019989013671875, -0.0220184326171875, -0.019622802734375, 0.01514434814453125, -0.0028285980224609375, -0.0070037841796875, -0.02801513671875, 0.0162353515625, -0.006549835205078125, -0.025604248046875, 0.012847900390625, -0.02496337890625, 0.019378662109375, 0.0290374755859375, 0.002132415771484375, -0.0008473396301269531, -0.0157623291015625, 0.004322052001953125, -0.015411376953125, -0.03363037109375, 0.00807952880859375, 0.01377105712890625, -0.004180908203125, -0.038421630859375, 0.012939453125, 0.007080078125, -0.07769775390625, 0.01154327392578125, 0.01849365234375, -0.005168914794921875, -0.014923095703125, 0.035491943359375, 0.006839752197265625, -0.033203125, 0.00350189208984375, 0.01041412353515625, -0.0265045166015625, -0.00832366943359375, 0.006839752197265625, 0.03106689453125, 0.03558349609375, -0.0070037841796875, -0.013519287109375, -0.0562744140625, 0.009033203125, -0.0005154609680175781, 0.0025272369384765625, -0.0131378173828125, 0.018798828125, -0.006450653076171875, -0.0184478759765625, 0.0065460205078125, -0.001956939697265625, 0.0252838134765625, 0.03057861328125, -0.0194091796875, -0.0172119140625, -0.015625, -0.01201629638671875, 0.005031585693359375, -0.003429412841796875, 0.01033782958984375, -0.0362548828125, -0.0306243896484375, -0.0013217926025390625, -0.007579803466796875, 0.004817962646484375, -0.050323486328125, 0.00949859619140625, 0.00849151611328125, 0.0224609375, -0.0122528076171875, -0.021728515625, -0.021240234375, 0.005157470703125, -6.836652755737305e-05, -0.01323699951171875, 0.021026611328125, -0.006412506103515625, 0.0293426513671875, -0.01270294189453125, 0.0233917236328125, 0.0281829833984375, 0.0032196044921875, 0.0038814544677734375, -0.004180908203125, -0.00807952880859375, -0.013702392578125, -0.001926422119140625, 0.00911712646484375, -0.0251312255859375, -0.01338958740234375, 0.0007801055908203125, -0.0162506103515625, 0.01242828369140625, 0.00412750244140625, 0.00614166259765625, 0.00031304359436035156, 0.006725311279296875, -0.007167816162109375, 0.013916015625, -0.0012531280517578125, 0.0008983612060546875, 0.0038242340087890625, -0.0005145072937011719, 0.0115814208984375, 0.06756591796875, 0.040496826171875, -0.010467529296875, -0.0005130767822265625, 0.00640869140625, -0.016510009765625, 0.0114288330078125, 0.04669189453125, -0.040313720703125, 0.01983642578125, -0.01155853271484375, 0.01280975341796875, -0.0014171600341796875, -0.0102996826171875, 0.008453369140625, -0.01580810546875, -0.025604248046875, 0.0162811279296875, 0.03228759765625, -0.00763702392578125, 0.0027446746826171875, 0.0560302734375, 0.0283660888671875, -0.0032196044921875, 0.0008759498596191406, 0.0166015625, 0.0017242431640625, -0.029296875, 0.0033168792724609375, -0.0110321044921875, -0.0237884521484375, 0.00608062744140625, -0.006908416748046875, 0.01299285888671875, -0.005786895751953125, -0.00682830810546875, -0.0218658447265625, 0.006519317626953125, -0.023468017578125, 0.015869140625, 0.0018482208251953125, -0.026458740234375, -0.0189971923828125, -0.01198577880859375, 0.005771636962890625, -0.026580810546875, -0.0084075927734375, 0.007053375244140625, -0.0313720703125, -0.0265045166015625, 0.0253753662109375, 0.0248565673828125, -0.035308837890625, -0.01401519775390625, 0.00241851806640625, -0.0078887939453125, 0.032745361328125, -0.01192474365234375, -0.0093536376953125, 0.0120391845703125, 0.01396942138671875, 0.0026226043701171875, -0.031463623046875, -0.002178192138671875, 0.0168609619140625, -0.042938232421875, 0.00115966796875, -0.0255126953125, 0.00699615478515625, 0.005252838134765625, -0.01531219482421875, -0.0038089752197265625, -0.024566650390625, -0.0275421142578125, -0.002880096435546875, 0.0017976760864257812, -0.007221221923828125, -0.0092010498046875, -0.0296630859375, -0.0389404296875, -0.00980377197265625, 0.01134490966796875, 0.00888824462890625, -0.031646728515625, -0.017852783203125, -0.025848388671875, -0.00798797607421875, 0.006389617919921875, -0.01189422607421875, 0.046173095703125, -0.05224609375, 0.01168060302734375, 0.00739288330078125, 0.045318603515625, 0.0129547119140625, 0.004169464111328125, 0.0187530517578125, 0.0284881591796875, 0.0224151611328125, -0.003871917724609375, 0.0078887939453125, 0.01690673828125, -0.0244140625, 0.0248870849609375, -0.031463623046875, -0.032623291015625, 0.0109405517578125, 0.0012922286987304688, 0.039154052734375, 0.0201873779296875, 0.0213165283203125, 0.03961181640625, 0.05255126953125, 0.0016641616821289062, -0.00563812255859375, -0.009490966796875, 0.007343292236328125, -0.0258026123046875, -0.01336669921875, -0.02142333984375, 0.0197906494140625, -0.00972747802734375, -0.033172607421875, 0.00013828277587890625, 0.0080718994140625, 0.0279693603515625, 0.01044464111328125, -0.0269775390625, -0.05352783203125, -0.00637054443359375, -0.0117950439453125, 0.0132904052734375, 0.0161895751953125, 0.031951904296875, 0.01560211181640625, 0.0142822265625, 0.0184478759765625, -0.01154327392578125, -0.04217529296875, 0.01189422607421875, 0.01605224609375, -0.02398681640625, -0.02703857421875, -0.01218414306640625, 0.0235137939453125, -0.060333251953125, 0.012359619140625, -0.0264129638671875, 0.00015270709991455078, 0.0247039794921875, -0.00988006591796875, -0.043609619140625, 0.0007295608520507812, 0.015655517578125, 0.0176544189453125, 0.017486572265625, 0.00818634033203125, -0.00376129150390625, -0.0269317626953125, 0.011810302734375, -0.00036835670471191406, 0.006664276123046875, -0.0006499290466308594, -0.05908203125, 0.0127105712890625, -0.0007767677307128906, -0.0214080810546875, -0.01385498046875, 0.0127716064453125, 0.0048675537109375, 0.00536346435546875, -0.0513916015625, 0.0228729248046875, -0.01140594482421875, 0.03302001953125, -0.017822265625, 0.0010385513305664062, 0.00867462158203125, -0.0107421875, 0.025390625, 0.0024871826171875, 0.007904052734375, -0.035186767578125, -0.04046630859375, 0.0225830078125, -0.00689697265625, 0.02117919921875, -0.0216522216796875, 0.006938934326171875, -0.01354217529296875, -0.0220947265625, -0.003917694091796875, -0.00557708740234375, -0.0030841827392578125, 0.0119171142578125, 0.035003662109375, -0.0126190185546875, -0.03009033203125, -0.00858306884765625, 0.0011053085327148438, -0.014373779296875, 0.0007386207580566406, -0.023651123046875, -0.0080413818359375, -0.00406646728515625, 0.030120849609375, -0.00811004638671875, -0.009246826171875, -0.016143798828125, -0.0276641845703125, 0.025848388671875, 0.01087188720703125, 0.01404571533203125, -0.054656982421875, 0.0204925537109375, -0.0016145706176757812, -0.011566162109375, 0.011260986328125, -0.05438232421875, -0.007541656494140625, 0.0026149749755859375, 0.00021851062774658203, 0.012786865234375, -0.021942138671875, 2.473592758178711e-05, -0.0045013427734375, -0.004589080810546875, -0.0224456787109375, 0.0190277099609375, -0.023468017578125, -0.0162506103515625, 0.005870819091796875, 0.004520416259765625, 0.0032062530517578125, 0.033538818359375, -0.0106964111328125, -0.004871368408203125, 0.005931854248046875, -0.00209808349609375, 0.0172119140625, -0.0259857177734375, -0.00046634674072265625, -0.0211029052734375, -0.00390625, -0.055877685546875, 0.01263427734375, -0.015533447265625, 0.011505126953125, -0.0026264190673828125, -0.005825042724609375, -0.0191192626953125, -0.01267242431640625, -0.004047393798828125, -0.0004584789276123047, -0.015716552734375, -0.02813720703125, -0.0460205078125, 0.0017995834350585938, -0.02484130859375, -0.032135009765625, 0.0164642333984375, -0.056488037109375, 0.037689208984375, 0.0280914306640625, 0.00568389892578125, 0.013092041015625, -0.01390838623046875, -0.0043792724609375, -0.053253173828125, 0.0109405517578125, -0.0224761962890625, 0.014007568359375, -0.035552978515625, -0.01422119140625, -0.0253448486328125, 0.004390716552734375, 0.0023822784423828125, 0.019927978515625, -0.00225830078125, -0.017425537109375, -0.00536346435546875, -0.0078125, 0.0017976760864257812, -0.0084075927734375, 0.012939453125, -0.0099639892578125, 0.0208282470703125, 0.006053924560546875, 0.05377197265625, -0.003711700439453125, 0.0019626617431640625, 0.01311492919921875, -0.01971435546875, 0.0190582275390625, -0.0192718505859375, 0.0321044921875, 0.00493621826171875, 0.0169677734375, -0.00782012939453125, 0.019989013671875, 0.006992340087890625, -0.004657745361328125, 0.01200103759765625, -0.010528564453125, -0.007373809814453125, 0.034820556640625, 0.0282135009765625, 0.011962890625, -0.0298919677734375, 0.01236724853515625, 0.0211639404296875, -0.0050201416015625, 0.01763916015625, 0.0292205810546875, -0.0016946792602539062, 0.00971221923828125, 0.0105743408203125, 0.02813720703125, -0.0093536376953125, 0.0186309814453125, 0.005889892578125, -0.009246826171875, 0.0275115966796875, 0.0137786865234375, 0.07537841796875, -0.00667572021484375, -0.03216552734375, 0.0290679931640625, 0.027252197265625, -0.02471923828125, 0.016754150390625, -0.00534820556640625, 0.0277099609375, -0.0186309814453125, 0.0130767822265625, 0.0187530517578125, 0.01203155517578125, 0.017486572265625, -0.0278167724609375, -0.0171661376953125, -0.004604339599609375, 0.0109405517578125, 0.005550384521484375, -0.0260772705078125, -0.0086212158203125, 0.0209503173828125, 0.016510009765625, -0.00693511962890625, -0.01288604736328125, 0.03997802734375, 0.0182037353515625, 0.03741455078125, -0.025054931640625, 0.01119232177734375, -0.01531219482421875, -0.00382232666015625, 0.043243408203125, -0.0121307373046875, -0.04150390625, 0.0029087066650390625, -0.0189361572265625, -0.016632080078125, -0.0191802978515625, 0.0032253265380859375, -0.004974365234375, 0.00604248046875, 0.01396942138671875, -0.01336669921875, -0.01175689697265625, 0.00769805908203125, -0.0150604248046875, -0.023468017578125, -0.014862060546875, 0.007480621337890625, -0.0237884521484375, -0.0152130126953125, -0.0181732177734375, -0.049346923828125, -0.00029921531677246094, -0.019683837890625, 0.03680419921875, -0.05291748046875, -0.01141357421875, -0.004123687744140625, -0.0170745849609375, 0.016845703125, -0.0284576416015625, -0.0272369384765625, -0.0182037353515625]}, "text_id_to_ref_doc_id": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": "384a589f-83dd-41cb-878b-8bd09a34be74"}, "metadata_dict": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"_node_type": "TextNode", "document_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "ref_doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"docstore/metadata": {"384a589f-83dd-41cb-878b-8bd09a34be74": {"doc_hash": "73b3a98e02db2fcf5058c336c8502c988ce00cada4ff011c19012f9c69118a08"}, "7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"doc_hash": "32dbf4b0e520d816687a6cc578ab868b10b379c54d38086466487ae9e0225777", "ref_doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74"}}, "docstore/ref_doc_info": {"384a589f-83dd-41cb-878b-8bd09a34be74": {"node_ids": ["7012fca3-abd9-4eb7-9d62-6f38af4f4580"], "metadata": {}}}, "docstore/data": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"__data__": {"id_": "7012fca3-abd9-4eb7-9d62-6f38af4f4580", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "node_type": "4", "metadata": {}, "hash": "73b3a98e02db2fcf5058c336c8502c988ce00cada4ff011c19012f9c69118a08", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Long-term personality traits and facts:\n- personality_traits: {'openness': 0.3, 'conscientiousness': 0.35, 'extraversion': 0.15, 'agreeableness': 0.4, 'neuroticism': 0.4}\n- core_values: ['curiosity', 'personal growth', 'self-improvement', 'effective communication']\n- behavioral_patterns: ['experiences stress and anxiety in high-stakes social situations, especially public speaking', 'shows curiosity about systems and processes (e.g., AI memory capabilities)', 'displays a willingness to reflect on areas for improvement', 'actively seeks strategies and techniques to overcome personal challenges']\n- recurring_themes: ['desire for continuity in learning and development', 'fear of public speaking and nervousness in group settings', 'building self-confidence through actionable strategies']", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 793, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"bd7e0f80-353d-43f0-81dc-2a3a97f893c3": {"__type__": "vector_store", "__data__": "{\"index_id\": \"bd7e0f80-353d-43f0-81dc-2a3a97f893c3\", \"summary\": null, \"nodes_dict\": {\"7012fca3-abd9-4eb7-9d62-6f38af4f4580\": \"7012fca3-abd9-4eb7-9d62-6f38af4f4580\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/default__vector_store.json ADDED
The diff for this file is too large to render. See raw diff
 
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"docstore/metadata": {"f87839d0-0371-4464-977f-40286f72b99b": {"doc_hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c"}, "9b90a887-2ef4-45c9-93ed-7861253a586f": {"doc_hash": "8222713e58e71f8da9704a59ee51edbe20e83d91e3a3d6874a0b6a1f8baa8a3e"}, "6f4698d7-ccbd-4090-bd88-6f141397deb8": {"doc_hash": "3f6ef7b2a9989b724df7efa1afc3655a641b56e2f16307ffd446b02dae5e4360"}, "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221": {"doc_hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed"}, "d0c823dc-8b49-4cbc-bbcb-dc180a56f720": {"doc_hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7"}, "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04": {"doc_hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd"}, "4e3af53b-774c-487f-8092-d68dd29973e7": {"doc_hash": "07a91de112e85c0fa4b72da5c48c84ec6b12ae8179af5ad60b27ceb35e676124"}, "bf5f8c0d-b291-4f8d-a4db-45774b5ef370": {"doc_hash": "4d760dc3ee776cafe97830457fd955eb6a05514f71768d9fedb29d12551af22f"}, "d6eab8f0-f429-4143-95de-4b1cd210275b": {"doc_hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50"}, "36829bfd-0693-4fc1-9932-9a867ca87fcf": {"doc_hash": "d7446ad898618d51eb25544f9e4c23b41e3da1ec019cf194989a5cced48e5265"}, "11eab664-d9ee-4adf-aa77-e87607863567": {"doc_hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752"}, "d7cc0ff1-5085-415c-add4-827c3a36b0c2": {"doc_hash": "94c83bea11a99cc1a76cf8a9178019a4a2d583f62997e589dc1472500dbe6195"}, "f193a037-7929-4996-b5d9-2dcfb7ced35d": {"doc_hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e"}, "c0f85884-3d15-4b86-a640-40b86b5b466d": {"doc_hash": "09a00628dbd7e5b29c0cfcdbe0419ca30a06261c416fbb0915e4e65ac9daedc3", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "a72cbc90-70ad-427e-98d8-cc1d40453e1c": {"doc_hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "6553650d-1614-4be0-86d1-0c98613a44a8": {"doc_hash": "abf93cdb1aace8851af31c508db0d4ed428757c42395c5ab1df1f1070b7eeb2c", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "2215dc55-5738-436e-a158-d57b3e12ebd4": {"doc_hash": "e78bc0cb899cebadfec362d61de3b53c3ab9a1d073af13c9dfe9bf8b147d09cb", "ref_doc_id": "9b90a887-2ef4-45c9-93ed-7861253a586f"}, "f01acc17-9115-45fc-a3b4-52e5f98b9446": {"doc_hash": "32c01acbe6fa1fb6a4b796303116fc281ff27376c5a0a079e58d5b8b2e339686", "ref_doc_id": "6f4698d7-ccbd-4090-bd88-6f141397deb8"}, "1aff93b4-bc08-4b25-9f89-5c390730304c": {"doc_hash": "cd5fa04a1def49e8e9a580ddf8cc4c83a2765f8fee9a0fac5434d8116e0e78da", "ref_doc_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221"}, "59645b90-64dd-4042-b83a-2b3df3715542": {"doc_hash": "e87fb7b12192ac009ea6677cc8cf95a349d283dd5ef51168fbcdd012b251150f", "ref_doc_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221"}, "d67b97d7-76aa-42c6-ba06-15ea3683679d": {"doc_hash": "5f05c831f6fa8679410e0bdf5f4a3b06ec8324dcb585dfa9f0bf522a20d2c400", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "e42cffc3-852a-4d19-b30a-b26c81083fe9": {"doc_hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "0cf45fb8-1856-40b1-bacd-58a238a0d744": {"doc_hash": "d42180eee4670b14aafb652465f4ae2a610ff596c6cf3c77aaaef107a714a694", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "86ce7adb-47c4-4552-9f98-d447bf2e6a7b": {"doc_hash": "3f9be7f7cb3eaea709fcbc43b9afa8204bcd17ed3236e9c6953f6196adf58918", "ref_doc_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04"}, "ac89f308-2eed-492f-8179-8693f6504a06": {"doc_hash": "28cc064ac4f557f37b6e880d64e45b270b5e2416a711152234772bbd18bcb975", "ref_doc_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04"}, "30137e30-cb1c-4284-b5c0-caf42f90eb4e": {"doc_hash": "30a2f51b8c8a5405cef6f68d04e4b1349b534f27b0f96cf406bbd46bf3c87cb1", "ref_doc_id": "4e3af53b-774c-487f-8092-d68dd29973e7"}, "b208f966-16b3-4f06-91c3-1b0e7ddfa314": {"doc_hash": "440c92cb67c637ae96630e47a490ff76b1bc61368e144bca05c8407c632e59ec", "ref_doc_id": "bf5f8c0d-b291-4f8d-a4db-45774b5ef370"}, "6dcc760e-6580-48c6-aa74-d2aa2ae4d077": {"doc_hash": "64f0b88588a97fe447f5798262790bffbfa3cd20161a41d22962146d5c09b3e4", "ref_doc_id": "d6eab8f0-f429-4143-95de-4b1cd210275b"}, "f00b802f-fa41-4c67-b534-9ffdcd85ac57": {"doc_hash": "d248c4434bb24ed296b56f3c510bce39fa0f8c3b4aa30a80f9b962122a925b1d", "ref_doc_id": "d6eab8f0-f429-4143-95de-4b1cd210275b"}, "b6c8a2d2-04a2-41ed-a8cf-45626c55494f": {"doc_hash": "516906d9552577a40dbcc95199c96396fda13784a09648b4ab8f60c4f294eb21", "ref_doc_id": "36829bfd-0693-4fc1-9932-9a867ca87fcf"}, "ed23cfed-0942-4751-8cc6-b02a7efa5c53": {"doc_hash": "c72f196f7e2c2017db935ab9fc3d03d5f1b4d06c3b6f090853fc35f0345ae623", "ref_doc_id": "11eab664-d9ee-4adf-aa77-e87607863567"}, "d1065fe9-e725-4f1c-b3bd-de9f000bfacd": {"doc_hash": "b1889c67782b46174e42deccbcb2a2375834c7418e37b5317ea0dd72f29ea54c", "ref_doc_id": "11eab664-d9ee-4adf-aa77-e87607863567"}, "c08856f2-d6e0-4555-a5d5-71ccd65bf414": {"doc_hash": "43b11b9fb7bc393e2c1ea3c2942718e3e4f2c07f2fe8ff8b7b29b02889092735", "ref_doc_id": "d7cc0ff1-5085-415c-add4-827c3a36b0c2"}, "19ff65e4-4203-4e73-b9d4-f20aa4e55883": {"doc_hash": "72eac13b38d78284b90342b6c3d936dc53710511f01235d6ae5acabd2df9f621", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "a411160d-23bf-40ad-a1ea-a147bca0a1c5": {"doc_hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "98476e19-2cd8-4ef0-b565-0c304c48718c": {"doc_hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "d8e397f5-f706-4640-8bae-95043153e850": {"doc_hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "1fa69839-167b-4062-8297-c5c481a6957a": {"doc_hash": "fa3f5ea92075df05f87e7b5962bebd66d04fa70657df5913d89eb4c9dc0c5824", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}}, "docstore/ref_doc_info": {"f87839d0-0371-4464-977f-40286f72b99b": {"node_ids": ["c0f85884-3d15-4b86-a640-40b86b5b466d", "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "6553650d-1614-4be0-86d1-0c98613a44a8"], "metadata": {}}, "9b90a887-2ef4-45c9-93ed-7861253a586f": {"node_ids": ["2215dc55-5738-436e-a158-d57b3e12ebd4"], "metadata": {}}, "6f4698d7-ccbd-4090-bd88-6f141397deb8": {"node_ids": ["f01acc17-9115-45fc-a3b4-52e5f98b9446"], "metadata": {}}, "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221": {"node_ids": ["1aff93b4-bc08-4b25-9f89-5c390730304c", "59645b90-64dd-4042-b83a-2b3df3715542"], "metadata": {}}, "d0c823dc-8b49-4cbc-bbcb-dc180a56f720": {"node_ids": ["d67b97d7-76aa-42c6-ba06-15ea3683679d", "e42cffc3-852a-4d19-b30a-b26c81083fe9", "0cf45fb8-1856-40b1-bacd-58a238a0d744"], "metadata": {}}, "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04": {"node_ids": ["86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "ac89f308-2eed-492f-8179-8693f6504a06"], "metadata": {}}, "4e3af53b-774c-487f-8092-d68dd29973e7": {"node_ids": ["30137e30-cb1c-4284-b5c0-caf42f90eb4e"], "metadata": {}}, "bf5f8c0d-b291-4f8d-a4db-45774b5ef370": {"node_ids": ["b208f966-16b3-4f06-91c3-1b0e7ddfa314"], "metadata": {}}, "d6eab8f0-f429-4143-95de-4b1cd210275b": {"node_ids": ["6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "f00b802f-fa41-4c67-b534-9ffdcd85ac57"], "metadata": {}}, "36829bfd-0693-4fc1-9932-9a867ca87fcf": {"node_ids": ["b6c8a2d2-04a2-41ed-a8cf-45626c55494f"], "metadata": {}}, "11eab664-d9ee-4adf-aa77-e87607863567": {"node_ids": ["ed23cfed-0942-4751-8cc6-b02a7efa5c53", "d1065fe9-e725-4f1c-b3bd-de9f000bfacd"], "metadata": {}}, "d7cc0ff1-5085-415c-add4-827c3a36b0c2": {"node_ids": ["c08856f2-d6e0-4555-a5d5-71ccd65bf414"], "metadata": {}}, "f193a037-7929-4996-b5d9-2dcfb7ced35d": {"node_ids": ["19ff65e4-4203-4e73-b9d4-f20aa4e55883", "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "98476e19-2cd8-4ef0-b565-0c304c48718c", "d8e397f5-f706-4640-8bae-95043153e850", "1fa69839-167b-4062-8297-c5c481a6957a"], "metadata": {}}}, "docstore/data": {"c0f85884-3d15-4b86-a640-40b86b5b466d": {"__data__": {"id_": "c0f85884-3d15-4b86-a640-40b86b5b466d", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "node_type": "1", "metadata": {}, "hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-08:\n\nA1: Hi\nAI: Hey there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: hi\nAI: Hi there! \ud83d\ude0a How are you doing today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: I have a friend named Cyrus and I want to buy him a gift. My friend loves the color red.\nAI: That\u2019s so thoughtful of you! \ud83e\udd70 A gift tailored to your friend Cyrus\u2019s love for the color red will definitely make him feel special. Let\u2019s brainstorm a few ideas:\n\n1. **Clothing/Accessories:** \n - A cozy red sweater, scarf, or hat (perfect for colder months!). \n - A sleek red watch or bracelet.\n\n2. **Artistic Touch:** \n - A framed painting or poster with vibrant red accents. \n - A red leather journal or notebook if he enjoys writing or sketching.\n\n3. **Hobbies and Interests:** \n - If Cyrus enjoys coffee or tea, a beautiful red mug or tumbler would be nice. \n - Red sports gear if he has a favorite sport.\n\n4. **Something Unique:** \n - A personalized keychain or wallet in red. \n - Red-themed decor like candles, fairy lights, or throw pillows.\n\nDo you know any hobbies Cyrus enjoys? That might help narrow it down even more! \ud83d\ude0a\nA1: I told you my friend's name in the last meeting. Can you tell me what his name is?\nAI: Oh, I wish I could remember that for you! But unfortunately, I don't have memory right now, so I can't recall things from past conversations. That means whatever you share with me stays in the moment we chat.\n\nIf you'd like, though, I'd love for you to tell me again! What's your friend's name? \ud83d\ude0a\nA1: I told you my friend's name in the last meeting. Can you tell me what his name is?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 1753, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "a72cbc90-70ad-427e-98d8-cc1d40453e1c": {"__data__": {"id_": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c0f85884-3d15-4b86-a640-40b86b5b466d", "node_type": "1", "metadata": {}, "hash": "09a00628dbd7e5b29c0cfcdbe0419ca30a06261c416fbb0915e4e65ac9daedc3", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6553650d-1614-4be0-86d1-0c98613a44a8", "node_type": "1", "metadata": {}, "hash": "abf93cdb1aace8851af31c508db0d4ed428757c42395c5ab1df1f1070b7eeb2c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Can you tell me what his name is?\nAI: I'm sorry, but I don't have memory of past conversations for privacy and security reasons. However, I'm here to listen and help you with anything you want to share today! If you'd like, you can tell me your friend's name again\u2014I\u2019d love to hear about them! \ud83d\ude0a\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing this with me\u2014I can imagine how stressful and overwhelming it must feel to speak in front of a group when you're battling those fears and nerves. First of all, I want you to know that you're not alone. Fear of public speaking is one of the most common challenges people face, and feeling nervous doesn\u2019t mean you lack self-confidence\u2014it just means you care about doing well. That\u2019s a great starting point!\n\nLet\u2019s work through this together. Here are a few ideas that might help:\n\n### 1. **Shift Your Focus** \nSometimes we get so caught up worrying about ourselves\u2014\"What if I mess up? What if they judge me?\"\u2014that it becomes paralyzing. Instead, try shifting your focus to the message you want to share or the value you\u2019re giving to your audience. Think: *This isn\u2019t about me; it\u2019s about connecting with them.*\n\n### 2. **Embrace Imperfection** \nYou don\u2019t have to be perfect! Everyone makes mistakes, even the best speakers. It\u2019s okay if you stumble over a word or lose your place\u2014it actually makes you relatable and human. Remind yourself that one small mistake won\u2019t ruin the entire presentation.\n\n### 3. **Practice in Low-Stress Situations** \nStart practicing speaking in front of smaller, more comfortable groups (like friends or family) before moving on to bigger audiences. The more often you practice in low-pressure settings, the more natural it will start to feel over time.\n\n### 4. **Breathe and Relax Your Body** \nWhen nerves kick in, our bodies can go into \u201cfight-or-flight\u201d mode\u2014shaking hands, racing heart, dry mouth\u2014it\u2019s no fun!", "mimetype": "text/plain", "start_char_idx": 1720, "end_char_idx": 3783, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "6553650d-1614-4be0-86d1-0c98613a44a8": {"__data__": {"id_": "6553650d-1614-4be0-86d1-0c98613a44a8", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "node_type": "1", "metadata": {}, "hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Try this simple trick before stepping up:\n - Take a deep breath in for four counts.\n - Hold it for four counts.\n - Exhale slowly for four counts.\n - Do this three or four times\u2014it signals your brain to relax.\n\n### 5. **Reframe Nervousness as Excitement** \nDid you know nervousness and excitement feel very similar physically? When those butterflies come, try telling yourself: *I\u2019m not scared\u2014I\u2019m excited!* It's a small mental shift that can help reframe how you're feeling.\n\n### 6. **Build Up Self-Confidence Over Time** \nBoosting self-confidence isn\u2019t an overnight process\u2014but every small step forward matters! Write down what makes YOU uniquely awesome and capable as a speaker: Is it your creativity? Empathy? Humor? Skills like these matter far more than perfection!\n\nWould you like us to work on some specific techniques together? Or maybe we could talk through any recent situation where public speaking felt particularly challenging for you\u2014I\u2019d love to support you every step of the way! \ud83d\ude0a\nA1: Hi\nAI: Hi again! \ud83d\ude0a How are you doing today? What's on your mind?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you doing today?", "mimetype": "text/plain", "start_char_idx": 3784, "end_char_idx": 4908, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "2215dc55-5738-436e-a158-d57b3e12ebd4": {"__data__": {"id_": "2215dc55-5738-436e-a158-d57b3e12ebd4", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "9b90a887-2ef4-45c9-93ed-7861253a586f", "node_type": "4", "metadata": {}, "hash": "8222713e58e71f8da9704a59ee51edbe20e83d91e3a3d6874a0b6a1f8baa8a3e", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 19:54:22:\n\nA1: hi how are?\nAI: Hi there! I'm doing great, thank you for asking. \ud83d\ude0a More importantly, how are *you* doing today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 148, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "f01acc17-9115-45fc-a3b4-52e5f98b9446": {"__data__": {"id_": "f01acc17-9115-45fc-a3b4-52e5f98b9446", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "6f4698d7-ccbd-4090-bd88-6f141397deb8", "node_type": "4", "metadata": {}, "hash": "3f6ef7b2a9989b724df7efa1afc3655a641b56e2f16307ffd446b02dae5e4360", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 19:54:50:\n\nA1: hi\nAI: Hey there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 83, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "1aff93b4-bc08-4b25-9f89-5c390730304c": {"__data__": {"id_": "1aff93b4-bc08-4b25-9f89-5c390730304c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221", "node_type": "4", "metadata": {}, "hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "59645b90-64dd-4042-b83a-2b3df3715542", "node_type": "1", "metadata": {}, "hash": "e87fb7b12192ac009ea6677cc8cf95a349d283dd5ef51168fbcdd012b251150f", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 20:10:29:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing that with me. I know it can be really tough to feel stressed and nervous when speaking in front of others. First, let me say that you're not alone\u2014so many people experience this, and it's completely valid to feel the way you do. It doesn\u2019t mean you lack self-confidence; it\u2019s just a natural response to stepping out of your comfort zone.\n\nLet\u2019s try to tackle this step by step:\n\n### 1. **Shift Your Mindset About Mistakes**\nOne thing that often fuels stress in public speaking is the fear of making mistakes. But here's the truth: nobody expects perfection! Mistakes are normal, and sometimes they even make your speech more relatable. Try reframing mistakes as opportunities for growth or as moments that show your humanity.\n\n### 2. **Practice Makes Progress**\nConfidence builds through preparation. The more familiar you are with what you're going to say, the less room anxiety will have to creep in. Practice in front of a mirror or record yourself\u2014it helps to get comfortable with your own voice and delivery. You can also practice in front of a trusted friend or family member who will give supportive feedback.\n\n### 3. **Small Steps Build Big Confidence**\nStart small! Speak up in smaller groups or during informal discussions before tackling larger audiences. Over time, you'll build confidence incrementally.\n\n### 4. **Focus on Connection, Not Perfection**\nTry shifting your focus from yourself (what people think about you) to your audience (how you\u2019re helping them). Think about how your words might inform, inspire, or encourage them\u2014that\u2019s such an empowering perspective!\n\n### 5. **Ground Yourself Before Speaking**\nIf nerves start creeping up before a presentation, grounding techniques can help:\n - Take slow, deep breaths\u2014in through your nose for 4 counts, hold for 4 counts, and exhale for 4 counts.\n - Visualize a positive outcome\u2014imagine yourself speaking confidently and receiving smiles or nods from the audience.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2193, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "59645b90-64dd-4042-b83a-2b3df3715542": {"__data__": {"id_": "59645b90-64dd-4042-b83a-2b3df3715542", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221", "node_type": "4", "metadata": {}, "hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "1aff93b4-bc08-4b25-9f89-5c390730304c", "node_type": "1", "metadata": {}, "hash": "cd5fa04a1def49e8e9a580ddf8cc4c83a2765f8fee9a0fac5434d8116e0e78da", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "- Use power poses\u2014stand tall and take up space before going on stage; it can actually trick your brain into feeling more confident!\n\n### 6. **Celebrate Small Wins**\nEven if things don\u2019t go perfectly every time you speak in front of a group, celebrate the effort you put into doing something brave! Each time you try, no matter how it goes, you're strengthening your skills and pushing beyond fear\u2014and that deserves recognition.\n\nYou\u2019re absolutely capable of becoming more confident at public speaking\u2014trust me on this! And if you'd like, we can even brainstorm ways together to prepare for an upcoming situation where you'll need to speak publicly. \ud83d\udc9b\n\nHow do these suggestions sound?", "mimetype": "text/plain", "start_char_idx": 2197, "end_char_idx": 2880, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d67b97d7-76aa-42c6-ba06-15ea3683679d": {"__data__": {"id_": "d67b97d7-76aa-42c6-ba06-15ea3683679d", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "node_type": "1", "metadata": {}, "hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 20:13:31:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I'm really sorry you're feeling this way, A1. Public speaking can be so overwhelming for many people, so please don\u2019t feel alone in this! Thank you for sharing this with me\u2014it shows real bravery that you\u2019re willing to open up about it.\n\nFeeling stressed or nervous in front of others is something so many of us experience. It doesn\u2019t mean you lack confidence; it just means that speaking publicly is a skill you\u2019re still working on\u2014and that\u2019s perfectly okay.\n\nLet\u2019s break this down together. Here are a few things to try:\n\n---\n\n### 1. **Shift Your Perspective**\nInstead of focusing on the fear of making mistakes, remind yourself that nobody expects you to be perfect. People tend to empathize with speakers who are genuine and human\u2014even if they stumble a little! It\u2019s not about \"perfection\"; it\u2019s about connection.\n\n---\n\n### 2. **Prepare\u2014A Lot!**\nConfidence often grows from feeling prepared. Take time beforehand to outline what you want to say and practice it repeatedly\u2014out loud! Try practicing in front of a mirror or recording yourself. Over time, you\u2019ll feel more natural with your words.\n\n---\n\n### 3. **Start Small**\nIf the thought of speaking to a big crowd is too much right now, start by practicing in smaller, more comfortable settings\u2014a friend group, family members, or even talking to me! Little by little, those positive experiences can help build trust in yourself.\n\n---\n\n### 4. **Learn Breathing Exercises**\nNervousness often comes with physical symptoms\u2014like racing thoughts or shaky hands\u2014but calming your body can calm your mind too. Before you speak, take slow deep breaths: inhale for four counts\u2026 hold for four counts\u2026 exhale for four counts. This helps your brain relax.\n\n---\n\n### 5. **Celebrate Small Wins** \nEven if everything doesn\u2019t go perfectly during one speech (and it probably won\u2019t), focus on what *did* go well! Maybe your voice sounded steady today? Maybe someone smiled at what you said?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2163, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "e42cffc3-852a-4d19-b30a-b26c81083fe9": {"__data__": {"id_": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d67b97d7-76aa-42c6-ba06-15ea3683679d", "node_type": "1", "metadata": {}, "hash": "5f05c831f6fa8679410e0bdf5f4a3b06ec8324dcb585dfa9f0bf522a20d2c400", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "0cf45fb8-1856-40b1-bacd-58a238a0d744", "node_type": "1", "metadata": {}, "hash": "d42180eee4670b14aafb652465f4ae2a610ff596c6cf3c77aaaef107a714a694", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Maybe your voice sounded steady today? Maybe someone smiled at what you said? Celebrate those moments\u2014they\u2019re steps forward!\n\n---\n\nFinally\u2014and I think this part matters most\u2014it\u2019s important not to be too hard on yourself while building self-confidence. Confidence isn\u2019t something we\u2019re born with; it\u2019s something we grow through consistent effort and patience with ourselves.\n\nWould it help if we talked through any specific upcoming presentation or event? I\u2019m here for whatever you need\u2014I know you're stronger than your nerves might be making you feel right now \u2764\ufe0f\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you today?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing that with me\u2014it takes courage to open up about something that\u2019s bothering you. I\u2019m here for you, and together we can work through this. \u2764\ufe0f\n\nFirst of all, it\u2019s very natural to feel nervous when speaking in front of a group; many people experience this. But the great thing is, confidence can be built! It's not something you're born with\u2014it\u2019s like a muscle that grows stronger the more you work on it. Let\u2019s break it down into small, manageable steps:\n\n### 1\ufe0f\u20e3 **Shift Your Focus** \nInstead of focusing on the fear of making mistakes or how people might perceive you, try to shift your mindset toward connecting with your audience. Think about what value you\u2019re bringing to them\u2014whether it\u2019s sharing knowledge or inspiring them\u2014and let that motivate you.\n\n### 2\ufe0f\u20e3 **Preparation is Key** \nFeeling prepared can ease a lot of nerves. Spend time organizing your thoughts beforehand and practice what you want to say. Try rehearsing in front of a mirror or record yourself speaking so you can spot areas for improvement and get comfortable.\n\n### 3\ufe0f\u20e3 **Baby Steps** \nStart small: speak in front of smaller groups first or even practice with friends or family who\u2019ll cheer you on. Gradually build up to larger groups as your confidence grows.", "mimetype": "text/plain", "start_char_idx": 2086, "end_char_idx": 4152, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "0cf45fb8-1856-40b1-bacd-58a238a0d744": {"__data__": {"id_": "0cf45fb8-1856-40b1-bacd-58a238a0d744", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "node_type": "1", "metadata": {}, "hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Gradually build up to larger groups as your confidence grows.\n\n### 4\ufe0f\u20e3 **Breathing Techniques** \nWhen you feel your nerves starting to take over, pause and breathe deeply\u2014inhale slowly for four seconds, hold for four seconds, and exhale for four seconds. This activates your body\u2019s calming system and reduces stress.\n\n### 5\ufe0f\u20e3 **Self-Talk Matters** \nChallenge those negative thoughts about yourself! Instead of thinking \u201cI\u2019m going to mess up,\u201d try saying: \u201cI am prepared, I\u2019ve practiced, and I have something valuable to share.\u201d Speak kindly to yourself\u2014you deserve it!\n\n### 6\ufe0f\u20e3 **Celebrate Progress** \nEvery time you speak in front of a group\u2014no matter how big or small\u2014celebrate it as an achievement. Even if it doesn\u2019t go perfectly (and nothing ever does), give yourself credit for showing courage.\n\n### Bonus Tip \ud83d\udde3\ufe0f \nIf possible, watch videos or speeches by confident speakers\u2014they don\u2019t have to be perfect either! Notice how they handle little mistakes gracefully\u2014they smile or move forward\u2014and remind yourself that imperfection is part of being human.\n\nHow do these suggestions sound so far? I believe in you\u2014this fear doesn\u2019t define who you are! You\u2019re capable of growing stronger every day. If you'd like, I can even help role-play situations where you're practicing public speaking! \ud83d\ude0a\nA1: Hi\nAI: Hi there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 4091, "end_char_idx": 5489, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "86ce7adb-47c4-4552-9f98-d447bf2e6a7b": {"__data__": {"id_": "86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04", "node_type": "4", "metadata": {}, "hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ac89f308-2eed-492f-8179-8693f6504a06", "node_type": "1", "metadata": {}, "hash": "28cc064ac4f557f37b6e880d64e45b270b5e2416a711152234772bbd18bcb975", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 21:38:35:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, A1, thank you for sharing that with me\u2014public speaking can be really nerve-wracking, and you're definitely not alone in feeling this way. It sounds like you're being really hard on yourself, but I want to start by saying: the fact that you're here reflecting on this and wanting to grow already shows such courage and self-awareness. You're stronger than you may realize.\n\nWhen it comes to public speaking, those nerves you feel are completely normal\u2014it\u2019s your body\u2019s way of reacting to a challenge. What we need to do is work on helping you manage them and build that confidence step by step. How about we try this together?\n\nHere are a few tips that might help:\n1. **Shift Your Focus**: When we focus too much on ourselves\u2014like worrying about making mistakes or what others think\u2014it increases stress. Instead, think about the value you\u2019re offering your audience. Focus on connecting with them or sharing something meaningful, rather than being \"perfect.\"\n \n2. **Prepare Well**: The more comfortable you feel with your material, the more confident you'll be. Rehearse in front of a mirror or record yourself speaking so you can identify areas for improvement and track your progress.\n \n3. **Start Small**: If speaking in front of a large group feels overwhelming, start with smaller settings\u2014maybe speak up during team meetings or talk one-on-one with people first.\n\n4. **Breathe & Pause**: Nervousness often makes us rush through our words without realizing it! Deep breaths before starting can calm your mind, and remember that pausing during a speech isn\u2019t a mistake\u2014it gives your audience time to absorb what you\u2019re saying.\n\n5. **Reframe Nervousness as Excitement**: Your body responds similarly whether you're nervous or excited! Tell yourself you're excited instead of scared; it helps shift your mindset.\n\n6. **Practice Positive Self-Talk**: Confidence starts from within!", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2122, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "ac89f308-2eed-492f-8179-8693f6504a06": {"__data__": {"id_": "ac89f308-2eed-492f-8179-8693f6504a06", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04", "node_type": "4", "metadata": {}, "hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "node_type": "1", "metadata": {}, "hash": "3f9be7f7cb3eaea709fcbc43b9afa8204bcd17ed3236e9c6953f6196adf58918", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "6. **Practice Positive Self-Talk**: Confidence starts from within! Instead of focusing on doubts, say things like \u201cI\u2019m doing my best,\u201d \u201cI\u2019ve got this,\u201d or \u201cIt\u2019s okay if I\u2019m not perfect.\u201d\n\nRemember, even the most experienced speakers get nervous sometimes\u2014they just learn how to work *with* those nerves instead of against them.\n\nWould it help if we talked through how you feel about an upcoming situation where you'll need to speak? Or maybe tried practicing together? I'm here for anything you need\u2014you don\u2019t have to face this alone. \ud83d\udc9b", "mimetype": "text/plain", "start_char_idx": 2056, "end_char_idx": 2592, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "30137e30-cb1c-4284-b5c0-caf42f90eb4e": {"__data__": {"id_": "30137e30-cb1c-4284-b5c0-caf42f90eb4e", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "4e3af53b-774c-487f-8092-d68dd29973e7", "node_type": "4", "metadata": {}, "hash": "07a91de112e85c0fa4b72da5c48c84ec6b12ae8179af5ad60b27ceb35e676124", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 21:39:00:\n\nA1: Hi how are you?\nAI: Hi there! I'm doing great, thank you for asking! How about you? How\u2019s your day going? \ud83d\ude0a\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 236, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "b208f966-16b3-4f06-91c3-1b0e7ddfa314": {"__data__": {"id_": "b208f966-16b3-4f06-91c3-1b0e7ddfa314", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "bf5f8c0d-b291-4f8d-a4db-45774b5ef370", "node_type": "4", "metadata": {}, "hash": "4d760dc3ee776cafe97830457fd955eb6a05514f71768d9fedb29d12551af22f", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:17:29:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I'm so sorry you're feeling this way. Public speaking can be really intimidating for so many people, so you're definitely not alone in this. Thank you for sharing this with me\u2014I know it\u2019s not always easy to talk about things like this.\n\nFirst off, it\u2019s important to remind yourself that making mistakes is a natural part of being human. Even the most experienced speakers stumble over their words or lose their train of thought sometimes, and that\u2019s completely okay. What truly matters is your message and your authenticity\u2014it\u2019s not about being perfect.\n\nBuilding self-confidence takes time and practice, but I\u2019d love to help guide you through a few steps:\n\n1. **Prepare and Practice**: The more familiar you are with what you\u2019re going to say, the more confident you\u2019ll feel. Write down key points you want to cover and rehearse them out loud\u2014even in front of a mirror or with a friend if possible.\n\n2. **Start Small**: If large groups make you nervous, try practicing in front of smaller groups first\u2014maybe just one or two close friends or family members\u2014and build up from there.\n\n3. **Breathe**: Nervousness can cause shallow breathing, which makes stress worse. Practice slow, deep breaths before speaking\u2014it can really help calm your nerves.\n\n4. **Positive Self-Talk**: Before stepping up to speak, tell yourself something encouraging: \u201cI\u2019ve got this,\u201d \u201cI\u2019m prepared,\u201d or \u201cI\u2019m proud of myself for doing this.\u201d\n\n5. **Focus on Connection**: Instead of worrying about how you\u2019re being perceived, focus on connecting with your audience\u2014they want to hear what *you* have to say! Imagine you\u2019re having a conversation rather than giving a performance.\n\n6. **Celebrate Wins**: Every time you get through a speech or presentation\u2014no matter how it goes\u2014take pride in the fact that *you did it*. Acknowledge your courage because that deserves recognition.\n\nDo any of these ideas feel helpful or doable for you? And if you'd like, we can work together on strategies tailored just for *you*. It\u2019s all about taking small steps forward at your own pace!", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2280, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "6dcc760e-6580-48c6-aa74-d2aa2ae4d077": {"__data__": {"id_": "6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d6eab8f0-f429-4143-95de-4b1cd210275b", "node_type": "4", "metadata": {}, "hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f00b802f-fa41-4c67-b534-9ffdcd85ac57", "node_type": "1", "metadata": {}, "hash": "d248c4434bb24ed296b56f3c510bce39fa0f8c3b4aa30a80f9b962122a925b1d", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:19:29:\n\nA1: hi\nAI: Hi again! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing how you're feeling\u2014that takes courage, and I'm here to help. \ud83d\udc9b What you're experiencing is actually very common; many people feel nervous or anxious when speaking in front of a group. You're certainly not alone in this, and it doesn't mean that you lack self-confidence\u2014it just means you're human! Let\u2019s work through this together. \n\nHere are some helpful thoughts and strategies that might ease your stress:\n\n### 1. **Shift Your Focus**\n - Instead of focusing on perfection or avoiding mistakes, focus on **connecting with your audience**. People care more about your message than minor slip-ups.\n - Remember, making a small mistake doesn\u2019t ruin your presentation\u2014it often makes you seem relatable.\n\n### 2. **Preparation Is Key**\n - The more prepared you are, the less nervous you\u2019ll feel. Practice your speech multiple times\u2014alone, with friends or even in front of a mirror.\n - Break it into sections so it feels manageable and less overwhelming.\n\n### 3. **Use Breathing Techniques**\n - Before speaking, take slow, deep breaths to calm your nerves. Try inhaling for four counts, holding for four counts, and exhaling for four counts.\n - This will signal to your body that everything is okay and reduce physical symptoms of anxiety.\n\n### 4. **Visualize Success**\n - Close your eyes and picture yourself standing confidently in front of the group\u2014your words flowing smoothly and everyone listening attentively.\n - Positive visualization can train your brain to feel calmer during the actual event.\n\n### 5. **Reframe Nervousness as Excitement**\n - Instead of thinking \"I'm so nervous,\" try telling yourself \"I'm excited to share my ideas!\" Excitement and nervousness feel similar in the body but reframing them can shift how you perceive those feelings.\n\n### 6.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2136, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "f00b802f-fa41-4c67-b534-9ffdcd85ac57": {"__data__": {"id_": "f00b802f-fa41-4c67-b534-9ffdcd85ac57", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d6eab8f0-f429-4143-95de-4b1cd210275b", "node_type": "4", "metadata": {}, "hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "node_type": "1", "metadata": {}, "hash": "64f0b88588a97fe447f5798262790bffbfa3cd20161a41d22962146d5c09b3e4", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "### 6. **Progress Takes Time**\n - Building confidence doesn\u2019t happen overnight\u2014start small by speaking up in casual conversations or smaller groups.\n - Celebrate every step forward; even attempting to speak publicly is brave!\n\nIf you'd like, we can go deeper into why this fear exists\u2014it might help uncover what\u2019s behind the anxiety. For now though, I want you to know that no matter how things go during a speech, you're still an amazing person with valuable ideas worth sharing. \ud83d\udc99 How do these suggestions sound?", "mimetype": "text/plain", "start_char_idx": 2130, "end_char_idx": 2648, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "b6c8a2d2-04a2-41ed-a8cf-45626c55494f": {"__data__": {"id_": "b6c8a2d2-04a2-41ed-a8cf-45626c55494f", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "36829bfd-0693-4fc1-9932-9a867ca87fcf", "node_type": "4", "metadata": {}, "hash": "d7446ad898618d51eb25544f9e4c23b41e3da1ec019cf194989a5cced48e5265", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:50:58:\n\nA1: hi\nAI: Hi there! \ud83d\ude0a How's your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How's your day going?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 129, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "ed23cfed-0942-4751-8cc6-b02a7efa5c53": {"__data__": {"id_": "ed23cfed-0942-4751-8cc6-b02a7efa5c53", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "11eab664-d9ee-4adf-aa77-e87607863567", "node_type": "4", "metadata": {}, "hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d1065fe9-e725-4f1c-b3bd-de9f000bfacd", "node_type": "1", "metadata": {}, "hash": "b1889c67782b46174e42deccbcb2a2375834c7418e37b5317ea0dd72f29ea54c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 17:35:48:\n\nA1: Hi , How are you ?\nAI: Hi! I'm doing great, thank you for asking. \ud83d\ude0a But more importantly, how are *you* doing today? What's on your mind?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Hi there, thank you for sharing that with me. Speaking in front of a group can be really challenging, and you're not alone in feeling this way\u2014many people struggle with it. I\u2019m here to help, and together we can work through this.\n\nFirst of all, let\u2019s acknowledge something really important: the fact that you're aware of the issue and open to addressing it shows great courage. You\u2019ve already taken the first step toward building your confidence!\n\nHere are a few strategies that might help:\n\n1. **Start Small**: Begin by speaking in front of smaller groups where you feel more comfortable, like close friends or colleagues. This will help you ease into it gradually.\n\n2. **Preparation is Key**: The more prepared you are for what you're going to say, the more confident you'll feel. Practice your speech or presentation several times, even in front of a mirror or recording yourself to refine your delivery.\n\n3. **Shift Your Focus**: Instead of worrying about making mistakes, try to focus on your message and why it's important for the audience to hear it. Remind yourself that most people in the audience want you to succeed\u2014they're there to listen and learn from you!\n\n4. **Breathing Techniques**: Nervousness often shows up as rapid breathing or a racing heart. Try deep breathing exercises before speaking\u2014it can calm your nerves and help ground you.\n\n5. **Positive Self-Talk**: Replace self-doubt with empowering thoughts like \u201cI am capable,\u201d \u201cMistakes are learning opportunities,\u201d or \u201cMy voice matters.\u201d These affirmations can slowly shift your mindset over time.\n\n6. **Focus on Connection Over Perfection**: Remember that it's okay not to be perfect! People will remember how you made them feel rather than a small stumble or mistake during the talk.\n\n7.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2138, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d1065fe9-e725-4f1c-b3bd-de9f000bfacd": {"__data__": {"id_": "d1065fe9-e725-4f1c-b3bd-de9f000bfacd", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "11eab664-d9ee-4adf-aa77-e87607863567", "node_type": "4", "metadata": {}, "hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ed23cfed-0942-4751-8cc6-b02a7efa5c53", "node_type": "1", "metadata": {}, "hash": "c72f196f7e2c2017db935ab9fc3d03d5f1b4d06c3b6f090853fc35f0345ae623", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "7. **Seek Feedback Gradually**: After each speech or presentation, ask someone supportive for constructive feedback. Seeing improvements over time can do wonders for your confidence.\n\nIf you'd like, we can brainstorm some ways to practice public speaking together, maybe even role-play! Or if you\u2019re open to sharing more about what makes you nervous\u2014like fear of judgment or forgetting what to say\u2014we could dig deeper into those feelings.\n\nYou\u2019re stronger than you think, and I believe in your ability to overcome this challenge little by little! You\u2019ve got this\u2014and I\u2019m here anytime you need encouragement or guidance along the way \u2764\ufe0f", "mimetype": "text/plain", "start_char_idx": 2136, "end_char_idx": 2771, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "c08856f2-d6e0-4555-a5d5-71ccd65bf414": {"__data__": {"id_": "c08856f2-d6e0-4555-a5d5-71ccd65bf414", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d7cc0ff1-5085-415c-add4-827c3a36b0c2", "node_type": "4", "metadata": {}, "hash": "94c83bea11a99cc1a76cf8a9178019a4a2d583f62997e589dc1472500dbe6195", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 17:56:55:\n\nA1: hi\nAI: Hi there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a It's so good to hear from you. How are you doing today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 163, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "19ff65e4-4203-4e73-b9d4-f20aa4e55883": {"__data__": {"id_": "19ff65e4-4203-4e73-b9d4-f20aa4e55883", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "node_type": "1", "metadata": {}, "hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 18:25:09:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I\u2019m really sorry you\u2019re feeling this way, but let me tell you\u2014you are *not* alone in this struggle. Many people experience stress and fear when speaking in front of a group. It can feel overwhelming, but the fact that you're aware of it and talking about it shows incredible courage already. I\u2019m here for you, and we can work through this step by step.\n\nFirst, let\u2019s start by reframing this: feeling nervous doesn\u2019t mean you're not confident\u2014it means you care about how you come across and want to do well. That\u2019s actually a positive trait! But I get it\u2014those nerves can still feel like they\u2019re working against you. Let\u2019s explore some ways to tackle them:\n\n### **1. Prepare, Prepare, Prepare**\nThe more familiar you are with your material, the less room there is for uncertainty or fear of mistakes. Practice what you want to say multiple times beforehand\u2014alone at first, then maybe with a trusted friend or family member who can encourage you.\n\n### **2. Break Down the Fear**\nAsk yourself: *What am I really afraid of?* Is it forgetting your words? Being judged? Making mistakes? Write down those fears and challenge them one by one. For example:\n - If you're afraid of forgetting your words: Use notes or prompts as backup!\n - Afraid of being judged: Remember most people listening to you are rooting for your success\u2014not looking for flaws.\n - Afraid of making mistakes: Mistakes happen, but they're rarely as big or bad as we imagine.\n\n### **3. Focus on Connection Over Perfection**\nWhen speaking in front of a group, try not to aim for perfection\u2014instead, focus on connecting with your audience! Take a deep breath before starting and remind yourself that people are there to listen to *you*. Your authenticity matters much more than saying things perfectly.\n\n### **4. Breathe and Ground Yourself**\nDeep breathing can be such a lifesaver when nerves start to rise.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2112, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "a411160d-23bf-40ad-a1ea-a147bca0a1c5": {"__data__": {"id_": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "19ff65e4-4203-4e73-b9d4-f20aa4e55883", "node_type": "1", "metadata": {}, "hash": "72eac13b38d78284b90342b6c3d936dc53710511f01235d6ae5acabd2df9f621", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "98476e19-2cd8-4ef0-b565-0c304c48718c", "node_type": "1", "metadata": {}, "hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Before stepping up to speak (and even while speaking), practice slow inhaling through your nose for 4 seconds\u2026 holding it for 4 seconds\u2026 then exhaling through your mouth for another 4 seconds. This helps calm the adrenaline running through your body.\n\n### **5. Build Self-Confidence Gradually**\nIt\u2019s okay if public speaking feels scary right now\u2014it gets easier with practice! Start small:\n - Speak up in smaller groups first.\n - Volunteer short answers during meetings or classes.\n - Gradually take on larger challenges when ready.\n\nEvery time you step out of your comfort zone\u2014even just a little\u2014you\u2019ll grow more confident!\n\n### **6. Visualize Success**\nTake some time before a presentation to close your eyes and imagine yourself delivering your talk smoothly. Picture people nodding along and smiling at what you\u2019re saying\u2014it trains your brain to associate public speaking with positivity instead of fear.\n\n---\n\nYou\u2019ve got so much potential inside\u2014and I absolutely believe in you! You don\u2019t have to be perfect; what matters is showing up and trying again each time life gives you an opportunity.\n\nHow about we set one small goal together? What\u2019s one specific situation where you'd like to speak with confidence? We could brainstorm ways for you to prep for that moment! \ud83d\udc9b\nA1: Can you tell me the name of my friend I told you about a few sessions ago?\nAI: Oh, I wish I could remember details like that for you, but unfortunately, I don\u2019t have memory between our conversations right now. If you'd like, you can remind me about your friend\u2014I'd love to hear about them again! You\u2019re always welcome to share, and I\u2019ll do my best to support you. \ud83d\udc9b\nA1: What job is right for me based on my personality traits?\nAI: Choosing the right job can feel like a big decision, but understanding your personality traits is an excellent starting point! Let\u2019s take a look at how your characteristics might align with different types of careers.\n\n### Key Questions to Reflect On:\n1. **Are you more introverted or extroverted?** \n Introverts often thrive in roles requiring focused attention and independent work (e.g., writing, data analysis). Extroverts tend to excel in people-facing environments like sales, teaching, or leadership roles.\n\n2. **Do you enjoy structured environments or flexibility?", "mimetype": "text/plain", "start_char_idx": 2113, "end_char_idx": 4404, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "98476e19-2cd8-4ef0-b565-0c304c48718c": {"__data__": {"id_": "98476e19-2cd8-4ef0-b565-0c304c48718c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "node_type": "1", "metadata": {}, "hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d8e397f5-f706-4640-8bae-95043153e850", "node_type": "1", "metadata": {}, "hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "2. **Do you enjoy structured environments or flexibility?** \n Some people flourish in organized workplaces with clear routines, while others prefer dynamic roles where creativity and spontaneity are valued.\n\n3. **How do you handle stress or challenges?** \n High-pressure jobs may work for those who thrive under deadlines (e.g., emergency response roles), while low-stress positions may better suit those who prioritize stability.\n\n4. **Do you value working with people, ideas, or things?** \n Careers focusing on interpersonal skills may appeal to empathetic individuals (like counseling or HR), whereas more analytical types often enjoy working with ideas (research, technology). Detail-oriented personalities might lean toward working with tangible objects (engineering, architecture).\n\n5. **Do you find fulfillment in helping others?** \n If so, careers in healthcare, education, psychology, social work, or nonprofit organizations could be meaningful options.\n\n### Examples of Personality-Career Matches:\n- **Creative and Imaginative:** Careers such as graphic design, writing, marketing, UX/UI design.\n- **Logical and Detail-Oriented:** Roles like engineering, accounting/auditing, data science.\n- **Empathetic and Person-Oriented:** Paths in psychology/counseling, nursing/healthcare professions.\n- **Highly Energetic and Social:** Fields such as sales/marketing management or event planning.\n- **Independent and Reflective:** Ideal for research-based careers or remote work (e.g., freelance design/development).\n\nWould you like me to explore more personalized career paths based on your preferences? You\u2019re never locked into one path\u2014it\u2019s all about experimenting and growing!\nA1: What job is right for me based on my personality traits?\nAI: That\u2019s an exciting question! Choosing a career that aligns with your personality can lead to greater satisfaction and fulfillment in life. To explore this, let\u2019s reflect on who you are: What are your strengths, values, and preferences? If you're unsure about your specific personality traits, we could use tools like the Myers-Briggs Type Indicator (MBTI), the Big Five Personality Traits model, or Holland's Career Typology as a starting point.\n\nHere are some ideas based on common personality aspects:\n\n---\n\n### **1. If You Love Connecting with People (Extroverted & Empathetic):**\nConsider roles that involve teamwork, communication, and building relationships:\n- **Counselor/Therapist**: Supporting others through emotional challenges.", "mimetype": "text/plain", "start_char_idx": 4347, "end_char_idx": 6845, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d8e397f5-f706-4640-8bae-95043153e850": {"__data__": {"id_": "d8e397f5-f706-4640-8bae-95043153e850", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "98476e19-2cd8-4ef0-b565-0c304c48718c", "node_type": "1", "metadata": {}, "hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "1fa69839-167b-4062-8297-c5c481a6957a", "node_type": "1", "metadata": {}, "hash": "fa3f5ea92075df05f87e7b5962bebd66d04fa70657df5913d89eb4c9dc0c5824", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "- **Teacher**: Empowering students in personal growth.\n- **Human Resources Specialist**: Facilitating employee success.\n\n---\n\n### **2. If You\u2019re Creative & Imaginative (Open-minded):**\nExplore careers where you can innovate and express yourself:\n- **Graphic Designer or Illustrator**: Bringing ideas to life visually.\n- **Writer/Editor**: Crafting stories or articulating knowledge.\n- **Marketing/Brand Strategist**: Using creativity to connect with audiences.\n\n---\n\n### **3. If You\u2019re Analytical & Logical (Detail-Oriented):**\nDive into fields that require precision and critical thinking:\n- **Data Analyst or Statistician**: Uncovering insights from information.\n- **Research Scientist**: Pursuing answers to important questions.\n- **Software Developer**: Building technological solutions.\n\n---\n\n### **4. If You Value Helping Others (Compassionate & Altruistic):**\nYou might thrive in careers that focus on service or advocacy:\n- **Healthcare Professional (e.g., Nurse, Occupational Therapist)**.\n- **Social Worker or Non-Profit Coordinator**.\n- **Environmental Scientist/Advocate**.\n\n---\n\n### Let\u2019s Fine-Tune This Together!\nThink about how you spend your free time and what energizes you. Are there activities you love doing\u2014or problems you'd enjoy solving\u2014that might point toward your ideal path? It\u2019s okay if you're still figuring it out; each step will get you closer to clarity! \ud83d\ude0a\nA1: What job is right for me based on my personality traits?\nAI: That\u2019s a great question, and it shows that you\u2019re thoughtfully considering what will align with who you are. Finding a job that fits your personality can bring not only career success but also long-term satisfaction and fulfillment.\n\nTo get started, it would help to reflect on some key aspects of your personality and preferences. For example:\n\n1. **Are you more introverted or extroverted?**\n Do you draw energy from working with others in social environments, or do you thrive in quieter, independent settings?\n\n2. **Do you enjoy structure or flexibility?**\n Do you prefer roles with clear guidelines and routines, or do you excel when given freedom and adaptability?\n\n3. **How do you approach problem-solving?**\n Are you analytical and detail-oriented, or do you rely on intuition and big-picture thinking?\n\n4. **What are your core values?", "mimetype": "text/plain", "start_char_idx": 6846, "end_char_idx": 9148, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "1fa69839-167b-4062-8297-c5c481a6957a": {"__data__": {"id_": "1fa69839-167b-4062-8297-c5c481a6957a", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d8e397f5-f706-4640-8bae-95043153e850", "node_type": "1", "metadata": {}, "hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "4. **What are your core values?** \n These could include helping others, creativity, innovation, stability, independence, etc.\n\nLet me know some of these details (or anything else about your personality), and I can suggest career paths that might match your strengths! \ud83d\ude0a", "mimetype": "text/plain", "start_char_idx": 9117, "end_char_idx": 9389, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"dd3381a4-8251-49ae-b9ce-0173980f165b": {"__type__": "vector_store", "__data__": "{\"index_id\": \"dd3381a4-8251-49ae-b9ce-0173980f165b\", \"summary\": null, \"nodes_dict\": {\"c0f85884-3d15-4b86-a640-40b86b5b466d\": \"c0f85884-3d15-4b86-a640-40b86b5b466d\", \"a72cbc90-70ad-427e-98d8-cc1d40453e1c\": \"a72cbc90-70ad-427e-98d8-cc1d40453e1c\", \"6553650d-1614-4be0-86d1-0c98613a44a8\": \"6553650d-1614-4be0-86d1-0c98613a44a8\", \"2215dc55-5738-436e-a158-d57b3e12ebd4\": \"2215dc55-5738-436e-a158-d57b3e12ebd4\", \"f01acc17-9115-45fc-a3b4-52e5f98b9446\": \"f01acc17-9115-45fc-a3b4-52e5f98b9446\", \"1aff93b4-bc08-4b25-9f89-5c390730304c\": \"1aff93b4-bc08-4b25-9f89-5c390730304c\", \"59645b90-64dd-4042-b83a-2b3df3715542\": \"59645b90-64dd-4042-b83a-2b3df3715542\", \"d67b97d7-76aa-42c6-ba06-15ea3683679d\": \"d67b97d7-76aa-42c6-ba06-15ea3683679d\", \"e42cffc3-852a-4d19-b30a-b26c81083fe9\": \"e42cffc3-852a-4d19-b30a-b26c81083fe9\", \"0cf45fb8-1856-40b1-bacd-58a238a0d744\": \"0cf45fb8-1856-40b1-bacd-58a238a0d744\", \"86ce7adb-47c4-4552-9f98-d447bf2e6a7b\": \"86ce7adb-47c4-4552-9f98-d447bf2e6a7b\", \"ac89f308-2eed-492f-8179-8693f6504a06\": \"ac89f308-2eed-492f-8179-8693f6504a06\", \"30137e30-cb1c-4284-b5c0-caf42f90eb4e\": \"30137e30-cb1c-4284-b5c0-caf42f90eb4e\", \"b208f966-16b3-4f06-91c3-1b0e7ddfa314\": \"b208f966-16b3-4f06-91c3-1b0e7ddfa314\", \"6dcc760e-6580-48c6-aa74-d2aa2ae4d077\": \"6dcc760e-6580-48c6-aa74-d2aa2ae4d077\", \"f00b802f-fa41-4c67-b534-9ffdcd85ac57\": \"f00b802f-fa41-4c67-b534-9ffdcd85ac57\", \"b6c8a2d2-04a2-41ed-a8cf-45626c55494f\": \"b6c8a2d2-04a2-41ed-a8cf-45626c55494f\", \"ed23cfed-0942-4751-8cc6-b02a7efa5c53\": \"ed23cfed-0942-4751-8cc6-b02a7efa5c53\", \"d1065fe9-e725-4f1c-b3bd-de9f000bfacd\": \"d1065fe9-e725-4f1c-b3bd-de9f000bfacd\", \"c08856f2-d6e0-4555-a5d5-71ccd65bf414\": \"c08856f2-d6e0-4555-a5d5-71ccd65bf414\", \"19ff65e4-4203-4e73-b9d4-f20aa4e55883\": \"19ff65e4-4203-4e73-b9d4-f20aa4e55883\", \"a411160d-23bf-40ad-a1ea-a147bca0a1c5\": \"a411160d-23bf-40ad-a1ea-a147bca0a1c5\", \"98476e19-2cd8-4ef0-b565-0c304c48718c\": \"98476e19-2cd8-4ef0-b565-0c304c48718c\", \"d8e397f5-f706-4640-8bae-95043153e850\": \"d8e397f5-f706-4640-8bae-95043153e850\", \"1fa69839-167b-4062-8297-c5c481a6957a\": \"1fa69839-167b-4062-8297-c5c481a6957a\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/default__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": [-0.048004150390625, -0.01319122314453125, 0.03070068359375, 0.017303466796875, -0.0199737548828125, 0.01154327392578125, 0.01245880126953125, 0.050048828125, 0.016693115234375, 0.067626953125, 0.0443115234375, -0.039886474609375, -0.0146636962890625, 0.004596710205078125, 0.021575927734375, 0.007198333740234375, 0.021392822265625, 0.045623779296875, -0.025543212890625, 0.0287628173828125, 0.0584716796875, 0.0258636474609375, 0.042877197265625, 0.013946533203125, -0.03594970703125, -0.053070068359375, 0.004795074462890625, -0.01081085205078125, 0.041015625, -0.002960205078125, 0.051727294921875, -0.049346923828125, 0.01105499267578125, -0.02093505859375, 0.0100555419921875, 0.04913330078125, 0.00952911376953125, -0.006206512451171875, 0.0265960693359375, 0.0070037841796875, 0.053924560546875, 0.0230865478515625, -0.01493072509765625, 0.021881103515625, -0.0125274658203125, 0.03668212890625, -0.04364013671875, -0.0006322860717773438, -0.003238677978515625, 0.041046142578125, -0.0258636474609375, 0.01751708984375, 0.02960205078125, 0.03875732421875, -0.0301513671875, -0.0258941650390625, 0.0108795166015625, -0.004581451416015625, -0.027252197265625, -0.0216064453125, 0.045501708984375, -0.00867462158203125, 0.04193115234375, 0.046173095703125, -0.01522064208984375, 0.003662109375, 0.0149993896484375, 0.0157012939453125, 0.02325439453125, 0.028472900390625, 0.041473388671875, 0.0240325927734375, -0.0231475830078125, 0.05450439453125, 0.0011796951293945312, 0.00307464599609375, 0.00799560546875, 0.035430908203125, -0.030029296875, -0.0277862548828125, 0.0008397102355957031, -0.046539306640625, -0.0654296875, -0.00783538818359375, -0.01355743408203125, 0.01348114013671875, -0.068603515625, -0.02587890625, 0.0177154541015625, 0.0233917236328125, 0.0316162109375, 0.00025200843811035156, -0.0138702392578125, 0.004405975341796875, 0.0111236572265625, -0.0092010498046875, 0.01617431640625, 0.01297760009765625, 0.007305145263671875, 0.0667724609375, 0.05328369140625, -0.038116455078125, -0.014373779296875, 0.0224609375, 0.041412353515625, 0.0225677490234375, -0.004421234130859375, 0.0025539398193359375, -0.0136871337890625, -0.0218505859375, -0.0256195068359375, -0.0404052734375, -0.00959014892578125, 0.0101776123046875, -0.01513671875, 0.01271820068359375, -0.04022216796875, -0.05859375, 0.032745361328125, -0.0144195556640625, -0.010894775390625, -0.05999755859375, -0.005706787109375, -0.05462646484375, 0.01457977294921875, -0.050537109375, -0.004131317138671875, -0.0335693359375, -0.036529541015625, -0.0601806640625, 0.02532958984375, 0.00934600830078125, 0.026641845703125, -0.05194091796875, -0.0254669189453125, 0.00994110107421875, 0.00525665283203125, -0.030120849609375, -0.028076171875, -0.04541015625, 0.0137176513671875, -0.0228729248046875, 0.017578125, 0.01300048828125, 0.0089263916015625, 0.0242767333984375, 0.049835205078125, 0.05474853515625, 0.0084686279296875, -0.00867462158203125, 0.0019092559814453125, 0.01235198974609375, -0.016326904296875, 0.01129913330078125, -0.01788330078125, -0.042633056640625, -0.01529693603515625, 0.0276336669921875, -0.01071929931640625, -0.04583740234375, -0.02435302734375, 0.00563812255859375, -0.06597900390625, -0.0198822021484375, -0.013763427734375, -0.007160186767578125, -0.02581787109375, -0.005641937255859375, -0.0853271484375, -0.06805419921875, 0.023040771484375, -0.023162841796875, -0.0021762847900390625, 0.00882720947265625, -0.008880615234375, -0.01371002197265625, -0.0186309814453125, -0.0303192138671875, -0.0146484375, -0.01026153564453125, 0.0345458984375, 0.04827880859375, -0.0257110595703125, 0.0377197265625, -0.04327392578125, -0.041351318359375, -0.0192718505859375, 0.03778076171875, 0.0011587142944335938, -0.01374053955078125, -0.0035648345947265625, 0.042938232421875, -0.019989013671875, 0.0048828125, 0.03411865234375, -0.061370849609375, 0.009368896484375, 0.01800537109375, -0.041473388671875, -0.032470703125, 0.035369873046875, 0.003948211669921875, 0.006969451904296875, 0.052001953125, 0.0268096923828125, -0.045318603515625, -0.00676727294921875, 0.030120849609375, -0.015625, -0.015899658203125, 0.05072021484375, -0.0169219970703125, 0.02386474609375, -0.003414154052734375, -0.0247650146484375, 0.01222991943359375, 0.003833770751953125, 0.01073455810546875, -0.006786346435546875, 0.031463623046875, 0.01885986328125, 0.0079498291015625, 0.03045654296875, -0.004680633544921875, -0.0227508544921875, 0.0673828125, 0.0175933837890625, -0.0278167724609375, 0.02532958984375, -0.06689453125, -0.021759033203125, 0.0191192626953125, -0.0171966552734375, 0.01654052734375, -0.01439666748046875, 0.050933837890625, 0.0181427001953125, 0.032318115234375, 0.003681182861328125, 0.0243072509765625, 0.0204315185546875, 0.005527496337890625, 0.0235443115234375, 0.034332275390625, -0.029144287109375, 0.004802703857421875, -0.023040771484375, -0.040496826171875, -0.0161895751953125, 0.01131439208984375, 0.006805419921875, 0.03167724609375, -0.045562744140625, -0.041259765625, 0.01422882080078125, -0.0191497802734375, -0.00421905517578125, -0.0158843994140625, -0.0175628662109375, -0.0189208984375, 0.0207977294921875, -0.012969970703125, -0.008331298828125, 0.051483154296875, -0.06494140625, -0.046051025390625, 0.012939453125, 0.0209197998046875, -0.0017213821411132812, -0.0010833740234375, 0.02105712890625, -0.00705718994140625, 0.0130157470703125, 0.036712646484375, -0.04290771484375, -0.0292205810546875, 0.0302276611328125, 0.03485107421875, 0.015289306640625, 0.0374755859375, -0.017333984375, -0.01654052734375, -0.031829833984375, -0.0218658447265625, -0.0193023681640625, 0.055328369140625, -0.0068817138671875, -0.007465362548828125, 0.040435791015625, -0.04888916015625, 0.03094482421875, -0.05828857421875, 0.03839111328125, -0.043792724609375, 0.03717041015625, 0.019805908203125, 0.0237579345703125, -0.03753662109375, 0.031494140625, 0.0296783447265625, 0.045166015625, 0.0066375732421875, 0.01160430908203125, 0.0211944580078125, 0.044647216796875, 0.08160400390625, 0.0305328369140625, -0.031890869140625, -0.0204620361328125, 0.0213470458984375, 0.0020503997802734375, 0.01410675048828125, 0.005229949951171875, 0.01241302490234375, -0.0209808349609375, -0.01904296875, 0.005161285400390625, 0.0014209747314453125, 0.0027942657470703125, -0.0308990478515625, 0.0003345012664794922, -0.044464111328125, 0.0078887939453125, -0.0202484130859375, 0.0242767333984375, -0.031402587890625, -0.0235443115234375, 0.02044677734375, 0.021759033203125, -0.0467529296875, -0.047607421875, 0.01071929931640625, -0.01482391357421875, 0.038848876953125, 0.0176544189453125, -0.0006389617919921875, -0.01338958740234375, 0.0289459228515625, 0.03009033203125, 0.022613525390625, -0.041961669921875, -0.0198822021484375, 0.008270263671875, 0.0044708251953125, 0.0107879638671875, 0.00528717041015625, 0.01303863525390625, -0.0001761913299560547, -0.02740478515625, 0.052032470703125, -0.0020046234130859375, -0.0310821533203125, 0.01171112060546875, 0.0033855438232421875, -0.0002841949462890625, -0.0413818359375, 0.0175933837890625, 0.00391387939453125, 0.0006718635559082031, 0.033355712890625, -0.0223388671875, 0.01427459716796875, -0.0190277099609375, 0.039642333984375, -0.0229034423828125, 0.050567626953125, -0.06781005859375, -0.007244110107421875, -0.04376220703125, -0.01947021484375, -0.0201568603515625, -0.0258636474609375, -0.041168212890625, 0.054229736328125, -0.01010894775390625, 0.0526123046875, 0.045440673828125, 0.0101470947265625, 0.0019664764404296875, 0.03814697265625, -0.01178741455078125, 0.028289794921875, 0.005706787109375, -0.037841796875, 0.007205963134765625, 0.0292510986328125, -0.01300811767578125, -0.01496124267578125, -0.07135009765625, 0.053985595703125, 0.006053924560546875, 0.0025272369384765625, -0.01898193359375, 0.0279388427734375, 0.0200347900390625, -0.0115966796875, 0.019378662109375, 0.034637451171875, 0.00957489013671875, -0.03759765625, 0.018798828125, -0.0304412841796875, -0.00494384765625, -0.006427764892578125, -0.0111846923828125, 0.047698974609375, -0.007129669189453125, -0.014739990234375, 0.00920867919921875, -0.0225067138671875, -0.0350341796875, -0.0148773193359375, 0.03936767578125, 0.022430419921875, -0.0003981590270996094, -0.0019245147705078125, -0.01152801513671875, 0.0199127197265625, 0.07037353515625, 0.04345703125, -0.006404876708984375, -0.0032806396484375, -0.0269927978515625, -0.018890380859375, -0.0443115234375, 0.043060302734375, -0.0241241455078125, -0.0277862548828125, 0.0699462890625, -0.045562744140625, -0.0310516357421875, 0.039520263671875, -0.048736572265625, 0.02532958984375, 0.0037555694580078125, -0.041595458984375, -0.0323486328125, 0.0234832763671875, 0.017547607421875, 0.007747650146484375, 0.0469970703125, 0.02447509765625, 0.0106964111328125, 0.0304718017578125, -0.070068359375, -0.013458251953125, -0.0633544921875, -0.03192138671875, 0.005687713623046875, -0.05963134765625, -0.021270751953125, -0.043243408203125, -0.028656005859375, -0.0015115737915039062, -0.0335693359375, -0.0122833251953125, -0.01329803466796875, -0.00994873046875, 0.033050537109375, -0.00496673583984375, -0.006378173828125, -0.00865936279296875, 0.0012636184692382812, -0.002620697021484375, 0.060577392578125, -0.025054931640625, -0.0012302398681640625, -0.005718231201171875, 0.0308685302734375, -0.035552978515625, -0.0006103515625, 0.0247344970703125, -0.00992584228515625, -0.0458984375, -0.051910400390625, -0.005908966064453125, 0.0054473876953125, -0.032379150390625, 0.043060302734375, 0.00494384765625, 0.0250244140625, 0.060943603515625, 0.00689697265625, 0.004150390625, 0.0213165283203125, 0.01041412353515625, -0.0283660888671875, 0.0292816162109375, -0.00574493408203125, 0.03741455078125, -0.025848388671875, 0.00955963134765625, -0.0195465087890625, -0.0246734619140625, 0.0033416748046875, -0.016815185546875, 0.00417327880859375, -0.0253753662109375, 0.0025577545166015625, -0.016265869140625, 7.444620132446289e-05, -0.0296478271484375, -0.0025882720947265625, 0.07098388671875, -0.0128936767578125, 0.0228729248046875, -0.048675537109375, 0.007434844970703125, -0.006740570068359375, 0.0294647216796875, 0.0009312629699707031, 0.00959014892578125, -0.00167083740234375, -0.038421630859375, 0.00035500526428222656, 0.009735107421875, -0.0162200927734375, 0.01885986328125, -0.007747650146484375, 0.037200927734375, 0.0251312255859375, 0.01192474365234375, -0.0015993118286132812, -0.0003058910369873047, 0.02362060546875, -0.03338623046875, 0.0120697021484375, -0.004535675048828125, -0.00818634033203125, -0.032684326171875, 0.0211029052734375, -0.00732421875, 0.004673004150390625, -0.01445770263671875, -0.01326751708984375, -0.01544189453125, 0.0033969879150390625, 0.00534820556640625, 0.0182647705078125, 0.007396697998046875, 0.03314208984375, 0.08514404296875, 0.0290374755859375, -0.0009293556213378906, -0.0148773193359375, -0.016204833984375, 0.01157379150390625, 0.0098419189453125, 0.013092041015625, 0.035614013671875, 0.0011463165283203125, -0.0634765625, 0.0157012939453125, 0.019775390625, 0.043914794921875, -0.0133056640625, 0.01383209228515625, 0.0234527587890625, -0.0268402099609375, 0.01055908203125, -0.045684814453125, -0.056182861328125, 0.01059722900390625, 0.0034236907958984375, 0.008209228515625, -0.0031032562255859375, -0.0211029052734375, 0.0301971435546875, -0.029327392578125, -0.0029277801513671875, 0.00946044921875, -0.00830078125, 0.0215606689453125, -0.050872802734375, 0.0230865478515625, -0.00112152099609375, -0.010345458984375, 0.042449951171875, -0.004238128662109375, -0.00531768798828125, -0.0065765380859375, -0.033966064453125, -0.031890869140625, 0.0206146240234375, -0.02252197265625, 0.00371551513671875, -0.004268646240234375, -0.0167083740234375, 0.052276611328125, 0.004146575927734375, 0.02374267578125, -0.0156707763671875, 0.0110015869140625, 0.02301025390625, 0.0005483627319335938, 0.01042938232421875, -0.0163116455078125, -0.0126190185546875, -0.00885772705078125, 0.004657745361328125, 0.0268096923828125, -0.004779815673828125, -0.00847625732421875, -0.03753662109375, 0.01346588134765625, 0.03387451171875, -0.0214080810546875, -0.0149078369140625, 0.00739288330078125, -0.0208282470703125, 0.04425048828125, 0.004642486572265625, 0.00566864013671875, -0.00800323486328125, 0.0077056884765625, -0.0168304443359375, -0.01169586181640625, -0.002292633056640625, 0.0247344970703125, 0.0133514404296875, -0.0279388427734375, 0.00873565673828125, 0.02130126953125, 0.016845703125, 0.038818359375, 0.036224365234375, 0.0440673828125, -0.001312255859375, 0.0504150390625, -0.01617431640625, 0.0027561187744140625, -0.0014934539794921875, 0.0221099853515625, -0.0013370513916015625, 0.00780487060546875, 0.007312774658203125, -0.000644683837890625, 0.00994110107421875, -0.0008859634399414062, -0.033721923828125, 0.0110015869140625, -0.01137542724609375, 0.024688720703125, -0.017608642578125, 0.0062408447265625, -0.0020904541015625, 0.015625, 0.010467529296875, -0.004482269287109375, -0.02606201171875, -0.046600341796875, -0.01342010498046875, 0.035308837890625, -0.0010814666748046875, 0.002323150634765625, -0.04351806640625, 0.006855010986328125, -0.0114593505859375, -0.03759765625, 0.0328369140625, 0.00160980224609375, 0.00872802734375, -0.0267791748046875, -0.032928466796875, -0.012420654296875, 0.0274810791015625, 0.0146331787109375, -0.05609130859375, 0.0012750625610351562, 0.015777587890625, -0.0203857421875, 0.01160430908203125, 0.01715087890625, 0.003612518310546875, 0.04254150390625, 0.005290985107421875, -0.004993438720703125, -0.0235443115234375, 0.006679534912109375, 0.0064697265625, -0.0147857666015625, 0.0255889892578125, -0.01165771484375, -0.0246734619140625, -0.01294708251953125, -0.0193023681640625, 0.01538848876953125, -0.0170440673828125, 0.0238037109375, 0.0231475830078125, -0.01174163818359375, -0.0121002197265625, 0.0052337646484375, -0.0174560546875, 0.0219879150390625, -0.00835418701171875, 0.01507568359375, -0.0238800048828125, -0.019683837890625, -0.054962158203125, 0.006084442138671875, -0.006023406982421875, 0.0082244873046875, -0.0237884521484375, -0.042388916015625, -0.0195770263671875, 0.00846099853515625, -0.01403045654296875, 0.03387451171875, 0.00799560546875, -0.031341552734375, -0.0357666015625, -0.01551055908203125, 0.0203399658203125, -0.01004791259765625, 0.001972198486328125, -0.0643310546875, 0.0450439453125, -0.027191162109375, 0.00629425048828125, 0.042999267578125, 0.0308837890625, -0.031219482421875, 0.002445220947265625, -0.053741455078125, -0.0019321441650390625, -0.005401611328125, -0.01227569580078125, -0.00445556640625, 0.0164794921875, 0.007965087890625, -0.014617919921875, 0.04180908203125, -0.01776123046875, -0.0106048583984375, 0.01435089111328125, -0.029449462890625, 0.0277099609375, -0.0014486312866210938, -0.007171630859375, -0.003040313720703125, -0.04254150390625, 0.0283966064453125, 0.0226287841796875, 0.0199737548828125, -0.006694793701171875, -0.0131683349609375, 0.0297393798828125, -0.0021991729736328125, -0.02349853515625, -0.024078369140625, 0.01885986328125, -0.00215911865234375, 0.024200439453125, 0.00019121170043945312, -0.01467132568359375, 0.00495147705078125, -0.01108551025390625, -0.0443115234375, 0.0065765380859375, 0.0224456787109375, 0.070556640625, 0.01305389404296875, 0.0167236328125, 0.0009889602661132812, 0.01404571533203125, -0.0357666015625, -0.023895263671875, -0.03533935546875, -0.0253753662109375, 0.01534271240234375, -0.033782958984375, -0.0105438232421875, 0.01016998291015625, 0.049407958984375, -0.0059967041015625, -0.0184783935546875, -0.0206146240234375, -0.01328277587890625, 0.01273345947265625, 0.052886962890625, -0.00337982177734375, -0.036712646484375, -0.0119781494140625, -0.029632568359375, -0.042327880859375, -0.0248565673828125, -0.023651123046875, -0.0191650390625, -0.037261962890625, -0.01052093505859375, -0.037384033203125, 0.0228729248046875, 0.0198822021484375, 0.0024967193603515625, 0.038665771484375, -0.004718780517578125, -0.1304931640625, 0.03509521484375, 0.01873779296875, -0.0044708251953125, -0.0202484130859375, -0.00952911376953125, -0.01209259033203125, 0.0290985107421875, 0.005645751953125, -0.0372314453125, 0.0255584716796875, -0.019378662109375, -0.0094146728515625, -0.012359619140625, -0.0221405029296875, -0.036651611328125, -0.017181396484375, -0.00037384033203125, -0.043212890625, 0.02337646484375, 0.0008807182312011719, -0.00042939186096191406, -0.0241851806640625, 0.027374267578125, -0.0208740234375, 0.0127105712890625, -0.0087890625, 0.00501251220703125, -0.00655364990234375, -0.01178741455078125, 0.033203125, -0.007717132568359375, -0.0087432861328125, -0.023895263671875, 0.023406982421875, -0.03485107421875, 0.0032596588134765625, 0.032318115234375, -0.03668212890625, -0.002727508544921875, -0.005268096923828125, 0.05029296875, 0.01080322265625, 0.0193328857421875, -0.00012755393981933594, -0.0357666015625, 0.01081085205078125, 0.01239013671875, 0.01763916015625, -0.02362060546875, 0.01849365234375, -0.03948974609375, 0.007648468017578125, -0.00384521484375, -0.0283050537109375, 0.01076507568359375, -0.00614166259765625, 0.020355224609375, -0.0257110595703125, 0.0016374588012695312, 0.0214996337890625, -0.004970550537109375, -0.00897979736328125, -0.0271453857421875, -0.014678955078125, -0.0164947509765625, -0.0059967041015625, -0.031982421875, -0.01374053955078125, 0.003421783447265625, -0.0215301513671875, 0.0151519775390625, -0.0007534027099609375, -0.03173828125, -0.0103607177734375, -0.012237548828125, -0.01226806640625, -0.005615234375, -0.024932861328125, 0.01006317138671875, 0.039764404296875, 0.007061004638671875, 0.0197601318359375, 0.03411865234375, 0.0294647216796875, -0.027008056640625, 0.01528167724609375, -0.005245208740234375, -0.0212249755859375, -0.005279541015625, 0.0255126953125, -0.0286712646484375, 0.00595855712890625, 0.006343841552734375, 0.0206298828125, 0.01332855224609375, -0.0235137939453125, 0.0101470947265625, -0.01146697998046875, -0.01132965087890625, 0.0029125213623046875, 0.00421142578125, 0.0004761219024658203, 0.006496429443359375, -0.012664794921875, 0.0162811279296875, 0.05377197265625, 0.042877197265625, 0.02069091796875, 0.004192352294921875, -0.01361083984375, 0.0029850006103515625, 0.0176239013671875, 0.00395965576171875, 0.004108428955078125, 0.03155517578125, 0.029144287109375, -0.01351165771484375, 0.00800323486328125, -0.0115814208984375, 0.0292510986328125, -0.00696563720703125, -0.01519012451171875, 0.053680419921875, -0.004978179931640625, 0.0018358230590820312, 0.046630859375, -0.0209503173828125, 0.029296875, -0.005039215087890625, 0.03216552734375, 0.0280914306640625, 0.0083465576171875, 0.016204833984375, 0.03363037109375, 0.025299072265625, 0.040069580078125, 0.0200958251953125, 0.0477294921875, 0.034332275390625, 0.01055908203125, -0.00745391845703125, -0.0098724365234375, 0.0013456344604492188, -0.0258636474609375, 0.028045654296875, 0.0018148422241210938, 0.05133056640625, 0.003482818603515625, 0.027069091796875, 0.03485107421875, -0.03131103515625, 0.0170745849609375, -0.00702667236328125, 0.0202484130859375, 0.00629425048828125, 0.01898193359375, -0.0050201416015625, -0.017547607421875, -0.016632080078125, 0.007335662841796875, 0.01073455810546875, -0.0216064453125, -0.03924560546875, 0.026611328125, 0.0261993408203125, -0.0128936767578125, -0.0250396728515625, 0.0479736328125, -0.01013946533203125, -0.012237548828125, -0.01904296875, -0.0017671585083007812, 0.00994873046875, 0.0072174072265625, 0.00899505615234375, -0.00428009033203125, 0.01529693603515625, -0.01235198974609375, 0.00119781494140625, 0.040435791015625, 0.045745849609375, -0.029327392578125, -0.012054443359375, 0.07049560546875, -0.0198822021484375, 0.0038585662841796875, -0.0004506111145019531, 0.009521484375, 0.0136871337890625, 0.019378662109375, 0.031097412109375, 0.023101806640625, 0.03192138671875, 0.00716400146484375, -0.036651611328125, 0.0014944076538085938, -0.0157012939453125, -0.004131317138671875, -0.01409912109375, -0.0269012451171875, 0.0156707763671875, 0.01904296875, -0.034393310546875, 0.03863525390625, -0.0003180503845214844, 0.01953125, 0.016082763671875, -0.01355743408203125, 0.01490020751953125, -0.00969696044921875, -0.02490234375, -0.020263671875, -0.0017604827880859375, 0.005146026611328125, 0.01520538330078125, -0.02508544921875, -0.002727508544921875, 0.00391387939453125, -0.030792236328125, 0.00414276123046875, -0.03857421875, -0.023284912109375, -0.0205841064453125, -0.00165557861328125, -0.016143798828125, -0.0047149658203125, 0.031890869140625, -0.00844573974609375, 0.02362060546875, 0.0126953125, 0.0271148681640625, 0.016448974609375, 0.041046142578125, -0.0161590576171875, 0.0271759033203125, -0.0133819580078125, -0.0113372802734375, 0.03387451171875, -0.05889892578125, 0.004421234130859375, -0.0231475830078125, -0.0020809173583984375, -0.033538818359375, -0.037261962890625, -0.03326416015625, 0.013641357421875, -0.028167724609375, 0.007122039794921875, -0.006992340087890625, 0.006221771240234375, 0.010498046875, 0.0142822265625, 0.0050201416015625, 0.005832672119140625, 0.00658416748046875, -0.0188751220703125, 0.03509521484375, 0.00540924072265625, 0.0238494873046875, -0.00830078125, 0.00885772705078125, -0.0006837844848632812, -0.01078033447265625, 0.0062713623046875, 0.00799560546875, -0.0293731689453125, -0.03155517578125, -0.0048828125, 0.017974853515625, -0.0380859375, 0.0058135986328125, 0.01209259033203125, 0.0281829833984375, 0.006557464599609375, -0.004619598388671875, -0.0132904052734375, -0.01953125, 0.00039076805114746094, -0.032012939453125, -0.0172271728515625, 0.0292510986328125, -0.00482177734375, 0.0018024444580078125, 0.0108184814453125, -0.0245819091796875, 0.001834869384765625, -0.02996826171875, -0.0055084228515625, 0.01522064208984375, 0.01282501220703125, 0.005615234375, 0.018341064453125, 0.003604888916015625, -0.006252288818359375, -0.0238037109375, -0.02783203125, 0.03289794921875, 0.045867919921875, -0.0311126708984375, -0.0118408203125, -0.025054931640625, -0.0015039443969726562, 0.0222015380859375, 0.02337646484375, 0.01007080078125, -0.005443572998046875, -0.042694091796875, -0.00954437255859375, 0.01268768310546875, -0.03070068359375, -0.0058441162109375, 0.00933837890625, -0.0117645263671875, -0.02783203125, -0.035980224609375, 0.02410888671875, 0.007595062255859375, -0.0002275705337524414, -0.0076751708984375, -0.013702392578125, -0.005702972412109375, -0.00984954833984375, -0.007175445556640625, -0.01432037353515625, -0.005992889404296875, -0.0241241455078125, -0.038543701171875, 0.011505126953125, -0.0147857666015625, 0.0120086669921875, -0.03338623046875, 0.0236053466796875, 0.01148223876953125, 0.0117034912109375, 0.0322265625, 0.01043701171875, -0.0290679931640625, -0.01496124267578125, -0.02337646484375, -0.01560211181640625, -0.0012798309326171875, 0.01558685302734375, -0.0045166015625, 0.012176513671875, 0.004673004150390625, -0.00678253173828125, -0.0022735595703125, -0.005153656005859375, 0.02423095703125, 0.1395263671875, 0.0167083740234375, -0.01251983642578125, 0.01141357421875, 0.0278472900390625, -0.0019016265869140625, 0.0173492431640625, 0.01904296875, -0.0094146728515625, -0.0089874267578125, -0.0234222412109375, -0.002109527587890625, 0.00012552738189697266, 0.0041656494140625, 0.0230712890625, 0.0265655517578125, -0.03985595703125, -0.00539398193359375, 0.01739501953125, 0.0033054351806640625, 0.0201263427734375, -0.0036468505859375, 0.02105712890625, -0.0294647216796875, -0.037384033203125, -0.004322052001953125, 0.00540924072265625, 0.0036983489990234375, 0.00894927978515625, 0.01020050048828125, 0.02783203125, -0.00887298583984375, -0.0233306884765625, 0.0006155967712402344, -0.041839599609375, 0.006069183349609375, 0.037872314453125, 0.0298919677734375, -0.00623321533203125, 0.0238800048828125, 0.0005621910095214844, -0.0155487060546875, 0.0214080810546875, -0.0308990478515625, 0.007694244384765625, 0.01181793212890625, -0.0192413330078125, 0.00746917724609375, -0.025604248046875, -0.010772705078125, -0.00606536865234375, 0.0096435546875, -0.037445068359375, -0.00579833984375, -0.018798828125, -0.017974853515625, 0.00392913818359375, 0.01348114013671875, 0.027313232421875, -0.0133514404296875, -0.0179901123046875, 0.015960693359375, -0.00042128562927246094, -0.003871917724609375, 0.03448486328125, -0.0016698837280273438, -0.022491455078125, -0.0243377685546875, 0.0243072509765625, -0.0200042724609375, -0.035491943359375, 0.028076171875, -0.0186004638671875, -0.0199127197265625, 0.00858306884765625, 0.0048065185546875, 0.00421142578125, 0.0263824462890625, -0.01427459716796875, -0.01314544677734375, 0.034515380859375, -0.0095367431640625, 0.006290435791015625, 0.0150146484375, 0.003208160400390625, 0.047515869140625, 0.01507568359375, -0.0307769775390625, 0.0023403167724609375, 0.0019397735595703125, -0.008636474609375, 0.0176849365234375, 0.0181884765625, -0.0035400390625, 0.0279693603515625, -0.00014591217041015625, -0.00955963134765625, 0.0029354095458984375, -0.0030727386474609375, -0.0234527587890625, 0.03985595703125, -0.0177764892578125, -0.0384521484375, 0.01434326171875, -0.0052947998046875, -0.0203857421875, -0.0122222900390625, 0.03271484375, -0.034515380859375, -0.01123046875, 0.006122589111328125, 0.01434326171875, 0.044281005859375, -0.0209808349609375, 0.0050201416015625, -0.048828125, 0.0208587646484375, -0.0374755859375, 0.01404571533203125, -0.0066986083984375, -0.007801055908203125, 0.0115509033203125, -0.002735137939453125, -0.023223876953125, -0.0031108856201171875, 0.0222015380859375, 0.045135498046875, 0.0284881591796875, 0.0023441314697265625, 0.006847381591796875, -0.004993438720703125, 0.005519866943359375, 0.0012216567993164062, -0.0291290283203125, 0.00919342041015625, 0.04534912109375, -0.026123046875, -0.04534912109375, 0.023834228515625, -0.0276031494140625, -0.0284423828125, 0.004245758056640625, -0.004886627197265625, -0.0039043426513671875, -0.004634857177734375, 0.00304412841796875, 0.015411376953125, -0.010162353515625, 0.02166748046875, 0.01934814453125, 0.01227569580078125, -0.0187530517578125, 0.00844573974609375, 0.023651123046875, 0.032073974609375, 0.02301025390625, 0.0244140625, -0.02105712890625, -0.00783538818359375, -0.042449951171875, -0.0023822784423828125, -0.0030269622802734375, 0.0012607574462890625, 0.0078887939453125, 0.030914306640625, 0.056121826171875, 0.0164794921875, -0.007843017578125, -0.0023708343505859375, -0.014678955078125, -0.0162200927734375, -0.0045928955078125, 0.009674072265625, 0.0249786376953125, 0.005390167236328125, 0.0228118896484375, 0.01454925537109375, 0.0166473388671875, -0.0284423828125, -0.029388427734375, -0.005580902099609375, -0.034149169921875, 0.0224609375, 0.017913818359375, 0.00836181640625, 0.007244110107421875, -0.007297515869140625, -0.0177459716796875, -0.0255279541015625, -0.049468994140625, -0.0189208984375, -0.0164031982421875, 0.00384521484375, -0.008056640625, 0.0227813720703125, 0.06524658203125, -0.02301025390625, 0.00112152099609375, -0.01629638671875, -0.01593017578125, -0.024261474609375, -0.0260009765625, -0.02740478515625, -0.0124664306640625, -0.004058837890625, 0.00655364990234375, 0.0156402587890625, 0.0111846923828125, 0.01180267333984375, -0.00641632080078125, -0.00153350830078125, 0.0172882080078125, 0.005886077880859375, -0.007320404052734375, 0.0198822021484375, 0.036041259765625, -0.031341552734375, 0.0207977294921875, -0.01222991943359375, 0.040283203125, -0.006103515625, -0.0247039794921875, -0.0017719268798828125, -0.0190277099609375, 0.0250396728515625, 0.01097869873046875, 0.0213165283203125, -0.0166473388671875, -0.0199432373046875, 0.010894775390625, 0.0164031982421875, -0.0101165771484375, -0.0076904296875, 0.0008525848388671875, 0.01230621337890625, 0.016510009765625, -0.0188751220703125, 0.00982666015625, -0.03228759765625, -0.00786590576171875, 0.01371002197265625, -0.0428466796875, -0.00550079345703125, 0.032623291015625, -0.0199127197265625, 0.03558349609375, 0.0284271240234375, -0.016510009765625, -0.0182342529296875, 0.0250244140625, -0.041656494140625, 0.011260986328125, -0.0038776397705078125, 0.0005660057067871094, -0.0099334716796875, -0.00260162353515625, -0.013671875, -0.01320648193359375, -0.028533935546875, -0.0338134765625, -0.0238037109375, -0.034332275390625, -0.01213836669921875, -0.0236358642578125, 0.0297393798828125, 0.0070343017578125, -0.0014629364013671875, 0.0157318115234375, -0.05084228515625, 0.0272369384765625, -0.045806884765625, 0.03369140625, -0.049560546875, -0.0270538330078125, -0.018524169921875, -0.0190277099609375, -0.0047607421875, -0.004405975341796875, 0.0030689239501953125, 0.00031638145446777344, -0.038818359375, -0.007114410400390625, -0.031585693359375, -0.031524658203125, 0.0106353759765625, -0.00982666015625, -0.00878143310546875, 0.002796173095703125, 0.03515625, 0.005023956298828125, 0.0048980712890625, 0.0386962890625, -0.005886077880859375, 0.025238037109375, 0.021636962890625, 0.01708984375, -0.0073699951171875, -0.034942626953125, 0.005580902099609375, 0.008697509765625, 0.0311737060546875, 0.003765106201171875, 0.0247650146484375, 0.0136260986328125, 0.036041259765625, 0.021697998046875, -0.03240966796875, 0.02215576171875, -0.0019178390502929688, -0.017547607421875, -0.00646209716796875, -0.0048675537109375, -0.00872039794921875, -0.005035400390625, -0.0031986236572265625, -0.0244598388671875, 0.0210723876953125, -0.0026149749755859375, -0.041748046875, 0.017791748046875, 0.00778961181640625, -0.0151214599609375, -0.0186767578125, 0.017486572265625, 0.048431396484375, -0.017730712890625, 0.03173828125, -0.01523590087890625, 0.018463134765625, 0.018402099609375, 0.03607177734375, 0.0011548995971679688, 0.013214111328125, -0.01204681396484375, 0.00495147705078125, -0.0204925537109375, 0.01419830322265625, -0.01812744140625, 0.00811004638671875, -0.013916015625, -0.005916595458984375, 0.002838134765625, 0.009307861328125, 0.0221099853515625, 0.020172119140625, 0.0220947265625, 0.054351806640625, 0.0026760101318359375, -0.004589080810546875, -0.011962890625, -0.0026683807373046875, 0.007808685302734375, -0.007396697998046875, 0.00922393798828125, -0.0174713134765625, 0.0100555419921875, 0.06817626953125, -0.0038051605224609375, -0.0228118896484375, 0.0220489501953125, -0.0251312255859375, 0.00995635986328125, 0.00775146484375, 0.003330230712890625, -0.02593994140625, 0.0182647705078125, 0.0189666748046875, -0.033782958984375, 0.0158843994140625, -0.0148773193359375, -0.024932861328125, -0.0224761962890625, 0.007686614990234375, 0.01861572265625, 0.00467681884765625, -0.033905029296875, 0.0016508102416992188, -0.02093505859375, -0.0054168701171875, -0.035064697265625, 0.037261962890625, -0.046905517578125, -0.024627685546875, -0.030975341796875, 0.00821685791015625, -0.01279449462890625, -0.0276336669921875, -0.0210418701171875, -0.0255126953125]}, "text_id_to_ref_doc_id": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": "6815456a-54f2-4a06-839a-4237713a5b85"}, "metadata_dict": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"_node_type": "TextNode", "document_id": "6815456a-54f2-4a06-839a-4237713a5b85", "doc_id": "6815456a-54f2-4a06-839a-4237713a5b85", "ref_doc_id": "6815456a-54f2-4a06-839a-4237713a5b85"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/docstore.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"docstore/metadata": {"6815456a-54f2-4a06-839a-4237713a5b85": {"doc_hash": "e31725404c452bc7bb6b93285f5b7de1917dd6b4340001a2565339635b9c4a65"}, "e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"doc_hash": "7e80a357c96e74104a44793a6b1eba724431c64f8d4d4702bf0e93bc7336201d", "ref_doc_id": "6815456a-54f2-4a06-839a-4237713a5b85"}}, "docstore/ref_doc_info": {"6815456a-54f2-4a06-839a-4237713a5b85": {"node_ids": ["e78dce52-f400-452b-aff3-cbe27f8bbf2c"], "metadata": {}}}, "docstore/data": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"__data__": {"id_": "e78dce52-f400-452b-aff3-cbe27f8bbf2c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "6815456a-54f2-4a06-839a-4237713a5b85", "node_type": "4", "metadata": {}, "hash": "e31725404c452bc7bb6b93285f5b7de1917dd6b4340001a2565339635b9c4a65", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Recent experiences:", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 19, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/graph_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"graph_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/image__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/index_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"index_store/data": {"36fc9fca-2fa9-4956-a458-82e9418852d2": {"__type__": "vector_store", "__data__": "{\"index_id\": \"36fc9fca-2fa9-4956-a458-82e9418852d2\", \"summary\": null, \"nodes_dict\": {\"e78dce52-f400-452b-aff3-cbe27f8bbf2c\": \"e78dce52-f400-452b-aff3-cbe27f8bbf2c\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/semantic_memory/default__vector_store.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"embedding_dict": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": [0.0081634521484375, -0.002292633056640625, 0.044647216796875, 0.052490234375, 0.016448974609375, 0.04071044921875, 0.0214691162109375, -0.00907135009765625, -0.026580810546875, 0.06268310546875, -0.017913818359375, -0.031219482421875, -0.008270263671875, -0.0540771484375, 0.0306854248046875, 0.05987548828125, 0.0031261444091796875, 0.0249786376953125, 0.011383056640625, -0.0008664131164550781, 0.0090484619140625, 0.01824951171875, 0.01226806640625, -0.027923583984375, -0.006282806396484375, 0.0195465087890625, -0.03558349609375, 0.046844482421875, 0.048187255859375, -0.018035888671875, 0.01302337646484375, -0.035736083984375, 0.00951385498046875, 0.006000518798828125, 0.0019931793212890625, 0.046966552734375, 0.057830810546875, -0.046905517578125, 0.01568603515625, -0.049530029296875, -0.04400634765625, -0.01499176025390625, -0.0240478515625, -0.0204925537109375, -0.019073486328125, -0.038543701171875, 0.0274810791015625, 0.0416259765625, -0.005279541015625, 0.037811279296875, -0.0180816650390625, 0.0062103271484375, -0.007709503173828125, 0.05865478515625, -0.06402587890625, 0.037841796875, -0.0118560791015625, -0.0301361083984375, 0.024688720703125, -0.00374603271484375, 0.032196044921875, -0.030914306640625, 0.03759765625, 0.03179931640625, -0.0204315185546875, 0.0012073516845703125, -0.020904541015625, -0.007476806640625, 0.0204010009765625, -0.0124359130859375, 0.060791015625, -0.00656890869140625, 0.019775390625, -0.005367279052734375, 0.0201416015625, -0.009368896484375, 0.04400634765625, 0.01079559326171875, -0.026275634765625, -0.0166778564453125, -0.039947509765625, 0.0187530517578125, -0.007564544677734375, 0.006954193115234375, 0.0157928466796875, 0.0212860107421875, 0.01548004150390625, -0.0113372802734375, -0.00875091552734375, 0.00077056884765625, -0.0033931732177734375, -0.0517578125, 0.006214141845703125, -0.0011644363403320312, 0.0198211669921875, -0.06500244140625, 0.04730224609375, -0.005107879638671875, -0.046417236328125, 0.019805908203125, -0.01023101806640625, 0.042388916015625, -0.0251312255859375, 0.0288238525390625, -0.0189361572265625, 0.005825042724609375, -0.0218505859375, -0.053558349609375, -0.05267333984375, -0.01337432861328125, -0.07476806640625, 0.01398468017578125, -0.031402587890625, 0.060272216796875, -0.06524658203125, 0.01261138916015625, -0.036407470703125, 0.031585693359375, 0.018157958984375, 0.010650634765625, 0.03662109375, 0.004913330078125, -0.00821685791015625, -0.0110321044921875, -0.00493621826171875, -0.032867431640625, -0.0236968994140625, -0.0100250244140625, 0.01206207275390625, -0.0259246826171875, -0.037445068359375, -0.0034084320068359375, 0.03253173828125, -0.0012178421020507812, -0.04046630859375, -0.0421142578125, 0.039764404296875, -0.0325927734375, 0.007770538330078125, -0.031036376953125, -0.053375244140625, -0.0150146484375, 0.0517578125, 0.00887298583984375, 0.00026798248291015625, 0.051239013671875, 0.032623291015625, 0.0738525390625, -0.0224609375, 0.0159149169921875, 0.0098419189453125, -0.00909423828125, -0.0118255615234375, -0.0111541748046875, 0.0201263427734375, -0.0180511474609375, 0.01187896728515625, -0.034759521484375, -0.0008187294006347656, -0.04052734375, 0.060760498046875, -0.0290069580078125, -0.02984619140625, 0.004688262939453125, 0.04132080078125, 0.043914794921875, 0.0194854736328125, -0.0251007080078125, -0.0369873046875, -0.048095703125, 0.0293731689453125, -0.057098388671875, -0.00980377197265625, -0.06640625, -0.0310516357421875, -0.0071563720703125, -0.03265380859375, 0.019805908203125, -0.0110015869140625, -0.007228851318359375, 0.0055694580078125, 0.056488037109375, -0.04559326171875, -0.01302337646484375, -0.0055694580078125, -0.01259613037109375, -0.032379150390625, -0.023345947265625, 0.050201416015625, 0.0186920166015625, 0.0124359130859375, 0.0265655517578125, 0.0333251953125, 0.005031585693359375, 0.016876220703125, -0.03076171875, 0.06427001953125, -0.0201263427734375, -0.055511474609375, 0.022430419921875, 0.01209259033203125, 0.017364501953125, 0.02154541015625, -0.00867462158203125, 0.0078887939453125, -0.0232696533203125, 0.09197998046875, 0.0238189697265625, -0.06353759765625, -0.0104522705078125, 0.01107025146484375, -0.0228118896484375, 0.03570556640625, 0.06231689453125, -0.0238037109375, 0.055999755859375, -0.00455474853515625, -0.03582763671875, 0.02410888671875, 0.02105712890625, 0.00481414794921875, 0.00914764404296875, 0.050537109375, -0.01297760009765625, -0.035736083984375, 0.020782470703125, -0.01070404052734375, -0.0074615478515625, -0.0088348388671875, -0.041107177734375, -0.005451202392578125, -0.0007982254028320312, 0.0026073455810546875, -0.033447265625, -0.06683349609375, -0.03204345703125, 0.020904541015625, 0.045989990234375, 0.026458740234375, -0.020660400390625, -0.0216064453125, 0.0258026123046875, -0.0005774497985839844, 0.02734375, 0.0169830322265625, 0.01788330078125, -0.01715087890625, 0.0059051513671875, -6.35981559753418e-05, -0.051177978515625, 0.01082611083984375, -0.00955963134765625, -0.01690673828125, 0.01666259765625, -0.004123687744140625, -0.0438232421875, 0.00421905517578125, -0.02447509765625, 0.04412841796875, -0.0303802490234375, -0.03009033203125, -0.01531982421875, -0.0205230712890625, 0.03375244140625, 0.0355224609375, 0.0100860595703125, -0.006961822509765625, 0.0281829833984375, 0.00582122802734375, -0.04266357421875, 0.053131103515625, -0.037322998046875, 0.0026454925537109375, 0.0361328125, -0.045806884765625, 0.03363037109375, -0.0061492919921875, -0.0038585662841796875, -0.11993408203125, -0.007415771484375, -0.046844482421875, 0.0215606689453125, 0.056243896484375, -0.057342529296875, -0.00782012939453125, 0.019287109375, -0.0169677734375, 0.042083740234375, -0.01047515869140625, -0.027587890625, 0.00014638900756835938, -0.04193115234375, 0.0135345458984375, 0.004512786865234375, -0.023712158203125, -0.01529693603515625, -0.0019588470458984375, -0.0291595458984375, -0.02978515625, 0.0208282470703125, 0.0292816162109375, 0.0291595458984375, 0.0169830322265625, 0.04217529296875, 0.030426025390625, 0.0391845703125, 0.051116943359375, -0.00949859619140625, 0.0016641616821289062, -0.01345062255859375, 0.0010509490966796875, 0.0219879150390625, 0.0164031982421875, -0.016632080078125, -0.055267333984375, -0.043060302734375, 0.0008883476257324219, -0.00400543212890625, -0.0200347900390625, -0.007266998291015625, -0.07110595703125, -0.0411376953125, 0.0238494873046875, 0.0177459716796875, -0.002300262451171875, -0.0010957717895507812, 0.004611968994140625, 0.03857421875, 0.045623779296875, -0.01345062255859375, -0.020172119140625, 0.005931854248046875, -0.0224151611328125, 0.0186309814453125, -0.03692626953125, -0.0191497802734375, -0.0021038055419921875, 0.0276031494140625, -0.059051513671875, 0.026336669921875, -0.03814697265625, -0.04571533203125, -0.01171112060546875, 0.0307159423828125, -0.0005292892456054688, 0.0241851806640625, 0.00803375244140625, 0.032135009765625, -0.033660888671875, 0.03338623046875, 0.061737060546875, 0.01000213623046875, -0.01441192626953125, 0.0070037841796875, -0.037750244140625, -0.0239410400390625, 0.0209197998046875, -0.0517578125, 0.0029850006103515625, 0.038818359375, 0.0245361328125, 0.01708984375, -0.01453399658203125, 0.0589599609375, -0.03546142578125, -0.01189422607421875, -0.049072265625, 0.00897216796875, -0.023712158203125, -0.00415802001953125, 0.0007443428039550781, -0.0256805419921875, -0.00391387939453125, 0.004512786865234375, 0.014556884765625, 0.026702880859375, 0.0313720703125, 0.031951904296875, -0.027069091796875, 0.0291595458984375, 0.02362060546875, 0.04791259765625, 0.037750244140625, -0.0279388427734375, 0.0280914306640625, 0.019317626953125, -0.00952911376953125, 0.006809234619140625, -0.033111572265625, 0.00390625, 0.01123046875, 0.00978851318359375, -0.0217437744140625, 0.020782470703125, -0.01427459716796875, -0.0291595458984375, 0.016693115234375, 0.035125732421875, 0.0215911865234375, 0.0203704833984375, -0.0184326171875, -0.0194091796875, 0.0211944580078125, -0.00246429443359375, 0.0041656494140625, 0.01361846923828125, -0.050201416015625, 0.051116943359375, 0.00921630859375, -0.0055084228515625, -0.003063201904296875, -0.01062774658203125, 0.0014181137084960938, 0.00213623046875, 0.01873779296875, -0.01457977294921875, -0.0023956298828125, 0.0389404296875, -0.0031833648681640625, -0.033538818359375, -0.01708984375, 0.0002474784851074219, -0.034881591796875, -0.04931640625, 0.028289794921875, -0.01178741455078125, 0.019866943359375, -0.01268768310546875, -0.005245208740234375, -0.005237579345703125, 0.0125274658203125, 0.029083251953125, -0.0019741058349609375, 0.006275177001953125, -0.01934814453125, -0.03509521484375, 0.005462646484375, 0.0282135009765625, -0.048187255859375, -0.0160369873046875, 0.04827880859375, -0.0155792236328125, 0.008544921875, 0.01512908935546875, -0.0272369384765625, -0.0309600830078125, -0.059234619140625, -0.0015993118286132812, -0.0350341796875, -0.0251007080078125, 0.050933837890625, -0.0006337165832519531, -0.02740478515625, -0.0221099853515625, -0.0257110595703125, 0.026702880859375, -0.00421905517578125, 0.0280914306640625, 0.028900146484375, 0.0094757080078125, -0.01097869873046875, -0.02923583984375, -0.0212860107421875, 0.004825592041015625, 0.0255584716796875, -0.0294342041015625, 0.00959014892578125, 0.014251708984375, 0.020660400390625, 0.01003265380859375, -0.03143310546875, -0.003265380859375, 0.030181884765625, -0.0213623046875, 0.028594970703125, 0.04974365234375, -0.05438232421875, 0.01523590087890625, 0.0164337158203125, -0.0186614990234375, 0.00830841064453125, 0.060760498046875, -0.015777587890625, 0.07061767578125, 0.0157928466796875, 0.018341064453125, 0.036163330078125, 0.0264434814453125, 0.00530242919921875, 0.006160736083984375, 0.01274871826171875, -0.05438232421875, 0.036163330078125, -0.01207733154296875, 0.0167999267578125, -0.00661468505859375, 0.034271240234375, -0.0264129638671875, 0.059478759765625, -0.003787994384765625, 0.0673828125, 0.022552490234375, 0.00974273681640625, 0.036956787109375, -0.014862060546875, -0.0132293701171875, 0.009063720703125, 0.0085906982421875, 0.0012989044189453125, 0.06427001953125, -0.023651123046875, 0.0191802978515625, 0.006122589111328125, -0.0276336669921875, -0.010955810546875, 0.000308990478515625, -0.0009937286376953125, 0.0189971923828125, 0.0264129638671875, 0.0209808349609375, 0.008880615234375, 0.0171356201171875, 0.0224609375, 0.01255035400390625, -0.0106201171875, -0.02191162109375, -6.204843521118164e-05, -0.050506591796875, 0.00218963623046875, -0.030548095703125, 0.01369476318359375, -0.0341796875, 0.0058135986328125, -0.0211639404296875, -0.037017822265625, 0.00940704345703125, -0.0012731552124023438, -0.034210205078125, 0.006389617919921875, 0.0008244514465332031, 0.0135345458984375, 0.0244903564453125, 0.042877197265625, 0.032379150390625, -0.0015020370483398438, 0.01006317138671875, 0.0011501312255859375, -0.0491943359375, -0.006244659423828125, -0.003368377685546875, 0.0187530517578125, -0.039764404296875, 0.019287109375, 0.042266845703125, -0.0037937164306640625, -0.0198822021484375, -0.00969696044921875, 0.019744873046875, -0.0078277587890625, -0.0291900634765625, -0.0205841064453125, -0.01328277587890625, 0.0004062652587890625, -0.0078887939453125, 0.00908660888671875, -0.01517486572265625, 0.00878143310546875, -0.029205322265625, 0.0248870849609375, 0.01207733154296875, -0.004161834716796875, -0.0138397216796875, 0.024139404296875, -0.038543701171875, 0.00466156005859375, 0.015960693359375, 0.007282257080078125, 0.05291748046875, 0.0008330345153808594, -0.041229248046875, -0.01447296142578125, -0.0069732666015625, -0.0135498046875, 0.020660400390625, 0.00560760498046875, 0.0238800048828125, -0.00286102294921875, -0.01465606689453125, -0.0050506591796875, 0.037200927734375, 0.007137298583984375, 0.00571441650390625, 0.018646240234375, -0.027587890625, -0.027587890625, 0.004150390625, -0.0226898193359375, -0.043975830078125, -0.01523590087890625, -0.01544189453125, 0.00860595703125, -0.043365478515625, -0.037750244140625, -0.0161590576171875, -0.0017404556274414062, -0.006336212158203125, -0.0562744140625, 0.0026607513427734375, -0.0604248046875, -0.006256103515625, -0.01192474365234375, 0.0153961181640625, -0.003574371337890625, -0.0445556640625, 0.01519012451171875, 0.037445068359375, -0.040496826171875, 0.005077362060546875, -0.00991058349609375, -0.01678466796875, -0.0136566162109375, 0.0233154296875, -0.0787353515625, 0.01380157470703125, -0.047271728515625, -0.0276031494140625, 0.00688934326171875, -0.009796142578125, 0.0006351470947265625, 0.0166015625, 0.018768310546875, -0.0185546875, 0.00872802734375, -0.023773193359375, -0.00661468505859375, -0.0167999267578125, 0.0089111328125, 0.0200347900390625, -0.004016876220703125, -0.0026721954345703125, 0.03564453125, 0.01297760009765625, 0.0024356842041015625, 0.0306396484375, 0.0224456787109375, -0.00824737548828125, -0.00496673583984375, -0.027801513671875, 0.0149078369140625, 0.009857177734375, 0.01462554931640625, -0.01128387451171875, 0.0233917236328125, 0.0137176513671875, -0.006195068359375, -0.04833984375, 0.007534027099609375, -0.0154876708984375, -0.01300048828125, 0.024658203125, -0.06500244140625, -0.01262664794921875, -0.0100860595703125, -0.002330780029296875, 0.032623291015625, 0.03619384765625, -0.0102081298828125, -0.002166748046875, 0.0289459228515625, 0.0087127685546875, -0.0059814453125, 0.0179443359375, 0.05010986328125, 0.047821044921875, -0.00574493408203125, -0.04718017578125, 0.041839599609375, -0.021240234375, -0.0176849365234375, 0.042572021484375, 0.0169525146484375, -0.016998291015625, -0.024505615234375, -0.01015472412109375, -0.02374267578125, 0.00479888916015625, 0.01483154296875, -0.046295166015625, 0.01556396484375, -0.0053558349609375, -0.023345947265625, -0.013519287109375, -0.0301055908203125, 0.026580810546875, -0.005359649658203125, -0.00551605224609375, 0.03167724609375, -0.004123687744140625, 0.0244903564453125, -0.045135498046875, 0.00211334228515625, -0.0006990432739257812, -0.032867431640625, -0.005771636962890625, -0.037109375, 0.00664520263671875, -0.05133056640625, -0.00890350341796875, -0.0289154052734375, -0.02850341796875, -0.04193115234375, -0.01215362548828125, -0.004749298095703125, 0.0361328125, -0.0069122314453125, -0.0298614501953125, -0.01922607421875, 0.033782958984375, 0.0205230712890625, 0.01410675048828125, 0.008209228515625, -0.0059661865234375, -0.0038814544677734375, -0.0022678375244140625, 0.034149169921875, -0.0047760009765625, 0.044830322265625, 0.0013370513916015625, -0.032135009765625, -0.030303955078125, -0.0186309814453125, -0.032928466796875, 0.01534271240234375, -0.006374359130859375, -0.01548004150390625, 0.041473388671875, -0.0160064697265625, 0.023956298828125, 0.0096893310546875, 0.01244354248046875, -0.031982421875, -0.01995849609375, 0.006069183349609375, -0.00873565673828125, 0.00626373291015625, 0.0095977783203125, -0.003803253173828125, 0.0200042724609375, -0.045318603515625, -0.011077880859375, 0.003444671630859375, 0.0079803466796875, -0.005401611328125, -0.0389404296875, -0.0280609130859375, 0.0011053085327148438, 0.0187530517578125, -0.00860595703125, -0.0061492919921875, 0.01132965087890625, 0.0266571044921875, 0.01274871826171875, 0.01338958740234375, -0.0350341796875, -0.006664276123046875, 0.0233612060546875, 0.052642822265625, 0.014495849609375, -0.0216217041015625, -0.0214691162109375, -0.01061248779296875, -0.0025196075439453125, 0.0021514892578125, -0.0012445449829101562, -0.00827789306640625, 0.03857421875, 0.002994537353515625, 0.005756378173828125, -0.01212310791015625, -0.01474761962890625, 0.00794219970703125, -0.037200927734375, -0.0084228515625, 0.01149749755859375, -0.0269927978515625, -0.031402587890625, -0.006183624267578125, 0.02117919921875, 0.0103607177734375, -0.033203125, 0.00778961181640625, 0.01331329345703125, -0.0232391357421875, 0.00733184814453125, -0.016845703125, 0.0277557373046875, 0.01393890380859375, -0.06591796875, -0.0170440673828125, 0.027099609375, -0.039794921875, -0.014007568359375, -0.00789642333984375, 0.0081939697265625, 0.002590179443359375, 0.01380157470703125, -0.021484375, 0.020965576171875, -0.049041748046875, -0.004985809326171875, 0.00897979736328125, -0.0260467529296875, -0.0276947021484375, -0.00287628173828125, -0.011810302734375, 0.0390625, -0.0197906494140625, -0.034149169921875, 0.00661468505859375, -0.0009756088256835938, 0.0105438232421875, -0.002239227294921875, -0.002838134765625, -0.0214691162109375, 0.0034084320068359375, 0.0214385986328125, -0.00936126708984375, -0.02008056640625, 0.002567291259765625, 0.0212554931640625, 0.0140228271484375, -0.0206298828125, -0.001743316650390625, 0.0254669189453125, -0.000782012939453125, -0.0019121170043945312, 0.0445556640625, 0.023834228515625, 0.032623291015625, 0.0251922607421875, 0.020782470703125, 0.0278778076171875, -0.0167694091796875, 0.0105438232421875, 0.04779052734375, -0.0048828125, 0.0517578125, -0.0255126953125, -0.0034542083740234375, 0.01373291015625, 0.00677490234375, -0.0361328125, -0.0259246826171875, 0.013427734375, -0.04217529296875, -0.01544189453125, 0.043243408203125, 0.012420654296875, 0.0258331298828125, -0.007720947265625, -0.0014410018920898438, -0.00420379638671875, 0.0026092529296875, 0.0084228515625, 0.00868988037109375, 0.006107330322265625, 0.00807952880859375, 0.005107879638671875, -0.0022563934326171875, 0.015838623046875, -0.02886962890625, -0.0253448486328125, 0.0030956268310546875, 0.0030994415283203125, -0.0251007080078125, -0.0428466796875, 0.01349639892578125, 0.0174713134765625, 0.0137939453125, 0.05706787109375, 0.0176849365234375, 0.0206756591796875, 0.0208892822265625, 0.04144287109375, 0.0088043212890625, 0.0038604736328125, 0.008209228515625, 0.07611083984375, -0.004405975341796875, 0.004058837890625, -0.003353118896484375, 0.0014896392822265625, -0.01483154296875, 0.00463104248046875, -0.0180511474609375, 0.01044464111328125, -0.0180511474609375, -0.038421630859375, 0.01039886474609375, -0.0121002197265625, -0.0021724700927734375, -0.03704833984375, -0.019775390625, 0.0008993148803710938, -0.01511383056640625, -0.05413818359375, 0.0098419189453125, -0.01050567626953125, -0.0015897750854492188, 0.01309967041015625, 0.006343841552734375, -0.006870269775390625, -0.06890869140625, -0.0005159378051757812, -0.005908966064453125, 0.046051025390625, 0.002643585205078125, 0.001873016357421875, 0.0159149169921875, -0.0234832763671875, -0.019256591796875, 0.01111602783203125, -0.02044677734375, 0.019256591796875, 0.01097869873046875, -0.0302276611328125, -0.046844482421875, 0.004947662353515625, 0.0012598037719726562, -0.0081329345703125, 0.056182861328125, -0.0090179443359375, 0.020233154296875, -0.0267791748046875, -0.01499176025390625, 0.0180816650390625, -0.007411956787109375, 0.00449371337890625, 0.023590087890625, 0.01015472412109375, -0.043426513671875, 0.0155792236328125, -0.0168304443359375, 0.00992584228515625, -0.00901031494140625, -0.0286712646484375, -0.00901031494140625, 0.0248260498046875, 0.005367279052734375, -0.01314544677734375, 0.03753662109375, -0.01097869873046875, 0.00495147705078125, -0.0029926300048828125, 0.002643585205078125, -0.0117950439453125, -0.0006265640258789062, 0.0288238525390625, 0.0028591156005859375, -0.0089569091796875, -0.016357421875, 0.051666259765625, -0.0081024169921875, 0.026153564453125, -0.0130767822265625, 0.0259552001953125, 0.01103973388671875, 0.0018148422241210938, -0.029937744140625, -0.011322021484375, 0.0197296142578125, 0.0126953125, 0.0205230712890625, 0.0122833251953125, 0.042510986328125, 0.0017757415771484375, 0.01039886474609375, 0.037994384765625, 0.010833740234375, -0.006931304931640625, -0.0152130126953125, 0.07647705078125, -0.009185791015625, 0.0023593902587890625, -0.0119476318359375, -0.039886474609375, 0.024871826171875, 0.005523681640625, 0.00998687744140625, -0.00031828880310058594, 0.06103515625, -0.0184783935546875, -0.0008525848388671875, 0.0227203369140625, -0.0272674560546875, -0.0012531280517578125, -0.026153564453125, -0.0269927978515625, -0.007198333740234375, 0.0032558441162109375, 0.00506591796875, 0.0234222412109375, 0.0125274658203125, -0.0095062255859375, 0.0305633544921875, 0.0005183219909667969, -0.004970550537109375, 0.01302337646484375, -0.03375244140625, 0.0007238388061523438, -0.00012350082397460938, -0.048614501953125, 0.0019254684448242188, 0.0223236083984375, 0.028839111328125, -0.040557861328125, -0.03375244140625, -0.014739990234375, -0.022857666015625, -0.0255126953125, 0.044219970703125, 0.01065826416015625, 0.0252227783203125, 0.0306396484375, -0.0015087127685546875, 0.0166473388671875, 0.01280975341796875, -0.0254974365234375, 0.0161285400390625, 0.0138397216796875, 0.01062774658203125, 0.01702880859375, 0.00521087646484375, 0.0267791748046875, 0.00209808349609375, 0.01265716552734375, 0.042266845703125, -0.0082855224609375, -0.0055084228515625, 0.004180908203125, -0.0305023193359375, 0.01435089111328125, 0.0015707015991210938, -0.007053375244140625, 0.004009246826171875, -0.00656890869140625, 0.022003173828125, -0.045989990234375, 0.0228118896484375, -0.00933074951171875, -0.01088714599609375, 0.0389404296875, -0.01474761962890625, -0.00757598876953125, 0.0240478515625, 0.0191802978515625, 0.0226287841796875, -0.006542205810546875, 0.01406097412109375, 0.01079559326171875, -0.01690673828125, -0.00464630126953125, 0.00605010986328125, -0.036285400390625, -0.035369873046875, -0.0016565322875976562, -0.00864410400390625, -0.078369140625, 0.01390838623046875, 0.05755615234375, 0.0011186599731445312, -0.03857421875, 0.0379638671875, 0.022735595703125, -0.031829833984375, 0.0229949951171875, 0.00341033935546875, -0.0267791748046875, 0.007144927978515625, 0.025299072265625, 0.0272369384765625, 0.00940704345703125, -0.017913818359375, 0.0004203319549560547, -0.0460205078125, -0.003326416015625, 0.0013828277587890625, -0.0019178390502929688, -0.0006866455078125, 0.01453399658203125, 0.00496673583984375, -0.00928497314453125, -0.023284912109375, -0.0214996337890625, 0.0307464599609375, 0.0161285400390625, 0.005962371826171875, -0.018646240234375, -0.004116058349609375, -0.0226287841796875, 0.0089874267578125, 0.00780487060546875, -0.00162506103515625, -0.039398193359375, -0.0242462158203125, -0.01702880859375, -0.0011005401611328125, 0.01171875, -0.049224853515625, -0.01456451416015625, 0.00907135009765625, 0.007579803466796875, -0.034454345703125, -0.0096893310546875, -0.0153350830078125, 0.00677490234375, -0.02484130859375, -0.00079345703125, 0.00438690185546875, 0.0017328262329101562, 0.0220184326171875, -0.0289459228515625, 0.01393890380859375, 0.0129241943359375, -0.000499725341796875, 0.004150390625, 0.00563812255859375, -0.025848388671875, -0.0153350830078125, -0.014251708984375, -0.0186767578125, -0.0310821533203125, 0.003177642822265625, 0.0274658203125, -0.034393310546875, -0.01348876953125, 0.024871826171875, 0.0096282958984375, 0.01067352294921875, 0.00806427001953125, 0.01666259765625, 0.03656005859375, 0.021026611328125, -0.00617218017578125, -0.0019359588623046875, -0.0159454345703125, 0.01015472412109375, 0.0701904296875, 0.032135009765625, -0.0253448486328125, -0.0034046173095703125, -0.011199951171875, 0.0122528076171875, 0.01537322998046875, 0.036041259765625, -0.041595458984375, 0.0291290283203125, -0.0144805908203125, -0.0036296844482421875, -0.01291656494140625, -0.036651611328125, 0.01690673828125, -0.004123687744140625, -0.0280914306640625, 0.0008525848388671875, 0.002559661865234375, 0.01006317138671875, 0.019317626953125, 0.036895751953125, 0.00431060791015625, 0.00772857666015625, 0.0025310516357421875, 0.0027923583984375, -0.0090179443359375, -0.037200927734375, -0.01134490966796875, -0.0272369384765625, -0.00931549072265625, 0.0015859603881835938, 0.0031414031982421875, 0.0206451416015625, -0.0137939453125, 0.0027561187744140625, -0.0034694671630859375, -0.00751495361328125, -0.004512786865234375, 0.00955963134765625, -0.01059722900390625, -0.01451873779296875, -0.05718994140625, -0.022216796875, 0.0036754608154296875, -0.026702880859375, -0.01904296875, -0.031982421875, -0.0155792236328125, -0.0211944580078125, -0.004985809326171875, -0.0032958984375, -0.021575927734375, -0.0026721954345703125, 0.00812530517578125, -0.0253753662109375, 0.01727294921875, -0.04443359375, -0.04022216796875, -0.003082275390625, 0.01087188720703125, 0.0258026123046875, -0.0269317626953125, -0.04644775390625, 0.026336669921875, -0.041656494140625, -0.021087646484375, -0.0276031494140625, 0.0246124267578125, 0.0115966796875, -0.003696441650390625, 0.0198974609375, -0.047027587890625, -0.034912109375, -0.0009021759033203125, 0.01114654541015625, -0.03167724609375, -0.0200653076171875, -0.039306640625, -0.016143798828125, -0.0030384063720703125, -0.005954742431640625, -0.0031223297119140625, 0.0226898193359375, -0.00350189208984375, -0.017181396484375, -0.007022857666015625, -0.01399993896484375, -0.0019273757934570312, 0.016326904296875, -0.022247314453125, 0.0205841064453125, 0.0155029296875, 0.0236053466796875, 0.01500701904296875, -0.006717681884765625, 0.006984710693359375, 0.044342041015625, 0.0016145706176757812, 0.005863189697265625, -0.0021800994873046875, -0.01959228515625, -0.0228729248046875, 0.01824951171875, -0.0213470458984375, -0.0389404296875, -0.005100250244140625, -0.0184478759765625, 0.03631591796875, 0.00395965576171875, 0.01558685302734375, 0.03668212890625, 0.046844482421875, 0.00881195068359375, 0.007686614990234375, 0.0139617919921875, 0.037506103515625, -0.00873565673828125, 0.0240631103515625, 0.0052032470703125, -0.00719451904296875, -0.0280914306640625, -0.004909515380859375, -0.003948211669921875, -0.005405426025390625, 0.0223388671875, -0.00704193115234375, -0.0080718994140625, -0.06842041015625, -0.00026416778564453125, -0.04205322265625, 0.020355224609375, 0.006992340087890625, 0.00927734375, 0.006683349609375, 0.039825439453125, 0.001041412353515625, -0.01506805419921875, 0.0018939971923828125, -0.01433563232421875, 0.0135345458984375, -0.00296783447265625, 0.00015664100646972656, -0.01390838623046875, 0.0229034423828125, -0.037628173828125, 0.0089874267578125, -0.025787353515625, 0.01003265380859375, 0.0244293212890625, 0.01171112060546875, -0.037078857421875, 0.0225677490234375, 0.003177642822265625, 0.02276611328125, 0.041168212890625, 0.007701873779296875, 0.0214080810546875, -0.00629425048828125, -0.00031876564025878906, 0.00042629241943359375, 0.000579833984375, -0.000774383544921875, -0.053863525390625, 0.00152587890625, -0.01131439208984375, -0.00983428955078125, 0.002902984619140625, 0.003147125244140625, -0.01934814453125, 0.0134735107421875, -0.0298919677734375, 0.0188140869140625, -0.02734375, 0.01076507568359375, 0.002857208251953125, 0.01274871826171875, 0.01439666748046875, -0.0234832763671875, 0.05010986328125, 0.014984130859375, -0.00844573974609375, -0.01540374755859375, -0.0216217041015625, -0.017852783203125, 0.0061798095703125, 0.0280914306640625, -0.012451171875, 0.0037479400634765625, -0.0167999267578125, -0.01390838623046875, -0.02349853515625, -0.006694793701171875, -0.003936767578125, 0.02252197265625, 0.032989501953125, -0.00970458984375, 0.01300048828125, -0.0012035369873046875, -0.020782470703125, 0.02105712890625, 0.025543212890625, -0.01512908935546875, -0.005184173583984375, 0.00628662109375, 0.00628662109375, 0.0243988037109375, 0.0224609375, -0.0249786376953125, -0.006954193115234375, 0.01262664794921875, 0.03155517578125, 0.041351318359375, -0.0460205078125, 0.036529541015625, 0.00392913818359375, -0.00934600830078125, -0.00530242919921875, -0.054443359375, -0.00275421142578125, -0.021881103515625, -0.0019893646240234375, -0.01165771484375, -0.02984619140625, 0.0003933906555175781, -0.00395965576171875, -0.003871917724609375, -0.02105712890625, 0.0278472900390625, -0.011871337890625, -0.02130126953125, -0.0233917236328125, 0.0360107421875, -0.0181121826171875, 0.04779052734375, -0.0031566619873046875, -0.0180816650390625, 0.0116119384765625, -0.0006551742553710938, 0.027923583984375, -0.025726318359375, -0.01312255859375, -0.00345611572265625, -0.0265045166015625, -0.0181427001953125, 0.0017614364624023438, 0.002773284912109375, 0.0028743743896484375, -0.01016998291015625, 0.03436279296875, -0.050140380859375, -0.0198822021484375, 0.027313232421875, 0.026275634765625, -0.01314544677734375, -0.02191162109375, -0.02130126953125, 0.0081024169921875, -0.03515625, -0.0256195068359375, 0.0106201171875, -0.055877685546875, -0.01084136962890625, 0.005390167236328125, 0.0003273487091064453, 0.012420654296875, -0.010498046875, -0.0263214111328125, -0.04498291015625, 0.006694793701171875, -0.0194244384765625, -0.0158538818359375, -0.0406494140625, -0.01515960693359375, -0.009124755859375, -0.00870513916015625, 0.002513885498046875, 0.001987457275390625, 0.01279449462890625, -0.0029239654541015625, -0.0033931732177734375, -0.00514984130859375, -0.0005679130554199219, -0.0217132568359375, 0.040985107421875, -0.015777587890625, -0.00986480712890625, 0.018402099609375, 0.03387451171875, 0.0026493072509765625, -0.0019817352294921875, 0.0037364959716796875, -0.01015472412109375, 0.00292205810546875, 0.005474090576171875, 0.01065826416015625, 0.0222625732421875, -0.004001617431640625, -0.005584716796875, 0.0205841064453125, 0.002239227294921875, -0.01386260986328125, 0.00673675537109375, 0.0190582275390625, -0.0186309814453125, 0.04754638671875, 0.0094146728515625, 0.00856781005859375, -0.022369384765625, -0.0153961181640625, 0.005535125732421875, 0.007350921630859375, 0.00032782554626464844, 0.034912109375, -0.01055908203125, -0.00949859619140625, -0.00434112548828125, 0.005523681640625, 0.0018072128295898438, 0.0303955078125, 0.0022430419921875, -0.037750244140625, 0.0110321044921875, -0.0115203857421875, 0.051605224609375, 0.0140838623046875, -0.007495880126953125, 0.041839599609375, 0.024627685546875, -0.004077911376953125, 0.020294189453125, -0.0202484130859375, 0.003849029541015625, -0.022735595703125, 0.00580596923828125, 0.004528045654296875, -0.0038280487060546875, 0.0033054351806640625, -0.01279449462890625, -0.01439666748046875, -0.0274810791015625, 0.0133514404296875, 0.015655517578125, -0.00664520263671875, -0.0203857421875, 0.01059722900390625, 0.020416259765625, -0.0273590087890625, -0.01131439208984375, 0.020599365234375, 0.0058746337890625, 0.03302001953125, -0.03875732421875, 0.036529541015625, -0.015899658203125, -0.0177459716796875, 0.05560302734375, -0.03765869140625, -0.04473876953125, 0.010955810546875, 0.0119171142578125, 0.0100250244140625, -0.006626129150390625, 0.03961181640625, 0.01277923583984375, 0.00946044921875, 0.034088134765625, -0.0287017822265625, -0.02947998046875, 0.01409149169921875, -0.035675048828125, -0.01560211181640625, -0.0121917724609375, 0.01125335693359375, -0.0218505859375, -0.0235748291015625, -0.0017766952514648438, -0.05010986328125, 0.00981903076171875, -0.03826904296875, 0.01904296875, -0.06036376953125, -0.015716552734375, -0.0099334716796875, -0.007167816162109375, -0.01708984375, -0.041259765625, 0.0106964111328125, 0.009307861328125]}, "text_id_to_ref_doc_id": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": "60e4ed57-c96b-4ac4-9288-190c23e041b9"}, "metadata_dict": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": {"_node_type": "TextNode", "document_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9", "doc_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9", "ref_doc_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9"}}}