Yermek68 commited on
Commit
b95b531
·
verified ·
1 Parent(s): 1530a12

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -244
app.py CHANGED
@@ -1,254 +1,109 @@
1
  import os
2
  import time
3
- import threading
4
- import requests
5
  import gradio as gr
6
- import pandas as pd
7
- import matplotlib.pyplot as plt
8
- import base64
9
- from io import BytesIO
10
  from datetime import datetime
11
 
12
- from core.dashboard import ErohaDashboard
13
- from core.intelligence import update_memory, summarize_context
14
- from core.selfcheck import evaluate_answer, improve_answer
15
- from core.learning import analyze_user_input, adapt_answer
16
- from core.model_selector import choose_model
17
-
18
-
19
- # ==============================
20
- # 🔐 ENVIRONMENT CONFIG
21
- # ==============================
22
- HF_TOKEN = os.getenv("HF_TOKEN", "")
23
- LOG_FILE = "logs/history.csv"
24
- os.makedirs("logs", exist_ok=True)
25
- dashboard = ErohaDashboard()
26
-
27
-
28
- # ==============================
29
- # 🧠 Router Manager
30
- # ==============================
31
- class RouterManager:
32
- def __init__(self, token: str):
33
- self.token = token
34
- self.router_url = "https://router.huggingface.co"
35
- self.headers = {"Authorization": f"Bearer {self.token}"}
36
- self.is_router_healthy = True
37
- self.last_check = None
38
- self.reconnect_attempts = 0
39
- self.last_token_validation = 0
40
-
41
- def validate_token(self):
42
- """Проверяет, действителен ли токен"""
43
- try:
44
- r = requests.get(self.router_url + "/status", headers=self.headers, timeout=10)
45
- if r.status_code == 200:
46
- return True
47
- elif r.status_code == 401:
48
- print("🔒 Ошибка: недействительный токен Hugging Face!")
49
- self.is_router_healthy = False
50
- return False
51
- return False
52
- except Exception:
53
  return False
 
 
 
54
 
55
- def check_router_health(self):
56
- """Проверяет доступность Router API"""
57
- try:
58
- start = time.time()
59
- r = requests.post(self.router_url, headers=self.headers, json={"inputs": "ping"})
60
- latency = round(time.time() - start, 2)
61
- if r.status_code == 200:
62
- self.is_router_healthy = True
63
- self.last_check = datetime.now()
64
- self.reconnect_attempts = 0
65
- print(f"✅ Router API активен ({latency}s)")
66
- else:
67
- self.is_router_healthy = False
68
- print(f"⚠️ Router API ответил {r.status_code}")
69
- except Exception as e:
70
- self.is_router_healthy = False
71
- print("❌ Router недоступен:", str(e))
72
-
73
- def auto_reconnect(self):
74
- """Автоматическое восстановление при потере связи"""
75
- self.reconnect_attempts += 1
76
- delay = min(30, 2 ** self.reconnect_attempts)
77
- print(f"🔁 Попытка переподключения через {delay}s...")
78
- time.sleep(delay)
79
- self.check_router_health()
80
-
81
- def request(self, model_id: str, prompt: str):
82
- """Отправляет запрос с failover и auto-heal"""
83
- payload = {
84
- "model": model_id,
85
- "inputs": prompt,
86
- "parameters": {"max_new_tokens": 600, "temperature": 0.7},
87
- }
88
-
89
- try:
90
- response = requests.post(
91
- self.router_url,
92
- headers=self.headers,
93
- json=payload,
94
- timeout=60,
95
- )
96
- if response.status_code == 200:
97
- data = response.json()
98
- if isinstance(data, list) and "generated_text" in data[0]:
99
- return data[0]["generated_text"]
100
- elif isinstance(data, dict) and "generated_text" in data:
101
- return data["generated_text"]
102
- else:
103
- raise RuntimeError("Неверный формат ответа")
104
- elif response.status_code >= 500:
105
- print("⚠️ Ошибка Router 5xx. Переподключение...")
106
- self.auto_reconnect()
107
- return self.request(model_id, prompt)
108
- else:
109
- raise RuntimeError(f"Router ошибка: {response.status_code}")
110
-
111
- except Exception as e:
112
- print(f"❌ Router ошибка: {e}, активируем fallback...")
113
- return self.fallback_request(prompt)
114
-
115
- def fallback_request(self, prompt):
116
- """Fallback на стабильную модель"""
117
- fallback_model = "mistralai/Mixtral-8x7B-Instruct-v0.1"
118
- try:
119
- response = requests.post(
120
- self.router_url,
121
- headers=self.headers,
122
- json={"model": fallback_model, "inputs": prompt},
123
- timeout=60,
124
- )
125
- if response.status_code == 200:
126
- data = response.json()
127
- if isinstance(data, list) and "generated_text" in data[0]:
128
- return f"[⚠️ Fallback {fallback_model}] {data[0]['generated_text']}"
129
- raise RuntimeError(f"Fallback ошибка: {response.status_code}")
130
- except Exception as e:
131
- return f"❌ Ошибка fallback: {e}"
132
-
133
-
134
- # ==============================
135
- # 🐕 Watchdog Thread
136
- # ==============================
137
- def watchdog_loop(router_manager: RouterManager):
138
- """Поток, который следит за Router API и токеном"""
139
- while True:
140
- try:
141
- router_manager.check_router_health()
142
- now = time.time()
143
- # Проверка токена каждые 10 минут
144
- if now - router_manager.last_token_validation > 600:
145
- router_manager.validate_token()
146
- router_manager.last_token_validation = now
147
- time.sleep(60)
148
- except Exception as e:
149
- print("⚠️ Watchdog ошибка:", str(e))
150
- time.sleep(30)
151
-
152
-
153
- # ==============================
154
- # 🧠 Основная генерация
155
- # ==============================
156
- router_manager = RouterManager(HF_TOKEN)
157
-
158
-
159
- def generate_response(user_input):
160
  try:
