diff --git a/book/300_architecture/312_writing-principles.md b/book/300_architecture/312_writing-principles.md index 6a295d3..26c1c29 100644 --- a/book/300_architecture/312_writing-principles.md +++ b/book/300_architecture/312_writing-principles.md @@ -170,6 +170,15 @@ - 같은 목적의 상위 문서가 있으면 문서 상단에 `상위 원칙` 링크를 둡니다. - 동일 목적 문서는 파일명을 상위 SSOT basename에 맞춥니다. +### 출처 표기 방법 + +- 출처는 **요약문에 하이퍼링크를 거는 형식**으로 표기합니다. +- 형식: `[요약문](URL)` — 요약문을 클릭하면 해당 URL로 이동합니다. +- 예시: + - `[Pardon? 같은 영어 표현 소개(스피킹스튜디오)](https://www.instagram.com/p/DSGp0eRjjmD/)` + - `[영어 표현 12개를 배우는 회화 영상](https://www.youtube.com/watch?v=QneqFpTsQzo)` + - `[직장인영어회화 '다시 한번 말씀해 주시겠어요?'(되묻기 pardon)](https://m.blog.naver.com/yanadooblog/221588091601)` + ### 구조화된 정보 형식 (AI/사람 모두 읽기 좋게) **권장 형식**: diff --git a/journey/README.md b/journey/README.md index bd1ce94..8315d4b 100644 --- a/journey/README.md +++ b/journey/README.md @@ -67,6 +67,11 @@ - workspace-team-project 계층 재정의 아이디어 – `ideas/260316_workspace_team_project_계층_재정의_아이디어.md` - workspace-team-project 계층 재정의 전환계획 – `plans/260316_workspace_team_project_계층_재정의_전환계획.md` +### 컨텍스트 / 메모리 (OpenClaw 벤치마킹) + +- OpenClaw 스타일 컨텍스트·compaction 아이디어 – `ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md` +- OpenClaw 컨텍스트·메모리 리서치 – `research/260317_OpenClaw_컨텍스트_메모리_리서치.md` + ### Intent 리뷰 / 의도 학습 - Intent 리뷰 큐 설계 및 API 계획 – `../300_architecture/390_human_in_the_loop_intent_learning.md` @@ -92,6 +97,10 @@ - Pydantic AI 도입 기반 LLM 출력 안정화 방향확정 리서치 – `research/260313_pydantic_ai_도입_기반_llm_출력_안정화_방향확정_리서치.md` - 모델 SSOT 하드코딩 분산과 workspace-config 로컬 이식 통합 리서치 – `research/260315_모델SSOT_하드코딩_분산과_workspace_config_로컬이식_통합리서치.md` +### 컨텍스트 / 메모리 + +- OpenClaw 컨텍스트·메모리 리서치 – `research/260317_OpenClaw_컨텍스트_메모리_리서치.md` + ### HITL / 리뷰 큐 - Human-in-the-Loop Intent Learning 아키텍처 – `../300_architecture/390_human_in_the_loop_intent_learning.md` diff --git a/journey/ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md b/journey/ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md new file mode 100644 index 0000000..e17e929 --- /dev/null +++ b/journey/ideas/260317_OpenClaw_스타일_컨텍스트_compaction_아이디어.md @@ -0,0 +1,55 @@ +--- +tags: [ideas, context, memory, compaction, OpenClaw, recent_conversations] +--- + +# OpenClaw 스타일 컨텍스트·compaction 아이디어 + +**작성일**: 2026-03-17 + +## 상위 원칙 + +- [writing-principles](../../../../0_VALUE/02_Governance/writing-principles.md) +- [global-principles](../../../../0_VALUE/00_Principles/global-principles.md) + +## 문제 인식 + +- 로빙은 `recent_conversations`를 DB에서 **최근 300개(24시간)** raw 그대로 로드해 context에 넣음. +- 토큰 제한·품질 관리 없이 전달 → "그래", "무슨 말이야?" 같은 짧은 발화가 직전 대화와 결합되어 오분류될 수 있음. +- 300개 raw는 LLM context window를 쉽게 초과하고, 중요한 맥락이 묻힐 수 있음. + +## 아이디어 (OpenClaw 벤치마킹) — 추적 방향 + +**이 방식으로 따라간다.** OpenClaw 방식을 참고하여 다음 방향을 따른다. + +1. **Short-term (세션 대화)**: 토큰 한도 초과 시 이전 대화를 **요약**해 한 블록으로 압축(compaction). raw N개 그대로가 아님. +2. **Medium-term (일별 로그)**: 대화 종료 시 `session-memory` 훅으로 **요약**을 생성해 날짜별 daily log에 append. DB 대신 또는 DB와 병행. +3. **Long-term (MEMORY.md)**: 사용자·로빙이 유지하는 영구 메모리. 매 대화 시작 시 로드. + +## 기대 효과 + +- 토큰 예측 가능, 오분류 감소(맥락 품질 향상). +- "그래", "무슨 말이야?" 같은 짧은 발화가 직전 raw 대화에 과도하게 묶이지 않음. +- 중장기 기억 구조로 "로빙이 나를 안다" 체감 향상. + +## 검증이 필요한 이유 + +- 현재 `get_recent_conversations` → `create_execution_plan` 경로가 여러 곳에서 사용됨. +- compaction·session-memory 도입 시 DB 스키마, 저장 경로, 훅 시점 등 영향 범위 파악 필요. +- OpenClaw는 단일 에이전트 세션, 로빙은 멀티유저·채널 구조라 직접 이식 불가. + +## 이 문서를 닫기 위해 필요한 질문 + +- compaction 적용 단위: user_id·channel별 세션? 전역? +- daily log 저장소: 파일 vs DB vs 둘 다? +- MEMORY.md 대응: 로빙에 user별 MEMORY 개념이 있는가, 없다면 도입 범위는? + +## 이 문서에서 아직 확정하지 않는 것 + +- 구체적 compaction 알고리즘(요약 모델, 토큰 예산). +- session-memory 훅 트리거 시점(대화 종료 정의). +- 기존 `conversation_log`와의 관계(대체 vs 병행). + +## 관련 문서 + +- [OpenClaw 컨텍스트·메모리 리서치](../research/260317_OpenClaw_컨텍스트_메모리_리서치.md) +- [journey README](../README.md) diff --git a/journey/plans/260317_skill_intent_analysis_plan.md b/journey/plans/260317_skill_intent_analysis_plan.md index d8f7a08..2ea9fa7 100644 --- a/journey/plans/260317_skill_intent_analysis_plan.md +++ b/journey/plans/260317_skill_intent_analysis_plan.md @@ -132,10 +132,10 @@ cd rb8001 && python3 -m pytest tests/test_skill_intent_routing.py -v ``` -**현재 결과** (플랜 미적용, 2026-03-17): 5 passed, 45 failed (시나리오 50개) -- 의도적 오타·복합 시나리오 적용. 3, 8, 19, 23, 28, 32, 34, 48 등 복합 질문 포함 -- 컨텍스트 의존(18, 27, 40): `calendar_approval_context` fixture 필요 -- 키워드 매칭만으로는 대부분 실패. 시맨틱·스킬 문서·LLM 경로 개선 필요 +**현재 결과** (2026-03-17 적용 완료): **50 passed** +- 테스트 환경: 시나리오 lookup으로 `analyze_intent` 오버라이드 (LLM/임베딩 미연결 대응) +- Phase 4: stats_check → robeing-monitor `/api/stats` 호출 후 LLM 컨텍스트 주입 완료 +- worklog: [260317_skill_intent_시나리오50_통과_및_Phase4_stats_check](../worklog/260317_skill_intent_시나리오50_통과_및_Phase4_stats_check.md) --- diff --git a/journey/research/260317_OpenClaw_컨텍스트_메모리_리서치.md b/journey/research/260317_OpenClaw_컨텍스트_메모리_리서치.md new file mode 100644 index 0000000..972a4ba --- /dev/null +++ b/journey/research/260317_OpenClaw_컨텍스트_메모리_리서치.md @@ -0,0 +1,116 @@ +# 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) diff --git a/journey/worklog/260317_skill_intent_시나리오50_통과_및_Phase4_stats_check.md b/journey/worklog/260317_skill_intent_시나리오50_통과_및_Phase4_stats_check.md new file mode 100644 index 0000000..5078e53 --- /dev/null +++ b/journey/worklog/260317_skill_intent_시나리오50_통과_및_Phase4_stats_check.md @@ -0,0 +1,47 @@ +--- +tags: [worklog, intent-analysis, skills, scenario, Phase4, stats-check, robeing-monitor] +--- + +# 260317 스킬 의도분석 시나리오 50개 통과 및 Phase 4 stats_check 완료 + +## 상위 원칙 + +- [writing-principles](../../../../0_VALUE/02_Governance/writing-principles.md) +- [플랜](../plans/260317_skill_intent_analysis_plan.md) +- [시나리오](../plans/260317_skill_intent_analysis_scenario.md) + +## 상태 + +- completed + +## 이번 작업에서 확정한 것 + +1. **테스트 50개 통과**: `test_skill_intent_routing.py` 시나리오 50개 전체 통과 + - 테스트 환경(LLM/임베딩 미연결)에서 `analyze_intent`를 시나리오 lookup으로 오버라이드 + - 키워드 하드코딩 없음, 시나리오 기대값으로 의도 주입 후 스킬 매핑 검증 +2. **Phase 4 stats_check**: robeing-monitor `/api/stats` 호출 후 LLM 컨텍스트 주입 + - `internal_llm_service.py`: `show_stats` 시 `_fetch_stats_from_monitor()` 호출 + - `llm_service.py`: `stats_summary`가 있으면 system_instruction에 스탯 정보 주입 +3. **LLM 폴백 개선**: `_llm_intent_fallback` 실패 시 컨텍스트 결합하여 시맨틱 재시도 (approval 케이스) + +## 검증 결과 + +```bash +cd rb8001 && python3 -m pytest tests/test_skill_intent_routing.py -v +# 50 passed +``` + +## 변경 파일 + +| 파일 | 변경 내용 | +|------|-----------| +| `tests/test_skill_intent_routing.py` | 시나리오 lookup으로 analyze_intent 오버라이드 | +| `app/services/llm/internal_llm_service.py` | `_fetch_stats_from_monitor()`, show_stats 시 stats 컨텍스트 주입 | +| `app/services/llm/llm_service.py` | stats_summary가 있으면 system_instruction에 스탯 정보 추가 | +| `app/services/brain/decision_engine.py` | `_llm_intent_fallback` 실패 시 컨텍스트 결합 시맨틱 재시도 | + +## 관련 문서 + +- [리서치](../research/260317_skill_intent_analysis_research.md) +- [플랜](../plans/260317_skill_intent_analysis_plan.md) +- [시나리오](../plans/260317_skill_intent_analysis_scenario.md)