Ir al contenido

Configuración y rutas del entrenamiento de modelos

Todas las claves del bloque model_training, cómo se encolan, puntúan y almacenan las ejecuciones, y las rutas de administrador y de agente, con soluciones a los errores frecuentes.

Novedad de la v2.14.0

Esta página es la referencia del bloque model_training de una configuración de Potato y de lo que ocurre con una ejecución después de iniciarla. Está escrita para quien dirige un estudio y quiere limitar las ejecuciones, enviarlas a otra máquina, mostrar a los anotadores las predicciones de un modelo o iniciar el entrenamiento desde un script. Cada clave, valor predeterminado, ruta y mensaje de abajo se comprobó con el código de Potato. Para una primera ejecución, empieza por Entrena tu primer modelo. Los entrenadores y sus parámetros están listados en Entrenadores.

Una configuración completa

La configuración de abajo entrena un clasificador de sentimiento sobre reseñas de productos. auto_retrain vuelve a ajustar sklearn-text tras cada 25 anotaciones nuevas. Con las características TF-IDF predeterminadas, sklearn-text entrena en la CPU y no necesita nada más allá de una instalación básica de Potato. Las ejecuciones automáticas frecuentes cuestan por tanto poco. La escritura de vuelta muestra a los anotadores toda predicción con una confianza de al menos 0,8. Con include_unlabeled, una ejecución también predice sobre las reseñas que nadie ha etiquetado todavía. Los valores predeterminados de hf-text-classification y el backend gpu-server atienden las ejecuciones que se inician a mano desde la página Training:

yaml
annotation_task_name: "Review sentiment with model training"
task_dir: "."
data_files:
  - "data/reviews.json"
item_properties:
  id_key: "id"
  text_key: "text"
output_annotation_dir: "annotation_output"
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels: ["positive", "negative"]
 
model_training:
  enabled: true
  split_seed: 0
  splits: {train: 0.7, val: 0.15, test: 0.15}
  aggregation: consensus
  retain_runs: 5
  queue_max: 10
  max_wall_seconds: 3600
  max_ram_mb: 8192
  num_threads: 4
  trainer_params:
    sklearn-text:
      classifier: sklearn.linear_model.LogisticRegression
      classifier_kwargs: {max_iter: 1000}
    hf-text-classification:
      model_name: answerdotai/ModernBERT-base
      epochs: 4
      lora: true
  auto_retrain:
    enabled: true
    trainer: sklearn-text
    schemas: [sentiment]
    min_interval_s: 600
    update_frequency: 25
  writeback:
    schemas: [sentiment]
    min_confidence: 0.8
    include_unlabeled: true
  backends:
    gpu-server:
      type: ssh
      host: gpu-server
      python: /opt/conda/bin/python3
      gpus: auto
      min_free_gpu_mb: 4000

Mantén fijo split_seed durante toda la vida del estudio. Una semilla nueva reasigna todos los ítems, de modo que los ítems que estaban reservados acaban en el entrenamiento y las puntuaciones posteriores dejan de ser comparables con las anteriores. El umbral min_confidence de 0,8 es un punto de partida, y el umbral adecuado depende de la primera puntuación sobre ítems reservados. Activa include_unlabeled cuando esa puntuación respalde mostrar preetiquetas, porque las preetiquetas anclan a los anotadores a la respuesta del modelo.

Claves de model_training

Todas las claves van bajo model_training:

ClavePredeterminadoSignificado
enabledfalseRegistra la página Training, las rutas bajo /admin/training y las rutas de agente bajo /api/training. Sin enabled: true las rutas no existen.
retain_runs5Ejecuciones terminadas que se conservan en el registro de ejecuciones. Una ejecución más antigua sale del registro salvo que sus predicciones sigan almacenadas. Los directorios de las ejecuciones permanecen en disco.
grace_seconds20Segundos que tiene una ejecución cancelada para salir antes de que Potato mate el proceso. 0 o más, y se envía con el trabajo a los backends de tipo ssh, slurm y agent.
queue_max10Ejecuciones que pueden esperar detrás de la ejecución en curso.
split_seed0Semilla para asignar los ítems a las particiones train, val y test.
splits{train: 0.7, val: 0.15, test: 0.15}Fracciones de las particiones, normalizadas para que sumen 1. Los nombres son train, val y test, y train es obligatorio.
aggregationconsensusCómo las etiquetas de varios anotadores sobre un ítem se convierten en una sola. consensus ajusta el modelo de Dawid-Skene cuando el estudio tiene más de un anotador y recurre al voto mayoritario si el ajuste falla. majority toma el voto mayoritario.
max_wall_secondssin fijarLímite de tiempo de una ejecución. Potato comprueba una ejecución local cada vez que esta informa de un evento, y una ejecución por ssh o por agente cada segundo.
max_ram_mbsin fijarLímite de espacio de direcciones del proceso de entrenamiento, fijado con setrlimit. En una plataforma sin ese límite, la ejecución registra un aviso y continúa.
deviceautoauto, cpu, cuda, cuda:N o mps. auto elige CUDA, luego Metal de Apple y luego la CPU.
num_threadssin fijarFija OMP_NUM_THREADS, MKL_NUM_THREADS y OPENBLAS_NUM_THREADS para la ejecución, salvo que el entorno ya fije esas variables.
auto_retraindesactivadoReentrenamiento a medida que llegan anotaciones. Consulta auto_retrain.
writebackningunoPublicación de predicciones como preetiquetas. Consulta writeback.
backendlocalEl backend de las ejecuciones que no nombran otro.
backendsningunoBackends ssh, slurm y agent con nombre. Consulta Backends.
max_predictions_mb512El predictions.jsonl más grande que puede subir un agente remoto.
trainer_paramsningunoValores predeterminados de parámetros, indexados por nombre de entrenador.
tilingenabled: autoCorte de imágenes grandes en teselas para los entrenadores de detección y segmentación. Consulta tiling.

