Formatos de importación
Qué formatos acepta AstrApp al importar, cómo los convierte a ChatML y cómo representar llamadas a herramientas y razonamiento en tus ejemplos.
¿Qué formato debo usar?
El entrenamiento en AstrApp es SFT (fine-tuning supervisado) y su formato es ChatML. Todo lo que importas se convierte a ChatML: las conversaciones se guardan así y el entrenamiento las lee así. Si puedes elegir, escribe tus datos en ChatML; si ya los tienes en otro formato de la tabla de abajo, impórtalos tal cual.
Para los conceptos generales (tipos de dataset, plantillas de chat, tamaño) consulta la guía técnica Datasets para fine-tuning.
ChatML
Cada ejemplo es una lista de mensajes con su rol. En un archivo JSONL va una conversación por línea.
{"messages": [{"role": "system", "content": "Eres un asistente de atención al cliente amable y profesional."}, {"role": "user", "content": "Hola, quiero saber el estado de mi pedido"}, {"role": "assistant", "content": "¡Hola! Con gusto te ayudo. ¿Me compartes tu número de pedido para revisarlo?"}]}Roles
| Rol | Para qué sirve |
|---|---|
system | La personalidad, el contexto y las reglas del asistente. Va una vez, al inicio. |
user | El mensaje del usuario o cliente: una pregunta, una instrucción o una solicitud. |
assistant | La respuesta ideal. Es lo que el modelo aprende a generar. |
tool | El resultado de una herramienta que el asistente llamó. |
En ChatML los roles no se traducen
system, user, assistant o tool. Un rol como human o gpt dentro de messages se guarda tal cual; si pasa en muchas conversaciones, la vista previa de la importación te avisa que no tienen mensajes de usuario o de asistente. Los alias (human, bot, cliente…) solo se traducen en ShareGPT, CSV, XML y TXT.Varios turnos
Alterna mensajes de user y assistant dentro del mismo arreglo, con tantos turnos como necesites.
{
"messages": [
{
"role": "system",
"content": "Eres un asistente de ventas de una concesionaria de autos."
},
{
"role": "user",
"content": "Hola, busco un auto familiar"
},
{
"role": "assistant",
"content": "¡Bienvenido! Te ayudo a encontrarlo. ¿Cuántas personas viajan normalmente y para qué lo usarías?"
},
{
"role": "user",
"content": "Somos 5, dos adultos y tres niños. Lo usaríamos para ir a la escuela y viajar los fines de semana"
},
{
"role": "assistant",
"content": "Para cinco personas con ese uso te conviene una SUV mediana: espacio para todos, cajuela para el equipaje y buen rendimiento en ciudad. ¿Quieres que agendemos una prueba de manejo?"
}
]
}Cómo puede venir un archivo JSON
- Un arreglo de conversaciones, o una sola conversación.
- Un objeto que envuelve el arreglo en
conversationso endata. - Un arreglo de mensajes sueltos (
[{ "role": …, "content": … }]): se importa como una sola conversación.
En un arreglo JSON, el primer elemento decide el formato de todo el archivo: no mezcles formatos en el mismo arreglo. En JSONL cada línea se lee por separado.
Formatos que se convierten a ChatML
El importador detecta el formato por el contenido, no por la extensión del archivo.
| Formato | Estructura | Cómo queda en ChatML |
|---|---|---|
| ChatML | { messages: [{ role, content }] } | Queda tal cual. Conserva tool_calls y name. |
| ShareGPT | { conversations: [{ from, value }] } | human → user, gpt → assistant, observation → tool, function_call → llamada a herramienta. |
| Qwen (lista de turnos) | [{ from, value }] | Igual que ShareGPT, pero cada línea es directamente la lista de turnos. |
| Alpaca | { instruction, input?, output } | instruction (más input, si hay) → user; output → assistant. |
| input / output | { input, output } | input → user; output → assistant. |
| prompt / completion | { prompt, completion } | prompt → user; completion → assistant. |
| CSV / TSV | Columnas de rol y contenido, o de usuario y asistente | Una conversación por id o por fila. Ver Importar CSV. |
| TXT de WhatsApp | Export del chat con fecha, hora y remitente | Una conversación por cada tramo del chat separado por 6 horas o más sin mensajes. |
| TXT con prefijos de rol | Líneas que empiezan con Usuario: o Asistente: | Todo el archivo queda como una conversación. |
| TXT con nombres | Un chat entre dos personas, con el nombre de quien habla al inicio de cada línea (Ana: Hola) | Todo el archivo queda como una conversación; una línea de guiones (---) separa varias. Eliges quién responde por tu negocio y los nombres no se guardan. |
| XML | <conversation> con <message role="…"> | Cada <conversation> es una conversación. |
| Parquet | Columnas de un formato JSON de esta tabla, o una columna messages | Se procesa en el servidor al importar. |
Alpaca, input/output y prompt/completion aceptan además un campo system opcional, que se convierte en el primer mensaje. En ShareGPT, un turno con un from desconocido se descarta.
Un ejemplo de cada uno. En JSONL cada línea se lee por separado, así que este archivo se importa tal cual y produce cinco conversaciones:
{"conversations": [{"from": "human", "value": "¿Cuál es el horario?"}, {"from": "gpt", "value": "De lunes a viernes, de 9 a 18 h."}]}
[{"from": "human", "value": "¿Tienen estacionamiento?"}, {"from": "gpt", "value": "Sí, gratuito para clientes."}]
{"instruction": "Clasifica el mensaje del cliente", "input": "El pedido llegó tarde y abierto.", "output": "Queja: retraso y empaque dañado."}
{"input": "¿Aceptan tarjeta?", "output": "Sí, todas las tarjetas de crédito y débito."}
{"prompt": "¿Hacen factura?", "completion": "Sí, pídela con tu RFC al pagar."}CSV y hojas de cálculo
Un CSV puede traer una fila por mensaje (columnas de rol y contenido) o una fila por conversación (columnas de usuario y asistente). Las columnas que se reconocen y los errores típicos están en Importar CSV.
Chats exportados de WhatsApp
Un export de WhatsApp se reconoce por su contenido (las líneas con fecha, hora y remitente), aunque el archivo tenga otra extensión. AstrApp descarta los avisos de multimedia omitida, de cifrado y de llamadas perdidas.
Quién queda como asistente
user y el segundo participante como assistant; si hay más participantes, también quedan como user. Si tu negocio escribió primero, los roles quedan invertidos: revísalos en la vista previa antes de importar.Llamadas a herramientas
Si tu modelo debe consultar APIs o bases de datos, incluye en los ejemplos cuándo llama a cada herramienta y cómo usa el resultado.
Con campos estructurados
El asistente lleva la llamada en tool_calls y el resultado va en un mensaje con rol tool y el name de la herramienta. Es lo que genera la Síntesis cuando le das herramientas, y el importador conserva esos campos en archivos JSON y JSONL.
{
"messages": [
{"role": "system", "content": "Eres un asistente de ventas de una concesionaria. Consulta el inventario antes de dar precios."},
{"role": "user", "content": "¿Tienen algún sedán disponible?"},
{"role": "assistant", "content": "", "tool_calls": [{"name": "buscar_vehiculos", "arguments": {"tipo_carroceria": "Sedan"}}]},
{"role": "tool", "name": "buscar_vehiculos", "content": "2 resultados: Toyota Corolla 2024, $359,900 MXN; Honda Civic 2024, $399,900 MXN"},
{"role": "assistant", "content": "Tengo dos sedanes disponibles: el Toyota Corolla 2024 en $359,900 MXN y el Honda Civic 2024 en $399,900 MXN. ¿Quieres agendar una prueba de manejo?"}
]
}Con etiquetas en el texto
También puedes escribir la llamada dentro del texto, con etiquetas <tool_call> en el mensaje del asistente y <tool_response> en el de la herramienta, como las usan los modelos Qwen.
{
"messages": [
{
"role": "system",
"content": "Eres un asistente de ventas de una concesionaria. Tienes acceso a herramientas para buscar vehículos en el inventario."
},
{
"role": "user",
"content": "¿Tienen algún sedán disponible?"
},
{
"role": "assistant",
"content": "<tool_call>\n{\"name\": \"buscar_vehiculos\", \"arguments\": {\"tipo_carroceria\": \"Sedan\"}}\n</tool_call>"
},
{
"role": "tool",
"content": "<tool_response>\n{\"total\": 2, \"vehiculos\": [{\"marca\": \"Toyota\", \"modelo\": \"Corolla\", \"anio\": 2024, \"precio\": 359900}, {\"marca\": \"Honda\", \"modelo\": \"Civic\", \"anio\": 2024, \"precio\": 399900}]}\n</tool_response>"
},
{
"role": "assistant",
"content": "Encontré 2 sedanes disponibles:\n\n1. **Toyota Corolla 2024**: $359,900 MXN\n2. **Honda Civic 2024**: $399,900 MXN\n\n¿Te doy más detalles de alguno o agendamos una prueba de manejo?"
}
]
}Reglas que el modelo va a imitar
- Un mensaje
toolpor cada llamada, en el mismo orden que las llamadas. - El asistente solo afirma datos que devolvió una herramienta: precios, existencias o fechas que ningún resultado trae no deben aparecer en su respuesta.
- Los resultados pueden ser simulados: no necesitas conectar herramientas reales para crear el dataset.
Razonamiento con <think>
Puedes enseñar al modelo a razonar antes de responder: el razonamiento va al inicio del mensaje del asistente, entre etiquetas <think>.
{
"messages": [
{
"role": "system",
"content": "Eres el asistente de una tienda en línea. Envío estándar (3 a 5 días): $99 MXN. Express (1 a 2 días): $199 MXN. El envío estándar es gratis en pedidos desde $999 MXN."
},
{
"role": "user",
"content": "Mi carrito suma $850, ¿cuánto pago de envío a Guadalajara?"
},
{
"role": "assistant",
"content": "<think>\nEl carrito suma $850, menos de $999, así que no aplica el envío gratis. Opciones: estándar $99 o express $199.\n</think>\n\nTu carrito suma $850, así que el envío todavía tiene costo:\n\n- **Estándar (3 a 5 días):** $99 MXN\n- **Express (1 a 2 días):** $199 MXN\n\nSi agregas $149 más, el envío estándar es gratis."
}
]
}Úsalo cuando
- La respuesta requiere cálculos o lógica.
- Hay decisiones condicionales (si X, entonces Y).
- El modelo debe decidir qué herramienta usar.
- Hay que sopesar varios factores antes de responder.
Evítalo cuando
- Las respuestas son simples y directas (saludos, preguntas frecuentes).
- La velocidad de respuesta es la prioridad: razonar alarga cada respuesta.
- La conversación es puramente informativa.
<think>: se entrena como parte de la respuesta, y tu modelo lo va a generar. Si no quieres mostrarle el razonamiento al usuario final, quítalo en la aplicación que presenta la respuesta.Harmony y el formato de salida
En Conversaciones › Síntesis eliges un Formato de salida (ChatML, Alpaca, ShareGPT, Harmony o Qwen), y en Datasets › Importar datos un Formato de exportación (ChatML, Alpaca, ShareGPT o Qwen). Esa elección queda registrada en el dataset, pero no cambia cómo se guardan las conversaciones: AstrApp las guarda en ChatML, Datasets › Exportar las descarga en JSONL con messages y el entrenamiento las lee en ChatML.
El importador no lee archivos Harmony
system aparte y los turnos en conversations con role y content no produce ninguna conversación. Pásalo a ChatML antes de importarlo: pon el system como primer mensaje de messages.¿No estás seguro del formato?
Empieza con ChatML para tu primer fine-tuning. Agrega herramientas o razonamiento cuando tengas un modelo base que funcione bien. Las opciones para generarlos están en Configuración avanzada.