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:
Claudio Drews 2026-06-02 10:11:58 -03:00 committed by GitHub
commit bae035f8fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 39 additions and 8 deletions

View File

@ -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

View File

@ -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,
)

View File

@ -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)

View File

@ -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