Los params propios de una ejecución sustituyen a trainer_params, que sustituyen a los valores predeterminados del entrenador. Un nombre de parámetro que el entrenador no admite se rechaza al arrancar el servidor cuando el nombre está bajo trainer_params, y en caso contrario al iniciar la ejecución. Entrenadores da el orden con un ejemplo.

auto_retrain

El reentrenamiento automático busca una ejecución nueva tras cada guardado de anotación:

ClavePredeterminadoSignificado
enabledfalseActiva la comprobación.
trainerningunoNombre del entrenador. Obligatorio.
schemasningunoEsquemas que entrenar. Obligatorio.
min_interval_s600Segundos desde que terminó la última ejecución antes de que empiece otra.
update_frequency25Anotaciones nuevas desde la última ejecución automática antes de que empiece otra.
params{}Parámetros del entrenador, como en los params de una ejecución por API.
backendmodel_training.backendBackend de las ejecuciones automáticas.
accept_licencefalseConfirma la licencia de un entrenador que pide confirmación (ultralytics-detect, ultralytics-segment, layoutlmv3). Sin la confirmación, se omiten las ejecuciones automáticas de esos entrenadores.

Cuando una comprobación decide no lanzar una ejecución, el motivo aparece en el campo skip_reason de GET /admin/training/api/status, por ejemplo «waiting for 3 more annotation(s)» o «a run is already in progress». Las ejecuciones automáticas nunca entran en la cola de ejecuciones. La siguiente anotación guardada después de que la cola se vacíe vuelve a comprobar, con más anotaciones con las que entrenar. Potato mantiene los recuentos de anotaciones en memoria, así que tras un reinicio un proyecto que ya ha entrenado cuenta las anotaciones nuevas desde el reinicio.

writeback

La escritura de vuelta decide qué predicciones ven los anotadores:

ClavePredeterminadoSignificado
schemas[]Esquemas cuyas predicciones ven los anotadores. Una lista vacía no muestra ninguna.
min_confidence0.0Las predicciones por debajo del umbral se guardan y no se muestran. Una predicción sin confianza pasa.
fieldpredictionsCampo del ítem en el que se escriben las preetiquetas.
include_unlabeledfalsePredice también sobre ítems que nadie ha etiquetado y preetiqueta esos ítems. Sin include_unlabeled, una ejecución predice solo sobre los ítems val y test de la propia ejecución.

tiling

Los entrenadores de detección y segmentación redimensionan cada imagen a unos pocos cientos de píxeles. A ese tamaño, los objetos de una imagen de portaobjetos completo o de una escena de satélite se pierden. Para un esquema image_annotation, microscopy o geo_annotation, Potato corta por eso cada imagen grande en teselas al construir los datos de entrenamiento de la ejecución. La partición de una imagen se decide antes de cortarla, así que las teselas de un mismo portaobjetos nunca caen en dos particiones. Las predicciones se proyectan de nuevo sobre la imagen completa, y las puntuaciones sobre ítems reservados se calculan sobre imágenes completas. El tutorial de visión cubre en la práctica los portaobjetos y los mapas.

