Index
2026-05-10 — Plan

ApiMem Tool-Calling + CoTracker3 Visual Memory 설계

memer / robomme_policy_learning | VideoUnmaskSwap shell-game 공략 — P0~P5 로드맵

TL;DR

3
Visual Tools
5
Phases
8
Max tool calls/tick
50
Target Episodes

1 배경 / 목적

현황: ApiMem BinFill 8-run 종합 결론 (260504)

BinFill에서 flash-lite / pro × 1-call / 2-step × bbox-prompt 모든 조합이 4~17% SR noise 범위. Pipeline robustify (0 error/parse/loop) 완료 후에도 SR 불변 → detection bottleneck 아님. 남은 ~56pp 격차 가설: (a) wording mismatch, (b) coord precision sub-pixel, (c) timing.

Hypothesis (b) 검증용 Hybrid πHL (job 9951, BinFill, flash-lite + LoRA coord swap) 결과: SR 12% (+4pp vs ApiMem baseline 8%). Coord 부분 기여하지만 LoRA 64%와 52pp 격차 유지.

새로운 각도: Static-Frame-Blindness 가설

BinFill 가설 (a)(b)(c)와 직교하는 전혀 다른 문제가 있다. Unmask/Swap 류 task는 정의상 정적 프레임만으로 풀 수 없다:

원리적 한계: 초기 cube 위치를 인지해도, swap 이후 "어느 container가 원래 빨간 cube를 덮고 있는지"는 motion을 추적하지 않으면 알 수 없다. text-only mt에 매 tick 좌표 변화를 적어야 하는데 비현실적.

VideoUnmaskSwap 특히 타이트한 swap loop 포함 → ApiMem의 구조적 실패 가능성 높음. 이 설계가 "시각적 메모리"를 model에게 직접 쥐여주는 접근으로 공략.

관련 선행 연구와의 차이

방법메모리 유형이 설계와 차이
MemER (Anthropic)raw frame keyframes, fixed selectionmodel이 annotated tool output만 저장. 능동 선택.
PI Mem (Torne et al.)text-only mtvisual annotated layer 추가 (text mt 유지)
Set-of-Marks (SoM)단일 정적 annotated frametemporal tracking으로 확장 (CoTracker3)

2 작업 내용 (설계)

세 가지 Visual Tool 카탈로그

annotate_objects(target_labels?: list[str]) → 현재 프레임에서 detection → Pillow bbox + colored label draw → {image_b64, objects: [{label, box_2d, color}]} 색상 매핑: label에 'red'/'blue'/'green' substring → 해당 색, 그 외 yellow track_objects(from_keyframe_idx: int, target_labels: list[str], draw_trail: bool=True) → saved_keyframes[idx].objects 에서 5×5 grid query points 생성 → frame_buffer[keyframe_t:current_t] 슬라이스 → CoTracker3 offline → visible 점 median±1.5*MAD 으로 새 bbox 재구성 → {image_b64, objects: [{label, box_2d_now, lost}]} save_keyframe(caption: str) → _last_tool_image (직전 annotate/track 결과) → keyframes deque push (maxlen=5 FIFO) → {saved, keyframe_idx, n_keyframes} → 저장 없으면 error "no recent annotate/track output"

멀티-턴 Protocol (per K-tick)

[user message] current_frame + saved keyframe images (자동 첨부) + task_goal + mt + last_subgoal text + "tools available, emit final JSON when ready" [assistant] → tool_call(annotate_objects) OR tool_call(track_objects) OR tool_call(save_keyframe) OR final JSON {memory_summary, subgoal} [hard cap: 8 tool calls/tick] 초과 시: "budget exhausted, emit JSON now" → 그래도 tool call → last_subgoal fallback

메모리 모델 변경

항목기존이후
text memorymt: str그대로 유지
visual memory없음keyframes: deque[Keyframe] (maxlen=5)
keyframe 내용-annotated/tracked PIL image + objects + frame_buffer_idx_at_save
매 reasoning call 첨부current frame 1장current frame + 저장된 keyframe images 전부 auto-attach

수정 파일 목록

