GPT-Acredita-350M

El primer modelo de lenguaje entrenado desde cero para responder preguntas sobre acreditación universitaria colombiana.


Descripción

GPT-Acredita-350M es un modelo GPT-2 style de 350 millones de parámetros entrenado completamente desde cero sobre un corpus de pregunta-respuesta especializado en acreditación universitaria colombiana. A diferencia de los modelos de propósito general, este modelo fue diseñado específicamente para responder preguntas sobre el marco normativo del Consejo Nacional de Acreditación (CNA), el Decreto 1330 de 2019, la Resolución 21795 de 2020 y los procesos de autoevaluación de programas académicos colombianos.

El modelo fue desarrollado por el grupo de investigación de la Escuela de Ingeniería de Sistemas y Computación (EISC) de la Universidad del Valle, Cali, Colombia, como parte del proyecto ChatAcredita PRO.


Características del modelo

Parámetro Valor
Arquitectura GPT-2 style (transformer decoder causal)
Parámetros ~350 millones
Capas 24
Cabezas de atención 16
Dimensión embedding 1024
Tamaño de contexto 1024 tokens
Vocabulario 32,000 tokens (BPE propio)
Tokenizer BPE entrenado sobre corpus CNA
Formato de entrenamiento Pregunta-Respuesta (Q&A)
Iteraciones 50,000 steps
Entrenamiento Desde cero — sin modelo base previo
Hardware NVIDIA RTX 4090 (24 GB VRAM)
Tiempo de entrenamiento ~15 horas

Dataset de entrenamiento

El modelo fue entrenado sobre un corpus de pregunta-respuesta generado a partir de más de 700 documentos institucionales de acreditación universitaria colombiana, procesados con el siguiente pipeline:

  1. Extracción de texto con pymupdf4llm (soporte para tablas e imágenes)
  2. Chunking semántico con solapamiento
  3. Generación de pares Q&A con Llama-3.3-70B-Versatile vía Groq API
  4. Formato delimitado para entrenamiento causal:
### Pregunta: ¿Cuáles son los 10 factores del CNA?
### Respuesta: Los factores son: 1) Misión y Proyecto Institucional...
<|eos|>

Fuentes del corpus:

  • Lineamientos CNA para acreditación de alta calidad
  • Decreto 1330 de 2019 (registro calificado)
  • Resolución 21795 de 2020
  • Reportes de autoevaluación EISC (factores 1–10)
  • Documentos de programas PAIS y TEDESOFT
  • Reportes de grupos de investigación (Minciencias/Colciencias)

Tamaño del corpus: ~93,829 pares Q&A · ~5.8M tokens


Uso

Instalación

pip install torch transformers tokenizers huggingface_hub

Inferencia básica

import torch
from huggingface_hub import hf_hub_download
from tokenizers import Tokenizer

# Descargar modelo y tokenizer
model_path     = hf_hub_download("raulgdp/gpt-acredita-350m", "gpt_acredita.pt")
tokenizer_path = hf_hub_download("raulgdp/gpt-acredita-350m", "tokenizer.json")

# Cargar tokenizer
tokenizer = Tokenizer.from_file(tokenizer_path)

# Cargar modelo
checkpoint = torch.load(model_path, map_location="cpu", weights_only=False)
config     = checkpoint["config"]

# --- Definir la arquitectura GPT-Acredita ---
import torch.nn as nn

