Update app.py
Browse files
app.py
CHANGED
|
@@ -2,7 +2,9 @@ import gradio as gr
|
|
| 2 |
import spaces
|
| 3 |
import torch
|
| 4 |
import os
|
|
|
|
| 5 |
import base64
|
|
|
|
| 6 |
from PIL import Image
|
| 7 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 8 |
from groq import Groq
|
|
@@ -10,6 +12,32 @@ from mistralai import Mistral
|
|
| 10 |
import google.generativeai as genai
|
| 11 |
from huggingface_hub import snapshot_download
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
# --- CONFIGURAÇÕES ---
|
| 14 |
LOCAL_MODEL_ID = "Qwen/Qwen2.5-Coder-32B-Instruct"
|
| 15 |
local_model = None
|
|
@@ -151,33 +179,28 @@ def run_gemini(messages, model_id):
|
|
| 151 |
return response.text
|
| 152 |
except Exception as e: return f"❌ Gemini Error ({model_id}): {e}"
|
| 153 |
|
| 154 |
-
# --- ROTEADOR
|
| 155 |
-
def router(message, history, model_selector):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
formatted_history = []
|
| 157 |
|
| 158 |
-
#
|
| 159 |
-
# Isso resolve o erro "too many values to unpack"
|
| 160 |
for turn in history:
|
| 161 |
-
# CASO 1: Formato Antigo [[user, bot]]
|
| 162 |
if isinstance(turn, (list, tuple)) and len(turn) >= 2:
|
| 163 |
user_content = turn[0]
|
| 164 |
bot_content = turn[1]
|
| 165 |
-
|
| 166 |
-
# Extrai texto se for complexo
|
| 167 |
if isinstance(user_content, dict) and 'text' in user_content:
|
| 168 |
user_content = user_content['text']
|
| 169 |
-
|
| 170 |
formatted_history.append({"role": "user", "content": str(user_content)})
|
| 171 |
if bot_content:
|
| 172 |
formatted_history.append({"role": "assistant", "content": str(bot_content)})
|
| 173 |
-
|
| 174 |
-
# CASO 2: Formato Novo/Messages (Dicionário)
|
| 175 |
elif isinstance(turn, dict):
|
| 176 |
-
# Já está no formato certo, só copiamos
|
| 177 |
formatted_history.append(turn)
|
| 178 |
|
| 179 |
-
# --- FIM DO FIX ---
|
| 180 |
-
|
| 181 |
# Processa mensagem ATUAL
|
| 182 |
current_content = []
|
| 183 |
text_input = message.get("text", "")
|
|
@@ -221,7 +244,7 @@ def router(message, history, model_selector):
|
|
| 221 |
|
| 222 |
# --- INTERFACE ---
|
| 223 |
with gr.Blocks() as demo:
|
| 224 |
-
gr.Markdown("# 🔀 APIDOST (
|
| 225 |
|
| 226 |
with gr.Row():
|
| 227 |
model_dropdown = gr.Dropdown(
|
|
|
|
| 2 |
import spaces
|
| 3 |
import torch
|
| 4 |
import os
|
| 5 |
+
import time
|
| 6 |
import base64
|
| 7 |
+
from collections import defaultdict
|
| 8 |
from PIL import Image
|
| 9 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 10 |
from groq import Groq
|
|
|
|
| 12 |
import google.generativeai as genai
|
| 13 |
from huggingface_hub import snapshot_download
|
| 14 |
|
| 15 |
+
# --- CONFIGURAÇÃO DE SEGURANÇA (RATE LIMIT) ---
|
| 16 |
+
# Berta: Configuração para impedir que engraçadinhos queimem sua API.
|
| 17 |
+
# Permite 5 mensagens a cada 60 segundos por IP.
|
| 18 |
+
RATE_LIMIT_MAX_REQUESTS = 5
|
| 19 |
+
RATE_LIMIT_WINDOW_SECONDS = 600
|
| 20 |
+
ip_tracker = defaultdict(list)
|
| 21 |
+
|
| 22 |
+
def check_rate_limit(request: gr.Request):
|
| 23 |
+
"""Verifica se o IP está abusando."""
|
| 24 |
+
if not request:
|
| 25 |
+
return True # Se rodar local sem request, libera.
|
| 26 |
+
|
| 27 |
+
client_ip = request.client.host
|
| 28 |
+
current_time = time.time()
|
| 29 |
+
|
| 30 |
+
# Limpa requisições antigas desse IP
|
| 31 |
+
ip_tracker[client_ip] = [t for t in ip_tracker[client_ip] if current_time - t < RATE_LIMIT_WINDOW_SECONDS]
|
| 32 |
+
|
| 33 |
+
# Verifica se excedeu
|
| 34 |
+
if len(ip_tracker[client_ip]) >= RATE_LIMIT_MAX_REQUESTS:
|
| 35 |
+
return False
|
| 36 |
+
|
| 37 |
+
# Registra nova requisição
|
| 38 |
+
ip_tracker[client_ip].append(current_time)
|
| 39 |
+
return True
|
| 40 |
+
|
| 41 |
# --- CONFIGURAÇÕES ---
|
| 42 |
LOCAL_MODEL_ID = "Qwen/Qwen2.5-Coder-32B-Instruct"
|
| 43 |
local_model = None
|
|
|
|
| 179 |
return response.text
|
| 180 |
except Exception as e: return f"❌ Gemini Error ({model_id}): {e}"
|
| 181 |
|
| 182 |
+
# --- ROTEADOR COM PROTEÇÃO DE IP ---
|
| 183 |
+
def router(message, history, model_selector, request: gr.Request): # <--- Request injetado pelo Gradio
|
| 184 |
+
|
| 185 |
+
# 1. VERIFICAÇÃO DE SPAM
|
| 186 |
+
if not check_rate_limit(request):
|
| 187 |
+
return f"⛔ **BLOQUEIO DE SEGURANÇA:** Você excedeu o limite de requisições ({RATE_LIMIT_MAX_REQUESTS}/min). Aguarde um pouco."
|
| 188 |
+
|
| 189 |
formatted_history = []
|
| 190 |
|
| 191 |
+
# Tratamento de histórico blindado
|
|
|
|
| 192 |
for turn in history:
|
|
|
|
| 193 |
if isinstance(turn, (list, tuple)) and len(turn) >= 2:
|
| 194 |
user_content = turn[0]
|
| 195 |
bot_content = turn[1]
|
|
|
|
|
|
|
| 196 |
if isinstance(user_content, dict) and 'text' in user_content:
|
| 197 |
user_content = user_content['text']
|
|
|
|
| 198 |
formatted_history.append({"role": "user", "content": str(user_content)})
|
| 199 |
if bot_content:
|
| 200 |
formatted_history.append({"role": "assistant", "content": str(bot_content)})
|
|
|
|
|
|
|
| 201 |
elif isinstance(turn, dict):
|
|
|
|
| 202 |
formatted_history.append(turn)
|
| 203 |
|
|
|
|
|
|
|
| 204 |
# Processa mensagem ATUAL
|
| 205 |
current_content = []
|
| 206 |
text_input = message.get("text", "")
|
|
|
|
| 244 |
|
| 245 |
# --- INTERFACE ---
|
| 246 |
with gr.Blocks() as demo:
|
| 247 |
+
gr.Markdown("# 🔀 APIDOST (Protected Mode)")
|
| 248 |
|
| 249 |
with gr.Row():
|
| 250 |
model_dropdown = gr.Dropdown(
|