Entrenamiento LoRA con Unsloth
Entrena un LoRA en un dataset en formato de chat con Unsloth en una GPU local y exporta el resultado como GGUF. El dataset es del usuario (producirlo es específico del problema); este skill comienza desde train.jsonl y val.jsonl. Servir el modelo es un paso separado: la carpeta de ejecución que deja este skill (GGUF más run.json) es lo que toma un skill de servicio como ollama-model.
Ejecuta cada script a través del lanzador, con la herramienta Bash: ${CLAUDE_SKILL_DIR}/scripts/run <script.py> [args]. El skill permite exactamente ese comando, por lo que se ejecuta en modo automático; llamar a un script de otra manera será rechazado allí. Si un comando del lanzador es rechazado después de un nuevo mensaje del usuario, invoca este skill nuevamente. El lanzador ejecuta check_data.py con cualquier Python 3 y preflight.py, train.py y export_gguf.py con el Python del entorno Unsloth, en la carpeta padre de su carpeta --out/--run (Unsloth escribe una carpeta unsloth_compiled_cache/ en el directorio actual). Da cada ruta como una ruta absoluta: los comandos no comparten un directorio de trabajo.
Antes de empezar, averigua
- La carpeta del dataset y el conjunto de evaluación que se usará más tarde para comparar modelos: no debe ser parte del entrenamiento. Si no lo hay, propón reservar ejemplos antes del entrenamiento.
- El/los modelo(s) base, como nombres de Unsloth 4-bit (ej.
unsloth/Qwen2.5-Coder-3B-Instruct-bnb-4bit). Varios modelos base significa una carpeta de ejecución cada uno y los mismos pasos para cada uno, uno tras otro (references/base-models.md). - La máquina: el entrenamiento necesita una GPU CUDA y el Python del entorno Unsloth. Pregunta al usuario por la ruta de ese Python si
UNSLOTH_PYTHONno está definido y~/.config/llm-finetune/unsloth-pythonno existe, y escribe la ruta como la primera línea de ese archivo (con su aprobación): el lanzador lo lee desde allí. - La carpeta de ejecuciones, donde irán las carpetas de ejecución, fuera de cualquier checkout de git.
<runs>a continuación es su ruta absoluta.
Pasos
1. Verificar los datos
${CLAUDE_SKILL_DIR}/scripts/run check_data.py <data> --eval <eval.jsonl>
Debe imprimir ok. Fallará en líneas rotas, conversaciones que no terminan con una respuesta del asistente, y prompts de validación o evaluación que también están en entrenamiento, con la misma o diferente respuesta: el modelo los ha visto, por lo que miden recuerdo. La solución es sacarlos de validación o evaluación (o arreglar cómo se dividen los datos), nunca cambiar el entrenamiento para que la verificación pase. También informa cómo se usan los mensajes del sistema: ninguno, uno compartido o mixto (ver references/chat-formats.md).
2. Preflight de la máquina
${CLAUDE_SKILL_DIR}/scripts/run preflight.py --params-b <miles de millones de parámetros> --out <runs>/<run>
La memoria libre de GPU importa más que la total: juegos, un navegador con aceleración de GPU, o un modelo que un servidor local aún mantiene (ollama ps, descargar con ollama stop <model>) pueden dejar muy poca. Si preflight lista otros usuarios de GPU, informa al usuario y deja que decida, no mates procesos. Con --params-b estima la necesidad (un modelo de 3B en 4-bit alcanzó un pico de 6.6 GiB con longitud de secuencia 1024 y tamaño de lote 4, uno de 7B con 8.1 GiB) y, cuando la memoria libre es menor, imprime el par --batch-size/--grad-accum a usar en su lugar. Es una estimación de dos ejecuciones: para otros tamaños o longitudes de secuencia pasa --need-gib y observa el pico que reporte la ejecución de prueba.
Si una importación falla, el entorno está roto, consulta references/troubleshooting.md antes de reinstalar nada.
3. Ejecución de prueba
${CLAUDE_SKILL_DIR}/scripts/run train.py --model <base> --data <data> --out <runs>/<run>-smoke --max-steps 2
Lee la salida, no solo verifiques el código de salida:
- el primer ejemplo renderizado: la línea del sistema en la parte superior es lo que el modelo aprenderá a esperar,
- los tokens que reciben pérdida: solo la respuesta, no la pregunta,
- longitudes de tokens: una advertencia de truncamiento significa aumentar
--max-seq-lengtho descartar ejemplos, - el turno del sistema que un servidor debe enviar, y las advertencias al respecto. Una plantilla de pensamiento (Qwen3, Qwen3.5) pone un bloque vacío
thinking responsedelante de cada respuesta entrenada: informa al usuario de que la aplicación lo recibirá en las respuestas y debe eliminarlo.
4. Ejecución completa
${CLAUDE_SKILL_DIR}/scripts/run train.py --model <base> --data <data> --out <runs>/<run>
Se ejecuta durante un rato (minutos para unos pocos miles de ejemplos en un modelo de 3B, más para uno de 7B). Inícialo con la opción de fondo de la herramienta Bash en lugar de mantener una sesión abierta (la herramienta mantiene la salida en un archivo, ese es el registro: no agregues >, ; o && al comando, la preaprobación cubre el comando del lanzador exactamente como se muestra), y verifícalo con ${CLAUDE_SKILL_DIR}/scripts/run train_status.py <runs>/<run>: paso, pérdidas, el paso con la pérdida de validación más baja y el tiempo restante, desde el último punto de control. Después de un fallo usa --resume.
Reporta la pérdida de entrenamiento y validación y el pico de memoria de GPU. Una pérdida de validación muy por encima de la pérdida de entrenamiento significa sobreajuste: menos épocas o más datos.
5. Exportación
${CLAUDE_SKILL_DIR}/scripts/run export_gguf.py --run <runs>/<run>
Toma unos minutos para un modelo de 3B y más de diez para uno de 7B (fusionando, convirtiendo, cuantizando), que es más de lo que la herramienta Bash permite que se ejecute un comando en primer plano: inícialo en segundo plano como el entrenamiento y espera a que termine. Escribe el GGUF en <run>/gguf/ y lo registra en run.json con su tamaño y suma de verificación. Elimina el modelo fusionado de 16 bits (varios GB, --keep-merged lo conserva, y entonces el GGUF permanece en <run>/gguf_gguf/) y el Modelfile que Unsloth escribe junto al GGUF: ese usa la plantilla estándar, no el diseño que usó el entrenamiento, por lo tanto no sigas la sugerencia de Unsloth de ollama create a partir de él. Espera una advertencia [CRITICAL] sobre el convertidor de llama.cpp en cada exportación; informa al usuario de lo que significa (references/troubleshooting.md), no detiene la exportación. La carpeta de ejecución ya está lista para servir: continúa con el skill ollama-model, o pasa la sección chat de run.json a quien sea que sirva el modelo (references/run-json.md).
6. Limpiar (preguntar primero)
Una vez que el modelo esté exportado y evaluado, ofrece eliminar lo que solo se necesita para reanudar o para verificar la configuración: <run>/checkpoints/ (para --resume, varios GB para un modelo de 7B) y la carpeta <run>-smoke. Indica cuánto espacio ocupa cada uno y elimina solo lo que el usuario acepte. Conserva adapter/ y run.json: son pequeños, y son lo que necesitan una nueva exportación y las notas de versión.
Reglas
- Nunca cambies el dataset para hacer que la evaluación luzca mejor, y nunca evalúes en datos de entrenamiento.
- No instales ni actualices paquetes en el entorno Unsloth sin preguntar: su combinación torch/CUDA es frágil.
- Pregunta antes de eliminar carpetas de ejecución o puntos de control.