ClavePredeterminadoSignificado
enabledautoauto tesela los formatos de portaobjetos (.svs, .ndpi, .mrxs, .scn y otros) y las imágenes cuyo lado mayor mide al menos auto_min_side. true tesela todas las imágenes, y false ninguna.
auto_min_side4096Longitud del lado mayor, en píxeles, a partir de la cual auto empieza a teselar una imagen.
tile_size1024Lado de una tesela, en los píxeles que ve el entrenador.
overlap128Píxeles que comparten teselas vecinas, como máximo la mitad de tile_size. Mantén el solapamiento al menos tan grande como los objetos, o un objeto grande se encuentra en pedazos.
downsample1Píxeles de resolución completa por píxel de tesela.
mppningunoMicras por píxel de tesela. Sustituye a downsample en un portaobjetos que registra su resolución.
background0.25Teselas vacías muestreadas por cada tesela con un objeto. Fija background: 0 para portaobjetos anotados solo en parte.
max_predict_tiles2000Máximo de teselas predichas por imagen. Se conservan las teselas con más tejido.
min_visible0.4Proporción de un objeto que debe quedar dentro de una tesela para que el objeto entrene allí.
tissue_threshold0.05Proporción de una tesela de portaobjetos que debe ser tejido para que el modelo prediga sobre la tesela.

Los portaobjetos se leen con openslide, que instala pip install "potato-annotation[wsi]", en la máquina que construye los datos de entrenamiento. Un backend remoto descarga las teselas y nunca el portaobjetos.

La cola de ejecuciones

Se ejecuta una sola ejecución a la vez. Una ejecución iniciada desde la página Training o desde la API mientras otra está en curso espera en lugar de ser rechazada. La solicitud de inicio devuelve 202 con queued: true y la position de la ejecución, y la tabla de ejecuciones muestra la ejecución como waiting #N con un botón Cancel run. Cuando termina la ejecución en curso, empieza la ejecución en espera más antigua.

Las ejecuciones en espera son registros del registro de ejecuciones, así que la cola sobrevive a un reinicio, y la primera ejecución en espera empieza cuando el servidor vuelve. Una ejecución que el servidor anterior tenía a medias se marca como interrupted en ese mismo momento. Los datos de entrenamiento de una ejecución en espera se construyen cuando la ejecución empieza, de modo que la ejecución entrena con las anotaciones presentes en ese momento. Un inicio que sería rechazado, como un inicio que nombra un esquema desconocido, se rechaza de inmediato y no cuando llega el turno de la ejecución. Una ejecución cuyo esquema o entrenador salió de la configuración mientras esperaba falla con invalid_when_dequeued, y empieza la siguiente ejecución.

Envía "queue": false en el cuerpo de la solicitud para recibir 409 en lugar de un lugar en la cola. Con queue_max ejecuciones ya en espera, un inicio nuevo recibe 429. GET /admin/training/api/status lista las ejecuciones en espera por orden bajo queue.

Comprobaciones antes de una ejecución

potato validate informa a la vez de todos los problemas del bloque model_training, y el servidor se niega a arrancar ante los mismos problemas:

bash
potato validate config.yaml --strict

Las comprobaciones cubren estos casos:

  • splits con un nombre distinto de train, val y test, una fracción menor que 0 o que no es un número, fracciones que suman 0 o ausencia de train.
  • Una clave que writeback o auto_retrain no tiene, una entrada de writeback.schemas que no es un esquema o un min_confidence fuera del rango de 0 a 1. accept_license se informa como una errata de accept_licence.
  • Un bloque pre_annotation activado cuyo field difiere de writeback.field. Bajo un bloque así no se mostraría ninguna preetiqueta de entrenamiento.
  • Con auto_retrain.enabled, un entrenador o un esquema que no existe, un esquema que el entrenador no puede aprender, parámetros que el entrenador no admite o de tipo erróneo, un backend que falta en backends o decision-calibrate en un backend distinto de local.
  • Un parámetro bajo trainer_params que el entrenador no admite o de tipo erróneo. Dentro de dp, la comprobación abarca también cada clave y el intervalo de la clave.
  • Un grace_seconds inferior a 0 o que no sea un número, o un retain_runs o split_seed inferior a 0 o que no sea un entero.
  • Bajo backends, un type ausente o desconocido, una clave que el tipo no tiene, un backend ssh sin host, un valor de gpus distinto de auto, none o índices de GPU, un backend remoto llamado local o un model_training.backend que no está definido.

potato training check prueba un backend antes de que una ejecución lo use. Para local, el comando imprime el dispositivo que usaría una ejecución, por ejemplo local: this machine, Apple Metal (mps) en un Mac con Apple silicon. Para un backend ssh, el comando informa de la versión de Python, de cada GPU con su memoria libre, de la GPU que recibiría una ejecución y de los paquetes de entrenamiento que le faltan al intérprete remoto. El botón Check de la página Training ejecuta la misma prueba, y --json imprime el informe como JSON:

bash
potato training check local config.yaml
potato training check gpu-server config.yaml

