From df591e4e01c7e0988fc31a28eefd2acc48781194 Mon Sep 17 00:00:00 2001 From: serversdown Date: Sun, 21 Jun 2026 04:19:26 +0000 Subject: [PATCH] feat: decouple embeddings from the local-chat backend (EMBED_BASE_URL) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Embeddings shared LOCAL_BASE_URL with the local chat backend (the 3090's Ollama), so the 3090 being powered off killed all chat (every turn embeds to recall + to store). Add a separate EMBED_BASE_URL (defaults to LOCAL_BASE_URL, so existing setups are unchanged) and use it in llm.embed. Deployed: a user-level Ollama (CPU) now runs nomic-embed-text on lyra-cortex itself; EMBED_BASE_URL points at 127.0.0.1:11434 while LOCAL_BASE_URL still points the local chat backend at the 3090. Local embeddings verified identical to the 3090's (cosine 0.999994, 768-dim) so existing vectors stay valid — no re-embed. Co-Authored-By: Claude Opus 4.8 (1M context) --- .env.example | 4 ++++ lyra/config.py | 4 ++++ lyra/llm.py | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 3d1661b..535d38c 100644 --- a/.env.example +++ b/.env.example @@ -22,3 +22,7 @@ SUMMARY_BACKEND=local # Where Lyra stores her memory. LYRA_DB_PATH=data/lyra.db + +# Optional: run embeddings on a separate always-on Ollama (decoupled from +# LOCAL_BASE_URL, which serves local chat). Defaults to LOCAL_BASE_URL if unset. +# EMBED_BASE_URL=http://127.0.0.1:11434 diff --git a/lyra/config.py b/lyra/config.py index e5ee22d..e36f51e 100644 --- a/lyra/config.py +++ b/lyra/config.py @@ -22,6 +22,7 @@ class Config: embed_backend: str # "cloud" (OpenAI) or "local" (Ollama) embed_model: str # OpenAI embedding model local_embed_model: str # Ollama embedding model + embed_base_url: str # Ollama endpoint for embeddings (own box, decoupled from local chat) summary_backend: str # "local" or "cloud" — backend used to compact memory db_path: Path @@ -38,6 +39,9 @@ def load() -> Config: embed_backend=os.getenv("EMBED_BACKEND", "cloud").lower(), embed_model=os.getenv("EMBED_MODEL", "text-embedding-3-small"), local_embed_model=os.getenv("LOCAL_EMBED_MODEL", "nomic-embed-text"), + # Embeddings can live on their own always-on box, separate from the local + # chat backend. Defaults to LOCAL_BASE_URL so existing setups are unchanged. + embed_base_url=os.getenv("EMBED_BASE_URL", os.getenv("LOCAL_BASE_URL", "http://localhost:11434")), summary_backend=os.getenv("SUMMARY_BACKEND", "local").lower(), db_path=Path(os.getenv("LYRA_DB_PATH", "data/lyra.db")), ) diff --git a/lyra/llm.py b/lyra/llm.py index fa51d7b..de02efe 100644 --- a/lyra/llm.py +++ b/lyra/llm.py @@ -173,7 +173,7 @@ def embed(texts: list[str]) -> list[list[float]]: cfg = load() if cfg.embed_backend == "local": resp = httpx.post( - f"{cfg.local_base_url}/api/embed", + f"{cfg.embed_base_url}/api/embed", json={"model": cfg.local_embed_model, "input": texts}, timeout=120, )