FrostIce commited on
Commit
d8e8db4
·
verified ·
1 Parent(s): 5efbcc2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -133
app.py CHANGED
@@ -1,50 +1,13 @@
1
- # -------------------------------------------------------------
2
- # app.py – Gradio‑чат с локальной LLaMA‑моделью
3
- # -------------------------------------------------------------
4
- import os
5
- import json
6
- import pathlib
7
- import gc
8
- from typing import List, Tuple, Any
9
-
10
  import gradio as gr
11
- from llama_cpp import Llama
12
- from huggingface_hub import snapshot_download
13
-
14
- # ------------------------------------------------------------------
15
- # 1️⃣ Загрузка модели из HuggingFace (необходимо один раз)
16
- # ------------------------------------------------------------------
17
- MODEL_REPO = "neuphonic/neutts-air"
18
- MODEL_FILE = "neutss-air-BF16.gguf"
19
- CACHE_DIR = os.getenv("HF_HOME", pathlib.Path.home() / ".cache" / "huggingface" / "hub")
20
-
21
- print("🔎 Скачиваем модель (может занять несколько минут)...")
22
- model_path = snapshot_download(
23
- repo_id=MODEL_REPO,
24
- revision="main",
25
- cache_dir=str(CACHE_DIR),
26
- local_files_only=False, # False → скачивает, если нет локально
27
- allow_patterns=[MODEL_FILE],
28
- )
29
-
30
- gguf_path = os.path.join(model_path, MODEL_FILE)
31
- print(f"✅ Модель скачана в {gguf_path}")
32
 
33
- # ------------------------------------------------------------------
34
- # 2️⃣ Инициализация Llama‑CPP (GPU/CPU зависит от того, как установлен пакет)
35
- # ------------------------------------------------------------------
36
- llm = Llama(
37
- model_path=gguf_path,
38
- n_ctx=2048, # длина контекста (можно увеличить, если хватает VRAM)
39
- n_threads=8, # количество CPU‑ядер
40
- n_gpu_layers=-1, # -1 → попытаться использовать всё доступное GPU (если сборка поддерживает)
41
- verbose=False,
42
- )
43
 
44
- # ------------------------------------------------------------------
45
- # 3️⃣ Системный промпт – будет всегда первой репликой
46
- # ------------------------------------------------------------------
47
- SYSTEM_PROMPT = """You are a Web‑assistant. For every user request return **exactly one JSON object**
48
  with the following possible fields:
49
  {
50
  "TEXT": "<optional short explanation>",
@@ -61,128 +24,71 @@ with the following possible fields:
61
  }
62
  }
63
  If you don't need any action, set all fields to null or empty strings.
64
- """
65
-
66
- # ------------------------------------------------------------------
67
- # 4️⃣ Вспомогательная функция: формируем запрос в стиле OpenAI‑Chat
68
- # ------------------------------------------------------------------
69
- def build_chat(messages: List[Tuple[str, str]]) -> str:
70
- """
71
- Преобразуем историю (list of (human,assistant)) в один строковый prompt,
72
- совместимый с Llama‑CPP, где каждая реплика отделяется тегами <|user|>,
73
- <|assistant|> и <|system|>.
74
- """
75
- prompt = f"<|system|>{SYSTEM_PROMPT}<|end|>"
76
- for human, assistant in messages:
77
- prompt += f"<|user|>{human}<|end|>"
78
- prompt += f"<|assistant|>{assistant}<|end|>"
79
- return prompt
80
-
81
-
82
- # ------------------------------------------------------------------
83
- # 5️⃣ Основная бизнес‑логика – генерация ответа модели
84
- # ------------------------------------------------------------------
85
- def respond(message: str, history: List[List[str]]) -> List[List[Any]]:
86
- """
87
- Принимает новое сообщение пользователя и текущую историю чата.
88
- Возвращает обновлённую историю, где второй элемент списка – JSON‑строка
89
- модели (или сообщение об ошибке).
90
- """
91
- # 1️⃣ Преобразуем историю в формат (human,assistant)
92
- chat_history = [(h, a) for h, a in history] # тип List[Tuple[str,str]]
93
 