신규 생성: api_mem/tools.py — Pillow draw + ToolDispatcher (annotate/track/save) api_mem/tracker.py — CoTrackerWrapper singleton (lazy GPU init) api_mem/tool_specs.py — OpenAI tools schema JSON (3 tools) tests/api_mem/test_tools.py, test_tracker.py scripts/analyze_tool_calling.py 수정: api_mem/api.py — get_subgoal → multi-turn loop + _get_subgoal_with_tools api_mem/prompts/base.py — TOOL_USE_GUIDANCE 추가, GROUNDED_COORD_INFO 축약 subgoal_predictor.py — full _frame_buffer → get_subgoal(frames, full_frame_buffer) eval.py:Args — api_mem_tools_enabled, max_tool_calls, max_keyframes run_api_mem_one_episode.sh — 7번째 인자 TOOLS (0/1)

구현 Phase 로드맵

Phase내용기간DoD
P0CoTracker3 install + 1-ep replay sanity (login GPU)0.5dmp4 bbox tracking 눈검사 OK + GPU mem 측정
P1tools.py + tracker.py + unit tests 4개1dpytest PASS; sample annotated PNG 4장
P2api.py multi-turn 리팩터 (OpenAI tools= API)1.5dBinFill ep0 dry run: tool call → final JSON 확인
P3prompts/base.py TOOL_USE_GUIDANCE 추가0.5dprompt smoke import test PASS
P4VideoUnmaskSwap 50 ep sweep 제출0.5d50 ep 완료, log.json 생성
P5analyze_tool_calling.py + SR 보고0.5dtool/tick 분포 + SR vs baseline 비교

3 결과 (예상 시나리오 — 실험 전)

VideoUnmaskSwap SR 결과해석다음 액션
30%+tool calling이 swap tracking 문제를 실제로 해결. static-frame-blindness 가설 지지ButtonUnmaskSwap, VideoUnmask, VideoRepick 등 swap 변종 전체 확장
8~30%부분 기여 — prompt/tracking 튜닝 여지tool 호출 빈도, trail 옵션, query point density 변경 후 재실험
<8%tool calling 자체로는 부족wording/timing 가설로 이동, 또는 detection-only annotate(CoTracker 없이) 경량화 후 재시도

비용 예상 (LetSur flash-lite)

평균 5~7 tool calls/K-tick × ~25 K-tick/ep × 50 ep ≈ 비용 ~현 1-shot baseline의 3×. 수용 가능.

측정할 지표

- 전체 SR (50 ep) - 평균 tool calls / K-tick (mean, p50, p95) - save_keyframe 호출 빈도 (visual memory 적극 활용 여부) - track_objects 호출 시점 분포 (swap 타이밍에 맞춰 부르는지) - per-episode failure mode: ① tool 안 부르고 final JSON 직진 ② tracker lost (visible < 3) ③ 옳은 keyframe인데 wrong subgoal ④ pi0.5 alignment 문제

4 Takeaway

설계 의미

text-only mt 위에 visual annotated memory layer를 얹은 첫 시도. 기존 PI-Mem (language-only)과 MemER (raw keyframe)의 agentic hybrid — model이 무엇을 annotate/track할지 능동적으로 결정한다.

Shell-game (hidden-state) 류 task는 zero-shot VLM의 알려진 약점이다. 이 설계가 제대로 작동하면, swap-variant 전반(VideoUnmaskSwap, ButtonUnmaskSwap, VideoRepick 등)의 SR을 끌어올리는 일반 lever가 된다.

만약 실패하더라도 "CoTracker3 visual tracking이 robot manipulation에서 유용한가"를 처음으로 직접 실측하는 실험이므로, 부정 결과도 프로젝트 전략에 중요한 정보다.

5 Next Steps

리스크 — CoTracker GPU footprint

CoTracker3 ~6 GB. SAPIEN sim (~2-3 GB)과 같은 GPU에서 공존 가능 여부 P0 sanity에서 측정 필수. NG면 SERVER_GPU idle time 공유 또는 별도 GPU 요청.

리스크 — 모델이 tool을 안 부를 수 있음

tool_choice="auto"이므로 first tick에서 모델이 그냥 final JSON 직진할 수 있음. P4 sweep 후 분석 시 "tool 안 쓴 ep 비율" 확인. 필요 시 "MUST call annotate_objects on first call" 강제 추가.

다음 즉시 작업

P0 CoTracker sanity (sanity_cotracker_one_episode.py 이미 완성) → P1 tools.py + unit tests. P0~P1은 job 9951 결과 기다리는 동안 병행 가능. P4 sweep은 9951 끝난 후 GPU 확보되면 즉시 제출: sbmr 10 "bash scripts/run_api_mem_one_episode.sh VideoUnmaskSwap gemini-2.5-flash-lite tools_v1 0 0 1 1" --gres=gpu:2 -c 16 --mem=400GB --qos=extra