Index
2026-06-02 — Progress Snapshot

Scene-Mem API Track — v2 Snapshot

RoboCasa 858 시나리오 · hierarchical next-subtask · 메모리 4종 × gemini 3세대 · S=100 완료

TL;DR

.34
Best slot (M2)
300
n / cell
12
cells (3×4)
0
parse_fail
57
tests green

1 Goal · Formulation (v2)

Goal: RoboCasa 기반 scene-memory 벤치마크(/home/nas_main/taewoongkang/Dataset/scene-mem-benchmark, 858 시나리오)에서 "로봇이 ~8분 영상으로 여러 task 수행 후, 메모리를 반영해 올바른 fine sub-task를 내보내는 능력"을 측정. 로드맵: API 트랙Open-VLM 튜닝ours. 현재 API 트랙.

v2 Hierarchical Next-Subtask Policy

모든 API call이 동일한 default 프롬프트(STEP_SYSTEM + step_user_text(goal) + STATE 이미지 + 메서드 메모리). 일관성을 위해 메모리는 "여기 메모리야"라고 텍스트로 노출하지 않고 메서드의 입력 구조에 내장. 출력 = StepOut{action, object, place, raw, keyframe_positions, memory}.

walk: oracle 세그먼트 순회 → 타깃 세그먼트는 K-분할 fine-step walk → 타깃 step(target_fine_idx)에서 중단 score: 예측 sub-task ↔ GT target_fine_subtask · slot match (action ∧ object ∧ place) templates: configs/templates.json + aliases.json — 150-scn 샘플에서 통계적 induction ACTIONS = [navigate, pick, place, open, close, other] (core5 92.4% coverage)
왜 v2인가: 초기 형식은 메서드마다 다른 프롬프트를 썼고 메모리를 사용자 텍스트로 노출했음 → 메서드 간 공정 비교 불가. v2는 프롬프트 통일 + 메모리를 입력 구조에 내장하여 "메모리 표현"의 효과만 분리 측정.

2 메모리 메서드 (이 부분만 분기, 같은 프롬프트)

control
장기 메모리 없음. 현재창(recent_window=8)만 STATE로. 바닥 baseline.
M1 Rule-based subsample
전체 history 균일 sub-sample 이미지(m1_history=8). naive but cheap. 중간 수준 향상.
M2 MemER 시각 keyframe ⭐
arXiv 2510.20328. 모델이 매 step keyframe_positions emit → 결정적 1D single-linkage 클러스터링(d=5, median-low) → last-memory_length=8 유지.
M3 PI MEM 텍스트 running notes
PI π0.6 Mem.pdf §III-B. 모델이 매 step memory 필드에 압축 self-notes 출력 → 다음 step에 "Prior notes:" prefix로 carry-forward.

공통 입력

Cameras
3 (L/R/eye_in_hand)
Composite
1536×512 세로
Sampling
2 Hz
Recent window
8 frames
JPEG quality
85
Max side
512 px

3 Setup · 인프라

LLM Access

직접 OpenAI / Gemini 키 없음 → Letsur OpenAI-호환 게이트웨이. 모델명은 provider 공식 ID. OpenAI gpt-*는 content-safety로 robocasa 이미지 차단 → 제외. 단가는 provider 정가 동일.

OPENAI_BASE_URL=https://gw.letsur.ai/v1 OPENAI_API_KEY=<~/envs/api_keys.txt 'Letsur:' value> models tested: gemini-2.5-flash · gemini-3-flash-preview · gemini-3.5-flash methods: control / m1 / m2 / m3

코드 베이스

Branch
main (clean)
Tests
57 / 57 green
try-except 수
0 (rule)
Spec
v2 design doc

핵심 파일

scene_mem_api/runner.py # 오케스트레이션 (autoregressive, resume, cache) scene_mem_api/policy_factory.py + memory/*.py # 메서드 4종 scene_mem_api/prompts.py # STEP_SYSTEM + step_user_text (통합) scene_mem_api/templates.py # parse_subtask + slot 정규화 scene_mem_api/dataset.py # resolve_target / target_fine_info scene_mem_api/metrics.py # slot/exact/action_ok/place_ok scene_mem_api/cache.py # per-test recall (memory는 recall row에 저장) scene_mem_api/viz.py # HTML 리포트 + 영상 임베드 (target-frame seek) docs/specs/2026-05-19-scene-mem-api-track-design-v2.md # 정본 설계서

실행 커맨드

