conversor-ideas / app.py
lukasnet's picture
Upload app.py
340a631 verified
import gradio as gr
import subprocess
import os
import sys
from pathlib import Path
# Paths (Relative to Space root)
# In HF Spaces, we'll upload the Paper-KG-Pipeline folder
PIPELINE_SCRIPT = Path("Paper-KG-Pipeline/scripts/idea2story_pipeline.py")
OUTPUT_RESULT = Path("Paper-KG-Pipeline/output/pipeline_result.json")
def run_pipeline(idea, progress=gr.Progress()):
"""
Runs the Idea2Story pipeline script as a subprocess and streams output.
"""
logs = []
try:
if not idea.strip():
logs.append("⚠️ Por favor ingresa una idea.")
yield "\n".join(logs), None
return
# Locate Python executable
# In HF Spaces, we use the system python
python_exec = Path(sys.executable)
script_path = PIPELINE_SCRIPT.absolute()
if not script_path.exists():
logs.append(f"❌ No se encontró el script en: {script_path}")
yield "\n".join(logs), None
return
logs.append(f"🚀 Iniciando pipeline...")
logs.append(f"📂 Carpeta actual: {os.getcwd()}")
logs.append(f"📜 Script: {script_path}")
yield "\n".join(logs), None
command = [
str(python_exec),
str(script_path),
idea
]
# Ensure UTF-8 environment limits encoding errors
env = os.environ.copy()
env["PYTHONIOENCODING"] = "utf-8"
# HF specific: add to pythonpath
env["PYTHONPATH"] = os.path.join(os.getcwd(), "Paper-KG-Pipeline", "src")
# --- CONFIGURACIÓN AUTOMÁTICA PARA DEPLOY ---
# 1. Inyectar configuración de Gemini
env["LLM_PROVIDER"] = "openai_compatible_chat"
env["LLM_BASE_URL"] = "https://generativelanguage.googleapis.com/v1beta/openai/"
env["LLM_MODEL"] = "gemini-2.0-flash"
env["EMBEDDING_API_URL"] = "https://generativelanguage.googleapis.com/v1beta/openai/embeddings"
env["EMBEDDING_MODEL"] = "gemini-embedding-001"
# 2. Configurar reintentos para el Preflight (evitar fallo rápido)
env["I2P_PREFLIGHT_LLM_RETRIES"] = "10"
env["I2P_PREFLIGHT_EMB_RETRIES"] = "10"
# 3. Mapear clave API
if "GEMINI_API_KEY" in env:
env["LLM_API_KEY"] = env["GEMINI_API_KEY"]
env["EMBEDDING_API_KEY"] = env["GEMINI_API_KEY"]
logs.append("✅ GEMINI_API_KEY encontrada e inyectada.")
elif "LLM_API_KEY" not in env:
logs.append("⚠️ ADVERTENCIA: No se encontró GEMINI_API_KEY.")
logs.append(f"🔍 DEBUG: LLM_MODEL={env.get('LLM_MODEL')}")
# 4. (HOTFIX) Parchear common.py en el servidor para aumentar reintentos globales
# Esto evita tener que subir carpetas enteras de nuevo.
try:
common_py = Path("Paper-KG-Pipeline/src/idea2paper/infra/llm_providers/common.py")
if common_py.exists():
with open(common_py, "r", encoding="utf-8") as f:
content = f.read()
# Si tiene pocos reintentos, lo subimos a 15 y backoff a 4
if "total=8" not in content and "total=15" not in content:
logs.append("🔧 Parcheando common.py para mejorar resistencia a Rate Limits...")
# Reemplazamos configuraciones antiguas o por defecto
import re
content = re.sub(r"total=\d+", "total=15", content)
content = re.sub(r"backoff_factor=\d+", "backoff_factor=4", content)
content = re.sub(r"status_forcelist=\[.*?\]", "status_forcelist=[429, 500, 502, 503, 504]", content)
with open(common_py, "w", encoding="utf-8") as f:
f.write(content)
logs.append("✅ common.py parcheado con éxito.")
except Exception as e:
logs.append(f"⚠️ No se pudo parchear common.py: {e}")
# --------------------------------------------
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
encoding='utf-8',
errors='replace',
env=env,
cwd=os.getcwd()
)
# Stream output
for line in iter(process.stdout.readline, ''):
logs.append(line.rstrip())
if len(logs) % 1 == 0:
yield "\n".join(logs), None
process.wait()
if process.returncode == 0:
logs.append("\n✅ Pipeline completado con éxito!")
# Load result
if OUTPUT_RESULT.exists():
try:
import json
with open(OUTPUT_RESULT, "r", encoding="utf-8") as f:
result_data = json.load(f)
yield "\n".join(logs), result_data
except Exception as e:
logs.append(f"\n⚠️ Error leyendo resultado: {e}")
yield "\n".join(logs), None
else:
logs.append("\n⚠️ Archivo de resultado no encontrado.")
yield "\n".join(logs), None
else:
logs.append(f"\n❌ Pipeline falló con código {process.returncode}")
yield "\n".join(logs), None
except Exception as e:
import traceback
logs.append(f"\n❌ Error GUI: {str(e)}")
logs.append(traceback.format_exc())
yield "\n".join(logs), None
# GUI Layout
with gr.Blocks(title="Conversor de ideas en papers") as demo:
gr.Markdown("# 🚀 Conversor de ideas en papers")
gr.Markdown("Transforme su idea de investigación en una historia/documento estructurado utilizando gráficos de conocimiento y LLM.")
with gr.Row():
with gr.Column(scale=1):
idea_input = gr.Textbox(
label="Tu idea a investigar",
placeholder="ej: Razonamiento automatizado en grandes modelos de lenguaje...",
lines=3
)
run_btn = gr.Button("Generar Historia", variant="primary")
with gr.Row():
with gr.Column(scale=1):
logs_output = gr.Textbox(
label="Registros de Ejecución",
interactive=False,
lines=20,
autoscroll=True
)
with gr.Column(scale=1):
result_output = gr.JSON(
label="Resultado Generado",
)
run_btn.click(
fn=run_pipeline,
inputs=[idea_input],
outputs=[logs_output, result_output]
)
if __name__ == "__main__":
demo.launch()