Index
2026-06-19 — Experiment

Scene-Mem — Recall mode + m3v2 sub-task log (S=100, 16/18)

memer-style `lang` 회상 질의 + m3 over-advance 보정 시도 · gemini 3종 × 4 메서드 + m3v2

TL;DR

16/18
Cells done
0.00
Recall slot (all cells)
.107
Best m3v2 (2.5-flash mem)
71
Tests green
~$300
Actual cost (vs $38 est)

📋 전체 row inspector (4,800+ rows, 16 셀 모두) — slot ✓/✗·action·place·memory snippet까지 모든 row 다 보이는 다크 테마 인스펙터.

1 배경 / 목적

이전 v2 cross-model S=100 결과(260528)에서 두 가지 한계:

  1. M3 텍스트 메모리가 강모델서 0으로 붕괴 (over-advance) — running notes에 "Placed X"를 적어 target+1 예측.
  2. "최종 goal" 차원 미측정 — 데이터셋의 eval_spec.tests[].lang ("Show me where X is placed.") 회상 질의가 진짜 final goal인데 활용 안 함.

이번 실험: (a) target=recall 모드 추가 (memer-style 전 episode 메모리 누적 → 끝 lang query 1 call), (b) m3v2 메서드 추가 (mechanical sub-task log로 self-narrative 차단).

shared walk 최적화: 한 시나리오의 3 test가 같은 walk 메모리 누적 결과를 공유. observe()를 final call에서 skip해서 pristine 메모리 상태 유지. naive(test마다 새 walk) 대비 API 호출 ~60% 절감.

2 구현 — 5 파일 변경 + 14 신규 테스트

recall mode 흐름

walk : 모든 segment (transit 포함) 순차 → 1 call/segment, memory 누적 (1회만/scn) final×N: 마지막 segment recent_window를 STATE로, lang query를 GOAL로 → N=len(tests) 호출, observe=False (memory state pristine) score: pred ↔ target_fine_subtask (같은 slot pipeline) 호출 수: ~14 calls/scn (walks ~11 + 3 finals) — naive의 ~40%

m3v2 sub-task log policy

_log: list[str] # step_out.raw 누적, step_out.memory 무시 observe(out, win) → log.append(out.raw) context_parts() → "SUB-TASKS YOU HAVE EXECUTED SO FAR ... 1. <raw1> 2. <raw2> ... The entries above are ALREADY emitted and considered done. For THIS step, emit the SINGLE next sub-task. Do not re-emit; do not skip ahead."

cache 격리 (memory vs recall 충돌 회피)

스모크 1회차에서 recall이 memory-mode 캐시를 잘못 hit해 wrong row 반환. Cache(target=...)로 subdir 분리:

memory: cache/<model>/<method>/<scn>/recall__<test_id>.json (기존 보존) recall: cache/<model>/<method>/<scn>/recall/recall__<test_id>.json (신규)

테스트

71 / 71 green (이전 57 + 신규 14): recall_target_info canonical/sentinel/per-test 독립, m3v2 log accumulation/memory-ignore/format, runner shared-walk 호출 카운트/observe-skip 불변/cache resume.

3 결과 (S=100, n=300/cell, 16/18 완성)

RECALL mode — slot / place / action

modelcontrolm1m2m3m3v2
gemini-2.5-flash .000/.02/.10 .000/.04/.04 .003/.02/.04 .000/.01/.12 .000/.08/.19
gemini-3-flash-preview .000/.12/.14 .003/.13/.03 .000/.24/.02 .000/.08/.24 — (cost limit)
gemini-3.5-flash .000/.13/.14 .000/.17/.00 .000/.25/.01 .000/.12/.21 .000/.15/.02
모든 셀 slot ≈ 0. action_acc가 약간 올라가는 건 모델이 memory에서 "place" 패턴을 흉내내는 결과 — 틀린 object/place로 (아래 §4.1).

MEMORY mode — m3v2 신규 컬럼

modelcontrolm1m2m3m3v2 (신규)
gemini-2.5-flash .040/.50/.04 .013/.42/.10 .033/.45/.12 .087/.59/.24 .107/.44/.27
gemini-3-flash-preview .060/.57/.07 .267/.67/.39 .337/.73/.41 .097/.59/.10 — (cost limit)
gemini-3.5-flash .000/.61/.00 .237/.62/.32 .290/.65/.36 .000/.59/.00 .003/.56/.02
m3v2 효과는 약모델에서만 미미하게 양성 (2.5-flash slot .087→.107 +22%). 강모델(3.5-flash) m3=0/m3v2=.003 — 사실상 동일하게 붕괴 (§4.2 참조).

3.5 결과 예시 — RECALL mode (메인 측정)

R-A. 회상 영상 — composite (placement event + recall call)

시각화 정직성 노트: 각 영상은 2개 phase로 구성됨:
  • Phase 1 — PLACEMENT EVENT (초록 테두리): 에피소드 중간 어느 시점에 실제 placement가 일어난 sub-window. 모델은 회상 시점에 이걸 직접 보지 못함 — 메모리가 잡아냈어야 할 사건.
  • Phase 2 — RECALL CALL (빨간 테두리, 에피소드 끝): 모델이 final call을 받은 시점. 모델이 실제로 본 8 STATE 프레임은 노란 STATE 표식으로 마킹 (마지막 segment 전체에 걸쳐 ~15초 간격으로 분포). 나머지 빨간 테두리 구간은 인간이 last_segment의 task 흐름 보라고 표시한 것일 뿐 모델 미관측.
회상 질문(steak/bowl/fish placement)이 Phase 1에서 일어나고, 모델은 Phase 2에서 8 STATE 프레임 + 메모리만 가지고 답해야 함. 영상이 보여주는 두 구간 사이 시간 간격이 바로 "memory가 다리를 놓아야 했던 거리".

gemini-3.5-flash / m3 (recall에서 action_acc 최고 .21). 모든 4 케이스에서 slot ✗.

scn 0016 · "Show me where the steak is placed."
P1 (~15s): steak이 freezer로 옮겨지는 placement event
P2 (~120s): ArrangeUtensils 마지막 task 중 8 STATE 마킹
PRED ✗: "Navigate to the fridge"
scn 0016 · "Show me where the bowl is placed."
P1: RestockBowls의 bowl→cabinet placement
P2: ArrangeUtensils 중 8 STATE 마킹
PRED ✗: "Navigate to the cabinet" (fixture 방향성은 잡힘)
scn 0016 · "Show me where the fish is placed."
P1: OvenBroilFish의 fish→oven bottom rack placement
P2: ArrangeUtensils 중 STATE 마킹
PRED ✗: "Navigate to the fridge" (위치도 틀림)
scn 0020 · "Show me where the steak is placed."
P1: MoveFridgeToFreezer의 steak placement (시나리오 처음)
P2: OpenOven (last_seg 짧음, ~9s)
PRED ✗: "Open the fridge door" (마지막 task가 OpenOven이라 따라감)

R-B. 같은 (scn, test)에서 5 메서드 응답 — gemini-3.5-flash

모든 메서드가 회상 질의를 next-action으로 응답. 메모리에 누적된 정보를 read out하는 행동을 어떤 메서드도 못 함. 차이는 "어디로 navigate"만.

scn / testLANG · GTcontrolm1m2m3m3v2
0016 / Steak LANG: Show me where the steak is placed.
GT: Place the steak on a shelf in the freezer
Navigate to the fridge Navigate to the fridge Navigate to the fridge Navigate to the fridge Navigate to the fridge
0016 / Bowl LANG: Show me where the bowl is placed.
GT: Place a bowl in the cabinet
Navigate to the counter Navigate to the counter Navigate to the cabinet Navigate to the cabinet Navigate to the counter
0016 / Fish LANG: Show me where the fish is placed.
GT: Place the fish on the bottom rack of the oven
Navigate to the fridge Navigate to the counter Navigate to the oven Navigate to the fridge Navigate to the fridge
0020 / Steak LANG: Show me where the steak is placed.
GT: Place the steak on a shelf in the freezer
The steak is placed inside the oven. Open the fridge door Open the fridge door Open the fridge door The steak is inside the oven
핵심 패턴: 아무도 회상 응답을 하지 않음. 메모리에 placement 정보가 있어도 모델은 STEP_SYSTEM의 "emit next sub-task" 지시를 따라 Navigate / Open 액션 출력. m3는 fixture는 약간 더 잘 맞춤(0016/Bowl/Fish에서 cabinet/oven 향함) — 메모리에서 추출은 하지만 회상 format으로 응답 안 함. recall slot_acc 0의 메커니즘 = prompt format 미스매치, 메모리 능력 부족 아님.

R-C. 같은 (scn, test)에서 5 메서드 응답 — gemini-2.5-flash (약모델 비교)

scn / testLANG · GT (요약)controlm1m2m3m3v2
0016 / Steak Steak → freezer Navigate to the fridge Navigate to the refrigerator Navigate to the fridge Navigate to the kitchen to locate the steak. Navigate to the fridge
0016 / Bowl Bowl → cabinet Navigate to the cabinet Navigate to the counter where the bowl is placed Navigate around the kitchen to find the bowl Navigate to the kitchen to find the bowl Navigate to the cabinet
0016 / Fish Fish → oven (bottom rack) Navigate to the fridge Navigate to the refrigerator Navigate to the counter Navigate to the fridge Navigate to the fridge
0020 / Steak Steak → freezer Open the fridge door Close the fridge door Navigate to the counter Navigate to the fridge Place the steak in the oven (act✓ obj✓ place✗)

약모델은 더 verbose하지만 패턴 동일. m3v2 0020/Steak가 유일하게 "Place ..." format 응답 (action_ok=True) — 그러나 fixture가 freezer 아닌 oven으로 틀림 (action_acc 부풀리기 케이스의 전형).

R-D. 메모리 누락 메커니즘 (M3의 self-overwrite 특성)

M3 메모리는 직전 step의 self-narrative만 carry-forward → 에피소드 끝까지 가면 마지막 segment 활동만 보존, earlier-segment의 placement 정보 손실.

scn 0006 / 3-flash-preview m3 / 모든 3 test에서 메모리 동일: "I have moved the onion and tangerine from the sink to the counter. I have also moved the bowl to the sink. I am now placing the cup in the sink." ← 마지막 segment(ClearSink) 활동만 → steak/bowl/fish 정보 0 Test 0 — "Show me where the steak..." PRED: "Navigate to the fridge" (메모리에 정보 없어서 추측) Test 1 — "Show me where the bowl..." PRED: "Place the cup in the sink" (메모리 last 활동 그대로 반복) Test 2 — "Show me where the fish..." PRED: "Navigate to the fridge"
M3 메모리는 self-overwrite 특성상 episode 끝에선 마지막 segment 활동만 남음. earlier-segment 회상이 본질적으로 불가능. m3v2의 mechanical log는 이 한계는 해결 (모든 step 보존)이지만, recall 응답 format 문제는 여전히 해결 못 함.

3.6 결과 예시 — MEMORY mode (보조, m3 vs m3v2 over-advance)

M-A. m3 vs m3v2 같은 row 페어

3.5-flash · combo_0006 / MoveFridgeToFreezerSAME pred 자체 메모리 차단해도 pred 동일

GT : Place the steak on a shelf in the freezer (tfi=1, K=4) m3 pred: "Close the freezer door" m3 mem : "Placed the steak in the freezer. Now closing the freezer door." m3v2 pred: "Close the freezer door"정확히 동일 m3v2 log : ['Place the steak in the freezer', 'Close the freezer door'] (scoring step = k=tfi=1)

3.5-flash · combo_0006 / RestockBowlsDIFFERENT pred 둘 다 over-advance, 다른 방향

GT : Place a bowl in the cabinet m3 pred: "Close the cabinet door" m3 mem : "Both bowls have been placed inside the cabinet. Closing the cabinet door." m3v2 pred: "Complete the task""task done" 선언 m3v2 log : 7 entries; last = ['Close the cabinet door', 'Complete the task']

3.5-flash · combo_0006 / OvenBroilFishDIFFERENT pred 둘 다 "rack 넣기"로 over-advance

GT : Place the fish on the bottom rack of the oven m3 pred: "Push the bottom rack back inside the oven" m3 mem : "Placed the fish on the bottom rack. Now pushing the rack back inside." m3v2 pred: "Slide the oven tray back inside" m3v2 log : 6 entries; last = ['Place the fish on the oven', 'Slide the oven tray back inside']

2.5-flash · combo_0006 / RestockBowls — m3v2가 "task complete" narrative로 누수

GT : Place a bowl in the cabinet m3 pred: "Open the cabinet door" m3 mem : "The robot needs to open the cabinet, then pick up the bowls..." m3v2 pred: "All bowls have been placed in the cabinet and the cabinet is closed, task complete." m3v2 log : 7 entries; last = ['Close the cabinet door', 'All bowls have been placed...'] ← log에 "task complete" narrative가 들어가버림 (mechanical log도 narrative 누수 가능)
패턴 요약: m3v2가 self-narrative 차단해도 pred 결과는 m3와 유사 (같거나 비슷한 over-advance). 약모델은 m3v2 log에 "task complete" 같은 narrative 응답이 들어가는 누수도 있음 — mechanical 보장이 100% 아님.

M-B. 오버레이 영상 — m3 vs m3v2 같은 시나리오

좌측 = 라이브 episode (agentview_left), 우측 = GOAL / GT / PRED / MEMORY 패널. 파란 테두리 = target sub-window(채점 시점) ±5초. 노란 STATE 표식 = 모델이 실제로 본 8 프레임 (cap_uniform across sub-window @ recent_window=8). 모두 gemini-3.5-flash.

시각화 정직성: memory mode에서는 모델 STATE 8 프레임이 sub-window(~9초) 안에 dense하게 분포 (~1초 간격) — recall mode와 달리 영상이 보여주는 구간과 STATE 영역이 거의 일치. 노란 STATE 표식이 약 1초 간격으로 깜빡임.

페어 1: scn 0016 MoveFridgeToFreezer (GT: Place the steak on a shelf in the freezer)

M3 (텍스트 narrative)
mem: "Placed the steak in the freezer. Now closing the freezer door."
pred ✗: "Close the freezer door"
M3v2 (mechanical log)
log: ['Place the steak in the freezer', 'Close the fridge door']
pred ✗: "Close the fridge door"

페어 2: scn 0020 RestockBowls (GT: Place a bowl in the cabinet)

M3 (텍스트 narrative)
mem: "Both bowls placed... Closing the cabinet door."
pred ✗: "Close the cabinet door"
M3v2 (mechanical log)
log: 7 entries · last = ['Close the cabinet door', 'Complete the task']
pred ✗: "Complete the task" (narrative 누수)
영상이 확인하는 핵심: 좌측 라이브 영상은 동일 시나리오 동일 시점(파란 테두리 = scoring step). m3와 m3v2 모두 STATE는 placement-직후 시점이라 "Place" 행동이 이미 끝난 것으로 보임. 메모리 표현이 다른데도 pred는 over-advance(target+1) 또는 narrative 누수로 비슷하게 떨어짐 — walk sub-window 위치가 결정적이라는 §4.2 finding을 영상으로 입증.

더 많은 row 예시 + 모든 16 셀 전체 데이터: 전체 row inspector.

4 핵심 발견 3가지

4.1 Recall mode 실패 — prompt format 미스매치

STEP_SYSTEM이 "emit next fine sub-task"이라 모델은 lang query를 회상 Q&A로 받지 않고 navigation/continuation action으로 응답.

LANG : "Show me where the steak is placed." GT : "Place the steak on a shelf in the freezer" PRED examples (gemini-3.5-flash, m3 recall): "Navigate to the fridge" "Place the cup in the sink" ← memory에서 '방금 한 일' 흉내 "Place the pot in the sink" ← memory: "Placed pan, carrying pot..."

메모리에 정답("steak in freezer")이 있어도 모델은 read out 안 하고 다음 행동 emit. action_acc 약간 상승은 memory의 "place" 패턴을 모방하기 때문(틀린 object/place).

해결 방향

회상 측정을 살리려면 (a) final call 전용 system prompt 분리 (v2 unified-prompt 원칙 깨야 함), (b) lang에 format 힌트 추가 ("Reply in 'Place the <object> in the <fixture>' format"), (c) StepOut 스키마에 answer_fixture 필드 추가. 현 prompt 디자인으로는 recall 측정 불가라는 점 자체가 finding.

4.2 M3 over-advance 진짜 원인 = STATE 위치 (메모리 표현 ❌)

같은 시나리오·test·모델로 m3 vs m3v2 직접 비교 (gemini-3.5-flash memory mode):

scn 0006 / MoveFridgeToFreezer / 3.5-flash: GT : Place the steak on a shelf in the freezer (target_fine_idx=1, K=4) m3 pred: "Close the freezer door" m3 mem : "Placed the steak in the freezer. Now closing the freezer door." m3v2 pred: "Close the freezer door"동일! m3v2 log : ['Place the steak in the freezer', 'Close the freezer door'] (scoring step = k=tfi=1, log entries from k=0과 k=1)

m3v2가 self-narrative를 차단했음에도 pred는 정확히 동일하게 over-advance. 이유:

over-advance는 메모리 표현 결함이 아니라 fine-walk sub-window 부정확성. m3v2 메커니즘은 깨끗하지만 이 walk 구조에서는 m3와 거의 같은 점수.

4.3 m3v2 효과는 약모델에서만 미미하게 양성

memory modem3 (기존)m3v2 (신규)변화
gemini-2.5-flash slot.087.107+22%
gemini-3.5-flash slot.000.003~0
gemini-3-flash-preview.097N/A

약모델은 텍스트 narrative 작성에 노이즈 → mechanical log가 도움. 강모델은 어차피 정확히 self-narrate 하므로 차이 없고, over-advance가 walk 구조 문제라 메모리 변경으로 못 잡음.

m3v2는 약모델 보조용으로만 가치. 강모델 비교에는 거의 무의미.

5 비용 — 추정 8× 빗나감

추정 (사전)실제
호출당 단가$0.0012~$0.011
16/18 셀 총 비용~$38~$300
원인 분석:
  • 신모델 단가: gemini-3.5-flash / 3-flash-preview가 2.5-flash 대비 5-10× 비싼 신모델. 옛 memory-mode S=100 평균($50)에서 직선 추정한 게 잘못.
  • 이미지 페이로드: 3-cam composite(1536×512) + 메모리 keyframe(M2 8장 누적) + recent_window(8장). 호출당 입력 토큰 추정보다 훨씬 큼.
  • shared-walk는 호출수 줄였지만 토큰 총량 안 줄어듦: 마지막 final call이 누적된 메모리 통째로 받음.

책임: 본런 전 1-2 시나리오 calibration 안 한 것. 향후 추정엔 보수적 마진 + sanity check 필수.

6 Next Steps

측정 메커니즘 개선이 메모리 메서드 비교보다 선결

  1. fine-walk sub-window 보정 (M3 over-advance 진짜 원인 처리)
    • A. target_fine_idx-1 위치를 채점 step으로 (sub-window 한 칸 일찍)
    • B. 채점 target±1 허용 후 두 지표 동시 보고
    • C. fine별 정확한 프레임 경계 데이터 추가 요청 → 비율분할 폐기
  2. Recall prompt 재설계 (lang 측정 살리려면)
    • final call 전용 system prompt OR StepOut 스키마 확장 (answer_fixture 필드)
    • lang에 format 힌트 ("Reply in 'Place the <object> in the <fixture>'")
  3. 3-flash-preview m3v2 미완 셀 처리
    • Letsur 한도 갱신 (~$33 추정)
    • 또는 16/18 final로 마무리 (이 리포트가 그 결론)

비용 관리 개선

다음 본런 전 단가 calibration 필수: 1 시나리오 × 모델별 × 메서드 → 평균 단가 측정 → 보수 마진 1.5× 적용. 신모델은 가설 굳혀진 뒤 마지막에만 (gemini-2.5-flash로 prototype 검증 → 후속).

7 재현 / 참고

# Recall mode 실행 OPENAI_API_KEY=<letsur> OPENAI_BASE_URL=https://gw.letsur.ai/v1 \ python -m scene_mem_api.runner \ --model gemini-2.5-flash --method m3v2 --target recall \ --stage full --limit 100 # Memory mode m3v2 python -m scene_mem_api.runner \ --model gemini-2.5-flash --method m3v2 --target memory \ --stage full --limit 100 # 결과 파일 results/<model>__<method>__full__recall.json # recall mode results/<model>__<method>__full.json # memory mode # 캐시 (격리) cache/<model>/<method>/<scn>/recall/... # recall mode cache/<model>/<method>/<scn>/... # memory mode