161
  start = time.time()
162
- prefs = analyze_user_input(user_input)
163
- model_id = choose_model(user_input)
164
-
165
- result = router_manager.request(model_id, user_input)
166
- check = evaluate_answer(result)
167
- improved = improve_answer(result)
168
- personalized = adapt_answer(improved)
169
- update_memory(user_input, personalized)
170
- context = summarize_context()
171
-
172
- response_time = round(time.time() - start, 2)
173
- dashboard.log_request(model_id, prefs["category"], response_time)
174
-
175
- df = pd.DataFrame([{
176
- "time": time.strftime("%Y-%m-%d %H:%M:%S"),
177
- "model": model_id,
178
- "category": prefs["category"],
179
- "response_time": response_time,
180
- "prompt": user_input,
181
- "response": personalized[:1500],
182
- }])
183
- df.to_csv(LOG_FILE, mode="a", index=False, header=not os.path.exists(LOG_FILE))
184
-
185
- summary = (
186
- f"🧠 **Модель:** `{model_id}`\n"
187
- f"⚡ **Время отклика:** {response_time} сек\n"
188
- f"🔍 **Проверка качества:** {check['result']}\n"
189
- f"{'; '.join(check['feedback']) if check['feedback'] else '✅ Всё отлично'}\n\n"
190
- f"{context}"
191
- )
192
-
193
- return f"{personalized}\n\n{summary}"
194
-
195
  except Exception as e:
196
- return f"❌ Ошибка выполнения: {str(e)}"
197
-
198
-
199
- # ==============================
200
- # 📈 Аналитика
201
- # ==============================
202
- def generate_chart():
203
- if not os.path.exists(LOG_FILE):
204
- return "⚠️ Нет данных для графика."
205
- df = pd.read_csv(LOG_FILE)
206
- if df.empty:
207
- return "⚠️ История пуста."
208
- df["time"] = pd.to_datetime(df["time"])
209
- df = df.tail(50)
210
-
211
- plt.figure(figsize=(8, 4))
212
- plt.plot(df["time"], df["response_time"], marker="o", linewidth=1.5)
213
- plt.title("⚡ Скорость отклика моделей (последние 50 запросов)")
214
- plt.xlabel("Время")
215
- plt.ylabel("Секунды")
216
- plt.grid(True)
217
- buffer = BytesIO()
218
- plt.savefig(buffer, format="png", bbox_inches="tight")
219
- buffer.seek(0)
220
- img_base64 = base64.b64encode(buffer.read()).decode("utf-8")
221
- plt.close()
222
- return f"<img src='data:image/png;base64,{img_base64}'/>"
223
-
224
-
225
- def show_dashboard():
226
- metrics_text, df = dashboard.dashboard_ui()
227
- chart_html = generate_chart()
228
- return metrics_text, df, chart_html
229
-
230
-
231
- # ==============================
232
- # 🎨 Gradio UI
233
- # ==============================
234
- with gr.Blocks(title="Eroha AgentAPI v5.8 Production-Cluster Core", theme="soft") as app:
235
- gr.Markdown("# 🤖 Eroha AgentAPI v5.8 — Production-Cluster Core 🚀")
236
- gr.Markdown("**Полный контроль: Router-watchdog + auto-heal + token-validation + fallback.**")
237
-
238
- with gr.Tab("💬 Agent Chat"):
239
- user_input = gr.Textbox(label="Введите запрос", placeholder="Например: придумай легенду о ИИ, который нашёл сознание.")
240
- output_box = gr.Textbox(label="Ответ", lines=15)
241
- submit_btn = gr.Button("🚀 Отправить")
242
- submit_btn.click(fn=generate_response, inputs=user_input, outputs=output_box)
243
-
244
- with gr.Tab("📊 Dashboard"):
245
- metrics = gr.Markdown(label="📈 Общая статистика")
246
- log_table = gr.Dataframe(headers=["time", "model", "category", "response_time"], label="История запросов")
247
- chart_box = gr.HTML()
248
- refresh = gr.Button("🔄 Обновить дашборд")
249
- refresh.click(show_dashboard, outputs=[metrics, log_table, chart_box])
250
-
251
- # 🔥 Запуск watchdog-потока
252
- threading.Thread(target=watchdog_loop, args=(router_manager,), daemon=True).start()
253
-
254
- app.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import os
2
  import time
