forked from Rockachopa/Timmy-time-dashboard
This commit is contained in:
@@ -7,10 +7,11 @@ Also includes vector similarity utilities (cosine similarity, keyword overlap).
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import math
|
||||
import json
|
||||
import httpx # Import httpx for Ollama API calls
|
||||
|
||||
import httpx # Import httpx for Ollama API calls
|
||||
|
||||
from config import settings
|
||||
|
||||
@@ -20,14 +21,21 @@ logger = logging.getLogger(__name__)
|
||||
EMBEDDING_MODEL = None
|
||||
EMBEDDING_DIM = 384 # MiniLM dimension, will be overridden if Ollama model has different dim
|
||||
|
||||
|
||||
class OllamaEmbedder:
|
||||
"""Mimics SentenceTransformer interface for Ollama."""
|
||||
|
||||
def __init__(self, model_name: str, ollama_url: str):
|
||||
self.model_name = model_name
|
||||
self.ollama_url = ollama_url
|
||||
self.dimension = 0 # Will be updated after first call
|
||||
self.dimension = 0 # Will be updated after first call
|
||||
|
||||
def encode(self, sentences: str | list[str], convert_to_numpy: bool = False, normalize_embeddings: bool = True) -> list[list[float]] | list[float]:
|
||||
def encode(
|
||||
self,
|
||||
sentences: str | list[str],
|
||||
convert_to_numpy: bool = False,
|
||||
normalize_embeddings: bool = True,
|
||||
) -> list[list[float]] | list[float]:
|
||||
"""Generate embeddings using Ollama."""
|
||||
if isinstance(sentences, str):
|
||||
sentences = [sentences]
|
||||
@@ -43,9 +51,9 @@ class OllamaEmbedder:
|
||||
response.raise_for_status()
|
||||
embedding = response.json()["embedding"]
|
||||
if not self.dimension:
|
||||
self.dimension = len(embedding) # Set dimension on first successful call
|
||||
self.dimension = len(embedding) # Set dimension on first successful call
|
||||
global EMBEDDING_DIM
|
||||
EMBEDDING_DIM = self.dimension # Update global EMBEDDING_DIM
|
||||
EMBEDDING_DIM = self.dimension # Update global EMBEDDING_DIM
|
||||
all_embeddings.append(embedding)
|
||||
except httpx.RequestError as exc:
|
||||
logger.error("Ollama embeddings request failed: %s", exc)
|
||||
@@ -59,6 +67,7 @@ class OllamaEmbedder:
|
||||
return all_embeddings[0]
|
||||
return all_embeddings
|
||||
|
||||
|
||||
def _get_embedding_model():
|
||||
"""Lazy-load embedding model, preferring Ollama if configured."""
|
||||
global EMBEDDING_MODEL
|
||||
@@ -69,8 +78,13 @@ def _get_embedding_model():
|
||||
return EMBEDDING_MODEL
|
||||
|
||||
if settings.timmy_embedding_backend == "ollama":
|
||||
logger.info("MemorySystem: Using Ollama for embeddings with model %s", settings.ollama_embedding_model)
|
||||
EMBEDDING_MODEL = OllamaEmbedder(settings.ollama_embedding_model, settings.normalized_ollama_url)
|
||||
logger.info(
|
||||
"MemorySystem: Using Ollama for embeddings with model %s",
|
||||
settings.ollama_embedding_model,
|
||||
)
|
||||
EMBEDDING_MODEL = OllamaEmbedder(
|
||||
settings.ollama_embedding_model, settings.normalized_ollama_url
|
||||
)
|
||||
# We don't know the dimension until after the first call, so keep it default for now.
|
||||
# It will be updated dynamically in OllamaEmbedder.encode
|
||||
return EMBEDDING_MODEL
|
||||
@@ -79,7 +93,7 @@ def _get_embedding_model():
|
||||
from sentence_transformers import SentenceTransformer
|
||||
|
||||
EMBEDDING_MODEL = SentenceTransformer("all-MiniLM-L6-v2")
|
||||
EMBEDDING_DIM = 384 # Reset to MiniLM dimension
|
||||
EMBEDDING_DIM = 384 # Reset to MiniLM dimension
|
||||
logger.info("MemorySystem: Loaded local embedding model (all-MiniLM-L6-v2)")
|
||||
except ImportError:
|
||||
logger.warning("MemorySystem: sentence-transformers not installed, using fallback")
|
||||
@@ -107,13 +121,12 @@ def embed_text(text: str) -> list[float]:
|
||||
if model and model is not False:
|
||||
embedding = model.encode(text)
|
||||
# Ensure it's a list of floats, not numpy array
|
||||
if hasattr(embedding, 'tolist'):
|
||||
if hasattr(embedding, "tolist"):
|
||||
return embedding.tolist()
|
||||
return embedding
|
||||
return _simple_hash_embedding(text)
|
||||
|
||||
|
||||
|
||||
def cosine_similarity(a: list[float], b: list[float]) -> float:
|
||||
"""Calculate cosine similarity between two vectors."""
|
||||
dot = sum(x * y for x, y in zip(a, b, strict=False))
|
||||
|
||||
Reference in New Issue
Block a user