Skip to content

[Fix] NLG judge 빈 분석 평가 배열 서버 정규화 - #222

Merged
whc9999 merged 8 commits into
devfrom
fix/missing-keyword-candidate-prompt
Jul 29, 2026
Merged

[Fix] NLG judge 빈 분석 평가 배열 서버 정규화#222
whc9999 merged 8 commits into
devfrom
fix/missing-keyword-candidate-prompt

Conversation

@whc9999

@whc9999 whc9999 commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

✨ 어떤 이유로 PR를 하셨나요?

  • feature 병합
  • 버그 수정(아래에 issue #를 남겨주세요)
  • 코드 개선
  • 코드 수정
  • 배포
  • 기타(아래에 자세한 내용 기입해주세요)

📋 세부 내용 - 왜 해당 PR이 필요한지 작업 내용을 자세하게 설명해주세요

  • questionAnalyses가 빈 입력이면 questionAnalysisEvaluations를 서버에서 빈 배열로 정규화
  • 빈 입력에서 Judge가 생성한 문장 평가를 실패 처리하지 않고 구조적으로 제거
  • noAnalysisAppropriateness, strengths, missingKeywords, overallUsefulness, errorCodes, rationale 보존
  • response null 및 caseId mismatch는 기존 validation failure 유지
  • question_analysis_count_mismatch 재시도 로직과 내부 validation reason 타입 제거
  • 빈 입력 정규화 시 원본/정규화 평가 개수 WARN 로그 추가
  • NLG judge 빈 입력 정규화 및 비대상 실패 회귀 테스트 보강
  • DTO, enum, 프롬프트, CSV 포맷은 변경하지 않음

📸 작업 화면 스크린샷

⚠️ PR하기 전에 확인해주세요

  • 로컬테스트를 진행하셨나요?
  • 머지할 브랜치를 확인하셨나요?
  • 관련 label을 선택하셨나요?

🚨 관련 이슈 번호 [#150 ]

Summary by CodeRabbit

  • 개선 사항

    • 리뷰용 CSV에 질문, 답변, 주요 업무, 자격 요건 정보가 함께 포함됩니다.
    • AI 평가 결과가 입력된 질문 분석과 정확히 대응되도록 검증이 강화되었습니다.
    • 입력 분석이 없을 때 불필요한 문장 평가가 자동으로 정리됩니다.
    • 평가 실패 시 원인과 오류 정보가 더 구체적으로 기록됩니다.
    • 누락 키워드 후보가 실제 채용 요건과 답변에 근거해 더 정확하게 생성됩니다.
  • 테스트

    • CSV 출력, 평가 매칭, 오류 처리 및 누락 키워드 규칙 검증이 보강되었습니다.

whc9999 added 7 commits July 29, 2026 18:43
- review CSV에 question, answer, mainTasks, qualifications 컬럼 추가
- 입력 CSV 값을 변환 없이 검수용 review row에 복사
- 기존 replay 판정 및 summary 생성 로직은 유지
- review CSV 문맥 컬럼 복사 테스트 추가
- 1차 후보 프롬프트에 missingKeywordCandidates 전용 생성 규칙 추가
- 누락 키워드는 mainTasks 또는 qualifications의 명시 항목만 사용하도록 제한
- JD 밖 개념 확장 및 일반화 금지 규칙 추가
- relatedRequirement는 JD 원문 기반으로만 작성하도록 제한
- 답변에 이미 존재하는 역량은 누락 후보로 생성하지 않도록 명시
- precision 우선 및 애매한 경우 빈 배열 반환 규칙 추가
- 상세페이지/브랜드 운영/행정지원 negative few-shot 추가
- 후보 프롬프트 회귀 테스트 보강
- caseId mismatch 발생 시 expected/actual caseId와 response null 여부 로깅
- 빈 questionAnalyses에 대한 judge 평가 개수 불일치 로깅
- NLG judge 평가 예외 발생 시 stacktrace 포함 ERROR 로그 출력
- JsonProcessingException originalMessage 로깅
- IllegalArgumentException validationMessage 로깅
- 기존 judge 결과, 평가 기준, CSV 포맷은 유지
- Judge 응답 null, caseId mismatch, questionAnalysis 개수 불일치 원인 구분 로그 추가
- Judge 호출 및 Structured Output 역직렬화 실패 시 stacktrace 포함 ERROR 로그 출력
- Jackson path/reference chain과 실패 필드명 로깅
- NlgEvaluationErrorCode enum 역직렬화 실패 시 unknownValue와 targetEnum 로깅
- root cause 타입과 메시지 로깅
- 기존 Judge 프롬프트, DTO, enum, validation 기준, CSV failureStage 호환성 유지
- questionAnalysesJson에 명시된 분석 항목만 questionAnalysisEvaluations로 평가하도록 프롬프트 보강
- questionAnalysesJson이 빈 배열이면 questionAnalysisEvaluations도 반드시 빈 배열로 반환하도록 명시
- raw/sanitized/review candidate에서 분석을 추론하거나 복원하지 않도록 금지
- rejected 또는 removed candidate를 questionAnalysisEvaluation으로 변환하지 않도록 명시
- 빈 분석은 validation error가 아니며 noAnalysisAppropriateness로 평가하도록 정리
- 분석 N개 입력 시 입력 분석 N개에만 대응 평가하도록 출력 계약 추가
- NLG judge 프롬프트 회귀 테스트 추가
- DTO, enum, validation, CSV 포맷은 변경하지 않음
- questionAnalyses가 비어 있는데 judge가 questionAnalysisEvaluations를 생성한 경우만 1회 재시도
- 내부 JudgeValidationReason과 JudgeValidationResult로 validation 실패 사유 구분
- response null, caseId mismatch, 역직렬화 오류, judge 호출 실패는 재시도하지 않도록 유지
- 재시도 시작, 성공, 재실패 로그 추가
- 재시도 성공 시 두 번째 응답만 최종 결과로 사용
- 재시도 실패 시 기존 judge_validation_failed 결과 유지
- NLG judge 재시도 조건 및 비대상 실패 유형 테스트 추가
- DTO, enum, 프롬프트, CSV 포맷은 변경하지 않음
- questionAnalyses가 빈 입력이면 questionAnalysisEvaluations를 서버에서 빈 배열로 정규화
- 빈 입력에서 Judge가 생성한 문장 평가를 실패 처리하지 않고 구조적으로 제거
- noAnalysisAppropriateness, strengths, missingKeywords, overallUsefulness, errorCodes, rationale 보존
- response null 및 caseId mismatch는 기존 validation failure 유지
- question_analysis_count_mismatch 재시도 로직과 내부 validation reason 타입 제거
- 빈 입력 정규화 시 원본/정규화 평가 개수 WARN 로그 추가
- NLG judge 빈 입력 정규화 및 비대상 실패 회귀 테스트 보강
- DTO, enum, 프롬프트, CSV 포맷은 변경하지 않음
@whc9999 whc9999 self-assigned this Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@whc9999, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a3761919-9c05-4365-81bf-0b21acaf9ce6

📥 Commits

Reviewing files that changed from the base of the PR and between df589b9 and 408061d.

⛔ Files ignored due to path filters (1)
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix_normalized.csv is excluded by !**/*.csv
📒 Files selected for processing (6)
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayService.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClient.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayServiceTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClientTest.java
📝 Walkthrough

Walkthrough

NLG 평가의 프롬프트 계약, 응답 정규화, 예외 로깅이 강화되었습니다. Missing keyword 후보 생성 규칙이 구체화되었고, 리플레이 리뷰 CSV에 원본 입력 필드가 추가되었습니다. 관련 테스트도 각 변경 사항에 맞게 갱신되었습니다.

Changes

NLG 평가 처리

Layer / File(s) Summary
평가 프롬프트 계약과 테스트
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java, src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClientTest.java
questionAnalysisEvaluations가 입력 분석과 1:1로 대응하고, 입력이 비어 있으면 빈 배열이 되도록 프롬프트와 테스트가 추가되었습니다.
응답 정규화와 실패 행 처리
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java, src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchServiceTest.java
빈 문장 분석의 응답 평가를 빈 배열로 정규화하며, null 응답·caseId 불일치·예외 처리와 평가 호출 횟수 검증이 갱신되었습니다.
LLM 호출과 예외 진단 로깅
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java, src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java
LLM 호출 예외를 재전파하면서 root cause를 기록하고, JSON 경로·실패 필드·열거형 정보를 포함한 구조화 로그를 추가했습니다.

Missing keyword 리뷰 CSV

Layer / File(s) Summary
원본 입력 필드가 포함된 리뷰 행
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayService.java, src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayServiceTest.java
리뷰 CSV에 question, answer, mainTasks, qualifications 컬럼과 원본 값이 추가되었고, 테스트가 각 값을 검증합니다.

Missing keyword 후보 프롬프트

Layer / File(s) Summary
후보 생성 규칙과 프롬프트 검증
src/main/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClient.java, src/test/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClientTest.java
후보 생성 시 정밀도 우선, 명시적 근거 제한, 추론·일반화 금지, 답변에 이미 드러난 역량 제외 규칙과 부정 예시가 추가되었습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NlgEvaluationBatchService
  participant NlgEvaluationAiClient
  participant OpenAI
  NlgEvaluationBatchService->>NlgEvaluationAiClient: evaluate 호출
  NlgEvaluationAiClient->>OpenAI: 평가 프롬프트 전송
  OpenAI-->>NlgEvaluationAiClient: 구조화된 평가 응답 반환
  NlgEvaluationAiClient-->>NlgEvaluationBatchService: 평가 결과 반환
  NlgEvaluationBatchService->>NlgEvaluationBatchService: 빈 questionAnalysisEvaluations 정규화
Loading

Possibly related PRs

Suggested reviewers: shinae1023

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 NLG judge의 빈 분석 평가 배열 서버 정규화라는 핵심 변경을 명확히 담고 있어 적절합니다.
Description check ✅ Passed 필수 섹션과 이슈 번호가 포함되어 있고 작업 내용도 구체적이라 템플릿을 대부분 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/missing-keyword-candidate-prompt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayService.java`:
- Around line 53-59: Update REQUIRED_HEADERS in
MissingKeywordSanitizerReplayService to include "question" so missing question
headers fail fast during input validation. In
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayService.java
lines 53-59, add the required header; in
src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayServiceTest.java
lines 154-163, add a regression test removing the question header and asserting
validation failure.

In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java`:
- Around line 196-202: The duplicated rootCause(Throwable) traversal should be
centralized. In
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java
lines 196-202, remove the private rootCause method and use Spring’s
NestedExceptionUtils.getMostSpecificCause(...) or a shared package utility;
apply the same removal and shared call in
src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java
lines 965-971, and consider moving findCause there into the same utility if it
serves the same purpose.

In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java`:
- Around line 156-184: Update both validation-failure branches in
NlgEvaluationBatchService so each emits only one log.warn call. Add the
responseNull field to the existing reason-specific log messages, using true for
the null-response branch and false for the case-id-mismatch branch, then remove
the duplicate warn calls while preserving the existing failure returns.
- Around line 844-907: Refactor logEvaluationFailure so the shared “NLG Judge
evaluation failed” log is emitted once after determining the exception-specific
values, using one consistent exceptionType format (prefer the simple class
name). Preserve the additional JsonProcessingException detail log with
getOriginalMessage(), and retain the existing fields and root-cause information
for all exception types.

In
`@src/main/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClient.java`:
- Around line 675-678: Example 3의 `JD main_tasks`와 `Answer` 내용을 일치시키도록 수정하세요.
`사업 및 행정지원`을 유지하려면 답변에 사업 지원 수행 경험을 명시하고, 그렇지 않으면 JD를 `행정지원`으로 좁혀 행정 업무와 예산
관리만으로 전체 충족으로 판정되지 않게 하세요.

In
`@src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClientTest.java`:
- Around line 129-156: Extend NlgEvaluationAiClientTest with an evaluate()
regression test that stubs LlmConcurrencyLimiter.execute(any(), any()) to throw
a specific RuntimeException and asserts client.evaluate(...) rethrows the
identical instance without wrapping. Reuse the existing judge-input construction
helpers and mock setup, and cover the original exception propagation contract
rather than only prompt generation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c451b342-90b9-46e2-8fe4-bff02e480ab5

📥 Commits

Reviewing files that changed from the base of the PR and between 1e11672 and df589b9.

⛔ Files ignored due to path filters (8)
  • evaluation/evaluation_missing_keyword_sanitizer_review.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_current.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_current_comparison.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix_comparison.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix_diagnostics.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix_empty_contract.csv is excluded by !**/*.csv
  • evaluation/evaluation_nlg_judge_two_pass_candidate_prompt_fix_retry.csv is excluded by !**/*.csv
📒 Files selected for processing (8)
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayService.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClient.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchService.java
  • src/main/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClient.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/MissingKeywordSanitizerReplayServiceTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationAiClientTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/evaluation/NlgEvaluationBatchServiceTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/analysis/service/ai/AnalysisAiClientTest.java

- missing keyword replay 입력 필수 헤더에 question 추가
- question 헤더 누락 fail-fast 회귀 테스트 추가
- NLG judge root cause 추적을 Spring NestedExceptionUtils로 통일
- NLG judge validation 실패 WARN 중복 제거
- NLG judge 실패 로그를 공통 경로로 정리
- JsonProcessingException 상세 originalMessage 로그 유지
- missing keyword negative example의 JD와 답변 문맥 정합성 수정
- NLG judge evaluate 예외 전파 회귀 테스트 추가
@whc9999
whc9999 merged commit d491bc7 into dev Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant