Spaces:
Runtime error
Runtime error
| #!/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) | |