初始化项目,由ModelHub XC社区提供模型
Model: raulgdp/gpt-acredita-350m Source: Original Platform
This commit is contained in:
35
.gitattributes
vendored
Normal file
35
.gitattributes
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.model filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||||
|
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||||
252
README.md
Normal file
252
README.md
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
---
|
||||||
|
language:
|
||||||
|
- es
|
||||||
|
license: apache-2.0
|
||||||
|
tags:
|
||||||
|
- text-generation
|
||||||
|
- gpt2
|
||||||
|
- acreditacion
|
||||||
|
- colombia
|
||||||
|
- cna
|
||||||
|
library_name: transformers
|
||||||
|
pipeline_tag: text-generation
|
||||||
|
base_model: gpt2
|
||||||
|
---
|
||||||
|
# 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install torch transformers tokenizers huggingface_hub
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inferencia básica
|
||||||
|
|
||||||
|
```python
|
||||||
|
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](https://huggingface.co/raulgdp/deepseek14b-acredita).
|
||||||
|
- 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
|
||||||
|
|
||||||
|
```bibtex
|
||||||
|
@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.*
|
||||||
32
config.json
Normal file
32
config.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"activation_function": "gelu_new",
|
||||||
|
"architectures": [
|
||||||
|
"GPT2LMHeadModel"
|
||||||
|
],
|
||||||
|
"attn_pdrop": 0.0,
|
||||||
|
"bos_token_id": 1,
|
||||||
|
"dtype": "float32",
|
||||||
|
"embd_pdrop": 0.0,
|
||||||
|
"eos_token_id": 2,
|
||||||
|
"initializer_range": 0.02,
|
||||||
|
"layer_norm_epsilon": 1e-05,
|
||||||
|
"model_type": "gpt2",
|
||||||
|
"n_ctx": 1024,
|
||||||
|
"n_embd": 1024,
|
||||||
|
"n_head": 16,
|
||||||
|
"n_inner": 4096,
|
||||||
|
"n_layer": 24,
|
||||||
|
"n_positions": 1024,
|
||||||
|
"reorder_and_upcast_attn": false,
|
||||||
|
"resid_pdrop": 0.0,
|
||||||
|
"scale_attn_by_inverse_layer_idx": false,
|
||||||
|
"scale_attn_weights": true,
|
||||||
|
"summary_activation": null,
|
||||||
|
"summary_first_dropout": 0.1,
|
||||||
|
"summary_proj_to_labels": true,
|
||||||
|
"summary_type": "cls_index",
|
||||||
|
"summary_use_proj": true,
|
||||||
|
"transformers_version": "4.57.6",
|
||||||
|
"use_cache": true,
|
||||||
|
"vocab_size": 32000
|
||||||
|
}
|
||||||
6
generation_config.json
Normal file
6
generation_config.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"_from_model_config": true,
|
||||||
|
"bos_token_id": 1,
|
||||||
|
"eos_token_id": 2,
|
||||||
|
"transformers_version": "4.57.6"
|
||||||
|
}
|
||||||
3
gpt_acredita.pt
Normal file
3
gpt_acredita.pt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:f5180261593a1ec271dc4047c1b970205a82e3998e888ad7fb059ee5f2da7b00
|
||||||
|
size 4033894921
|
||||||
3
model.safetensors
Normal file
3
model.safetensors
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:54e67265eb71b0ddc427cd40acdcd48555175e23e6aa93083605be39b9473dc5
|
||||||
|
size 1344542208
|
||||||
6
special_tokens_map.json
Normal file
6
special_tokens_map.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"bos_token": "<|bos|>",
|
||||||
|
"eos_token": "<|eos|>",
|
||||||
|
"pad_token": "<|eos|>",
|
||||||
|
"unk_token": "<|unk|>"
|
||||||
|
}
|
||||||
159171
tokenizer.json
Normal file
159171
tokenizer.json
Normal file
File diff suppressed because it is too large
Load Diff
44
tokenizer_config.json
Normal file
44
tokenizer_config.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"added_tokens_decoder": {
|
||||||
|
"0": {
|
||||||
|
"content": "<|pad|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"content": "<|eos|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"content": "<|bos|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"content": "<|unk|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bos_token": "<|bos|>",
|
||||||
|
"clean_up_tokenization_spaces": false,
|
||||||
|
"eos_token": "<|eos|>",
|
||||||
|
"extra_special_tokens": {},
|
||||||
|
"model_max_length": 1024,
|
||||||
|
"pad_token": "<|eos|>",
|
||||||
|
"tokenizer_class": "PreTrainedTokenizerFast",
|
||||||
|
"unk_token": "<|unk|>"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user