117 lines
6.2 KiB
Markdown
117 lines
6.2 KiB
Markdown
# OpenClaw 컨텍스트·메모리 리서치
|
|
|
|
**작성일**: 2026-03-17
|
|
**목적**: OpenClaw의 직전 대화·컨텍스트 처리 방식을 조사하고, 로빙 적용 가능성을 검토한다.
|
|
|
|
**관련 문서**:
|
|
- [아이디어: OpenClaw 스타일 컨텍스트·compaction](../ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md)
|
|
- [writing-principles](../../../../0_VALUE/02_Governance/writing-principles.md)
|
|
|
|
---
|
|
|
|
## 1. 사실 (Facts)
|
|
|
|
### 1.1 OpenClaw 1차 자료
|
|
|
|
| 항목 | 출처 | 내용 |
|
|
|------|------|------|
|
|
| Context 정의 | [open-claw.bot/docs/concepts/context](https://open-claw.bot/docs/concepts/context) | "실행 시 모델로 전송되는 모든 데이터". 디스크 Memory와 구분됨. |
|
|
| Context 구성요소 | 동일 | Attachments, Tool Calls & Results, **Conversation History**, System Prompt |
|
|
| Conversation History | 동일 | "이번 세션에서 주고받은 메시지 기록" |
|
|
| Compaction | [open-claw.bot/docs/concepts/compaction](https://open-claw.bot/docs/concepts/compaction) | 토큰 한도 근접 시 **이전 대화를 요약**해 한 블록으로 압축. auto-compaction 기본 활성화. |
|
|
| Manual Compaction | 동일 | `/compact Focus on decisions and open questions` — 우선순위 지시 가능 |
|
|
| Persistence | 동일 | 요약은 session JSONL에 저장. 재시작 후에도 유지. |
|
|
| 3-Layer Memory | [learnopenclaw.com/core-concepts/memory](https://learnopenclaw.com/core-concepts/memory) | Short-term(세션), Medium-term(daily log), Long-term(MEMORY.md) |
|
|
| Short-term | 동일 | LLM context window 내. 세션 종료 시 초기화. 자동 유지. |
|
|
| Medium-term | 동일 | `session-memory` 훅이 대화 종료 시 **요약** 생성 → 날짜별 daily log 마크다운에 append |
|
|
| Long-term | 동일 | MEMORY.md. 사용자 직접 관리. `boot-md` 훅으로 매 대화 시작 시 로드 |
|
|
| Hybrid Search | 동일 | 70% vector, 30% BM25. MEMORY 검색 시 사용 |
|
|
| Session isolation | [session-management-compaction](https://open-claw.bot/docs/cli/reference/session-management-compaction) | `session.dmScope`: per-channel(공유) vs per-channel-peer(격리) |
|
|
| Compaction 설정 | 동일 | `reserveTokens`, `keepRecentTokens` 등 |
|
|
|
|
### 1.2 로빙 현재 구현
|
|
|
|
| 항목 | 파일 | 내용 |
|
|
|------|------|------|
|
|
| 조회 | `app/state/database.py` 115-147행 | `get_recent_conversations(user_id, limit=300, window_hours=24)` |
|
|
| DB | `conversation_log` | `message`, `response`, `intent`, `timestamp` |
|
|
| 조건 | 동일 | `user_id`(UUID), `timestamp >= cutoff`(24h), `ORDER BY timestamp DESC` |
|
|
| 제한 | 동일 | Slack ID(`U`로 시작)면 `[]` 반환 |
|
|
| 전달 | `app/router/message_router.py` 320-351행 | `get_user_context()` → `recent_conversations` |
|
|
| 사용처 | `decision_engine.analyze_intent()` | approval, CONTEXT_FOLLOWUP, LLM 폴백 시 `previous_message + message` 결합 |
|
|
| 필터 | 동일 331-339행 | 정책 placeholder 응답 제거 |
|
|
|
|
---
|
|
|
|
## 2. 해석 (Interpretation)
|
|
|
|
### 2.1 OpenClaw vs 로빙 차이
|
|
|
|
| 구분 | OpenClaw | 로빙 |
|
|
|------|----------|------|
|
|
| 대화 로드 | 세션 단위, 토큰 예산 내 | 24h 내 300개 raw |
|
|
| 초과 시 | compaction(요약) | 제한 없음(호출부에서 잘라쓸 가능성) |
|
|
| 중장기 | daily log + MEMORY.md | 없음 |
|
|
| 세션 | 단일 에이전트, 채널/peer 격리 | 멀티유저, user_id·channel |
|
|
| 저장 | JSONL + 마크다운 파일 | PostgreSQL `conversation_log` |
|
|
|
|
### 2.2 로빙에 compaction이 필요한 이유
|
|
|
|
- 300개 raw는 수만~수십만 토큰. 대부분 LLM 호출 시 전부 주입 불가.
|
|
- 실제로는 handler에서 `recent_conversations[:N]` 등으로 잘라쓸 가능성 있으나, **어디서 몇 개를 쓰는지** 명시적이지 않음.
|
|
- "그래", "무슨 말이야?" 오분류: 직전 raw 대화와 결합해 시맨틱/LLM이 잘못된 의도로 분류. **요약된 맥락**이면 노이즈 감소 기대.
|
|
|
|
### 2.3 적용 시 고려사항
|
|
|
|
1. **compaction 단위**: user_id·channel별 세션. 로빙은 요청 단위 무상태이므로 "세션" 정의 필요(예: 30분 내 연속 대화).
|
|
2. **요약 생성 시점**: 대화 종료 정의 어려움. OpenClaw는 단일 스레드 대화. 로빙은 비동기·멀티채널. → **주기적 배치** 또는 **N회 대화마다** 요약 후 append 가능.
|
|
3. **저장소**: daily log는 파일 vs DB. 로빙 인프라가 DB 중심이면 `conversation_summary` 테이블 추가 검토.
|
|
4. **MEMORY.md 대응**: user별 `user_memory` 또는 `robeing_memory` 테이블. boot 시 로드.
|
|
|
|
---
|
|
|
|
## 3. 미확정 항목 (Unresolved)
|
|
|
|
- compaction 요약에 사용할 LLM 모델·토큰 예산.
|
|
- `session-memory` 훅 트리거: "대화 종료"를 타임아웃(예: 30분 무응답) vs 명시적 `/end` vs 배치.
|
|
- 기존 `conversation_log`와 요약 저장소 관계: 대체 vs 병행(원본 유지 + 요약 추가).
|
|
- Slack ID → UUID 매핑 없을 때 `recent_conversations`가 `[]`인 문제. OpenClaw는 세션 파일로 해결. 로빙은 Gateway `X-User-Id` 전달 전제.
|
|
|
|
---
|
|
|
|
## 4. 코드 경로 (로빙)
|
|
|
|
```
|
|
get_recent_conversations(user_id, limit=300, window_hours=24)
|
|
← message_router.get_user_context()
|
|
← message_service.route_message()
|
|
→ context["recent_conversations"]
|
|
→ create_execution_plan(message, context)
|
|
→ analyze_intent(message, context)
|
|
├ approval: context["recent_conversations"][0].intent
|
|
├ CONTEXT_FOLLOWUP: previous_message + message → semantic
|
|
└ _llm_intent_fallback: combined → semantic 재시도
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 1차 자료 링크
|
|
|
|
- [OpenClaw Context](https://open-claw.bot/docs/concepts/context)
|
|
- [OpenClaw Compaction](https://open-claw.bot/docs/concepts/compaction)
|
|
- [OpenClaw Session & Compaction](https://open-claw.bot/docs/cli/reference/session-management-compaction)
|
|
- [OpenClaw Memory System](https://learnopenclaw.com/core-concepts/memory)
|
|
|
|
---
|
|
|
|
## 6. 다음 단계
|
|
|
|
1. 아이디어 문서 기준으로 플랜 작성(Phase별 작업 단위).
|
|
2. compaction 프로토타입: `get_recent_conversations` 대체 또는 래퍼로 "최근 N개 raw + 그 이전은 요약 1블록" 반환.
|
|
3. session-memory 훅: `save_conversation` 호출 후 조건 만족 시 요약 생성·저장.
|
|
|
|
---
|
|
|
|
**tags**: [research, context, memory, compaction, OpenClaw, robeing]
|
|
**상위 원칙**: [writing-principles](../../../../0_VALUE/02_Governance/writing-principles.md)
|