Spaces:
Sleeping
feat(pizzeria-chatbot): Initialize project with core chatbot functionality
Browse files- Add Gradio-based web interface for user interactions
- Implement menu loader module to read and cache pizzeria menu from text file
- Create Open Router API client for LLM-powered responses
- Add chat handler to coordinate between UI, menu, and LLM components
- Include comprehensive design documentation with architecture diagrams
- Add deployment instructions and preparation script for Hugging Face Spaces
- Create requirements.txt with all necessary Python dependencies
- Add .gitignore for Python virtual environments and IDE files
- Include sample menu.txt with pizzeria offerings and pricing
- Set up project structure with modular, maintainable code organization
This establishes the foundation for a Ukrainian-language pizzeria chatbot that leverages LLM capabilities to answer customer questions about menu items, pricing, and ingredients.
- .gitignore +42 -0
- .kiro/specs/pizzeria-chatbot/design.md +420 -0
- .kiro/specs/pizzeria-chatbot/requirements.md +82 -0
- .kiro/specs/pizzeria-chatbot/tasks.md +70 -0
- DEPLOYMENT_INSTRUCTIONS.md +99 -0
- README.md +102 -0
- app.py +28 -0
- chat_handler.py +73 -0
- llm_client.py +150 -0
- menu.txt +42 -0
- menu_loader.py +35 -0
- prepare_for_deployment.sh +31 -0
- requirements.txt +3 -0
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
env/
|
| 8 |
+
venv/
|
| 9 |
+
ENV/
|
| 10 |
+
build/
|
| 11 |
+
develop-eggs/
|
| 12 |
+
dist/
|
| 13 |
+
downloads/
|
| 14 |
+
eggs/
|
| 15 |
+
.eggs/
|
| 16 |
+
lib/
|
| 17 |
+
lib64/
|
| 18 |
+
parts/
|
| 19 |
+
sdist/
|
| 20 |
+
var/
|
| 21 |
+
wheels/
|
| 22 |
+
*.egg-info/
|
| 23 |
+
.installed.cfg
|
| 24 |
+
*.egg
|
| 25 |
+
|
| 26 |
+
# Environment variables
|
| 27 |
+
.env
|
| 28 |
+
.env.local
|
| 29 |
+
|
| 30 |
+
# IDE
|
| 31 |
+
.vscode/
|
| 32 |
+
.idea/
|
| 33 |
+
*.swp
|
| 34 |
+
*.swo
|
| 35 |
+
*~
|
| 36 |
+
|
| 37 |
+
# OS
|
| 38 |
+
.DS_Store
|
| 39 |
+
Thumbs.db
|
| 40 |
+
|
| 41 |
+
# Logs
|
| 42 |
+
*.log
|
|
@@ -0,0 +1,420 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Design Document
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
Чат-бот піцерії - це проста Python-based веб-аплікація, що використовує Gradio для інтерфейсу користувача та Open Router API для обробки природної мови. Система читає меню з текстового файлу та надає його як контекст для LLM, щоб відповідати на запитання клієнтів українською мовою.
|
| 6 |
+
|
| 7 |
+
### Ключові технології
|
| 8 |
+
- **Python 3.10+**: Основна мова програмування
|
| 9 |
+
- **Gradio**: Фреймворк для створення веб-інтерфейсу
|
| 10 |
+
- **Open Router API**: Доступ до LLM моделей
|
| 11 |
+
- **Hugging Face Spaces**: Платформа для хостингу
|
| 12 |
+
|
| 13 |
+
## Architecture
|
| 14 |
+
|
| 15 |
+
Система має просту трирівневу архітектуру:
|
| 16 |
+
|
| 17 |
+
```mermaid
|
| 18 |
+
graph TB
|
| 19 |
+
User[Користувач] --> GradioUI[Gradio Interface]
|
| 20 |
+
GradioUI --> ChatHandler[Chat Handler]
|
| 21 |
+
ChatHandler --> MenuLoader[Menu Loader]
|
| 22 |
+
ChatHandler --> LLMClient[Open Router Client]
|
| 23 |
+
MenuLoader --> MenuFile[(menu.txt)]
|
| 24 |
+
LLMClient --> OpenRouter[Open Router API]
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
### Компоненти
|
| 28 |
+
|
| 29 |
+
1. **Gradio Interface**: Веб-інтерфейс для взаємодії з користувачем
|
| 30 |
+
2. **Chat Handler**: Основна логіка обробки повідомлень
|
| 31 |
+
3. **Menu Loader**: Завантаження та кешування меню з файлу
|
| 32 |
+
4. **Open Router Client**: Клієнт для взаємодії з LLM API
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
## Components and Interfaces
|
| 37 |
+
|
| 38 |
+
### 1. Menu Loader (`menu_loader.py`)
|
| 39 |
+
|
| 40 |
+
**Відповідальність**: Завантаження та надання доступу до меню піцерії
|
| 41 |
+
|
| 42 |
+
**Функції**:
|
| 43 |
+
```python
|
| 44 |
+
def load_menu(file_path: str = "menu.txt") -> str:
|
| 45 |
+
"""
|
| 46 |
+
Завантажує меню з текстового файлу
|
| 47 |
+
|
| 48 |
+
Args:
|
| 49 |
+
file_path: Шлях до файлу меню
|
| 50 |
+
|
| 51 |
+
Returns:
|
| 52 |
+
Текст меню у форматі string
|
| 53 |
+
|
| 54 |
+
Raises:
|
| 55 |
+
FileNotFoundError: Якщо файл не знайдено
|
| 56 |
+
"""
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
**Особливості**:
|
| 60 |
+
- Підтримка UTF-8 кодування для української мови
|
| 61 |
+
- Обробка помилок при відсутності файлу
|
| 62 |
+
- Простий текстовий формат для легкого редагування
|
| 63 |
+
|
| 64 |
+
### 2. Open Router Client (`llm_client.py`)
|
| 65 |
+
|
| 66 |
+
**Відповідальність**: Взаємодія з Open Router API
|
| 67 |
+
|
| 68 |
+
**Функції**:
|
| 69 |
+
```python
|
| 70 |
+
def create_chat_completion(
|
| 71 |
+
user_message: str,
|
| 72 |
+
menu_context: str,
|
| 73 |
+
conversation_history: list = None
|
| 74 |
+
) -> str:
|
| 75 |
+
"""
|
| 76 |
+
Відправляє запит до LLM та отримує відповідь
|
| 77 |
+
|
| 78 |
+
Args:
|
| 79 |
+
user_message: Повідомлення користувача
|
| 80 |
+
menu_context: Контекст меню піцерії
|
| 81 |
+
conversation_history: Історія розмови (опціонально)
|
| 82 |
+
|
| 83 |
+
Returns:
|
| 84 |
+
Відповідь від LLM
|
| 85 |
+
|
| 86 |
+
Raises:
|
| 87 |
+
APIError: При помилках API
|
| 88 |
+
"""
|
| 89 |
+
```
|
| 90 |
+
|
| 91 |
+
**Конфігурація**:
|
| 92 |
+
- API ключ з environment variable `OPENROUTER_API_KEY`
|
| 93 |
+
- Модель: рекомендується `meta-llama/llama-3.1-8b-instruct:free` (безкоштовна)
|
| 94 |
+
- Temperature: 0.7 (баланс між креативністю та точністю)
|
| 95 |
+
- Max tokens: 500 (достатньо для відповідей про меню)
|
| 96 |
+
|
| 97 |
+
**System Prompt**:
|
| 98 |
+
```
|
| 99 |
+
Ти - дружній асистент піцерії. Твоя задача - допомагати клієнтам з інформацією про меню.
|
| 100 |
+
Відповідай українською мовою, будь ввічливим та корисним.
|
| 101 |
+
Використовуй тільки інформацію з наданого меню.
|
| 102 |
+
Якщо клієнт запитує щось не пов'язане з меню, ввічливо поясни, що ти можеш допомогти тільки з питаннями про меню піцерії.
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
### 3. Chat Handler (`chat_handler.py`)
|
| 106 |
+
|
| 107 |
+
**Відповідальність**: Координація між компонентами та обробка логіки чату
|
| 108 |
+
|
| 109 |
+
**Функції**:
|
| 110 |
+
```python
|
| 111 |
+
def process_message(
|
| 112 |
+
user_message: str,
|
| 113 |
+
chat_history: list
|
| 114 |
+
) -> tuple[list, str]:
|
| 115 |
+
"""
|
| 116 |
+
Обробляє повідомлення користувача
|
| 117 |
+
|
| 118 |
+
Args:
|
| 119 |
+
user_message: Повідомлення від користувача
|
| 120 |
+
chat_history: Історія чату у форматі Gradio
|
| 121 |
+
|
| 122 |
+
Returns:
|
| 123 |
+
Tuple з оновленою історією та порожнім рядком для очищення input
|
| 124 |
+
"""
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
**Логіка обробки**:
|
| 128 |
+
1. Отри��ати повідомлення користувача
|
| 129 |
+
2. Завантажити меню (якщо ще не завантажено)
|
| 130 |
+
3. Підготувати контекст для LLM
|
| 131 |
+
4. Відправити запит до Open Router
|
| 132 |
+
5. Обробити відповідь та оновити історію
|
| 133 |
+
6. Обробити помилки та показати дружні повідомлення
|
| 134 |
+
|
| 135 |
+
### 4. Gradio Interface (`app.py`)
|
| 136 |
+
|
| 137 |
+
**Відповідальність**: Веб-інтерфейс та точка входу
|
| 138 |
+
|
| 139 |
+
**Компоненти UI**:
|
| 140 |
+
- `gr.Chatbot()`: Відображення історії розмови
|
| 141 |
+
- `gr.Textbox()`: Поле вводу для користувача
|
| 142 |
+
- `gr.Button()`: Кнопка відправки (опціонально, можна використовувати Enter)
|
| 143 |
+
|
| 144 |
+
**Конфігурація**:
|
| 145 |
+
```python
|
| 146 |
+
demo = gr.ChatInterface(
|
| 147 |
+
fn=process_message,
|
| 148 |
+
title="🍕 Чат-бот Піцерії",
|
| 149 |
+
description="Запитайте мене про наше меню!",
|
| 150 |
+
theme=gr.themes.Soft(),
|
| 151 |
+
examples=[
|
| 152 |
+
"Які у вас є піци?",
|
| 153 |
+
"Скільки коштує Маргарита?",
|
| 154 |
+
"Що входить до складу Пепероні?"
|
| 155 |
+
]
|
| 156 |
+
)
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
## Data Models
|
| 162 |
+
|
| 163 |
+
### Menu File Format (`menu.txt`)
|
| 164 |
+
|
| 165 |
+
Простий текстовий формат для легкого редагування:
|
| 166 |
+
|
| 167 |
+
```
|
| 168 |
+
=== МЕНЮ ПІЦЕРІЇ "СМАЧНА ПІЦА" ===
|
| 169 |
+
|
| 170 |
+
ПІЦИ:
|
| 171 |
+
|
| 172 |
+
1. Маргарита - 150 грн
|
| 173 |
+
Інгредієнти: томатний соус, моцарела, базилік, оливкова олія
|
| 174 |
+
Розмір: 30 см
|
| 175 |
+
|
| 176 |
+
2. Пепероні - 180 грн
|
| 177 |
+
Інгредієнти: томатний соус, моцарела, пепероні
|
| 178 |
+
Розмір: 30 см
|
| 179 |
+
|
| 180 |
+
3. Чотири сири - 200 грн
|
| 181 |
+
Інгредієнти: моцарела, пармезан, горгонзола, фета
|
| 182 |
+
Розмір: 30 см
|
| 183 |
+
|
| 184 |
+
НАПОЇ:
|
| 185 |
+
|
| 186 |
+
1. Кока-кола - 30 грн (0.5л)
|
| 187 |
+
2. Вода - 20 грн (0.5л)
|
| 188 |
+
3. Сік апельсиновий - 35 грн (0.3л)
|
| 189 |
+
|
| 190 |
+
РЕЖИМ РОБОТИ:
|
| 191 |
+
Пн-Нд: 10:00 - 22:00
|
| 192 |
+
|
| 193 |
+
ДОСТАВКА:
|
| 194 |
+
Безкоштовна доставка при замовленні від 300 грн
|
| 195 |
+
```
|
| 196 |
+
|
| 197 |
+
### Conversation History Format
|
| 198 |
+
|
| 199 |
+
Gradio використовує список кортежів для історії:
|
| 200 |
+
```python
|
| 201 |
+
chat_history = [
|
| 202 |
+
("Привіт! Які у вас є піци?", "Вітаю! У нас є три види піц: Маргарита (150 грн)..."),
|
| 203 |
+
("Скільки коштує Пепероні?", "Піца Пепероні коштує 180 грн...")
|
| 204 |
+
]
|
| 205 |
+
```
|
| 206 |
+
|
| 207 |
+
### Environment Variables
|
| 208 |
+
|
| 209 |
+
```
|
| 210 |
+
OPENROUTER_API_KEY=your_api_key_here
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
## Error Handling
|
| 214 |
+
|
| 215 |
+
### 1. Menu File Errors
|
| 216 |
+
|
| 217 |
+
**Сценарій**: Файл меню не знайдено або не може бути прочитаний
|
| 218 |
+
|
| 219 |
+
**Обробка**:
|
| 220 |
+
```python
|
| 221 |
+
try:
|
| 222 |
+
menu = load_menu()
|
| 223 |
+
except FileNotFoundError:
|
| 224 |
+
return "❌ Помилка: файл меню не знайдено. Зверніться до адміністратора."
|
| 225 |
+
except Exception as e:
|
| 226 |
+
return f"❌ Помилка читання меню: {str(e)}"
|
| 227 |
+
```
|
| 228 |
+
|
| 229 |
+
### 2. API Errors
|
| 230 |
+
|
| 231 |
+
**Сценарій**: Open Router API недоступний або повертає помилку
|
| 232 |
+
|
| 233 |
+
**Обробка**:
|
| 234 |
+
```python
|
| 235 |
+
try:
|
| 236 |
+
response = llm_client.create_chat_completion(...)
|
| 237 |
+
except requests.exceptions.RequestException:
|
| 238 |
+
return "❌ Вибачте, сервіс тимчасово недоступний. Спробуйте пізніше."
|
| 239 |
+
except Exception as e:
|
| 240 |
+
return "❌ Виникла помилка. Спробуйте ще раз."
|
| 241 |
+
```
|
| 242 |
+
|
| 243 |
+
### 3. API Key Missing
|
| 244 |
+
|
| 245 |
+
**Сценарій**: Environment variable з API ключем не встановлена
|
| 246 |
+
|
| 247 |
+
**Обробка**:
|
| 248 |
+
```python
|
| 249 |
+
api_key = os.getenv("OPENROUTER_API_KEY")
|
| 250 |
+
if not api_key:
|
| 251 |
+
raise ValueError("OPENROUTER_API_KEY environment variable is not set")
|
| 252 |
+
```
|
| 253 |
+
|
| 254 |
+
### 4. Rate Limiting
|
| 255 |
+
|
| 256 |
+
**Сценарій**: Перевищено ліміт запитів до API
|
| 257 |
+
|
| 258 |
+
**Обробка**:
|
| 259 |
+
- Показати дружнє повідомлення користувачу
|
| 260 |
+
- Запропонувати спробувати через хвилину
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
## Testing Strategy
|
| 265 |
+
|
| 266 |
+
### 1. Manual Testing
|
| 267 |
+
|
| 268 |
+
Для початківця найпростіший підхід - мануальне тестування:
|
| 269 |
+
|
| 270 |
+
**Тест-кейси**:
|
| 271 |
+
1. Запуск аплікації локально
|
| 272 |
+
2. Перевірка відображення інтерфейсу
|
| 273 |
+
3. Відправка різних типів запитань:
|
| 274 |
+
- Про конкретну піцу
|
| 275 |
+
- Про ціни
|
| 276 |
+
- Про інгредієнти
|
| 277 |
+
- Про режим роботи
|
| 278 |
+
- Питання не пов'язані з меню
|
| 279 |
+
4. Перевірка коректності відповідей
|
| 280 |
+
5. Тестування з відсутнім файлом меню
|
| 281 |
+
6. Тестування �� невалідним API ключем
|
| 282 |
+
|
| 283 |
+
### 2. Local Development Testing
|
| 284 |
+
|
| 285 |
+
**Запуск локально**:
|
| 286 |
+
```bash
|
| 287 |
+
# Встановити залежності
|
| 288 |
+
pip install -r requirements.txt
|
| 289 |
+
|
| 290 |
+
# Встановити environment variable
|
| 291 |
+
export OPENROUTER_API_KEY="your_key_here"
|
| 292 |
+
|
| 293 |
+
# Запустити аплікацію
|
| 294 |
+
python app.py
|
| 295 |
+
```
|
| 296 |
+
|
| 297 |
+
**Очікуваний результат**:
|
| 298 |
+
- Gradio запускається на `http://localhost:7860`
|
| 299 |
+
- Інтерфейс відкривається в браузері
|
| 300 |
+
- Можна відправляти повідомлення та отримувати відповіді
|
| 301 |
+
|
| 302 |
+
### 3. Hugging Face Deployment Testing
|
| 303 |
+
|
| 304 |
+
**Кроки**:
|
| 305 |
+
1. Створити Space на Hugging Face
|
| 306 |
+
2. Завантажити файли: `app.py`, `requirements.txt`, `menu.txt`, інші модулі
|
| 307 |
+
3. Встановити Secret `OPENROUTER_API_KEY` в налаштуваннях Space
|
| 308 |
+
4. Дочекатися білду
|
| 309 |
+
5. Протестувати публічний URL
|
| 310 |
+
|
| 311 |
+
**Перевірки**:
|
| 312 |
+
- Space успішно збудувався
|
| 313 |
+
- Інтерфейс доступний публічно
|
| 314 |
+
- Бот відповідає коректно
|
| 315 |
+
- Кілька користувачів можуть користуватися одночасно
|
| 316 |
+
|
| 317 |
+
## Deployment Configuration
|
| 318 |
+
|
| 319 |
+
### Project Structure
|
| 320 |
+
|
| 321 |
+
```
|
| 322 |
+
pizzeria-chatbot/
|
| 323 |
+
├── app.py # Головний файл з Gradio interface
|
| 324 |
+
├── chat_handler.py # Логіка обробки чату
|
| 325 |
+
├── llm_client.py # Клієнт для Open Router API
|
| 326 |
+
├── menu_loader.py # Завантаження меню
|
| 327 |
+
├── menu.txt # Файл з меню
|
| 328 |
+
├── requirements.txt # Python залежності
|
| 329 |
+
└── README.md # Документація проекту
|
| 330 |
+
```
|
| 331 |
+
|
| 332 |
+
### requirements.txt
|
| 333 |
+
|
| 334 |
+
```
|
| 335 |
+
gradio>=4.0.0
|
| 336 |
+
requests>=2.31.0
|
| 337 |
+
python-dotenv>=1.0.0
|
| 338 |
+
```
|
| 339 |
+
|
| 340 |
+
### README.md для Hugging Face
|
| 341 |
+
|
| 342 |
+
```markdown
|
| 343 |
+
---
|
| 344 |
+
title: Pizzeria Chatbot
|
| 345 |
+
emoji: 🍕
|
| 346 |
+
colorFrom: red
|
| 347 |
+
colorTo: yellow
|
| 348 |
+
sdk: gradio
|
| 349 |
+
sdk_version: 4.0.0
|
| 350 |
+
app_file: app.py
|
| 351 |
+
pinned: false
|
| 352 |
+
---
|
| 353 |
+
|
| 354 |
+
# Чат-бот Піцерії
|
| 355 |
+
|
| 356 |
+
Інтерактивний чат-бот для піцерії, що використовує LLM для відповідей на запитання про меню.
|
| 357 |
+
|
| 358 |
+
## Налаштування
|
| 359 |
+
|
| 360 |
+
Встановіть Secret `OPENROUTER_API_KEY` в налаштуваннях Space.
|
| 361 |
+
```
|
| 362 |
+
|
| 363 |
+
### Environment Setup на Hugging Face
|
| 364 |
+
|
| 365 |
+
1. Перейти в Settings Space
|
| 366 |
+
2. Додати Secret: `OPENROUTER_API_KEY`
|
| 367 |
+
3. Вставити ваш API ключ з Open Router
|
| 368 |
+
4. Зберегти та перезапустити Space
|
| 369 |
+
|
| 370 |
+
## Design Decisions and Rationale
|
| 371 |
+
|
| 372 |
+
### 1. Чому Gradio?
|
| 373 |
+
|
| 374 |
+
**Рішення**: Використовувати Gradio замість Flask/FastAPI
|
| 375 |
+
|
| 376 |
+
**Обґрунтування**:
|
| 377 |
+
- Мінімальний код для створення UI
|
| 378 |
+
- Вбудована підтримка чат-інтерфейсу
|
| 379 |
+
- Нативна інтеграція з Hugging Face
|
| 380 |
+
- Ідеально для початківців
|
| 381 |
+
- Автоматичний responsive дизайн
|
| 382 |
+
|
| 383 |
+
### 2. Чому текстовий файл для меню?
|
| 384 |
+
|
| 385 |
+
**Рішення**: Зберігати меню в простому .txt файлі
|
| 386 |
+
|
| 387 |
+
**Обґрунтування**:
|
| 388 |
+
- Легко редагувати без знань програмування
|
| 389 |
+
- Не потрібна база даних для маленької піцерії
|
| 390 |
+
- Швидке завантаження
|
| 391 |
+
- Простота для початківця
|
| 392 |
+
|
| 393 |
+
### 3. Чому Open Router?
|
| 394 |
+
|
| 395 |
+
**Рішення**: Використовувати Open Router замість прямого доступу до OpenAI/Anthropic
|
| 396 |
+
|
| 397 |
+
**Обґрунтування**:
|
| 398 |
+
- Єдиний API для різних моделей
|
| 399 |
+
- Є безкоштовні моделі для тестування
|
| 400 |
+
- Простий у використанні
|
| 401 |
+
- Гнучкість у виборі моделі
|
| 402 |
+
|
| 403 |
+
### 4. Простота над складністю
|
| 404 |
+
|
| 405 |
+
**Рішення**: Мінімальна архітектура без баз даних, черг, кешування
|
| 406 |
+
|
| 407 |
+
**Обґрунтування**:
|
| 408 |
+
- Проект для початківця
|
| 409 |
+
- Маленька піцерія не потребує складної інфраструктури
|
| 410 |
+
- Легше підтримувати та розуміти
|
| 411 |
+
- Швидше розгорнути та запустити
|
| 412 |
+
|
| 413 |
+
### 5. Українська мова
|
| 414 |
+
|
| 415 |
+
**Рішення**: Весь інтерфейс та відповіді українською
|
| 416 |
+
|
| 417 |
+
**Обґрунтування**:
|
| 418 |
+
- Цільова аудиторія - українські клієнти
|
| 419 |
+
- LLM добре працюють з українською
|
| 420 |
+
- Природніше для користувачів
|
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Requirements Document
|
| 2 |
+
|
| 3 |
+
## Introduction
|
| 4 |
+
|
| 5 |
+
Цей документ описує вимоги до інтерактивного чат-бота для маленької піцерії. Бот дозволить клієнтам отримувати інформацію про меню через природну мову, використовуючи LLM модель через Open Router. Інтерфейс буде реалізовано за допомогою Gradio та розгорнуто на платформі Hugging Face.
|
| 6 |
+
|
| 7 |
+
## Glossary
|
| 8 |
+
|
| 9 |
+
- **Chatbot System**: Програмна система, що включає веб-інтерфейс Gradio, інтеграцію з LLM та обробку запитів користувачів
|
| 10 |
+
- **Menu File**: Текстовий файл, що містить інформацію про меню піцерії
|
| 11 |
+
- **LLM Service**: Сервіс Open Router для обробки природної мови
|
| 12 |
+
- **User**: Клієнт піцерії, який взаємодіє з чат-ботом
|
| 13 |
+
- **Gradio Interface**: Веб-інтерфейс для взаємодії користувача з ботом
|
| 14 |
+
|
| 15 |
+
## Requirements
|
| 16 |
+
|
| 17 |
+
### Requirement 1
|
| 18 |
+
|
| 19 |
+
**User Story:** Як клієнт піцерії, я хочу бачити зручний веб-інтерфейс чату, щоб легко спілкуватися з ботом
|
| 20 |
+
|
| 21 |
+
#### Acceptance Criteria
|
| 22 |
+
|
| 23 |
+
1. THE Chatbot System SHALL display a web interface using Gradio framework
|
| 24 |
+
2. THE Chatbot System SHALL provide a text input field for User messages
|
| 25 |
+
3. THE Chatbot System SHALL display conversation history between User and bot
|
| 26 |
+
4. THE Chatbot System SHALL respond within 10 seconds to each User message
|
| 27 |
+
|
| 28 |
+
### Requirement 2
|
| 29 |
+
|
| 30 |
+
**User Story:** Як клієнт, я хочу запитувати про меню природною мовою, щоб швидко знайти потрібну інформацію
|
| 31 |
+
|
| 32 |
+
#### Acceptance Criteria
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
1. WHEN User submits a question about menu, THE Chatbot System SHALL send the question to LLM Service
|
| 36 |
+
2. THE Chatbot System SHALL include Menu File content in the context for LLM Service
|
| 37 |
+
3. THE Chatbot System SHALL return LLM Service response to User in Ukrainian language
|
| 38 |
+
4. THE Chatbot System SHALL handle questions about pizza types, prices, ingredients, and availability
|
| 39 |
+
|
| 40 |
+
### Requirement 3
|
| 41 |
+
|
| 42 |
+
**User Story:** Як власник піцерії, я хочу легко оновлювати меню у текстовому файлі, щоб бот завжди надавав актуальну інформацію
|
| 43 |
+
|
| 44 |
+
#### Acceptance Criteria
|
| 45 |
+
|
| 46 |
+
1. THE Chatbot System SHALL read menu information from a text file at startup
|
| 47 |
+
2. THE Chatbot System SHALL support UTF-8 encoding for Ukrainian text in Menu File
|
| 48 |
+
3. WHEN Menu File is updated, THE Chatbot System SHALL load new content after restart
|
| 49 |
+
4. THE Chatbot System SHALL handle missing Menu File by displaying an error message
|
| 50 |
+
|
| 51 |
+
### Requirement 4
|
| 52 |
+
|
| 53 |
+
**User Story:** Як розробник, я хочу використовувати Open Router API, щоб мати доступ до потужних LLM моделей
|
| 54 |
+
|
| 55 |
+
#### Acceptance Criteria
|
| 56 |
+
|
| 57 |
+
1. THE Chatbot System SHALL authenticate with LLM Service using API key from environment variable
|
| 58 |
+
2. THE Chatbot System SHALL send requests to LLM Service with menu context and user question
|
| 59 |
+
3. IF LLM Service returns an error, THEN THE Chatbot System SHALL display a friendly error message to User
|
| 60 |
+
4. THE Chatbot System SHALL configure LLM Service with appropriate temperature and token limits
|
| 61 |
+
|
| 62 |
+
### Requirement 5
|
| 63 |
+
|
| 64 |
+
**User Story:** Як розробник, я хочу розгорнути бота на Hugging Face, щоб клієнти могли користуватися ним онлайн
|
| 65 |
+
|
| 66 |
+
#### Acceptance Criteria
|
| 67 |
+
|
| 68 |
+
1. THE Chatbot System SHALL run on Hugging Face Spaces platform
|
| 69 |
+
2. THE Chatbot System SHALL include all required dependencies in requirements.txt file
|
| 70 |
+
3. THE Chatbot System SHALL expose Gradio Interface on public URL
|
| 71 |
+
4. THE Chatbot System SHALL handle concurrent User sessions independently
|
| 72 |
+
|
| 73 |
+
### Requirement 6
|
| 74 |
+
|
| 75 |
+
**User Story:** Як клієнт, я хочу отримувати корисні відповіді навіть на нечіткі запити, щоб легко знайти потрібну піцу
|
| 76 |
+
|
| 77 |
+
#### Acceptance Criteria
|
| 78 |
+
|
| 79 |
+
1. WHEN User asks unclear question, THE Chatbot System SHALL provide helpful suggestions based on Menu File
|
| 80 |
+
2. THE Chatbot System SHALL maintain conversation context across multiple messages
|
| 81 |
+
3. THE Chatbot System SHALL respond in friendly and helpful tone
|
| 82 |
+
4. IF User asks question unrelated to menu, THEN THE Chatbot System SHALL politely redirect to menu topics
|
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Implementation Plan
|
| 2 |
+
|
| 3 |
+
- [x] 1. Створити структуру проекту та базові файли
|
| 4 |
+
- Створити файл `requirements.txt` з необхідними залежностями (gradio, requests, python-dotenv)
|
| 5 |
+
- Створити файл `menu.txt` з прикладом меню піцерії українською мовою
|
| 6 |
+
- Створити файл `README.md` з описом проекту та інструкціями для Hugging Face
|
| 7 |
+
- _Requirements: 3.1, 3.2, 5.2_
|
| 8 |
+
|
| 9 |
+
- [x] 2. Реалізувати Menu Loader модуль
|
| 10 |
+
- Створити файл `menu_loader.py` з функцією `load_menu()`
|
| 11 |
+
- Реалізувати читання файлу з UTF-8 кодуванням
|
| 12 |
+
- Додати обробку помилок для відсутнього файлу (FileNotFoundError)
|
| 13 |
+
- Додати обробку загальних помилок читання файлу
|
| 14 |
+
- _Requirements: 3.1, 3.2, 3.4_
|
| 15 |
+
|
| 16 |
+
- [x] 3. Реалізувати Open Router Client модуль
|
| 17 |
+
- Створити файл `llm_client.py` з функцією `create_chat_completion()`
|
| 18 |
+
- Реалізувати читання API ключа з environment variable `OPENROUTER_API_KEY`
|
| 19 |
+
- Додати валідацію наявності API ключа при ініціалізації
|
| 20 |
+
- Реалізувати HTTP запит до Open Router API з використанням requests
|
| 21 |
+
- Налаштувати параметри запиту: модель `meta-llama/llama-3.1-8b-instruct:free`, temperature 0.7, max_tokens 500
|
| 22 |
+
- Створити system prompt для асистента піцерії українською мовою
|
| 23 |
+
- Додати обробку помилок API (RequestException, timeout, rate limiting)
|
| 24 |
+
- Реалізувати парсинг відповіді від API та повернення тексту
|
| 25 |
+
- _Requirements: 4.1, 4.2, 4.3, 4.4, 2.3_
|
| 26 |
+
|
| 27 |
+
- [x] 4. Реалізувати Chat Handler модуль
|
| 28 |
+
- Створити файл `chat_handler.py` з функцією `process_message()`
|
| 29 |
+
- Реалізувати завантаження меню при першому виклику (lazy loading)
|
| 30 |
+
- Реалізувати формування контексту для LLM з меню та повідомленням користувача
|
| 31 |
+
- Додати логіку виклику LLM client з підготовленим контекстом
|
| 32 |
+
- Реалізувати оновлення історії чату у форматі Gradio (список кортежів)
|
| 33 |
+
- Додати обробку всіх помилок з дружніми повідомленнями українською
|
| 34 |
+
- _Requirements: 2.1, 2.2, 3.1, 6.2, 6.3_
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
- [x] 5. Створити Gradio інтерфейс
|
| 38 |
+
- Створити файл `app.py` як головну точку входу
|
| 39 |
+
- Імпортувати необхідні модулі (gradio, chat_handler)
|
| 40 |
+
- Створити `gr.ChatInterface` з функцією `process_message` як callback
|
| 41 |
+
- Налаштувати заголовок "🍕 Чат-бот Піцерії" та опис українською
|
| 42 |
+
- Додати приклади запитань (examples) для користувачів
|
| 43 |
+
- Налаштувати тему інтерфейсу (gr.themes.Soft())
|
| 44 |
+
- Додати виклик `demo.launch()` для запуску сервера
|
| 45 |
+
- _Requirements: 1.1, 1.2, 1.3, 5.3_
|
| 46 |
+
|
| 47 |
+
- [x] 6. Додати обробку edge cases та покращення UX
|
| 48 |
+
- Додати перевірку на порожні повідомлення користувача
|
| 49 |
+
- Реалізувати логіку для питань не пов'язаних з меню (перенаправлення до меню)
|
| 50 |
+
- Додати timeout для API запитів (10 секунд згідно з вимогами)
|
| 51 |
+
- Додати інформативні повідомлення про помилки для різних сценаріїв
|
| 52 |
+
- _Requirements: 1.4, 6.1, 6.4, 4.3_
|
| 53 |
+
|
| 54 |
+
- [x] 7. Підготувати проект до deployment на Hugging Face
|
| 55 |
+
- Перевірити що всі файли на місці (app.py, requirements.txt, menu.txt, README.md, модулі)
|
| 56 |
+
- Додати YAML front matter до README.md для Hugging Face Space
|
| 57 |
+
- Перевірити що requirements.txt містить всі залежності з правильними версіями
|
| 58 |
+
- Додати інструкції в README.md про налаштування Secret `OPENROUTER_API_KEY`
|
| 59 |
+
- Додати .gitignore файл для виключення .env та інших локальних файлів
|
| 60 |
+
- _Requirements: 5.1, 5.2, 5.3_
|
| 61 |
+
|
| 62 |
+
- [x] 8. Локальне тестування
|
| 63 |
+
- Створити `.env` файл з тестовим API ключем для локальної розробки
|
| 64 |
+
- Запустити аплікацію локально командою `python app.py`
|
| 65 |
+
- Протестува��и базові запитання про меню (піци, ціни, інгредієнти)
|
| 66 |
+
- Протестувати edge cases (порожні повідомлення, питання не про меню)
|
| 67 |
+
- Протестувати обробку помилок (відсутній menu.txt, невалідний API ключ)
|
| 68 |
+
- Перевірити що відповіді приходять українською мовою
|
| 69 |
+
- Перевірити що інтерфейс коректно відображається
|
| 70 |
+
- _Requirements: 1.1, 1.2, 1.3, 1.4, 2.3, 2.4, 3.4, 4.3, 6.1, 6.2, 6.3, 6.4_
|
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 Інструкція з розгортання на Hugging Face
|
| 2 |
+
|
| 3 |
+
## Файли для завантаження
|
| 4 |
+
|
| 5 |
+
Завантажте ці файли на ваш Space: https://huggingface.co/spaces/DocSA/pizza_chatbot4
|
| 6 |
+
|
| 7 |
+
### Обов'язкові файли:
|
| 8 |
+
1. ✅ `app.py` - головний файл додатку
|
| 9 |
+
2. ✅ `chat_handler.py` - обробка чату
|
| 10 |
+
3. ✅ `llm_client.py` - клієнт Open Router
|
| 11 |
+
4. ✅ `menu_loader.py` - завантаження меню
|
| 12 |
+
5. ✅ `menu.txt` - меню піцерії
|
| 13 |
+
6. ✅ `requirements.txt` - залежності Python
|
| 14 |
+
7. ✅ `README.md` - документація (з YAML front matter)
|
| 15 |
+
|
| 16 |
+
### Опціональні файли:
|
| 17 |
+
- `.gitignore` - для Git
|
| 18 |
+
|
| 19 |
+
## Кроки розгортання
|
| 20 |
+
|
| 21 |
+
### Крок 1: Завантажити файли через Web UI
|
| 22 |
+
|
| 23 |
+
1. Відкрийте https://huggingface.co/spaces/DocSA/pizza_chatbot4
|
| 24 |
+
2. Натисніть "Files" вгорі
|
| 25 |
+
3. Натисніть "Add file" → "Upload files"
|
| 26 |
+
4. Перетягніть всі файли з проекту
|
| 27 |
+
5. Натисніть "Commit changes to main"
|
| 28 |
+
|
| 29 |
+
### Крок 2: Налаштувати API ключ
|
| 30 |
+
|
| 31 |
+
1. Перейдіть в "Settings" вашого Space
|
| 32 |
+
2. Знайдіть розділ "Repository secrets"
|
| 33 |
+
3. Натисніть "New secret"
|
| 34 |
+
4. Введіть:
|
| 35 |
+
- **Name:** `OPENROUTER_API_KEY`
|
| 36 |
+
- **Value:** ваш API ключ з Open Router
|
| 37 |
+
5. Натисніть "Save"
|
| 38 |
+
|
| 39 |
+
### Крок 3: Отримати API ключ Open Router (якщо ще немає)
|
| 40 |
+
|
| 41 |
+
1. Зареєструйтесь на https://openrouter.ai/
|
| 42 |
+
2. Перейдіть в розділ "Keys"
|
| 43 |
+
3. Натисніть "Create Key"
|
| 44 |
+
4. Скопіюйте ключ
|
| 45 |
+
5. Додайте його в Secrets (див. Крок 2)
|
| 46 |
+
|
| 47 |
+
### Крок 4: Дочекатися білду
|
| 48 |
+
|
| 49 |
+
1. Space автоматично почне білдитися
|
| 50 |
+
2. Зачекайте 1-2 хвилини
|
| 51 |
+
3. Перевірте логи на наявність помилок
|
| 52 |
+
4. Коли статус стане "Running" - готово! ✅
|
| 53 |
+
|
| 54 |
+
### Крок 5: Протестувати
|
| 55 |
+
|
| 56 |
+
Відкрийте ваш Space та спробуйте запитання:
|
| 57 |
+
- "Які у вас є піци?"
|
| 58 |
+
- "Скільки коштує Маргарита?"
|
| 59 |
+
- "Що входить до складу Пепероні?"
|
| 60 |
+
|
| 61 |
+
## Альтернативний метод: Git
|
| 62 |
+
|
| 63 |
+
Якщо ви знайомі з Git:
|
| 64 |
+
|
| 65 |
+
```bash
|
| 66 |
+
# Клонувати Space
|
| 67 |
+
git clone https://huggingface.co/spaces/DocSA/pizza_chatbot4
|
| 68 |
+
cd pizza_chatbot4
|
| 69 |
+
|
| 70 |
+
# Скопіювати файли проекту
|
| 71 |
+
cp /path/to/project/*.py .
|
| 72 |
+
cp /path/to/project/*.txt .
|
| 73 |
+
cp /path/to/project/README.md .
|
| 74 |
+
|
| 75 |
+
# Закомітити та запушити
|
| 76 |
+
git add .
|
| 77 |
+
git commit -m "Deploy pizzeria chatbot"
|
| 78 |
+
git push
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
## Troubleshooting
|
| 82 |
+
|
| 83 |
+
### Помилка: "OPENROUTER_API_KEY not set"
|
| 84 |
+
- Перевірте що ви додали Secret в Settings
|
| 85 |
+
- Перезапустіть Space після додавання Secret
|
| 86 |
+
|
| 87 |
+
### Помилка: "No module named 'gradio'"
|
| 88 |
+
- Перевірте що requirements.txt завантажено
|
| 89 |
+
- Перевірте формат файлу (без зайвих символів)
|
| 90 |
+
|
| 91 |
+
### Space не запускається
|
| 92 |
+
- Перевірте логи в розділі "Logs"
|
| 93 |
+
- Переконайтесь що всі файли завантажені
|
| 94 |
+
- Перевірте що README.md має YAML front matter
|
| 95 |
+
|
| 96 |
+
## Готово! 🎉
|
| 97 |
+
|
| 98 |
+
Ваш чат-бот піцерії тепер доступний онлайн!
|
| 99 |
+
Поділіться посиланням з клієнтами: https://huggingface.co/spaces/DocSA/pizza_chatbot4
|
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Pizzeria Chatbot
|
| 3 |
+
emoji: 🍕
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: yellow
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 4.0.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# 🍕 Чат-бот Піцерії
|
| 13 |
+
|
| 14 |
+
Інтерактивний чат-бот для піцерії, що використовує LLM для відповідей на запитання про меню українською мовою.
|
| 15 |
+
|
| 16 |
+
## Опис
|
| 17 |
+
|
| 18 |
+
Цей проект створений для маленької піцерії, щоб клієнти могли легко дізнатися про меню через природну мову. Бот використовує:
|
| 19 |
+
- **Gradio** для веб-інтерфейсу
|
| 20 |
+
- **Open Router API** для обробки природної мови
|
| 21 |
+
- **Текстовий файл** для зберігання меню
|
| 22 |
+
|
| 23 |
+
## Функціональність
|
| 24 |
+
|
| 25 |
+
- 💬 Природна мова спілкування українською
|
| 26 |
+
- 🍕 Інформація про піци, ціни та інгредієнти
|
| 27 |
+
- 🥤 Інформація про напої
|
| 28 |
+
- ⏰ Режим роботи та умови доставки
|
| 29 |
+
- 🎯 Розумні відповіді на нечіткі запити
|
| 30 |
+
|
| 31 |
+
## Налаштування для Hugging Face Spaces
|
| 32 |
+
|
| 33 |
+
### Крок 1: Завантажити файли
|
| 34 |
+
Завантажте всі файли проекту до вашого Space:
|
| 35 |
+
- `app.py`
|
| 36 |
+
- `chat_handler.py`
|
| 37 |
+
- `llm_client.py`
|
| 38 |
+
- `menu_loader.py`
|
| 39 |
+
- `menu.txt`
|
| 40 |
+
- `requirements.txt`
|
| 41 |
+
|
| 42 |
+
### Крок 2: Налаштувати API ключ
|
| 43 |
+
1. Перейдіть в Settings вашого Space
|
| 44 |
+
2. Знайдіть розділ "Repository secrets"
|
| 45 |
+
3. Додайте новий Secret:
|
| 46 |
+
- Name: `OPENROUTER_API_KEY`
|
| 47 |
+
- Value: ваш API ключ з [Open Router](https://openrouter.ai/)
|
| 48 |
+
4. Збережіть та перезапустіть Space
|
| 49 |
+
|
| 50 |
+
### Крок 3: Отримати API ключ Open Router
|
| 51 |
+
1. Зареєструйтесь на [openrouter.ai](https://openrouter.ai/)
|
| 52 |
+
2. Перейдіть в розділ Keys
|
| 53 |
+
3. Створіть новий API ключ
|
| 54 |
+
4. Скопіюйте його для використання в Secrets
|
| 55 |
+
|
| 56 |
+
## Локальна розробка
|
| 57 |
+
|
| 58 |
+
### Встановлення залежностей
|
| 59 |
+
```bash
|
| 60 |
+
pip install -r requirements.txt
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
### Налаштування environment variable
|
| 64 |
+
Створіть файл `.env` в корені проекту:
|
| 65 |
+
```
|
| 66 |
+
OPENROUTER_API_KEY=your_api_key_here
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
### Запуск
|
| 70 |
+
```bash
|
| 71 |
+
python app.py
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
Додаток буде доступний за адресою: `http://localhost:7860`
|
| 75 |
+
|
| 76 |
+
## Структура проекту
|
| 77 |
+
|
| 78 |
+
```
|
| 79 |
+
pizzeria-chatbot/
|
| 80 |
+
├── app.py # Головний файл з Gradio інтерфейсом
|
| 81 |
+
├── chat_handler.py # Логіка обробки чату
|
| 82 |
+
├── llm_client.py # Клієнт для Open Router API
|
| 83 |
+
├── menu_loader.py # Завантаження меню з файлу
|
| 84 |
+
├── menu.txt # Меню піцерії
|
| 85 |
+
├── requirements.txt # Python залежності
|
| 86 |
+
└── README.md # Документація
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
## Технології
|
| 90 |
+
|
| 91 |
+
- Python 3.10+
|
| 92 |
+
- Gradio 4.0+
|
| 93 |
+
- Open Router API
|
| 94 |
+
- Hugging Face Spaces
|
| 95 |
+
|
| 96 |
+
## Автор
|
| 97 |
+
|
| 98 |
+
Проект створений як навчальний приклад для початківців у Python розробці.
|
| 99 |
+
|
| 100 |
+
## Ліцензія
|
| 101 |
+
|
| 102 |
+
MIT
|
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Головний файл додатку - Gradio інтерфейс для чат-бота піцерії.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import gradio as gr
|
| 6 |
+
from chat_handler import process_message
|
| 7 |
+
|
| 8 |
+
# Створюємо Gradio ChatInterface
|
| 9 |
+
demo = gr.ChatInterface(
|
| 10 |
+
fn=process_message,
|
| 11 |
+
title="🍕 Чат-бот Піцерії",
|
| 12 |
+
description="Вітаю! Я допоможу вам дізнатися про наше меню. Запитайте мене про піци, напої, ціни або умови доставки!",
|
| 13 |
+
theme=gr.themes.Soft(),
|
| 14 |
+
examples=[
|
| 15 |
+
"Які у вас є піци?",
|
| 16 |
+
"Скільки коштує Маргарита?",
|
| 17 |
+
"Що входить до складу Пепероні?",
|
| 18 |
+
"Які у вас напої?",
|
| 19 |
+
"Який режим роботи?",
|
| 20 |
+
"Умови доставки?"
|
| 21 |
+
],
|
| 22 |
+
retry_btn=None,
|
| 23 |
+
undo_btn=None,
|
| 24 |
+
clear_btn="🗑️ Очистити чат"
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
if __name__ == "__main__":
|
| 28 |
+
demo.launch()
|
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Модуль для обробки логіки чату.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from typing import List, Tuple, Optional
|
| 6 |
+
import menu_loader
|
| 7 |
+
import llm_client
|
| 8 |
+
|
| 9 |
+
# Глобальна змінна для кешування меню
|
| 10 |
+
_menu_cache: Optional[str] = None
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def load_menu_once() -> str:
|
| 14 |
+
"""
|
| 15 |
+
Завантажує меню один раз та кешує його.
|
| 16 |
+
|
| 17 |
+
Returns:
|
| 18 |
+
Текст меню
|
| 19 |
+
|
| 20 |
+
Raises:
|
| 21 |
+
Exception: При помилках завантаження меню
|
| 22 |
+
"""
|
| 23 |
+
global _menu_cache
|
| 24 |
+
|
| 25 |
+
if _menu_cache is None:
|
| 26 |
+
_menu_cache = menu_loader.load_menu()
|
| 27 |
+
|
| 28 |
+
return _menu_cache
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def process_message(message: str, history: List[Tuple[str, str]]) -> str:
|
| 32 |
+
"""
|
| 33 |
+
Обробляє повідомлення користувача та повертає відповідь бота.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
message: Повідомлення від користувача
|
| 37 |
+
history: Історія чату у форматі Gradio [(user_msg, bot_msg), ...]
|
| 38 |
+
|
| 39 |
+
Returns:
|
| 40 |
+
Відповідь бота
|
| 41 |
+
"""
|
| 42 |
+
# Перевірка на порожнє повідомлення
|
| 43 |
+
if not message or not message.strip():
|
| 44 |
+
return "❌ Будь ласка, введіть ваше запитання."
|
| 45 |
+
|
| 46 |
+
# Перевірка на занадто довге повідомлення
|
| 47 |
+
if len(message) > 500:
|
| 48 |
+
return "❌ Повідомлення занадто довге. Будь ласка, сформулюйте коротше (до 500 символів)."
|
| 49 |
+
|
| 50 |
+
try:
|
| 51 |
+
# Завантажуємо меню (lazy loading з кешуванням)
|
| 52 |
+
menu_context = load_menu_once()
|
| 53 |
+
|
| 54 |
+
# Отримуємо відповідь від LLM
|
| 55 |
+
bot_response = llm_client.create_chat_completion(
|
| 56 |
+
user_message=message,
|
| 57 |
+
menu_context=menu_context,
|
| 58 |
+
conversation_history=history
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
return bot_response
|
| 62 |
+
|
| 63 |
+
except FileNotFoundError as e:
|
| 64 |
+
# Помилка відсутності файлу меню
|
| 65 |
+
return str(e)
|
| 66 |
+
|
| 67 |
+
except ValueError as e:
|
| 68 |
+
# Помилка з API ключем
|
| 69 |
+
return str(e)
|
| 70 |
+
|
| 71 |
+
except Exception as e:
|
| 72 |
+
# Інші помилки
|
| 73 |
+
return f"❌ Виникла помилка: {str(e)}"
|
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Модуль для взаємодії з Open Router API.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
from openai import OpenAI
|
| 7 |
+
from typing import Optional
|
| 8 |
+
from dotenv import load_dotenv
|
| 9 |
+
|
| 10 |
+
# Завантажуємо змінні з .env файлу
|
| 11 |
+
load_dotenv()
|
| 12 |
+
|
| 13 |
+
# System prompt для асистента піцерії
|
| 14 |
+
SYSTEM_PROMPT = """Ти - дружній асистент піцерії "Смачна Піца". Твоя задача - допомагати клієнтам з інформацією про меню.
|
| 15 |
+
|
| 16 |
+
ВАЖЛИВІ ПРАВИЛА:
|
| 17 |
+
- Відповідай ТІЛЬКИ українською мовою
|
| 18 |
+
- Будь ввічливим, дружнім та корисним
|
| 19 |
+
- Використовуй ТІЛЬКИ інформацію з наданого меню
|
| 20 |
+
- Якщо клієнт запитує щось не пов'язане з меню (погода, новини, інші теми), ввічливо поясни, що ти можеш допомогти тільки з питаннями про меню піцерії
|
| 21 |
+
- Відповідай коротко та по суті
|
| 22 |
+
- Якщо клієнт не впевнений що замовити, запропонуй варіанти з меню
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class OpenRouterClient:
|
| 27 |
+
"""Клієнт для роботи з Open Router API."""
|
| 28 |
+
|
| 29 |
+
def __init__(self):
|
| 30 |
+
"""Ініціалізація клієнта з перевіркою API ключа."""
|
| 31 |
+
self.api_key = os.getenv("OPENROUTER_API_KEY")
|
| 32 |
+
if not self.api_key:
|
| 33 |
+
raise ValueError(
|
| 34 |
+
"❌ OPENROUTER_API_KEY не встановлено. "
|
| 35 |
+
"Додайте API ключ в environment variables."
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
# Ініціалізуємо OpenAI клієнт з Open Router endpoint
|
| 39 |
+
self.client = OpenAI(
|
| 40 |
+
base_url="https://openrouter.ai/api/v1",
|
| 41 |
+
api_key=self.api_key
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
self.model = "tngtech/deepseek-r1t2-chimera:free"
|
| 45 |
+
self.temperature = 0.7
|
| 46 |
+
self.max_tokens = 500
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def create_chat_completion(
|
| 50 |
+
self,
|
| 51 |
+
user_message: str,
|
| 52 |
+
menu_context: str,
|
| 53 |
+
conversation_history: Optional[list] = None
|
| 54 |
+
) -> str:
|
| 55 |
+
"""
|
| 56 |
+
Відправляє запит до LLM та отримує відповідь.
|
| 57 |
+
|
| 58 |
+
Args:
|
| 59 |
+
user_message: Повідомлення користувача
|
| 60 |
+
menu_context: Контекст меню піцерії
|
| 61 |
+
conversation_history: Історія розмови (опціонально)
|
| 62 |
+
|
| 63 |
+
Returns:
|
| 64 |
+
Відповідь від LLM
|
| 65 |
+
|
| 66 |
+
Raises:
|
| 67 |
+
requests.exceptions.RequestException: При помилках API
|
| 68 |
+
Exception: При інших помилках
|
| 69 |
+
"""
|
| 70 |
+
try:
|
| 71 |
+
# Формуємо повідомлення для API
|
| 72 |
+
messages = [
|
| 73 |
+
{
|
| 74 |
+
"role": "system",
|
| 75 |
+
"content": f"{SYSTEM_PROMPT}\n\nМЕНЮ ПІЦЕРІЇ:\n{menu_context}"
|
| 76 |
+
}
|
| 77 |
+
]
|
| 78 |
+
|
| 79 |
+
# Додаємо історію розмови якщо є
|
| 80 |
+
if conversation_history:
|
| 81 |
+
for user_msg, bot_msg in conversation_history:
|
| 82 |
+
messages.append({"role": "user", "content": user_msg})
|
| 83 |
+
messages.append({"role": "assistant", "content": bot_msg})
|
| 84 |
+
|
| 85 |
+
# Додаємо поточне повідомлення користувача
|
| 86 |
+
messages.append({"role": "user", "content": user_message})
|
| 87 |
+
|
| 88 |
+
# Відправляємо запит через OpenAI SDK
|
| 89 |
+
completion = self.client.chat.completions.create(
|
| 90 |
+
model=self.model,
|
| 91 |
+
messages=messages,
|
| 92 |
+
temperature=self.temperature,
|
| 93 |
+
max_tokens=self.max_tokens,
|
| 94 |
+
timeout=10.0
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
# Отримуємо відповідь
|
| 98 |
+
assistant_message = completion.choices[0].message.content
|
| 99 |
+
return assistant_message.strip()
|
| 100 |
+
|
| 101 |
+
except Exception as e:
|
| 102 |
+
error_message = str(e).lower()
|
| 103 |
+
|
| 104 |
+
# Обробка специфічних помилок
|
| 105 |
+
if "rate limit" in error_message or "429" in error_message:
|
| 106 |
+
return "❌ Перевищено ліміт запитів. Будь ласка, спробуйте через хвилину."
|
| 107 |
+
|
| 108 |
+
if "unauthorized" in error_message or "401" in error_message:
|
| 109 |
+
return "❌ Помилка автентифікації. Перевірте API ключ."
|
| 110 |
+
|
| 111 |
+
if "timeout" in error_message:
|
| 112 |
+
return "❌ Час очікування відповіді вичерпано. Спробуйте ще раз."
|
| 113 |
+
|
| 114 |
+
if "connection" in error_message:
|
| 115 |
+
return "❌ Помилка з'єднання. Перевірте інтернет-з'єднання."
|
| 116 |
+
|
| 117 |
+
# Загальна помилка
|
| 118 |
+
return f"❌ Виникла помилка: {str(e)}"
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
# Глобальний екземпляр клієнта
|
| 122 |
+
_client_instance = None
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def get_client() -> OpenRouterClient:
|
| 126 |
+
"""Отримати глобальний екземпляр клієнта (singleton pattern)."""
|
| 127 |
+
global _client_instance
|
| 128 |
+
if _client_instance is None:
|
| 129 |
+
_client_instance = OpenRouterClient()
|
| 130 |
+
return _client_instance
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def create_chat_completion(
|
| 134 |
+
user_message: str,
|
| 135 |
+
menu_context: str,
|
| 136 |
+
conversation_history: Optional[list] = None
|
| 137 |
+
) -> str:
|
| 138 |
+
"""
|
| 139 |
+
Зручна функція для створення chat completion.
|
| 140 |
+
|
| 141 |
+
Args:
|
| 142 |
+
user_message: Повідомлення користувача
|
| 143 |
+
menu_context: Контекст меню піцерії
|
| 144 |
+
conversation_history: Історія розмови (опціонально)
|
| 145 |
+
|
| 146 |
+
Returns:
|
| 147 |
+
Відповідь від LLM
|
| 148 |
+
"""
|
| 149 |
+
client = get_client()
|
| 150 |
+
return client.create_chat_completion(user_message, menu_context, conversation_history)
|
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
=== МЕНЮ ПІЦЕРІЇ "СМАЧНА ПІЦА" ===
|
| 2 |
+
|
| 3 |
+
ПІЦИ:
|
| 4 |
+
|
| 5 |
+
1. Маргарита - 150 грн
|
| 6 |
+
Інгредієнти: томатний соус, моцарела, базилік, оливкова олія
|
| 7 |
+
Розмір: 30 см
|
| 8 |
+
|
| 9 |
+
2. Пепероні - 180 грн
|
| 10 |
+
Інгредієнти: томатний соус, моцарела, пепероні
|
| 11 |
+
Розмір: 30 см
|
| 12 |
+
|
| 13 |
+
3. Чотири сири - 200 грн
|
| 14 |
+
Інгредієнти: моцарела, пармезан, горгонзола, фета
|
| 15 |
+
Розмір: 30 см
|
| 16 |
+
|
| 17 |
+
4. Гавайська - 170 грн
|
| 18 |
+
Інгредієнти: томатний соус, моцарела, шинка, ананаси
|
| 19 |
+
Розмір: 30 см
|
| 20 |
+
|
| 21 |
+
5. М'ясна - 220 грн
|
| 22 |
+
Інгредієнти: томатний соус, моцарела, салямі, шинка, бекон, курка
|
| 23 |
+
Розмір: 30 см
|
| 24 |
+
|
| 25 |
+
НАПОЇ:
|
| 26 |
+
|
| 27 |
+
1. Кока-кола - 30 грн (0.5л)
|
| 28 |
+
2. Вода - 20 грн (0.5л)
|
| 29 |
+
3. Сік апельсиновий - 35 грн (0.3л)
|
| 30 |
+
4. Сік яблучний - 35 грн (0.3л)
|
| 31 |
+
5. Чай - 25 грн
|
| 32 |
+
|
| 33 |
+
РЕЖИМ РОБОТИ:
|
| 34 |
+
Пн-Нд: 10:00 - 22:00
|
| 35 |
+
|
| 36 |
+
ДОСТАВКА:
|
| 37 |
+
Безкоштовна доставка при замовленні від 300 грн
|
| 38 |
+
Час доставки: 30-45 хвилин
|
| 39 |
+
|
| 40 |
+
КОНТАКТИ:
|
| 41 |
+
Телефон: +380 XX XXX XX XX
|
| 42 |
+
Адреса: м. Київ, вул. Хрещатик, 1
|
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Модуль для завантаження меню піцерії з текстового файлу.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
def load_menu(file_path: str = "menu.txt") -> str:
|
| 6 |
+
"""
|
| 7 |
+
Завантажує меню з текстового файлу.
|
| 8 |
+
|
| 9 |
+
Args:
|
| 10 |
+
file_path: Шлях до файлу меню (за замовчуванням "menu.txt")
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
Текст меню у форматі string
|
| 14 |
+
|
| 15 |
+
Raises:
|
| 16 |
+
FileNotFoundError: Якщо файл не знайдено
|
| 17 |
+
Exception: При інших помилках читання файлу
|
| 18 |
+
"""
|
| 19 |
+
try:
|
| 20 |
+
with open(file_path, 'r', encoding='utf-8') as file:
|
| 21 |
+
menu_content = file.read()
|
| 22 |
+
|
| 23 |
+
if not menu_content.strip():
|
| 24 |
+
raise ValueError("Файл меню порожній")
|
| 25 |
+
|
| 26 |
+
return menu_content
|
| 27 |
+
|
| 28 |
+
except FileNotFoundError:
|
| 29 |
+
raise FileNotFoundError(f"❌ Файл меню '{file_path}' не знайдено. Переконайтесь, що файл існує.")
|
| 30 |
+
|
| 31 |
+
except UnicodeDecodeError:
|
| 32 |
+
raise Exception(f"❌ Помилка кодування файлу '{file_path}'. Файл повинен бути у форматі UTF-8.")
|
| 33 |
+
|
| 34 |
+
except Exception as e:
|
| 35 |
+
raise Exception(f"❌ Помилка читання меню: {str(e)}")
|
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# Скрипт для підготовки файлів до розгортання на Hugging Face
|
| 4 |
+
|
| 5 |
+
echo "🍕 Підготовка файлів для розгортання..."
|
| 6 |
+
|
| 7 |
+
# Створити папку для deployment
|
| 8 |
+
mkdir -p deployment_files
|
| 9 |
+
|
| 10 |
+
# Копіювати необхідні файли
|
| 11 |
+
cp app.py deployment_files/
|
| 12 |
+
cp chat_handler.py deployment_files/
|
| 13 |
+
cp llm_client.py deployment_files/
|
| 14 |
+
cp menu_loader.py deployment_files/
|
| 15 |
+
cp menu.txt deployment_files/
|
| 16 |
+
cp requirements.txt deployment_files/
|
| 17 |
+
cp README.md deployment_files/
|
| 18 |
+
cp .gitignore deployment_files/
|
| 19 |
+
|
| 20 |
+
echo "✅ Файли скопійовані в папку 'deployment_files/'"
|
| 21 |
+
echo ""
|
| 22 |
+
echo "📋 Список файлів для завантаження:"
|
| 23 |
+
ls -1 deployment_files/
|
| 24 |
+
echo ""
|
| 25 |
+
echo "🚀 Наступні кроки:"
|
| 26 |
+
echo "1. Відкрийте https://huggingface.co/spaces/DocSA/pizza_chatbot4"
|
| 27 |
+
echo "2. Натисніть 'Files' → 'Add file' → 'Upload files'"
|
| 28 |
+
echo "3. Завантажте всі файли з папки 'deployment_files/'"
|
| 29 |
+
echo "4. Додайте Secret 'OPENROUTER_API_KEY' в Settings"
|
| 30 |
+
echo ""
|
| 31 |
+
echo "📖 Детальні інструкції в файлі DEPLOYMENT_INSTRUCTIONS.md"
|
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=4.0.0
|
| 2 |
+
openai>=1.0.0
|
| 3 |
+
python-dotenv>=1.0.0
|