Ranoosh / memory.py
mrwabnalas40's picture
Upload 70 files
a2cbfcc verified
raw
history blame
5.33 kB
# memory.py
# -*- coding: utf-8 -*-
"""
ذاكرة المستخدم/العامة + قاعدة المعرفة في ملف واحد، بدون أي استيراد عكسي (circular import).
يوفّر:
- load_memory(user_id) / save_memory(user_id, data)
- load_global_memory() / save_global_memory(data)
- load_knowledge_base() / save_knowledge_base(data)
- learn_from_unknown(prompt) / update_knowledge_base(prompt, answer)
"""
from __future__ import annotations
import json
import os
import tempfile
import threading
from typing import Any, Dict
# ========= مسارات التخزين =========
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# مجلد بيانات الذاكرة
DATA_DIR = os.path.join(BASE_DIR, "data")
os.makedirs(DATA_DIR, exist_ok=True)
# ملفات الذاكرة
GLOBAL_MEMORY_FILE = os.path.join(DATA_DIR, "global_memory.json")
USER_MEMORY_PREFIX = "memory_" # memory_<user_id>.json
# ملف قاعدة المعرفة (متوافق مع نسختك السابقة)
knowledge_base_path = os.path.join(BASE_DIR, "knowledge_base.json")
# قفل للتزامن
_lock = threading.RLock()
# ========= أدوات JSON آمنة =========
def _safe_write_json(path: str, data: Dict[str, Any]) -> None:
"""
كتابة ذرّية لضمان عدم تلف الملف حتى مع انقطاع مفاجئ.
"""
with _lock:
os.makedirs(os.path.dirname(path), exist_ok=True)
fd, tmp_path = tempfile.mkstemp(prefix=".tmp_", dir=os.path.dirname(path))
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
f.flush()
os.fsync(f.fileno())
os.replace(tmp_path, path)
finally:
if os.path.exists(tmp_path):
try:
os.remove(tmp_path)
except OSError:
pass
def _read_json(path: str) -> Dict[str, Any]:
"""
قراءة JSON بأمان. يعيد dict فارغ عند عدم وجود الملف أو في حال تلفه.
"""
with _lock:
if not os.path.exists(path):
return {}
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {}
def _user_file(user_id: str) -> str:
"""
تكوين اسم ملف آمن للمستخدم.
"""
safe_id = "".join(ch for ch in str(user_id) if ch.isalnum() or ch in ("-", "_")) or "default"
return os.path.join(DATA_DIR, f"{USER_MEMORY_PREFIX}{safe_id}.json")
# ========= واجهة الذاكرة (لـ learner.py) =========
def load_memory(user_id: str) -> Dict[str, Any]:
"""
قراءة ذاكرة مستخدم (dict).
"""
return _read_json(_user_file(user_id))
def save_memory(user_id: str, data: Dict[str, Any]) -> None:
"""
حفظ ذاكرة مستخدم (dict).
"""
if not isinstance(data, dict):
raise TypeError("save_memory expects a dict")
_safe_write_json(_user_file(user_id), data)
def load_global_memory() -> Dict[str, Any]:
"""
قراءة الذاكرة العامة (dict).
"""
return _read_json(GLOBAL_MEMORY_FILE)
def save_global_memory(data: Dict[str, Any]) -> None:
"""
حفظ الذاكرة العامة (dict).
"""
if not isinstance(data, dict):
raise TypeError("save_global_memory expects a dict")
_safe_write_json(GLOBAL_MEMORY_FILE, data)
# ========= واجهة قاعدة المعرفة (متوافقة مع نسختك السابقة) =========
def load_knowledge_base() -> Dict[str, Any]:
return _read_json(knowledge_base_path)
def save_knowledge_base(data: Dict[str, Any]) -> None:
if not isinstance(data, dict):
raise TypeError("save_knowledge_base expects a dict")
_safe_write_json(knowledge_base_path, data)
def learn_from_unknown(prompt: str):
"""
نفس السلوك السابق: يطبع رسالة ويطلب إجابة ليتم تعلمها.
"""
print("نورا: لا أملك إجابة لهذا السؤال حاليًا. سأبحث عن إجابة وأتعلم.")
answer = input("يرجى تزويدي بالإجابة المناسبة لأتعلمها: ")
if answer and answer.strip():
return answer
return None
def update_knowledge_base(prompt: str, answer: str) -> None:
kb = load_knowledge_base()
kb[prompt] = answer
save_knowledge_base(kb)
# ========= تصدير الأسماء =========
__all__ = [
"load_memory", "save_memory", "load_global_memory", "save_global_memory",
"load_knowledge_base", "save_knowledge_base",
"learn_from_unknown", "update_knowledge_base",
]
# ========= اختبار سريع =========
if __name__ == "__main__":
uid = "osama"
# اختبار ذاكرة المستخدم/العامة
u = load_memory(uid)
u["counter"] = u.get("counter", 0) + 1
save_memory(uid, u)
g = load_global_memory()
g["last_user"] = uid
save_global_memory(g)
print("User memory:", load_memory(uid))
print("Global memory:", load_global_memory())
# اختبار قاعدة المعرفة
update_knowledge_base("ما هي نورا؟", "مساعد ذكي")
print("KB size:", len(load_knowledge_base()))