Aplicación Local con LLM Open-Source

 Aplicación Local con LLM Open-Source para Generar Actas de Audiencia

Voy a mostrarte cómo construir una solución completamente local y open-source usando modelos de HuggingFace y herramientas Python.

1. Modelos Open-Source Recomendados

Para esta tarea, estos modelos funcionan bien:

  • Resumen: facebook/bart-large-cnn, google/pegasus-xsum

  • Generación de texto: databricks/dolly-v2-12b, togethercomputer/RedPajama-INCITE-7B-Instruct

  • Especializados legal: nlpaueb/legal-bert-base-uncased, LexPredict/lexgpt

2. Instalación de Dependencias

bash
pip install transformers torch sentencepiece python-docx unstructured

3. Implementación Completa

python
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
from docx import Document
import datetime

class GeneradorActasLocal:
    def __init__(self):
        # Cargar modelo de resumen
        self.resumidor = pipeline(
            "summarization", 
            model="facebook/bart-large-cnn",
            device="cpu"  # Cambia a "cuda" si tienes GPU
        )
        
        # Cargar modelo generativo (ej. Dolly)
        self.tokenizer = AutoTokenizer.from_pretrained("databricks/dolly-v2-3b")
        self.generador = AutoModelForSeq2SeqLM.from_pretrained(
            "databricks/dolly-v2-3b",
            device_map="auto"
        )
        
        # Plantilla base
        self.plantilla = """
        ACTA DE AUDIENCIA - {fecha}
        
        LUGAR: {lugar}
        HORA INICIO: {hora_inicio}
        HORA TÉRMINO: {hora_termino}
        
        PARTICIPANTES:
        {participantes}
        
        PUNTOS TRATADOS:
        {puntos}
        
        ACUERDOS:
        {acuerdos}
        
        OBSERVACIONES:
        {observaciones}
        
        FIRMAS:
        {firmas}
        """

    def resumir_texto(self, texto, max_length=150):
        return self.resumidor(texto, max_length=max_length)[0]['summary_text']
    
    def generar_texto_estructurado(self, prompt):
        inputs = self.tokenizer(prompt, return_tensors="pt").to("cuda")
        outputs = self.generador.generate(**inputs, max_new_tokens=200)
        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    def extraer_entidades(self, texto):
        # Implementar NER aquí o usar librería como spaCy
        return {
            "participantes": "Participante 1, Participante 2",
            "puntos": "1. Punto uno\n2. Punto dos",
            "acuerdos": "Ninguno registrado"
        }
    
    def generar_acta(self, texto_audiencia, lugar="Sala de audiencias"):
        # Paso 1: Resumir el contenido
        resumen = self.resumir_texto(texto_audiencia)
        
        # Paso 2: Extraer información estructurada
        entidades = self.extraer_entidades(texto_audiencia)
        
        # Paso 3: Generar contenido para secciones
        prompt_acuerdos = f"Basado en el siguiente texto de audiencia, lista los acuerdos alcanzados:\n\n{texto_audiencia}"
        acuerdos = self.generar_texto_estructurado(prompt_acuerdos)
        
        # Paso 4: Completar plantilla
        ahora = datetime.datetime.now()
        acta = self.plantilla.format(
            fecha=ahora.strftime("%d/%m/%Y"),
            lugar=lugar,
            hora_inicio=ahora.strftime("%H:%M"),
            hora_termino=(ahora + datetime.timedelta(hours=1)).strftime("%H:%M"),
            participantes=entidades["participantes"],
            puntos=entidades["puntos"],
            acuerdos=acuerdos,
            observaciones=resumen,
            firmas="___________________________\n___________________________"
        )
        
        return acta
    
    def guardar_word(self, texto, nombre_archivo="acta.docx"):
        doc = Document()
        for linea in texto.split('\n'):
            if linea.strip().startswith('ACTA') or linea.strip().startswith('LUGAR'):
                doc.add_heading(linea.strip(), level=1)
            elif linea.strip().endswith(':'):
                doc.add_heading(linea.strip(), level=2)
            else:
                doc.add_paragraph(linea)
        doc.save(nombre_archivo)
        return nombre_archivo

# Uso
if __name__ == "__main__":
    generador = GeneradorActasLocal()
    
    # Ejemplo de texto de audiencia (en la práctica, leerías de un archivo)
    texto_ejemplo = """
    En la audiencia celebrada hoy, el juez Rodríguez inició la sesión a las 10:00 AM...
    El abogado Pérez presentó sus argumentos sobre el caso de indemnización...
    La contraparte, representada por el abogado Gómez, solicitó una prórroga...
    Se acordó revisar la documentación adicional y reprogramar para el día 15...
    """
    
    acta = generador.generar_acta(texto_ejemplo)
    print("Acta generada:\n", acta)
    
    archivo = generador.guardar_word(acta)
    print(f"Documento guardado como {archivo}")

4. Alternativas para Mejorar el Sistema

Usar modelos especializados en documentos legales:

python
# Reemplazar en __init__:
self.legal_model = pipeline(
    "text-generation",
    model="LexPredict/lexgpt",
    device="cuda" if torch.cuda.is_available() else "cpu"
)

Procesamiento de documentos PDF/Word existentes:

python
from unstructured.partition.auto import partition

def procesar_documento(self, ruta_archivo):
    elements = partition(ruta_archivo)
    texto = "\n".join([str(el) for el in elements])
    return self.generar_acta(texto)

5. Requisitos del Sistema

  • Mínimos: 16GB RAM, sin GPU (usará CPU)

  • Recomendado: 32GB RAM, GPU con 8GB+ VRAM

  • Óptimo: GPU con 24GB+ VRAM para modelos grandes

6. Posibles Problemas y Soluciones

  1. Memoria insuficiente:

    • Usa modelos más pequeños (ej. "facebook/bart-large-cnn" en lugar de modelos de 7B)

    • Implementa carga en 8-bit: model = AutoModelForSeq2SeqLM.from_pretrained(..., load_in_8bit=True)

  2. Calidad de resultados:

    • Afina los prompts

    • Implementa un sistema de post-procesamiento

    • Entrena un modelo específico con datos de actas reales (fine-tuning)

Comentarios

Entradas populares de este blog

Los 3 mejores LLMs ligeros y open source para tu caso

Mistral 7B Instruct cuantizado

editor de texto enriquecido nativo