Spaces:
Sleeping
Sleeping
File size: 4,011 Bytes
3be03dd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | """
Backend connectivity for the memory system.
Provides:
- Sentence-transformer embedding helpers (_load_embedder, _embed)
- Supabase connection management (_get_supabase, _using_supabase)
- SQLite local fallback connector (_get_sqlite)
"""
import os
import sqlite3
import threading
from functools import lru_cache
# ββ Embedding helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@lru_cache(maxsize=1)
def _load_embedder():
"""
Load sentence-transformers model once, cache it.
all-MiniLM-L6-v2: 80MB, fast, 384-dim vectors β perfect for this.
Returns None if sentence-transformers not installed.
"""
try:
from sentence_transformers import SentenceTransformer
return SentenceTransformer("all-MiniLM-L6-v2")
except ImportError:
return None
def _embed(text: str) -> list[float] | None:
"""
Convert text to a 384-dimensional vector.
Returns None if embedding model not available β callers handle this.
"""
model = _load_embedder()
if model is None:
return None
return model.encode(text[:500], normalize_embeddings=True).tolist()
# ββ Supabase connection ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
_supabase_client = None
_supabase_lock = threading.Lock()
def _get_supabase():
"""
Return a Supabase client, or None if not configured.
Uses a module-level singleton β creates the connection once.
Thread-safe via lock.
"""
global _supabase_client
with _supabase_lock:
if _supabase_client is not None:
return _supabase_client
url = os.getenv("SUPABASE_URL", "")
key = os.getenv("SUPABASE_KEY", "")
if not url or not key:
return None # not configured β caller falls back to local
try:
from supabase import create_client
_supabase_client = create_client(url, key)
print("[memory] Connected to Supabase")
return _supabase_client
except Exception as e:
print(f"[memory] Supabase connection failed: {e} β using local fallback")
return None
def _using_supabase() -> bool:
return _get_supabase() is not None
# ββ Local SQLite fallback paths ββββββββββββββββββββββββββββββββββββββββββββββββ
_DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data")
_SQLITE_PATH = os.path.join(_DATA_DIR, "memory.db")
def _get_sqlite():
"""Return a SQLite connection, creating the DB and tables if needed."""
os.makedirs(_DATA_DIR, exist_ok=True)
conn = sqlite3.connect(_SQLITE_PATH, check_same_thread=False)
conn.execute("""
CREATE TABLE IF NOT EXISTS episodes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
ticker TEXT,
recommendation TEXT,
confidence INTEGER,
price_at_time REAL,
report TEXT,
outcome TEXT,
created_at TEXT
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS stock_analyses (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
ticker TEXT,
recommendation TEXT,
confidence INTEGER,
report TEXT,
created_at TEXT
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS user_preferences (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
preference TEXT,
created_at TEXT
)
""")
conn.commit()
return conn
|