Keyvan1986 commited on
Commit
00684b2
·
verified ·
1 Parent(s): 3e6c6e3

Update utils/memory_utils.py

Browse files
Files changed (1) hide show
  1. utils/memory_utils.py +86 -38
utils/memory_utils.py CHANGED
@@ -4,7 +4,7 @@ import json
4
  import time
5
  import shutil
6
  import gradio as gr
7
- from huggingface_hub import HfApi
8
 
9
  # LlamaIndex Imports
10
  try:
@@ -13,7 +13,6 @@ except ImportError:
13
  pass
14
 
15
  # Local Imports setup
16
- # فرض بر این است که این فایل در utils/ است و memory_bank یک پوشه عقب‌تر است
17
  bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
18
  sys.path.append(bank_path)
19
 
@@ -28,20 +27,25 @@ except ImportError:
28
  # 1. تنظیمات مسیر و هاب (Cloud Config)
29
  # ==========================================
30
 
31
- # !!! مهم: این قسمت را با نام کاربری و نام دیتاست خودتان پر کنید !!!
32
- # مثال: "ali-b/my-bot-memory"
33
- REPO_ID = "Keyvan1986/Emma-memory-storage"
34
  REPO_TYPE = "dataset"
35
 
36
- # دریافت توکن از متغیرهای محیطی (Secrets)
37
  HF_TOKEN = os.environ.get("HF_TOKEN")
38
 
39
  CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
40
  BASE_DIR = os.path.dirname(CURRENT_DIR)
41
  MEMORIES_DIR = os.path.join(BASE_DIR, "memories")
 
 
42
  MEMORY_FILE_NAME = "update_memory_0512_eng.json"
43
  MEMORY_FILE_PATH = os.path.join(MEMORIES_DIR, MEMORY_FILE_NAME)
44
 
 
 
 
 
45
  # اطمینان از وجود پوشه در زمان ایمپورت
46
  os.makedirs(MEMORIES_DIR, exist_ok=True)
47
 
@@ -52,44 +56,61 @@ os.makedirs(MEMORIES_DIR, exist_ok=True)
52
 
53
  def push_to_hub():
54
  """
55
- فایل حافظه را به دیتاست هاگینگ‌فیس آپلود می‌کند.
 
56
  """
57
  if not HF_TOKEN:
58
- print("⚠️ Warning: HF_TOKEN not found. Memory is NOT saved to the cloud.")
59
  return
60
 
61
  if "YOUR_USERNAME" in REPO_ID:
62
- print("⚠️ Warning: REPO_ID is not set in memory_utils.py. Cloud sync skipped.")
63
  return
64
 
65
  try:
66
  api = HfApi(token=HF_TOKEN)
67
- # آپلود فایل
 
 
68
  api.upload_file(
69
  path_or_fileobj=MEMORY_FILE_PATH,
70
  path_in_repo=MEMORY_FILE_NAME,
71
  repo_id=REPO_ID,
72
  repo_type=REPO_TYPE,
73
- commit_message=f"Auto-save: {time.strftime('%Y-%m-%d %H:%M:%S')}"
74
  )
75
- print(f"☁️ Synced to Hub: {REPO_ID}")
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  except Exception as e:
77
  print(f"❌ Cloud Sync Error: {e}")
78
 
79
  def pull_from_hub():
80
  """
81
- آخرین نسخه حافظه را دانلود می‌کند.
 
82
  """
83
  if not HF_TOKEN or "YOUR_USERNAME" in REPO_ID:
84
  return
85
 
86
  try:
87
  api = HfApi(token=HF_TOKEN)
88
- # بررسی وجود فایل
89
  files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
90
 
 
91
  if MEMORY_FILE_NAME in files:
92
- print(f"📥 Downloading memory from Hub...")
93
  api.hf_hub_download(
94
  repo_id=REPO_ID,
95
  repo_type=REPO_TYPE,
@@ -97,9 +118,26 @@ def pull_from_hub():
97
  local_dir=MEMORIES_DIR,
98
  force_download=True
99
  )
100
- print("✅ Download complete.")
101
  else:
