본문으로 건너뛰기

Drift Monitoring UI

GenD /admin/drift 대시보드는 등록된 MLflow 모델별 데이터 드리프트 보고서를 시각화하고, 관리자에게 다음 4 가지 운영 액션을 제공합니다.

Dashboard 진입 — 모델 선택 + 시계열 + 보고서 목록 (#1535 follow-up #1)

demo_credit_risk 모델 선택 후 prod AKS UI (gend.genon.ai) 의 실 캡쳐 — #1626 batch_predict feature sink + 분포 shift seed + drift compute 결과:

Drift Dashboard 리스트 — score=1.0 breach 추이

상단 — MLflow 등록 모델 picker (datalist + Apply + 새로고침).
중단 — 드리프트 점수 추이 sparkline. 5건 보고서 (좌=옛 stub, 우=신규 1.000 breach) — 분포 shift 후 실 KS 결과 가 sparkline 우측 끝으로 급상승.
하단 — 보고서 표: 최신 row drift_score=1.000 / status=breach / rows=10 / 트리거=수동 / 알림 발송: 6/2/2026 5:39 PM (notification 자동 dispatch).

리포트 상세 — DriftReportDetailSheet + KS p-value chart (#1567)

표의 "상세" (👁) 버튼 클릭 → 우측 슬라이드 sheet:

Drift Report DetailSheet — KS p-value bar chart 실 데이터

  • 메타 블록: drift_score=1.0, rows=10, Reference MLflow Run 8f065881... (#1564 baseline 첨부 run), 윈도우 6/1~6/3, ML Batch Run, 알림 발송 시각, 생성일
  • admin 액션: "상태 오버라이드" / "삭제" 버튼. 본 보고서는 notified → "감사 보존을 위해 이 보고서는 삭제할 수 없습니다" 안내
  • 피처별 P-VALUE 차트 (#1567): KS p-value horizontal bar chart 가 실 데이터로 렌더 — income: 1.1e-5, credit_history_len: 2.2e-4, age: 0.002 모두 빨강 (p<0.01 strong drift). 하단 표 도 동일 정보 표시

M3 실 구현 검증 (#1617 — 2026-06-02)

#1565 ML-B 의 drift_service M3 실 구현 + #1618 Dagster prod 재배포 + #1617 schema/boto3 fix 가 모두 prod 에 반영된 후의 동작:

M3 — 신규 모델 빈 상태 (보고서 0건)

demo_credit_risk_plugin 선택 시 보고서 0건. "드리프트 계산" 트리거 시:

reference_run 상태결과
baseline artifact 보유 + sink table 존재200 OK + 의미있는 drift_score + drifted_features
baseline artifact 보유 + sink table 부재422 DriftCurrentEmptyErrorTABLE_NOT_FOUND 명시 (silent fail 금지)
baseline artifact 미보유 (옛 학습)422 DriftBaselineMissingError — tag gend.drift.baseline 부재 명시

본 검증에서 silent score=0 (M2 stub) 행위가 완전 제거 확인 — 의미있는 422 raise 가 router 의 새 매핑으로 UI toast 노출.

실 데이터 시드 prerequisite (#1626) — 완료 (2026-06-02)

#1626 (PR #1629 머지) 로 batch_predict_asset 가 prediction 과 함께 input feature value 도 sink. sink schema = customer_id (VARCHAR) + age/income/credit_history_len (DOUBLE) + prediction (DOUBLE) + ml_batch_run_id (VARCHAR) + predicted_at (TIMESTAMP).

운영 배포 (#1632, 2026-06-02):

  1. ✅ Dagster image 재빌드 (0.2.20260602-b7009873) + rollout
  2. DROP TABLE iceberg.gold.predictions_demo_credit_risk (옛 4-컬럼)
  3. ✅ silver seed (10 row, 분포 shift) + ml_batch_demo_credit_risk_job 머티리얼라이즈 → 새 7-컬럼 sink
  4. POST /api/v1/models/demo_credit_risk/drift/computedrift_score=1.0 / status=breach / drifted_features={income: 1.1e-5, credit_history_len: 2.2e-4, age: 0.002}

→ 본 가이드의 dashboard-list + DetailSheet 캡쳐가 실 KS p-value chart 노출 완료.

Distribution Overlay (#1567 Cycle 1 — 2026-06-03)

기존 KS p-value horizontal bar (#1567 이전) + drifted_features table 아래에 distribution overlay panel 추가. 다른 솔루션 (Databricks Lakehouse Monitoring / Arize / Evidently / WhyLabs / Fiddler) 의 표준 패턴.

구성:

  • 상단: feature 선택 Radix Tabs (numeric column 별)
  • 본문: Recharts <ComposedChart> overlay — reference (회색) + current (빨강) bar
  • 하단: summary stat 비교 table — mean / std / p5 / p25 / p50 / p75 / p95 양쪽

Backend endpoint:

GET /api/v1/models/{model_name}/drift/{report_id}/distribution
  • admin only + workspace fence (require_admin)
  • lazy — DetailSheet 열릴 때만 호출 → drift_report row 크기 영향 0
  • 422 매핑 (silent fail 금지):
    • reference_run_id NULL (옛 stub) → DriftDistributionUnavailableError
    • MLflow baseline 부재 → DriftBaselineMissingError
    • Trino sink 부재 / 윈도우 0건 → DriftCurrentEmptyError
    • common numeric column 0 → DriftDistributionEmptyError (#1626 prerequisite)

Frontend cache:

  • zustand in-memory distributions: Record<report_id, DistributionProfile>
  • explicit invalidate 만 새로고침 (sheet 닫혀도 유지)

Cycle 2 / 3 의 후속:

  • PSI / Wasserstein / JS divergence (Cycle 2)
  • Categorical chi-square (Cycle 2)
  • Threshold editor (Cycle 2)
  • Alert rule editor + auto-dispatch (Cycle 3)
액션HTTP경로권한
보고서 목록 / 단건 조회GET/api/v1/models/{name}/drift[?…] / /{report_id}user (workspace fence)
수동 계산 (Compute)POST/api/v1/models/{name}/drift/computeadmin
상태 오버라이드PUT/api/v1/models/{name}/drift/{report_id}admin
소프트 삭제DELETE/api/v1/models/{name}/drift/{report_id}admin

배경 컨텍스트:

  • 백엔드 PoC: PR #1217 — GET /drift + POST /drift/compute.
  • 백엔드 M2 mutation contract: PR #1225 — PUT / DELETE + 알림 처리 분리.
  • 백엔드 batch integration: ML Batch run completion 시 evaluate_drift_with_baseline() 가 자동으로 보고서를 생성하고 NotificationService 로 발송합니다.
  • UI: PR #이슈 #1213 — 본 대시보드.

페이지 구조

/admin/drift
├── Header # 페이지 제목 + "드리프트 계산" 버튼 (admin)
├── Model picker # MLflow 등록 모델 datalist + Apply
├── Sparkline chart # 선택 모델의 drift_score 시계열 (newest-rightmost)
├── Report table # 보고서 목록 (Created · Version · Score · Status · Rows · Trigger · Notified)
├── DriftReportDetailSheet # 우측 슬라이드: 메타 + 피처별 p-value
├── DriftComputeDialog # 수동 계산 (Reference Run ID + window + 옵션 threshold/version)
├── DriftOverrideDialog # 관리자 상태 오버라이드 (사유 ≥ 3자)
└── DeleteDialog # AlertDialog — soft delete 확인

운영자 워크플로우

1) 모델 선택

  1. 사이드바 하단 ⚙ 관리 콘솔운영 & 모니터링드리프트 모니터링 클릭.
  2. "MLflow Registered Model" 입력란에 모델명 (예: credit_risk) 입력 또는 datalist 드롭다운에서 선택.
  3. Apply 버튼 클릭 → GET /api/v1/models/{name}/drift?limit=50&offset=0 호출.

만약 보고서가 없으면 빈 상태 카드가 표시됩니다. 처음 모델 등록 후 수동 계산을 한 번 수행하거나, ML Batch run 이 자동 생성하기를 기다리세요.

2) 시계열 분석

buildSparklinePoints() 헬퍼가 newest-first (created_at DESC) 응답을 뒤집어 오른쪽이 최신이 되도록 SVG polyline 을 그립니다. Y 축은 관측 범위로 normalize 하되 최소 span 0.05 를 보장하므로 평탄한 0 값 시리즈도 보입니다.

3) 보고서 상세

테이블 행의 View 를 클릭하면 우측 슬라이드 시트가 열리며 다음을 표시합니다.

  • 메타: reference run id, 평가 윈도우, ml_batch_run_id, notified_at, created_at.
  • 피처별 p-value 표 (drifted_features dict 가 정렬되어 노출).
  • 관리자 액션 버튼: Override Status, Delete.

notified_at 이 NULL 이 아닌 보고서의 Delete 버튼은 자동으로 비활성화됩니다. 백엔드가 동일한 조건에서 409 를 반환하므로 라운드트립을 사전 차단합니다.

4) 수동 계산 (Compute)

상단 드리프트 계산 버튼 → 다이얼로그.

필드필수비고
Reference MLflow Run ID필수drift_baseline.npz artifact 가 첨부된 학습 run 의 ID
Window Start / End필수datetime-local picker, 기본값은 오늘 00:00 ~ 현재
Model Version선택NULL = alias 에서 자동 해석
Threshold선택[0, 1] 범위, NULL = MLBatchJob.drift_threshold

성공 시 sonner toast 로 score / status 표시 + 보고서 목록 자동 갱신.

5) 상태 오버라이드

행의 Override 또는 상세 시트의 Override Status 클릭.

  • 새 상태: ok / warn / breach.
  • 오버라이드 사유: 최소 3자, 감사 로그에 영구 기록.

백엔드는 AuditMiddleware 의 request-body capture + 구조화된 drift_status_override 로그라인으로 이중 기록합니다.

6) 소프트 삭제

행의 Delete 또는 상세 시트의 Delete 클릭 → AlertDialog 확인.

  • 삭제 대상이 notified_at != null 이면 버튼 자체가 비활성화 (감사 보존).
  • 백엔드는 행을 보존하되 후속 로직에서 무시합니다 (soft delete).

권한 매트릭스

액션non-admin useradmin
보고서 목록 / 단건 조회OK (workspace fence)OK
Compute버튼 disabled + 403OK
Override버튼 disabled + 403OK
Delete버튼 disabled + 403OK (notified=null 만)

UI 가 버튼을 disabled 처리하지만 백엔드 require_admin 이 최종 진실의 원천입니다.

API 호출 흐름

operator clicks Apply
→ useDriftStore.setModelName(name)
→ useDriftStore.fetchReports(name)
→ GET /api/v1/models/{name}/drift?limit=50&offset=0
→ set reports[]

operator clicks Compute (admin)
→ DriftComputeDialog 검증 (reference_run_id + window + threshold)
→ useDriftStore.compute(name, body)
→ POST /api/v1/models/{name}/drift/compute
→ 성공 시 fetchReports(name) 재실행
→ 토스트 (score, status) 표시

operator clicks Override (admin)
→ DriftOverrideDialog 검증 (drift_status + override_reason ≥ 3)
→ useDriftStore.updateStatus(name, id, body)
→ PUT /api/v1/models/{name}/drift/{id}
→ 성공 시 reports[] in-place 갱신 (refetch 없음)
→ 토스트 (새 status) 표시

operator clicks Delete (admin, notified=null only)
→ AlertDialog 확인
→ useDriftStore.deleteReport(name, id)
→ DELETE /api/v1/models/{name}/drift/{id}
→ 성공 시 fetchReports(name) 재실행
→ 토스트 (id) 표시

트러블슈팅

증상원인 / 조치
Apply 후 빈 상태보고서가 아직 없음 — /admin/ml-batch 의 잡이 완료됐는지 확인하거나 수동 계산
Compute 시 422 "reference_run_id"MLflow run 이 없거나 drift_baseline.npz artifact 가 첨부되지 않음
Compute 시 422 "model_version"명시한 버전이 MLflow registry 에 없음 — NULL 로 두면 alias 자동 해석
Override 시 422 "override_reason"사유가 3자 미만 — Pydantic min_length=3
Delete 시 409 "notified report"알림이 이미 발송된 보고서 — 감사 보존 정책상 삭제 불가
403 모든 mutationadmin 권한 부재 — Keycloak realm role 확인

실 run 결과 캡쳐 SOP (#1535)

audit wonmoc13s (#1531) deferred — 기존 05-admin-drift-authenticated.png (cycle 15 캡쳐) 는 model picker idle 상태. baseline+current 데이터 보유 모델의 실 drift 결과 (drift_score / PSI / KS p-value chart) PNG 가 부재했다.

본 캡쳐를 갱신하려면 다음 seed orchestration 이 prerequisite:

prerequisite — seed orchestration 절차

  1. MLflow registered model 등록

    • 이미 prod 에 등록된 모델이 있는지 확인:
      kubectl --context aks-genos-prod -n gend port-forward svc/mlflow 5000:5000 &
      curl -s http://localhost:5000/api/2.0/mlflow/registered-models/list | jq '.registered_models | length'
    • 0건이면 ML Plugin train 가이드 (ml-plugin-train.md) 의 Stage 2-4 를 1회 수행해 registry 에 1개 모델 등록.
  2. baseline + current 데이터 보유 확인

    • drift compute 는 baseline run 의 drift_baseline.npz artifact + 현재 데이터 window 두 개를 모두 요구.
    • baseline run 확인:
      curl -s "http://localhost:5000/api/2.0/mlflow/runs/search?experiment_ids=<id>" \
      | jq '.runs[] | select(.data.tags[]?.key == "drift_baseline") | .info.run_id'
  3. drift compute trigger

    • GenD UI /admin/drift → 모델 선택 → "드리프트 계산" 버튼 → reference_run_id 입력 → Submit.
    • 또는 API 직접 (#1597 #1557 Minor — backend pydantic schema 정합):
      WINDOW_START=$(date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)
      WINDOW_END=$(date -u +%Y-%m-%dT%H:%M:%SZ)
      curl -X POST "https://gend.genon.ai/api/v1/models/<name>/drift/compute" \
      -H "Authorization: Bearer $ADMIN_TOKEN" \
      -H "Content-Type: application/json" \
      -d "{\"reference_run_id\":\"<run_id>\",\"current_data_window_start\":\"$WINDOW_START\",\"current_data_window_end\":\"$WINDOW_END\"}"
  4. 결과 PNG 캡쳐

    • Playwright password grant 패턴 (cli-sso.md 참고) 으로 /admin/drift 접속, 모델 선택 → 보고서 row 클릭 → DriftReportDetailSheet 의 시계열 차트 + 피처별 p-value 풀 렌더 대기 (page.waitForSelector('table tbody tr')).
    • page.screenshot({path: 'docs-site/static/img/m3-cycle/07-admin-drift-real-run.png', fullPage: true}).
  5. 본 가이드 / drift-monitoring.md 의 placeholder 교체

    • 기존 idle 캡쳐 (05-admin-drift-authenticated.png) 옆에 실 run 결과 캡쳐 07-admin-drift-real-run.png 를 nominative 배치.

본 PR (#1535) 의 scope

SOP 가이드 문서화만 — 실 PNG 캡쳐는 prerequisite seed orchestration 완료 후 follow-up PR 에서 진행.

deferred 사유: prod MLflow registry 에 baseline+current 데이터 보유 모델이 등록 돼 있는 상태가 prerequisite. seed 작업이 단일 worktree-ship turn 의 scope 를 초과 (자체 plugin install + train 1회 + drift baseline metadata 등록 등 다단계).

관련 문서