에피소드 5편(1.2 GB) 위에 세 가족 find · restore · resume의 채점 행 36개가 얹혀 있다. 실제 파일을 열어 층 구조 · 필드 · 판정 규칙을 정리하고, 각 가족마다 실제 행 하나를 프레임 그림과 함께 끝까지 따라간다. 마지막에 아직 없는 네 번째 가족 routine의 설계 제안을 같은 편의 실측값으로 붙였다.
데이터셋은 무거운 층(contexts/)과 가벼운 층(eval/)으로 정확히 갈린다.
용량비가 14,000:1이고, 이게 설계의 핵심이다 — 에피소드는 한 번 만들고 안 고치며, 질의·채점 규칙만 다시 빌드한다.
DATASET_sample_v1/ 1.2 GB ├─ contexts/ 로봇이 실제로 굴러간 에피소드 원본. 질의 규칙 없음 │ ├─ type1/ val_144__2 88 MB seed < 1000 · 사용자 발화 없음 │ │ val_406__0 289 MB │ │ val_733__0 346 MB │ └─ type2/ val_101__1100 299 MB seed ≥ 1000 · 사용자가 task를 주고 중간에 끊음 │ val_733__1100 206 MB └─ eval/ 채점 단위. tools/build_eval.py 생성물 — 손으로 고치면 지워짐 ├─ index.json 가족 × 컨텍스트 매트릭스 ├─ find/ queries.jsonl stats.json README.md ├─ restore/ queries.jsonl stats.json README.md ├─ resume/ queries.jsonl stats.json (README 없음) └─ routine/ — 아직 없다. 설계 제안은 §5b
| kind | 영상 안에서 | 쓰는 가족 | seed | 이 kind에만 있는 것 |
|---|---|---|---|---|
| type1 | 로봇이 집을 돌며 물건을 옮긴다. 사용자 발화 없음 | find restore | < 1000 | states/final.npz |
| type2 | 사용자가 반복 유닛 task를 순차로 주고 중간에 세운다 | resume | ≥ 1000 | states/cut_*.npz · index.json |
README와 실물이 어긋난다. contexts/README.md는 type2 전용 파일로
tasks.json·utterances.json을 적어놨지만 이 배포본에는 둘 다 없다.
같은 내용이 subtasks.json의 tasks/cuts/stage 키와
질의 행의 commands[]로 흡수돼 있다. 로더를 파일명 기준으로 짜면 깨진다.
meta.json 494 B house·seed·fps·카메라·지문 subtasks.json 6.7 KB 이벤트 4개 + 세그먼트 traj.h5 53.8 MB 12,778 스텝 전 상태 states/final.npz 2.2 KB 가벼운 스키마 videos/ exo_camera_1.mp4 13.9 MB 640×480 @25fps exo_camera_2.mp4 14.1 MB wrist_camera.mp4 10.4 MB
meta.json 325 B subtasks.json 13.0 KB 유닛 10개 + tasks + cuts + stage traj.h5 37.8 MB 9,265 스텝 states/ 11×19 KB cut_00..09 + final index.json 태그↔프레임↔시각 videos/ 274 MB 동일 3 카메라
같은 states/인데 스키마가 완전히 다르다.
type1 final.npz는 names(25) · pose(25,7) · robot_base_pose(7) · frame 네 배열뿐인
추적 객체 스냅샷(start_state_schema: "v0_track_tail")이고,
type2 cut_*.npz는 qpos(82) · qvel(77) · ctrl(11) · model_geom_* · model_body_*까지 든
MuJoCo 전체 상태 덤프(35개 키)다. type2만 물리 상태까지 정확히 복원된다.
가족이 달라도 이 11개는 같은 이름·같은 뜻이다. 36행 전부에 대해 확인했다 — 결손 0.
가족 고유 필드는 중첩 payload 없이 같은 층에 나란히 놓인다.
| 필드 | 뜻 | 이 샘플의 실제 값 |
|---|---|---|
| schema_version | 행 스키마 | "1.0" (36/36) |
| family | eval/<family>/와 같다 | find · restore · resume |
| kind | EVAL_TASKS 레지스트리 키 | find_target · find_distractor · restore · resume |
| query_id | <family>:<ep>:<local> — 전역 유일 | find:val_144__2:q00 |
| context | 데이터셋 루트 상대. 절대경로·심링크 금지 | contexts/type1/val_144__2 |
| context_frames | 정책이 보는 닫힌 구간. 자르는 건 읽는 쪽 | [0, 12777] / [0, 651] |
| start_state | context 상대 | states/final.npz · states/cut_01.npz |
| query | 정책에 주는 문장 | 아래 각 가족 표 참조 |
| budget_steps | 스텝 예산 | 400 ~ 12000 |
| oracle | 오라클 실행 후 채운다. null = 아직 안 돌림 |
find null restore null resume 7/7 |
| tags | 분석 축. 채점에 안 쓴다 | relocate · shift · twin_merge · r1 |
캐시 키는 (context, context_frames[1])다.
이 샘플에서 find·restore는 전 행이 편 전체를 본다 —
val_144__2 [0,12777] · val_406__0 [0,11436] · val_733__0 [0,13408].
즉 두 가족의 캐시 키가 자동으로 같아지므로, 러너는 context로 묶어 편당 한 번만 컨텍스트를 로드하면 된다
(find 편당 6.0행, restore 편당 3.67행).
에피소드가 끝난 상태(states/final.npz)에서 시작해, 영상 속에서 옮겨졌던 물건을 다시 찾아 집는다.
18행 · 컨텍스트 3 · 정답 21개, 자격 탈락 1건(ambiguous, 탈락률 5.3%).
find:val_144__2:q00find_target steps=multi n_candidates=2 twin_nearby=false budget=1500
"Pick up all the bowls I moved earlier"
이 편은 4개 이벤트로 이뤄져 있고, 그중 2개가 bowl을 옮긴다. 그래서 이 한 문장의 정답이 2개다.
settled_frame 2107.settled_frame 12777로 방금 안착.answers[] 두 개| obj | xyz | room | surface | settled | last_seen | s_since_seen | d_base_end | scoring |
|---|---|---|---|---|---|---|---|---|
| bowl_…_1_0_4 | 8.756, 10.135, 0.365 | 4 | armchair | 2107 | 6744 | 241.3 s | 7.24 m | pick |
| bowl_…_2_0_6 | 6.155, 2.869, 0.845 | 7 | diningtable | 12777 | 12774 | 0.1 s | 0.65 m | pick |
두 정답의 기억 난이도가 정반대다 — 하나는 241초 전에 마지막으로 봤고 7.24 m 떨어져 있으며, 다른 하나는 0.1초 전 눈앞(0.65 m)에 있다. 한 행 안에 "기억해야 하는 것"과 "보고 있는 것"이 같이 들어간다.
candidates[]는 근거다 —
각 정답이 어느 이벤트에서 나왔는지(ev0 frames [0,2082] / ev3 frames [8880,12764])를 기록한다.
| query_id | query | kind | steps | twin | n | scoring |
|---|---|---|---|---|---|---|
| val_144__2:q00 | Pick up all the bowls I moved earlier | target | multi | – | 2 | pick |
| val_144__2:q01 | Pick up the remote control I moved earlier | target | single | twin | 1 | pick |
| val_144__2:q02 | Pick up the cell phone | distr | single | – | 1 | pick |
| val_144__2:q03 | Pick up the soap bottle | distr | single | – | 1 | nav_only |
| val_144__2:q04 | Pick up the pot | distr | single | – | 1 | pick |
| val_144__2:q05 | Pick up the spray bottle | distr | single | – | 1 | nav_only |
| val_144__2:q06 | Pick up the apple | distr | single | – | 1 | pick |
| val_406__0:q00 | Pick up the fork I moved earlier | target | single | twin | 1 | pick |
| val_406__0:q01 | Pick up the vase I moved earlier | target | single | – | 1 | pick |
| val_406__0:q02 | Pick up the tissue box I moved earlier | target | single | – | 1 | pick |
| val_406__0:q03 | Pick up the bowl I moved earlier | target | single | – | 1 | pick |
| val_733__0:q00 | Pick up the bowl I moved earlier | target | single | – | 1 | nav_only |
| val_733__0:q01 | Pick up all the remote controls I moved earlier | target | multi | – | 2 | pick |
| val_733__0:q02 | Pick up the bottle I moved earlier | target | single | twin | 1 | pick |
| val_733__0:q03 | Pick up the spoon | distr | single | twin | 1 | pick |
| val_733__0:q04 | Pick up the knife | distr | single | – | 1 | pick |
| val_733__0:q05 | Pick up all the forks | distr | multi | twin | 2 | pick |
| val_733__0:q06 | Pick up the vase | distr | single | – | 1 | pick |
find_target vs find_distractor가 문장으로 구분된다.
target은 "I moved earlier"가 붙고(영상 속 사건에 근거), distractor는 안 붙는다(처음부터 그 자리에 있던 물건).
9 : 9로 균형. 즉 "기억이 필요한 질의"와 "그냥 탐색이면 되는 질의"가 반씩이고, 이 대조가 기억 효과의 측정축이다.
find가 "어디 있나"를 묻는다면 restore는 "원래 어디 있었나"를 묻는다. 찾아서 집고, 되돌려 놓아야 끝난다. 11행 · 컨텍스트 3 · 정답 17개, 같은 컨텍스트를 find와 공유한다.
restore:val_144__2:q00restore origin=first steps=single twin_nearby=true budget=5000
"Pick up the remote control and place it in or on where it first was"
리모컨은 이 편에서 두 번 옮겨졌다: 침대 → 변기(ev1) → 식탁(ev2).
origin=first는 맨 처음 자리인 침대를 답으로 요구한다. 중간 경유지인 변기는 오답이고,
그건 other_origins에 따로 기록돼 교차 오답 진단에 쓰인다.
origin_frames [0, 2790], 이 자리에서 5.64초 관측됨.find:val_144__2:q01의 정답이다.answers[0] 핵심 수치| 필드 | 값 | 뜻 |
|---|---|---|
| d_xy | 8.679 m | from→to 변위. 자격 하한 1.0 m |
| same_room / n_hops | false / 2 | 방을 2번 건너야 한다 |
| approach | in_reach | 집는 건 제자리에서 가능 (d_base_end 0.56 m) |
| r_place / check_quat | 0.15 m / false | 판정 반경. 자세(quat)는 안 본다 |
| other_origins | [[12.611, 0.833, 0.587]] | 변기 — 오답으로 걸러야 할 다른 원래 자리 |
| twins | remotecontrol_…_2_0_7 (d_xy 0.518 m) | 같은 에셋이 52 cm 옆에 있다 — 잘못 집기 쉬움 |
| shares_answer_with | find:val_144__2:q01 | 독립이 아닌 측정임을 명시 |
| query_id | steps | origin | twin | n | approach | d_xy | same_room | hops | budget |
|---|---|---|---|---|---|---|---|---|---|
| val_144__2:q00 | single | first | twin | 1 | in_reach | 8.679 | – | 2 | 5000 |
| val_144__2:q01 | single | previous | twin | 1 | in_reach | 7.053 | – | 2 | 5000 |
| val_144__2:q02 | multi | first | twin | 3 | navigate | 4.602 | same | 1 | 12000 |
| val_406__0:q00 | single | first | twin | 1 | navigate | 1.946 | same | 2 | 5000 |
| val_406__0:q01 | single | previous | twin | 1 | navigate | 8.589 | – | 2 | 5000 |
| val_406__0:q02 | single | first | – | 1 | navigate | 1.509 | same | 1 | 5000 |
| val_406__0:q03 | single | first | – | 1 | navigate | 4.693 | – | 1 | 5000 |
| val_406__0:q04 | single | first | – | 1 | in_reach | 7.399 | – | 1 | 5000 |
| val_406__0:q05 | multi | first | twin | 3 | navigate | 1.946 | same | 2 | 12000 |
| val_733__0:q00 | single | first | twin | 1 | in_reach | 1.177 | same | 1 | 5000 |
| val_733__0:q01 | multi | first | twin | 3 | navigate | 14.354 | – | 1 | 12000 |
대조쌍이 설계돼 있다.
origin=first 9행 vs previous 2행이 짝을 이룬다 —
val_144__2의 q00(first, 침대)/q01(previous, 변기)은 같은 물체·같은 문장 틀인데 정답만 다르다.
"첫 자리"와 "직전 자리"를 구분해서 기억하는지가 그대로 갈린다.
거리 분포가 넓다.
d_xy 중앙 4.693 m · p10 1.177 · p90 12.19 · 최대 14.354 m.
가장 가까운 다른 물체까지는 중앙 0.588 m밖에 안 되므로(d_nearest_obj),
0.15 m 판정 반경은 옆 물체 위에 놓는 실수를 잡아낼 만큼 빡빡하다.
type2 편에서만 나온다. 사용자가 반복 유닛 task를 순차로 주고 중간에 세운다.
질의 문장은 7행 전부 동일하고 — 정보는 전부 start_state와 commands[]에 있다.
7행 · 컨텍스트 2 · 탈락 0.
"You were in the middle of something. Continue what you were doing."
resume:val_101__1100:cut_01press_button cue=bare cut_phase=clean budget=400
이 편의 사용자 지시는 세 개였다:
| task | kind | utterance | start_frame | n / done |
|---|---|---|---|---|
| T1 | press_button | Press the button on the dryer three times. | 1 | 3 / 3 |
| T2 | visit_rooms | Navigate to every room in the house. | 848 | 4 / 4 |
| T3 | put_in_container | Pick up three of the eggs from the dresser and place them into the basket. | 3169 | 3 / 3 |
cut_01은 frame 651에서 끊는다. T1의 3번 중 2번을 눌렀고(m=2),
1번 남았다(r=1). 이 시점에 정책이 보는 것은 프레임 0–651과 T1 발화 한 줄뿐이다 —
T2·T3는 아직 주어지지도 않았으므로 decoy_tasks로만 들어간다.
세로 눈금 = 컷 10개(states/index.json). 굵은 눈금 4개가 이 배포본의 질의로 채택됐다.
done_units에 frame 453, 650이 기록됨. 1회 남음.오라클이 이미 돌아 있다.
oracle: {steps: 196, unit_order: ["t1app_Clothes_Dryer_2"], completed: 1} —
예산 400스텝은 오라클 196스텝의 약 2배로 잡혔다.
| query_id | cut@frame | task type | n | m(완료) | r(남음) | budget | oracle steps | decoys |
|---|---|---|---|---|---|---|---|---|
| val_101__1100:cut_01 | 651 | press_button | 3 | 2 | 1 | 400 | 196 | T2, T3 |
| val_101__1100:cut_02 | 848 | press_button | 3 | 3 | 0 | 400 | 0 | T2, T3 |
| val_101__1100:cut_05 | 2615 | visit_rooms | 4 | 3 | 1 | 829 | 553 | T1, T3 |
| val_101__1100:cut_08 | 7529 | put_in_container | 3 | 2 | 1 | 2583 | 1722 | T1, T2 |
| val_733__1100:cut_01 | 591 | press_button | 3 | 2 | 1 | 400 | 196 | T2, T3 |
| val_733__1100:cut_02 | 788 | press_button | 3 | 3 | 0 | 400 | 0 | T2, T3 |
| val_733__1100:cut_05 | 3143 | visit_rooms | 4 | 3 | 1 | 936 | 624 | T1, T3 |
r=0 2행이 이 가족의 함정이다.
stats.json의 by_r: {0: 2, 1: 5}가 그것이다.
두 행 모두 컷 시점에 해당 task가 이미 n번 다 채워져 있고, 오라클도 steps 0 · completed 0이다.
즉 "계속하라"는 말에 반사적으로 한 번 더 누르면 틀린다.
기억 없이 문장만 따라가는 정책을 잡아내는 음성 대조군이다.
find/restore/resume은 전부 특정 사건을 묻는다 — 그 물건, 그 자리, 그 컷. routine은 다르다: 여러 사건에 공통으로 흐르는 규칙을 유도해서, 본 적 없는 물건에 적용하라고 한다. taxonomy 하위 3종은 D1 배치 규칙 · D2 절차 규칙 · D3 금지이고, 아래는 그중 D1이다.
val_406__0의 이벤트 5개가 물건을 놓은 곳을 표면 클래스로 세면 이렇게 된다.
아무도 의도하지 않았는데 3/5가 같은 클래스로 간다.
| ev | 물건 | 출처 → 목적지 | 목적지 표면 (실제 body name) | room | 클래스 |
|---|---|---|---|---|---|
| 0 | fork | 조리대 → 서랍장 | chestofdrawers_bcf35268…_1_0_7 | 7 | chestofdrawers |
| 1 | vase | TV장 → 서랍장 | chestofdrawers_bcf35268…_1_0_7 | 7 | chestofdrawers |
| 2 | fork | 서랍장 → 식탁 | diningtable_f113cf7f…_2_0_6 | 6 | diningtable |
| 3 | tissue box | TV장 → 서랍장 | chestofdrawers_10acc45c…_1_0_4 | 4 | chestofdrawers |
| 4 | bowl | 서랍장 → 세면대 | sink_07e796f3…_1_0_5 | 5 | sink |
bcf35268…10acc45c… — 에셋이 다르다.이 세 장이 D1의 핵심을 그대로 보여준다.
두 서랍장은 에셋 해시가 다르다(bcf35268… vs 10acc45c…) — 색도 재질도 방도 다르다.
그러니 정답은 좌표도 인스턴스도 아니고 카테고리다. restore가
xyz + r_place 0.15로 한 점을 찍는 것과 판정 방식 자체가 갈린다.
이름이 두 개다. 발화는 “dresser”라고 하는데
body name은 chestofdrawers_*다(subtasks.json의
slots.place_name vs obj 비교). 규칙은 body name의 에셋 클래스로 정의하고,
질의 문장은 사람이 쓰는 낱말로 쓴다 — 이 매핑을 채점기가 들고 있어야 한다.
규칙 과제의 난점은 “그럴듯한 오답”을 만드는 것인데, 이 편에서는 저절로 생겼다.
| 표면 | 출처로 | 목적지로 | 역할 |
|---|---|---|---|
| chestofdrawers ×2 | 2 | 3 | 정답 클래스 |
| stand (TV장) | 2 | 0 | 최상급 미끼 |
| countertop | 1 | 0 | 미끼 |
| diningtable | 0 | 1 | 반례 |
| sink | 0 | 1 | 반례 |
TV장은 로봇이 두 번이나 앞에 서서 물건을 집은 곳인데 놓은 적은 한 번도 없다. 관측 빈도로만 고르면 반드시 걸린다 — “자주 본 표면”과 “물건을 두는 표면”을 구분해야 통과한다.
routine에서 가장 위험한 설계 지점이다. 문장 하나로 이 가족은 메모리 과제가 되기도 하고 상식 퀴즈가 되기도 한다. 문장은 아래 세 가지를 동시에 만족해야 한다.
| # | 요구 | 안 지키면 |
|---|---|---|
| 1 | 규칙의 축을 지정한다 — 방인가, 가구 종류인가, 서랍 안인가 | 정책이 무엇을 유도해야 할지 몰라 ambiguous 탈락 |
| 2 | 규칙의 값은 절대 주지 않는다 — “서랍장”이라는 낱말이 문장에 없어야 한다 | 기억 없이 풀린다 → perception task로 강등 (규칙 1 위반) |
| 3 | 일반성을 표시한다 — usually / kind of 같은 반복·범주 신호 |
“내가 마지막에 놓은 곳”으로 읽혀 단일 사건 조회가 된다 → find/restore와 구분 소실 |
| 가족 | template | 뒷절이 가리키는 것 | 정답의 정체 |
|---|---|---|---|
| restore | PickAndPlace(restore) | … place it in or on where it first was | 그 물체의 과거 → 좌표 1점 |
| restore | PickAndPlace(restore) | … place it in or on where it was just before | 그 물체의 직전 → 좌표 1점 |
| routine | PickAndPlace(routine) | … place it in or on the kind of place where things usually go in this house | 그 집의 규칙 → 표면 클래스 |
뒷절 슬롯 하나만 갈아끼우면 된다 —
PickAndPlace 템플릿을 그대로 쓰므로 MolmoSpaces 학습 분포에서 벗어나지 않는다.
restore가 물체의 이력을 묻는 자리에 routine은 집의 규칙을 넣는다.
| 하위 | 질의 문장 | 축을 지정하는 부분 |
|---|---|---|
| D1 배치 |
Pick up the mug and place it in or on the kind of place where things usually go in this house |
the kind of place = 표면 클래스usually = 반복/규칙 신호 |
| D2 절차 |
Put one more egg in the basket, the way the others were done in this house |
the way = 순서 축the others = 앞선 유닛 참조 |
| D3 금지 |
Put the mug down somewhere it can stay — somewhere this house would put it |
would put it = 허용/금지 축금지 표면은 문장에 안 나온다 |
D3의 A5 충돌을 문장으로 푼다. “금지”를 “안 하기”로 내면 규칙을 지켜서 안 한 것과 그냥 못 한 것이 구분되지 않아 공리 A5(기권도 정답)와 부딪힌다. 위처럼 “금지된 곳을 피해서 놓기”로 내면 양성 판정이 된다 — 반경 안에 놓을 곳이 여럿이고 그중 하나가 이 집에서 물건을 절대 두지 않는 표면이면, 판정은 “놓았고 & 금지 표면이 아니다”로 끝난다. 기권과 명확히 갈린다.
이 가족은 find_distractor가 이미 걸렸던 함정을 훨씬 크게 밟는다. 파일럿 실측에서 find_distractor의 blind 정확도가 0.75였다 — 비누는 욕실, 냄비는 주방이라는 상식만으로 풀렸다는 뜻이다. “머그를 치워라”는 그보다 더 심하다. 방어 없이 내면 blind가 규칙을 안 보고도 맞힌다.
| # | 방어 | 구체적으로 |
|---|---|---|
| 1 | 반사실 짝 (공리 A6) | 문장은 집마다 똑같이 두고 정답만 다르게 저작한다. 같은 “머그를 이 집 규칙대로 놓아라”가
house A에서는 chestofdrawers, house B에서는 countertop, house C에서는 shelf.
최소 2집을 짝으로 묶어 둘 다 맞아야 득점 — resume이 7행 전부 같은 문장인 것과 같은 원리다. |
| 2 | 반상식 배치를 섞는다 | 규칙 값의 일정 비율을 상식과 어긋나게 저작한다. 마침 이 편이 그 예다 — 포크를 서랍장에 올린다(ev0). 상식으로는 주방 서랍이다. |
| 3 | blind control@chance 고정 | 후보 표면 클래스가 K개면 blind 기대값은 1/K다. 편마다 K를 세어
n_surface_classes로 행에 기록하고, blind가 1/K를 유의하게 넘으면 그 편을 탈락시킨다. |
홀드아웃 물체 선정 규칙도 문장이 정한다.
홀드아웃은 규칙 근거에 안 나온 카테고리여야 한다. 근거가 fork·vase·tissue box이므로
홀드아웃이 또 fork면 “같은 물체를 어디 뒀더라”(= find)로 풀려버린다.
mug는 세 카테고리 어디에도 없고 컨텍스트 동안 한 번도 안 움직였다 — 그래서 골랐다.
공통 봉투 11필드는 그대로 두고, 고유부만 얹는다(중첩 payload 없음, 다른 가족과 같은 규약).
주황 표시가 저작해야 하는 부분이고 나머지는 실측값이다.
{
// ── 공통 봉투 11 (다른 가족과 동일) ──
"schema_version": "1.0",
"family": "routine",
"kind": "routine_placement", // D1. D2=routine_procedure, D3=routine_prohibition
"query_id": "routine:val_406__0:q00",
"context": "contexts/type1/val_406__0",
"context_frames": [0, 11436],
"start_state": "states/final.npz",
"query": "Pick up the mug and place it in or on the kind of place
where things usually go in this house",
"budget_steps": 5000,
"oracle": null,
"tags": ["placement_rule"],
// ── routine 고유부 ──
"template": "PickAndPlace(routine)", // restore와 같은 틀. 뒷절 슬롯만 우리 것
"rule": { "type": "surface_class", "value": "chestofdrawers",
"utterance_word": "dresser" }, // body name ↔ 사람 낱말
"n_surface_classes": 6, // blind control@chance = 1/6 ≈ 0.167
"counterfactual_pair": "routine:val_733__0:q00", // 공리 A6 — 같은 문장, 다른 정답
"n_evidence": 3,
"evidence": [ // 규칙을 세운 사건들 (근거)
{ "event": 0, "obj": "fork_a17d780c…_1_0_6", "frames": [1782, 2181],
"surface": "chestofdrawers_bcf35268…_1_0_7", "room": 7 },
{ "event": 1, "obj": "vase_939cc49c…_1_0_7", "frames": [3483, 3882],
"surface": "chestofdrawers_bcf35268…_1_0_7", "room": 7 },
{ "event": 3, "obj": "tissuepaper_1f28299e…_1_0_7", "frames": [8717, 9116],
"surface": "chestofdrawers_10acc45c…_1_0_4", "room": 4 } ],
"counterexamples": [ // 규칙을 안 따른 사건 — 자격 판정에 쓴다
{ "event": 2, "surface": "diningtable_f113cf7f…_2_0_6" },
{ "event": 4, "surface": "sink_07e796f3…_1_0_5" } ],
"holdout": { // 규칙을 본 적 없는 물체에 적용
"obj": "mug_ac3a060b…_1_0_6",
"xyz": [0.870, 3.139, 0.804], "room": 6,
"moved_during_context": false, // ← 어떤 이벤트에도 안 나온다 (실측)
"observed": true, "seen_s": <측정 필요> },
"answers": [ {
"obj": "mug_ac3a060b…_1_0_6",
"to_class": "chestofdrawers",
"any_instance_ok": true, // ← restore와 갈리는 지점
"instances": [
{ "surface": "chestofdrawers_bcf35268…_1_0_7", "room": 7,
"xyz": [9.129, 3.801, 0.707], "reach_min": 0.500 },
{ "surface": "chestofdrawers_10acc45c…_1_0_4", "room": 4,
"xyz": [9.017, 8.507, 0.771], "reach_min": 0.650 } ],
"r_place": 0.15, "check_quat": false,
"d_xy_min": 8.3 // mug → 가장 가까운 서랍장
} ],
"distractors": [ // 채점 안 함. 오답 진단용 (실측 집계)
{ "surface": "stand_6bc09b7e…_1_0_7", "room": 7,
"src_count": 2, "dst_count": 0, "role": "source_only" },
{ "surface": "countertop_d89e05e8…_1_0_6", "room": 6,
"src_count": 1, "dst_count": 0, "role": "source_only" } ]
}
규칙 하나에 사건 3개가 들어간다. 편의 이벤트 예산이 4~5개이므로 두 번째 규칙을 심을 자리가 남지 않는다 — find가 편당 4.8행, restore가 1.9행을 뽑는 것과 구조가 다르다. 이것이 routine을 편당 최대 1행으로 묶는 구조적 상한이고, 총량 추정 ~90행(D1 40 · D2 30 · D3 20)의 근거다.
이 편을 그대로 쓸 수는 없다. 3/5는 “그런 경향”이지 규칙이 아니다 — 식탁 1회·세면대 1회라는 반례가 있어서, 정책이 “서랍장”을 못 맞혀도 틀렸다고 하기 어렵다. 실제 D1 편은 배치 4/4를 규칙으로 고정하고 홀드아웃을 따로 두도록 저작해야 한다. 그러면 그 편의 이벤트가 “같은 곳에 놓기”로 채워지므로 목적지 다양성이 떨어지고, 그 편에서 나오는 find/restore 행이 줄어든다. routine은 순증분이 아니다.
| 하위 | 규칙의 형태 | 붙일 편 | 판정 | 가장 큰 난점 |
|---|---|---|---|---|
| D1 배치 | “물건은 X 클래스 위에 둔다” | type1 | 홀드아웃이 X 인스턴스 반경 안 | 반례가 섞이면 규칙이 약해진다 (위 사례) |
| D2 절차 | “X 하기 전에 Y를 먼저 한다” | type2 — 이미 반복 유닛 구조 press ×3 · visit ×4 · put ×3 |
홀드아웃 유닛에서 순서가 지켜짐 | 순서 제약이 있는 task 조합이 필요 |
| D3 금지 | “여기엔 절대 두지 않는다” | type1 | 안 하는 것이 정답 (음성 판정) | “규칙을 지킨 것”과 “그냥 안 한 것”이 구분 안 된다 |
D2가 가장 싸다. type2는 이미 같은 유닛을 3~4회 반복하는 구조라 규칙을 새로 심을 필요 없이 순서 제약만 얹으면 된다. 반대로 D3가 가장 비싸다 — 음성 판정은 “예산 안에서 다른 유효한 행동을 했는가”라는 부가 조건 없이는 기권과 구분되지 않는다. 이건 공리 A5(기권도 정답)와 정면으로 부딪히므로 별도 설계가 필요하다.
traj.h5 — 프레임 단위 전 상태영상 프레임 수와 정확히 1:1이다 (val_144__2: 12,778 프레임 = 12,778 스텝 = mp4 nb_frames).
가변 길이 항목은 uint8 패딩 버퍼로 들어 있다.
traj_0/
obs/extra/
tracked_obj_pose (12778, 25, 7) float32 ← 추적 객체 25개의 pose 궤적
tracked_obj_pixels (12778, 25, 3) int32 ← 화면상 픽셀 위치 (가시성 판정)
robot_base_pose (12778, 7) float32
tcp_pose (12778, 7) float32
scene_joint_qpos (12778, 14) float32 ← fixture 개폐 상태
policy_phase (12778,) int64
policy_num_retries (12778,) int64
env_states (12778, 50000) uint8 ← 직렬화 버퍼
obs/agent/qpos,qvel (12778, 2000) uint8 ← 직렬화 버퍼
sensor_param/{exo_camera_1, exo_camera_2, wrist_camera}/
cam2world_gl (…,4,4) · extrinsic_cv (…,3,4) · intrinsic_cv (…,3,3) float64
env_states/articulations/panda (12778, 31) float32
rewards · success · terminated · truncated · fail (12778,)
sensor_data/ 그룹은 비어 있다 — 픽셀은 mp4로만 배포된다.
카메라 파라미터는 프레임마다 들어 있으므로 3D 재투영은 h5만으로 가능하다.
subtasks.json — 사건의 대본이벤트 하나가 nav → manip(pick) → carry → manip(place) 네 세그먼트로 쪼개져 있고,
각 세그먼트에 프레임 구간·템플릿·자연어 instruction·프리미티브 목록이 붙는다.
// type1/val_144__2 · subtasks[0]
{ "idx": 0, "kind": "pick_and_place", "frames": [0, 2082], "outcome": "ok",
"task_description": "Pick up the bowl from the dresser in the bedroom and place it in or on the armchair",
"slots": { "pickup_name":"bowl", "source":"dresser", "source_room":"bedroom",
"place_name":"armchair", "place_room":"bedroom" },
"segments": [
{ "kind":"nav", "frames":[ 0, 257], "template":"NavToObj", "prims":["nav"] },
{ "kind":"manip", "frames":[ 258, 559], "template":"Pick", "prims":["approach","grasp","lift"] },
{ "kind":"carry", "frames":[ 560, 1740], "template":"NavToObj", "prims":["carry","navcarry"] },
{ "kind":"manip", "frames":[1741, 2082], "template":"PickAndPlace(tail)", "prims":["place","release","retreat"] } ],
"settled_frame": 2107, "moved_m": 4.618, "on_floor": false, "lifted": true, "tags": ["shift"] }
| 편 | 스텝 | ev | 이벤트 | moved | outcome | tags |
|---|---|---|---|---|---|---|
| val_144__2 | 12778 | 0 | bowl: 침실 서랍장 → 안락의자 | 4.618 | ok | shift |
| 1 | remote: 침대 → 욕실 변기 | 8.342 | ok | – | ||
| 2 | remote: 변기 → 거실 식탁 | 7.056 | ok | relocate, twin_merge | ||
| 3 | bowl: 주방 조리대 → 거실 식탁 | 8.029 | ok | – | ||
| val_406__0 | 11437 | 0 | fork: 주방 조리대 → 거실 서랍장 | 7.475 | ok | – |
| 1 | vase: TV장 → 서랍장 | 1.508 | ok | shift | ||
| 2 | fork: 서랍장 → 주방 식탁 | 8.589 | ok | relocate, twin_merge | ||
| 3 | tissue box: TV장 → 침실 서랍장 | 4.694 | ok | – | ||
| 4 | bowl: 침실 서랍장 → 욕실 세면대 | 7.400 | ok | – | ||
| val_733__0 | 13409 | 0 | bowl: 주방 조리대 → 거실 카트 | 9.734 | failed_dropped | – |
| 1 | remote: TV장 → 침실 식탁 | 14.355 | ok | – | ||
| 2 | bowl: 카트 → TV장 | 0.000 | failed_no_place | relocate, twin_merge | ||
| 3 | remote: 침실 의자 → 욕실 변기 | 12.191 | ok | – | ||
| 4 | bottle: 주방 식탁 → 의자 | 1.227 | ok | shift |
수집 실패를 버리지 않고 채점 난이도를 낮춰서 살린다. 이 샘플에 실제 사례가 3건 있다.
val_733__0 ev0)수집 정책이 bowl을 카트로 옮기다 떨어뜨렸다(outcome: failed_dropped).
그런데 이 실패가 find:val_733__0:q00의 정답으로 그대로 살아 있다:
{ "obj": "bowl_6befd62f…_1_0_6",
"xyz": [3.029, 9.75, 0.045], ← z=4.5cm, 바닥
"room": null, "surface": null, ← 어느 가구 위도 아님
"on_floor": true, "misplaced": "on_floor",
"settled_frame": 2447, "last_seen_frame": 6949, "s_since_last_seen": 258.4,
"pickable": false, "pick_fail": {"ik/reach": 480}, ← IK가 480번 실패
"scoring": "navigate_only" } ← 집기 채점을 포기하고 접근만 채점
즉 "바닥에 떨어진 물건을 기억해서 그 앞까지 가는가"라는 질의로 재활용됐다.
misplaced: on_floor는 stats의 축으로도 노출된다(misplaced: {no: 20, on_floor: 1}).
val_144__2 q03·q05)soap bottle(z=1.047)과 spray bottle(z=1.064)은 처음부터 그 자리에 있던 distractor인데,
둘 다 pickable: false · pick_fail: {"ik/reach": 480}이라 navigate_only로 내려갔다.
실패 원인이 정책이 아니라 로봇 팔의 도달 한계(고정 베이스 8-D)라서, 집기를 요구하는 것 자체가 불공정하다.
채점 축이 섞여 있다. stats의 scoring: {navigate_only: 3, pick: 18}은
행이 아니라 정답 21개 기준이다(18+3=21). 러너가 행 단위로 집계하면 숫자가 안 맞는다.
val_733__0 ev2)failed_no_place, moved_m: 0.0. 물건이 아예 안 움직였으므로 d_xy 자격 하한 1.0 m를
통과하지 못하고, 이 이벤트에서는 restore 행이 나오지 않았다(val_733__0는 restore 2행뿐).
문서와 실물을 대조하면서 확인한 불일치·함정. 심각도 순.
restore/stats.json의 shares_find: {rows: 11, frac: 1.0} —
restore 11행 전부가 find 행과 정답을 공유한다. 두 가족 점수를 더하거나 평균 내면 같은 물체를 두 번 세는 셈이다.
행마다 shares_answer_with가 명시돼 있으니 보고 시 반드시 분리하거나 명시해야 한다.
29행 전부 oracle: null이고 stats.oracle = {run: 0, ok: null}.
예산(budget_steps 1500 / 5000 / 12000)이 오라클 실측이 아니라 상수로 박혀 있다는 뜻이다
— find는 18행 전부 1500, restore는 single 5000 / multi 12000 두 값뿐.
resume만 7/7 오라클이 채워져 있고, 그쪽 예산은 실측의 약 1.5~2배로 잡혀 있다(196→400, 553→829, 1722→2583).
contexts/README.md가 없는 파일을 가리킨다type2 전용으로 적힌 tasks.json·utterances.json이 실물에 없다.
내용은 subtasks.json의 tasks/cuts/stage와 질의 행의 commands[]에 있다.
restore/README.md의 탈락률 표기가 모순으로 읽힌다"자격 탈락률은 0.0%다 (merged_multi 4 · multi_capped 1)"인데 dropped.total은 5다.
merge·cap은 자격 탈락이 아니라 행 병합이라 분모에서 빠진 것으로 보이지만, 문장만 봐서는 알 수 없다.
find 쪽은 ambiguous 1 → 5.3%로 정상 계산된다.
eval/resume/에 README가 없고 stats 스키마도 다르다find·restore의 stats.json은 rows / answers / contexts / dropped / axes / by_context 구조인데,
resume은 n_query / n_context / n_dropped / by_r / by_type로 키 이름부터 다르다.
세 가족을 한 파서로 훑을 수 없다.
answers[].on_floor가 21개 중 11개에만 있다나머지 10개는 키 자체가 없다. a["on_floor"]로 접근하면 KeyError.
a.get("on_floor", False)로 읽거나 misplaced 필드를 쓰는 게 안전하다.
같은 정보를 담은 misplaced는 21/21 존재한다.
house·seed를 최상위에 든다find·restore에는 없다. 둘 다 query_id에서 파싱 가능하므로 기능상 문제는 없지만,
공통 봉투 바깥의 필드라 스키마 검증기를 짤 때 걸린다.
traj.h5에는 컷 이후 프레임이 그대로 들어 있다 —
context_frames = [f0, f1]이 닫힌 구간이고, 자르는 것은 읽는 쪽 책임이다.
특히 resume에서 컷 이후를 흘리면 그게 곧 정답 누설이다.(context, context_frames[1]). find·restore는 이 값이 자동으로 같아지므로
편당 1회 로드로 최대 10행(val_144__2: find 7 + restore 3)을 처리할 수 있다.tags는 채점에 쓰지 않는다. 분석 축 전용이다.r.