Sara / app.py
N3lson's picture
Update app.py
4963880 verified
Raw
History Blame Contribute Delete
4.39 kB
import os
import subprocess
import time
import gradio as gr
import requests
from huggingface_hub import hf_hub_download
# 1. Ajuste al repositorio oficial de Google (GGUF Balanceado)
REPO_ID = "google/gemma-4-12B-it-qat-q4_0-gguf"
FILENAME = "gemma-4-12b-it-qat-q4_0.gguf"
BIN_PATH = "./serverLlama"
# Definimos la ruta de destino limpia
MODEL_PATH = "/app/gemma-4-12b.gguf" if os.path.exists("/app") else "./gemma-4-12b.gguf"
if not os.path.exists(MODEL_PATH):
print(f"Descargando {FILENAME} desde el repositorio oficial de Google...")
descarga = hf_hub_download(
repo_id=REPO_ID,
filename=FILENAME,
local_dir="/app" if os.path.exists("/app") else "."
)
# Renombramos el archivo para que coincida con la ruta de tu serverLlama
os.rename(descarga, MODEL_PATH)
print("¡Descarga oficial completada con éxito!")
# 2. Darle permisos de ejecución a tu binario subido
print("Configurando permisos para serverLlama...")
os.chmod(BIN_PATH, 0o755)
# 3. Arrancar tu binario serverLlama en segundo plano con 32k de contexto
print("Encendiendo serverLlama con 32k de contexto en segundo plano...")
subprocess.Popen([
BIN_PATH,
"--model", MODEL_PATH,
"--host", "127.0.0.1",
"--port", "8080",
"--threads", "2",
"--ctx-size", "32768",
# 🔥 EXTREMO - SOLO PARA PRUEBAS (Necesita 65GB+ RAM)
# "--ctx-size", "262144", # 262K - Límite oficial del modelo
# "--ctx-size", "229376", # 224K - Casi máximo
# "--ctx-size", "196608", # 192K - Muy pesado
# "--ctx-size", "163840", # 160K - Extremo
# ⚠️ MUY ALTO (Necesita 40GB+ RAM)
# "--ctx-size", "131072", # 128K - Análisis de libros completos
# "--ctx-size", "114688", # 112K - Documentos muy largos
# "--ctx-size", "98304", # 96K - Investigación profunda
# 📊 ALTO (Necesita 27GB+ RAM)
# "--ctx-size", "81920", # 80K - Análisis extenso
# "--ctx-size", "73728", # 72K - Documentos largos
# "--ctx-size", "65536", # 64K - Límite recomendado para 32GB RAM
# "--ctx-size", "24576",
"--n-predict", "4096",
# Optimizaciones de caché
"--cache-type-k", "q4_0",
"--cache-type-v", "q4_0",
# Batch size para 2 vCPUs
# "--batch-size", "4096",
# "--ubatch-size", "4096",
"--batch-size", "1536",
"--ubatch-size", "768",
])
# Esperamos a que el backend en C++ reserve la memoria y levante el puerto
time.sleep(10)
print("¡Servidor backend en C++ listo!")
# 4. Función de comunicación entre Gradio y tu binario local
def predict_api(prompt, system_prompt="Eres un asistente experto y conciso."):
if not prompt.strip():
return "Por favor, escribe un prompt válido."
headers = {"Content-Type": "application/json"}
data = {
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": prompt}
],
"temperature": 0.7
}
try:
response = requests.post("http://127.0.0.1:8080/v1/chat/completions", json=data, headers=headers)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"].strip()
return f"Error del backend (Código {response.status_code}): {response.text}"
except Exception as e:
return f"Error al conectar con serverLlama: {e}"
# 5. Interfaz Gráfica Estándar de Gradio
with gr.Blocks() as demo:
gr.Markdown("# Backend de IA - Sara (serverLlama + Gradio 32k)")
with gr.Row():
with gr.Column():
txt_prompt = gr.Textbox(label="Prompt / Pregunta", lines=4, placeholder="Escribe aquí...")
txt_system = gr.Textbox(label="System Prompt", value="Eres un asistente experto.", lines=2)
btn_enviar = gr.Button("Enviar", variant="primary")
with gr.Column():
txt_salida = gr.Textbox(label="Respuesta de Sara", lines=8, interactive=False)
btn_enviar.click(fn=predict_api, inputs=[txt_prompt, txt_system], outputs=txt_salida)
# Endpoint expuesto para tu script local
api_endpoint = gr.Interface(
fn=predict_api,
inputs=[gr.Textbox(elem_id="prompt"), gr.Textbox(elem_id="system_prompt")],
outputs=gr.Textbox(),
api_name="predict_api"
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)