Spaces:
Running
Running
| """ | |
| Base interface for embedding providers. | |
| Defines the abstract contract that all embedding providers must implement, | |
| ensuring consistency across different provider implementations. | |
| """ | |
| from abc import ABC, abstractmethod | |
| from typing import List | |
| class EmbeddingProviderError(Exception): | |
| """Base exception for embedding provider errors.""" | |
| pass | |
| class EmbeddingRateLimitError(EmbeddingProviderError): | |
| """Raised when provider rate limit is exceeded.""" | |
| pass | |
| class EmbeddingContextLimitError(EmbeddingProviderError): | |
| """Raised when input text exceeds model's context limit.""" | |
| pass | |
| class BaseEmbeddingProvider(ABC): | |
| """ | |
| Abstract base class for embedding providers. | |
| All embedding providers must inherit from this class and implement | |
| the abstract methods to ensure consistent behavior across providers. | |
| Example: | |
| >>> provider = OpenAIEmbeddingProvider(api_key="sk-...") | |
| >>> embedding = await provider.generate_embedding("Hello world", "text-embedding-3-small") | |
| >>> len(embedding) | |
| 1536 | |
| """ | |
| def __init__(self, api_key: str = None): | |
| """ | |
| Initialize the embedding provider. | |
| Args: | |
| api_key: Optional API key for the provider. If not provided, | |
| will attempt to use environment variable. | |
| """ | |
| self._api_key = api_key | |
| self._client = None | |
| async def generate_embedding( | |
| self, text: str, model: str | |
| ) -> List[float]: | |
| """ | |
| Generate a single embedding for the given text. | |
| Args: | |
| text: The input text to embed | |
| model: The model identifier to use | |
| Returns: | |
| List of floats representing the embedding vector | |
| Raises: | |
| EmbeddingProviderError: If the API call fails | |
| EmbeddingRateLimitError: If rate limit is exceeded | |
| EmbeddingContextLimitError: If text exceeds context limit | |
| """ | |
| pass | |
| async def generate_embeddings_batch( | |
| self, texts: List[str], model: str | |
| ) -> List[List[float]]: | |
| """ | |
| Generate embeddings for multiple texts in a single batch call. | |
| Args: | |
| texts: List of input texts to embed | |
| model: The model identifier to use | |
| Returns: | |
| List of embedding vectors (one per input text) | |
| Raises: | |
| EmbeddingProviderError: If the API call fails | |
| EmbeddingRateLimitError: If rate limit is exceeded | |
| EmbeddingContextLimitError: If any text exceeds context limit | |
| """ | |
| pass | |
| def get_model_name(self, model_id: str) -> str: | |
| """ | |
| Get a human-readable display name for a model. | |
| Args: | |
| model_id: The internal model identifier | |
| Returns: | |
| Human-readable model name | |
| """ | |
| pass | |
| def estimate_cost(self, text: str, model: str) -> float: | |
| """ | |
| Estimate the cost in USD for embedding the given text. | |
| Args: | |
| text: The input text | |
| model: The model identifier | |
| Returns: | |
| Estimated cost in USD | |
| """ | |
| pass | |
| def get_context_limit(self, model: str) -> int: | |
| """ | |
| Get the maximum token limit for a model. | |
| Args: | |
| model: The model identifier | |
| Returns: | |
| Maximum number of tokens supported | |
| """ | |
| pass | |
| def get_provider_name(self) -> str: | |
| """ | |
| Get the name of this embedding provider. | |
| Returns: | |
| Provider name (e.g., "OpenAI", "Cohere") | |
| """ | |
| pass | |
| def _validate_text_input(self, text: str) -> None: | |
| """ | |
| Validate text input before processing. | |
| Args: | |
| text: The input text to validate | |
| Raises: | |
| ValueError: If text is empty, None, or not a string | |
| """ | |
| if not isinstance(text, str): | |
| raise ValueError(f"Text must be a string, got {type(text).__name__}") | |
| if not text or not text.strip(): | |
| raise ValueError("Text cannot be empty or whitespace only") | |
| def _estimate_tokens(self, text: str) -> int: | |
| """ | |
| Estimate token count for text. | |
| Uses heuristic: 1 token ≈ 4 characters (average for English text). | |
| Args: | |
| text: The input text | |
| Returns: | |
| Estimated token count | |
| """ | |
| return len(text) // 4 | |
| def _truncate_to_fit(self, text: str, max_tokens: int) -> str: | |
| """ | |
| Truncate text to fit within the token limit. | |
| Args: | |
| text: The input text | |
| max_tokens: Maximum allowed tokens | |
| Returns: | |
| Truncated text that fits within the limit | |
| """ | |
| estimated_tokens = self._estimate_tokens(text) | |
| if estimated_tokens <= max_tokens: | |
| return text | |
| # Truncate to fit (with some buffer for safety) | |
| target_chars = max_tokens * 4 | |
| return text[:target_chars] | |