class CausalSelfAttention(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.n_head  = config["n_head"]
        self.n_embd  = config["n_embd"]
        self.c_attn  = nn.Linear(config["n_embd"], 3 * config["n_embd"])
        self.c_proj  = nn.Linear(config["n_embd"], config["n_embd"])
        self.register_buffer("bias", torch.tril(
            torch.ones(config["block_size"], config["block_size"])
        ).view(1, 1, config["block_size"], config["block_size"]))

    def forward(self, x):
        B, T, C = x.size()
        q, k, v = self.c_attn(x).split(self.n_embd, dim=2)
        k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
        q = q.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
        v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
        att = (q @ k.transpose(-2, -1)) * (1.0 / (k.size(-1) ** 0.5))
        att = att.masked_fill(self.bias[:, :, :T, :T] == 0, float("-inf"))
        att = torch.softmax(att, dim=-1)
        return (att @ v).transpose(1, 2).contiguous().view(B, T, C)

class MLP(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.c_fc   = nn.Linear(config["n_embd"], 4 * config["n_embd"])
        self.c_proj = nn.Linear(4 * config["n_embd"], config["n_embd"])
        self.act    = nn.GELU()
    def forward(self, x):
        return self.c_proj(self.act(self.c_fc(x)))

class Block(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.ln_1 = nn.LayerNorm(config["n_embd"])
        self.attn = CausalSelfAttention(config)
        self.ln_2 = nn.LayerNorm(config["n_embd"])
        self.mlp  = MLP(config)
    def forward(self, x):
        x = x + self.attn(self.ln_1(x))
        x = x + self.mlp(self.ln_2(x))
        return x

class GPTAcredita(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.transformer = nn.ModuleDict({
            "wte": nn.Embedding(config["vocab_size"], config["n_embd"]),
            "wpe": nn.Embedding(config["block_size"], config["n_embd"]),
            "h":   nn.ModuleList([Block(config) for _ in range(config["n_layer"])]),
            "ln_f": nn.LayerNorm(config["n_embd"]),
        })
        self.lm_head = nn.Linear(config["n_embd"], config["vocab_size"], bias=False)

    def forward(self, idx):
        B, T = idx.size()
        pos  = torch.arange(T, device=idx.device)
        x    = self.transformer.wte(idx) + self.transformer.wpe(pos)
        for block in self.transformer.h:
            x = block(x)
        return self.lm_head(self.transformer.ln_f(x))

    @torch.no_grad()
    def generate(self, idx, max_new_tokens=200, temperature=0.7, top_k=50):
        for _ in range(max_new_tokens):
            idx_cond = idx[:, -config["block_size"]:]
            logits   = self(idx_cond)[:, -1, :]
            logits   = logits / temperature
            v, _     = torch.topk(logits, min(top_k, logits.size(-1)))
            logits[logits < v[:, [-1]]] = float("-inf")
            idx = torch.cat([idx, torch.multinomial(
                torch.softmax(logits, dim=-1), num_samples=1
            )], dim=1)
            # Detener en <|eos|>
            if tokenizer.token_to_id("<|eos|>") in idx[0, -3:].tolist():
                break
        return idx

# Cargar pesos
device = "cuda" if torch.cuda.is_available() else "cpu"
model  = GPTAcredita(config).to(device)
model.load_state_dict(checkpoint["model_state_dict"])
model.eval()

# Hacer una pregunta
def preguntar(pregunta: str, max_tokens: int = 200) -> str:
    prompt  = f"### Pregunta: {pregunta}\n### Respuesta:"
    encoded = tokenizer.encode(prompt)
    ids     = torch.tensor([encoded.ids], dtype=torch.long, device=device)
    out     = model.generate(ids, max_new_tokens=max_tokens, temperature=0.7)
    decoded = tokenizer.decode(out[0].tolist())
    if "### Respuesta:" in decoded:
        resp = decoded.split("### Respuesta:")[-1]
        return resp.split("<|eos|>")[0].strip()
    return decoded

# Ejemplo
print(preguntar("¿Cuáles son los 10 factores del CNA?"))
print(preguntar("¿Qué establece el Decreto 1330 de 2019?"))

Limitaciones

  • Con 350M parámetros, las respuestas son menos precisas que modelos más grandes como DeepSeek-Acredita-14B.
  • El modelo puede alucinar detalles normativos específicos (artículos, fechas, cifras exactas).
  • Diseñado para uso en sistemas RAG donde el contexto documental complementa la generación.
  • El vocabulario BPE fue entrenado sobre el corpus CNA — puede tener dificultades con texto fuera de este dominio.

Contexto del proyecto

Este modelo es parte del ecosistema ChatAcredita PRO, que incluye:

Modelo Descripción
raulgdp/gpt-acredita-350m GPT desde cero — baseline Q&A
raulgdp/deepseek14b-acredita DeepSeek-R1-Distill-Qwen-14B fine-tuned

El sistema completo usa un pipeline RAG con BGE-M3 + BM25 → RRF → BGE-Reranker-v2-m3 sobre una colección Qdrant Cloud con más de 90,000 fragmentos de documentos CNA.


Cita

@misc{gutierrez2025gptacredita,
  title        = {GPT-Acredita-350M: A Causal Language Model Trained from Scratch
                  for Colombian University Accreditation Q\&A},
  author       = {Gutierrez, Raul and others},
  year         = {2025},
  institution  = {EISC, Universidad del Valle, Cali, Colombia},
  howpublished = {\url{https://huggingface.co/raulgdp/gpt-acredita-350m}},
  note         = {ChatAcredita PRO Project}
}

Licencia

Apache 2.0


Desarrollado en la Escuela de Ingeniería de Sistemas y Computación (EISC), Universidad del Valle, Cali, Colombia.

Downloads last month
19
Safetensors
Model size
0.3B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for raulgdp/gpt-acredita-350m

Finetuned
(2264)
this model

Collection including raulgdp/gpt-acredita-350m