import os
import sys
from typing import Any, Dict, List, Optional, Type
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,
get_test_mode,
is_mock_mode,
is_real_mode,
TestMode,
)
class EmbeddingServiceInterface:
@classmethod
def get_dimension(cls) -> int:
raise NotImplementedError
@classmethod
def embed(cls, text: str) -> Dict[str, Any]:
raise NotImplementedError
@classmethod
def embed_batch(cls, texts: List[str]) -> List[Dict[str, Any]]:
raise NotImplementedError
@classmethod
def similarity(cls, text1: str, text2: str) -> Dict[str, Any]:
raise NotImplementedError
def get_embedding_service_class() -> Type[EmbeddingServiceInterface]:
mode = get_test_mode()
if is_mock_mode():
from perf.services import TestEmbeddingService
return TestEmbeddingService
else:
try:
from perf.real_service import RealEmbeddingService
return RealEmbeddingService
except ImportError:
print("Warning: RealEmbeddingService not available, falling back to mock")
from perf.services import TestEmbeddingService
return TestEmbeddingService
class MockEmbeddingService:
def __init__(self):
from perf.services import TestEmbeddingService
self._service = TestEmbeddingService
def get_dimension(self) -> int:
return self._service.get_dimension()
def embed(self, text: str) -> Dict[str, Any]:
return self._service.embed(text)
def embed_batch(self, texts: List[str]) -> List[Dict[str, Any]]:
return self._service.embed_batch(texts)
def similarity(self, text1: str, text2: str) -> Dict[str, Any]:
return self._service.similarity(text1, text2)
class RealEmbeddingService:
def __init__(self, base_url: Optional[str] = None):
self.base_url = base_url or get_api_base_url()
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 get_model_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})
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}
)
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},
)
response.raise_for_status()
return response.json()
def create_embedding_service(mode: Optional[str] = None) -> Any:
if mode == "mock":
return MockEmbeddingService()
elif mode == "real":
return RealEmbeddingService()
elif mode is not None:
raise ValueError(f"Unknown service mode: {mode}")
if is_mock_mode():
return MockEmbeddingService()
else:
try:
return RealEmbeddingService()
except Exception as e:
print(f"Warning: Failed to create real service: {e}")
print("Falling back to mock service")
return MockEmbeddingService()
def pytest_configure(config):
mode = get_test_mode()
print(f"\n{'=' * 60}")
print(f"Test Configuration:")
print(f" Mode: {mode.value}")
print(f" Model: {get_model_name()}")
print(f" Dimension: {get_model_dimension()}")
print(f" API URL: {get_api_base_url()}")
print(f"{'=' * 60}\n")
@pytest.fixture(scope="session")
def test_mode() -> str:
return get_test_mode().value
@pytest.fixture(scope="session")
def model_name() -> str:
return get_model_name()
@pytest.fixture(scope="session")
def model_dimension() -> int:
return get_model_dimension()
@pytest.fixture
def embedding_service() -> Any:
return create_embedding_service()
@pytest.fixture
def mock_embedding_service() -> MockEmbeddingService:
return MockEmbeddingService()
@pytest.fixture
def real_embedding_service() -> RealEmbeddingService:
return RealEmbeddingService()
@pytest.fixture
def api_base_url() -> str:
return get_api_base_url()
@pytest.fixture
def sample_text() -> str:
return "Hello, world! This is a test."
@pytest.fixture
def sample_texts() -> list:
return [
"Hello world",
"Machine learning is great",
"Artificial intelligence is the future",
]
@pytest.fixture
def short_text() -> str:
return "AI"
@pytest.fixture
def chinese_text() -> str:
return "你好世界"
@pytest.fixture
def long_text() -> str:
return (
"Machine learning is a subset of artificial intelligence that enables "
"systems to learn and improve from experience without being explicitly "
"programmed. It focuses on developing computer programs that can access "
"data and use it to learn for themselves."
)
@pytest.fixture
def special_char_text() -> str:
return "Hello! @#$% &*() World"