
En testet gjennomgang for finjustering av NVIDIA GR00T N1.7 på et SO-100 LeRobot datasett: ekte flagg, modality.json, v2.1-kravet, hva en kjøring koster, og fellene.
NVIDIA leverer et finjusteringseksempel for akkurat den armen du sannsynligvis eier. Inne i Isaac-GR00T-arkivet finnes det en mappe kalt demo_data/cube_to_bowl_5: fem episoder, 4 148 bilder ved 30 fps, allerede skrevet som LeRobot v2.1, med en matchende modalitetskonfigurasjon under examples/SO100/. Dens meta/info.json rapporterer robot_type: so101_follower, som i LeRobot er den samme konfigurasjonsklassen som so100_follower. Det er genuint nyttig, fordi det betyr at referansebanen for GR00T N1.7 på en seks-frihetsgrad hobbyarm vedlikeholdes av personene som skrev modellen. Det er ikke en nedskalert humanoid demo, det er den samme armen.
Den dårlige nyheten er avstanden mellom I recorded 60 episodes og the arm does the task. Det er omtrent seks steder hvor denne pipelinen feiler stille i stedet for høyt, og fire av dem ligger i filer de fleste aldri åpner: meta/modality.json, Python-datakonfigurasjonen, meta/relative_stats.json, og datasettets egen versjonsstreng. Denne guiden går gjennom den manuelle ruten fra start til slutt med de virkelige kommandoene, og viser deretter den samme jobben som et skjema på AY-Robots. Alt nedenfor ble sjekket mot Isaac-GR00T main-grenen per 20. august 2026 (n1.7-release-linjen) og lerobot 0.6.1, publisert til PyPI 3. august 2026. Oppstrøms beveger seg raskt, og der et flagg ble omdøpt, sier denne artikkelen det.
Hva du trenger å vite før du starter
- •GR00T N1.7 finjustering krever 40 GB eller mer VRAM. NVIDIA anbefaler H100- eller L40-noder. Et 24 GB RTX 4090 vil ikke gjøre denne jobben, selv om det vil trene SmolVLA og ACT.
- •Datasettet må være LeRobot v2 (v2.0 eller v2.1) pluss en GR00T-spesifikk meta/modality.json. Et LeRobot v3.0-datasett lastes ikke inn og må konverteres ned.
- •Inngangspunktet er gr00t/experiment/launch_finetune.py, en tyro CLI. Den har ingen --seed-flagg, så kjøringer er ikke bit-for-bit reproduserbare.
- •For en tilpasset arm er embodiment-taggen NEW_EMBODIMENT, og den taggen gjør --modality-config-path obligatorisk.
- •Den leverte SO-100-oppskriften forutsier armledd som RELATIVE deltaer og griperen som et ABSOLUTT mål. Å få den sammenkoblingen baklengs er en stille feil, ikke en feilmelding.
- •På AY-Robots er den samme jobben et skjema: 20000 trinn, batch 32, læringsrate 1e-4, omtrent 4 til 12 USD på A100 80 GB eller H100-nivået.
Hva GR00T N1.7 faktisk er
GR00T N1.7 er en syn-språk-handlingsmodell med dobbelt-systemoppsettet beskrevet i det originale GR00T N1-dokumentet: en syn-språk-modul som leser kameraene og instruksjonen, og en diffusjonstransformator som omdanner dette til en del kontinuerlige motorkommandoer. N1.7 erstattet den første halvdelen. Eagle-ryggraden fra N1.6 er borte, byttet ut med nvidia/Cosmos-Reason2-2B på en Qwen3-VL-arkitektur, og modellen ble forhåndstrent på omtrent 20 000 timer med egosentrisk menneskevideo i tillegg til robotdataene. NVIDIAs egen rapport angir tallet til 20 854 timer og rapporterer at å gå fra 1k til 20k timer mer enn dobler gjennomsnittlig oppgavefullføring.
Den andre halvdelen endret seg også, på måter som er viktige for din kjøring. Handlingshodet falt fra 32 diffusjonslag til 16, den predikerte handlingsbiten vokste fra 16 trinn til 40, og maksimal tilstands- og handlingsbredde gikk fra 29 til 132. Disse tre tallene kommer fra endringsloggen i depotets README; NVIDIAs egen lanseringspost beskriver fortsatt System 1 som en 32-lags DiT, så der de to er uenige, stol på depotet du er i ferd med å klone. Handlinger uttrykkes som standard i et relativt end-effektor-rom, deltaer fra den nåværende posituren snarere enn absolutte mål, noe som er det som lar manipulasjonsprioriteringer lært fra menneskevideo overføres til robotkontroll i det hele tatt. Selve hodet er en strømningsmatchende diffusjonstransformator, samme familie som Pi0.5, men med en annen ryggrad foran den. Hvis du fortsatt er på forrige generasjon, dekker N1.7 mot N1.5 om oppgraderingen rettferdiggjør å gjøre om pipelinen din.
| Egenskap | Verdi | Hvor det kommer fra |
|---|---|---|
| Parametere | 3,000,000,000 | Hugging Face model card |
| Syn-språk-ryggrad | nvidia/Cosmos-Reason2-2B (Qwen3-VL), gated on Hugging Face | repo README |
| Handlingshode | Strømningsmatchende diffusjonstransformator, 16 lag (N1.6 hadde 32) | repo README |
| Predikert handlingshorisont | 40 trinn for basis-sjekkpunktet (N1.6 hadde 16) | getting_started/policy.md and repo README |
| Maksimal tilstands- og handlingsbredde | 132 (N1.6 hadde 29) | repo README |
| Kodelisens | Apache 2.0 | Isaac-GR00T repository |
| Vektlisens | NVIDIA Open Model License Agreement | model card |
| Latens, H100 80 GB, PyTorch eager, 4 denoising-trinn, 1 kamera | 85.8 ms ende til ende, 11.7 Hz | model card timing table |
| Samme maskinvare, TensorRT full pipeline | 27.9 ms ende til ende, 35.9 Hz | model card timing table |
| Latens AY-Robots oppgir for sin servert GR00T N1.7 | 152 ms per handlingstrinn | AY-Robots policy catalog |
De siste tre radene forklarer det meste av skuffelsen folk rapporterer. Overskriftens 27.9 ms er en TensorRT-motor på en H100 med ett kamera og fire denoising-trinn. Ren PyTorch på samme kort er 85.8 ms, og modellkortet angir gapet til 3.08x. Ingen av tallene inkluderer et serving-lag, et andre kamera eller et nettverkshopp. De 152 ms per handlingstrinn som AY-Robots oppgir for sin servert GR00T N1.7 er tallet med serving i loopen, og en offentlig-internett rundtur kommer i tillegg til det. Mer om dette på slutten. For tallene ved siden av andre modeller, legger GR00T N1.7 mot Pi0.5 og GR00T N1.7 mot SmolVLA dem ut side ved side.

Hva kjøringen trenger før du skriver noe
| Krav | Finjustering | Inferens |
|---|---|---|
| VRAM, NVIDIA-veiledning | 40 GB eller mer, H100 eller L40 anbefales | 16 GB eller mer, et RTX 4090 fungerer |
| Python og CUDA på dGPU | 3.12 og CUDA 12.8 | 3.12 og CUDA 12.8 |
| Videobakgrunn | torchcodec 0.8.0, kun FFmpeg 4 til 7 | samme |
| Datasettformat | LeRobot v2 pluss meta/modality.json | ikke aktuelt |
| Hugging Face-tilgang | godkjent for nvidia/Cosmos-Reason2-2B | samme |
| Andre verktøy | git-lfs og uv | uv |
| AY-Robots GPU-nivå for groot1.7-treneren | A100 80 GB eller H100 80 GB | pod klargjøres automatisk |
Hvert GR00T-sjekkpunkt, inkludert basis nvidia/GR00T-N1.7-3B, laster nvidia/Cosmos-Reason2-2B ved første bruk, og dette depotet er portbeskyttet. README beskriver feilen nøyaktig: modellastingen mislykkes med en GatedRepoError / 401 Client Error. Det den ikke nevner er når dette skjer, som er etter at du har leid kortet og kjøringen har startet. Be om tilgang på modellsiden, kjør deretter uv run huggingface-cli login eller eksporter HF_TOKEN før du leier noe.
Trinn 0: episodene selv
Alt nedenfor forutsetter at du allerede har spilt inn episoder. Hvis ikke, er det det virkelige første trinnet, og det er det som avgjør hvor godt resultatet kan bli, fordi imitasjonslæring ikke kan gjenopprette informasjon som ikke er i dataene. Kalibrer begge armene først, kjør deretter følgeren med en lederarm mens lerobot-record skriver parquet-filene og kamerastrømmene. Hvis kalibrering er feil, beskriver leddverdiene i datasettet ditt en litt annen robot enn den som senere vil utføre policyen, og ingen mengde trening fikser det.
lerobot-record \
--robot.type=so100_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
--teleop.type=so100_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_leader_arm \
--dataset.repo_id=${HF_USER}/cube-into-bowl \
--dataset.num_episodes=60 \
--dataset.single_task="put the cube in the yellow bowl" \
--display_data=trueLeRobots eget råd er å spille inn minst 50 episoder med omtrent 10 per objektplassering, holde kameraene faste og holde gripeatferden konsistent. Legg til variasjon senere, ikke i starten. Tommelfingerregelen verdt å huske: hvis du ikke kunne utføre oppgaven selv fra kamerabildene alene, kan heller ikke policyen det. For det armspesifikke oppsettet, SO-100 komme i gang og SO-100 LeRobot-siden dekker porter, kalibrering og kamera-indekser. På AY-Robots kan du også gjøre dette over internett fra nettleseren ved hjelp av teleoperasjon og ta opp direkte fra økten.
Trinn 1: datasettet må være LeRobot v2.1
Dette er den vanligste hindringen. LeRobots nåværende CODEBASE_VERSION på main er v3.0, så alt du tar opp i dag med en nåværende verktøykjede kommer ut som v3.0. GR00Ts laster forventer v2. Repositoriet er eksplisitt om hvorfor: mange oppstrøms datasett som DROID, LIBERO og Bridge er publisert i v2, og native støtte for begge er planlagt, men ikke levert. Så konverteringen er opp til deg, og den kjører i sitt eget virtualenv av en konkret grunn: scripts/lerobot_conversion har sitt eget pyproject som krever Python 3.10 eller 3.11 og fester lerobot til én git-commit, mens Isaac-GR00T selv krever Python 3.12. Installer konverteren fra rotmappen til repositoriet, og du får gr00t pakken i stedet, noe som er feilen README advarer om. Hvis du er ny i formatet, forklarer LeRobot-datasett ordlisteoppføringen hva som faktisk er inni et slikt.
# from the Isaac-GR00T repo root
cd scripts/lerobot_conversion
uv venv
source .venv/bin/activate
uv pip install -e . --verbose
# pulls the dataset from the Hub and writes a v2.1 copy into the default cache
python convert_v3_to_v2.py --repo-id <your-hf-user>/<your-dataset>
# or, back in the repo root, keep it next to the SO-100 example
uv run --project scripts/lerobot_conversion \
python scripts/lerobot_conversion/convert_v3_to_v2.py \
--repo-id <your-hf-user>/<your-dataset> \
--root examples/SO100/my_dataset_lerobotHvis v3.0-datasettet allerede eksisterer lokalt, bygger skriptet v2.1-layouten ved siden av det og bytter deretter: originalen flyttes til en søskenmappe med versjonen lagt til, <name>_v3.0, og den konverterte kopien tar den opprinnelige stien. (Skriptets egen docstring kaller den mappen _v30; koden legger til versjonsstrengen, så det du faktisk får er _v3.0.) Andre overraskelse: utdataene lander alltid under <root>/<repo-id>, så --root examples/SO100/my_dataset_lerobot gir deg examples/SO100/my_dataset_lerobot/<your-hf-user>/<your-dataset>, og den lengre stien er den --dataset-path ønsker senere. Når en treningsjobb avviser datasettet ditt på grunn av versjonsårsaker, lister siden om datasettet avvist som v3 de nøyaktige symptomene.
Strukturen GR00T ønsker etter konvertering er det klassiske v2-oppsettet: meta/info.json, meta/episodes.jsonl, meta/tasks.jsonl, parquet-filer under data/chunk-000/, MP4-filer under videos/chunk-000/observation.images.
Trinn 2: modality.json, de seks tallene som bestemmer alt
I et LeRobot-datasett lagres robotens tilstand og handling som flate float32-arrayer. For en SO-100 har begge formen [6]: fem armledd og en griper. Demodatasettet navngir dem shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos, gripper.pos, men disse navnene finnes i info.json og ingenting i parquet-filen sier hvilken indeks som er hvilken. meta/modality.json leverer denne tilordningen, og GR00T vil ikke trene uten den. Her er den som repositoryet leverer for SO-100, ordrett.
{
"state": {
"single_arm": {
"start": 0,
"end": 5
},
"gripper": {
"start": 5,
"end": 6
}
},
"action": {
"single_arm": {
"start": 0,
"end": 5
},
"gripper": {
"start": 5,
"end": 6
}
},
"video": {
"front": {
"original_key": "observation.images.front"
},
"wrist": {
"original_key": "observation.images.wrist"
}
},
"annotation": {
"human.task_description": {
"original_key": "task_index"
}
}
}Kopier den inn i ditt konverterte datasett på meta/modality.json og gi videonøklene nytt navn til det kameraene dine faktisk heter. Hvis du spilte inn med et enkelt overliggende kamera kalt top, da er original_key observation.images.top og det vennlige navnet er det datakonfigurasjonen din vil referere til. De to må stemme overens, og ingen av dem sjekker den andre for deg. Språkannoteringen er verre, fordi den samme nøkkelen må vises tre steder.
| Lag | Fil | SO-100-form brukt i repoet |
|---|---|---|
| Parquet-kolonne | data/chunk-*/episode_*.parquet | annotation.human.task_description |
| modality.json-nøkkel | meta/modality.json, under "annotation", uten annotation.-prefikset | human.task_description |
| modality_keys i datakonfigurasjonen | your so100_config.py | annotation.human.task_description |
Segmentene etter annotation. velges av den som har laget datasettet. SO-100 demo-data bruker annotation.human.task_description; LIBERO og SimplerEnv bruker annotation.human.action.task_description. Begge er gyldige. Hvis du kopierte en konfigurasjon fra et LIBERO-eksempel og pekte den mot ditt eget SO-100-opptak, løses språkanalen til ingenting, og modellen trener på en tom instruksjon. Tapet faller fortsatt. Policyen gjør fortsatt noe. Den ignorerer bare det du ba den om å gjøre.
Trinn 3: datakonfigurasjonen, relativ arm og absolutt griper
Modalitetskonfigurasjonen er en Python-fil snarere enn JSON, fordi den også bestemmer hvordan hver handlingsgruppe representeres. Dette er den delen av N1.7-arbeidsflyten som ikke eksisterte i samme form i N1.5, og den delen som er verdt å lese to ganger. Den leverte SO-100-konfigurasjonen forutsier de fem armleddene som RELATIVE deltaer fra gjeldende tilstand og griperen som en ABSOLUTE målposisjon, fordi et binært åpen-eller-lukket signal fungerer bedre som et mål enn som et delta.
from gr00t.configs.data.embodiment_configs import register_modality_config
from gr00t.data.embodiment_tags import EmbodimentTag
from gr00t.data.types import (
ActionConfig, ActionFormat, ActionRepresentation, ActionType, ModalityConfig,
)
so100_config = {
"video": ModalityConfig(
delta_indices=[0], # current frame only
modality_keys=["front", "wrist"], # must match modality.json
),
"state": ModalityConfig(
delta_indices=[0],
modality_keys=["single_arm", "gripper"],
),
"action": ModalityConfig(
delta_indices=list(range(0, 16)), # predict 16 future steps
modality_keys=["single_arm", "gripper"],
action_configs=[
ActionConfig(rep=ActionRepresentation.RELATIVE, # arm joints
type=ActionType.NON_EEF,
format=ActionFormat.DEFAULT),
ActionConfig(rep=ActionRepresentation.ABSOLUTE, # gripper
type=ActionType.NON_EEF,
format=ActionFormat.DEFAULT),
],
),
"language": ModalityConfig(
delta_indices=[0],
modality_keys=["annotation.human.task_description"],
),
}
register_modality_config(so100_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT)To detaljer her vil koste deg en dag hvis du ikke kjenner dem. For det første, action_configs er posisjonsbasert: dokumentasjonen krever samme lengde og samme rekkefølge som modality_keys, og de er tydelige på konsekvensen av å gjøre feil, som er at feil representasjon blir brukt uten varsel. Griperen din blir trent som et delta og armen din som et absolutt mål, og det er ingen feilmelding. For det andre, register_modality_config hevder at taggen ikke allerede er registrert, så en andre NEW_EMBODIMENT-konfigurasjon i samme Python-prosess dør med Embodiment tag ... already registered. Du kan ikke importere to av disse inn i ett skript. En tredje regel håndheves senere, ved utrulling: handlingens delta_indices må være det sammenhengende området som starter på null. Et spredt vindu som [0, 4, 8] avvises, fordi alt nedstrøms indekserer den predikerte biten lineært og ellers ville utført feil rader.
Normaliseringsstatistikk, spesielt meta/relative_stats.json, beregnes for den horisontlengden du hadde da du genererte dem. Forkort handlingshorisonten fra 16 til 8 uten å regenerere, og treningen dør med IndexError: boolean index did not match indexed array ... dimension is 8 but corresponding boolean dimension is 16. Løsningen er én kommando: python gr00t/data/stats.py --dataset-path <path> --embodiment-tag NEW_EMBODIMENT --modality-config-path examples/SO100/so100_config.py. Kjør den etter enhver endring i delta_indices.
Trinn 4: miljøet
N1.7 flyttet depotet til og Python 3.12. Den gamle conda pluss pip install -e . -stien eksisterer fortsatt i en skjult del av README, men den advarer om at GPU-avhengigheter, inkludert flash-attn og TensorRT, kan kreve manuell installasjon. Bruk uv med mindre du har en spesifikk grunn til å ikke gjøre det. Når det gjelder flash-attn, sparer én detalj forvirring: du vil se Installing flash-attn skrevet ut ved hver uv run. Den bygges ikke på nytt. uv re-validerer et URL-festet hjul som allerede er bufret, og det tar to eller tre sekunder.
- 1Installer git-lfs, deretter klon med submoduler
git-lfs er påkrevd, ikke valgfritt. Uten det vil parquet-filene i demo_data/ lastes ned som pekerstubber, og demo-kjøringen vil mislykkes på et datasett som ser ut til å være til stede i filoversikten.
bashsudo apt install git-lfs && git lfs install git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T cd Isaac-GR00T - 2Installer uv og synkroniser miljøet
Standardinstallasjonen trekker inn GPU-avhengighetene, inkludert flash-attn og TensorRT. På et ferskt A100- eller H100-bilde er dette det lengste enkelttrinnet, så gjør det før du begynner å vie oppmerksomhet til noe annet.
bashcurl -LsSf https://astral.sh/uv/install.sh | sh sudo apt-get update && sudo apt-get install -y ffmpeg uv sync --python 3.12 uv run python -c "import gr00t; print('GR00T installed successfully')" - 3Autentiser mot Hugging Face
Gjør dette før den første treningslanseringen, ikke etter at den feiler åtte minutter ut i prosessen.
bashuv run huggingface-cli login # or: export HF_TOKEN=<your_token> - 4Sanity-sjekk på de medfølgende SO-100 demo-dataene
Før du rører ditt eget opptak, kjør 2000 trinn på demo_data/cube_to_bowl_5. Det er fem episoder, det fullføres raskt, og det beviser miljøet snarere enn dataene dine. Hvis denne kjøringen mislykkes, vil ingenting du gjør med datasettet ditt hjelpe.
bashCUDA_VISIBLE_DEVICES=0 uv run python \ gr00t/experiment/launch_finetune.py \ --base-model-path nvidia/GR00T-N1.7-3B \ --dataset-path demo_data/cube_to_bowl_5 \ --embodiment-tag NEW_EMBODIMENT \ --modality-config-path examples/SO100/so100_config.py \ --num-gpus 1 \ --output-dir /tmp/test_finetune \ --max-steps 2000 \ --global-batch-size 32 \ --dataloader-num-workers 4
FFmpeg 8. torchcodec 0.8.0 støtter kun FFmpeg 4 til 7, og Ubuntu 25.10 og nyere leveres med versjon 8. Feilen er Could not load libtorchcodec, som ser ut som en ødelagt installasjon snarere enn en versjonskonflikt. Installer en eldre kjøretid, for eksempel conda install -c conda-forge 'ffmpeg<8', og legg bibliotekene på LD_LIBRARY_PATH. CUDA_HOME er udefinert. Finjustering mislykkes fullstendig. Kjør bash scripts/deployment/dgpu/install_deps.sh én gang, eller bare export CUDA_HOME=/usr/local/cuda.
Trinn 5: `fine-tune`-kommandoen og hva dens flagg egentlig er satt til som standard
Bytt ut demo-datasettet med ditt eget og legg til de innstillingene du faktisk ønsker. Nedenfor er den fullstendige formen som repositoriet bruker i sin egen `new-embodiment`-veiledning, inkludert augmentering- og sjekkpunktflaggene som det korte README-eksemplet utelater. Dette er i snever forstand: språkryggraden og den visuelle koderen forblir frosne, og det som trenes er projektoren og diffusjonsaksjonshodet.
export NUM_GPUS=1
CUDA_VISIBLE_DEVICES=0 uv run python \
gr00t/experiment/launch_finetune.py \
--base-model-path nvidia/GR00T-N1.7-3B \
--dataset-path ./my_dataset_lerobot \
--embodiment-tag NEW_EMBODIMENT \
--modality-config-path examples/SO100/so100_config.py \
--num-gpus $NUM_GPUS \
--output-dir /tmp/so100 \
--save-total-limit 5 \
--save-steps 2000 \
--max-steps 20000 \
--use-wandb \
--global-batch-size 32 \
--color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
--dataloader-num-workers 4| Flagg | Standard i FinetuneConfig | Hva det gjør |
|---|---|---|
| --global-batch-size | 64 | Total batch over alle GPU-er før gradientakkumulering. De medfølgende eksemplene bruker 32. |
| --learning-rate | 1e-4 | Samme verdi som AY-Robots sender for sin groot1.7-trener. |
| --max-steps | 10000 | Totalt antall optimaliseringstrinn. `examples/finetune.sh`-wrapperen er også satt til 10000 som standard. |
| --gradient-accumulation-steps | 1 | Multipliserer den effektive batchen. Verdier over 1 utløser en advarsel som forteller deg den akkumulerte størrelsen. |
| --save-steps and --save-total-limit | 1000 and 5 | Sjekkpunktfrekvens, og hvor mange som beholdes. Eldre slettes. |
| --weight-decay and --warmup-ratio | 1e-5 and 0.05 | Satt eksplisitt av `examples/finetune.sh` også. |
| --state-dropout-prob | 0.2 in the CLI, 0.8 in the model config | Slipper tilfeldigvis proprioceptiv tilstand under trening. Senk den hvis oppgaven din er avhengig av tilstand. |
| --tune-llm and --tune-visual | False and False | Ryggraden forblir frossen som standard. |
| --tune-projector and --tune-diffusion-model | True and True | Projektoren og diffusjonsaksjonshodet er det som faktisk trenes. |
| --use-percentiles | True | Normaliser med q01 og q99 i stedet for rå min og maks. |
| --dataloader-num-workers | 2 | Lasteren er CPU-basert av design. Eksemplene øker dette til 4. |
| --seed | does not exist | Det er ingen seed-flagg på denne CLI-en. |
Den siste raden er ikke en skrivefeil. launch_finetune.py er en tyro CLI generert fra en dataklasse, og den dataklassen har ingen seed-felt. README-filen bemerker separat 5 til 6 prosent varians mellom kjøringer forårsaket av ikke-deterministisk bildeaugmentering. To kjøringer med identiske flagg vil ikke produsere identiske sjekkpunkter, noe som betyr mye når du prøver å avgjøre om en hyperparameterendring hjalp eller om du var heldig. Til sammenligning bruker lerobots egen trener standardinnstillingen seed 1000, og LeRobot GR00T-oppskriften sender --seed=42 eksplisitt.
Finjustering kjører med eval_strategy="no", så det er ingen valideringstapskurve i det hele tatt. Du får treningstap og ingenting annet. Den nye-embodiment-guiden ber deg slå det på med --eval-strategy steps --eval-steps 500, men det flagget finnes ikke på launch_finetune.py: CLI-en genereres av tyro fra FinetuneConfig-dataklassen, og eval_strategy, eval_steps og eval_batch_size er felt i TrainingConfig i stedet. Standardverdiene der er "no", 500 og 2. For å nå dem, bruk det fullere inngangspunktet gr00t/experiment/launch_train.py, hvor det nestede flagget er --training.eval-strategy. Uansett forteller et fallende treningstap alene deg svært lite om generalisering, noe som er nøyaktig situasjonen beskrevet på tapet faller, men policyen gjør ingenting.
Hva en 20000-trinns kjøring koster
GR00T N1.7 trenger et 80 GB kort, så kostnadsspørsmålet har et snevert svar. På AY-Robots kjører groot1.7-treneren på A100 80 GB eller H100 80 GB-nivået, hvor en kjøring tar 3 til 6 timer til 1.20 til 2.00 USD per time på spotmarkedet. Det er omtrent 4 til 12 USD for standard 20000-trinns jobben. Den samme oppgaven på SmolVLA eller ACT lander på et 24 GB kort til 0.30 til 0.60 USD per time og 1 til 3 USD per kjøring. Det er den virkelige avveiningen: GR00T koster omtrent fire ganger så mye per forsøk, og du kan ikke kjøre det på 4090 under skrivebordet ditt.
| Modell | GPU-nivå | Typisk kjøretid | Typisk kostnad | Minimum episoder |
|---|---|---|---|---|
| GR00T N1.7 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| GR00T N1.5 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| Pi0.5 | A100 80 GB or H100 80 GB | 3 to 6 hours | 4 to 12 USD | 50 |
| SmolVLA | RTX 4090 or any 24 GB card | 2 to 5 hours | 1 to 3 USD | 30 |
| ACT | RTX 4090 or any 24 GB card | 2 to 5 hours | 1 to 3 USD | 50 |
Minimum 50-episode er et gulv, ikke et mål. NVIDIAs egen FAQ er mer krevende: omtrent 100 trajektorier for en enkel plukk-og-plasser-oppgave på et fast sted, 500 eller mer for komplekse eller flertrinns-scener, og 100 til 500 for finmanipulasjon. Hvis du sitter med 20 episoder, bruk ettermiddagen på å spille inn i stedet for kvelden på å finjustere. Den datainnsamlingsguiden dekker hva som skiller en nyttig episode fra en bortkastet,spill inn ditt første datasett er kortversjonen, og SO-100 datainnsamling er den armspesifikke.
Trinn 6: åpen-sløyfe evaluering før du rører armen
Ikke legg en fersk sjekkpunkt på en fysisk arm for å finne ut om treningen fungerte. Kjør den åpen-sløyfe evalueringen først. Den spiller av en innspilt episode, ber modellen om handlinger ved hvert trinn, og plotter prediksjon mot sannhet med MSE og MAE. Det koster ingenting og fanger opp kartleggingsfeilene fra trinn 2 og 3.
uv run python gr00t/eval/open_loop_eval.py \
--dataset-path ./my_dataset_lerobot \
--embodiment-tag NEW_EMBODIMENT \
--model-path /tmp/so100/checkpoint-20000 \
--traj-ids 0 \
--execution-horizon 16 \
--steps 400 \
--modality-keys single_arm gripperRepositoriet nekter bevisst å publisere en mål-MSE for egendefinerte data, og det er riktig: tallet avhenger av dine handlingsenheter, din oppgave og din datasettstørrelse, så en terskel kopiert fra en annens arm betyr ingenting. Det som er meningsfullt er trenden. Her er referansekjøringen som repositoriet dokumenterer på en enkelt H100 med demo-datasettet på fem episoder og 2000 trinn.
| Sjekkpunkt | Gjennomsnittlig MSE på traj 0 | Gjennomsnittlig MAE på traj 0 |
|---|---|---|
| 500 | 87.5 | 5.63 |
| 1000 | 25.4 | 3.30 |
| 1500 | 13.2 | 2.18 |
| 2000 | 10.0 | 1.76 |
Formen er signalet, ikke de absolutte verdiene. Feilen bør falle jevnt etter hvert som akkumuleres. Gjennomsnittlig over alle fem treningsepisodene, i stedet for kun bane 0, scoret repoets siste sjekkpunkt omtrent 7.5 MSE og 1.5 MAE, så selv referansekjøringen leses annerledes avhengig av hvilke episoder du gjennomsnittsberegner. Registrer din egen grunnlinje på den umodifiserte demo-kommandoen før du endrer noe med dine egne data: hvis du ikke kan reprodusere en kjent-god kjøring, kan du ikke skille en oppsettfeil fra et dataproblem. Repositoriet kartlegger også de vanlige symptomene til årsaker, og hver av dem er operasjonelle snarere enn en modellfeil.
| Symptom | Sannsynlig årsak |
|---|---|
| MSE flatt eller stigende over sjekkpunkter | Læringsrate for lav, eller dataen lastes ikke i det hele tatt. Sjekk --dataset-path og datalaster-arbeiderne. |
| Prediksjonskurven er flat eller konstant | modality.json-nøkler eller --modality-config-path stemmer ikke overens. Handlingsnøklene er ikke mappet. |
| MSE enorm, eller NaN-tap under trening | Normalisering av handling og tilstand. Verifiser meta/stats og at handlingsområdene er fysisk plausible. |
| Bra på traj 0, dårlig på tilbakeholdte episoder | Datamangel, ikke en feil. Fem demoepisoder kan ikke generalisere. |
Den andre ruten: lerobot-train i stedet for Isaac-GR00T
Den nåværende LeRobot-utgivelsen, 0.6.1 på PyPI siden 3. august 2026, tilbyr en annen og ganske annerledes måte å finjustere de samme basisvektene på. LeRobot eksponerer GR00T N1.7 som en policytype og trener den gjennom sitt eget lerobot-train-inngangspunkt. To ting er viktige her. LeRobot CLI er et sett med konsollskript, så alt du leser som sier python lerobot/scripts/train.py er utdatert og vil ikke kjøre. Og LeRobot fjernet GR00T N1.5-støtte fullstendig, og avviste N1.5-sjekkpunkter og -konfigurasjoner med en migreringsmerknad, så hvis du trenger N1.5 gjennom LeRobot må du låse til lerobot==0.5.1, den siste utgivelsen som støtter det, publisert 7. april 2026.
pip install "lerobot[groot]" "lerobot[training]"
hf auth login
lerobot-train \
--dataset.repo_id=$HF_USER/$DATASET_NAME \
--dataset.image_transforms.enable=true \
--policy.type=groot \
--policy.device=cuda \
--policy.base_model_path=nvidia/GR00T-N1.7-3B \
--policy.embodiment_tag=new_embodiment \
--policy.chunk_size=16 \
--policy.n_action_steps=16 \
--policy.use_relative_actions=true \
--policy.relative_exclude_joints='["gripper"]' \
--policy.use_bf16=true \
--seed=42 \
--batch_size=64 \
--steps=20000 \
--save_freq=5000 \
--output_dir=$OUTPUT_DIR| Aspekt | Isaac-GR00T launch_finetune.py | lerobot-train --policy.type=groot |
|---|---|---|
| Datasetversjon | Kun LeRobot v2, konvertering nødvendig | Native LeRobot-datasett, ingen nedgradering |
| Modalitetskartlegging | meta/modality.json pluss en Python-datakonfigurasjon | ingen modality.json; oppførsel satt av --policy.*-flagg på kommandolinjen |
| Frø | ingen frøflagg i det hele tatt | --seed, LeRobot standard 1000 |
| Relative handlinger | per-nøkkel ActionConfig i datakonfigurasjonen | --policy.use_relative_actions pluss --policy.relative_exclude_joints |
| Publiserte referanseresultater | SO-100 open-loop MSE-trend på demodata | LIBERO-suiter, 96,5 prosent gjennomsnitt over fire suiter |
| Distribusjonssti | run_gr00t_server.py pluss eval_so100.py over ZMQ | lerobot-rollout, med sanntids-chunking (queue_threshold bør forbli på eller under 5) |
- Hvert flagg er synlig og kan endres. Du kan frigjøre den visuelle koderen, flytte state_dropout_prob, eller forkorte handlingshorisonten.
- Open-loop-plottene er lokale filer. Å diff'e checkpoint-5000 mot checkpoint-20000 er en skallkommando.
- Du er ikke avhengig av at noen plattform forblir online, og sjekkpunktet ligger på disken din i et standardformat.
- Repoets benchmark-eksempler for LIBERO, SimplerEnv og DROID gir deg kjente, gode kjøringer å reprodusere før du stoler på dine egne data.
- Miljøet er mesteparten av arbeidet. FFmpeg-versjon, CUDA_HOME, git-lfs, den gatede ryggraden, torchcodec: ingen av disse er modellproblemer, og hver av dem stopper kjøringen.
- Konverteringen fra v3.0 til v2.1 krever et separat virtuelt miljø med sitt eget installasjonstrinn, og den overskriver datasettkatalogen din på stedet.
- GPU-leie faktureres når du starter feilsøking, ikke når trening starter, og ingenting stopper instansen når kjøringen er ferdig.
- Ingen frø betyr ingen bit-for-bit reproduserbarhet, i tillegg til 5 til 6 prosent variasjon fra kjøring til kjøring fra augmentering alene.
To måter å få det samme sjekkpunktet på
Du leier GPU-en og eier hvert steg. Realistisk sett tar dette en ettermiddag første gang, og tjue minutter hver gang etter det.
- Ta opp episoder med lerobot-record på SO-100. Du får et LeRobot v3.0 datasett.
- Konverter det ned til v2.1 med scripts/lerobot_conversion/convert_v3_to_v2.py i sitt eget virtuelle miljø.
- Skriv meta/modality.json og en Python modalitetskonfigurasjon, registrert under EmbodimentTag.NEW_EMBODIMENT.
- Lei et 80 GB kort, klon med submoduler, uv sync, autentiser mot Hugging Face.
- Kjør launch_finetune.py, deretter open_loop_eval.py på flere sjekkpunkter, og sammenlign MSE-trenden før du rører maskinvaren.
- Trekk sjekkpunktet av maskinen før du ødelegger instansen, og bygg deretter serveringsbanen til armen.
Kopier sjekkpunktet fra den leide instansen før du slår den av. --save-total-limit 5 betyr også at eldre sjekkpunkter slettes etter hvert som treningen skrider frem, så sjekkpunktet du ønsket ved steg 5000 eksisterer kanskje ikke lenger ved steg 20000.
Samme jobb som et skjema. Du velger modell og datasett, bakenden leier en GPU på spotmarkedet basert på nødvendig VRAM, kjører treneren og skriver sjekkpunkter til objektlagring. GR00T N1.7 på SO-100-guiden er denne nøyaktige kombinasjonen; treningsmatrisen har alle andre modell- og armparinger, inkludert GR00T N1.7 på SO-101.
| Hva groot1.7-treneren sender | Verdi |
|---|---|
| Batchstørrelse | 32 |
| Læringsrate | 1e-4 |
| Maks steg | 20000 |
| Gradientakkumulering | 1, og det trer i kraft for denne treneren |
| Ekstra innstilling eksponert i skjemaet | saveSteps |
| Grunnleggende sjekkpunkt | nvidia/GR00T-N1.7-3B |
| Akseptert datasettformat | LeRobot v2.0 eller v2.1 |
Datasettet kan komme fra en Hugging Face repo-ID, fra din egen maskin, eller fra en økt du spilte inn med skrivebordsklienten. Inferens er et separat steg: plattformen provisjonerer en pod som serverer policyen, og din lokale robotklient kommuniserer med dette endepunktet. Poder har en inaktiv vakthund og ødelegger seg selv etter en inaktiv periode, slik at en glemt nettleserfane ikke faktureres over natten. Hvis du heller ikke vil klikke, finnes de samme operasjonene på CLI-en og MCP-serveren.
GR00T N1.7 og Pi0.5 er kun skybaserte her; kun SmolVLA og ACT kjører også lokalt. V2.1-kravet forsvinner heller ikke, fordi et v3.0-datasett fortsatt må konverteres ned før GR00T-lasteren vil akseptere det. Og ingenting skriver dine modality.json-semantikker for deg: hvis kameranøklene eller språknøkkelen din er feil, er de feil på begge ruter. Se treningsdokumentasjonen for hva bakenden gjør og ikke gjør på dine vegne.

