MrAlexGov commited on
Commit
c3da58c
·
verified ·
1 Parent(s): 70405cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -33
app.py CHANGED
@@ -1,10 +1,13 @@
1
  import gradio as gr
2
- from transformers import pipeline, AutoTokenizer
3
  from typing import List, Dict, Any, Tuple
4
  import torch
 
 
 
 
5
 
6
  # CPU-модели (только одна маленькая модель для экономии памяти)
7
- # Исправлено: используем словарь вместо множества
8
  MODELS = {
9
  "Qwen2.5-0.5B": "Qwen/Qwen2.5-0.5B-Instruct",
10
  "Qwen2.5-1.5B": "Qwen/Qwen2.5-1.5B-Instruct",
@@ -13,23 +16,39 @@ MODELS = {
13
  def load_model(model_key: str):
14
  model_id = MODELS[model_key]
15
  print(f"🚀 Загрузка {model_id}...")
 
16
  tokenizer = AutoTokenizer.from_pretrained(model_id)
17
  if tokenizer.pad_token is None:
18
  tokenizer.pad_token = tokenizer.eos_token
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  pipe = pipeline(
21
  "text-generation",
22
- model=model_id,
23
  tokenizer=tokenizer,
24
- torch_dtype=torch.float32, # Use float32 for CPU
25
- device_map=None, # Explicitly set to CPU
26
  max_new_tokens=128, # Ещё меньше токенов для экономии памяти
27
  do_sample=True,
28
  temperature=0.7,
29
- pad_token_id=tokenizer.eos_token_id,
30
- # Memory optimization parameters
31
- low_cpu_mem_usage=True,
32
- trust_remote_code=True
33
  )
34
  print(f"✅ {model_id} загружена!")
35
  return pipe
@@ -57,50 +76,112 @@ def respond(message: str,
57
  messages.append({"role": "user", "content": message})
58
 
59
  tokenizer = pipe.tokenizer
60
- prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
61
 
62
- outputs = pipe(prompt, max_new_tokens=512, do_sample=True, temperature=0.7)
63
- bot_reply = outputs[0]["generated_text"][len(prompt):].strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  print(f"✅ Ответ: {bot_reply[:50]}...")
66
 
67
- new_history = history + [{"role": "user", "content": message}, {"role": "assistant", "content": bot_reply}]
 
 
 
68
  return new_history, "", gr.update(value="")
69
 
70
  except Exception as e:
71
  error_msg = f"❌ {model_key}: {str(e)}"
72
  print(f"💥 {error_msg}")
73
- new_history = history + [{"role": "user", "content": message}, {"role": "assistant", "content": error_msg}]
 
 
 
74
  return new_history, error_msg, gr.update(value="")
75
 
76
- with gr.Blocks(title="🚀 Локальный HF Чат (на слабом CPU!)") as demo:
77
- gr.Markdown("# Локальный Inference (без API!)\n**Маленькие модели** — 1-3 сек CPU. Большие думают ооочень долго. Нет limits/token. В качестве примера.")
 
 
 
 
 
78
 
79
  with gr.Row():
80
- # Исправлено: первое значение должно быть ключом из словаря MODELS
81
- model_dropdown = gr.Dropdown(choices=list(MODELS.keys()), value="Qwen2.5-0.5B", label="🧠 Модель")
82
- system_prompt = gr.Textbox(label="📝 System", placeholder="Ты весёлый ИИ.", lines=2)
 
 
 
 
 
 
 
 
 
83
 
84
- chatbot = gr.Chatbot(height=500, label="Чат") # ← без type
 
 
 
 
85
 
86
  with gr.Row():
87
- msg_input = gr.Textbox(placeholder="Привет! (Enter)", show_label=False, lines=1)
88
- send_btn = gr.Button("📤 Отправить", variant="primary")
 
 
 
 
 
89
 
90
  with gr.Row():
91
- clear_btn = gr.Button("🗑️ Очистить")
92
- retry_btn = gr.Button("🔄 Повторить")
93
 
94
- status = gr.Textbox(label="Логи", interactive=False, lines=4)
95
-
96
- send_btn.click(fn=respond, inputs=[msg_input, chatbot, model_dropdown, system_prompt], outputs=[chatbot, status, msg_input])
97
- msg_input.submit(fn=respond, inputs=[msg_input, chatbot, model_dropdown, system_prompt], outputs=[chatbot, status, msg_input])
 
 
98
 
99
- def clear():
 
100
  return [], "", gr.update(value="")
101
- clear_btn.click(clear, outputs=[chatbot, status, msg_input])
102
 
103
- def retry(history: List[Dict[str, str]]):
104
  if history:
105
  last_user_msg = None
106
  for msg in reversed(history):
@@ -109,7 +190,48 @@ with gr.Blocks(title="🚀 Локальный HF Чат (на слабом CPU!)
109
  break
110
  return last_user_msg if last_user_msg else ""
111
  return ""
112
- retry_btn.click(retry, inputs=[chatbot], outputs=[msg_input])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
  if __name__ == "__main__":
115
- demo.queue(max_size=10).launch(debug=True, ssr_mode=False)
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
3
  from typing import List, Dict, Any, Tuple
4
  import torch
5
+ import warnings
6
+
7
+ # Подавляем ненужные предупреждения
8
+ warnings.filterwarnings("ignore", message=".*low_cpu_mem_usage.*")
9
 
10
  # CPU-модели (только одна маленькая модель для экономии памяти)
 
11
  MODELS = {
12
  "Qwen2.5-0.5B": "Qwen/Qwen2.5-0.5B-Instruct",
13
  "Qwen2.5-1.5B": "Qwen/Qwen2.5-1.5B-Instruct",
 
16
  def load_model(model_key: str):
17
  model_id = MODELS[model_key]
18
  print(f"🚀 Загрузка {model_id}...")
19
+
20
  tokenizer = AutoTokenizer.from_pretrained(model_id)
21
  if tokenizer.pad_token is None:
22
  tokenizer.pad_token = tokenizer.eos_token
23
 
24
+ # Сначала загружаем модель отдельно с оптимизацией памяти
25
+ try:
26
+ model = AutoModelForCausalLM.from_pretrained(
27
+ model_id,
28
+ torch_dtype=torch.float32,
29
+ device_map=None, # Используем CPU
30
+ low_cpu_mem_usage=True,
31
+ trust_remote_code=True
32
+ )
33
+ except Exception as e:
34
+ print(f"⚠️ Не удалось загрузить с low_cpu_mem_usage: {e}")
35
+ print("🔄 Пробуем без low_cpu_mem_usage...")
36
+ model = AutoModelForCausalLM.from_pretrained(
37
+ model_id,
38
+ torch_dtype=torch.float32,
39
+ trust_remote_code=True
40
+ )
41
+
42
+ # Затем создаем pipeline
43
  pipe = pipeline(
44
  "text-generation",
45
+ model=model,
46
  tokenizer=tokenizer,
47
+ device=-1, # Явно указываем CPU (-1 означает CPU)
 
48
  max_new_tokens=128, # Ещё меньше токенов для экономии памяти
49
  do_sample=True,
50
  temperature=0.7,
51
+ pad_token_id=tokenizer.eos_token_id
 
 
 
52
  )
53
  print(f"✅ {model_id} загружена!")
54
  return pipe
 
76
  messages.append({"role": "user", "content": message})
77
 
78
  tokenizer = pipe.tokenizer
 
79
 
80
+ # Используем чат-шаблон для Qwen моделей
81
+ try:
82
+ prompt = tokenizer.apply_chat_template(
83
+ messages,
84
+ tokenize=False,
85
+ add_generation_prompt=True
86
+ )
87
+ except Exception as e:
88
+ print(f"⚠️ Ошибка применения чат-шаблона: {e}")
89
+ # Альтернативный способ форматирования
90
+ prompt = ""
91
+ for msg in messages:
92
+ if msg["role"] == "system":
93
+ prompt += f"System: {msg['content']}\n\n"
94
+ elif msg["role"] == "user":
95
+ prompt += f"User: {msg['content']}\n\n"
96
+ elif msg["role"] == "assistant":
97
+ prompt += f"Assistant: {msg['content']}\n\n"
98
+ prompt += "Assistant:"
99
+
100
+ outputs = pipe(
101
+ prompt,
102
+ max_new_tokens=256, # Уменьшил для экономии памяти
103
+ do_sample=True,
104
+ temperature=0.7,
105
+ repetition_penalty=1.1
106
+ )
107
+
108
+ # Извлекаем ответ
109
+ generated_text = outputs[0]["generated_text"]
110
+ if generated_text.startswith(prompt):
111
+ bot_reply = generated_text[len(prompt):].strip()
112
+ else:
113
+ bot_reply = generated_text.strip()
114
 
115
  print(f"✅ Ответ: {bot_reply[:50]}...")
116
 
117
+ new_history = history + [
118
+ {"role": "user", "content": message},
119
+ {"role": "assistant", "content": bot_reply}
120
+ ]
121
  return new_history, "", gr.update(value="")
122
 
123
  except Exception as e:
124
  error_msg = f"❌ {model_key}: {str(e)}"
125
  print(f"💥 {error_msg}")
126
+ new_history = history + [
127
+ {"role": "user", "content": message},
128
+ {"role": "assistant", "content": error_msg}
129
+ ]
130
  return new_history, error_msg, gr.update(value="")
131
 
132
+ with gr.Blocks(title="🚀 Локальный HF Чат (на слабом CPU!)", theme=gr.themes.Soft()) as demo:
133
+ gr.Markdown("""
134
+ # 🚀 Локальный Inference (без API!)
135
+ **Маленькие модели** — 1-3 сек CPU. Большие думают ооочень долго. Нет limits/token. В качестве примера.
136
+
137
+ ⚠️ **Внимание**: Модели загружаются при первшем выборе и могут занять несколько минут!
138
+ """)
139
 
140
  with gr.Row():
141
+ model_dropdown = gr.Dropdown(
142
+ choices=list(MODELS.keys()),
143
+ value="Qwen2.5-0.5B",
144
+ label="🧠 Модель",
145
+ info="Выберите модель (загрузка при первшем использовании)"
146
+ )
147
+ system_prompt = gr.Textbox(
148
+ label="📝 System Prompt",
149
+ placeholder="Ты весёлый и полезный ИИ-ассистент.",
150
+ lines=2,
151
+ value="Ты весёлый и полезный ИИ-ассистент."
152
+ )
153
 
154
+ chatbot = gr.Chatbot(
155
+ height=400,
156
+ label="Чат",
157
+ avatar_images=(None, "🤖")
158
+ )
159
 
160
  with gr.Row():
161
+ msg_input = gr.Textbox(
162
+ placeholder="Напишите сообщение... (Enter для отправки)",
163
+ show_label=False,
164
+ lines=2,
165
+ scale=4
166
+ )
167
+ send_btn = gr.Button("📤 Отправить", variant="primary", scale=1)
168
 
169
  with gr.Row():
170
+ clear_btn = gr.Button("🗑️ Очистить историю", variant="secondary")
171
+ retry_btn = gr.Button("🔄 Повторить последнее", variant="secondary")
172
 
173
+ status = gr.Textbox(
174
+ label="Статус",
175
+ interactive=False,
176
+ lines=3,
177
+ placeholder="Здесь будут отображаться логи работы..."
178
+ )
179
 
180
+ # Обработчики событий
181
+ def clear_chat():
182
  return [], "", gr.update(value="")
 
183
 
184
+ def retry_last(history: List[Dict[str, str]]):
185
  if history:
186
  last_user_msg = None
187
  for msg in reversed(history):
 
190
  break
191
  return last_user_msg if last_user_msg else ""
192
  return ""
193
+
194
+ # Привязка событий
195
+ send_btn.click(
196
+ fn=respond,
197
+ inputs=[msg_input, chatbot, model_dropdown, system_prompt],
198
+ outputs=[chatbot, status, msg_input]
199
+ )
200
+
201
+ msg_input.submit(
202
+ fn=respond,
203
+ inputs=[msg_input, chatbot, model_dropdown, system_prompt],
204
+ outputs=[chatbot, status, msg_input]
205
+ )
206
+
207
+ clear_btn.click(
208
+ fn=clear_chat,
209
+ outputs=[chatbot, status, msg_input]
210
+ )
211
+
212
+ retry_btn.click(
213
+ fn=retry_last,
214
+ inputs=[chatbot],
215
+ outputs=[msg_input]
216
+ )
217
+
218
+ # Информация о состоянии
219
+ gr.Markdown("""
220
+ ### 💡 Советы:
221
+ 1. Первая загрузка модели может занять 1-5 минут
222
+ 2. Ответы генерируются на CPU, будьте терпеливы
223
+ 3. Для более быстрых ответов используйте Qwen2.5-0.5B
224
+ 4. Очищайте историю, если чат становится медленным
225
+ """)
226
 
227
  if __name__ == "__main__":
228
+ print("=" * 50)
229
+ print("🚀 Запуск локального чат-бота на CPU")
230
+ print("=" * 50)
231
+
232
+ demo.queue(max_size=5).launch(
233
+ debug=False,
234
+ show_error=True,
235
+ server_name="0.0.0.0",
236
+ server_port=7860
237
+ )