OPENAI_API_KEY=<letsur> OPENAI_BASE_URL=https://gw.letsur.ai/v1 \ python -m scene_mem_api.runner \ --model gemini-3-flash-preview \ --method m2 \ --stage full --limit 100 # 주의: --stage dev 는 40 cap 먼저 적용. S 조절은 --stage full --limit S

4 Cross-model 결과 (S=100, n=300/cell)

3 시나리오/시나리오, 100 시나리오 → 300 test/cell. compound 2건은 ambiguous로 graceful skip. parse_fail = 0.

채점 방식 (Scoring)

모든 cell은 동일한 채점기(scene_mem_api/metrics.py + templates.py)를 통과 → 셀당 n=300 평균. 한 step 채점 흐름:

pred_subtask ─┐ ├─→ parse_subtask() ─→ (action, object, place) gt_subtask ──┘ ↓ 슬롯별 정규화·비교 → 3가지 지표

parse_subtask는 5개 정규식(navigate / pick / place / open / close)으로 fine sub-task 문자열을 (action, object, place) 3-슬롯으로 분해. 매칭 실패하거나 멀티-클로즈("X and then Y") 등 잡음이면 action="other", object=place=None. 정규화: lowercase → 관사 제거 → 보수적 단수화 → aliases.json 명시 alias만 치환. place는 중첩구("shelf in the freezer" → "freezer")만 축약.

metric계산식의미
action_accp.action == g.action동사(navigate/pick/place/open/close/other) 일치. 가장 느슨
place_accp.place == g.place (정규화 후)장소 fixture 일치. None==None도 일치(navigate/open/close엔 object 없음)
slot_accaction_ok ∧ place_ok ∧ obj_ok3슬롯 전부 일치. 가장 엄격, 메인 지표
(참고) exact_accpred.strip().lower() == gt.strip().lower()원문 문자열 통째 일치. 조항/어순 차이도 fail
왜 3개 지표를 같이 보고하는가:
  • exact_acc만: "Place a bowl..." vs "Place the bowl..." 같은 사소한 조항 차이도 0 → 실력이 노이즈에 묻힘
  • slot_acc: 정규화·alias 후 슬롯 비교. 의미적 동치 인정, 메인 지표
  • action / place: slot의 부분 신호. 분해하면 "동사는 맞췄는데 object에서 떨어졌나" 진단 가능
place 상식 prior 주의: place_acc는 control도 .50–.61로 높음. 모델이 STATE를 거의 안 보고도 robocasa 환경의 default 가구(cabinet / freezer / sink 등)에서 자주 맞추기 때문. 메모리 효과는 action / slot으로 보는 게 더 깨끗(control action ≤ .07).

예: gemini-3-flash-preview / m2 = .34 / .73 / .41 = "300개 중 동사 41%, 장소 73%, 세 슬롯 모두 34% 맞음" (slot ≤ min(action, place)).

parse_subtask — 6개 액션 grammar (templates.json, 통계 induction)

150-scn 샘플 fine 12,486건 분석에서 통계적으로 골라진 core5 grammar (T1–T5)가 92.4% 커버. 나머지 7.6%는 T6 "other"로 폴백되어 slot에서 자동 miss.

T1 navigate : ^Navigate to (?:the|a|an) (?P<place>.+?)\.?$ T2 pick : ^Pick up (?:the|a|an) (?P<object>.+?) from (?:the|a|an) (?P<place>.+?)\.?$ T3 place : ^Place (?:the|a|an) (?P<object>.+?) (?:in|on|into|onto|inside) (?:the|a|an) (?P<place>.+?)\.?$ T4 open : ^Open (?:the|a|an) (?P<place>.+?) door[\w ]*\.?$ T5 close : ^Close (?:the|a|an) (?P<place>.+?) door[\w ]*\.?$ T6 other : 5개 모두 실패 → action='other', object=place=None, raw=원문 그대로

슬롯 정규화 (normalize) — 5단계 순차

① lowercase + 양끝 strip ② 선두 관사 제거 : "the cabinet" → "cabinet" ③ 내부 공백 정리 : "the freezer" → "freezer" ④ 보수적 단수화 : "bowls" → "bowl" ("glass" 같은 -ss 끝 단어는 제외) ⑤ aliases.json 명시 lookup : refrigerator → fridge, freezer compartment → freezer, stovetop → stove, countertop → counter, trash can → trash, garbage can → trash, counter top → counter

의도된 비-병합: toaster oven ≠ oven, dining counter ≠ counter, bottom rack ≠ oven 등 의미상 다른 fixture는 합치지 않음 — 모델이 "toaster oven"이라 해야 할 곳에 "oven"이라 쓰면 slot miss (의도된 엄격성).

place 슬롯 추가 — _reduce_place (중첩구 축약)

