feat(semantic_search): support local OpenAI-compatible embedding servers (#22)

Adds a LocalEmbedder that targets any OpenAI-compatible embedding
endpoint (Ollama, llama.cpp, vLLM, LM Studio, ...). Zero new
Python dependencies — reuses the existing openai SDK with a
custom base_url. Defaults to Ollama at http://localhost:11434/v1
with nomic-embed-text @ 768 dims; override via env vars for other
servers/models (e.g. bge-m3 @ 1024 dims for better Turkish).

Refactors the shared encode/similarity logic into a private base
class so OpenRouterEmbedder and LocalEmbedder don't duplicate ~50
lines. OpenRouter keeps its ranking headers; local sends none.

Adds get_embedder() factory selecting the provider based on
EMBEDDING_PROVIDER (local) or OPENROUTER_API_KEY presence, and
is_semantic_search_available() that returns True for either path.
mcp_server_main now uses these so the semantic_search tool is
exposed when only a local server is configured.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
saidsurucu
2026-05-03 01:50:47 +03:00
co-authored by Claude Opus 4.7
parent 42731a2c03
commit fb29146755
4 changed files with 227 additions and 95 deletions
+18 -2
View File
@@ -1,7 +1,23 @@
# semantic_search/__init__.py
from .embedder import OpenRouterEmbedder, is_openrouter_available
from .embedder import (
OpenRouterEmbedder,
LocalEmbedder,
get_embedder,
is_openrouter_available,
is_local_embedding_configured,
is_semantic_search_available,
)
from .vector_store import VectorStore
from .processor import DocumentProcessor
__all__ = ['OpenRouterEmbedder', 'is_openrouter_available', 'VectorStore', 'DocumentProcessor']
__all__ = [
'OpenRouterEmbedder',
'LocalEmbedder',
'get_embedder',
'is_openrouter_available',
'is_local_embedding_configured',
'is_semantic_search_available',
'VectorStore',
'DocumentProcessor',
]