Views
No views yet
| 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 |
pymupdf4llm (soporte para tablas e imágenes)Llama-3.3-70B-Versatile vía Groq API### Pregunta: ¿Cuáles son los 10 factores del CNA?
### Respuesta: Los factores son: 1) Misión y Proyecto Institucional...
<|eos|>pip install torch transformers tokenizers huggingface_hub1import torch
2from huggingface_hub import hf_hub_download
3from tokenizers import Tokenizer
4
5# Descargar modelo y tokenizer
6model_path = hf_hub_download("raulgdp/gpt-acredita-350m", "gpt_acredita.pt")
7tokenizer_path = hf_hub_download("raulgdp/gpt-acredita-350m", "tokenizer.json")
8
9# Cargar tokenizer
10tokenizer = Tokenizer.from_file(tokenizer_path)
11
12# Cargar modelo
13checkpoint = torch.load(model_path, map_location="cpu", weights_only=False)
14config = checkpoint["config"]
15
16# --- Definir la arquitectura GPT-Acredita ---
17import torch.nn as nn
18
19class CausalSelfAttention(nn.Module):
20 def __init__(self, config):
21 super().__init__()
22 self.n_head = config["n_head"]
23 self.n_embd = config["n_embd"]
24 self.c_attn = nn.Linear(config["n_embd"], 3 * config["n_embd"])
25 self.c_proj = nn.Linear(config["n_embd"], config["n_embd"])
26 self.register_buffer("bias", torch.tril(
27 torch.ones(config["block_size"], config["block_size"])
28 ).view(1, 1, config["block_size"], config["block_size"]))
29
30 def forward(self, x):
31 B, T, C = x.size()
32 q, k, v = self.c_attn(x).split(self.n_embd, dim=2)
33 k = k.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
34 q = q.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
35 v = v.view(B, T, self.n_head, C // self.n_head).transpose(1, 2)
36 att = (q @ k.transpose(-2, -1)) * (1.0 / (k.size(-1) ** 0.5))
37 att = att.masked_fill(self.bias[:, :, :T, :T] == 0, float("-inf"))
38 att = torch.softmax(att, dim=-1)
39 return (att @ v).transpose(1, 2).contiguous().view(B, T, C)
40
41class MLP(nn.Module):
42 def __init__(self, config):
43 super().__init__()
44 self.c_fc = nn.Linear(config["n_embd"], 4 * config["n_embd"])
45 self.c_proj = nn.Linear(4 * config["n_embd"], config["n_embd"])
46 self.act = nn.GELU()
47 def forward(self, x):
48 return self.c_proj(self.act(self.c_fc(x)))
49
50class Block(nn.Module):
51 def __init__(self, config):
52 super().__init__()
53 self.ln_1 = nn.LayerNorm(config["n_embd"])
54 self.attn = CausalSelfAttention(config)
55 self.ln_2 = nn.LayerNorm(config["n_embd"])
56 self.mlp = MLP(config)
57 def forward(self, x):
58 x = x + self.attn(self.ln_1(x))
59 x = x + self.mlp(self.ln_2(x))
60 return x
61
62class GPTAcredita(nn.Module):
63 def __init__(self, config):
64 super().__init__()
65 self.transformer = nn.ModuleDict({
66 "wte": nn.Embedding(config["vocab_size"], config["n_embd"]),
67 "wpe": nn.Embedding(config["block_size"], config["n_embd"]),
68 "h": nn.ModuleList([Block(config) for _ in range(config["n_layer"])]),
69 "ln_f": nn.LayerNorm(config["n_embd"]),
70 })
71 self.lm_head = nn.Linear(config["n_embd"], config["vocab_size"], bias=False)
72
73 def forward(self, idx):
74 B, T = idx.size()
75 pos = torch.arange(T, device=idx.device)
76 x = self.transformer.wte(idx) + self.transformer.wpe(pos)
77 for block in self.transformer.h:
78 x = block(x)
79 return self.lm_head(self.transformer.ln_f(x))
80
81 @torch.no_grad()
82 def generate(self, idx, max_new_tokens=200, temperature=0.7, top_k=50):
83 for _ in range(max_new_tokens):
84 idx_cond = idx[:, -config["block_size"]:]
85 logits = self(idx_cond)[:, -1, :]
86 logits = logits / temperature
87 v, _ = torch.topk(logits, min(top_k, logits.size(-1)))
88 logits[logits < v[:, [-1]]] = float("-inf")
89 idx = torch.cat([idx, torch.multinomial(
90 torch.softmax(logits, dim=-1), num_samples=1
91 )], dim=1)
92 # Detener en <|eos|>
93 if tokenizer.token_to_id("<|eos|>") in idx[0, -3:].tolist():
94 break
95 return idx
96
97# Cargar pesos
98device = "cuda" if torch.cuda.is_available() else "cpu"
99model = GPTAcredita(config).to(device)
100model.load_state_dict(checkpoint["model_state_dict"])
101model.eval()
102
103# Hacer una pregunta
104def preguntar(pregunta: str, max_tokens: int = 200) -> str:
105 prompt = f"### Pregunta: {pregunta}\n### Respuesta:"
106 encoded = tokenizer.encode(prompt)
107 ids = torch.tensor([encoded.ids], dtype=torch.long, device=device)
108 out = model.generate(ids, max_new_tokens=max_tokens, temperature=0.7)
109 decoded = tokenizer.decode(out[0].tolist())
110 if "### Respuesta:" in decoded:
111 resp = decoded.split("### Respuesta:")[-1]
112 return resp.split("<|eos|>")[0].strip()
113 return decoded
114
115# Ejemplo
116print(preguntar("¿Cuáles son los 10 factores del CNA?"))
117print(preguntar("¿Qué establece el Decreto 1330 de 2019?"))| Modelo | Descripción |
|---|---|
raulgdp/gpt-acredita-350m | GPT desde cero — baseline Q&A |
raulgdp/deepseek14b-acredita | DeepSeek-R1-Distill-Qwen-14B fine-tuned |
1@misc{gutierrez2025gptacredita,
2 title = {GPT-Acredita-350M: A Causal Language Model Trained from Scratch
3 for Colombian University Accreditation Q\&A},
4 author = {Gutierrez, Raul and others},
5 year = {2025},
6 institution = {EISC, Universidad del Valle, Cali, Colombia},
7 howpublished = {\url{https://huggingface.co/raulgdp/gpt-acredita-350m}},
8 note = {ChatAcredita PRO Project}
9}