"Place the steak on a shelf in the freezer" 같은 중첩 위치구를 마지막 fixture로 축약. 의미 동치 인정용.

_NEST = ^.*\b(in|on|of|inside|into|onto) (the|a|an) ([\w ]+)$ "shelf in the freezer" → "freezer" ✓ 축약 "bottom rack of the oven" → "oven" ✓ 축약 "counter" → "counter" ✗ 변화 없음 "dining counter" → "dining counter" ✗ (nest 매치 안 됨, 보존)

워크드 예시 — 실제 S=100 row 채점 (시나리오 0016, M2)

GT : "Place the steak on a shelf in the freezer" pred: "Place the steak in the freezer" parse_subtask(GT): T3 place 매치 → object='steak', place='shelf in the freezer' _reduce_place: 'shelf in the freezer' → 'freezer' (NEST 매치) StepOut(action='place', object='steak', place='freezer') parse_subtask(pred): T3 place 매치 → object='steak', place='freezer' StepOut(action='place', object='steak', place='freezer') score: action_ok = 'place' == 'place' → True place_ok = 'freezer' == 'freezer' → True obj_ok = 'steak' == 'steak' → True slot_match = True ∧ True ∧ True → True exact = "place the steak in the freezer" == "place the steak on a shelf in the freezer" → False (어순/조사 차이로 fail이지만 slot은 통과 — 의도)

같은 시나리오 M3 (over-advance):

GT : "Place the steak on a shelf in the freezer" pred: "Close the freezer door" parse(GT) : action='place', object='steak', place='freezer' parse(pred): action='close', object=None, place='freezer' ← T5 close 매치 action_ok = 'place' vs 'close' → False place_ok = 'freezer' vs 'freezer' → True ← 우연히 같은 place! obj_ok = 'steak' vs None → False slot_match = False / exact = False
이 패턴이 셀 수치에 직접 반영: M3 (3-flash-preview) .10 / .59 / .10 = slot .10 / place .59 / action .10. place는 over-advance pred조차 우연히 같은 fixture("freezer")를 자주 가리키므로 ~.59까지 가지만, action과 slot은 .10에 머묾. 메모리 효과의 진짜 차이는 action / slot 컬럼에 있음.

summary 집계 (runner.py:_summary)

slot_acc = Σ(slot_match) / n # n=300, 분모는 status 무관 전체 place_acc = Σ(place_ok) / n action_acc = Σ(action_ok) / n exact_acc = Σ(exact) / n parse_fail = count(status=='parse_fail') no_target_frames = count(status=='no_target_frames') ambiguous_target = count(status=='ambiguous_target')

중요: parse_fail / no_target_frames / ambiguous_target 도 분모에 포함됨. 그 row는 모든 슬롯 False로 미리 채워지므로 자동 miss로 평균에 weight. S=100 실험에서 parse_fail=0, no_target_frames=0, ambiguous_target=2(compound 테스트, 평균에 자동 miss로 -0.007 영향).

알려진 한계 6가지

  1. place 상식 prior 부풀림 — control도 .50–.61. fixture 집합이 좁아 STATE 없이도 task instruction에서 추측 가능. 메모리 효과 판단은 action / slot 컬럼 우선.
  2. obj_ok가 row에 저장 안 됨 — slot 계산에만 쓰이고 단독 컬럼 없음. M3 over-advance가 "object는 맞췄는데 action만 틀린" 비율은 별도 재계산 패스 필요.
  3. proportional split의 fine 경계 부정확 — 데이터에 fine별 프레임 경계 부재. tfi step의 STATE가 실제 그 sub-task 수행 시점과 어긋나 모델이 "이미 끝난" 다음 step을 emit하면 slot miss.
  4. 데이터 tfi 버그 — RestockBowls 류 일부 test에서 target_fine_idx(인덱스)와 target_fine_subtask(문자열)가 불일치. 사용자가 "tfi가 정본"으로 결정 → 일부 row가 한 칸 어긋난 평가.
  5. other 폴백의 누수 — "Slide the rack back inside" 같은 자유형은 action='other' → 강제 slot miss. STEP_SYSTEM이 grammar strict 요구하므로 실용 영향은 작음.
  6. _noisy 필터 false-negative — "Open the cabinet door and grab a bowl"이 T4 open으로 매치되어 place='cabinet'로 잘못 분류. trailing clause를 door[\w ]*$가 흡수해서. 실데이터에서 GT는 단일-액션이라 영향 미미하지만 모델 출력에선 발생 가능.
상세 분석 문서: claude/260616/analysis-metric_definitions.md (10 섹션, 각 정규식·정규화 단계별 검증 결과·워크드 예시·6 한계 상세).

slot / place / action accuracy

model control m1 m2 ⭐ m3
gemini-2.5-flash .04 / .50 / .04 .01 / .42 / .10 .03 / .45 / .12 .09 / .59 / .24
gemini-3-flash-preview .06 / .57 / .07 .27 / .67 / .39 .34 / .73 / .41 .10 / .59 / .10
gemini-3.5-flash .00 / .61 / .00 .24 / .62 / .32 .29 / .65 / .36 .00 / .59 / .00

exact accuracy (전체 sub-task 문자열 일치)

modelcontrolm1m2m3
gemini-2.5-flash.020.003.007.017
gemini-3-flash-preview.013.043.060.020
gemini-3.5-flash.000.057.100.000
발견 1 · 벤치가 메모리를 변별함 — control은 어디서나 바닥(slot ≤ .06, action ≤ .07). place만 상식만으로 ~.5–.6. 메모리 추가 시 slot 큰 향상.
발견 2 · M2(시각 keyframe)가 최고 메모리 표현 — 신모델 전반 m2 > m1 > control. exact도 m2 최고(3.5-flash .100).
발견 3 · M3(텍스트)는 모델 의존·불안정 — 약모델(2.5-flash) slot .09로 최고이나 강모델서 .10 → .00으로 붕괴. 원인은 §5에서 분석.
발견 4 · 세대 점프 — m2 slot: 2.5-flash .03 → 3-flash-preview .34 (11×). 메모리 활용 능력 자체가 신모델에서 극적으로 향상.

5 M3 Over-advance 분석 (핵심 발견)

현상: 강모델(gemini-3-flash-preview / 3.5-flash)이 M3에서 slot ~0, action ~0으로 붕괴. control보다도 낮음.

근본 원인: self-memory와 next-subtask 예측의 상호작용

강한 모델은 매 step memory 필드에 "이번 step에서 무엇을 했다"를 압축해서 기록함. 다음 step에 그 메모리가 "Prior notes (your own running notes):\n..."으로 carry-forward되면, 모델은 "방금 한 행동은 이미 완료된 것"으로 간주하고 다음 다음 행동을 예측함 = over-advance.

비율-분할 STATE 근사(타깃 위치 부정확) + 자체 메모리의 강한 anchor가 결합 → 타깃 step에서 target+1 행동 예측.

실제 예시 (gemini-3.5-flash, M3)

memory: "Placed the steak in the freezer. Closed the freezer door." pred: "navigate to the trash" ← target+2 (이미 둘 다 끝난 줄 알고 다음 task) gt: "place the steak in the freezer" ← 사실은 아직 target step

왜 M2는 멀쩡한가

M2는 시각 keyframe만 모음. 모델이 "한 일"을 텍스트 단언으로 self-write하지 않으므로 over-advance bias 없음. 그저 "여기 과거 중요 프레임들 있어, 현재 STATE 보고 다음 행동 뭐가 맞아"가 됨.

중요 함의: M3 결과는 "PI MEM이 안 좋다"가 아니라 "self-narrating memory와 next-subtask 예측은 본질적으로 충돌한다"는 것. 측정 메커니즘을 고치면 M3는 다시 경쟁할 가능성. 이것이 next의 동기.

6 증거 — 영상

읽는 법: 영상은 agentview_left 카메라(에피소드 전체 ~8분 1ep). 같은 시나리오를 M2/M3에 동일하게 입력했을 때 GT 타깃 step에서 무엇을 예측했는지 + (M3는) 누적된 self-memory 텍스트도 함께 표시. 모두 gemini-3-flash-preview S=100 셋에서 발췌.

6.1 같은 시나리오 — M2 ✓ vs M3 ✗ (over-advance 메커니즘)

(a) M2 — keyframe FIFO · combo_002_L29_S48_0016 / MoveFridgeToFreezer
GT   : Place the steak on a shelf in the freezer
M2 pred ✓: Place the steak in the freezer (slot ✓)
시각 keyframe만 보고 현재 STATE에서 다음 fine-step을 정확히 예측. self-narrative 없음 → over-advance 없음.
(b) M3 — text running notes · 같은 시나리오 · 같은 시점
memory: "I have successfully moved the steak from the fridge to a shelf in the freezer. Both the fridge and freezer doors are currently open. I am now proceeding to close the freezer door, after which I will close the fridge door..."
M3 pred ✗: Close the freezer door (slot ✗ = target+1)
모델 자신의 노트에 타깃을 "successfully moved"로 단정 → 같은 타깃 step에서 다음다음 행동(close)을 예측. 같은 STATE인데도.
같은 시나리오·같은 모델·같은 STATE인데 (a)가 ✓이고 (b)가 ✗인 차이는 모델 실력이 아니라 메모리 표현. M3의 self-narrating memory가 target step에서 "이미 완료"를 단언해 over-advance를 유발한다는 가설을 같은 시나리오 비교로 시각적으로 입증.

