feat(memory): Complete fastembed migration — fix vector_search.py bug, update all model names, fix test mocks

Co-Authored-By: @memory <memory@aipass>
This commit is contained in:
AIOSAI
2026-05-07 17:53:34 -07:00
co-authored by @memory
parent 7dc84c3e31
commit 6c3e965414
7 changed files with 33 additions and 62 deletions
@@ -251,14 +251,14 @@ def process_file_to_vectors(
# Chunk content
chunks = chunk_content(content, chunk_size, chunk_overlap)
# Import ChromaDB and sentence transformers (late import for venv compatibility)
# Import ChromaDB and fastembed (late import for venv compatibility)
try:
import chromadb
from sentence_transformers import SentenceTransformer
from fastembed import TextEmbedding
client = chromadb.PersistentClient(path=str(CHROMA_PATH))
collection = client.get_or_create_collection(name=collection_name)
model = SentenceTransformer("all-MiniLM-L6-v2")
model = TextEmbedding("sentence-transformers/all-MiniLM-L6-v2")
# Generate embeddings and store
documents = []
@@ -280,7 +280,7 @@ def process_file_to_vectors(
)
# Batch encode
embeddings = model.encode(documents).tolist()
embeddings = [e.tolist() for e in model.embed(documents)]
# Upsert (update if exists, insert if not)
collection.upsert(documents=documents, embeddings=embeddings, ids=ids, metadatas=metadatas)
@@ -24,8 +24,7 @@ Design:
Dependencies (optional):
- chromadb
- sentence-transformers
- torch
- fastembed
"""
from typing import List, Dict, Any
@@ -56,7 +55,7 @@ class QueryEncoder:
Uses all-MiniLM-L6-v2 model with same settings.
"""
def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
def __init__(self, model_name: str = "sentence-transformers/all-MiniLM-L6-v2"):
"""
Initialize query encoder
@@ -64,28 +63,17 @@ class QueryEncoder:
model_name: HuggingFace model identifier (must match embedder.py)
Raises:
ImportError: If sentence-transformers or torch are not installed
ImportError: If fastembed is not installed
"""
# Late imports (heavy optional dependencies)
try:
import torch
from sentence_transformers import SentenceTransformer
from fastembed import TextEmbedding
except ImportError as e:
logger.info(f"[vector_search] Optional ML dependencies not available: {e}")
raise ImportError(
f"Search requires sentence-transformers and torch. "
f"Install with: pip install sentence-transformers torch. "
f"Original error: {e}"
)
raise ImportError(f"Search requires fastembed. Install with: pip install fastembed. Original error: {e}")
self.model_name = model_name
self.model = SentenceTransformer(model_name)
# GPU optimization if available
self.use_gpu = torch.cuda.is_available()
if self.use_gpu:
self.model = self.model.to("cuda")
self.model = TextEmbedding(model_name)
self.dimension = 384 # all-MiniLM-L6-v2 output dimension
def encode(self, query: str) -> List[float]:
@@ -98,21 +86,8 @@ class QueryEncoder:
Returns:
384-dimensional embedding as list
"""
import torch
# Encode with same settings as embedder.py
embedding = self.model.encode(
query,
convert_to_tensor=False, # Return numpy
normalize_embeddings=True, # Critical for L2 distance
show_progress_bar=False,
)
# Cleanup GPU memory if used
if self.use_gpu:
torch.cuda.empty_cache()
return embedding.tolist()
embeddings = list(self.model.embed([query]))
return embeddings[0].tolist()
# Global encoder instance (singleton pattern)
@@ -32,7 +32,7 @@ def main():
from fastembed import TextEmbedding
model = TextEmbedding("all-MiniLM-L6-v2")
model = TextEmbedding("sentence-transformers/all-MiniLM-L6-v2")
sorted_pairs = sorted(enumerate(texts), key=lambda x: len(x[1]))
sorted_indices, sorted_texts = zip(*sorted_pairs)
@@ -30,7 +30,7 @@ logger = get_system_logger()
class EmbeddingService:
"""Embedding service using fastembed (ONNX runtime, no torch dependency)."""
def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
def __init__(self, model_name: str = "sentence-transformers/all-MiniLM-L6-v2"):
try:
from fastembed import TextEmbedding
except ImportError as e: