DOCS/troubleshooting/251116_admin_intent_review_queue_api_implementation.md
Claude-51124 b65881f835 docs: Intent 리뷰 큐 API 구현 완료 및 테스트 결과 반영
- 251116_admin_intent_review_queue_api_implementation.md: 실제 API 테스트 결과 추가
- 390_human_in_the_loop_intent_learning.md: 체크리스트 업데이트 (라벨링 API 완료 표시)
2025-11-17 11:26:34 +09:00

6.7 KiB

Intent 리뷰 큐 조회/라벨링 API 구현

작성일: 2025-11-16
작성자: admin
관련 문서: 390_human_in_the_loop_intent_learning.md


1. 목적

관리자가 IntentReviewQueuestatus='pending' 항목을 조회하고, true_intent를 라벨링하여 status='confirmed' 또는 status='corrected'로 변경할 수 있는 REST API를 구현한다.

기대 효과: 사용자 피드백과 에러 케이스를 수집한 리뷰 큐를 관리자가 라벨링하여, 이후 재학습 배치 스크립트에서 활용할 수 있게 한다.


2. 관리자 시나리오

2.1 리뷰 큐 조회

  1. 관리자가 "오늘 처리해야 할 리뷰 항목"을 조회
  2. status='pending' 필터링
  3. 페이지네이션 지원 (기본 20개, 최대 100개)
  4. 정렬: created_at DESC (최신순)

2.2 라벨링

  1. 관리자가 특정 항목의 message, predicted_intent, alternatives를 확인
  2. 올바른 의도를 판단하여 true_intent 입력
  3. status 업데이트:
    • predicted_intent == true_intentstatus='confirmed'
    • predicted_intent != true_intentstatus='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_intentstatus='confirmed'
  • predicted_intent != true_intentstatus='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 작업 순서

  1. TDD: 테스트 작성 (tests/test_intent_review_api.py)

    • 리뷰 큐 조회/필터링/페이지네이션
    • 라벨링 (confirmed/corrected 상태 전이)
    • 통계 집계
  2. 모델 분리 (app/models/intent_review_model.py)

    • app/state/database.pyIntentReviewQueue 이동
    • Base import 경로 정리
  3. Repository 생성 (app/state/intent_review_repository.py)

    • get_review_queue(status, page, limit, intent_filter)
    • label_review_item(id, true_intent)
    • get_review_stats()
  4. DB 테이블 생성

    • create_tables() 호출 또는 마이그레이션 스크립트
    • 기존 테이블 존재 여부 확인 로직
  5. API 엔드포인트 구현 (app/router/intent_review_endpoint.py)

    • FastAPI router 정의
    • Pydantic 스키마 (Request/Response)
    • JWT 인증 (관리자 권한 검증 필요 시)
  6. 기존 코드 리팩토링

    • 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 컨테이너 (로컬)

테스트 결과

  1. GET /api/intent-review/stats

    {
        "total": 2,
        "by_status": {"pending": 1, "confirmed": 0, "corrected": 1},
        "by_intent": {"calendar_event": 2}
    }
    
  2. GET /api/intent-review/queue?status=pending

    • 페이지네이션 정상 작동
    • 필터링 정상 작동
    • JSON 응답 형식 정확
  3. 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_intentstatus='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/로 분리