3
+ import json
 
4
  import gradio as gr
5
+ import requests
 
 
 
6
  from datetime import datetime
7
 
8
+ # =========================
9
+ # ⚙️ НАСТРОЙКИ
10
+ # =========================
11
+ HF_TOKEN = os.getenv("HF_TOKEN") or "hf_your_token_here"
12
+
13
+ PRIMARY_MODEL = "google/gemma-2-2b-it"
14
+ FALLBACK_MODEL = "mistralai/Mixtral-8x7B-Instruct-v0.1"
15
+ ROUTER_URL = "https://router.huggingface.co"
16
+
17
+ HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"}
18
+
19
+
20
+ # =========================
21
+ # 🧩 ПОЛЕЗНЫЕ ФУНКЦИИ
22
+ # =========================
23
+
24
+ def check_token():
25
+ """Проверка валидности токена Hugging Face."""
26
+ try:
27
+ res = requests.get("https://router.huggingface.co/status", headers=HEADERS, timeout=8)
28
+ if res.status_code == 200:
29
+ return True
30
+ else:
31
+ print(f"⚠️ Токен Hugging Face невалиден ({res.status_code})")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  return False
33
+ except Exception as e:
34
+ print(f"Ошибка при проверке токена: {e}")
35
+ return False
36
 
37
+
38
+ def send_request(model: str, prompt: str):
39
+ """Отправка запроса к модели через Router API."""
40
+ payload = {"model": model, "inputs": prompt, "options": {"use_cache": True}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  try:
42
  start = time.time()
43
+ response = requests.post(ROUTER_URL, headers=HEADERS, json=payload, timeout=60)
44
+ latency = time.time() - start
45
+
46
+ if response.status_code == 200:
47
+ data = response.json()
48
+ # Универсальный парсинг ответа
49
+ if isinstance(data, list) and len(data) > 0 and "generated_text" in data[0]:
50
+ text = data[0]["generated_text"]
51
+ elif isinstance(data, dict) and "generated_text" in data:
52
+ text = data["generated_text"]
53
+ else:
54
+ text = str(data)
55
+ return text.strip(), latency, model, None
56
+ else:
57
+ return None, latency, model, f"Ошибка API {response.status_code}: {response.text}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
+ return None, 0, model, str(e)
60
+
61
+
62
+ def generate_text(prompt: str):
63
+ """Основная функция: попытка через основную модель → fallback при ошибке."""
64
+ if not check_token():
65
+ return "❌ Токен Hugging Face недействителен. Проверьте переменную HF_TOKEN."
66
+
67
+ # 1️⃣ Основная модель
68
+ output, latency, used_model, error = send_request(PRIMARY_MODEL, prompt)
69
+ if output:
70
+ return render_output(output, used_model, latency, success=True)
71
+
72
+ # 2️⃣ Fallback при ошибке
73
+ output_fb, latency_fb, model_fb, error_fb = send_request(FALLBACK_MODEL, prompt)
74
+ if output_fb:
75
+ return render_output(output_fb, model_fb, latency_fb, success=True, fallback=True)
76
+ else:
77
+ return f"❌ Ошибка при выполнении запроса:\n- {error}\n- Fallback: {error_fb}"
78
+
79
+
80
+ def render_output(text, model, latency, success=False, fallback=False):
81
+ """Форматированный вывод результата."""
82
+ emoji = "✅" if success else "⚠️"
83
+ fb_text = " (через fallback)" if fallback else ""
84
+ return (
85
+ f"{emoji} **Модель:** `{model}`{fb_text}\n"
86
+ f"⏱ **Время отклика:** {latency:.2f} сек\n\n"
87
+ f"🧠 **Ответ:**\n{text.strip()}"
88
+ )
89
+
90
+
91
+ # =========================
92
+ # 🧭 GRADIO UI
93
+ # =========================
94
+
95
+ with gr.Blocks(title="🤖 Eroha AgentAPI v5.7 — Stable Router Edition") as demo:
96
+ gr.Markdown("## 🧠 Eroha AgentAPI v5.7 — Stable Router Edition\n"
97
+ "Поддержка Router API + AutoFallback + Token Validation 🌐")
98
+
99
+ with gr.Row():
100
+ prompt = gr.Textbox(label="Введите запрос", placeholder="Например: 'Расскажи историю про ИИ, который научился понимать чувства.'", lines=3)
101
+ output = gr.Markdown(label="Ответ")
102
+
103
+ btn = gr.Button("🚀 Отправить", variant="primary")
104
+ btn.click(generate_text, inputs=prompt, outputs=output)
105
+
106
+ gr.Markdown("---")
107
+ gr.Markdown("🧩 **Eroha Router Core v5.7** | Автоопределение моделей + безопасный fallback")
108
+
109
+ demo.launch(server_name="0.0.0.0", server_port=7860)