102
- print("🆕 Memory file not found on Hub. Starting fresh.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  except Exception as e:
104
  print(f"⚠️ Cloud Download Error: {e}")
105
 
@@ -109,19 +147,18 @@ def pull_from_hub():
109
 
110
  def save_memory(data):
111
  """
112
- 1. ذخیره در دیسک محلی (Atomic Write)
113
- 2. ارسال به فضای ابری (Push to Hub)
114
  """
115
  try:
116
  os.makedirs(MEMORIES_DIR, exist_ok=True)
117
 
118
- # 1. Local Save
119
  temp_file = MEMORY_FILE_PATH + ".tmp"
120
  with open(temp_file, "w", encoding="utf-8") as f:
121
  json.dump(data, f, ensure_ascii=False, indent=4)
122
  os.replace(temp_file, MEMORY_FILE_PATH)
123
 
124
- # 2. Cloud Save
125
  push_to_hub()
126
 
127
  except Exception as e:
@@ -130,17 +167,17 @@ def save_memory(data):
130
 
131
  def load_memory():
132
  """
133
- 1. تلاش برای دانلود از فضای ابری
134
- 2. خواندن از دیسک محلی
135
- 3. اگر فایل نبود، ساخت فایل خالی
136
  """
137
- # 1. Cloud Pull
138
  pull_from_hub()
139
 
140
  # 2. Local Read / Create
141
  if not os.path.exists(MEMORY_FILE_PATH):
142
- print(f"⚠️ Memory file missing locally. Creating new at: {MEMORY_FILE_PATH}")
143
- save_memory({}) # فایل خالی می‌سازد و آپلود می‌کند
 
 
144
  return {}
145
 
146
  try:
@@ -159,10 +196,9 @@ def load_memory():
159
  # ==========================================
160
 
161
  def enter_name_llamaindex(name, memory_data, data_args, update_memory_index=True):
162
- """
163
- کاربر را ایجاد کرده و فایل را فوراً ذخیره می‌کند.
164
- """
165
  is_new_user = False
 
 
166
  if name not in memory_data:
167
  print(f"🆕 Creating new user profile for: {name}")
168
  memory_data[name] = {
@@ -173,38 +209,45 @@ def enter_name_llamaindex(name, memory_data, data_args, update_memory_index=True
173
  "profile": {}
174
  }
175
  is_new_user = True
 
 
176
 
177
  user_memory = memory_data[name]
178
 
179
- # اگر کاربر جدید است، سریعاً ذخیره و سینک کن
180
- if is_new_user:
181
- save_memory(memory_data)
182
-
183
- # 2. مدیریت ایندکس‌های وکتوری (LlamaIndex)
184
  sessions_memory = None
185
  episodic_memory = None
186
  semantic_memory = None
187
 
188
- base_index_dir = os.path.join(MEMORIES_DIR, "memory_index", "llamaindex", name)
189
 
190
  sessions_path = os.path.join(base_index_dir, "sessions_index.json")
191
  episodic_path = os.path.join(base_index_dir, "episodic_memory_index.json")
192
  semantic_path = os.path.join(base_index_dir, "semantic_memory_index.json")
193
 
 
194
  indices_exist = (
195
  os.path.exists(sessions_path) and
196
  os.path.exists(episodic_path) and
197
  os.path.exists(semantic_path)
198
  )
199
 
 
200
  if update_memory_index or not indices_exist:
201
  try:
 
202
  os.makedirs(base_index_dir, exist_ok=True)
203
  build_memory_index(memory_data, data_args, name=name)
 
 
 
 
 
 
204
  except Exception as e:
205
  print(f"Warning: Error building memory index (skipping): {e}")
206
 
207
- # بارگذاری ایندکس‌ها
208
  if os.path.exists(sessions_path):
209
  try:
210
  storage_context = StorageContext.from_defaults(persist_dir=sessions_path)
@@ -227,11 +270,16 @@ def enter_name_llamaindex(name, memory_data, data_args, update_memory_index=True
227
 
228
 
229
  def summarize_memory_event_personality(data_args, memory_data, user_name):
230
- # ذخیره قبل از عملیات سنگین
231
  save_memory(memory_data)
232
 
233
  try:
 
234
  updated_memory = summarize_memory(MEMORY_FILE_PATH, user_name, language='en')
 
 
 
 
235
  return updated_memory.get(user_name, {})
236
  except Exception as e:
237
  print(f"Error in summarize_memory: {e}")
 
4
  import time
5
  import shutil
6
  import gradio as gr
7
+ from huggingface_hub import HfApi, snapshot_download
8
 
9
  # LlamaIndex Imports
10
  try:
 
13
  pass
14
 
15
  # Local Imports setup
 
16
  bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
17
  sys.path.append(bank_path)
18
 
 
27
  # 1. تنظیمات مسیر و هاب (Cloud Config)
28
  # ==========================================
29
 
30
+ # !!! مهم: نام کاربری و دیتاست خود را اینجا وارد کنید !!!
31
+ REPO_ID = "YOUR_USERNAME/YOUR_DATASET_NAME"
 
32
  REPO_TYPE = "dataset"
33
 
34
+ # دریافت توکن
35
  HF_TOKEN = os.environ.get("HF_TOKEN")
36
 
37
  CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
38
  BASE_DIR = os.path.dirname(CURRENT_DIR)
39
  MEMORIES_DIR = os.path.join(BASE_DIR, "memories")
40
+
41
+ # فایل اصلی JSON
42
  MEMORY_FILE_NAME = "update_memory_0512_eng.json"
43
  MEMORY_FILE_PATH = os.path.join(MEMORIES_DIR, MEMORY_FILE_NAME)
44
 
45
+ # پوشه ایندکس‌های LlamaIndex
46
+ MEMORY_INDEX_DIR_NAME = "memory_index"
47
+ MEMORY_INDEX_PATH = os.path.join(MEMORIES_DIR, MEMORY_INDEX_DIR_NAME)
48
+
49
  # اطمینان از وجود پوشه در زمان ایمپورت
50
  os.makedirs(MEMORIES_DIR, exist_ok=True)
51
 
 
56
 
57
  def push_to_hub():
58
  """
59
+ 1. فایل JSON حافظه را آپلود می‌کند.
60
+ 2. پوشه memory_index (شامل وکتورها) را آپلود می‌کند.
61
  """
62
  if not HF_TOKEN:
63
+ print("⚠️ Warning: HF_TOKEN not found. Cloud sync skipped.")
64
  return
65
 
66
  if "YOUR_USERNAME" in REPO_ID:
67
+ print("⚠️ Warning: REPO_ID is not set. Cloud sync skipped.")
68
  return
69
 
70
  try:
71
  api = HfApi(token=HF_TOKEN)
72
+
73
+ # A) آپلود فایل JSON اصلی
74
+ print("☁️ Uploading JSON memory file...")
75
  api.upload_file(
76
  path_or_fileobj=MEMORY_FILE_PATH,
77
  path_in_repo=MEMORY_FILE_NAME,
78
  repo_id=REPO_ID,
79
  repo_type=REPO_TYPE,
80
+ commit_message=f"Auto-save JSON: {time.strftime('%Y-%m-%d %H:%M:%S')}"
81
  )
82
+
83
+ # B) آپلود پوشه ایندکس‌ها (Vector Stores)
84
+ if os.path.exists(MEMORY_INDEX_PATH):
85
+ print("☁️ Uploading Index folder (Vectors)...")
86
+ api.upload_folder(
87
+ folder_path=MEMORY_INDEX_PATH,
88
+ path_in_repo=MEMORY_INDEX_DIR_NAME, # در دیتاست هم داخل پوشه memory_index می‌رود
89
+ repo_id=REPO_ID,
90
+ repo_type=REPO_TYPE,
91
+ commit_message=f"Auto-save Indices: {time.strftime('%Y-%m-%d %H:%M:%S')}"
92
+ )
93
+
94
+ print(f"✅ Synced all data to Hub: {REPO_ID}")
95
+
96
  except Exception as e:
97
  print(f"❌ Cloud Sync Error: {e}")
98
 
99
  def pull_from_hub():
100
  """
101
+ 1. فایل JSON را دانلود می‌کند.
102
+ 2. پوشه memory_index را دانلود می‌کند.
103
  """
104
  if not HF_TOKEN or "YOUR_USERNAME" in REPO_ID:
105
  return
106
 
107
  try:
108
  api = HfApi(token=HF_TOKEN)
 
109
  files = api.list_repo_files(repo_id=REPO_ID, repo_type=REPO_TYPE)
110
 
111
+ # A) دانلود فایل JSON
112
  if MEMORY_FILE_NAME in files:
113
+ print(f"📥 Downloading JSON memory...")
114
  api.hf_hub_download(
115
  repo_id=REPO_ID,
116
  repo_type=REPO_TYPE,
 
118
  local_dir=MEMORIES_DIR,
119
  force_download=True
120
  )
 
121
  else:
122
+ print("🆕 Memory JSON not found on Hub. Creating fresh.")
123
+
124
+ # B) دانلود پوشه ایندکس‌ها (اگر وجود داشته باشد)
125
+ # بررسی می‌کنیم آیا پوشه memory_index در فایل‌های ریپو هست یا نه
126
+ has_index = any(f.startswith(MEMORY_INDEX_DIR_NAME) for f in files)
127
+
128
+ if has_index:
129
+ print(f"📥 Downloading Index folder (Vectors)...")
130
+ snapshot_download(
131
+ repo_id=REPO_ID,
132
+ repo_type=REPO_TYPE,
133
+ local_dir=MEMORIES_DIR,
134
+ allow_patterns=f"{MEMORY_INDEX_DIR_NAME}/**", # فقط پوشه ایندکس را بگیر
135
+ force_download=True # برای اطمینان از بروزرسانی
136
+ )
137
+ print("✅ Indices downloaded.")
138
+ else:
139
+ print("🆕 No existing indices on Hub. Will build locally.")
140
+
141
  except Exception as e:
142
  print(f"⚠️ Cloud Download Error: {e}")
143
 
 
147
 
148
  def save_memory(data):
149
  """
150
+ ذخیره اتمیک JSON + همگام‌سازی کامل با ابر
 
151
  """
152
  try:
153
  os.makedirs(MEMORIES_DIR, exist_ok=True)
154
 
155
+ # 1. Local Save (JSON)
156
  temp_file = MEMORY_FILE_PATH + ".tmp"
157
  with open(temp_file, "w", encoding="utf-8") as f:
158
  json.dump(data, f, ensure_ascii=False, indent=4)
159
  os.replace(temp_file, MEMORY_FILE_PATH)
160
 
161
+ # 2. Cloud Save (JSON + Folder)
162
  push_to_hub()
163
 
164
  except Exception as e:
 
167
 
168
  def load_memory():
169
  """
170
+ لود کردن (همراه با دانلود اولیه از ابر)
 
 
171
  """
172
+ # 1. Cloud Pull (JSON + Indices)
173
  pull_from_hub()
174
 
175
  # 2. Local Read / Create
176
  if not os.path.exists(MEMORY_FILE_PATH):
177
+ print(f"⚠️ Memory file missing locally. Creating new.")
178
+ # فایل خالی می‌سازیم اما هنوز آپلود نمی‌کنیم تا وقتی دیتایی بیاید
179
+ with open(MEMORY_FILE_PATH, "w", encoding="utf-8") as f:
180
+ json.dump({}, f)
181
  return {}
182
 
183
  try:
 
196
  # ==========================================
197
 
198
  def enter_name_llamaindex(name, memory_data, data_args, update_memory_index=True):
 
 
 
199
  is_new_user = False
200
+
201
+ # اطمینان از وجود ساختار کاربر در دیکشنری
202
  if name not in memory_data:
203
  print(f"🆕 Creating new user profile for: {name}")
204
  memory_data[name] = {
 
209
  "profile": {}
210
  }
211
  is_new_user = True
212
+ # اگر کاربر جدید است، همان اول فایل جیسون را ذخیره کن
213
+ save_memory(memory_data)
214
 
215
  user_memory = memory_data[name]
216
 
217
+ # --- مدیریت ایندکس‌های LlamaIndex ---
 
 
 
 
218
  sessions_memory = None
219
  episodic_memory = None
220
  semantic_memory = None
221
 
222
+ base_index_dir = os.path.join(MEMORY_INDEX_PATH, "llamaindex", name)
223
 
224
  sessions_path = os.path.join(base_index_dir, "sessions_index.json")
225
  episodic_path = os.path.join(base_index_dir, "episodic_memory_index.json")
226
  semantic_path = os.path.join(base_index_dir, "semantic_memory_index.json")
227
 
228
+ # بررسی اینکه آیا فایل‌های ایندکس به صورت لوکال وجود دارند (یا از ابر دانلود شده‌اند)
229
  indices_exist = (
230
  os.path.exists(sessions_path) and
231
  os.path.exists(episodic_path) and
232
  os.path.exists(semantic_path)
233
  )
234
 
235
+ # اگر ایندکس وجود ندارد یا درخواست آپدیت داریم، بسازیم
236
  if update_memory_index or not indices_exist:
237
  try:
238
+ print(f"⚙️ Building/Updating indices locally for {name}...")
239
  os.makedirs(base_index_dir, exist_ok=True)
240
  build_memory_index(memory_data, data_args, name=name)
241
+
242
+ # **نکته مهم:** الان که فایل‌های ایندکس ساخته شدند، باید آنها را به ابر بفرستیم
243
+ # تا اگر سرور ریستارت شد، این فایل‌ها نپرند.
244
+ print("☁️ Syncing new indices to cloud...")
245
+ push_to_hub()
246
+
247
  except Exception as e:
248
  print(f"Warning: Error building memory index (skipping): {e}")
249
 
250
+ # بارگذاری ایندکس‌ها در حافظه رم (RAM) برای استفاده مدل
251
  if os.path.exists(sessions_path):
252
  try:
253
  storage_context = StorageContext.from_defaults(persist_dir=sessions_path)
 
270
 
271
 
272
  def summarize_memory_event_personality(data_args, memory_data, user_name):
273
+ # قبل از عملیات سنگین، وضعیت فعلی را ذخیره کن
274
  save_memory(memory_data)
275
 
276
  try:
277
+ # این تابع احتمالا فایل‌های ایندکس را تغییر می‌دهد
278
  updated_memory = summarize_memory(MEMORY_FILE_PATH, user_name, language='en')
279
+
280
+ # چون خلاصه سازی ممکن است ایندکس‌ها را تغییر دهد، یک سینک نهایی انجام می‌دهیم
281
+ push_to_hub()
282
+
283
  return updated_memory.get(user_name, {})
284
  except Exception as e:
285
  print(f"Error in summarize_memory: {e}")