Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -1,25 +1,43 @@
|
|
1 |
# app.py
|
2 |
-
|
3 |
import gradio as gr
|
4 |
from transformers import pipeline, set_seed
|
5 |
import random
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
-
# Загружаем модель для генерации текста (text-generation pipeline)
|
8 |
-
# Выберите модель:
|
9 |
-
# 'distilgpt2' - маленькая английская модель GPT-2
|
10 |
-
# 'sberbank-ai/rugpt3small_based_on_gpt2' - маленькая русская модель (может требовать больше ресурсов)
|
11 |
-
# 'bigscience/bloomz-560m' - многоязычная модель поменьше (может быть медленной на CPU)
|
12 |
-
|
13 |
-
# Попробуем с distilgpt2 для начала, т.к. она легче всего запустится на CPU
|
14 |
-
# Если хотите русскую, раскомментируйте строку с 'sberbank-ai...' и закомментируйте distilgpt2
|
15 |
-
# generator = pipeline('text-generation', model='distilgpt2', max_new_tokens=50) # Ограничим длину генерации
|
16 |
-
# generator = pipeline('text-generation', model='sberbank-ai/rugpt3small_based_on_gpt2', max_new_tokens=50)
|
17 |
-
generator = pipeline('text-generation', model='distilgpt2', max_length=70, num_return_sequences=1, truncation=True) # Альтернативные параметры
|
18 |
-
|
19 |
-
print("Модель загружена!") # Для отладки в логах
|
20 |
-
|
21 |
-
# Установка зерна для воспроизводимости (опционально)
|
22 |
-
# set_seed(random.randint(0, 10000)) # Используем случайное зерно для разнообразия
|
23 |
|
24 |
# Функция, которая будет обрабатывать ввод пользователя и историю чата
|
25 |
def respond(message, chat_history):
|
@@ -27,70 +45,98 @@ def respond(message, chat_history):
|
|
27 |
Принимает сообщение пользователя и историю чата, возвращает ответ бота.
|
28 |
"""
|
29 |
print(f"Получено сообщение: {message}")
|
30 |
-
print(f"История
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
-
|
33 |
-
# Вариант 1: Просто сообщение пользователя
|
34 |
-
prompt = message
|
35 |
|
36 |
-
#
|
37 |
-
|
38 |
-
|
39 |
|
40 |
try:
|
41 |
# Генерируем ответ
|
42 |
-
#
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
-
bot_response = generator(prompt)[0]['generated_text']
|
47 |
|
48 |
-
#
|
49 |
-
# (
|
50 |
-
|
51 |
-
|
|
|
|
|
52 |
|
53 |
-
#
|
54 |
if not bot_response or len(bot_response.strip()) == 0:
|
55 |
-
bot_response = "... (модель не сгенерировала ответ)"
|
56 |
|
57 |
-
print(f"Сгенерированный
|
58 |
|
59 |
except Exception as e:
|
60 |
print(f"Ошибка при генерации: {e}")
|
61 |
-
|
|
|
|
|
|
|
|
|
62 |
|
63 |
# Добавляем пару (сообщение пользователя, ответ бота) в историю
|
64 |
chat_history.append((message, bot_response))
|
|
|
65 |
|
66 |
# Возвращаем пустую строку для очистки поля ввода и обновленную историю
|
67 |
return "", chat_history
|
68 |
|
69 |
-
# --- Создание интерфейса Gradio ---
|
70 |
with gr.Blocks() as demo:
|
71 |
-
gr.Markdown("#
|
72 |
-
gr.Markdown("
|
73 |
-
|
74 |
-
# Компонент чат-бота
|
75 |
-
chatbot = gr.Chatbot(label="Диалог")
|
76 |
-
|
77 |
-
# Поле ввода текста
|
78 |
-
msg = gr.Textbox(label="Ваше сообщение", placeholder="Напишите что-нибудь...")
|
79 |
|
80 |
-
#
|
|
|
81 |
clear = gr.Button("Очистить диалог")
|
82 |
|
83 |
-
# Связываем компоненты:
|
84 |
-
# Когда пользователь отправляет сообщение (нажатием Enter в Textbox или Button, если бы она была)
|
85 |
-
# вызывается функция respond с текущим сообщением и историей чата.
|
86 |
-
# Результат функции (пустая строка и новая история) обновляет Textbox (msg) и Chatbot (chatbot).
|
87 |
msg.submit(respond, [msg, chatbot], [msg, chatbot])
|
|
|
88 |
|
89 |
-
# Связываем кнопку очистки
|
90 |
-
clear.click(lambda: (None, None), None, [msg, chatbot], queue=False)
|
91 |
|
92 |
# Запускаем демо
|
93 |
-
|
94 |
-
# share=True
|
95 |
-
|
96 |
-
|
|
|
|
1 |
# app.py
|
|
|
2 |
import gradio as gr
|
3 |
from transformers import pipeline, set_seed
|
4 |
import random
|
5 |
+
import torch # Может понадобиться для указания устройства
|
6 |
+
|
7 |
+
# --- Настройки ---
|
8 |
+
# Выбираем русскую модель
|
9 |
+
# Попробуем 'sberbank-ai/rugpt3small_based_on_gpt2'.
|
10 |
+
# Если Space будет падать из-за нехватки памяти, возможно, придется вернуться к distilgpt2
|
11 |
+
# или искать еще более легкую модель.
|
12 |
+
MODEL_NAME = 'sberbank-ai/rugpt3small_based_on_gpt2'
|
13 |
+
# MODEL_NAME = 'distilgpt2' # Запасной вариант
|
14 |
+
|
15 |
+
# Параметры генерации
|
16 |
+
MAX_NEW_TOKENS = 100 # Увеличим максимальную длину *нового* текста
|
17 |
+
TEMPERATURE = 0.8 # Температура генерации (чуть больше случайности, >1 = больше бреда)
|
18 |
+
TOP_P = 0.9 # Ядерная выборка (nucleus sampling)
|
19 |
+
# --- Конец Настроек ---
|
20 |
+
|
21 |
+
|
22 |
+
print(f"Загрузка модели: {MODEL_NAME}...")
|
23 |
+
try:
|
24 |
+
# Попробуем указать device_map='auto' для лучшего распределения на ресурсах Space
|
25 |
+
# или torch_dtype=torch.float16 для экономии памяти (если поддерживается)
|
26 |
+
generator = pipeline(
|
27 |
+
'text-generation',
|
28 |
+
model=MODEL_NAME,
|
29 |
+
# Если есть GPU и CUDA: device=0
|
30 |
+
# Для CPU или автоматического определения: device=-1 (по умолчанию)
|
31 |
+
# Попробуем автоматическое распределение:
|
32 |
+
# device_map="auto", # Может помочь с памятью на много-GPU инстансах (редко в free Spaces)
|
33 |
+
# torch_dtype=torch.float16, # Если модель поддерживает и есть CUDA, ускорит и сэкономит память
|
34 |
+
)
|
35 |
+
print("Модель успешно загружена!")
|
36 |
+
except Exception as e:
|
37 |
+
print(f"Ошибка при загрузке модели: {e}")
|
38 |
+
# Завершаем работу, если модель не загрузилась
|
39 |
+
raise SystemExit(f"Не удалось загрузить модель {MODEL_NAME}. Ошибка: {e}")
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
# Функция, которая будет обрабатывать ввод пользователя и историю чата
|
43 |
def respond(message, chat_history):
|
|
|
45 |
Принимает сообщение пользователя и историю чата, возвращает ответ бота.
|
46 |
"""
|
47 |
print(f"Получено сообщение: {message}")
|
48 |
+
print(f"История чата (до): {chat_history}")
|
49 |
+
|
50 |
+
# --- Улучшенный Промпт ---
|
51 |
+
# Добавляем инструкцию/роль для бота (можно сделать сложнее)
|
52 |
+
system_prompt = "Ты — дружелюбный и полезный ИИ-ассистент. Отвечай на вопросы пользователя."
|
53 |
+
|
54 |
+
# Формируем историю для промпта (последние N обменов)
|
55 |
+
history_limit = 3 # Сколько последних пар "вопрос-ответ" учитывать
|
56 |
+
history_for_prompt = []
|
57 |
+
for user_msg, bot_msg in chat_history[-history_limit:]:
|
58 |
+
history_for_prompt.append(f"По��ьзователь: {user_msg}")
|
59 |
+
history_for_prompt.append(f"Ассистент: {bot_msg}")
|
60 |
|
61 |
+
history_str = "\n".join(history_for_prompt)
|
|
|
|
|
62 |
|
63 |
+
# Собираем финальный промпт
|
64 |
+
prompt = f"{system_prompt}\n\n{history_str}\nПользователь: {message}\nАссистент:"
|
65 |
+
print(f"--- Промпт для модели --- \n{prompt}\n------------------------")
|
66 |
|
67 |
try:
|
68 |
# Генерируем ответ
|
69 |
+
# Используем max_new_tokens для контроля длины именно ответа
|
70 |
+
generated_outputs = generator(
|
71 |
+
prompt,
|
72 |
+
max_new_tokens=MAX_NEW_TOKENS,
|
73 |
+
num_return_sequences=1,
|
74 |
+
# truncation=True, # Трункация уже не так нужна, если мы контролируем длину истории
|
75 |
+
do_sample=True, # Включаем сэмплирование для более "живых" ответов
|
76 |
+
temperature=TEMPERATURE,
|
77 |
+
top_p=TOP_P,
|
78 |
+
# pad_token_id=generator.tokenizer.eos_token_id # Указываем токен для паддинга
|
79 |
+
)
|
80 |
+
bot_response = generated_outputs[0]['generated_text']
|
81 |
+
|
82 |
+
# --- Очистка ответа ---
|
83 |
+
# Убираем весь промпт из сгенерированного текста
|
84 |
+
if bot_response.startswith(prompt):
|
85 |
+
bot_response = bot_response[len(prompt):].strip()
|
86 |
+
else:
|
87 |
+
# Иногда модель может начать ответ сразу, без повторения промпта,
|
88 |
+
# но может повторить последнюю часть (например, "Ассистент:")
|
89 |
+
# Это требует более сложной очистки, пока оставим базовую.
|
90 |
+
# Можно попробовать убирать только последнюю строку промпта:
|
91 |
+
last_prompt_line = "Ассистент:"
|
92 |
+
if bot_response.strip().startswith(last_prompt_line):
|
93 |
+
bot_response = bot_response.strip()[len(last_prompt_line):].strip()
|
94 |
|
|
|
95 |
|
96 |
+
# Дополнительная очистка от незавершенных предложений или артефактов
|
97 |
+
# (можно добавить обрезку по последнему знаку препинания .?!)
|
98 |
+
last_punctuation = max(bot_response.rfind('.'), bot_response.rfind('!'), bot_response.rfind('?'))
|
99 |
+
if last_punctuation != -1:
|
100 |
+
bot_response = bot_response[:last_punctuation+1]
|
101 |
+
|
102 |
|
103 |
+
# Проверка на пустой ответ
|
104 |
if not bot_response or len(bot_response.strip()) == 0:
|
105 |
+
bot_response = "... (модель не сгенерировала содержательный ответ)"
|
106 |
|
107 |
+
print(f"Сгенерированный ответ (очищенный): {bot_response}")
|
108 |
|
109 |
except Exception as e:
|
110 |
print(f"Ошибка при генерации: {e}")
|
111 |
+
# Попробуем дать более специфичную информацию, если возможно
|
112 |
+
if "out of memory" in str(e).lower():
|
113 |
+
bot_response = "Ой, кажется, мне не хватило памяти для генерации ответа. Попробуйте более короткий запрос или администратор может попробовать модель поменьше."
|
114 |
+
else:
|
115 |
+
bot_response = f"Ой, произошла ошибка при генерации ответа: {e}"
|
116 |
|
117 |
# Добавляем пару (сообщение пользователя, ответ бота) в историю
|
118 |
chat_history.append((message, bot_response))
|
119 |
+
print(f"История чата (после): {chat_history}")
|
120 |
|
121 |
# Возвращаем пустую строку для очистки поля ввода и обновленную историю
|
122 |
return "", chat_history
|
123 |
|
124 |
+
# --- Создание интерфейса Gradio (остается почти без изменений) ---
|
125 |
with gr.Blocks() as demo:
|
126 |
+
gr.Markdown("# Улучшенный Чат-Бот на Hugging Face")
|
127 |
+
gr.Markdown(f"Используемая модель: `{MODEL_NAME}`. Введите ваше сообщение.")
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
chatbot = gr.Chatbot(label="Диалог", height=500) # Увеличим высоту окна чата
|
130 |
+
msg = gr.Textbox(label="Ваше сообщение", placeholder="Спроси меня что-нибудь...")
|
131 |
clear = gr.Button("Очистить диалог")
|
132 |
|
|
|
|
|
|
|
|
|
133 |
msg.submit(respond, [msg, chatbot], [msg, chatbot])
|
134 |
+
clear.click(lambda: (None, []), None, [msg, chatbot], queue=False) # Очищаем историю на пустой список []
|
135 |
|
|
|
|
|
136 |
|
137 |
# Запускаем демо
|
138 |
+
print("Запуск Gradio интерфейса...")
|
139 |
+
# Используйте share=True только если запускаете локально и хотите временную публичную ссылку
|
140 |
+
# Для HF Spaces это не нужно.
|
141 |
+
demo.launch(debug=True)
|
142 |
+
# demo.launch(server_name="0.0.0.0", server_port=7860)
|