Formatos de dataset para afinar un modelo: chat, Alpaca, ShareGPT y cuál te toca
Los nombres de campo que espera cada entrenador, verificados contra su documentación oficial, y los detalles que rompen un archivo sin decir por qué.
Por Brayan Pedraza10 min de lectura
En corto
Casi todo el ecosistema come JSONL con una de cuatro formas: un campo text para preentrenamiento continuado, un campo messages con roles para chat (TRL, Unsloth y el afinado de OpenAI), los campos prompt y completion, o los tres campos instruction, input y output del formato Alpaca que esperan Axolotl, LLaMA-Factory y Unsloth. Elige según el entrenador que vayas a usar, no según lo que parezca más completo: un archivo con los nombres de campo equivocados falla en la validación y el mensaje rara vez dice cuál es el campo que sobra.
La tabla que resuelve el 90 % de los casos
| Forma | Campos | Para qué sirve | Quién la come |
|---|---|---|---|
| Texto | text | Seguir preentrenando con tu material | TRL |
| Conversación | messages[{role, content}] | Afinado supervisado de chat | TRL, Unsloth, OpenAI |
| Instrucción | prompt, completion | Afinado de completado | TRL |
| Alpaca | instruction, input, output | Afinado por instrucciones | Axolotl, LLaMA-Factory, Unsloth |
| ShareGPT | conversations[{from, value}] | Conjuntos públicos de chat | Muchos entrenadores |
| Preferencias | prompt, chosen, rejected | DPO y similares | TRL |
Fuente de la fila de TRL: su página de dataset formats, que los documenta como conversational y standard.
Los detalles que rompen cosas
Estos no salen en los tutoriales y cuestan una tarde cada uno.
PRMTrainer usa plurales
Donde el resto usa completion y label, PRMTrainer espera completions y labels. Un archivo válido para el resto de TRL falla aquí sin explicación clara.
El DPO de OpenAI no usa los nombres de TRL
Es el error más caro de la lista, porque parece que ya lo tienes resuelto. TRL usa prompt, chosen y rejected. OpenAI usa input —un objeto que envuelve messages—, preferred_output y non_preferred_output, y además solo admite un turno. Un exportador que asuma TRL produce archivos que no pasan la validación de OpenAI.
OpenAI admite peso por mensaje
En afinado supervisado puedes poner weight: 0 en un mensaje de asistente para que no se entrene sobre él. Útil cuando el ejemplo contiene una respuesta correcta y otra que quieres conservar como contexto pero no imitar.
LLaMA-Factory necesita una entrada extra
No basta con el JSONL: hay que registrar el conjunto en dataset_info.json con sus columns y sus tags. Si el entrenamiento arranca y no aprende nada, revisa ahí antes que en el modelo.
ShareGPT está deprecado como opción, no como formato
En Axolotl, type: sharegpt está deprecado. Hoy se declara type: chat_template con message_property_mappings. El formato de datos sigue siendo perfectamente usable; lo que cambió es cómo se le dice al entrenador que lo interprete.
Anthropic no tiene formato propio documentado
Que hayamos podido verificar, no hay un formato público de afinado de Anthropic. El único oficial legible es el de AWS Bedrock para Claude 3 Haiku: {"system": "...", "messages": [...]}, con un mínimo de 32 registros.
Cuál elegir, en tres preguntas
¿Quieres enseñarle conocimiento nuevo? Entonces probablemente no quieras afinar. El afinado enseña forma: tono, estructura, formato de salida, vocabulario del dominio. Para hechos que cambian, un RAG es más barato, más actualizable y más auditable. Si igual vas a afinar, usa text para preentrenamiento continuado.
¿Quieres que responda como tú responderías? Formato conversación (messages). Es el más portable: lo entienden TRL, Unsloth y el afinado de OpenAI con el mismo archivo.
¿Vas a usar Axolotl, LLaMA-Factory o Unsloth con recetas de la comunidad? Alpaca, porque es lo que esperan sus configuraciones de ejemplo y te ahorra traducir.
Para RAG, ninguno de los anteriores
Si el destino no es un entrenador sino una base vectorial, los formatos son otros:
| Destino | Forma |
|---|---|
| LangChain | Document con page_content y metadata |
| LlamaIndex | TextNode con id_, text y metadata |
| Pinecone, Qdrant, pgvector, Chroma | id, texto y metadatos |
Un detalle que ahorra dolores: que el id sea estable y derivado del contenido. Así, reindexar actualiza el nodo en vez de duplicarlo, y puedes regenerar el índice sin limpiarlo antes.
Lo que se puede generar sin llamar a un modelo
Hay un formato más que casi nadie produce desde documentos y que no necesita un modelo: los pares de recompensa verificable para aprendizaje por refuerzo.
DeepSeek-R1 (arXiv:2501.12948, §2.2.2) explica por qué importa:
«for math problems with deterministic results, the model is required to provide the final answer in a specified format […] enabling reliable rule-based verification of correctness […] We do not apply the outcome or process neural reward model […] because we find that the neural reward model may suffer from reward hacking.»
El conjunto de referencia de AI2 para esto tiene messages, ground_truth y dataset. Y GRPOTrainer solo exige la columna prompt: cualquier columna extra llega a la función de recompensa como argumento con nombre.
Conclusión práctica: un dataset de RLVR es JSONL con prompt y ground_truth, y una tabla de un PDF ya es un conjunto de hechos con respuesta única. «¿Cuánto costó el examen de laboratorio?» tiene una sola respuesta, está impresa en la página, y comprobarla es comparar dos cadenas.
Dos reglas de calidad que hay que aplicar al generarlos, o el dataset castiga al modelo por acertar:
- Si una clave de fila se repite, esa pregunta no se emite: tendría dos respuestas.
- Si hay empate en el máximo o el mínimo de una columna, tampoco.
Cómo exportarlo
En el navegador: PDF a datos de IA tiene los ocho formatos en un desplegable y te enseña las primeras líneas antes de descargar.
En terminal:
npx sirdas dataset docs/*.pdf --format chat --split --hf -d dataset/
npx sirdas dataset docs/*.pdf --format alpaca -d ds/
npx sirdas rl facturas/*.pdf --lang es -o rl.jsonl
npx sirdas rl --reward-fn > reward.py
Con --hf salen train.jsonl, validation.jsonl, test.jsonl y la tarjeta de Hugging Face. Con --reward-fn, la función de recompensa en Python lista para pegar en GRPOTrainer, con el mismo criterio de comparación que se usó al generar los pares.