Madras1 commited on
Commit
32fd3d5
·
verified ·
1 Parent(s): 33141da

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +10 -35
app.py CHANGED
@@ -11,37 +11,30 @@ import google.generativeai as genai
11
  from huggingface_hub import snapshot_download
12
 
13
  # --- 1. SEGURANÇA (RATE LIMIT) ---
14
- # Simples e eficiente: bloqueia spammer sem quebrar o app.
15
  MAX_REQUESTS_PER_MINUTE = 15
16
  BLOCK_TIME_SECONDS = 60
17
  ip_tracker = {}
18
 
19
  def check_spam(request: gr.Request):
20
- if not request: return True # Local run
21
  client_ip = request.client.host
22
  now = time.time()
23
 
24
- # Limpa histórico antigo do IP
25
  if client_ip in ip_tracker:
26
  ip_tracker[client_ip] = [t for t in ip_tracker[client_ip] if now - t < BLOCK_TIME_SECONDS]
27
 
28
- # Verifica bloqueio
29
  if client_ip in ip_tracker and len(ip_tracker[client_ip]) >= MAX_REQUESTS_PER_MINUTE:
30
  return False
31
 
32
- # Registra
33
  if client_ip not in ip_tracker: ip_tracker[client_ip] = []
34
  ip_tracker[client_ip].append(now)
35
  return True
36
 
37
  # --- 2. CONFIGURAÇÕES GLOBAIS ---
38
-
39
- # LOCAL (H200 - ZeroGPU)
40
  LOCAL_MODEL_ID = "Qwen/Qwen2.5-Coder-32B-Instruct"
41
  local_model = None
42
  local_tokenizer = None
43
 
44
- # CLIENTES API
45
  groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY")) if os.environ.get("GROQ_API_KEY") else None
46
  mistral_client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY")) if os.environ.get("MISTRAL_API_KEY") else None
47
  if os.environ.get("GEMINI_API_KEY"):
@@ -60,7 +53,6 @@ def encode_image(image_path):
60
  def run_local_h200(messages):
61
  global local_model, local_tokenizer
62
 
63
- # Validação rápida de imagem
64
  for m in messages:
65
  if isinstance(m['content'], list): return "⚠️ Modelo Local não suporta imagens. Use Gemini/Pixtral."
66
 
@@ -81,7 +73,6 @@ def run_groq(messages, model_id):
81
  if isinstance(m['content'], list): return "⚠️ Groq não suporta imagens. Use Gemini/Pixtral."
82
  if not groq_client: return "❌ Erro: GROQ_API_KEY ausente."
83
 
84
- # Limpa formato para Groq
85
  clean_msgs = [{"role": m['role'], "content": m['content']} for m in messages]
86
  try:
87
  completion = groq_client.chat.completions.create(
@@ -93,7 +84,6 @@ def run_groq(messages, model_id):
93
  def run_mistral(messages, model_id):
94
  if not mistral_client: return "❌ Erro: MISTRAL_API_KEY ausente."
95
 
96
- # Formata imagens para Mistral
97
  formatted_msgs = []
98
  for m in messages:
99
  content = m['content']
@@ -121,7 +111,6 @@ def run_gemini(messages, model_id):
121
  model = genai.GenerativeModel(model_id)
122
  chat_history = []
123
 
124
- # Converte histórico para Gemini
125
  for m in messages[:-1]:
126
  role = "user" if m['role'] == "user" else "model"
127
  parts = []
@@ -135,7 +124,6 @@ def run_gemini(messages, model_id):
135
  if os.path.exists(path): parts.append(Image.open(path))
136
  if parts: chat_history.append({"role": role, "parts": parts})
137
 
138
- # Última mensagem
139
  last_parts = []
140
  lc = messages[-1]['content']
141
  if isinstance(lc, str): last_parts.append(lc)
@@ -153,29 +141,23 @@ def run_gemini(messages, model_id):
153
 
154
  # --- 5. ROTEADOR CENTRAL ---
155
  def router(message, history, model_selector, request: gr.Request):
156
- # Check Spam
157
  if not check_spam(request):
158
  return "⛔ BLOQUEADO: Limite de mensagens excedido. Aguarde."
159
 
160
- # Prepara Histórico (Blindado contra formatos variados do Gradio)
161
  messages = []
162
  if history:
163
  for turn in history:
164
- # Formato antigo [user, bot]
165
  if isinstance(turn, (list, tuple)):
166
  u_text = turn[0]
167
- if isinstance(u_text, dict) and 'text' in u_text: u_text = u_text['text'] # Extrai texto se for dict
168
-
169
  messages.append({"role": "user", "content": str(u_text)})
170
  if len(turn) > 1 and turn[1]:
171
  messages.append({"role": "assistant", "content": str(turn[1])})
172
- # Formato novo {role: user...}
173
  elif isinstance(turn, dict):
174
  messages.append(turn)
175
 
176
- # Prepara Mensagem Atual (Multimodal ou Texto)
177
  current_content = []
178
- if isinstance(message, dict): # Multimodal
179
  text = message.get("text", "")
180
  files = message.get("files", [])
181
  if text: current_content.append({"type": "text", "text": text})
@@ -183,13 +165,11 @@ def router(message, history, model_selector, request: gr.Request):
183
 
184
  if not files: messages.append({"role": "user", "content": text})
185
  else: messages.append({"role": "user", "content": current_content})
186
- else: # Texto puro
187
  messages.append({"role": "user", "content": str(message)})
188
 
189
- # Roteamento
190
  print(f"🔀 Roteando para: {model_selector}")
191
 
192
- # GEMINI
193
  if "Gemini" in model_selector:
194
  tid = "gemini-1.5-flash"
195
  if "3.0" in model_selector: tid = "gemini-3.0-pro-preview"
@@ -198,30 +178,28 @@ def router(message, history, model_selector, request: gr.Request):
198
  elif "2.0" in model_selector: tid = "gemini-2.0-flash-exp"
199
  return run_gemini(messages, tid)
200
 
201
- # MISTRAL
202
  elif "Mistral" in model_selector:
203
  tid = "mistral-large-latest"
204
  if "Pixtral" in model_selector: tid = "pixtral-large-latest"
205
- elif "2509" in model_selector: tid = "magistral-medium-2509" # <--- Seu Magistral VIP
206
  elif "2512" in model_selector: tid = "mistral-large-2512"
207
  elif "Codestral" in model_selector: tid = "codestral-2508"
208
  return run_mistral(messages, tid)
209
 
210
- # GROQ
211
  elif "Groq" in model_selector:
212
  tid = "llama-3.3-70b-versatile"
213
- if "120B" in model_selector: tid = "openai/gpt-oss-120b" # <--- GPT OSS 120B
214
- elif "20B" in model_selector: tid = "openai/gpt-oss-20b" # <--- GPT OSS 20B
215
  return run_groq(messages, tid)
216
 
217
- # LOCAL
218
  elif "H200" in model_selector:
219
  return run_local_h200(messages)
220
 
221
  return "⚠️ Modelo não reconhecido."
222
 
223
- # --- 6. INTERFACE ---
224
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
 
225
  gr.Markdown("# 🔀 APIDOST v8: The Arsenal")
226
 
227
  with gr.Row():
@@ -245,7 +223,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
245
  interactive=True
246
  )
247
 
248
- # Berta: multimodal=True é vital para as imagens funcionarem no seu index.html
249
  chat = gr.ChatInterface(
250
  fn=router,
251
  additional_inputs=[model_dropdown],
@@ -253,8 +230,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
253
  )
254
 
255
  if __name__ == "__main__":
256
- # Pré-download do modelo local para não travar no primeiro uso
257
  try: snapshot_download(repo_id=LOCAL_MODEL_ID)
258
  except: pass
259
-
260
  demo.queue().launch()
 
11
  from huggingface_hub import snapshot_download
12
 
13
  # --- 1. SEGURANÇA (RATE LIMIT) ---
 
14
  MAX_REQUESTS_PER_MINUTE = 15
15
  BLOCK_TIME_SECONDS = 60
16
  ip_tracker = {}
17
 
18
  def check_spam(request: gr.Request):
19
+ if not request: return True
20
  client_ip = request.client.host
21
  now = time.time()
22
 
 
23
  if client_ip in ip_tracker:
24
  ip_tracker[client_ip] = [t for t in ip_tracker[client_ip] if now - t < BLOCK_TIME_SECONDS]
25
 
 
26
  if client_ip in ip_tracker and len(ip_tracker[client_ip]) >= MAX_REQUESTS_PER_MINUTE:
27
  return False
28
 
 
29
  if client_ip not in ip_tracker: ip_tracker[client_ip] = []
30
  ip_tracker[client_ip].append(now)
31
  return True
32
 
33
  # --- 2. CONFIGURAÇÕES GLOBAIS ---
 
 
34
  LOCAL_MODEL_ID = "Qwen/Qwen2.5-Coder-32B-Instruct"
35
  local_model = None
36
  local_tokenizer = None
37
 
 
38
  groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY")) if os.environ.get("GROQ_API_KEY") else None
39
  mistral_client = Mistral(api_key=os.environ.get("MISTRAL_API_KEY")) if os.environ.get("MISTRAL_API_KEY") else None
40
  if os.environ.get("GEMINI_API_KEY"):
 
