import os
import sys
from typing import Any, Dict, List, Optional
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from perf.config import get_api_base_url, get_model_dimension, get_model_name
class RealEmbeddingService:
def __init__(self, base_url: Optional[str] = None):
self.base_url = base_url or get_api_base_url()
self.model_name = get_model_name()
self.dimension = get_model_dimension()
self._session = None
def _get_session(self):
if self._session is None:
import requests
self._session = requests.Session()
return self._session
def get_dimension(self) -> int:
return self.dimension
def embed(self, text: str) -> Dict[str, Any]:
import requests
session = self._get_session()
response = session.post(
f"{self.base_url}/api/v1/embed", json={"text": text}, timeout=30.0
)
response.raise_for_status()
return response.json()
def embed_batch(self, texts: List[str]) -> List[Dict[str, Any]]:
import requests
session = self._get_session()
response = session.post(
f"{self.base_url}/api/v1/embed/batch", json={"texts": texts}, timeout=60.0
)
response.raise_for_status()
result = response.json()
return result.get("embeddings", [])
def similarity(self, text1: str, text2: str) -> Dict[str, Any]:
import requests
session = self._get_session()
response = session.post(
f"{self.base_url}/api/v1/similarity",
json={"source": text1, "target": text2},
timeout=30.0,
)
response.raise_for_status()
return response.json()
def cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
if len(vec1) != len(vec2):
raise ValueError("Vectors must have the same length")
dot_product = sum(a * b for a, b in zip(vec1, vec2))
norm1 = sum(a * a for a in vec1) ** 0.5
norm2 = sum(b * b for b in vec2) ** 0.5
if norm1 == 0 or norm2 == 0:
return 0.0
return dot_product / (norm1 * norm2)
class RealEmbeddingServiceWithFallback:
def __init__(self, base_url: Optional[str] = None):
self.base_url = base_url or get_api_base_url()
self._real_service = None
self._mock_service = None
self._use_fallback = False
self._fallback_reason = None
def _get_real_service(self) -> Optional[RealEmbeddingService]:
if self._real_service is None:
try:
self._real_service = RealEmbeddingService(self.base_url)
self._real_service.get_dimension()
self._use_fallback = False
self._fallback_reason = None
except Exception as e:
self._use_fallback = True
self._fallback_reason = str(e)
print(f"Warning: Real service unavailable: {e}")
print("Falling back to mock service")
return None
return self._real_service
def _get_mock_service(self):
if self._mock_service is None:
from perf.services import TestEmbeddingService
self._mock_service = TestEmbeddingService
return self._mock_service
def get_dimension(self) -> int:
real = self._get_real_service()
if real is not None and not self._use_fallback:
return real.get_dimension()
return self._get_mock_service().get_dimension()
def embed(self, text: str) -> Dict[str, Any]:
real = self._get_real_service()
if real is not None and not self._use_fallback:
return real.embed(text)
return self._get_mock_service().embed(text)
def embed_batch(self, texts: List[str]) -> List[Dict[str, Any]]:
real = self._get_real_service()
if real is not None and not self._use_fallback:
return real.embed_batch(texts)
return self._get_mock_service().embed_batch(texts)
def similarity(self, text1: str, text2: str) -> Dict[str, Any]:
real = self._get_real_service()
if real is not None and not self._use_fallback:
return real.similarity(text1, text2)
return self._get_mock_service().similarity(text1, text2)
def is_using_fallback(self) -> bool:
return self._use_fallback
def get_fallback_reason(self) -> Optional[str]:
return self._fallback_reason
def create_real_service(base_url: Optional[str] = None) -> RealEmbeddingService:
return RealEmbeddingService(base_url)
def create_service_with_fallback(
base_url: Optional[str] = None,
) -> RealEmbeddingServiceWithFallback:
return RealEmbeddingServiceWithFallback(base_url)
if __name__ == "__main__":
import sys
print("=== RealEmbeddingService Test ===")
print()
base_url = sys.argv[1] if len(sys.argv) > 1 else None
try:
service = RealEmbeddingService(base_url)
print(f"Service URL: {service.base_url}")
print(f"Model: {service.model_name}")
print(f"Dimension: {service.dimension}")
print()
print("Testing embed...")
result = service.embed("Hello, world!")
print(f" Embedding dimension: {result.get('dimension')}")
print(f" Vector sample: {result.get('embedding', [])[:5]}...")
print()
print("Testing embed_batch...")
texts = ["Text 1", "Text 2", "Text 3"]
results = service.embed_batch(texts)
print(f" Batch size: {len(results)}")
for i, r in enumerate(results):
print(f" Text {i + 1} dimension: {r.get('dimension')}")
print()
print("Testing similarity...")
result = service.similarity("Hello world", "Hello there")
print(f" Similarity score: {result.get('score')}")
print(f" Metric: {result.get('metric')}")
print()
print("All tests passed!")
except Exception as e:
print(f"Error: {e}")
print()
print("Make sure VecBoost service is running at the specified URL")
sys.exit(1)