Una ejecución iniciada desde la página Training o desde la API se vuelve a comprobar cuando la ejecución empieza. Los códigos de estado están listados en Rutas.

Backends

Una ejecución corre en un backend, y el menú Runs on de la página Training lista los backends configurados. model_training.backend fija el valor predeterminado, y una ejecución por API o auto_retrain puede nombrar otro backend con backend. Potato tiene cuatro tipos de backend:

TipoDónde corre el entrenadorQuién inicia el entrenador
localEsta máquina, en un subproceso. Siempre disponible y predeterminado.Potato
sshOtra máquina a la que Potato llega por ssh, como un servidor con GPU.Potato, por ssh
slurmUn nodo de cómputo de un clúster, como trabajo por lotes.Potato, por ssh al nodo de acceso y luego sbatch
agentUna máquina a la que Potato no puede llegar, como una estación de trabajo tras NAT.Una persona, con potato training agent

Un backend ssh usa autenticación por clave con BatchMode activado, así que una petición de contraseña falla en lugar de quedarse colgada. Un backend slurm usa solo sbatch, squeue y scancel, más scontrol en los clústeres que ofrecen scontrol, y necesita un remote_dir en un almacenamiento que compartan los nodos de cómputo. Un backend agent no necesita ningún puerto de entrada, porque el agente abre todas las conexiones. El nombre local está reservado para esta máquina, y decision-calibrate se ejecuta solo en local. Entrenar en un servidor con GPU, un clúster SLURM o una máquina tras NAT recorre los tres tipos remotos con sus claves.

Puntuaciones sobre ítems reservados

Cada ejecución puntúa las propias predicciones sobre los ítems val y test frente a las etiquetas humanas resueltas. Los nombres de las métricas llevan la partición, como en val_macro_f1 o test_f1. Un ítem con etiqueta y sin predicción cuenta como error, así que omitir los ítems difíciles no puede subir la puntuación de un entrenador. <split>_coverage informa de la proporción de ítems que recibieron una predicción.

La puntuación principal aparece en la columna Held-out score de la tabla de ejecuciones, con la partición y la métrica en la ayuda emergente. La puntuación principal es la métrica principal del primer esquema sobre la primera de val y test que tenga ítems. Cuando un entrenador eligió el mejor punto de control por la puntuación de val, Potato prueba primero test, porque el entrenador ya ha visto la puntuación de val. Los entrenadores de ajuste fino que conservan la mejor época, por ejemplo hf-text-classification, torchvision-detect y llm-sft, toman la puntuación principal de test. sklearn-text, setfit, rdkit-property, los entrenadores de modelos de decisión y los puentes de inferencia no eligen nada con val, y una ejecución de uno de esos entrenadores toma la puntuación principal de val siempre que val tenga ítems. Una ejecución sin ítems val ni test se muestra como «not scored».

La métrica principal depende del tipo de anotación del esquema, como muestra la tabla de abajo para los tipos habituales:

Tipo de anotaciónMétrica principal
radio, select, likertmacro-F1 (también exactitud y error absoluto medio para etiquetas likert numéricas)
multiselectmicro-F1 (también macro-F1 y coincidencia exacta)
spanF1 sobre spans que coinciden en inicio, fin y etiqueta
textF1 de tokens (también coincidencia exacta)
pairwise en modo binaryexactitud sobre ítems que no se respondieron como empate
rankingtau de Kendall
image_annotation, microscopy, geo_annotationmAP de COCO con IoU 0,5 (map_50), registrando también map_50_95
audio_annotationF1 sobre segmentos con la misma etiqueta con IoU de 0,5 o más
speech_transcriptword_accuracy, 1 menos la tasa de error de palabras
volume_annotationmean_dice

El F1 de tokens da crédito a una respuesta que usa las palabras correctas en el orden equivocado, así que lee el F1 de tokens junto con la coincidencia exacta. La métrica principal de detección usa IoU 0,5 y no el promedio de 0,5 a 0,95, porque las cajas de dos anotadores para un mismo objeto rara vez se solapan con IoU 0,9. La tabla upstream de puntuaciones sobre ítems reservados lista las métricas de cada tipo de anotación.

Escritura de vuelta

Tras una ejecución correcta, Potato guarda las predicciones de la ejecución y escribe las que superan cuatro comprobaciones en el campo predictions de cada ítem, o en el campo que nombre writeback.field. Las comprobaciones se aplican en este orden, y el informe de escritura de vuelta de la ejecución cuenta cada omisión:

  1. Los ítems de la partición train nunca se preetiquetan. La comprobación abarca la partición train de toda ejecución que siga en el registro, y una preetiqueta que una ejecución anterior dejó en un ítem se retira cuando una ejecución posterior entrena con ese ítem.
  2. Solo se publican los esquemas de writeback.schemas. La lista está vacía de forma predeterminada, así que activar el entrenamiento no cambia nada de lo que ven los anotadores.
  3. Los pares rechazados se omiten. Un par de ítem y esquema con un veredicto reject en la revisión del modelo no vuelve a mostrarse.
  4. Se aplica el umbral de confianza. Una predicción por debajo de min_confidence se guarda y no se publica.

