Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions memory_thread/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
from rich.panel import Panel
from rich.text import Text
from rich import print as rprint
from dotenv import load_dotenv

load_dotenv()

# ═══════════════════════════════════════════════════════════════════════════════
# WINDOWS UTF-8 FIX — no more Wakandan runes
Expand Down Expand Up @@ -216,6 +219,26 @@ def _enter_chat():
console.print("[dim]Goodbye.[/dim]")
break

# Slash commands (e.g., /provider use groq)
if raw.startswith("/"):
import shlex
import subprocess
try:
args = shlex.split(raw[1:])
if not args:
continue

# Construct command to invoke same entry point
cmd_args = [sys.executable, sys.argv[0]] if sys.argv[0].endswith(".py") else [sys.argv[0]]
cmd_args.extend(args)

subprocess.run(cmd_args)
console.print()
continue
except Exception as e:
console.print(f"[red]Command failed: {e}[/red]")
continue

# Chat handles EVERYTHING: remember, extract, contradict, respond
try:
response = client.chat(raw)
Expand Down
20 changes: 15 additions & 5 deletions memory_thread/db/qdrant_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,21 @@ def upsert(self, collection_name: str, points: List[Dict[str, Any]]):
def search(self, collection_name: str, query_vector: List[float], limit: int = 5) -> List[Any]:
"""Search for similar vectors."""
try:
return self.client.search(
collection_name=collection_name,
query_vector=query_vector,
limit=limit
)
# Fallback for deprecated 'search' if needed, or use 'query_points' for future compat
if hasattr(self.client, "search"):
return self.client.search(
collection_name=collection_name,
query_vector=query_vector,
limit=limit
)
elif hasattr(self.client, "query_points"):
return self.client.query_points(
collection_name=collection_name,
query=query_vector,
limit=limit
).points
else:
raise AttributeError("QdrantClient has no search method")
except Exception as e:
from memory_thread.utils.logger import get_logger
log = get_logger(__name__)
Expand Down
17 changes: 12 additions & 5 deletions memory_thread/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ def _generate_embedding(self, text: str) -> List[float]:
try:
from memory_thread.utils.embeddings import generate_embeddings
return generate_embeddings(tuple([text]))[0]
except ImportError:
except ImportError as e:
# sentence-transformers not installed
log.debug("sentence-transformers not installed, using zero vector")
log.warning(f"sentence-transformers failed: {e}")
return [0.0] * settings.EMBEDDING_DIMENSION
except Exception as e:
# Return zeros if embedding fails
Expand All @@ -188,8 +188,8 @@ def _extract_entities(self, text: str) -> List[Dict]:
try:
from memory_thread.services.hybrid_ner_service import extract_entities
return extract_entities(text)
except ImportError:
log.warning("hybrid_ner_service not available, skipping entity extraction")
except ImportError as e:
log.warning(f"hybrid_ner_service not available (ImportError: {e}), skipping entity extraction")
return []
except Exception as e:
log.warning(f"Entity extraction failed: {e}")
Expand Down Expand Up @@ -439,6 +439,9 @@ def remember(
def _persist_to_postgres(self, entity_id: uuid.UUID, content: str,
memory_type: str, state: EntityState, event: Event):
"""Persist memory to PostgreSQL."""
# Ensure event is persisted first to satisfy foreign key constraint
self.tms.persist_event(event)

with self._pg.get_cursor() as cur:
# Upsert into memories table (or entity_state)
cur.execute("""
Expand Down Expand Up @@ -1130,11 +1133,13 @@ def chat(

# Check explicit env override first
env_provider = os.environ.get("MT_PROVIDER")
if env_provider:
if env_provider and env_provider != "auto":
active_provider = env_provider.lower()
log.info(f"Using provider from ENV: {active_provider}")
else:
# Ensure we respect the vault's setting (which includes env vars now)
active_provider = vault.get_active_provider(user_id)
log.info(f"Using provider from Vault: {active_provider}")


log.debug(f"Chat request - Provider: {active_provider}, User: {user_id}")
Expand Down Expand Up @@ -1296,6 +1301,8 @@ def _generate_cloud(self, prompt: str, provider: str = "auto") -> str:
key = creds.get("api_key") if creds else os.environ.get("GROQ_API_KEY")
model = creds.get("model") if creds else os.environ.get("GROQ_MODEL", "llama-3.3-70b-versatile")

log.info(f"Groq API Key Check: Vault={'Found' if creds else 'Missing'}, Env={'Found' if os.environ.get('GROQ_API_KEY') else 'Missing'}")

if key:
log.info(f"Using Groq ({model})")
response = requests.post(
Expand Down
13 changes: 11 additions & 2 deletions memory_thread/services/hybrid_ner_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,17 @@ def extract_entities(text: str):
return ner_cache.get(text_hash)

# Run all stages
regex_entities = regex_ner(text)
spacy_entities, confidence = spacy_ner(text)
try:
regex_entities = regex_ner(text)
except Exception as e:
print(f"Regex NER failed: {e}")
regex_entities = []

try:
spacy_entities, confidence = spacy_ner(text)
except Exception as e:
print(f"Spacy NER failed: {e}")
spacy_entities, confidence = [], 0.0

final_entities = regex_entities + spacy_entities

Expand Down
2 changes: 1 addition & 1 deletion memory_thread/utils/embeddings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _get_local_model():
log.warning("sentence-transformers not installed. pip install sentence-transformers")
return None
except Exception as e:
log.warning(f"Failed to load embedding model: {e}")
log.warning(f"Failed to load embedding model: {e}", exc_info=True)
return None


Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ prometheus-client
fastapi
uvicorn
zmq
sentence-transformers