""" Модуль для взаємодії з Open Router API. """ import os from openai import OpenAI from typing import Optional from dotenv import load_dotenv # Завантажуємо змінні з .env файлу load_dotenv() # System prompt для асистента піцерії SYSTEM_PROMPT = """Ти - дружній асистент піцерії "Смачна Піца". Твоя задача - допомагати клієнтам з інформацією про меню. ВАЖЛИВІ ПРАВИЛА: - Відповідай ТІЛЬКИ українською мовою - Будь ввічливим, дружнім та корисним - Використовуй ТІЛЬКИ інформацію з наданого меню - Якщо клієнт запитує щось не пов'язане з меню (погода, новини, інші теми), ввічливо поясни, що ти можеш допомогти тільки з питаннями про меню піцерії - Відповідай коротко та по суті - Якщо клієнт не впевнений що замовити, запропонуй варіанти з меню """ class OpenRouterClient: """Клієнт для роботи з Open Router API.""" def __init__(self): """Ініціалізація клієнта з перевіркою API ключа.""" self.api_key = os.getenv("OPENROUTER_API_KEY") if not self.api_key: raise ValueError( "❌ OPENROUTER_API_KEY не встановлено. " "Додайте API ключ в environment variables." ) # Ініціалізуємо OpenAI клієнт з Open Router endpoint self.client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=self.api_key ) self.model = "deepseek/deepseek-r1-distill-llama-70b:free" self.temperature = 0.7 self.max_tokens = 500 def create_chat_completion( self, user_message: str, menu_context: str, conversation_history: Optional[list] = None ) -> str: """ Відправляє запит до LLM та отримує відповідь. Args: user_message: Повідомлення користувача menu_context: Контекст меню піцерії conversation_history: Історія розмови (опціонально) Returns: Відповідь від LLM Raises: requests.exceptions.RequestException: При помилках API Exception: При інших помилках """ try: # Формуємо повідомлення для API messages = [ { "role": "system", "content": f"{SYSTEM_PROMPT}\n\nМЕНЮ ПІЦЕРІЇ:\n{menu_context}" } ] # Додаємо історію розмови якщо є if conversation_history: for user_msg, bot_msg in conversation_history: messages.append({"role": "user", "content": user_msg}) messages.append({"role": "assistant", "content": bot_msg}) # Додаємо поточне повідомлення користувача messages.append({"role": "user", "content": user_message}) # Відправляємо запит через OpenAI SDK completion = self.client.chat.completions.create( model=self.model, messages=messages, temperature=self.temperature, max_tokens=self.max_tokens, timeout=10.0 ) # Отримуємо відповідь assistant_message = completion.choices[0].message.content return assistant_message.strip() except Exception as e: error_message = str(e).lower() # Обробка специфічних помилок if "rate limit" in error_message or "429" in error_message: return "❌ Перевищено ліміт запитів. Будь ласка, спробуйте через хвилину." if "unauthorized" in error_message or "401" in error_message: return "❌ Помилка автентифікації. Перевірте API ключ." if "timeout" in error_message: return "❌ Час очікування відповіді вичерпано. Спробуйте ще раз." if "connection" in error_message: return "❌ Помилка з'єднання. Перевірте інтернет-з'єднання." # Загальна помилка return f"❌ Виникла помилка: {str(e)}" # Глобальний екземпляр клієнта _client_instance = None def get_client() -> OpenRouterClient: """Отримати глобальний екземпляр клієнта (singleton pattern).""" global _client_instance if _client_instance is None: _client_instance = OpenRouterClient() return _client_instance def create_chat_completion( user_message: str, menu_context: str, conversation_history: Optional[list] = None ) -> str: """ Зручна функція для створення chat completion. Args: user_message: Повідомлення користувача menu_context: Контекст меню піцерії conversation_history: Історія розмови (опціонально) Returns: Відповідь від LLM """ client = get_client() return client.create_chat_completion(user_message, menu_context, conversation_history)