import hashlib
import random
from typing import Any, Dict, List, Optional
from perf.config import get_model_dimension, get_test_mode, is_mock_mode
class TestEmbeddingService:
@classmethod
def get_dimension(cls) -> int:
return get_model_dimension()
@classmethod
def embed(cls, text: str) -> Dict[str, Any]:
dimension = cls.get_dimension()
seed = int(hashlib.md5(text.encode()).hexdigest()[:8], 16) % (2**31)
random.seed(seed)
vector = [random.uniform(-1, 1) for _ in range(dimension)]
magnitude = sum(v**2 for v in vector) ** 0.5
if magnitude > 0:
vector = [v / magnitude for v in vector]
return {
"embedding": vector,
"dimension": len(vector),
}
@classmethod
def embed_batch(cls, texts: List[str]) -> List[Dict[str, Any]]:
return [cls.embed(text) for text in texts]
@classmethod
def similarity(cls, text1: str, text2: str) -> Dict[str, Any]:
emb1 = cls.embed(text1)
emb2 = cls.embed(text2)
dot_product = sum(a * b for a, b in zip(emb1["embedding"], emb2["embedding"]))
return {
"score": round(dot_product, 6),
"metric": "cosine",
}
@classmethod
def cosine_similarity(cls, vec1: List[float], vec2: List[float]) -> float:
dot_product = sum(a * b for a, b in zip(vec1, vec2))
return round(dot_product, 6)
class AdaptiveEmbeddingService:
def __init__(self):
self.test_mode = get_test_mode()
self._mock_service = TestEmbeddingService
self._real_service: Optional[Any] = None
def _get_real_service(self) -> Optional[Any]:
if self._real_service is None:
try:
from perf.real_service import RealEmbeddingServiceWithFallback
self._real_service = RealEmbeddingServiceWithFallback()
except ImportError:
self._real_service = None
return self._real_service
def get_dimension(self) -> int:
if is_mock_mode():
return self._mock_service.get_dimension()
real = self._get_real_service()
if real is not None and not real.is_using_fallback():
return real.get_dimension()
return self._mock_service.get_dimension()
def embed(self, text: str) -> Dict[str, Any]:
if is_mock_mode():
return self._mock_service.embed(text)
real = self._get_real_service()
if real is not None and not real.is_using_fallback():
return real.embed(text)
return self._mock_service.embed(text)
def embed_batch(self, texts: List[str]) -> List[Dict[str, Any]]:
if is_mock_mode():
return self._mock_service.embed_batch(texts)
real = self._get_real_service()
if real is not None and not real.is_using_fallback():
return real.embed_batch(texts)
return self._mock_service.embed_batch(texts)
def similarity(self, text1: str, text2: str) -> Dict[str, Any]:
if is_mock_mode():
return self._mock_service.similarity(text1, text2)
real = self._get_real_service()
if real is not None and not real.is_using_fallback():
return real.similarity(text1, text2)
return self._mock_service.similarity(text1, text2)
def is_using_real_engine(self) -> bool:
if is_mock_mode():
return False
real = self._get_real_service()
if real is not None:
return not real.is_using_fallback()
return False
def is_using_fallback(self) -> bool:
if is_mock_mode():
return True
real = self._get_real_service()
if real is not None:
return real.is_using_fallback()
return True
def get_embedding_service() -> AdaptiveEmbeddingService:
return AdaptiveEmbeddingService()
def is_real_mode() -> bool:
return not is_mock_mode()