Instructions to use JSHNSL/gr00t-ffw-sg2-finetune with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use JSHNSL/gr00t-ffw-sg2-finetune with LeRobot:
- Notebooks
- Google Colab
- Kaggle
- GR00T N1.7 파인튜닝 가이드 — ROBOTIS FFW_SG2 · L-Table Pick & Place
- 이 repo에 든 설정 파일 (터미널에서 바로 받기)
- 이 가이드가 전제하는 것
- 0. 사전 준비
- 1. Isaac-GR00T 설치 (ROBOTIS 포크)
- 2. 데이터 다운로드 + v3.0 → v2.0 변환
- 3. 설정 파일 2개 — 이 repo에서 받아서 배치 (편집 불필요)
- 4. 스모크 테스트 (1스텝) — 설정 검증 + VRAM 실측
- 5. 실제 파인튜닝 — VRAM에 따라 명령이 다르다
- 6. 눈으로 평가 — open-loop (로봇 없이, 그림)
- 7. 학습 결과 HuggingFace에 올리기 (선택)
- 8. 배포 (cyclo_intelligence) — 실물 로봇 PC
- 자주 걸리는 것 (실전에서 겪은 것들)
- GPU별 정리
- 나중에 wrist 카메라를 추가하면
- 이 repo에 든 설정 파일 (터미널에서 바로 받기)
GR00T N1.7 파인튜닝 가이드 — ROBOTIS FFW_SG2 · L-Table Pick & Place
이미 만든 LeRobot 데이터셋 (JSHNSL/ffw_sg2_ltable_merge, 596 ep · 19-dim · cam_head 1대)으로
NVIDIA GR00T N1.7 (3B VLA) 을 파인튜닝하고 ROBOTIS cyclo_intelligence 로 배포하기까지의 처음부터 끝까지.
관련: LeRobot 정책(ACT/VQ-BeT/Diffusion) 전체 파이프라인은 →
JSHNSL/humanoid-imitation-learning
☁️ EC2(40GB+ GPU)에서 diffusion head까지 제대로 학습하려면 → EC2.md (tmux · 인스턴스 선택 · 과금 주의 · action head 학습).
이 repo에 든 설정 파일 (터미널에서 바로 받기)
편집 없이 그대로 쓰는 완성본 2개. 다른 컴퓨터에서도 아래 한 줄이면 받아진다.
| 파일 | 무엇 | 놓을 위치 |
|---|---|---|
modality.json |
19-dim · 카메라 1대 modality | <데이터셋>/meta/modality.json |
ffw_sg2_ltable_config.py |
embodiment config (NEW_EMBODIMENT) | <Isaac-GR00T>/examples/CYCLO/ffw_sg2_ltable/ |
curl (제일 간단):
BASE=https://huggingface.co/JSHNSL/gr00t-ffw-sg2-finetune/resolve/main
# 데이터셋 meta/ 로
curl -fsSL "$BASE/modality.json" \
-o ~/groot_data/JSHNSL/ffw_sg2_ltable_merge/meta/modality.json
# Isaac-GR00T examples 로
mkdir -p ~/Isaac-GR00T/examples/CYCLO/ffw_sg2_ltable
curl -fsSL "$BASE/ffw_sg2_ltable_config.py" \
-o ~/Isaac-GR00T/examples/CYCLO/ffw_sg2_ltable/ffw_sg2_ltable_config.py
또는 hf CLI (repo 통째로):
hf download JSHNSL/gr00t-ffw-sg2-finetune modality.json ffw_sg2_ltable_config.py --local-dir ./gr00t_cfg
# 받은 뒤 각 위치로 복사
배치는 아래 3단계에 상세히 있다 (curl 대신 파일 직접 편집 옵션 포함).
이 가이드가 전제하는 것
| 항목 | 값 |
|---|---|
| 데이터셋 | JSHNSL/ffw_sg2_ltable_merge (LeRobot v3.0) |
| state / action | 19-dim — arm_left(8) · arm_right(8) · head(2) · lift(1) (odometry 없음) |
| 카메라 | 1대 — observation.images.cam_head (376×672) |
| 베이스 모델 | nvidia/GR00T-N1.7-3B (3B) + 백본 nvidia/Cosmos-Reason2-2B (gated) |
| 학습 코드 | ROBOTIS 포크 ROBOTIS-GIT/Isaac-GR00T-n1.7 |
⚠️ NVIDIA 원본이 아니라 ROBOTIS 포크를 써야 한다. 배포하는 cyclo_intelligence가 이 포크를 서브모듈로 쓰므로, 같은 코드로 학습해야 체크포인트가 로드된다.
0. 사전 준비
GPU
| 요구 | |
|---|---|
| 파인튜닝 | 40GB+ 권장 (H100 / L40 / A100). A6000도 됨(느림) |
| 추론 | 16GB+ |
GR00T N1.7은 3B지만 기본 설정이 VLM 백본을 얼리고(
tune_llm=False,tune_visual=False) projector + diffusion action head만 학습한다. 그래서 24GB에서도--global_batch_size를 낮추면 될 여지가 있다 (스모크 테스트에서 실측). RTX 5090(32GB)에서 batch 8 = 31GB 사례 있음.
gated 백본 승인 (필수)
GR00T의 VLM 백본 Cosmos-Reason2-2B 는 접근 승인이 필요하다.
→ https://huggingface.co/nvidia/Cosmos-Reason2-2B 에서 로그인 후 "Agree and access repository" 클릭.
토큰
export HF_TOKEN=hf_당신토큰 # gated 백본 다운로드용 (read 토큰으로 충분)
1. Isaac-GR00T 설치 (ROBOTIS 포크)
git-lfs 먼저 (필수 — 클론 전에)
sudo apt install git-lfs && git lfs install
안 하면
demo_data/·wheel 파일이 LFS 포인터(수십 바이트) 로 받아져uv sync가Invalid zip file structure로 실패한다.
클론 + 커밋 고정
cd ~
git clone --recurse-submodules https://github.com/ROBOTIS-GIT/Isaac-GR00T-n1.7.git Isaac-GR00T
cd Isaac-GR00T
git checkout e81d02b5c561dfafd0556f2a4a602016e670920c # cyclo_intelligence 서브모듈과 동일 커밋
배포 쪽이 쓰는 커밋:
cd ~/cyclo_intelligence && git submodule status cyclo_brain/policy/groot/Isaac-GR00T
환경 — Docker 권장
호스트 CUDA가 13이어도 컨테이너가 CUDA 12.8을 자체 포함하므로 안전하다.
cd ~/Isaac-GR00T
bash docker/build.sh # nvidia/cuda:12.8.0 기반, flash-attn 등 포함
docker images | grep gr00t
uv로 호스트에 직접 설치도 가능하다:
curl -LsSf https://astral.sh/uv/install.sh | sh sudo apt-get install -y ffmpeg uv sync --python 3.10 # dGPU x86_64 = Python 3.10단 호스트 CUDA 13이면 Triton 패치가 필요할 수 있다:
uv run bash scripts/patch_triton_cuda13.sh
2. 데이터 다운로드 + v3.0 → v2.0 변환
GR00T는 LeRobot v2 포맷을 쓴다. 변환 스크립트가 HF에서 받아서 변환까지 한다. 별도 uv 환경을 쓴다 (lerobot 버전이 본체와 다름):
sudo apt-get install -y ffmpeg # 비디오 재인코딩에 필요 (아직 안 했으면)
cd ~/Isaac-GR00T/scripts/lerobot_conversion
uv venv && source .venv/bin/activate
uv pip install -e .
GIT_LFS_SKIP_SMUDGE=1 uv pip install \
"lerobot @ git+https://github.com/huggingface/lerobot.git@c75455a6de5c818fa1bb69fb2d92423e86c70475"
python convert_v3_to_v2.py \
--repo-id JSHNSL/ffw_sg2_ltable_merge \
--root ~/groot_data
deactivate
결과:
~/groot_data/JSHNSL/ffw_sg2_ltable_merge ← v2.0 (이걸 학습에 씀)
~/groot_data/JSHNSL/ffw_sg2_ltable_merge_v3.0 ← 원본 v3.0 백업
확인:
ls ~/groot_data/JSHNSL/ffw_sg2_ltable_merge/meta/
# info.json episodes.jsonl tasks.jsonl stats.json ...
GPU 불필요. 596ep 비디오 재인코딩이라 시간이 걸린다.
3. 설정 파일 2개 — 이 repo에서 받아서 배치 (편집 불필요)
ROBOTIS의 examples/CYCLO/ffw_sg2_rev1 은 22-dim(+odometry) · 카메라 3대(+wrist) 를 요구하는데
우리 데이터는 19-dim · 카메라 1대다. 그대로 쓰면 없는 차원/비디오 키를 참조해 깨진다.
→ odometry 빼고 카메라 1대로 맞춘 완성본 2개를 이 repo에 넣어뒀다. 편집 없이 받아서 배치만 하면 된다.
| 파일 | 놓을 위치 |
|---|---|
modality.json |
<데이터셋>/meta/modality.json |
ffw_sg2_ltable_config.py |
<Isaac-GR00T>/examples/CYCLO/ffw_sg2_ltable/ |
BASE=https://huggingface.co/JSHNSL/gr00t-ffw-sg2-finetune/resolve/main
DS=~/groot_data/JSHNSL/ffw_sg2_ltable_merge
# ① modality.json → 데이터셋 meta/
curl -fsSL "$BASE/modality.json" -o "$DS/meta/modality.json"
# ② config.py → Isaac-GR00T examples/CYCLO/ffw_sg2_ltable/
mkdir -p ~/Isaac-GR00T/examples/CYCLO/ffw_sg2_ltable
curl -fsSL "$BASE/ffw_sg2_ltable_config.py" \
-o ~/Isaac-GR00T/examples/CYCLO/ffw_sg2_ltable/ffw_sg2_ltable_config.py
확인:
cat "$DS/meta/modality.json" # 19-dim, cam_left_head 1개
ls ~/Isaac-GR00T/examples/CYCLO/ffw_sg2_ltable/ # ffw_sg2_ltable_config.py
modality.json은 모델 비디오 키를cam_left_head로 두고 데이터 소스만 우리observation.images.cam_head로 가리킨다 → 배포 시 cyclo_intelligence 의 카메라 이름과 바로 맞는다.config.py는 embodimentNEW_EMBODIMENT로 등록한다.
참고 — 파일을 직접 만들고 싶으면 이 repo의 두 파일 내용을 그대로 쓰면 된다. Docker로 학습한다면
~/Isaac-GR00T/examples/CYCLO를 컨테이너에 마운트(4단계 스모크 참고)하므로, 호스트에 배치하면 컨테이너에서 보인다.
4. 스모크 테스트 (1스텝) — 설정 검증 + VRAM 실측
진짜 학습 전에 데이터·modality·embodiment 가 맞는지 1스텝만 돌린다.
Docker 컨테이너 진입 — ⚠️ /workspace 전체를 마운트하지 말 것 (이미지의 .venv 를 덮어써 torch 를 못 찾는다). 필요한 것만 하위 경로로 마운트:
docker run -it --rm --gpus all \
--ipc=host --ulimit memlock=-1 --ulimit stack=67108864 \
-e HF_TOKEN="$HF_TOKEN" \
-v ~/.cache/huggingface:/root/.cache/huggingface \
-v ~/groot_data:/workspace/groot_data \
-v ~/Isaac-GR00T/examples/CYCLO:/workspace/examples/CYCLO \
gr00t
컨테이너 안에서 환경 확인 후 스모크:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())" # True
python gr00t/experiment/launch_finetune.py \
--base_model_path nvidia/GR00T-N1.7-3B \
--dataset_path /workspace/groot_data/JSHNSL/ffw_sg2_ltable_merge \
--embodiment_tag NEW_EMBODIMENT \
--modality_config_path examples/CYCLO/ffw_sg2_ltable/ffw_sg2_ltable_config.py \
--num_gpus 1 --output_dir /tmp/groot_smoke \
--max_steps 1 --global_batch_size 1 --dataloader_num_workers 0
다른 터미널에서 VRAM 실측 (24GB로 되는지 여기서 결정):
watch -n1 nvidia-smi --query-gpu=memory.used,memory.total --format=csv
여기까지 통과하면 데이터·설정이 다 맞은 것이다.
5. 실제 파인튜닝 — VRAM에 따라 명령이 다르다
GR00T 3B 파인튜닝에서 메모리를 가르는 건 어느 부분을 학습하느냐(--tune-*) 다.
기본값은 VLM 백본을 얼리고(--no-tune-llm --no-tune-visual) projector + diffusion action head를 학습한다.
그중 diffusion action head가 실제 로봇 동작을 만든다 → 이걸 학습해야 "진짜 성능"이 나온다.
Ⓐ 40GB+ GPU (권장 — 제대로 학습) · A100/L40S/H100/RTX PRO 6000
python gr00t/experiment/launch_finetune.py \
--base_model_path nvidia/GR00T-N1.7-3B \
--dataset_path /workspace/groot_data/JSHNSL/ffw_sg2_ltable_merge \
--embodiment_tag NEW_EMBODIMENT \
--modality_config_path examples/CYCLO/ffw_sg2_ltable/ffw_sg2_ltable_config.py \
--num_gpus 1 --output_dir /workspace/groot_data/out/ffw_sg2_ltable \
--max_steps 20000 --save-steps 2000 \
--global_batch_size 16 --dataloader_num_workers 8
action head까지 학습(기본값). batch 16~32. 이게 정석.
Ⓑ 24GB GPU (실측 — 파이프라인 검증용) · RTX 4090/5000급
24GB에선 action head를 켜면 OOM이다 (batch 1로도 18MB 부족 — 실측). → head를 얼려서(projector만) 돌린다:
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
python gr00t/experiment/launch_finetune.py \
--base_model_path nvidia/GR00T-N1.7-3B \
--dataset_path /workspace/groot_data/JSHNSL/ffw_sg2_ltable_merge \
--embodiment_tag NEW_EMBODIMENT \
--modality_config_path examples/CYCLO/ffw_sg2_ltable/ffw_sg2_ltable_config.py \
--num_gpus 1 --output_dir /workspace/groot_data/out/ffw_sg2_ltable \
--max_steps 500 --save-steps 500 \
--global_batch_size 1 --gradient-accumulation-steps 16 \
--dataloader_num_workers 8 \
--no-tune-diffusion-model
⚠️
--no-tune-diffusion-model= action head 안 배움. 파이프라인·배포 경로 검증엔 좋지만 grasp 성능은 기대하지 말 것. 제대로 하려면 Ⓐ (40GB+).
| 인자 | 메모 |
|---|---|
--max_steps / --save-steps |
--save-steps 를 꼭 낮출 것. 기본 1000이라 그보다 짧게 돌리면 체크포인트가 안 생긴다 |
--global_batch_size |
40GB=16~32, 24GB=1 |
--gradient-accumulation-steps |
배치 쪼개 유효 배치 유지 (오타 주의: accumulation) |
--no-tune-diffusion-model |
24GB에서 OOM 회피용. 성능은 희생 |
--num_gpus |
다중 GPU: torchrun --nproc_per_node=N ... --num_gpus N |
⚠️ docker run -it --rm 로 붙어 있으면 그 터미널을 닫는 순간 컨테이너·학습이 사라진다. 긴 학습은
호스트에서 tmux 로 감싸거나, 컨테이너를 -d 로 띄우고 docker exec 로 들어가서 돌릴 것.
학습이 끝나면 출력 폴더 확인 (호스트):
sudo ls ~/groot_data/out/ffw_sg2_ltable/
# config.json model-0000N-of-000NN.safetensors model.safetensors.index.json experiment_cfg/ processor/ checkpoint-N/
6. 눈으로 평가 — open-loop (로봇 없이, 그림)
정답 액션 vs 정책 예측을 겹쳐 그린다. 로봇·오케스트레이터 없이 정책 단독으로 돈다. 컨테이너 안에서:
python gr00t/eval/open_loop_eval.py \
--dataset-path /workspace/groot_data/JSHNSL/ffw_sg2_ltable_merge \
--embodiment-tag NEW_EMBODIMENT \
--model-path /workspace/groot_data/out/ffw_sg2_ltable \
--traj-ids 0 --action-horizon 16 \
--save-plot-path /workspace/groot_data/eval
--modality-config-path인자는 없다 (modality는 체크포인트의experiment_cfg에서 읽음). 결과:~/groot_data/eval/traj_0.jpeg— 19개 관절 정답(파랑) vs 예측(주황) + MSE. 곡선이 겹치면 잘 배운 것. (projector-only면 많이 어긋난다 — 정상)
7. 학습 결과 HuggingFace에 올리기 (선택)
다른 컴퓨터/로봇 PC에서 받아 쓰려면 HF에 올린다. 컨테이너 안에서 (write 토큰 필요):
hf auth login # write 토큰 (안 되어 있으면)
python -c "from huggingface_hub import whoami; print(whoami()['name'])" # JSHNSL 확인
python -c "
from huggingface_hub import create_repo, upload_folder
repo = 'JSHNSL/groot_ffw_ltable'
create_repo(repo, repo_type='model', exist_ok=True)
upload_folder(
folder_path='/workspace/groot_data/out/ffw_sg2_ltable',
repo_id=repo, repo_type='model',
ignore_patterns=['checkpoint-*', 'training_args.bin', 'wandb_config.json'],
)
print('done ->', repo)
"
ignore_patterns로checkpoint-*(중복 12GB)·학습 잔여물 제외 → 추론에 필요한 것만 (~12.5GB) 올라간다.
받을 때 (배포할 PC에서):
hf download JSHNSL/groot_ffw_ltable \
--local-dir ~/cyclo_intelligence/docker/huggingface/lerobot/JSHNSL/groot_ffw_ltable
8. 배포 (cyclo_intelligence) — 실물 로봇 PC
cyclo_intelligence 캐시는 호스트에 마운트돼 있다:
~/cyclo_intelligence/docker/huggingface → 컨테이너 /root/.cache/huggingface.
→ docker cp(심볼릭 링크로 실패함) 대신 호스트에서 직접 복사한다.
SRC=~/groot_data/out/ffw_sg2_ltable
DST=~/cyclo_intelligence/docker/huggingface/lerobot/JSHNSL/groot_ffw_ltable
sudo mkdir -p "$DST"
# 추론에 필요한 것만 (checkpoint-N 중복·학습 잔여물 제외)
sudo cp -a "$SRC"/config.json \
"$SRC"/model-*.safetensors \
"$SRC"/model.safetensors.index.json \
"$SRC"/experiment_cfg \
"$SRC"/processor \
"$DST"/
웹 UI → Inference → 모델 타입 N1.7 (GR00T 그룹) → User JSHNSL → Policy groot_ffw_ltable → Load
⚠️ "Loading" 에서 안 넘어가면 → groot_server 수동 기동
GR00T는 별도 엔진 groot_server 를 쓴다 (LeRobot은 lerobot_server). 오케스트레이터가 자동 기동에
실패하면 Loading에서 멈춘다. 직접 띄우면 된다 (호스트):
docker start groot_server
docker logs -f groot_server 2>&1 | grep -v "Service call timed out"
로그에 이게 뜨면 로드 성공:
Loading GR00T policy from: /workspace/model/groot/groot_ffw_ltable
Policy info: {'video': ['cam_left_head'], 'state': ['arm_left','arm_right','head','lift'], ...}
→ modality(19-dim/카메라1개)를 정확히 읽었다는 뜻. 웹 UI가 Inference로 넘어간다.
GR00T 엔진은 모델의 modality 설정을 그대로 따라간다 —
odometry없으면/odom안 읽고, 카메라도 모델이 요구하는 것만 구독. 19-dim/카메라1개 그대로 동작한다. ⚠️ 실제 로봇 움직임은 실물 로봇+카메라가 연결된 로봇 PC에서만 의미 있다 (로봇 없으면 mock).
자주 걸리는 것 (실전에서 겪은 것들)
| 증상 | 원인 / 해결 |
|---|---|
변환 Permission denied: ~/groot_data/JSHNSL |
Docker(root)가 먼저 만들어 root 소유 → sudo chown -R $USER:$USER ~/groot_data ~/.cache/huggingface |
uv sync Invalid zip file structure |
wheel이 LFS 포인터 → git lfs install && git lfs pull 후 재시도 |
컨테이너에서 No module named 'torch' |
-v ~/Isaac-GR00T:/workspace 로 venv 덮어씀 → /workspace 전체 말고 하위 경로만 마운트 |
401 gated repo Cosmos-Reason2-2B |
백본 승인 안 됨 → HF에서 Agree + HF_TOKEN 전달 |
Isaac pip packaging._structures 손상 |
-m ensurepip --upgrade, 또는 get-pip.py --ignore-installed (⚠️ --force-reinstall 은 또 죽음) |
CUDA OutOfMemory (optimizer.step) |
24GB면 --no-tune-diffusion-model + PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True. 그래도면 40GB+ GPU |
Unrecognized options: --gradient-accmulation-steps |
오타. --gradient-accumulation-steps (u 빠짐) |
| 학습했는데 출력에 config만 있고 모델 없음 | --save-steps 가 --max_steps 보다 커서 저장 전에 끝남 → --save-steps 낮추기 |
docker cp ... path escapes from parent |
출력의 심볼릭 링크 때문 → 호스트 마운트에 직접 cp (8단계) |
| 웹 UI Loading 무한 | groot_server 자동 기동 실패 → docker start groot_server |
uv run 마다 Installing flash-attn... |
정상 (캐시 재검증, 2~3초). 재빌드 아님 |
GPU별 정리
| GPU | VRAM | action head 학습 | 방법 |
|---|---|---|---|
| RTX 5000 Blackwell 등 | 24GB | ❌ (OOM) | Ⓑ projector-only (검증용) |
| A100 / L40S / H100 | 40~80GB | ✅ | Ⓐ 정석 |
| RTX PRO 6000 Blackwell | 96GB | ✅ | Ⓐ, batch 크게. 로컬에서 EC2 없이 |
나중에 wrist 카메라를 추가하면
ffw_sg2_rev1 (22-dim + 카메라 3대) 에 가까워진다. modality.json 의 video 에 2개,
config.py 의 modality_keys 에 2개를 더한다. 단 데이터 596ep 재생성이 필요하다.
(현재 단일 cam_head 는 grasp 시 근접 시야가 부족해 폐루프 성능에 한계가 있다.)