fix: add dynamic dimension detection for Ollama embedding models
This fixes dimension mismatch errors when using embedding models with non-standard dimensions (e.g., qwen3-embedding:4b produces 2560-dim vectors instead of the hardcoded 768). Changes: - OllamaEmbeddingProvider: Detect dimensions dynamically by generating test embedding instead of hardcoding to 768 - qdrant_client: Call dimension detection before collection creation - app.py: Initialize Qdrant collection before starting background tasks in streamable-http transport path - tests: Fix integration tests to properly mock EmbeddingService wrapper Fixes dimension mismatch error: "could not broadcast input array from shape (2560,) into shape (768,)" All integration tests passing (6/6). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ class OllamaEmbeddingProvider(EmbeddingProvider):
|
||||
base_url: str,
|
||||
model: str = "nomic-embed-text",
|
||||
verify_ssl: bool = True,
|
||||
timeout=httpx.Timeout(timeout=120, connect=5),
|
||||
):
|
||||
"""
|
||||
Initialize Ollama embedding provider.
|
||||
@@ -29,8 +30,8 @@ class OllamaEmbeddingProvider(EmbeddingProvider):
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.model = model
|
||||
self.verify_ssl = verify_ssl
|
||||
self.client = httpx.AsyncClient(verify=verify_ssl, timeout=30.0)
|
||||
self._dimension = 768 # nomic-embed-text default
|
||||
self.client = httpx.AsyncClient(verify=verify_ssl, timeout=timeout)
|
||||
self._dimension: int | None = None # Will be detected dynamically
|
||||
logger.info(
|
||||
f"Initialized Ollama provider: {base_url} (model={model}, verify_ssl={verify_ssl})"
|
||||
)
|
||||
@@ -73,13 +74,36 @@ class OllamaEmbeddingProvider(EmbeddingProvider):
|
||||
embeddings.append(embedding)
|
||||
return embeddings
|
||||
|
||||
async def _detect_dimension(self):
|
||||
"""
|
||||
Detect embedding dimension by generating a test embedding.
|
||||
|
||||
This method queries the model to determine the actual dimension
|
||||
instead of relying on hardcoded values.
|
||||
"""
|
||||
if self._dimension is None:
|
||||
logger.debug(f"Detecting embedding dimension for model {self.model}...")
|
||||
test_embedding = await self.embed("test")
|
||||
self._dimension = len(test_embedding)
|
||||
logger.info(
|
||||
f"Detected embedding dimension: {self._dimension} for model {self.model}"
|
||||
)
|
||||
|
||||
def get_dimension(self) -> int:
|
||||
"""
|
||||
Get embedding dimension.
|
||||
|
||||
Returns:
|
||||
Vector dimension (768 for nomic-embed-text)
|
||||
Vector dimension for the configured model
|
||||
|
||||
Raises:
|
||||
RuntimeError: If dimension not detected yet (call _detect_dimension first)
|
||||
"""
|
||||
if self._dimension is None:
|
||||
raise RuntimeError(
|
||||
f"Embedding dimension not detected yet for model {self.model}. "
|
||||
"Call _detect_dimension() first or generate an embedding."
|
||||
)
|
||||
return self._dimension
|
||||
|
||||
def _check_model_is_loaded(self, autoload: bool = True):
|
||||
|
||||
Reference in New Issue
Block a user