#!/usr/bin/env python3 """ Smoke-Test für den Mem0-Sidecar — VOR und NACH jedem mem0/chromadb-Upgrade laufen lassen. Prüft genau die Pfade, die mem0-INTERNA nutzen (LLM-Extraktion/NoThink, Auto-Einordnung, Embeddings/Suche, Roh-Chroma-Graph). Nutzt eine WEGWERF-Collection unter /tmp — das echte Gedächtnis (/srv/models/mem0) wird NICHT angefasst. Aufruf: ~/.mem0/venv/bin/python ~/mission-control-v2/mem0_service/smoke_test.py Exit 0 = alles grün, sonst 1. """ import os import shutil import sys import tempfile import time # WICHTIG: Env vor dem Import von app setzen (app liest die Pfade beim Modul-Load). _TMP = tempfile.mkdtemp(prefix="mem0_smoke_") os.environ["MEM0_CHROMA_PATH"] = os.path.join(_TMP, "chroma") os.environ["MEM0_HISTORY_DB"] = os.path.join(_TMP, "history.db") os.environ["MEM0_COLLECTION"] = f"smoke_{int(time.time())}" sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import app _fails: list[str] = [] def check(name: str, cond: bool, detail: str = "") -> None: print(("PASS" if cond else "FAIL"), "—", name, ("" if cond else f":: {detail}")) if not cond: _fails.append(name) def main() -> int: app.mem() # Memory bauen (öffnet Chroma, pingt Modelle) # 1) Verbatim add + Rücklesen r = app.add_memory(app.MemIn(content="Smoke: der Himmel ist blau.", category="knowledge", source="smoke")) check("verbatim add + get", bool(r.get("id")) and "blau" in r.get("content", ""), str(r)[:160]) # 2) Embeddings / semantische Suche (Bedeutung, nicht Wort) res = app.list_memory(q="Welche Farbe hat der Himmel?") check("semantische Suche", any("blau" in i.get("content", "") for i in res), str(res)[:160]) # 3) Auto-Lernen: LLM-Extraktion (NoThink) + Deutsch erzwungen lr = app.learn(app.LearnIn(text="Ich heiße Max und programmiere am liebsten in Go.", source="smoke")) items = lr.get("results", []) check("Auto-Lernen extrahiert Fakten", len(items) > 0, str(lr)[:160]) joined = " ".join((i.get("content") or "") for i in items).lower() check("Extraktion auf Deutsch", any(w in joined for w in ("heißt", "programmiert", "mag", "bevorzugt", "name", "nutzt")), joined[:160]) # 4) Auto-Einordnung in die 4 gültigen Kategorien cats = {i.get("category") for i in items if i.get("category")} check("Auto-Einordnung gültige Kategorie", bool(cats) and cats <= set(app.CATEGORIES), str(cats)) # 5) Graph aus den Roh-Embeddings (Chroma-Interna) g = app.graph() check("Graph liefert Knoten", len(g.get("nodes", [])) >= 1, str({k: len(v) for k, v in g.items()})) print("\n" + ("ALLE TESTS GRÜN ✓" if not _fails else f"FEHLGESCHLAGEN: {_fails}")) return 0 if not _fails else 1 if __name__ == "__main__": try: code = main() finally: shutil.rmtree(_TMP, ignore_errors=True) sys.exit(code)