""" Утиліти для роботи з Google Embeddings API. Цей файл повинен бути розміщений у modules/ai_analysis/google_embeddings_utils.py """ import os import logging from typing import List, Dict, Any, Optional import time logger = logging.getLogger(__name__) # Перевірка наявності необхідних бібліотек try: from google import genai GOOGLE_GENAI_AVAILABLE = True logger.info("Google GenAI SDK успішно імпортовано") except ImportError as e: logger.warning(f"Google GenAI SDK не встановлено: {e}. Використання Google Embeddings буде вимкнено.") GOOGLE_GENAI_AVAILABLE = False class GoogleEmbeddingsManager: """ Менеджер для роботи з Google Embeddings API. """ def __init__(self, api_key=None, model_name="text-embedding-004", task_type="retrieval_query"): """ Ініціалізація менеджера Google Embeddings. Args: api_key (str, optional): API ключ для Google API. Якщо не вказано, спробує використати GEMINI_API_KEY з середовища. model_name (str): Назва моделі ембедингів. task_type (str): Тип задачі для ембедингів. Може бути "retrieval_query" або "retrieval_document". """ self.api_key = api_key or os.getenv("GEMINI_API_KEY") self.model_name = model_name self.task_type = task_type self.client = None self.initialized = False # Спроба ініціалізації клієнта self._initialize_client() def _initialize_client(self): """ Ініціалізує клієнт Google GenAI API. Returns: bool: True, якщо ініціалізація успішна, False в іншому випадку. """ if not GOOGLE_GENAI_AVAILABLE: logger.error("Google GenAI SDK не встановлено. Встановіть пакет: pip install google-genai") return False if not self.api_key: logger.error("API ключ для Google API не вказано. Встановіть змінну GEMINI_API_KEY.") return False try: # Ініціалізація клієнта genai.configure(api_key=self.api_key) self.client = genai.Client() self.initialized = True logger.info(f"Клієнт Google GenAI успішно ініціалізовано для моделі {self.model_name}") return True except Exception as e: logger.error(f"Помилка при ініціалізації клієнта Google GenAI: {e}") return False def get_embeddings(self, texts, batch_size=8, retry_attempts=3, retry_delay=1): """ Отримує ембединги для списку текстів. Args: texts (list): Список текстів для ембедингу. batch_size (int): Розмір батча для обробки. retry_attempts (int): Кількість спроб у випадку помилки. retry_delay (int): Затримка між спробами в секундах. Returns: list: Список ембедингів для кожного тексту або None у випадку помилки. """ if not self.initialized: if not self._initialize_client(): return None if not texts: logger.warning("Порожній список текстів для ембедингу") return [] # Переконуємося, що input завжди список if not isinstance(texts, list): texts = [texts] try: all_embeddings = [] # Обробка по батчам для ефективності for i in range(0, len(texts), batch_size): batch = texts[i:i + batch_size] # Спроби з повторами у випадку помилки for attempt in range(retry_attempts): try: result = self.client.models.embed_content( model=self.model_name, contents=batch, config={"task_type": self.task_type} ) # Вилучення ембедингів batch_embeddings = [embedding.values for embedding in result.embeddings] all_embeddings.extend(batch_embeddings) break except Exception as e: if attempt == retry_attempts - 1: logger.error(f"Не вдалося отримати ембединги після {retry_attempts} спроб: {e}") return None logger.warning(f"Спроба {attempt+1} невдала: {e}. Повторна спроба через {retry_delay} сек.") time.sleep(retry_delay) logger.info(f"Успішно отримано {len(all_embeddings)} ембедингів від Google API") return all_embeddings except Exception as e: logger.error(f"Помилка при отриманні ембедингів від Google API: {e}") return None def get_embedding_dimension(self): """ Отримує розмірність ембедингів. Returns: int: Розмірність ембедингів або 0 у випадку помилки. """ if not self.initialized: if not self._initialize_client(): return 0 try: # Отримуємо ембединг для тестового тексту result = self.client.models.embed_content( model=self.model_name, contents=["Test"], config={"task_type": self.task_type} ) # Отримуємо розмірність [embedding] = result.embeddings return len(embedding.values) except Exception as e: logger.error(f"Помилка при отриманні розмірності ембедингів: {e}") return 0 # Приклад використання if __name__ == "__main__": # Налаштування логування logging.basicConfig(level=logging.INFO) # Ініціалізація менеджера manager = GoogleEmbeddingsManager() # Отримання розмірності ембедингів dimension = manager.get_embedding_dimension() print(f"Розмірність ембедингів: {dimension}") # Отримання ембедингів для текстів texts = ["Це тестовий текст", "Це ще один тестовий текст"] embeddings = manager.get_embeddings(texts) if embeddings: print(f"Отримано {len(embeddings)} ембедингів") print(f"Розмірність першого ембедингу: {len(embeddings[0])}")