94
- # 2️⃣ Формируем полный prompt
95
- prompt = build_chat(chat_history + [(message, "")]) # последняя реплика ещё пустая
96
-
97
- # 3️⃣ Генерируем ответ (при необходимости задаём stop‑строку)
98
  try:
99
- # Параметры генерации можно подкорректировать:
100
- # temperature – креативность,
101
- # top_p – сэмплинг,
102
- # max_tokens – длина ответа.
103
- out = llm(
104
- prompt,
105
- max_tokens=512,
106
- temperature=0.2,
107
- top_p=0.95,
108
- repeat_penalty=1.1,
109
- stop=["<|assistant|>", "<|user|>", "<|system|>"], # остановка перед новым turn'ом
110
  )
111
- raw = out["choices"][0]["text"].strip()
112
-
113
- # Иногда модель генерирует лишний текст (например, объяснение) перед JSON.
114
- # Попытаемся вырезать первый валидный JSON‑объект.
115
- try:
116
- # Находим первую фигурную скобку
117
- start = raw.find("{")
118
- json_part = raw[start:] if start != -1 else raw
119
- parsed = json.loads(json_part)
120
- except Exception:
121
- # Если парсинг не удалось – считаем, что модель отдала обычный текст
122
- parsed = {"TEXT": raw, "WEBSITE": "", "SEARCH": "", "SUGGESTIONS": [], "TOOL": {}}
123
- except Exception as exc:
124
- parsed = {"TEXT": f"Ошибка модели: {str(exc)}",
125
- "WEBSITE": "", "SEARCH": "", "SUGGESTIONS": [], "TOOL": {}}
126
-
127
- # Приводим к строке, чтобы отобразить в чат‑боте
128
- bot_message = json.dumps(parsed, ensure_ascii=False, indent=2)
129
 
130
- # 4️⃣ Возвращаем обновленную историю
131
  return history + [[message, bot_message]]
132
 
 
 
 
133
 
134
- # ------------------------------------------------------------------
135
- # 6️⃣ Gradio‑интерфейс (не менялся)
136
- # ------------------------------------------------------------------
137
- with gr.Blocks(title="ESP Brain – локальная LLaMA") as demo:
138
- gr.Markdown("## 🤖 Web‑assistant powered by **neutts‑air** (LLaMA‑CPP)")
139
-
140
- chatbot = gr.Chatbot(height=600)
141
 
142
  with gr.Row():
143
  txt = gr.Textbox(
144
- placeholder="Напиши сообщение…",
145
  show_label=False,
146
- scale=8,
147
  )
148
  submit_btn = gr.Button("Отправить", scale=2)
149
 
150
  with gr.Row():
151
- retry_btn = gr.Button("🔄Повторить")
152
- undo_btn = gr.Button("↩️Отменить")
153
- clear_btn = gr.Button("🗑️Очистить")
154
 
155
- # -------------------------------------------------------------
156
- # Логика кнопок
157
- # -------------------------------------------------------------
158
  txt.submit(fn=respond, inputs=[txt, chatbot], outputs=chatbot)
159
  submit_btn.click(fn=respond, inputs=[txt, chatbot], outputs=chatbot)
160
 
161
  def retry_last(history):
162
- """Очистить последний ответ, чтобы пользователь мог написать заново."""
163
  if history:
164
- last_user = history[-1][0]
165
- return history[:-1] + [[last_user, None]]
166
  return history
167
 
168
  retry_btn.click(fn=retry_last, inputs=chatbot, outputs=chatbot, queue=False)
169
 
170
  def undo_last(history):