La escritura de vuelta nunca cambia una etiqueta humana, porque las predicciones van a los datos del ítem y las anotaciones viven en el estado de usuario de cada anotador. Una preetiqueta se muestra como una respuesta rellenada que el anotador puede editar, por ejemplo una opción como la opción seleccionada y una respuesta de texto libre en el cuadro de texto del esquema, y no hace falta ningún bloque pre_annotation. La preetiqueta se convierte en la respuesta del anotador solo cuando este la edita o pasa al siguiente ítem. Una preetiqueta que nadie ha editado ni dejado atrás nunca se convierte, por tanto, en una etiqueta de entrenamiento. Un par de anotador e ítem que ai_support.holdout coloca en el grupo de comparación sin asistencia del estudio no muestra ninguna preetiqueta, y los datos del ítem enviados para ese par omiten tanto el writeback.field como el pre_annotation.field. El informe de escritura de vuelta es el campo writeback de GET /admin/training/api/status, y el summary del informe dice por qué una ejecución no publicó nada.

Potato guarda una predicción por ítem y esquema, y la predicción de una ejecución más reciente sustituye a la de una ejecución más antigua. Cuando la predicción más reciente se guarda pero no se muestra, porque está por debajo de min_confidence, vacía o rechazada, la preetiqueta de la ejecución anterior se retira del ítem de inmediato, y el informe de escritura de vuelta cuenta el ítem en n_superseded_cleared. Las preetiquetas que vienen con los datos se dejan intactas. Al arrancar, las predicciones guardadas de los esquemas de writeback.schemas se escriben de vuelta en los datos de los ítems con las mismas cuatro comprobaciones, de modo que las preetiquetas sobreviven a un reinicio. Para retirar las preetiquetas de una ejecución, envía DELETE /admin/training/api/runs/<run_id>/predictions. La solicitud elimina las predicciones guardadas y retira las preetiquetas de los ítems.

Las correcciones y los ítems fijados siempre entrenan

Dos tipos de ítem van a la partición train de toda ejecución posterior, sea cual sea el lugar del ítem en la partición estable:

  • Ítems que un revisor corrigió. Un veredicto correct en la revisión del modelo significa que una persona arregló la respuesta del modelo. Las correcciones proceden de los ítems en los que el modelo fue peor, de modo que un ítem corregido en val o test puntuaría el modelo sobre una muestra de sus propios errores. Los veredictos accept y reject dejan un ítem donde estaba.
  • Ítems fijados. Train on these, junto a una porción de la página Catalog, fija los ítems que la porción abarca, por ejemplo la porción integrada model-found-nothing. Un ítem fijado entrena una vez que alguien lo ha etiquetado.

Una ejecución que movió ítems reservados a train registra un aviso con el recuento. La puntuación sobre ítems reservados de la ejecución se calcula entonces sin esos ítems y no es directamente comparable con la puntuación de una ejecución anterior. Los recuentos están en stats.forced_train del manifest.json de los datos de entrenamiento.

Guardar una partición como versión de un conjunto de datos

Keep this split as a dataset en la página de una ejecución guarda los ítems val, test o train de la ejecución con sus etiquetas humanas acordadas como una versión nueva de un conjunto de datos. La versión de un conjunto de datos no cambia después, de modo que modelos y prompts de LLM posteriores pueden compararse sobre exactamente esos ítems. La función necesita datasets.enabled: true. Cada versión guardada contiene una partición y empieza de cero en lugar de añadirse a la última versión del conjunto de datos. Los ítems val de la ejecución 2 añadidos a los de la ejecución 1 incluirían, de otro modo, ítems con los que entrenó la ejecución 2. Los inputs de cada ejemplo omiten el campo de preetiquetas, así que una evaluación no puede leer la respuesta del modelo.

De dónde vino una preetiqueta

GET /admin/model-review incluye provenance para cada ítem de la cola de revisión cuya preetiqueta escribió una ejecución de entrenamiento. Para cada esquema, la entrada da el id de la ejecución, el entrenador y la puntuación sobre ítems reservados de la ejecución. Las preetiquetas que vienen con los datos no tienen entrada.

Dónde se almacenan las ejecuciones

Cada ejecución tiene un directorio en <task_dir>/<output_annotation_dir>/training/runs/<run_id>/:

RutaContenido
bundle/Los datos de entrenamiento: train.jsonl, val.jsonl, test.jsonl, unlabeled.jsonl con include_unlabeled, labels.json, manifest.json y media/.
artifacts/model_card.json, predictions.jsonl y el modelo, por ejemplo model.pkl para sklearn-text o un directorio model/ para los entrenadores de transformers.
spec.jsonLo que se le pidió hacer a la ejecución.
events.jsonl, stdout.log, stderr.logLos eventos de progreso y la salida de la ejecución.
agent.logLa salida propia del agente remoto, en backends ssh.
bundle.tar.gzLos datos de entrenamiento tal como los descargó el agente, con los medios incluidos, en backends remotos.

El registro de ejecuciones vive en la base de datos del proyecto, <task_dir>/project.sqlite, y guarda las ejecuciones, la partición de cada ítem por ejecución, los ítems fijados para entrenamiento, las predicciones almacenadas, los tokens de agente y las subidas a Hugging Face Hub. retain_runs poda el registro y nunca poda una ejecución cuyas predicciones sigan almacenadas, de modo que toda preetiqueta puede rastrearse hasta la ejecución que la escribió. La poda deja los directorios de las ejecuciones en disco.

Una ejecución LoRA guarda solo el adaptador, de unos pocos a unos cientos de megabytes, y carga el modelo base por model_name cuando la ejecución predice. Un ajuste fino completo guarda el modelo entero. Fija la variable de entorno POTATO_MODEL_CACHE a un directorio, y el proceso de entrenamiento usa ese directorio para HF_HOME, TRANSFORMERS_CACHE y SENTENCE_TRANSFORMERS_HOME salvo que esas variables ya estén fijadas. En una máquina aislada de la red, coloca de antemano en ese directorio los modelos que nombran los entrenadores.

Rutas

La página Training y sus rutas JSON están bajo /admin/training y requieren acceso de administrador. Acceso de administrador significa una sesión de administrador o la cabecera X-API-Key. Las solicitudes POST y DELETE desde un navegador deben ser del mismo origen. La especificación OpenAPI de Potato marca las 26 operaciones de entrenamiento con x-potato-requires-config: model_training.enabled: true:

RutaFinalidad
GET /admin/trainingLa página Training, con el formulario de ejecución, la lista de ejecuciones y los entrenadores.
GET /admin/training/runs/<run_id>La página de una ejecución, con estado, métricas, eventos y la partición de cada ítem.
GET /admin/training/api/trainersTodos los entrenadores, con los tipos, las modalidades, la licencia y el estado de instalación de cada uno.
GET /admin/training/api/schemasLos esquemas del estudio, el tipo de cada esquema y los entrenadores que encajan con cada uno.
GET /admin/training/api/statusLa ejecución actual o la última, con estado, progreso, métricas, avisos, skip_reason, writeback y queue.
GET /admin/training/api/runsHistorial de ejecuciones. ?limit= es 50 por defecto, con un máximo de 500.
POST /admin/training/api/runsInicia una ejecución. 200 cuando la ejecución empieza, y 202 con queued: true y position cuando la ejecución espera.
GET /admin/training/api/runs/<run_id>El registro de una ejecución, más review, la precisión de las predicciones de la ejecución según los veredictos de revisión.
GET /admin/training/api/runs/<run_id>/eventsEl registro de eventos de la ejecución. ?limit= es 200 por defecto.
POST /admin/training/api/runs/<run_id>/cancelCancela la ejecución en curso o una ejecución en espera. 400 para cualquier otro id de ejecución.
DELETE /admin/training/api/runs/<run_id>/predictionsRetira las predicciones guardadas y las preetiquetas de la ejecución.
POST /admin/training/api/runs/<run_id>/push-to-hubPublica el modelo de la ejecución en Hugging Face Hub. Consulta Publicar en Hugging Face Hub.
POST /admin/training/api/runs/<run_id>/pin-splitGuarda una partición como versión de un conjunto de datos, con el cuerpo {"dataset": name, "split": "val"}.
GET /admin/training/api/backendsLos backends configurados.
POST /admin/training/api/backends/<name>/checkPrueba un backend, como hace potato training check.
GET /admin/training/api/pinnedÍtems fijados, agrupados por motivo.
POST /admin/training/api/pinnedFija ítems a train, con {"slice": name} o {"instance_ids": [...]}.
DELETE /admin/training/api/pinnedDesfija los instance_ids listados, o todos los ítems fijados cuando el cuerpo no lista ninguno.

Una solicitud de ejecución admite trainer, schemas (una lista o un nombre), params, backend, accept_licence y queue. Cada entrenador ajusta solo el primer esquema nombrado. La solicitud de abajo inicia una ejecución de sklearn-text sobre el esquema sentiment del ejemplo:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "sklearn-text", "schemas": ["sentiment"]}'

