DocSA commited on
Commit
72c85ee
·
verified ·
1 Parent(s): 76b43e6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +289 -0
app.py ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import gradio as gr
4
+ from google import genai
5
+ from google.genai import types
6
+ from dotenv import load_dotenv
7
+
8
+ # Завантаження змінних оточення
9
+ load_dotenv()
10
+
11
+ # Отримання API ключа (спершу з HF_ENVIRON, потім з локального .env)
12
+ api_key = os.environ.get("GEMINI_API_KEY")
13
+ if not api_key:
14
+ api_key = os.getenv("GEMINI_API_KEY")
15
+ if not api_key:
16
+ raise ValueError("API ключ не знайдено. Перевірте змінні оточення")
17
+
18
+ # Налаштування клієнта API
19
+ client = genai.Client(api_key=api_key)
20
+
21
+ # Назва моделі
22
+ MODEL_NAME = "gemini-2.5-flash-preview-04-17"
23
+
24
+ def load_menu():
25
+ """Функція для зчитування меню з файлу з покращеною обробкою шляхів"""
26
+ try:
27
+ # Спроба знайти файл відносно поточної директорії
28
+ if os.path.exists('menu.txt'):
29
+ print("Знайдено menu.txt в поточній директорії")
30
+ with open('menu.txt', 'r', encoding='utf-8') as file:
31
+ menu_content = file.read()
32
+ return menu_content
33
+
34
+ # Спроба знайти файл відносно директорії скрипту
35
+ script_dir = os.path.dirname(os.path.abspath(__file__))
36
+ menu_path = os.path.join(script_dir, 'menu.txt')
37
+ if os.path.exists(menu_path):
38
+ print(f"Знайдено menu.txt в директорії скрипту: {menu_path}")
39
+ with open(menu_path, 'r', encoding='utf-8') as file:
40
+ menu_content = file.read()
41
+ return menu_content
42
+
43
+ # Пошук в різних можливих директоріях (для Hugging Face)
44
+ for possible_dir in ['/app', '/home/user', '/content', '/workspace']:
45
+ menu_path = os.path.join(possible_dir, 'menu.txt')
46
+ if os.path.exists(menu_path):
47
+ print(f"Знайдено menu.txt в: {menu_path}")
48
+ with open(menu_path, 'r', encoding='utf-8') as file:
49
+ menu_content = file.read()
50
+ return menu_content
51
+
52
+ # Якщо файл не знайдено
53
+ print("ПОМИЛКА: Файл menu.txt не знайдено в жодній з директорій")
54
+ # Резервний вміст меню для демонстрації
55
+ return """# МЕНЮ ПІЦЕРІЇ "СМАЧНА ПІЦА" (РЕЗЕРВНА КОПІЯ)
56
+
57
+ ## КЛАСИЧНІ ПІЦИ
58
+
59
+ МАРГАРИТА
60
+ Опис: Класична піца з томатним соусом, моцарелою та базиліком
61
+ Інгредієнти: томатний соус, сир моцарела, свіжий базилік, оливкова олія
62
+ Розмір: 30 см | Ціна: 160 грн
63
+ Розмір: 40 см | Ціна: 220 грн
64
+
65
+ ПЕПЕРОНІ
66
+ Опис: Піца з пікантною ковбаскою пепероні
67
+ Інгредієнти: томатний соус, сир моцарела, пепероні
68
+ Розмір: 30 см | Ціна: 180 грн
69
+ Розмір: 40 см | Ціна: 250 грн"""
70
+
71
+ except Exception as e:
72
+ print(f"Помилка при зчитуванні меню: {str(e)}")
73
+ return "Меню тимчасово недоступне. Будь ласка, зверніться до адміністратора."
74
+
75
+ # Глобальна змінна для зберігання меню
76
+ menu_data = None
77
+
78
+ def get_menu():
79
+ """Повертає поточне меню, з можливістю оновлення"""
80
+ global menu_data
81
+ # Перше завантаження або оновлення меню кожну годину
82
+ if menu_data is None or not hasattr(get_menu, "last_update") or time.time() - get_menu.last_update > 3600:
83
+ menu_data = load_menu()
84
+ get_menu.last_update = time.time()
85
+
86
+ # Перевірка завантаження меню
87
+ if "Меню тимчасово недоступне" in menu_data:
88
+ print("УВАГА: Меню не завантажено коректно! Перевірте файл menu.txt")
89
+ else:
90
+ print(f"Меню успішно завантажено. Розмір: {len(menu_data)} символів")
91
+
92
+ return menu_data
93
+
94
+ def create_system_prompt():
95
+ """Створює системний промпт для моделі з меню піцерії"""
96
+ current_menu = get_menu()
97
+ return f"""
98
+ Ти дружній чат-бот української піцерії "Смачна Піца".
99
+ Твоє завдання - допомагати клієнтам дізнатися про меню, ціни, інгредієнти та доставку.
100
+
101
+ Дотримуйся цих правил:
102
+ 1. Завжди будь ввічливим і дружнім
103
+ 2. Відповідай ТІЛЬКИ на основі наданого меню
104
+ 3. Якщо клієнт запитує про щось, чого немає в меню, скажи, що такого у меню немає, але можеш запропонувати схожі опції
105
+ 4. Завжди пиши українською мовою
106
+ 5. Твої відповіді мають бути короткими і по суті
107
+ 6. Пам'ятай всю попередню розмову з клієнтом і використовуй цю інформацію
108
+ 7. Якщо клієнт раніше цікавився певними піцами, використовуй цю інформацію для рекомендацій
109
+
110
+ Ось актуальне меню:
111
+
112
+ {current_menu}
113
+ """
114
+
115
+ def extract_client_preferences(history):
116
+ """Аналізує історію розмови та виявляє уподобання клієнта"""
117
+ preferences = {
118
+ "піци": [],
119
+ "розмір": "",
120
+ "додатки": [],
121
+ "напої": []
122
+ }
123
+
124
+ # Аналіз історії повідомлень
125
+ for human_msg, _ in history:
126
+ human_msg = human_msg.lower()
127
+
128
+ # Виявлення вподобань щодо піц
129
+ for pizza in ["маргарита", "пепероні", "гавайська", "чотири сири", "карбонара", "барбекю", "вегетаріанська", "грибна"]:
130
+ if pizza in human_msg and pizza not in preferences["піци"]:
131
+ preferences["піци"].append(pizza)
132
+
133
+ # Виявлення вподобань щодо розміру
134
+ if "30 см" in human_msg:
135
+ preferences["розмір"] = "30 см"
136
+ if "40 см" in human_msg:
137
+ preferences["розмір"] = "40 см"
138
+
139
+ # Виявлення вподобань щодо додатків
140
+ for addition in ["часниковий соус", "кетчуп", "сирний соус"]:
141
+ if addition in human_msg and addition not in preferences["додатки"]:
142
+ preferences["додатки"].append(addition)
143
+
144
+ # Виявлення вподобань щодо напоїв
145
+ for drink in ["кола", "спрайт", "мінеральна вода"]:
146
+ if drink in human_msg and drink not in preferences["напої"]:
147
+ preferences["напої"].append(drink)
148
+
149
+ return preferences
150
+
151
+ def enhance_system_prompt(history):
152
+ """Створює розширений системний промпт з урахуванням уподобань клієнта"""
153
+ base_prompt = create_system_prompt()
154
+
155
+ if not history:
156
+ return base_prompt
157
+
158
+ preferences = extract_client_preferences(history)
159
+
160
+ # Додаємо інформацію про уподобання клієнта до промпту
161
+ preferences_prompt = "\nІнформація про уподобання клієнта на основі історії розмови:\n"
162
+
163
+ if preferences["піци"]:
164
+ preferences_prompt += f"- Клієнт цікавився такими піцами: {', '.join(preferences['піци'])}\n"
165
+
166
+ if preferences["розмір"]:
167
+ preferences_prompt += f"- Клієнт цікавився розміром: {preferences['розмір']}\n"
168
+
169
+ if preferences["додатки"]:
170
+ preferences_prompt += f"- Клієнт цікавився такими додатками: {', '.join(preferences['додатки'])}\n"
171
+
172
+ if preferences["напої"]:
173
+ preferences_prompt += f"- Клієнт цікавився такими напоями: {', '.join(preferences['напої'])}\n"
174
+
175
+ enhanced_prompt = base_prompt + preferences_prompt
176
+ return enhanced_prompt
177
+
178
+ def chat_with_history(message, history):
179
+ """Функція для чату з історією розмови"""
180
+ try:
181
+ # Перетворюємо історію розмови у формат для API
182
+ conversation = []
183
+
184
+ # Додаємо попередні повідомлення з історії
185
+ for human_msg, bot_msg in history:
186
+ conversation.append(
187
+ types.Content(
188
+ role="user",
189
+ parts=[types.Part.from_text(text=human_msg)]
190
+ )
191
+ )
192
+ conversation.append(
193
+ types.Content(
194
+ role="model",
195
+ parts=[types.Part.from_text(text=bot_msg)]
196
+ )
197
+ )
198
+
199
+ # Додаємо поточне повідомлення
200
+ conversation.append(
201
+ types.Content(
202
+ role="user",
203
+ parts=[types.Part.from_text(text=message)]
204
+ )
205
+ )
206
+
207
+ # Створюємо розширений системний промпт на основі історії
208
+ enhanced_prompt = enhance_system_prompt(history)
209
+
210
+ # Конфігурація для запиту
211
+ generate_content_config = types.GenerateContentConfig(
212
+ response_mime_type="text/plain",
213
+ system_instruction=[
214
+ types.Part.from_text(text=enhanced_prompt),
215
+ ],
216
+ )
217
+
218
+ # Відправляємо запит до моделі
219
+ response = client.models.generate_content(
220
+ model=MODEL_NAME,
221
+ contents=conversation,
222
+ config=generate_content_config,
223
+ )
224
+
225
+ return response.text
226
+
227
+ except Exception as e:
228
+ error_message = str(e)
229
+ print(f"Помилка при зверненні до API: {error_message}")
230
+
231
+ # Повертаємо зрозуміле повідомлення про помилку
232
+ if "rate limit" in error_message.lower():
233
+ return "Вибачте, зараз я отримую забагато запитів. Будь ласка, спробуйте знову через кілька хвилин."
234
+ elif "api key" in error_message.lower():
235
+ return "Виникла помилка з аутентифікацією. Будь ласка, повідомте адміністратора."
236
+ else:
237
+ return f"Вибачте, виникла технічна проблема. Спробуйте повторити запитання або зв'яжіться з піцерією за телефоном."
238
+
239
+ def display_menu():
240
+ """Функція для відображення поточного меню"""
241
+ return get_menu()
242
+
243
+ # Створюємо розширений інтерфейс з вкладками
244
+ with gr.Blocks(theme="soft") as demo:
245
+ gr.Markdown("# Чат-бот піцерії 'Смачна Піца'")
246
+ gr.Markdown("Вітаю! Я чат-бот піцерії 'Смачна Піца'. Запитайте мене про меню, ціни, інгредієнти або доставку.")
247
+
248
+ with gr.Tab("Чат"):
249
+ chatbot = gr.ChatInterface(
250
+ fn=chat_with_history,
251
+ examples=[
252
+ "Які у вас є піци?",
253
+ "Розкажи про піцу Пепероні",
254
+ "Скільки коштує доставка?",
255
+ "Які у вас є вегетаріанські піци?",
256
+ "Що порадиш з напоїв?",
257
+ "О котрій годині ви працюєте?"
258
+ ]
259
+ )
260
+
261
+ with gr.Tab("Меню"):
262
+ gr.Markdown(get_menu())
263
+
264
+ with gr.Tab("Про нас"):
265
+ gr.Markdown("""
266
+ # Піцерія "Смачна Піца"
267
+
268
+ Ми пропонуємо найсмачнішу піцу в місті, приготовану з найсвіжіших інгредієнтів!
269
+
270
+ ## Контактна інформація
271
+
272
+ 📞 Телефон: 067-123-4567
273
+ 🕒 Години роботи: щодня з 10:00 до 22:00
274
+ 🏠 Адреса: вул. Піцерійна, 1
275
+
276
+ ## Доставка
277
+
278
+ Безкоштовна доставка при замовленні від 300 грн
279
+ Час доставки: 30-60 хвилин
280
+ Зона доставки: в межах міста
281
+ """)
282
+
283
+ # Завантажуємо меню перед стартом
284
+ print("Ініціалізація програми...")
285
+ get_menu()
286
+
287
+ if __name__ == "__main__":
288
+ print("Запуск чат-бота піцерії...")
289
+ demo.launch(share=True) # share=True для генерації публічного посилання