File size: 7,999 Bytes
5b714a0
3f976bd
 
5b714a0
3f976bd
5b714a0
 
 
3f976bd
 
 
 
5b714a0
3f976bd
 
 
 
 
 
5b714a0
 
3f976bd
 
 
 
 
5b714a0
3f976bd
 
 
5b714a0
e6fa510
5b714a0
e6fa510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5b714a0
e6fa510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5b714a0
 
e6fa510
5b714a0
 
 
e6fa510
5b714a0
 
e6fa510
 
697670a
e6fa510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5b714a0
 
e6fa510
5b714a0
 
 
 
 
 
e6fa510
5b714a0
e6fa510
5b714a0
e6fa510
697670a
5b714a0
e6fa510
5b714a0
e6fa510
5b714a0
 
 
 
e6fa510
ac8fce8
5b714a0
 
e6fa510
 
 
5b714a0
e6fa510
 
 
 
 
8f26786
e6fa510
5b8affe
e6fa510
8f26786
5b714a0
e6fa510
5b714a0
8f26786
5b714a0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/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)