Merge pull request #3 from ClaudioDrews/fix/embedding-provider-agnostic
fix: make embedding provider-agnostic via env vars (closes #1)
This commit is contained in:
commit
bae035f8fb
11
.env.example
11
.env.example
|
|
@ -46,6 +46,17 @@ REFLECTION_LOG_PATH=/home/your-user/.hermes/logs/reflection_trigger.log
|
|||
# MaaS env path (reflection_trigger.py loads env from this location)
|
||||
MAA_ENV_PATH=/home/your-user/.env
|
||||
|
||||
# ── Embedding Backend ─────────────────────────────────
|
||||
|
||||
# Default: OpenRouter with Qwen3-Embedding-8B.
|
||||
# Recommended model: multilingual (excellent for non-English content),
|
||||
# high-quality 4096d embeddings, fast inference, affordable pricing.
|
||||
# To use a local model (Ollama, vLLM, llama.cpp), set both vars:
|
||||
# EMBEDDING_API_BASE=http://host.docker.internal:11434/v1
|
||||
# EMBEDDING_MODEL=nomic-embed-text
|
||||
# EMBEDDING_API_BASE=https://openrouter.ai/api/v1
|
||||
# EMBEDDING_MODEL=qwen/qwen3-embedding-8b
|
||||
|
||||
# ── Strongly Recommended ──────────────────────────────
|
||||
|
||||
# LLM extraction token limit — 1024 is too small, causes fabric truncation
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"""
|
||||
Embedding client via OpenRouter.
|
||||
Embedding client. Provider-agnostic — defaults to OpenRouter, configurable
|
||||
via EMBEDDING_API_BASE and EMBEDDING_MODEL for local Ollama/vLLM/llama.cpp.
|
||||
Mandatory dimension validation.
|
||||
"""
|
||||
import os
|
||||
|
|
@ -11,13 +12,17 @@ logger = logging.getLogger("cognitive-worker.embedding")
|
|||
|
||||
OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "")
|
||||
EMBEDDING_DIMS = int(os.environ.get("EMBEDDING_DIMS", "4096"))
|
||||
EMBEDDING_MODEL = "qwen/qwen3-embedding-8b"
|
||||
API_BASE = "https://openrouter.ai/api/v1"
|
||||
EMBEDDING_API_BASE = os.environ.get(
|
||||
"EMBEDDING_API_BASE", "https://openrouter.ai/api/v1"
|
||||
)
|
||||
EMBEDDING_MODEL = os.environ.get(
|
||||
"EMBEDDING_MODEL", "qwen/qwen3-embedding-8b"
|
||||
)
|
||||
|
||||
|
||||
async def get_embedding(text: str) -> list[float]:
|
||||
"""
|
||||
Generates embedding via OpenRouter.
|
||||
Generates embedding via the configured backend.
|
||||
Validates that the returned dimensions match EMBEDDING_DIMS.
|
||||
"""
|
||||
if not OPENROUTER_API_KEY:
|
||||
|
|
@ -38,7 +43,7 @@ async def get_embedding(text: str) -> list[float]:
|
|||
|
||||
async with httpx.AsyncClient(timeout=60) as client:
|
||||
resp = await client.post(
|
||||
f"{API_BASE}/embeddings",
|
||||
f"{EMBEDDING_API_BASE}/embeddings",
|
||||
headers=headers,
|
||||
json=payload,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,20 @@
|
|||
|
||||
> **Service:** Qdrant 1.17+ (Docker)
|
||||
> **Collection:** `knowledge_base` (4096d Cosine + BM25 sparse)
|
||||
> **Embedding:** Qwen3-Embedding-8B via OpenRouter
|
||||
> **Embedding:** Qwen3-Embedding-8B via OpenRouter (default; configurable)
|
||||
> **Endpoint:** `http://localhost:6333`
|
||||
|
||||
## Why Qwen3-Embedding-8B
|
||||
|
||||
The default embedding model is **Qwen3-Embedding-8B** for four reasons:
|
||||
|
||||
1. **Multilingual** — strong performance across 50+ languages, including Portuguese, Spanish, and other non-English content common in real-world agent use
|
||||
2. **Quality** — 4096-dimensional embeddings with high semantic fidelity; consistently ranks near the top of the MTEB leaderboard
|
||||
3. **Speed** — fast inference at 8B parameters, suitable for hourly ingestion pipelines without bottlenecking the ARQ worker
|
||||
4. **Cost** — affordable via OpenRouter ($0.025/1M tokens at time of writing); a full wiki re-index costs cents, not dollars
|
||||
|
||||
Users can switch to any OpenAI-compatible embedding API by setting `EMBEDDING_API_BASE` and `EMBEDDING_MODEL` in `.env`. If changing models, ensure `EMBEDDING_DIMS` matches both the new model's output and the Qdrant collection schema.
|
||||
|
||||
## What it stores
|
||||
|
||||
All knowledge that benefits from semantic search — wiki pages, session transcripts, raw documents, technical references. Content is ingested via the continuous ingest pipeline (hourly) and the wiki agent (scheduled).
|
||||
|
|
@ -75,7 +86,7 @@ Redis queue (ARQ job)
|
|||
│
|
||||
▼
|
||||
ARQ Worker (Docker)
|
||||
│ embed via Qwen3-Embedding-8B (OpenRouter)
|
||||
│ embed via configured backend (default: Qwen3-Embedding-8B)
|
||||
│ get_sparse_embedding() → BM25 (fastembed, local)
|
||||
▼
|
||||
Qdrant upsert (with dedup check)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
- Hermes Agent 0.14.0+ (tested on 0.15.2)
|
||||
- Python 3.11+
|
||||
- Docker 24.0+
|
||||
- OpenRouter API key (for embeddings and LLM extraction)
|
||||
- OpenRouter API key (or configured embedding backend — see [Layer 5: Qdrant](../layers/05-qdrant.md))
|
||||
- 16 GB RAM recommended (8 GB minimum)
|
||||
|
||||
## Installation
|
||||
|
|
@ -80,6 +80,10 @@ ICARUS_EXTRACTION_MAX_TOKENS=4096
|
|||
ICARUS_EXTRACTION_MODEL=deepseek/deepseek-v4-flash
|
||||
EMBEDDING_DIMS=4096
|
||||
|
||||
# Optional — Embedding backend (defaults to OpenRouter)
|
||||
# EMBEDDING_API_BASE=https://openrouter.ai/api/v1
|
||||
# EMBEDDING_MODEL=qwen/qwen3-embedding-8b
|
||||
|
||||
# Optional
|
||||
ICARUS_OBSIDIAN=1
|
||||
ICARUS_RESULT_MAX_CHARS=500
|
||||
|
|
|
|||
Loading…
Reference in New Issue