amp / app.py
CamiloVega's picture
Update app.py
a045b1b verified
import os
import openai
import whisper
import tempfile
import gradio as gr
from pydub import AudioSegment
import fitz # PyMuPDF para manejar PDFs
import docx # Para manejar archivos .docx
import pandas as pd # Para manejar archivos .xlsx y .csv
#from google.colab import userdata # Importa userdata de google.colab
# Load environment variables from the Hugging Face environment
openai.api_key = os.getenv("OPENAI_API_KEY")
# Configura tu clave API de OpenAI usando Google Colab userdata
#openai.api_key = userdata.get('OPENAI_API_KEY')
# Cargar el modelo Whisper de mayor calidad una vez
model = whisper.load_model("large")
def preprocess_audio(audio_file):
"""Preprocesa el archivo de audio para mejorar la calidad."""
try:
audio = AudioSegment.from_file(audio_file)
audio = audio.apply_gain(-audio.dBFS + (-20))
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:
audio.export(temp_file.name, format="mp3")
return temp_file.name
except Exception as e:
return f"Error al preprocesar el archivo de audio: {str(e)}"
def transcribir_audio(audio_file):
"""Transcribe un archivo de audio."""
try:
archivo_path = preprocess_audio(audio_file) if isinstance(audio_file, str) else preprocess_audio(tempfile.NamedTemporaryFile(delete=False, suffix=".mp3", mode='w+b').name)
resultado = model.transcribe(archivo_path)
return resultado.get("text", "Error en la transcripción")
except Exception as e:
return f"Error al procesar el archivo de audio: {str(e)}"
def leer_documento(documento_path):
"""Lee el contenido de un documento PDF, DOCX, XLSX o CSV."""
try:
if documento_path.endswith(".pdf"):
doc = fitz.open(documento_path)
return "\n".join([pagina.get_text() for pagina in doc])
elif documento_path.endswith(".docx"):
doc = docx.Document(documento_path)
return "\n".join([parrafo.text for parrafo in doc.paragraphs])
elif documento_path.endswith(".xlsx"):
return pd.read_excel(documento_path).to_string()
elif documento_path.endswith(".csv"):
return pd.read_csv(documento_path).to_string()
else:
return "Tipo de archivo no soportado. Por favor suba un documento PDF, DOCX, XLSX o CSV."
except Exception as e:
return f"Error al leer el documento: {str(e)}"
# Diccionario con las plantillas de Historias AMP
plantillas_amp = {
"Plantilla 1": "<div class=\"AmpStorie-container1\"><div class=\"AmpStorie-text1\">{contenido}</div></div>",
"Plantilla 2": "<div class=\"AmpStorie-text2\">{contenido}</div>",
"Plantilla 3": "<div class=\"AmpStorie-text3\">{contenido}</div>",
"Plantilla 4": "<div class=\"AmpStorie-container AmpStorie-container_full\"><div class=\"AmpStorie-text4\">{contenido}</div></div>",
"Plantilla 5": "<div class=\"AmpStorie-container AmpStorie-container_full\"><div class=\"AmpStorie-elementContainer\"><div class=\"AmpStorie-line\"></div><div class=\"AmpStorie-text5\">{contenido}</div></div></div>",
}
def generar_historia_amp(instrucciones, hechos, tono, plantilla_seleccionada, *args):
"""Genera una historia AMP a partir de instrucciones, hechos y transcripciones."""
tamaño = 40 # Tamaño fijo de 40 palabras
base_de_conocimiento = {"instrucciones": instrucciones, "hechos": hechos, "contenido_documentos": [], "audio_data": []}
num_audios = 5 * 3 # 5 audios * 3 campos (audio, nombre, cargo)
audios = args[:num_audios]
documentos = args[num_audios:]
for documento in documentos:
if documento is not None:
base_de_conocimiento["contenido_documentos"].append(leer_documento(documento.name))
for i in range(0, len(audios), 3):
audio_file, nombre, cargo = audios[i:i+3]
if audio_file is not None:
base_de_conocimiento["audio_data"].append({"audio": audio_file, "nombre": nombre, "cargo": cargo})
transcripciones_texto, transcripciones_brutas, total_citas_directas = "", "", 0
for idx, data in enumerate(base_de_conocimiento["audio_data"]):
if data["audio"] is not None:
transcripcion = transcribir_audio(data["audio"])
transcripcion_texto = f'"{transcripcion}" - {data["nombre"]}, {data["cargo"]}'
transcripcion_bruta = f'[Audio {idx + 1}]: "{transcripcion}" - {data["nombre"]}, {data["cargo"]}'
if total_citas_directas < len(base_de_conocimiento["audio_data"]) * 0.8:
transcripciones_texto += transcripcion_texto + "\n"
total_citas_directas += 1
else:
transcripciones_texto += f'{data["nombre"]} mencionó que {transcripcion}' + "\n"
transcripciones_brutas += transcripcion_bruta + "\n\n"
contenido_documentos = "\n\n".join(base_de_conocimiento["contenido_documentos"])
prompt_interno = """
Instrucciones para el modelo:
- Genera 6 bullets o puntos clave relacionados con las instrucciones y hechos proporcionados.
- Cada bullet debe tener aproximadamente {tamaño} palabras.
- recuerda: siempre debes generar seis bullets, de {tamaño} palabras cada uno
- No inventes información nueva.
- Sé riguroso con los hechos proporcionados.
- Genera una narrativa conectada y coherente entre los bullets, formando una historia completa.
- Al procesar los documentos cargados, extrae y resalta citas importantes y testimonios textuales de las fuentes.
- Al procesar los documentos cargados, extrae y resalta cifras clave.
"""
prompt = f"""
{prompt_interno}
Genera 6 bullets o puntos clave relacionados con la siguiente información, incluyendo un título y un gancho de 15 palabras (el gancho es lo que se conoce en inglés como hook, información adicional que complementa el título). El tono debe ser {tono}.
Instrucciones: {base_de_conocimiento["instrucciones"]}
Hechos: {base_de_conocimiento["hechos"]}
Contenido adicional de los documentos: {contenido_documentos}
Utiliza las siguientes transcripciones como citas directas e indirectas (sin cambiar ni inventar contenido):
{transcripciones_texto}
"""
try:
respuesta = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
texto = respuesta['choices'][0]['message']['content']
lines = texto.split("\n")
# Encontrar título y gancho
titulo = lines[0]
gancho = lines[1]
# Generar los bullets
bullets = []
bullet = ""
word_count = 0
for line in lines[2:]:
words = line.split()
if word_count + len(words) > tamaño:
bullets.append(bullet.strip())
bullet = line
word_count = len(words)
else:
bullet += " " + line
word_count += len(words)
if bullet:
bullets.append(bullet.strip())
# Encapsular los bullets en la plantilla seleccionada
contenido_bullets = ""
for bullet in bullets:
if bullet:
contenido_bullets += plantillas_amp[plantilla_seleccionada].format(contenido=bullet) + "\n\n"
historia_amp = f"{titulo}\n\n{gancho}\n\n{contenido_bullets}"
return historia_amp, transcripciones_brutas
except Exception as e:
return f"Error al generar la historia AMP: {str(e)}", ""
demo = gr.Blocks() # Crea el contexto de Gradio.Blocks()
with demo:
with gr.Column(scale=2):
instrucciones = gr.Textbox(label="Instrucciones para la historia AMP", lines=2)
hechos = gr.Textbox(label="Describe los hechos de la historia AMP", lines=4)
tono = gr.Dropdown(label="Tono de la historia AMP", choices=["serio", "neutral", "divertido"], value="neutral")
plantilla = gr.Dropdown(label="Plantilla AMP", choices=list(plantillas_amp.keys()), value="Plantilla 1")
with gr.Column(scale=3):
inputs_list = [instrucciones, hechos, tono, plantilla]
with gr.Tabs():
for i in range(1, 6):
with gr.TabItem(f"Audio {i}"):
audio = gr.Audio(type="filepath", label=f"Audio {i}")
nombre = gr.Textbox(label="Nombre", scale=1)
cargo = gr.Textbox(label="Cargo", scale=1)
inputs_list.extend([audio, nombre, cargo])
for i in range(1, 6):
with gr.TabItem(f"Documento {i}"):
documento = gr.File(label=f"Documento {i}")
inputs_list.append(documento)
btn_generar = gr.Button(value="Generar historia AMP")
output_historia = gr.Textbox(label="Historia AMP generada", lines=20)
output_transcripciones = gr.Textbox(label="Transcripciones brutas de los audios", lines=10)
btn_generar.click(generar_historia_amp, inputs_list, [output_historia, output_transcripciones])
demo.launch(debug=True)