- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동 - book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서) - 빈 폴더 제거 (journey/assets/*)
6.7 KiB
Intent 리뷰 큐 조회/라벨링 API 구현
작성일: 2025-11-16
작성자: admin
관련 문서: 390_human_in_the_loop_intent_learning.md
1. 목적
관리자가 IntentReviewQueue의 status='pending' 항목을 조회하고, true_intent를 라벨링하여 status='confirmed' 또는 status='corrected'로 변경할 수 있는 REST API를 구현한다.
기대 효과: 사용자 피드백과 에러 케이스를 수집한 리뷰 큐를 관리자가 라벨링하여, 이후 재학습 배치 스크립트에서 활용할 수 있게 한다.
2. 관리자 시나리오
2.1 리뷰 큐 조회
- 관리자가 "오늘 처리해야 할 리뷰 항목"을 조회
status='pending'필터링- 페이지네이션 지원 (기본 20개, 최대 100개)
- 정렬:
created_at DESC(최신순)
2.2 라벨링
- 관리자가 특정 항목의
message,predicted_intent,alternatives를 확인 - 올바른 의도를 판단하여
true_intent입력 status업데이트:predicted_intent == true_intent→status='confirmed'predicted_intent != true_intent→status='corrected'
2.3 통계 조회
- 전체 리뷰 큐 수
status별 집계 (pending/confirmed/corrected)- 의도별 분포
3. API 스펙
3.1 GET /api/intent-review/queue
목적: 리뷰 큐 조회 (필터링/페이지네이션)
Query Parameters:
status(optional):pending|confirmed|corrected(기본값:pending)page(optional): 페이지 번호 (기본값: 1)limit(optional): 페이지 크기 (기본값: 20, 최대: 100)intent(optional): 의도 필터 (예:calendar_query)
Response:
{
"items": [
{
"id": 1,
"conversation_log_id": 123,
"user_id": "00000000-0000-0000-0000-000000000001",
"message": "오늘 일정 정리해줘",
"predicted_intent": "calendar_event",
"predicted_confidence": 0.55,
"alternatives": [
{"intent": "calendar_query", "score": 0.52}
],
"user_feedback": "down",
"error": false,
"status": "pending",
"true_intent": null,
"created_at": "2025-11-16T07:00:00Z",
"updated_at": "2025-11-16T07:00:00Z"
}
],
"total": 42,
"page": 1,
"limit": 20,
"total_pages": 3
}
3.2 PUT /api/intent-review/{id}/label
목적: 리뷰 항목 라벨링
Request Body:
{
"true_intent": "calendar_query"
}
Response:
{
"success": true,
"id": 1,
"status": "corrected",
"true_intent": "calendar_query",
"updated_at": "2025-11-16T08:00:00Z"
}
로직:
predicted_intent == true_intent→status='confirmed'predicted_intent != true_intent→status='corrected'updated_at자동 갱신
3.3 GET /api/intent-review/stats
목적: 리뷰 큐 통계
Response:
{
"total": 100,
"by_status": {
"pending": 42,
"confirmed": 35,
"corrected": 23
},
"by_intent": {
"calendar_query": 15,
"calendar_event": 12,
"email_query": 8
}
}
4. 구현 계획
4.1 코드 구조 (원칙 준수)
app/
├── models/
│ └── intent_review_model.py # IntentReviewQueue 모델 (state/database.py에서 이동)
├── state/
│ └── intent_review_repository.py # CRUD 캡슐화 (신규)
└── router/
└── intent_review_endpoint.py # API 엔드포인트 (신규)
4.2 작업 순서
-
TDD: 테스트 작성 (
tests/test_intent_review_api.py)- 리뷰 큐 조회/필터링/페이지네이션
- 라벨링 (confirmed/corrected 상태 전이)
- 통계 집계
-
모델 분리 (
app/models/intent_review_model.py)app/state/database.py의IntentReviewQueue이동- Base import 경로 정리
-
Repository 생성 (
app/state/intent_review_repository.py)get_review_queue(status, page, limit, intent_filter)label_review_item(id, true_intent)get_review_stats()
-
DB 테이블 생성
create_tables()호출 또는 마이그레이션 스크립트- 기존 테이블 존재 여부 확인 로직
-
API 엔드포인트 구현 (
app/router/intent_review_endpoint.py)- FastAPI router 정의
- Pydantic 스키마 (Request/Response)
- JWT 인증 (관리자 권한 검증 필요 시)
-
기존 코드 리팩토링
app/state/conversation_repository.py: 새 repository 사용app/router/feedback_handler.py: 새 repository 사용
5. 인증/권한
현재: JWT 기반 get_current_user 사용
향후: 관리자 권한 체크 추가 고려 (현재는 모든 인증된 사용자 허용)
6. 체크리스트
- 테스트 작성 완료
- 모델 분리 완료 (
app/models/intent_review_model.py) - Repository 구현 완료 (
app/state/intent_review_repository.py) - DB 테이블 생성 확인 (
scripts/create_intent_review_queue_table.py실행 완료) - API 엔드포인트 구현 완료 (
app/router/intent_review_endpoint.py) - 기존 코드 리팩토링 완료 (
conversation_repository,feedback_handler) - 통합 테스트 통과 (Repository 테스트 6개 통과)
- 실제 API 테스트 통과 (통계/조회/라벨링 모두 성공)
7. 실제 API 테스트 결과
테스트 일시: 2025-11-17
테스트 환경: rb8001 컨테이너 (로컬)
테스트 결과
-
GET /api/intent-review/stats ✅
{ "total": 2, "by_status": {"pending": 1, "confirmed": 0, "corrected": 1}, "by_intent": {"calendar_event": 2} } -
GET /api/intent-review/queue?status=pending ✅
- 페이지네이션 정상 작동
- 필터링 정상 작동
- JSON 응답 형식 정확
-
PUT /api/intent-review/{id}/label ✅
{ "success": true, "id": 2, "status": "corrected", "true_intent": "calendar_query", "updated_at": "2025-11-17T02:26:05.148402" }predicted_intent != true_intent→status='corrected'정상 작동
Repository 테스트 결과
test_get_review_queue_pending_only: ✅ 통과test_get_review_queue_pagination: ✅ 통과test_get_review_queue_intent_filter: ✅ 통과test_label_review_item_confirmed: ✅ 통과test_label_review_item_corrected: ✅ 통과test_get_review_stats: ✅ 통과
8. 교훈
- TDD로 관리자 시나리오 전체를 안전하게 검증
- 모델/리포지토리 분리로 책임 명확화 및 확장성 확보
- DB 테이블 생성/마이그레이션을 함께 처리하여 배포 시 "테이블 없음" 오류 방지
- 코드 작성 원칙 준수: 모델은
app/models/, Repository는app/state/로 분리