pizza_chatbot5 / llm_client.py
DocUA's picture
1
3efd8fa
"""
Модуль для взаємодії з 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)