Sette sjekkpunktet tilbake på armen
Isaac-GR00T bruker en server-klient-deling over ZMQ. Policyen kjører på GPU-en, og en tynn klient på robotmaskinen sender observasjoner og mottar handlingsbiter. SO-100-eksemplet er komplett nok til å kopiere: start run_gr00t_server.py med sjekkpunktet ditt og --embodiment-tag NEW_EMBODIMENT, kjør deretter eval_so100.py på robotsiden med seriellporten, robot-ID-en, kamera-indeksene og språkinstruksjonen. Kameranavnene i den kommandoen må samsvare med de vennlige navnene fra din modality.json, ikke OS-enhetstallene.
# GPU side
uv run python gr00t/eval/run_gr00t_server.py \
--model-path /tmp/so100/checkpoint-20000 \
--embodiment-tag NEW_EMBODIMENT \
--device cuda:0 \
--host 0.0.0.0 --port 5555
# robot side, from gr00t/eval/real_robot/SO100
uv run --no-sync python eval_so100.py \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM2 \
--robot.id=orange_follower \
--robot.cameras="{ front: {type: opencv, index_or_path: 6, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
--policy_host=localhost --policy_port=5555 \
--lang_instruction="put the cube in the yellow bowl"Mens du kobler armen opp igjen: SO-100 bruker Feetech STS3215 busservoer på en 7.4 V skinne. Å mate dem med 12 V ødelegger dem, og det er en enkel feil hvis du også eier en LeKiwi, hvis base kjører på 12 V mens armen ikke gjør det. Sjekk strømforsyningen før første oppstart, ikke etter røyken. Se SO-100 maskinvaresiden og SO-100 mot LeKiwi. Hvis armen slår seg på, men ingenting beveger seg, er servoen svarer ikke stedet å starte.
Nå den ærlige delen om hvor policyen kjører, fordi trening og serving har forskjellige maskinvarehistorier. Finjustering krever 40 GB eller mer. Inferens gjør det ikke: README angir det til 16 GB eller mer og nevner RTX 4090 eksplisitt, så et kort du allerede eier kan serve et sjekkpunkt det aldri kunne ha produsert. Det som avgjør om policyen føles responsiv er ikke VRAM, det er hvor serveren befinner seg. På AY-Robots er GR00T N1.7 kun skybasert, så kontrollsløyfen betaler en offentlig internett-tur-retur i tillegg til de 152 ms per handlingstrinn, og bare SmolVLA og ACT kjører også lokalt. For langsom plukking og plassering er en ekstern pod overlevelig. For alt reaktivt er det ikke: policyen blir nølende på en måte som ser nøyaktig ut som en treningsfeil og er ikke det. ACT på 20 ms per handlingstrinn er modellen som tåler den strammeste sløyfen, SmolVLA ligger på 245 ms, og ingen mengde latensjustering kjøper tilbake en tur-retur som allerede er brukt. Kjør din første policy går gjennom serveringssiden fra ende til ende.
Hva som faktisk går galt
- GatedRepoError ved første kjøring. Du har ikke fått tilgang til nvidia/Cosmos-Reason2-2B, eller du autentiserte deg ikke. Dette skjer etter at GPU-klokken allerede har startet.
- Datasett avvist ved lasting. Nesten alltid et v3.0-datasett. Konverter det ned. Se datasett avvist som v3.
- IndexError om uoverensstemmende boolske dimensjoner. Du endret delta_indices og regenererte ikke statistikken.
- Tom for minne ved batch 32. Reduser --global-batch-size og øk --gradient-accumulation-steps, eller reduser --num-shards-per-epoch, noe konfigurasjonen eksplisitt foreslår når VRAM er begrenset. Se tom for minne under trening.
- Tapet faller, policyen gjør ingenting. Det er ingen valideringssplitt som standard, så en ren treningskurve beviser svært lite. Denne siden dekker diagnosen.
- Fungerer i ditt oppsett og ingen andre steder. Forventet med et lite datasett filmet under én lysforhold. NVIDIA anbefaler fargejitter-augmentering pluss 20 til 50 episoder under forskjellige lysforhold. Mer her.
- Griperen lukker aldri ordentlig. Sjekk at griperhandlingen er ABSOLUTT og armleddene RELATIVE, i den rekkefølgen i action_configs. Griperen lukker ikke lister opp de andre årsakene.
- Et kamera faller stille ut midt under opptak. Episoden lagres fortsatt og videonøkkelen eksisterer fortsatt, derfor er denne ekkel. Kamera ikke oppdaget dekker det.
Hele indeksen over feilmoduser finnes på . Hvis du velger mellom modeller i stedet for å feilsøke en, og har benchmark-tall med kilder vedlagt, og er sammenligningen de fleste faktisk trenger, fordi det er valget mellom en modell du kan trene på kortet under pulten din og en du må leie en 80 GB node for å finjustere. For bakgrunn om hvorfor disse modellene oppfører seg som de gjør, er VLA-oversikten og komplett SO-100-guide verdt å lese først. Og hvis du ikke eier en arm ennå, strømmer en fysisk SO-100 uten registrering.
Hvor mange episoder trenger jeg før finjustering av GR00T N1.7 er verdt det?▾
AY-Robots setter et minimum på 50 episoder for groot1.7-treneren. NVIDIAs egen FAQ er mer krevende: omtrent 100 trajektorier for en enkel plukk-og-plasser-oppgave på et fast sted, 500 eller mer for komplekse eller flertrinns-scener, og 100 til 500 for finmanipulasjon. Under 50 er det nesten alltid bedre å registrere mer data enn å justere hyperparametere. Hvis suksessen flater ut etter det, anbefaler NVIDIA HG-DAgger: kjør policyen, grip inn når den feiler, og legg til disse korreksjonene i datasettet.
Hvorfor klarer ikke datasettet mitt å laste, og hvordan finner jeg ut hvilken versjon det er?▾
Åpne meta/info.json og les codebase_version. LeRobots nåværende CODEBASE_VERSION på main er v3.0, så alt som er registrert med en nylig verktøykjede er v3.0, og GR00T-lasteren forventer v2. Konverter med scripts/lerobot_conversion/convert_v3_to_v2.py fra Isaac-GR00T-repoet, som skriver codebase_version: v2.1 inn i det konverterte datasettet. Skriptet kjører i sitt eget virtualenv fordi det trenger en annen lerobot-versjon enn GR00T krever.
Kan jeg finjustere GR00T N1.7 på et RTX 4090?▾
Nei. NVIDIA anbefaler 40 GB eller mer VRAM for finjustering og nevner H100- eller L40-noder; andre kort fungerer, men tar mye lengre tid. Et 4090 har 24 GB. AY-Robots tilbyr kun GR00T N1.7 på A100 80 GB og H100 80 GB nivået av samme grunn. Inferens er en annen historie: 16 GB er nok til å kjøre modellen, så et 4090 kan kjøre en policy det ikke kan trene. Hvis du vil ha en VLA du kan trene på 24 GB, er det SmolVLA på omtrent 450 M parametere eller ACT på omtrent 80 M.
Hvorfor gir to kjøringer med identiske flagg forskjellige sjekkpunkter?▾
Fordi launch_finetune.py ikke har et seed. Det er en tyro CLI generert fra en dataclass som ikke inneholder et seed-felt, så ingenting fester RNG. Repoet bemerker separat 5 til 6 prosent varians mellom kjøringer forårsaket av ikke-deterministisk bildeaugmentering. Hvis reproduserbarhet er viktig, bruk LeRobot-ruten i stedet: lerobot-train tar --seed og den publiserte GR00T-oppskriften sender --seed=42.
Bør jeg bruke Isaac-GR00T eller lerobot-train?▾
Bruk Isaac-GR00T hvis du vil ha referanseimplementeringen, per-nøkkel-kontroll over handlingsrepresentasjon, TensorRT-eksport, eller benchmark-eksemplene for å reprodusere før du stoler på dine egne data. Bruk lerobot-train hvis datasettet ditt allerede er LeRobot v3.0 og du helst ikke vil konvertere det, hvis du vil ha et seed, eller hvis resten av stacken din allerede er LeRobot. Begge finjusterer de samme nvidia/GR00T-N1.7-3B-vektene. Merk at LeRobot droppet GR00T N1.5-støtte helt: N1.5-sjekkpunkter avvises med en migreringsmerknad, og du må låse lerobot==0.5.1 for å fortsette å bruke dem.
Trenger jeg virkelig et håndleddskamera i tillegg til et frontkamera?▾
Den leverte SO-100-konfigurasjonen bruker begge, og modality.json mapper front og håndledd som separate videonøkler. Du kan trene med ett kamera, og modellkortets latens-tabell er målt med ett kamera, men håndleddsvisningen er det som gir policyen brukbar informasjon om griperen i kontaktøyeblikket. Hvis griperen lukker seg på feil tidspunkt i dine rollouts, er et manglende eller dårlig rettet håndleddskamera en av de første tingene å sjekke.
Finjuster GR00T N1.7 på din SO-100 uten å bygge miljøet først
Velg modell, datasett og hyperparametere i et skjema. Backend leier en A100 80 GB eller H100 på spotmarkedet, kjører treneren med batch 32, læringsrate 1e-4 og 20000 trinn, og skriver sjekkpunkter til objektlagring. Omtrent 4 til 12 USD per kjøring.
Åpne GR00T N1.7 treningsguideSources
- NVIDIA Isaac-GR00T repository README, N1.7 main branch
- Isaac-GR00T: Fine-tune on Custom Embodiments (NEW_EMBODIMENT)
- Isaac-GR00T: Finetuning Models for the SO100/SO101 Robot
- Isaac-GR00T: Robot Data Preparation Guide, the GR00T LeRobot format
- Isaac-GR00T: modality config and ActionConfig reference
- Isaac-GR00T: Policy API Guide and the embodiment tag list
- Isaac-GR00T: FinetuneConfig dataclass with every CLI default
- Isaac-GR00T: the shared finetune launcher wrapper
- GR00T N1.7 FAQ: data volume, augmentation and deployment
- nvidia/GR00T-N1.7-3B model card, including the inference timing table
- nvidia/Cosmos-Reason2-2B, the gated VLM backbone used by N1.7
- GR00T N1: An Open Foundation Model for Generalist Humanoid Robots
- NVIDIA Isaac GR00T N1.7: Open Reasoning VLA Model for Humanoid Robots
- LeRobot: GR00T Policy, the lerobot-train recipe
- LeRobot: Imitation Learning on Real-World Robots (lerobot-record, lerobot-train)
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started