Conversation
feat/v0.4
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 이 Pull Request는 AI 면접 시스템의 핵심 기능을 대폭 확장하고 안정성을 강화하는 데 중점을 둡니다. 문서 처리 지원 파일 형식을 늘리고, AI 질문 생성 및 답변 평가 로직을 고도화하여 사용자 경험을 개선합니다. 또한, 보안 취약점을 보완하고 내부 지원 시스템을 현대화하여 서비스의 전반적인 품질과 운영 효율성을 향상시킵니다. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d72c08a3b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return buildSessionLocalizedQueueEntries( | ||
| kind = InterviewQuestionKind.TECH, | ||
| entries = localized.entries.associate { (key, value) -> | ||
| key.toLong() to StoredLocalizedTurnContent( |
There was a problem hiding this comment.
Skip non-numeric localized keys before queue mapping
This code assumes every localized entry key is numeric and does key.toLong(), but localizeTurnContents can include arbitrary keys parsed from LLM output in addition to the original IDs. If the model emits an extra key like "item-1", this conversion throws NumberFormatException and the interview start flow fails (500) for English sessions. Use toLongOrNull() and ignore unknown keys when building queue entries.
Useful? React with 👍 / 👎.
| val DOCUMENT_ACTION_SIGNALS_EN = setOf("implemented", "designed", "improved", "introduced", "analyzed", "resolved", "optimized", "refactored", "collaborated", "validated", "built", "led") | ||
| val DOCUMENT_RESULT_SIGNALS_EN = setOf("result", "outcome", "improved", "reduced", "increased", "shortened", "completed", "achieved", "stabilized", "launched") | ||
| val DOCUMENT_REASONING_SIGNALS_EN = setOf("because", "therefore", "so that", "in order to", "reason", "evidence", "validated", "compared", "trade-off") | ||
| val MOTIVATION_SIGNALS = setOf("지원", "동기", "가치", "가치관", "중요", "이유", "관심", "기준", "태도", "관점", "포부") |
There was a problem hiding this comment.
Add English motivation tokens to fallback rubric
MOTIVATION_SIGNALS is Korean-only, but it is used in document heuristic scoring for all languages via hasMotivationSignal. In English interview sessions, fallback evaluation can therefore mark motivation/principle as missing even when the answer clearly states it, lowering motivation-related scores and producing misleading guidance. Add an English motivation signal set (or branch by answerLanguage) like the other EN/KR signal groups.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Code Review
전반적으로 매우 인상적인 대규모 업데이트입니다. 한국어/영어 면접 지원, DOCX/PPTX 문서 업로드, 디스코드 웹훅을 이용한 고객 지원 리포팅 등 중요한 기능들이 추가되었습니다.
특히 원자적인 리프레시 토큰 회전(atomic refresh token rotation)을 구현하여 보안을 크게 강화했고, 면접 답변 일괄 평가 기능으로 성능도 개선했습니다. 복잡한 정책 로직을 DocumentQuestionGenerationPolicy, UserLifecycleEmailService 같은 별도 컴포넌트로 분리하여 코드 구조와 가독성을 높인 점도 훌륭합니다. AI 프롬프트 엔지니어링도 훨씬 정교해져 생성되는 질문과 평가의 품질이 향상될 것으로 기대됩니다.
전반적으로 매우 완성도 높은 기여이며, 일괄 평가 기능의 확장성에 대한 한 가지 제안 사항을 남깁니다.
| fun evaluateTurnsBatch( | ||
| items: List<BatchTurnEvaluationInput>, | ||
| responseLanguage: InterviewLanguage = InterviewLanguage.KO | ||
| ): Map<String, AiTurnEvaluation> { | ||
| if (items.isEmpty()) return emptyMap() | ||
|
|
||
| val prompt = """ | ||
| ${evaluationSystemRole(responseLanguage, "interview evaluator")} | ||
| ${jsonLanguageInstruction(responseLanguage)} | ||
|
|
||
| 아래 각 항목을 서로 독립적으로 평가하고 반드시 JSON만 반환하세요. | ||
|
|
||
| 출력 JSON 스키마: | ||
| { | ||
| "items": [ | ||
| { | ||
| "key": "stable key", | ||
| "score": 0~100 숫자(소수점 2자리까지), | ||
| "feedback": "총평(2~4문장)", | ||
| "bestPractice": "개선 가이드(2~4문장)", | ||
| "rubric": { | ||
| "coverage": 0~100, | ||
| "accuracy": 0~100, | ||
| "communication": 0~100 | ||
| }, | ||
| "evidence": ["평가 근거", "..."] | ||
| } | ||
| ] | ||
| } | ||
|
|
||
| 공통 규칙: | ||
| - 항목별 평가는 서로 섞지 말고 독립적으로 수행 | ||
| - 반드시 모든 입력 key를 유지해서 반환 | ||
| - feedback, bestPractice, evidence는 모두 ${responseLanguage.displayLanguageName()}로 작성 | ||
| - kind=TECH: 질문 의도 적합성, 기술 정확성, 실무 근거를 중심으로 평가 | ||
| - kind=DOCUMENT: 사용자 답변 자체를 중심으로 평가하고 referenceAnswer는 정답 매칭이 아니라 보조 힌트로만 활용 | ||
| - questionType이 INTRODUCE_MOTIVATION, INTRODUCE_VALUE, INTRODUCE_FUTURE_PLAN 인 DOCUMENT 항목은 STAR를 과도하게 강제하지 말고 동기, 판단 기준, 실제 적용 계획, 근거 연결성을 평가 | ||
| - 그 외 DOCUMENT 항목은 질문 의도와 STAR 흐름(Situation, Task, Action, Result)을 함께 평가 | ||
| - kind=INTRO: 자기소개 답변으로서 역할, 강점, 지원 맥락, 전달력을 평가 | ||
| - answerLanguage=EN 이면 communication 점수에 grammar, sentence completeness, clarity, and natural professional English quality를 반영 | ||
|
|
||
| [items] | ||
| ${objectMapper.writeValueAsString(items)} | ||
| """.trimIndent() | ||
|
|
||
| return runCatching { | ||
| val generated = llmProviderRouter.generateJson(prompt) | ||
| parseBatchEvaluationJson(generated.text).mapValues { (_, value) -> | ||
| value.copy(model = generated.model, modelVersion = generated.modelVersion) | ||
| } | ||
| }.onFailure { ex -> | ||
| logger.warn("배치 면접 평가 실패(provider={}, count={}): {}", aiProperties.provider, items.size, ex.message) | ||
| }.getOrElse { ex -> | ||
| if (aiProperties.fallbackToHeuristic) emptyMap() else throw ex | ||
| } | ||
| } |
There was a problem hiding this comment.
evaluateTurnsBatch 메서드는 평가할 모든 인터뷰 턴을 포함하는 단일 프롬프트를 생성합니다. 이는 적은 수의 턴에 대해서는 효율적이지만, 입력 아이템의 총 크기가 LLM의 컨텍스트 창을 초과하는 경우를 처리하는 메커니즘이 없습니다. 만약 인터뷰 세션에 긴 답변을 포함한 많은 턴이 있는 경우, 프롬프트가 너무 커져 API 오류가 발생할 수 있습니다.
향후 확장성을 위해 items 목록에 대한 청킹(chunking) 메커니즘을 구현하는 것을 고려해 보세요. 턴들을 컨텍스트 창에 맞게 더 작은 배치로 나누어 순차적으로 처리하면 배치 평가 기능이 더 안정적이고 확장 가능해질 것입니다.
📢 기능 설명
필요시 실행결과 스크린샷 첨부
연결된 issue
연결된 issue를 자동으로 닫기 위해 아래 {이슈넘버}를 입력해주세요.
close #{이슈넘버}
🩷 Approve 하기 전 확인해주세요!
✅ 체크리스트