53
  def run_local_h200(messages):
54
  global local_model, local_tokenizer
55
 
 
56
  for m in messages:
57
  if isinstance(m['content'], list): return "⚠️ Modelo Local não suporta imagens. Use Gemini/Pixtral."
58
 
 
73
  if isinstance(m['content'], list): return "⚠️ Groq não suporta imagens. Use Gemini/Pixtral."
74
  if not groq_client: return "❌ Erro: GROQ_API_KEY ausente."
75
 
 
76
  clean_msgs = [{"role": m['role'], "content": m['content']} for m in messages]
77
  try:
78
  completion = groq_client.chat.completions.create(
 
84
  def run_mistral(messages, model_id):
85
  if not mistral_client: return "❌ Erro: MISTRAL_API_KEY ausente."
86
 
 
87
  formatted_msgs = []
88
  for m in messages:
89
  content = m['content']
 
111
  model = genai.GenerativeModel(model_id)
112
  chat_history = []
113
 
 
114
  for m in messages[:-1]:
115
  role = "user" if m['role'] == "user" else "model"
116
  parts = []
 
124
  if os.path.exists(path): parts.append(Image.open(path))
125
  if parts: chat_history.append({"role": role, "parts": parts})
126
 
 
127
  last_parts = []
128
  lc = messages[-1]['content']
129
  if isinstance(lc, str): last_parts.append(lc)
 
141
 
142
  # --- 5. ROTEADOR CENTRAL ---
143
  def router(message, history, model_selector, request: gr.Request):
 
144
  if not check_spam(request):
145
  return "⛔ BLOQUEADO: Limite de mensagens excedido. Aguarde."
146
 
 
147
  messages = []
148
  if history:
149
  for turn in history:
 
150
  if isinstance(turn, (list, tuple)):
151
  u_text = turn[0]
152
+ if isinstance(u_text, dict) and 'text' in u_text: u_text = u_text['text']
 
153
  messages.append({"role": "user", "content": str(u_text)})
154
  if len(turn) > 1 and turn[1]:
155
  messages.append({"role": "assistant", "content": str(turn[1])})
 
156
  elif isinstance(turn, dict):
157
  messages.append(turn)
158
 
 
159
  current_content = []
160
+ if isinstance(message, dict):
161
  text = message.get("text", "")
162
  files = message.get("files", [])
163
  if text: current_content.append({"type": "text", "text": text})
 
165
 
166
  if not files: messages.append({"role": "user", "content": text})
167
  else: messages.append({"role": "user", "content": current_content})
168
+ else:
169
  messages.append({"role": "user", "content": str(message)})
170
 
 
171
  print(f"🔀 Roteando para: {model_selector}")
172
 
 
173
  if "Gemini" in model_selector:
174
  tid = "gemini-1.5-flash"
175
  if "3.0" in model_selector: tid = "gemini-3.0-pro-preview"
 
178
  elif "2.0" in model_selector: tid = "gemini-2.0-flash-exp"
179
  return run_gemini(messages, tid)
180
 
 
181
  elif "Mistral" in model_selector:
182
  tid = "mistral-large-latest"
183
  if "Pixtral" in model_selector: tid = "pixtral-large-latest"
184
+ elif "2509" in model_selector: tid = "magistral-medium-2509"
185
  elif "2512" in model_selector: tid = "mistral-large-2512"
186
  elif "Codestral" in model_selector: tid = "codestral-2508"
187
  return run_mistral(messages, tid)
188
 
 
189
  elif "Groq" in model_selector:
190
  tid = "llama-3.3-70b-versatile"
191
+ if "120B" in model_selector: tid = "openai/gpt-oss-120b"
192
+ elif "20B" in model_selector: tid = "openai/gpt-oss-20b"
193
  return run_groq(messages, tid)
194
 
 
195
  elif "H200" in model_selector:
196
  return run_local_h200(messages)
197
 
198
  return "⚠️ Modelo não reconhecido."
199
 
200
+ # --- 6. INTERFACE (SEM TEMA - CORREÇÃO) ---
201
+ # Berta: Removi theme=gr.themes.Soft() pois sua versão do Gradio não suporta.
202
+ with gr.Blocks() as demo:
203
  gr.Markdown("# 🔀 APIDOST v8: The Arsenal")
204
 
205
  with gr.Row():
 
223
  interactive=True
224
  )
225
 
 
226
  chat = gr.ChatInterface(
227
  fn=router,
228
  additional_inputs=[model_dropdown],
 
230
  )
231
 
232
  if __name__ == "__main__":
 
233
  try: snapshot_download(repo_id=LOCAL_MODEL_ID)
234
  except: pass
 
235
  demo.queue().launch()