171
- """Удалить последнюю пару (user‑assistant)."""
172
  return history[:-1]
173
 
174
  undo_btn.click(fn=undo_last, inputs=chatbot, outputs=chatbot, queue=False)
175
 
176
  clear_btn.click(lambda: [], outputs=chatbot, queue=False)
177
 
178
- # ------------------------------------------------------------------
179
- # 7️⃣ Запуск приложения
180
- # ------------------------------------------------------------------
181
  if __name__ == "__main__":
182
- # Включаем очередь, чтобы несколько запросов не конфликтовали с GPU/CPU
183
  demo.queue()
184
  demo.launch(
185
- share=True, # получить публичный https‑линк (опционально)
186
  ssr_mode=False,
187
- debug=True,
188
- )
 
1
+ # app.py
 
 
 
 
 
 
 
 
2
  import gradio as gr
3
+ from g4f.client import Client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ client = Client()
 
 
 
 
 
 
 
 
 
6
 
7
+ # --- Обработчик диалога ---
8
+ def respond(message, history):
9
+ # Добавляем системное сообщение только при старте истории
10
+ messages = [{"role": "system", "content": """You are a Web‑assistant. For every user request return **exactly one JSON object**
11
  with the following possible fields:
12
  {
13
  "TEXT": "<optional short explanation>",
 
24
  }
25
  }
26
  If you don't need any action, set all fields to null or empty strings.
27
+ """}]
28
+
29
+ for human, assistant in history:
30
+ messages.append({"role": "user", "content": human})
31
+ messages.append({"role": "assistant", "content": assistant})
32
+
33
+ messages.append({"role": "user", "content": message})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
 
 
 
 
35
  try:
36
+ response = client.chat.completions.create(
37
+ model="deepseek-v3",
38
+ messages=messages
 
 
 
 
 
 
 
 
39
  )
40
+ bot_message = response.choices[0].message.content
41
+ except Exception as e:
42
+ bot_message = f"Ошибка: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ # Возвращаем обновлённую историю + новый ответ
45
  return history + [[message, bot_message]]
46
 
47
+ # --- Интерфейс ---
48
+ with gr.Blocks(title="ESP Brain") as demo:
49
+ gr.Markdown("## For api")
50
 
51
+ chatbot = gr.Chatbot(
52
+ height=600,
53
+ )
 
 
 
 
54
 
55
  with gr.Row():
56
  txt = gr.Textbox(
57
+ placeholder="Напиши сообщение...",
58
  show_label=False,
59
+ scale=8
60
  )
61
  submit_btn = gr.Button("Отправить", scale=2)
62
 
63
  with gr.Row():
64
+ retry_btn = gr.Button("🔄 Повторить")
65
+ undo_btn = gr.Button("↩️ Отменить")
66
+ clear_btn = gr.Button("🗑️ Очистить")
67
 
68
+ # Логика
 
 
69
  txt.submit(fn=respond, inputs=[txt, chatbot], outputs=chatbot)
70
  submit_btn.click(fn=respond, inputs=[txt, chatbot], outputs=chatbot)
71
 
72
  def retry_last(history):
 
73
  if history:
74
+ last_user_msg = history[-1][0]
75
+ return history[:-1] + [[last_user_msg, None]] # очищаем ответ
76
  return history
77
 
78
  retry_btn.click(fn=retry_last, inputs=chatbot, outputs=chatbot, queue=False)
79
 
80
  def undo_last(history):
 
81
  return history[:-1]
82
 
83
  undo_btn.click(fn=undo_last, inputs=chatbot, outputs=chatbot, queue=False)
84
 
85
  clear_btn.click(lambda: [], outputs=chatbot, queue=False)
86
 
87
+ # --- Запуск ---
 
 
88
  if __name__ == "__main__":
 
89
  demo.queue()
90
  demo.launch(
91
+ share=True,
92
  ssr_mode=False,
93
+ debug=True
94
+ )