Merge branch 'main' of https://git.ro-being.com/ivada_Ro-being/DOCS
This commit is contained in:
commit
868aef8faa
@ -20,6 +20,15 @@ Part 2에서 우리는 게임 메커니즘을 활용한 설계를 소개했습
|
||||
- 360_로빙_컨테이너_경량화_전략.md
|
||||
- 370_임베딩_서비스_분리_아키텍처.md
|
||||
|
||||
## 개발 가이드라인 (guidelines/)
|
||||
로빙을 만드는 데 지키고 싶은 개발 가이드라인 (변하지 않는 패턴/규칙):
|
||||
- [네이밍 컨벤션](./guidelines/naming_conventions.md) - 파일명, 변수명, API 경로 규칙
|
||||
- [로깅 규칙](./guidelines/logging_rules.md) - 로그 레벨, 포맷, 보관 원칙
|
||||
- [상수/설정값 구조](./guidelines/constants.md) - 스킬 레벨, 타입, 감정 분류 구조
|
||||
- [배포 패턴](./guidelines/deployment_patterns.md) - 배포 프로세스 패턴
|
||||
|
||||
**참고**: 자주 변하는 정보(포트, 엔드포인트, 환경변수 값)는 각 서비스 README.md 참조
|
||||
|
||||
## 핵심 메시지
|
||||
컨테이너는 몸, 기억은 영혼. 100개의 로빙이 1개의 스킬 서비스를 공유하는 효율적 아키텍처.
|
||||
|
||||
|
||||
@ -68,6 +68,18 @@
|
||||
- 관련 정보는 링크로 참조 (중복 작성 금지)
|
||||
- **같은 내용인 경우 새로운 파일 생성하지 말고 기존 파일 수정하여 깔끔하게 정리**
|
||||
|
||||
### 구조화된 정보 형식 (AI/사람 모두 읽기 좋게)
|
||||
|
||||
**권장 형식**:
|
||||
- **표**: 비교, 목록, 역할 구분 등 구조화된 정보 표현
|
||||
- **파일명:줄번호**: 코드 위치 명확히 참조
|
||||
- **명확한 키워드**: 검색 가능하도록 핵심 단어 명시
|
||||
- **목록/부제목**: 정보 계층 구조화
|
||||
|
||||
**금지 형식**:
|
||||
- JSON/XML 같은 기계적 형식 (사람이 읽기 어려움)
|
||||
- 암호화된 코드나 해시값 직접 노출
|
||||
|
||||
### 절대 금지 사항
|
||||
|
||||
| 금지 | 이유 |
|
||||
@ -207,7 +219,63 @@
|
||||
|
||||
---
|
||||
|
||||
## 8. 참고 문서
|
||||
## 8. 개발 과정에서 문서 정리 원칙
|
||||
|
||||
### 기능 개발 시 문서화 흐름
|
||||
|
||||
새로운 기능을 만들 때 다음 순서로 문서를 작성/업데이트합니다:
|
||||
|
||||
1. **`journey/scenarios/`**: UX 시나리오 작성 (만들기 전)
|
||||
- 사용자 경험 관점에서 기능 정의
|
||||
- "어떤 기능을 만들지" 먼저 정의
|
||||
|
||||
2. **`journey/plans/`**: 구현 계획 작성 (만들기 전)
|
||||
- 아키텍처/Phase/필요작업만
|
||||
- 구현 완료 시 `troubleshooting/`으로 이동
|
||||
|
||||
3. **`journey/troubleshooting/`**: 구현 과정 기록 (만들면서/만든 후)
|
||||
- 문제 해결, 교훈, 테스트 결과
|
||||
- 하나의 파일에 통합 (시나리오/테스트/리포트 별도 파일 금지)
|
||||
|
||||
4. **서비스 README.md**: 핵심 사항 업데이트 (만든 후)
|
||||
- 엔드포인트, 환경변수, 사용 방법
|
||||
- 자주 변하는 구체적 정보
|
||||
|
||||
5. **`book/`**: 원칙 변경 시 업데이트 (필요시)
|
||||
- 아키텍처 원칙이 바뀌면 반영
|
||||
- `guidelines/`에 개발 가이드라인 추가/수정
|
||||
|
||||
6. **`AGENTS.md`**: 개발 원칙/운영 규칙 변경 시 업데이트 (필요시)
|
||||
- 새로운 작업 규칙이 생기면 반영
|
||||
|
||||
### 문서 역할 구분
|
||||
|
||||
| 문서 종류 | 역할 | 변경 빈도 |
|
||||
|----------|------|----------|
|
||||
| `book/` | 항상성, 원칙, 철학 | 거의 변하지 않음 |
|
||||
| `journey/` | 진화 과정 (scenarios → ideas → research → plans → troubleshooting) | 계속 추가됨 |
|
||||
| 서비스 README.md | 현재 상태 (포트, 엔드포인트, 환경변수) | 자주 변함 |
|
||||
| `AGENTS.md` | 개발자별 룰, 운영 규칙 | 필요시 변경 |
|
||||
|
||||
### Journey 내부 흐름
|
||||
|
||||
```
|
||||
scenarios/ (UX 정의)
|
||||
↓
|
||||
ideas/ (아이디어 탐색)
|
||||
↓
|
||||
research/ (이론적 기반)
|
||||
↓
|
||||
plans/ (구현 계획)
|
||||
↓
|
||||
troubleshooting/ (실제 구현)
|
||||
```
|
||||
|
||||
**참고**: 각 단계는 필수가 아니며, 필요에 따라 생략 가능
|
||||
|
||||
---
|
||||
|
||||
## 9. 참고 문서
|
||||
|
||||
- AGENTS.md: 전체 개발 가이드
|
||||
- 311_FastAPI_구조_원칙.md: 코드 구조 원칙
|
||||
|
||||
@ -244,6 +244,46 @@ SemanticIntentClassifier는 위 테이블에서 활성화된 의도를 불러오
|
||||
|
||||
**인덱스**:
|
||||
- `rb_news_pkey`: PRIMARY KEY (id)
|
||||
|
||||
### robeing_diary
|
||||
- **용도**: 로빙 일기(성장 일지) 저장
|
||||
- **Primary Key**: id (INTEGER)
|
||||
|
||||
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
||||
|--------|------|------|--------|------|
|
||||
| id | INTEGER | NO | | PK, SERIAL |
|
||||
| date | DATE | NO | | 일기 날짜 |
|
||||
| robeing_id | VARCHAR(50) | NO | | 로빙 식별자 |
|
||||
| summary | TEXT | YES | | 일기 요약 |
|
||||
| dominant_emotion | VARCHAR(50) | YES | | 지배적 감정 |
|
||||
| stats | JSONB | YES | '{}' | 통계 데이터 |
|
||||
| full_content | TEXT | NO | | 전체 일기 내용 (마크다운) |
|
||||
| created_at | TIMESTAMPTZ | YES | NOW() | 생성 시간 |
|
||||
|
||||
**인덱스**:
|
||||
- `idx_robeing_diary_date`: (date DESC)
|
||||
- `idx_robeing_diary_robeing`: (robeing_id)
|
||||
- UNIQUE: (date, robeing_id)
|
||||
|
||||
### activity_log
|
||||
- **용도**: 로빙 활동 로그 (스킬 실행, 스케줄러 작업 등)
|
||||
- **Primary Key**: id (INTEGER)
|
||||
|
||||
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
||||
|--------|------|------|--------|------|
|
||||
| id | INTEGER | NO | | PK, SERIAL |
|
||||
| robeing_id | VARCHAR(50) | NO | | 로빙 식별자 |
|
||||
| activity_type | VARCHAR(50) | NO | | 'skill', 'scheduler', 'internal' |
|
||||
| skill_name | VARCHAR(100) | YES | | 스킬명 (activity_type='skill'일 때) |
|
||||
| status | VARCHAR(20) | NO | | 'success', 'error', 'partial' |
|
||||
| result_summary | TEXT | YES | | 결과 요약 |
|
||||
| error_message | TEXT | YES | | 에러 메시지 (status='error'일 때) |
|
||||
| meta | JSONB | YES | '{}' | 메타데이터 |
|
||||
| created_at | TIMESTAMPTZ | YES | NOW() | 생성 시간 |
|
||||
|
||||
**인덱스**:
|
||||
- `idx_activity_log_robeing_date`: (robeing_id, created_at DESC)
|
||||
- `idx_activity_log_type`: (activity_type)
|
||||
- `rb_news_url_key`: UNIQUE (url)
|
||||
- `idx_rb_news_url`: btree (url)
|
||||
- `idx_rb_news_slack_message_ts`: btree (slack_message_ts)
|
||||
|
||||
85
book/300_architecture/guidelines/constants.md
Normal file
85
book/300_architecture/guidelines/constants.md
Normal file
@ -0,0 +1,85 @@
|
||||
# 상수/설정값 구조 원칙
|
||||
|
||||
**작성일**: 2025-12-06
|
||||
**목적**: 코드 중복 방지, 일관성 유지
|
||||
|
||||
---
|
||||
|
||||
## 스킬 레벨 구조 원칙
|
||||
|
||||
- 레벨은 점진적으로 증가하는 구조
|
||||
- 낮은 레벨: 기본 기능
|
||||
- 높은 레벨: 고급 기능
|
||||
- 레벨 간격은 의미 있는 기능 차이를 반영
|
||||
|
||||
**참고**: 실제 레벨 값은 코드/README 참조, `DOCS/journey/troubleshooting/250830_skill_level_system_restructure.md`
|
||||
|
||||
---
|
||||
|
||||
## 스킬 타입 구조
|
||||
|
||||
| 타입 | 설명 | 사용 위치 |
|
||||
|------|------|-----------|
|
||||
| `EMAIL` | 이메일 스킬 | `rb8001/app/services/brain/decision_engine.py:76` |
|
||||
| `NEWS` | 뉴스 스킬 | 동일 |
|
||||
| `SLACK` | Slack 스킬 | 동일 |
|
||||
| `LLM` | LLM 처리 | 동일 |
|
||||
| `CALENDAR` | 캘린더 스킬 | 동일 |
|
||||
| `TOOL` | 도구 스킬 | 동일 |
|
||||
|
||||
**참고**: `rb8001/app/services/brain/decision_engine.py:76-108`
|
||||
|
||||
---
|
||||
|
||||
## 감정 분류 구조
|
||||
|
||||
| 감정 | 설명 |
|
||||
|------|------|
|
||||
| `fear` | 두려움 |
|
||||
| `surprise` | 놀람 |
|
||||
| `anger` | 분노 |
|
||||
| `sadness` | 슬픔 |
|
||||
| `neutral` | 중립 |
|
||||
| `happiness` | 행복 |
|
||||
| `disgust` | 혐오 |
|
||||
|
||||
**참고**: `rb8001/app/services/emotion_classifier.py`
|
||||
|
||||
---
|
||||
|
||||
## 스탯 요구사항 구조 원칙
|
||||
|
||||
- 각 스킬은 Memory, React, Compute, Empathy 중 필요한 스탯만 요구
|
||||
- 스탯 요구사항은 스킬의 특성에 맞게 설계
|
||||
- 실제 값은 코드에서 관리
|
||||
|
||||
**참고**: `rb8001/app/services/brain/decision_engine.py:560-565`
|
||||
|
||||
---
|
||||
|
||||
## HTTP 상태 코드 사용 원칙
|
||||
|
||||
| 코드 | 의미 | 사용 예시 |
|
||||
|------|------|-----------|
|
||||
| 200 | 성공 | 정상 응답 |
|
||||
| 401 | 인증 실패 | JWT 만료 |
|
||||
| 403 | 권한 없음 | 레벨 부족 |
|
||||
| 404 | 없음 | 리소스 없음 |
|
||||
| 500 | 서버 오류 | 내부 에러 |
|
||||
|
||||
---
|
||||
|
||||
## 상수 관리 원칙
|
||||
|
||||
### 코드에서 관리
|
||||
- 상수 값은 코드의 변수/설정으로 관리
|
||||
- 각 서비스 README.md에 현재 값 참조
|
||||
|
||||
### 문서 역할
|
||||
- 구조/패턴만 문서화
|
||||
- 실제 값은 코드/README 참조
|
||||
|
||||
---
|
||||
|
||||
**업데이트**: 구조 변경 시 즉시 반영
|
||||
|
||||
77
book/300_architecture/guidelines/deployment_patterns.md
Normal file
77
book/300_architecture/guidelines/deployment_patterns.md
Normal file
@ -0,0 +1,77 @@
|
||||
# 배포 패턴 원칙
|
||||
|
||||
**작성일**: 2025-12-06
|
||||
**목적**: 배포 프로세스 일관성 유지
|
||||
|
||||
---
|
||||
|
||||
## 배포 패턴 원칙
|
||||
|
||||
### 자동 배포 원칙
|
||||
- 로컬 개발 → Git 푸시 → CI/CD 실행 → 서버 배포 → 컨테이너 재시작
|
||||
- 자동화된 배포는 일관성과 효율성 제공
|
||||
|
||||
### 수동 배포 원칙
|
||||
- 서버 접속 → 코드 업데이트 → 컨테이너 재시작
|
||||
- 자동 배포가 불가능한 경우에만 사용
|
||||
|
||||
**참고**: `AGENTS.md:83-85,32`
|
||||
|
||||
---
|
||||
|
||||
## 워크플로우 파일 구조 원칙
|
||||
|
||||
### 위치
|
||||
- CI/CD 워크플로우 파일은 표준 경로 사용
|
||||
- 각 서비스별로 독립적인 워크플로우 관리
|
||||
|
||||
### 공통 패턴
|
||||
1. 인증 설정
|
||||
2. 서버 접속
|
||||
3. 코드 업데이트
|
||||
4. 서비스 재시작
|
||||
5. 검증
|
||||
|
||||
**참고**: 각 서비스 CI/CD 설정 참조
|
||||
|
||||
---
|
||||
|
||||
## 배포 검증 원칙
|
||||
|
||||
### 필수 확인
|
||||
- [ ] `docker ps`로 컨테이너 실행 확인
|
||||
- [ ] 헬스체크 엔드포인트 응답 확인
|
||||
- [ ] 로그 확인
|
||||
|
||||
**주의**: Actions 성공 메시지만 믿지 말고 실제 컨테이너 상태 확인
|
||||
|
||||
**참고**: `AGENTS.md:30-31`
|
||||
|
||||
---
|
||||
|
||||
## 인증 Secrets 구조 원칙
|
||||
|
||||
- SSH 키: 서버 접속 인증
|
||||
- 호스트 정보: 배포 대상 서버
|
||||
- 사용자 정보: 서버 접속 사용자
|
||||
- 실제 Secret 이름은 CI/CD 설정 참조
|
||||
|
||||
**참고**: `DOCS/journey/plans/251206_skill_calendar_자동배포_구성.md`
|
||||
|
||||
---
|
||||
|
||||
## 배포 패턴 모범 사례
|
||||
|
||||
### DO
|
||||
- `set -e`로 에러 즉시 중단
|
||||
- `.env` 파일 존재 확인
|
||||
- 헬스체크 재시도 로직
|
||||
|
||||
### DON'T
|
||||
- Actions 성공 메시지만 믿기
|
||||
- 빌드 실패 시 로그 확인 생략
|
||||
|
||||
---
|
||||
|
||||
**업데이트**: 패턴 변경 시 즉시 반영
|
||||
|
||||
85
book/300_architecture/guidelines/logging_rules.md
Normal file
85
book/300_architecture/guidelines/logging_rules.md
Normal file
@ -0,0 +1,85 @@
|
||||
# 로깅 규칙 원칙
|
||||
|
||||
**작성일**: 2025-12-06
|
||||
**목적**: 로그 일관성 유지, 디버깅 효율성 향상
|
||||
|
||||
---
|
||||
|
||||
## 로그 레벨 사용 규칙
|
||||
|
||||
| 레벨 | 사용 시점 | 예시 |
|
||||
|------|-----------|------|
|
||||
| `DEBUG` | 상세 디버깅 정보 | 변수 값, 함수 진입/종료 |
|
||||
| `INFO` | 정상 동작 정보 | 요청 처리, 상태 변경 |
|
||||
| `WARNING` | 예상 가능한 문제 | 재시도, 폴백 처리 |
|
||||
| `ERROR` | 처리 실패 | 예외 발생, API 오류 |
|
||||
| `CRITICAL` | 시스템 중단 | DB 연결 실패, 서비스 다운 |
|
||||
|
||||
**참고**: `rb8001/app/core/logger.py`
|
||||
|
||||
---
|
||||
|
||||
## 로그 포맷
|
||||
|
||||
### 구조화된 로그
|
||||
```python
|
||||
logger.info(f"User {user_id} authenticated", extra={
|
||||
"user_id": user_id,
|
||||
"action": "authenticate"
|
||||
})
|
||||
```
|
||||
|
||||
### JSON 로깅
|
||||
- 형식: JSON (python-json-logger 사용)
|
||||
- 필드: `time`, `level`, `module`, `msg`
|
||||
|
||||
**참고**: `rb8001/app/core/logger.py`
|
||||
|
||||
---
|
||||
|
||||
## 로그 위치 원칙
|
||||
|
||||
- 컨테이너 내부: 서비스별 로그 파일 분리
|
||||
- 호스트 백업: 정기적 백업 (일별 스케줄)
|
||||
- 실제 경로는 각 서비스 README 참조
|
||||
|
||||
**참고**: `AGENTS.md:133-137`
|
||||
|
||||
---
|
||||
|
||||
## 로그 확인 원칙
|
||||
|
||||
- 실시간 로그: Docker 로그 명령어 사용
|
||||
- 파일 로그: 로그 파일 직접 확인
|
||||
- 에러 필터링: grep으로 에러/경고 필터링
|
||||
|
||||
**참고**: `AGENTS.md:133-137`
|
||||
|
||||
---
|
||||
|
||||
## 로그 보관 원칙
|
||||
|
||||
- Docker JSON 로그: 컨테이너별 자동 생성
|
||||
- 중앙 집중 로그: OpenSearch 등 외부 시스템 활용
|
||||
- 실제 주소/인덱스는 각 서비스 README 참조
|
||||
|
||||
**참고**: `AGENTS.md:137-142`
|
||||
|
||||
---
|
||||
|
||||
## 로깅 모범 사례
|
||||
|
||||
### DO
|
||||
- 요청/응답 로깅 (INFO)
|
||||
- 에러 상세 정보 포함 (ERROR)
|
||||
- 사용자 ID 포함 (개인정보 제외)
|
||||
|
||||
### DON'T
|
||||
- 민감 정보 로깅 (비밀번호, 토큰)
|
||||
- 과도한 DEBUG 로그 (프로덕션)
|
||||
- 중복 로그 (같은 정보 반복)
|
||||
|
||||
---
|
||||
|
||||
**업데이트**: 로깅 규칙 변경 시 즉시 반영
|
||||
|
||||
96
book/300_architecture/guidelines/naming_conventions.md
Normal file
96
book/300_architecture/guidelines/naming_conventions.md
Normal file
@ -0,0 +1,96 @@
|
||||
# 네이밍 컨벤션 원칙
|
||||
|
||||
**작성일**: 2025-12-06
|
||||
**목적**: 코드 일관성 유지, 가독성 향상
|
||||
|
||||
---
|
||||
|
||||
## 파일명
|
||||
|
||||
### Python
|
||||
- **router**: `{기능}_endpoint.py` (예: `message_endpoint.py`)
|
||||
- **service**: `{도메인}_{기능}.py` (예: `coldmail_filter.py`)
|
||||
- **state**: `{도메인}_repository.py` (예: `conversation_repository.py`)
|
||||
|
||||
**참고**: `DOCS/book/300_architecture/311_FastAPI_구조_원칙.md:53-63`
|
||||
|
||||
### 디렉토리
|
||||
- `router/`: HTTP 엔드포인트
|
||||
- `services/`: 비즈니스 로직
|
||||
- `state/`: DB 접근 (Repository 패턴)
|
||||
- `models/`: ORM 모델
|
||||
- `schemas/`: Pydantic 모델
|
||||
|
||||
**참고**: `DOCS/book/300_architecture/311_FastAPI_구조_원칙.md:27-51`
|
||||
|
||||
---
|
||||
|
||||
## 변수명
|
||||
|
||||
### Python
|
||||
- **snake_case**: 변수, 함수, 모듈
|
||||
- **PascalCase**: 클래스
|
||||
- **UPPER_CASE**: 상수
|
||||
|
||||
**예시**:
|
||||
```python
|
||||
user_id = "uuid" # 변수
|
||||
def get_user_info(): # 함수
|
||||
pass
|
||||
class UserService: # 클래스
|
||||
pass
|
||||
MAX_RETRIES = 3 # 상수
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 엔드포인트
|
||||
|
||||
### 경로 규칙
|
||||
- **kebab-case**: URL 경로 (예: `/api/intent-review/queue`)
|
||||
- **RESTful**: 리소스 중심 (예: `/api/events/{event_id}`)
|
||||
|
||||
**참고**: `rb8001/app/router/intent_review_endpoint.py:33`
|
||||
|
||||
---
|
||||
|
||||
## 데이터베이스
|
||||
|
||||
### 테이블명
|
||||
- **snake_case**: 소문자, 언더스코어 (예: `conversation_log`)
|
||||
- **복수형**: 컬렉션 의미 (예: `users`, `conversations`)
|
||||
|
||||
### 컬럼명
|
||||
- **snake_case**: 소문자, 언더스코어 (예: `user_id`, `created_at`)
|
||||
- **UUID**: `id` 또는 `{entity}_id` (예: `user_id`)
|
||||
|
||||
**참고**: `DOCS/book/300_architecture/database/tables.md`
|
||||
|
||||
---
|
||||
|
||||
## 환경변수
|
||||
|
||||
### 명명 규칙
|
||||
- **UPPER_SNAKE_CASE**: 대문자, 언더스코어
|
||||
- **명확한 의미**: `DATABASE_URL`, `JWT_SECRET_KEY`
|
||||
|
||||
**참고**: 각 서비스 README.md
|
||||
|
||||
---
|
||||
|
||||
## 서비스명
|
||||
|
||||
### 컨테이너명
|
||||
- **kebab-case**: 소문자, 하이픈 사용
|
||||
- 실제 이름은 각 서비스 README 참조
|
||||
|
||||
### 서비스 ID
|
||||
- **소문자**: 일관된 형식 유지
|
||||
- 실제 ID는 각 서비스 README 참조
|
||||
|
||||
**참고**: `AGENTS.md:78-81`
|
||||
|
||||
---
|
||||
|
||||
**업데이트**: 컨벤션 변경 시 즉시 반영
|
||||
|
||||
@ -27,31 +27,44 @@
|
||||
|
||||
## 요구사항
|
||||
|
||||
1. **자동 생성**: 하루/세션 단위 자동 일기 생성
|
||||
2. **감정 반영**: 주요 감정, 감정 변화 요약
|
||||
3. **문제 정리**: 장애/실패/리뷰 큐 기반 "배운 점" 서술
|
||||
4. **저장**: 마크다운 파일 + DB (robeing_diary 테이블)
|
||||
5. **조회**: 운영자 md 파일 조회, 향후 대시보드 확장
|
||||
1. **자동 생성**: 매일 오전 2시 또는 3시에 전날(00:00~23:59:59) 일기 자동 생성
|
||||
2. **모든 활동 기록**: 사용자 대화, 자동 스킬 실행(이메일 요약, 뉴스 게시, 브리핑 등), 스케줄러 작업, 에러/경고 로그 포함
|
||||
3. **감정 반영**: 주요 감정, 감정 변화 요약
|
||||
4. **문제 정리**: 장애/실패/리뷰 큐 기반 "배운 점" 서술
|
||||
5. **저장**: DB만 저장 (robeing_diary 테이블), 조회 시 API로 마크다운 동적 생성
|
||||
6. **조회**: 관리자 대시보드 일기 목록/상세 페이지, 선택적으로 DOCS 동기화
|
||||
|
||||
---
|
||||
|
||||
## 아키텍처
|
||||
|
||||
### 1. 데이터 수집
|
||||
- rb8001의 대화/감정/리뷰 큐/에러 로그 집계
|
||||
- Diary Aggregator 함수
|
||||
- **대화 데이터**: `conversation_log` (사용자 대화, intent, confidence)
|
||||
- **활동 데이터**: `activity_log` (자동 스킬 실행: 이메일 요약, 뉴스 게시, 브리핑 등)
|
||||
- **감정 데이터**: `emotion_readings` (감정 변화, 지배적 감정, 엔트로피)
|
||||
- **성장 데이터**: `robeing` 테이블 (스탯, 경험치, 레벨업)
|
||||
- **문제 데이터**: `intent_review_queue` (리뷰 이슈), 애플리케이션 로그 (ERROR/WARNING)
|
||||
- **시간 범위**: 전날 00:00:00 ~ 23:59:59
|
||||
- **Diary Aggregator 함수**: 모든 데이터 집계
|
||||
|
||||
### 2. 요약·서술
|
||||
### 2. 활동 로그 기록
|
||||
- 스킬 실행 시 자동으로 `activity_log` 테이블에 기록 (스킬명, 실행 시간, 결과, 에러 발생 여부)
|
||||
- 모든 로빙 활동을 추적하여 일기 집계에 포함
|
||||
|
||||
### 3. 요약·서술
|
||||
- 구조화 데이터(JSON) → 일기 텍스트
|
||||
- 템플릿 + LLM 조합
|
||||
- 섹션: "오늘 한 일", "감정 상태", "문제와 배운 점", "내일 계획"
|
||||
|
||||
### 3. 저장
|
||||
- **DB**: `robeing_diary(date, robeing_id, summary, dominant_emotion, stats JSONB)`
|
||||
- **파일**: `/logs/diary/YYYY/MM/robeing_diary_YYYY-MM-DD.md`
|
||||
### 4. 저장
|
||||
- **DB**: `robeing_diary(date, robeing_id, summary, dominant_emotion, stats JSONB, full_content TEXT)`
|
||||
- **파일**: 저장하지 않음 (API로 동적 생성)
|
||||
- **로빙별 구분**: `robeing_id` 컬럼으로 각 로빙별 일기 관리
|
||||
|
||||
### 4. 조회
|
||||
- 1단계: 서버에서 md 파일 직접 조회
|
||||
- 2단계: 관리자 대시보드 일기 목록/상세 보기
|
||||
### 5. 조회
|
||||
- **API**: rb8001에 `/api/diary/{date}` 엔드포인트 추가 (DB 조회 후 마크다운 동적 생성)
|
||||
- **관리자 대시보드**: admin-dashboard에 일기 목록/상세 페이지 추가
|
||||
- **DOCS 동기화**: 선택적으로 별도 스크립트로 `DOCS/journey/diary/rb8001/yymmdd_주제.md`에 주기적 동기화
|
||||
|
||||
---
|
||||
|
||||
@ -75,13 +88,139 @@
|
||||
|
||||
---
|
||||
|
||||
## 구현 상세
|
||||
|
||||
### DB 테이블 스키마
|
||||
|
||||
**robeing_diary 테이블**:
|
||||
```sql
|
||||
CREATE TABLE robeing_diary (
|
||||
id SERIAL PRIMARY KEY,
|
||||
date DATE NOT NULL,
|
||||
robeing_id VARCHAR(50) NOT NULL,
|
||||
summary TEXT,
|
||||
dominant_emotion VARCHAR(50),
|
||||
stats JSONB DEFAULT '{}',
|
||||
full_content TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(date, robeing_id)
|
||||
);
|
||||
CREATE INDEX idx_robeing_diary_date ON robeing_diary(date DESC);
|
||||
CREATE INDEX idx_robeing_diary_robeing ON robeing_diary(robeing_id);
|
||||
```
|
||||
|
||||
**activity_log 테이블**:
|
||||
```sql
|
||||
CREATE TABLE activity_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
robeing_id VARCHAR(50) NOT NULL,
|
||||
activity_type VARCHAR(50) NOT NULL, -- 'skill', 'scheduler', 'internal'
|
||||
skill_name VARCHAR(100),
|
||||
status VARCHAR(20) NOT NULL, -- 'success', 'error', 'partial'
|
||||
result_summary TEXT,
|
||||
error_message TEXT,
|
||||
metadata JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX idx_activity_log_robeing_date ON activity_log(robeing_id, created_at DESC);
|
||||
CREATE INDEX idx_activity_log_type ON activity_log(activity_type);
|
||||
```
|
||||
|
||||
**참고**: `rb8001/app/state/database.py:44-57` (ConversationLog 모델), `rb8001/app/models/intent_review_model.py:11-32` (IntentReviewQueue 모델)
|
||||
|
||||
### 스킬 실행 로그 기록
|
||||
|
||||
**위치**: 스킬 실행 래퍼 함수 또는 미들웨어
|
||||
- `rb8001/app/services/skills/` 내 각 스킬의 `handle()` 메서드 시작/종료 시 기록
|
||||
- 또는 `rb8001/app/router/router.py`의 스킬 호출 부분에 데코레이터/미들웨어 추가
|
||||
|
||||
**기록 내용**: 스킬명, 실행 시간, 결과(success/error), 에러 메시지(있을 경우), 메타데이터
|
||||
|
||||
### API 엔드포인트
|
||||
|
||||
**rb8001**: `GET /api/diary/{date}?robeing_id=rb8001`
|
||||
- 요청: `date` (YYYY-MM-DD), `robeing_id` (선택, 기본값: rb8001)
|
||||
- 응답: `{"date": "2025-12-09", "robeing_id": "rb8001", "content": "# 로빙 일기...", "summary": "...", "dominant_emotion": "happiness"}`
|
||||
- 구현 위치: `rb8001/app/router/diary.py` (새 파일) 또는 `rb8001/app/router/router.py`
|
||||
|
||||
**참고**: `rb8001/app/state/state_service.py:179-207` (conversation 로그 API 패턴)
|
||||
|
||||
### 스케줄러 등록
|
||||
|
||||
**위치**: `rb8001/main.py:146-195` (startup_event 함수)
|
||||
- `rb8001/app/scheduler/jobs/diary_generator.py` 생성
|
||||
- `scheduler.add_job(diary_generator.generate_diary, 'cron', hour=2, minute=0, id='daily_diary')` 등록
|
||||
|
||||
**참고**: `rb8001/app/scheduler/jobs/naverworks_briefing.py` (스케줄러 작업 예시)
|
||||
|
||||
### LLM 프롬프트 템플릿
|
||||
|
||||
**입력**: 집계된 데이터 (JSON)
|
||||
**출력**: 마크다운 형식 일기
|
||||
**템플릿 구조**:
|
||||
```
|
||||
다음 데이터를 바탕으로 로빙의 하루 일기를 작성하세요:
|
||||
- 대화: {conversations_summary}
|
||||
- 활동: {activities_summary}
|
||||
- 감정: {emotions_summary}
|
||||
- 문제: {issues_summary}
|
||||
- 성장: {growth_summary}
|
||||
|
||||
형식:
|
||||
# 로빙 일기 – {date}
|
||||
## 오늘 한 일
|
||||
...
|
||||
## 감정 상태
|
||||
...
|
||||
## 문제와 배운 점
|
||||
...
|
||||
## 내일 계획
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 구현 단계
|
||||
|
||||
1. Diary Aggregator 스키마 정의
|
||||
2. TDD 테스트 작성
|
||||
3. 집계 로직 + md 템플릿 구현
|
||||
4. DB/파일 저장 연결
|
||||
5. 스케줄러 등록 (매일 자정)
|
||||
1. ✅ **DB 테이블 생성**: `robeing_diary`, `activity_log` 테이블 생성 완료 (`rb8001/app/state/diary_repository.py`)
|
||||
2. ⏳ **활동 로그 기록**: 스킬 실행 시 `activity_log`에 자동 기록 로직 추가
|
||||
3. ⏳ **Diary Aggregator 구현**: `rb8001/app/services/diary/aggregator.py` 생성, 모든 데이터 소스 집계
|
||||
4. ⏳ **일기 생성 로직**: `rb8001/app/services/diary/generator.py` 생성, LLM으로 일기 텍스트 생성
|
||||
5. ⏳ **스케줄러 등록**: `rb8001/app/scheduler/jobs/diary_generator.py` 생성, `main.py`에 등록
|
||||
6. ⏳ **API 엔드포인트**: `rb8001/app/router/diary.py` 생성, `/api/diary/{date}` 구현
|
||||
7. ⏳ **관리자 대시보드**: admin-dashboard에 일기 목록/상세 페이지 추가
|
||||
8. ⏳ **DOCS 동기화 스크립트**: 선택적으로 별도 스크립트로 DOCS 동기화
|
||||
|
||||
## 진행 상황
|
||||
|
||||
**완료 (2025-12-09)**:
|
||||
- DB 테이블 스키마 정의 및 생성 (`_ensure_tables()`)
|
||||
- Repository 함수 구현 (`save_diary`, `get_diary`, `save_activity_log`)
|
||||
- 테스트 완료 (더미 데이터 저장/조회 검증)
|
||||
|
||||
**다음 단계**: Diary Aggregator 및 일기 생성 로직 구현
|
||||
|
||||
---
|
||||
|
||||
## UX 시나리오
|
||||
|
||||
### 1. 자동 생성 (매일 오전 2시 또는 3시)
|
||||
- rb8001이 전날(00:00~23:59:59) 데이터 집계
|
||||
- `conversation_log`, `activity_log`, `emotion_readings`, `robeing`, `intent_review_queue`, 애플리케이션 로그 수집
|
||||
- LLM으로 일기 생성 후 `robeing_diary` 테이블에 저장
|
||||
|
||||
### 2. 운영자 조회 (관리자 대시보드)
|
||||
- `https://ro-being.com/admin/diary` 접속
|
||||
- 일기 목록 페이지: 날짜별 목록(최신순, 로빙별 필터)
|
||||
- 상세 페이지: `/api/diary/{date}` 호출 → 마크다운 렌더링
|
||||
- 필터/검색: 감정, 키워드, 로빙별
|
||||
|
||||
### 3. 활동 로그 기록
|
||||
- 스킬 실행 시 `activity_log` 테이블에 자동 기록
|
||||
- 일기 집계 시 "오늘 한 일" 섹션에 포함
|
||||
|
||||
### 4. DOCS 동기화 (선택적)
|
||||
- 별도 스크립트로 `DOCS/journey/diary/rb8001/yymmdd_주제.md`에 주기적 동기화
|
||||
|
||||
---
|
||||
|
||||
|
||||
82
journey/plans/251209_rb8001_calendar_intent_overlap_plan.md
Normal file
82
journey/plans/251209_rb8001_calendar_intent_overlap_plan.md
Normal file
@ -0,0 +1,82 @@
|
||||
# rb8001 캘린더 조회/생성 의도 경계 세부 설계
|
||||
|
||||
**날짜**: 2025-12-09
|
||||
**목표**: calendar_query vs calendar_event 경계 케이스를 UX/TDD 기준으로 명확히 정의하고, 3단계 의도 아키텍처와 일관되게 구현한다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 현재 상태 정리
|
||||
|
||||
- FastPath 정규식이 `calendar_query`를 `calendar_event`보다 우선 매칭하여, 조회·생성이 섞인 문장도 대부분 `calendar_query`로 고정됨.
|
||||
- 의도 패턴: `rb8001/app/services/brain/decision_engine.py:120-180`
|
||||
- 3단계 의도 파이프라인(Goal → ActionPlan → SkillSequence)은 도입되었지만, 캘린더 조회/생성 경계에는 아직 적극적으로 사용되지 않음.
|
||||
- 메타데이터 파이프라인: `rb8001/app/services/brain/decision_engine.py:540-629`
|
||||
- 기존 캘린더 테스트는 조회 vs 생성 분리, all-day 파싱, 승인 플로우에 초점.
|
||||
- 조회 vs 생성 TDD: `rb8001/tests/test_calendar_query_vs_create.py:1-220`
|
||||
- 로그 기반 시나리오: `rb8001/tests/test_intent_scenarios_from_logs.py:1-220`
|
||||
- 겹침 케이스 실험 스크립트: `rb8001/tests/test_calendar_intent_overlap_cases.py:1-80`
|
||||
|
||||
---
|
||||
|
||||
## 2. UX/의도 기준
|
||||
|
||||
- **조회 중심 문장**: "등록돼 있는지 확인", "일정 전체 확인", "스케줄 보여줘" → 기본 intent는 `calendar_query`.
|
||||
- **생성 중심 문장**: "일정 등록해줘/잡아줘/넣어줘" + 날짜·시간·타이틀 정보가 충분 → 기본 intent는 `calendar_event`.
|
||||
- **조회+생성 혼합 문장**: "있나 확인하고, 없으면 잡아줘", "필요하면 등록해줘" → 단일 intent로 강제하지 않고, ① 조회 → ② 조건부 생성 멀티 액션으로 다룬다.
|
||||
- UX 원칙: 애매하면 조용히 잘못 실행하지 말고, 한 번 더 물어보는 clarify를 사용한다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 설계 방향
|
||||
|
||||
### 3.1 FastPath 의도 판정 조정
|
||||
|
||||
- 조회/생성 정규식이 **동시에 매칭**되는 경우를 감지한다.
|
||||
- 이 경우 FastPath에서 바로 `calendar_query` 또는 `calendar_event`로 확정하지 않고, 상위 카테고리(예: `SCHEDULE_MANAGEMENT`) + 낮은 confidence로 내려 보낸다.
|
||||
- `"없으면 잡아줘"`, `"필요하면 등록해줘"` 등 조건부 생성 패턴은 별도 플래그로 표시하여 후속 단계에서 ActionPlan에 반영한다.
|
||||
|
||||
### 3.2 3단계 파이프라인 활용
|
||||
|
||||
- IntentAnalyzer/ActionPlanner에서 조회+생성 혼합 메시지를 **Goal: SCHEDULE_MANAGEMENT**로 해석한다.
|
||||
- ActionPlanner는 플래그/슬롯을 기준으로 다음 두 가지 플랜을 만든다.
|
||||
- Plan A: `[QUERY_CALENDAR]` (조회만)
|
||||
- Plan B: `[QUERY_CALENDAR, CONDITIONAL_CREATE_EVENT]` (없으면 등록)
|
||||
- SkillSelector는 Plan B에 대해 `CALENDAR.get_events` 후, 결과가 비어 있을 때만 `CALENDAR.create_event`를 실행하는 시퀀스를 생성한다.
|
||||
|
||||
### 3.3 Clarify·승인 흐름
|
||||
|
||||
- FastPath/IntentAnalyzer에서 의도 불확실(conf 낮거나 혼합)하면, LLM 기반 clarify 메시지를 생성한다.
|
||||
- 예: "먼저 내일 일정이 등록돼 있는지 확인하고, 없으면 일정까지 등록해드릴까요?"
|
||||
- 사용자가 "응/ㅇㅇ/그래" 등으로 승인하면 `calendar_approval`이 원래 Plan A/B를 기억한 상태에서 적절한 액션을 선택하도록 한다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 작업 항목 (하위 설계)
|
||||
|
||||
1. **의도 패턴/슬롯 확장**
|
||||
- 조회/생성 동시 매칭, `"없으면 잡아줘"`, `"필요하면 등록해줘"` 등을 감지하는 보조 패턴/슬롯 추가.
|
||||
- 위치: `rb8001/app/services/brain/decision_engine.py` 및 `app/services/brain/intent` 하위 모듈.
|
||||
2. **FastPath 의사결정 로직 개선**
|
||||
- `analyze_intent()`에서 캘린더 혼합 문장에 대해 단일 intent 강제 대신 상위 카테고리 + 플래그 반환.
|
||||
3. **ActionPlanner 확장**
|
||||
- `ActionPlanner.plan()`에서 SCHEDULE_MANAGEMENT + 플래그를 입력받아 `[QUERY]` vs `[QUERY→CONDITIONAL_CREATE]`를 구분.
|
||||
- 위치: `rb8001/app/services/brain/intent/action_planner.py`.
|
||||
4. **SkillSelector 멀티 액션 시퀀스**
|
||||
- `SkillSelector.select()`에서 CONDITIONAL_CREATE_EVENT를 지원하고, get_events 결과에 따라 create_event 실행 여부를 결정.
|
||||
- 위치: `rb8001/app/services/brain/intent/skill_selector.py`.
|
||||
5. **calendar_approval 행동 분기**
|
||||
- `DecisionEngine.decide_skill_sequence()` 또는 intent 파이프라인에서 `calendar_approval`이 직전 Plan A/B를 기억하도록 메타데이터 연결.
|
||||
6. **의도 경계 TDD 케이스 추가**
|
||||
- 위 10개 문장을 포함해 `"등록돼 있는지 확인"`, `"없으면 잡아줘"` 패턴을 `test_calendar_query_vs_create.py`, `test_intent_scenarios_from_logs.py`에 기대 intent/액션으로 고정.
|
||||
7. **리뷰 큐 연동 규칙**
|
||||
- calendar_query vs calendar_event margin이 작거나, 사용자 피드백(wrong/down)이 붙은 캘린더 케이스를 IntentReviewQueue에 자동 적재.
|
||||
- 위치: `rb8001/app/services/brain/intent_review.py`, `app/state/conversation_repository.py`.
|
||||
|
||||
---
|
||||
|
||||
## 5. 검증·운영
|
||||
|
||||
- `pytest rb8001/tests/test_calendar_query_vs_create.py rb8001/tests/test_intent_scenarios_from_logs.py`로 회귀 여부를 상시 확인한다.
|
||||
- 관리자용 Intent 리뷰 화면에서 캘린더 관련 샘플을 필터링하여, 조회↔생성 경계 오류를 집중 라벨링한다.
|
||||
- 일정 기간 운영 후, 리뷰 큐/로그 데이터를 기반으로 FastPath 정규식·threshold를 재튜닝하고 이 계획 문서를 `troubleshooting/` 문서로 승격한다.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user