sofia-qwen2.5-7b / README.md
EstebanBarac's picture
Add real model card (mérito Well-Tuned): QLoRA details, dataset, smoke test, usage
bdcdcb9 verified
|
Raw
History Blame Contribute Delete
5.05 kB
---
base_model: Qwen/Qwen2.5-7B-Instruct
library_name: transformers
license: apache-2.0
language:
- es
tags:
- qlora
- peft
- conversational
- education
- spanish
- build-small-hackathon
pipeline_tag: text-generation
---
# Sofía — Qwen2.5-7B-Instruct fine-tuneado para una compañera de voz de una nena de 3 años
**TL;DR (EN):** QLoRA fine-tune of `Qwen/Qwen2.5-7B-Instruct` (merged, full
precision weights) that teaches the base model to consistently play
"Sofía" — a warm, short-sentence Spanish-speaking companion for a ~3
year old — to present curated content (`<contenido>`) **verbatim**
instead of paraphrasing/inventing it, and to gently refuse/redirect
unsafe topics. Built for the
[Build Small Hackathon](https://huggingface.co/build-small-hackathon)
(track *Backyard AI*, mérito *Well-Tuned*). Powers the
[`sofia-educational-companion`](https://huggingface.co/spaces/build-small-hackathon/sofia-educational-companion)
Space.
## Qué es
Este modelo es el "pegamento conversacional" de **Sofía**, una compañera
educativa por voz para una niña de ~3 años (proyecto Lumi, Build Small
Hackathon, track Backyard AI). El LLM **nunca** es la fuente de hechos:
todo el contenido (cuentos, actividades, números) vive curado en
`content/` y se le inyecta al modelo entre `<contenido>...</contenido>`.
Este fine-tune entrena **estilo y seguridad**, no conocimiento.
Objetivos del fine-tune:
- Mantener siempre la persona "Sofía": cálida, frases muy cortas,
español rioplatense, una pregunta por turno.
- Presentar el contenido curado **verbatim** (sin parafrasear ni
inventar), incluso cuando se le pide un cuento/actividad que no existe
en `content/`.
- Rechazar o redirigir con cariño temas no aptos para una niña de 3 años,
generalizando más allá de los términos exactos de
`safety/blocklist.txt` (defensa en profundidad).
## Datos de entrenamiento
`finetune/build_dataset.py` genera `finetune/dataset.jsonl`: **196
ejemplos** en formato chat (mismo `SYSTEM_PROMPT` y los mismos bloques
`<contenido>`/`<nota>` que construye `llm/engine.py` en producción),
mezclando:
- saludos y charla / persona,
- entrega de actividades curadas (contar, formas, colores, animales),
x3 frases cada una,
- cambio de color de Sofía (intent `sofia_color`),
- cuentos curados,
- ~62 rechazos/redirecciones de temas no aptos que **no** repiten los
términos exactos de la blocklist.
## Entrenamiento
QLoRA sobre `Qwen/Qwen2.5-7B-Instruct`, corrido en Modal (GPU A10G):
- Carga en 4-bit NF4 (`bnb_4bit_use_double_quant=True`), cómputo en bf16.
- LoRA `r=16`, `alpha=32`,
`target_modules=["q_proj", "k_proj", "v_proj", "o_proj"]`.
- 3 épocas, batch size 2, gradient accumulation 4, learning rate 2e-4.
- 72 steps, ~408s en A10G. Loss 2.51 → 0.14.
- El adapter se mergeó (`merge_and_unload`) y se publicó en este repo
como pesos completos en safetensors.
Código: `finetune/train_modal.py` y `finetune/merge_lora.py` en el
[repo del proyecto](https://huggingface.co/spaces/build-small-hackathon/sofia-educational-companion).
## Evaluación (smoke test)
`finetune/smoke_test_modal.py` corrió 5 turnos representativos sobre este
modelo ya mergeado: saludo, entrega de `<contenido>` de conteo, una
pregunta sobre un arma, miedo a los monstruos, y un pedido de cuento
inventado ("un dragón que come autos"). Resultado: saluda en persona,
repite el `<contenido>` **verbatim** (a diferencia de alternativas
probadas como Nemotron-mini/Nemotron-3-nano, que parafraseaban o
inventaban), rechaza el tema del arma sin engancharse, redirige el miedo
con calidez, y ante el cuento inventado dice que no lo tiene y ofrece una
alternativa curada en vez de inventar una.
## Cómo usarlo
```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
MODEL_ID = "build-small-hackathon/sofia-qwen2.5-7b"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID, torch_dtype=torch.bfloat16
).to("cuda")
# SYSTEM_PROMPT exacto y bloques <contenido>/<nota>: ver llm/engine.py
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": "Hola Sofía"},
]
text = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
inputs = tokenizer(text, return_tensors="pt").to("cuda")
output = model.generate(
**inputs, max_new_tokens=120, do_sample=True, temperature=0.6
)
```
## Limitaciones
- Entrenado para **un caso de uso muy acotado**: compañera de juego para
una niña de 3 años, en español rioplatense, con contenido inyectado
por el sistema (`<contenido>`/`<nota>`/`<contexto>`). Fuera de ese
contexto se comporta básicamente como el Qwen2.5-7B-Instruct base.
- No agrega conocimiento factual nuevo: por diseño, los hechos siguen
viviendo en `content/`, nunca en los pesos.
- Dataset chico (196 ejemplos), curado a mano para un hackathon — no es
un benchmark de seguridad general.
## Licencia
Apache 2.0, igual que el modelo base `Qwen/Qwen2.5-7B-Instruct`.