eroha-agentapi / app.py
Yermek68's picture
Update app.py
e6fa510 verified
raw
history blame
8 kB
#!/usr/bin/env python3
import os
import requests
import gradio as gr
# ==========================================================
# 1️⃣ Проверка токена Hugging Face API
# ==========================================================
def check_hf_token():
token = os.getenv("HF_TOKEN")
if not token:
print("❌ HF_TOKEN не найден. Добавь его в Secrets.")
return "❌ HF_TOKEN не найден (добавь в Settings → Secrets)"
headers = {"Authorization": f"Bearer {token}"}
try:
response = requests.get("https://huggingface.co/api/whoami-v2", headers=headers, timeout=10)
if response.status_code == 200:
user = response.json().get("name", "неизвестный пользователь")
print(f"✅ Подключено к Hugging Face API. Авторизован как: {user}")
return f"✅ Подключено к Hugging Face API — {user}"
else:
print(f"⚠️ Токен отклонён. Код {response.status_code}")
return f"⚠️ Ошибка токена ({response.status_code})"
except Exception as e:
print(f"❌ Ошибка подключения к Hugging Face API: {e}")
return f"❌ Ошибка подключения: {e}"
status_message = check_hf_token()
# ==========================================================
# 2️⃣ Умный выбор модели с объяснением
# ==========================================================
def auto_select_model(prompt: str):
"""Определяет оптимальную модель + объяснение выбора"""
p = prompt.lower()
if any(x in p for x in ["квант", "физик", "матем", "логик", "наука", "формул"]):
return ("mistralai/Mistral-7B-Instruct-v0.3",
"🔬 Запрос научный, Mistral умеет логически рассуждать и точно объяснять сложные темы.")
elif any(x in p for x in ["код", "программ", "python", "debug", "ошибк", "скрипт"]):
return ("bigcode/starcoder2-3b",
"💻 Обнаружен запрос про программирование — Starcoder специализируется на коде и примерах.")
elif any(x in p for x in ["переведи", "английск", "translate", "перевод"]):
return ("facebook/nllb-200-distilled-600M",
"🌍 Запрос про языки — NLLB создан специально для качественного перевода.")
elif any(x in p for x in ["письмо", "мотивац", "совет", "отношен", "эмоци", "психолог"]):
return ("meta-llama/Llama-3.2-1B-Instruct",
"💬 Запрос гуманитарный — Llama хорошо пишет тексты и понимает эмоции.")
else:
return ("microsoft/Phi-3.5-mini-instruct",
"🧠 Общий запрос — Phi-3.5 универсален и даёт сбалансированные ответы.")
# Резервная цепочка (на случай ошибок)
FALLBACK_MODELS = [
"microsoft/Phi-3.5-mini-instruct",
"mistralai/Mistral-7B-Instruct-v0.3",
"meta-llama/Llama-3.2-1B-Instruct",
"bigcode/starcoder2-3b",
]
# ==========================================================
# 3️⃣ Проверка доступности модели
# ==========================================================
def check_model_status(model_name: str, token: str) -> bool:
headers = {"Authorization": f"Bearer {token}"}
url = f"https://huggingface.co/api/models/{model_name}"
try:
r = requests.get(url, headers=headers, timeout=10)
if r.status_code == 200:
print(f"✅ Модель доступна: {model_name}")
return True
else:
print(f"⚠️ Модель {model_name} недоступна (код {r.status_code})")
return False
except Exception as e:
print(f"❌ Ошибка при проверке модели {model_name}: {e}")
return False
# ==========================================================
# 4️⃣ Генерация ответа
# ==========================================================
def generate_response(user_input: str):
if not user_input.strip():
return "⚠️ Введите запрос", "—", "—"
token = os.getenv("HF_TOKEN")
if not token:
return "❌ Ошибка: HF_TOKEN не найден", "—", "—"
# 1. Определяем модель и объяснение
main_model, reason = auto_select_model(user_input)
selected_model = main_model
print(f"🧠 Выбрана модель: {main_model}")
# 2. Проверяем доступность
if not check_model_status(main_model, token):
for backup in FALLBACK_MODELS:
if check_model_status(backup, token):
selected_model = backup
reason += f"\n🔁 Основная модель недоступна — переключено на резервную: {backup}"
break
else:
return "❌ Все модели недоступны. Попробуй позже.", "—", "—"
# 3. Генерация
api_url = f"https://api-inference.huggingface.co/models/{selected_model}"
headers = {"Authorization": f"Bearer {token}"}
payload = {"inputs": user_input, "parameters": {"max_new_tokens": 400, "temperature": 0.7}}
try:
response = requests.post(api_url, headers=headers, json=payload, timeout=90)
if response.status_code == 200:
data = response.json()
if isinstance(data, list) and len(data) > 0 and "generated_text" in data[0]:
output = data[0]["generated_text"]
else:
output = str(data)
return output.strip(), selected_model, reason
else:
return f"⚠️ Ошибка API ({response.status_code}): {response.text}", selected_model, reason
except Exception as e:
return f"❌ Ошибка при обращении к модели {selected_model}: {e}", selected_model, reason
# ==========================================================
# 5️⃣ Интерфейс Gradio
# ==========================================================
with gr.Blocks(title="Eroha AgentAPI v3.3 — Explain Edition") as demo:
gr.Markdown(
f"<div style='background-color:#e8f5e9;padding:10px;border-radius:6px;border:1px solid #4caf50;"
f"color:#2e7d32;font-size:16px;margin-bottom:10px;'>{status_message}</div>"
)
gr.Markdown("### 🤖 Eroha AgentAPI v3.3 — Guru + Explain Mode (умный выбор и объяснение)")
with gr.Row():
user_input = gr.Textbox(
label="Введите запрос",
placeholder="Например: Напиши мотивационное письмо для собеседования",
lines=2,
)
with gr.Row():
output = gr.Textbox(label="Ответ", lines=10, placeholder="Здесь появится ответ")
with gr.Row():
model_used = gr.Textbox(label="Используемая модель", interactive=False)
explanation = gr.Textbox(label="Объяснение выбора", interactive=False)
submit_btn = gr.Button("🚀 Отправить запрос")
submit_btn.click(fn=generate_response, inputs=user_input, outputs=[output, model_used, explanation])
# ==========================================================
# 6️⃣ Запуск
# ==========================================================
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)