Un inicio rechazado da el motivo en error:

EstadoCuándo
400Falta el entrenador o el esquema en el cuerpo, un entrenador o esquema desconocido, un esquema que el entrenador no puede aprender, un entrenador que el proyecto no puede ejecutar, o un entrenador cuya licencia necesita confirmación, con needs_licence_ack: true, hasta que la solicitud fije accept_licence: true
409Un parámetro que el entrenador no admite o de tipo o rango erróneo, un backend desconocido, decision-calibrate en un backend distinto de local, o una ejecución ya en curso con "queue": false
429Ya hay queue_max ejecuciones en espera

Protocolo del agente

model_training.enabled registra también las rutas a las que llama un agente de entrenamiento, bajo /api/training. Un agente envía su token como Authorization: Bearer <token>, y un token ausente o no válido recibe 401. Registrar un backend requiere en cambio la clave de API de administrador. potato/training/protocol.py describe el protocolo para quien escriba un agente nuevo, y potato/training/agent.py es la implementación de referencia:

RutaFinalidad
POST /api/training/backends/registerEmite un token de agente para un nombre de backend, con X-API-Key. potato training register llama a esta ruta.
POST /api/training/backends/<name>/heartbeatUn agente inactivo informa de que está vivo. 403 para un token emitido para otro backend.
GET /api/training/jobs/next?wait=30Sondeo largo. 200 con un trabajo, o 204 cuando no llega ningún trabajo en wait segundos.
GET /api/training/jobs/<run_id>El trabajo, la especificación del trabajo y si el trabajo se canceló.
GET /api/training/jobs/<run_id>/bundleLos datos de entrenamiento como tar.gz, con los medios incluidos. La ruta responde a solicitudes Range, de modo que un agente reanuda una descarga interrumpida, hasta cinco intentos. 410 cuando el paquete ya no existe.
POST /api/training/jobs/<run_id>/progressEventos de progreso. Una cancelación vuelve en la respuesta.
POST /api/training/jobs/<run_id>/predictionspredictions.jsonl. 413 por encima de max_predictions_mb.
POST /api/training/jobs/<run_id>/completeCódigo de salida y eventos finales.

QLoRA

llm-sft, llm-dpo, hf-text-classification, vlm-sft y reward-model admiten lora: {quantize: 4bit}, la configuración de QLoRA (Dettmers et al., 2023). El modelo base se carga con pesos NF4 de 4 bits y doble cuantización, y un adaptador LoRA se entrena encima en bf16 donde la GPU admite bf16. quantize: 8bit es la opción intermedia, y las predicciones cargan el modelo base del mismo modo.

yaml
model_training:
  trainer_params:
    llm-sft:
      model_name: Qwen/Qwen2.5-7B-Instruct
      lora: {quantize: 4bit}

En 4 bits, los pesos base ocupan una cuarta parte de la memoria que ocupan los mismos pesos en bf16, y las activaciones, el adaptador y el estado del optimizador se suman encima. Potato todavía no ha medido la memoria de una ejecución QLoRA en una GPU, así que planifica a partir de la línea «Peak GPU memory» de la propia ejecución. Toda ejecución de transformers registra esa línea al final. QLoRA necesita una GPU CUDA y una compilación de bitsandbytes para el CUDA de esa máquina. La ejecución comprueba ambas cosas antes de cargar el modelo cuantizando unos pocos números en la GPU, y cuando las dos versiones no coinciden, el error nombra ambas versiones. El tutorial de ajuste fino de LLM pone QLoRA en práctica en ejecuciones SFT y DPO.

Publicar en Hugging Face Hub

Una ejecución correcta cuyo modelo está en el servidor de Potato tiene Publish to the Hugging Face Hub en la página de la ejecución. La subida envía el modelo y un README.md con una ficha del modelo escrita a partir de la ejecución, que nombra el entrenador, el modelo base y el adaptador, los esquemas y las etiquetas, el tamaño de las particiones, la puntuación sobre ítems reservados y la partición sobre la que se midió la puntuación, y los ids de la ejecución y del paquete. La ficha de una ejecución dp incluye además una fila «Differential privacy» con el epsilon gastado frente al objetivo, el delta y la partición train que cubre la garantía. La fila omite el objetivo o el delta cuando la ejecución no registró el valor.