6.2 M3 over-advance 패턴 — 일관된 4 케이스

memory 텍스트와 pred를 함께 보면 패턴이 동일하게 반복됨: "placed/successfully" → pred = "close/slide" (target+1).

0006 / MoveFridgeToFreezer
"...successfully picked up the steak from the fridge and placed it on a shelf in the freezer. Now I will close the freezer door..."
GT   : Place the steak on a shelf in the freezer
pred ✗: Close the freezer door
0020 / RestockBowls
"The cabinet was opened, and both bowls were placed inside. I am now closing the cabinet door to complete the goal."
GT   : Place a bowl in the cabinet
pred ✗: Close the cabinet door
0018 / OvenBroilFish
"Successfully placed the fish on the extended bottom rack of the oven. Next, I need to push the rack back inside..."
GT   : Place the fish on the bottom rack of the oven
pred ✗: Slide the oven rack back inside the oven
0023 / MoveFridgeToFreezer
"I have successfully placed the steak on the freezer shelf. Now I need to close the freezer door..."
GT   : Place the steak on a shelf in the freezer
pred ✗: Close the freezer door
4 시나리오·2 task 유형 모두 동일 시그니처: 자체 메모리 "successfully placed/moved ..." → pred = "Close ..." / "Slide ..." (정답 step보다 한 칸 앞). M3 메서드의 메커니즘적 결함이지 우연한 노이즈가 아님을 영상으로 확정.

7 미해결 한계

① [NEXT] M3 over-advance 보정 — 사용자 승인됨

3가지 옵션 (서로 배타 아님):

  • (a) 채점 타깃±1 허용 — 평가만 관대 처리. 메커니즘 안 고침.
  • (b) M3 프롬프트 제약 — "이미 수행한 행동은 기록·예측 금지, 아직 안 한 다음 행동만". 권장 (근본 교정)
  • (c) STATE를 타깃 직전으로 — fine 경계 부정확성 완화.

제안: (b) 본조치 + (a) 보조 진단 지표 병행.

② 데이터 target_fine_idx 버그 — 사용자 수정 대기

RestockBowls 류 일부 test에서 tfi 위치와 target_fine_subtask 문자열이 불일치. 사용자가 "tfi가 정본 (버그는 데이터)"로 결정 → 데이터 측 수정 필요. 일부 test 천장 제약.

③ slot / exact 전반 낮음 (.0–.34)

K-way 비율분할로 fine sub-task 경계 부정확. fine별 프레임 경계 데이터가 있으면 정밀화 가능.

④ 규모 확장

현재 S=100 (앞 100개, 결정적 샘플). val split 정의 → full 858. claude-haiku는 비용 감안해 추가 검토 (sonnet full ~$2.8K, gemini full ~$540).

8 Next Step

실행 계획 (사용자 승인됨)

  1. M3 over-advance 옵션 결정 — 위 (a)(b)(c) 중 선택. 제 권장은 (b) 본조치 + (a) 보조 진단.
  2. 구현scene_mem_api/memory/m3.py의 carry-forward 프롬프트 prefix에 "이미 한 것 기록·예측 금지" 제약 추가. 또는 STEP_SYSTEM에 M3 전용 메모리 가이드 절. subagent-driven (implementer → spec review → quality review).
  3. 재측정 — gemini 3종 × m3만 재실행 (m2/m1/control은 변경 없으므로 캐시 재사용). S=100 → 같은 셋.
  4. 비교 — m3 slot 약모델에서 유지되고 강모델서 회복하는지 확인. M2와 공정 비교.
예상 비용 (m3 재측정만)
~$15 (gemini 3종 × S=100)
예상 시간
~3–4h (resume)
차단 요인
옵션 (a)/(b)/(c) 선택

9 Cost · Related

비용 모델 (Letsur = provider 정가)

scalegemini 3종 4메서드claude-sonnet 4메서드
S=100 (현재)~$50~$330
S=858 (full)~$540~$2.8K

Related

MemER paper
arXiv 2510.20328
PI MEM paper
pi.website/download/Mem.pdf
Dataset source
동료 fork (junhahyung/scene-mem/robocasa)
후속 로드맵
Open-VLM tuning → ours

주요 산출물