Spaces:
Sleeping
Sleeping
| from openai import OpenAI | |
| import os | |
| import time | |
| import tempfile | |
| import docx | |
| from PIL import Image | |
| from utils.utils import preparar_bloques_texto_redes, markdown_a_word_docx | |
| openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| def analizar_archivo_y_generar_articulo(archivo): | |
| nombre = archivo.name.lower() | |
| if not (nombre.endswith(".docx")): | |
| yield None, "❌ El archivo debe ser un Word (.docx).", "" | |
| return | |
| yield None, "⏳ Leyendo archivo...", "" | |
| # Leer contenido | |
| textos = [] | |
| doc = docx.Document(archivo.name) | |
| textos = [p.text for p in doc.paragraphs if p.text.strip()] | |
| # if nombre.endswith(".docx"): | |
| # doc = docx.Document(archivo.name) | |
| # textos = [p.text for p in doc.paragraphs if p.text.strip()] | |
| # elif nombre.endswith((".jpg", ".png")): | |
| # image = Image.open(archivo.name) | |
| # texto_extraido = pytesseract.image_to_string(image) | |
| # textos = [texto_extraido] | |
| if not textos: | |
| yield None, "❌ No se pudo extraer contenido del archivo.", "" | |
| return | |
| bloques = preparar_bloques_texto_redes(textos) | |
| yield None, f"📑 {len(bloques)} bloques de texto detectados. Generando artículo...", "" | |
| articulos_parciales = [] | |
| for idx, bloque in enumerate(bloques): | |
| prompt = f"""Actúa como un periodista profesional. | |
| Redacta un artículo periodístico con la información del siguiente bloque: | |
| {bloque} | |
| 📌 Formato del artículo: | |
| - `#` Título | |
| - `##` Copete | |
| - `### Entradilla` | |
| - `### Desarrollo` | |
| - `### Cierre` | |
| No inventes datos. No uses encabezados diferentes ni emojis. Usa listas o tablas si es relevante. | |
| """ | |
| try: | |
| response = openai.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=[ | |
| {"role": "system", "content": "Eres un redactor periodístico profesional."}, | |
| {"role": "user", "content": prompt} | |
| ] | |
| ) | |
| articulo = response.choices[0].message.content.strip() | |
| articulos_parciales.append(articulo) | |
| yield None, f"✅ Bloque {idx+1}/{len(bloques)} procesado.", None | |
| except Exception as e: | |
| yield None, f"⚠️ Error en bloque {idx+1}: {e}", None | |
| # Generar artículo final | |
| if len(articulos_parciales) == 1: | |
| articulo_final = articulos_parciales[0] | |
| else: | |
| borradores = "\n\n".join(articulos_parciales) | |
| prompt_global = f"""A continuación, tienes varios borradores parciales de artículos periodísticos basados en diferentes bloques de información. | |
| {borradores} | |
| Unifica estos borradores en un único artículo profesional, estructurado con título, copete, entradilla, cuerpo y cierre. No repitas contenido, hazlo coherente y fluido como un único artículo largo, sin inventar datos.""" | |
| response = openai.chat.completions.create( | |
| model="gpt-4o", | |
| messages=[ | |
| {"role": "system", "content": "Eres un periodista experto en síntesis y redacción final."}, | |
| {"role": "user", "content": prompt_global} | |
| ] | |
| ) | |
| articulo_final = response.choices[0].message.content.strip() | |
| # Guardar artículo final como Markdown primero | |
| temp_md = tempfile.NamedTemporaryFile(delete=False, suffix=".md").name | |
| with open(temp_md, "w", encoding="utf-8") as f: | |
| f.write(articulo_final) | |
| # Convertir markdown a Word | |
| temp_docx = tempfile.NamedTemporaryFile(delete=False, suffix=".docx").name | |
| markdown_a_word_docx(temp_md, temp_docx) | |
| yield temp_docx, "✅ Artículo final generado correctamente.", "✅ Artículo generado con éxito" |