Skip to content

AI PLAN 결정을 ANALYZE에 재사용 - #138

Merged
krestar merged 8 commits into
mainfrom
feat/137-plan-intent-contract
Aug 11, 2026
Merged

AI PLAN 결정을 ANALYZE에 재사용#138
krestar merged 8 commits into
mainfrom
feat/137-plan-intent-contract

Conversation

@hywznn

@hywznn hywznn commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

한눈에 보기

PLAN에서 한 번 결정한 대표 Intent와 Workflow를 ANALYZE에서 그대로 재사용합니다.
지원하지 않는 발화는 OUT_OF_SCOPE로 PLAN에서 정상 종료하며, Slot 조회와 ANALYZE를 호출하지 않습니다.

왜 필요한가요?

기존 흐름에는 두 가지 문제가 있었습니다.

  1. PLAN에서 EXPIRY_RENEWAL / WF-STY-001을 결정한 뒤 ANALYZE가 같은 발화를 다시 분류했습니다.
    • 모델 호출이 중복됩니다.
    • PLAN과 ANALYZE의 Intent 또는 Workflow가 달라질 수 있습니다.
    • A.X 추론 시간이 ANALYZE에서도 다시 발생합니다.
  2. AI가 지원 범위 밖 발화에 OUT_OF_SCOPE와 빈 workflowId를 반환하면 Server가 이를 잘못된 Workflow로 거부했습니다.
    • 범위 밖 발화는 기술 장애가 아니라 정상적인 분석 결과여야 합니다.

이번 PR은 PLAN을 의사결정 단계, ANALYZE를 Slot 점검 단계로 분리합니다.

변경 후 흐름

지원 업무

HR 발화
  → PLAN: Intent + Workflow + evidence 결정
  → Server: PLAN 결정을 실행 이력에 보존
  → requiredFieldKeys만 DB에서 조회
  → ANALYZE: plannedIntent/plannedWorkflowId 재사용
  → Intent 모델 재호출 없이 Slot만 점검
  → NEEDS_INFO 또는 REVIEW_REQUIRED

지원 범위 밖 발화

"오늘 날씨 어때?"
  → PLAN: OUT_OF_SCOPE
  → Server: SUCCEEDED + OUT_OF_SCOPE 저장
  → SSE: COMPLETED
  → Slot 조회 없음
  → ANALYZE 호출 없음

계약 변경

PLAN 응답

PLAN의 대표 판단에 다음 값을 수용합니다.

{
  "detectedIntent": "EXPIRY_RENEWAL",
  "workflowId": "WF-STY-001",
  "evidence": "체류연장 준비해줘",
  "confidence": null,
  "confidenceSource": "UNAVAILABLE",
  "bertRoutingScore": 0.3088
}
  • A.X처럼 확률을 제공하지 않는 모델은 confidence=null, confidenceSource=UNAVAILABLE입니다.
  • BERT 라우팅 점수는 A.X confidence로 사용하지 않고 bertRoutingScore에 별도로 보존합니다.
  • evidence는 HR 원문의 substring이거나 null이어야 합니다.
  • evidenceextractedSlots의 가짜 Slot으로 저장하지 않습니다.
  • MVP에서는 대표 Intent와 Workflow 한 쌍만 처리합니다.

ANALYZE 요청

Server는 PLAN 결정을 기존 ai_attempt.analysis_input_json에 저장한 뒤 다음 필드로 전달합니다.

{
  "phase": "ANALYZE",
  "analysisInput": {
    "plannedIntent": "EXPIRY_RENEWAL",
    "plannedWorkflowId": "WF-STY-001"
  }
}
  • ANALYZE Candidate의 workflowIdplannedWorkflowId와 반드시 같아야 합니다.
  • PLAN confidence는 Intent 분류 이력이며 Candidate confidence로 복사하지 않습니다.
  • Candidate confidence는 nullable이며 값이 있을 때만 0..1 범위를 검증합니다.
  • PLAN 결정을 재사용해 Provider를 호출하지 않은 ANALYZE는 providerAttemptCount=0을 허용합니다.

OUT_OF_SCOPE 응답

계약 버전을 1.1.0으로 올리고 PLAN 전용 정상 결과를 추가했습니다.

{
  "outcome": "OUT_OF_SCOPE",
  "contextRequirement": null,
  "questions": [],
  "candidates": [],
  "validationErrors": [],
  "versions": {
    "contractVersion": "1.1.0"
  }
}

Server는 다음 조건을 모두 검증합니다.

  • OUT_OF_SCOPE는 PLAN에서만 허용
  • contextRequirement, 질문, Candidate, validation error가 없어야 함
  • 정상 실행 결과이므로 AiRun 상태는 SUCCEEDED
  • 공개 이벤트는 기존 클라이언트 계약을 유지해 COMPLETED
  • CONTEXT_REQUIRED가 아니므로 Slot resolution과 ANALYZE를 실행하지 않음

DB 변경

  • V40__allow_nullable_ai_candidate_confidence.sql
    • ai_candidate.confidence를 nullable로 변경합니다.
  • V41__add_ai_run_out_of_scope_outcome.sql
    • ai_run.analysis_outcome 체크 제약에 OUT_OF_SCOPE를 추가합니다.

기존 migration을 수정하지 않고 새 migration으로 제약을 확장했습니다.

A.X cold start 제한시간

같은 브랜치의 최신 변경에서 A.X 최초 모델 로딩을 고려해 Runtime 전체 제한시간을 설정값으로 관리하고 기본값을 240초로 조정했습니다.

  • PLAN 최초 cold start가 기존 10~15초 고정 제한에 막히지 않습니다.
  • 이후 요청도 동일한 deadline policy를 사용합니다.
  • 운영 환경에서는 GPU와 실제 cold start 측정값에 맞춰 설정을 조정할 수 있습니다.

Server가 거부하는 주요 경우

상황 결과
PLAN과 다른 Candidate Workflow UNEXPECTED_WORKFLOW
HR 원문에 없는 evidence INVALID_RESPONSE_CONTRACT
confidenceSource=UNAVAILABLE인데 confidence 존재 INVALID_RESPONSE_CONTRACT
confidence 또는 BERT score가 0..1 INVALID_RESPONSE_CONTRACT
ANALYZE에 planned 결정 누락 INVALID_REQUEST_CONTRACT
OUT_OF_SCOPE가 ANALYZE에서 반환됨 INVALID_RESPONSE_CONTRACT
OUT_OF_SCOPE에 context/질문/Candidate/error 포함 INVALID_RESPONSE_CONTRACT
계약 버전이 1.1.0과 다름 CONTRACT_VERSION_MISMATCH

자동 테스트 시나리오

시나리오 확인 내용
A.X PLAN nullable confidence와 별도 BERT routing score 수용
BERT PLAN PLAN confidence와 nullable Candidate confidence 분리
PLAN 결정 재사용 ANALYZE wire에 planned Intent/Workflow 포함
Provider 미호출 ANALYZE providerAttemptCount=0 수용
Workflow 변경 공격 PLAN과 다른 Candidate Workflow 거부
Evidence 검증 nullable 수용, 원문 밖 문자열 거부
OUT_OF_SCOPE 계약 PLAN의 payload-free 종료만 수용
OUT_OF_SCOPE API Runtime 1회, ANALYZE attempt 0개, SUCCEEDED, SSE COMPLETED
DB 저장 nullable Candidate confidence와 OUT_OF_SCOPE outcome 저장
A.X deadline 240초 설정값과 범위 검증

로컬 검증

./gradlew clean test
  • 전체 test cases: 517
  • failures: 0
  • errors: 0
  • 로컬 PostgreSQL 환경이 없어 PostgreSQL 전용 test cases 37 skip
  • 최신 원격 A.X deadline 커밋 위에 rebase한 뒤 전체 테스트 재실행 완료

실제 연동 Smoke Test

지원 업무

  1. 체류연장 준비해줘로 AiRun 생성
  2. PLAN attempt에 detectedIntent=EXPIRY_RENEWAL, workflowId=WF-STY-001 저장 확인
  3. ANALYZE analysis_input_json에 planned Intent/Workflow 보존 확인
  4. AI의 ANALYZE provider attempt가 0인지 확인
  5. Candidate가 있으면 workflowId=WF-STY-001, confidence=null 허용 확인

지원 범위 밖 업무

  1. 오늘 날씨 어때?로 AiRun 생성
  2. 최종 status=SUCCEEDED, analysisOutcome=OUT_OF_SCOPE 확인
  3. ai_attempt가 PLAN 한 건뿐인지 확인
  4. SSE가 COMPLETED로 종료되는지 확인

병합 전 확인

@hywznn hywznn self-assigned this Aug 11, 2026
@hywznn
hywznn requested a review from krestar August 11, 2026 10:18
krestar
krestar previously approved these changes Aug 11, 2026

@krestar krestar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PLAN에서 결정한 Intent/Workflow 보존 및 ANALYZE 재사용 흐름, Candidate Workflow 검증과 nullable confidence 계약까지 확인했습니다.
CI도 정상이며 구현 방향 문제 없어 승인합니다.
실제 Server↔AI PLAN→ANALYZE smoke test만 병합 전 확인 부탁드립니다.

@krestar
krestar self-requested a review August 11, 2026 11:19
krestar
krestar previously approved these changes Aug 11, 2026

@krestar krestar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1.1.0인거랑 OUT_OF_SCOPE 가 AI쪽에서만 준비된거 #138에서도 수정하신거 확인했습니다.

@hywznn

hywznn commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

AI #33 계약 정합성 확인 및 체크리스트 갱신

AI #33 최신 head 35d92fa와 Server #138을 다시 대조했습니다.

확인 완료

  • Analyses contractVersion=1.1.0
  • PLAN의 대표 Intent/Workflow/evidence 반환
  • A.X confidence=null, confidenceSource=UNAVAILABLE
  • bertRoutingScore 별도 반환
  • ANALYZE의 plannedIntent, plannedWorkflowId 재사용
  • ANALYZE Intent 모델 재호출 없음
  • Candidate confidence=null, providerAttemptCount=0
  • PLAN 전용 OUT_OF_SCOPE terminal outcome

Server #138은 최신 head 1347e87에서 CI가 통과했고, AI #33도 APPROVED, MERGEABLE 상태입니다. 이에 따라 “AI 최신 HEAD와 계약 정합성 확인”은 완료로 변경했습니다.

아직 완료하지 않은 항목

코드와 계약 테스트가 일치하는 것과 실제 배포 환경에서 두 서비스가 통신하는 것은 별개의 검증이므로, smoke 항목은 그대로 미완료로 유지했습니다.

AI #33: fowoco/ai#33

@krestar
krestar merged commit c376f46 into main Aug 11, 2026
4 checks passed
@krestar
krestar deleted the feat/137-plan-intent-contract branch August 11, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[AI Contract][P0] PLAN Intent 결정을 ANALYZE에 재사용

2 participants