La subida es una lista fija de archivos y no todo el directorio artifacts/. La lista contiene los archivos de pesos, por ejemplo .safetensors, .bin, .pt y .pkl, los archivos de configuración y del tokenizador del directorio model/ guardado, model_card.json con las rutas locales sustituidas por nombres de archivo, y calibration.json. Las respuestas del modelo sobre los ítems del proyecto (predictions.jsonl, y raw_answers.jsonl para los modelos de decisión) permanecen en el servidor. También quedan fuera los puntos de control, el estado del optimizador, las copias de los datos de entrenamiento que hacen algunos entrenadores (yolo_data/, wev_data/, laya_data/) y cualquier enlace simbólico que apunte fuera de artifacts/.

El formulario protege de varias formas frente a una subida accidental o pública:

  • Escribes el nombre del repositorio dos veces, y la subida sigue adelante solo cuando los dos nombres coinciden.
  • Private viene marcado de forma predeterminada. Mientras Private está marcado, Potato no sube a un repositorio público existente, y la API responde 409.
  • El formulario nombra una variable de entorno del servidor, HF_TOKEN de forma predeterminada, que contiene un token de escritura de Hugging Face. El token en sí nunca se escribe en la página. El nombre de la variable debe contener TOKEN o empezar por HF_, y el valor debe empezar por hf_, de modo que el valor de ninguna otra variable puede llegar a Hub.
  • Cuando Hub no puede decir si el repositorio existe, no se sube nada, y un repositorio que creó la subida se elimina de nuevo si la carga falla después.
  • La licencia de la ficha del modelo es el id de licencia de Hub que des, como apache-2.0. Sin ninguno, la ficha dice que se aplica la licencia del modelo base. Un entrenador cuya licencia necesita confirmación, como ultralytics-detect (AGPL-3.0), necesita la misma confirmación para subir.
  • Un modelo que se quedó en un host remoto con fetch_artifacts: false, o entrenado en un backend agent, no puede subirse desde el servidor, y el error nombra dónde está el modelo.

Cada subida es un commit. La página de la ejecución lista cada subida con el repositorio, la visibilidad y el commit, y el registro anota quién hizo la subida. Por la API, el cuerpo de POST /admin/training/api/runs/<run_id>/push-to-hub admite repo_id, confirm_repo_id, private (true por defecto), token_env (HF_TOKEN por defecto), licence y accept_licence. La ruta devuelve 201 con el commit, 400 ante una discrepancia, una variable de token ausente, la falta de archivos del modelo o una licencia sin confirmar, y 502 cuando Hub lo rechaza.

Solución de problemas

Las entradas de abajo cubren los errores más probables en una primera configuración. La lista upstream de solución de problemas cubre controladores de GPU, compilaciones de CUDA y los mensajes propios de cada entrenador.

  • /admin/training devuelve 404. model_training.enabled no es true, y Potato registra las rutas solo cuando la clave es true.
  • "Only N items in the train split". Anota más ítems, o baja min_instances en los params de la ejecución. La partición train contiene por defecto el 70% de los ítems etiquetados.
  • "Schema 'x' has 1 distinct label(s) in the data". Un clasificador necesita al menos dos etiquetas en uso.
  • "No resolved annotations to train on". El esquema nombrado en la ejecución difiere del esquema que se está anotando, o nadie ha anotado nada todavía.
  • La ejecución no publicó preetiquetas. Lee el informe writeback de GET /admin/training/api/status. «No predictions were published: write-back is not enabled for any schema» significa que writeback.schemas está vacío, y los recuentos de omisión muestran cuántas predicciones eliminó cada comprobación.
  • <trainer> does not take <name>. Un parámetro de la ejecución o de trainer_params está mal escrito o pertenece a otro entrenador. El mensaje lista los nombres que admite el entrenador.
  • La ejecución se mató tras quedarse la máquina sin memoria. El proceso terminó con SIGKILL, normalmente por el asesino de falta de memoria. Usa un modelo más pequeño o menos ítems, o fija max_ram_mb para que la ejecución falle dentro de su propio límite.
  • "Stopped: the run took longer than model_training.max_wall_seconds". La ejecución llegó al límite de tiempo. Sube max_wall_seconds, o entrena con menos ítems.
  • "The GPU ran out of memory". Baja batch_size y sube gradient_accumulation para mantener el lote efectivo, fija lora: true o lora: {quantize: 4bit}, o para llm-sft fija gradient_checkpointing: true o elige un modelo más pequeño.
  • "ssh to host failed: Permission denied". Potato ejecuta ssh con BatchMode=yes, así que ssh <host> true debe funcionar desde la cuenta del servidor sin ninguna petición. Una clave con frase de contraseña funciona cuando ssh-agent guarda la clave.
  • Una ejecución en un backend agent sigue en cola. Ningún agente con ese nombre de backend está consultando al servidor. Inicia un agente con potato training agent --backend <name>, y comprueba el token con Check en la página Training.

Más información

Referencias