Repository navigation
fix(ai): 비개발 직군 면접이 IT 면접관 페르소나로 진행되던 문제 - #276
Merged
Merged
Conversation
plainto_tsquery 는 토큰을 전부 AND 로 묶는다. 그런데 이 검색의 질의는 꼬리질문이면 "직전질문 + 답변", 질문 풀이면 "모드 + 직군 + 자기소개 600자"라 토큰이 10~90개다. 그 전부를 담은 청크는 존재하지 않으므로 full-text 브랜치가 항상 0건이었고, RRF 가 조용히 벡터 단독 검색으로 퇴화했다. 운영 실측: 꼬리질문 질의 47/47, 질문 풀 질의 30/30 이 0건. 구현돼 있고 테스트도 통과하지만 실제 질의 형태에서는 무효인 상태였다. tsquery 를 OR 로 결합한다. 운영과 같은 헤딩 청킹 인덱스에서 질의 47개, top_k=5 기준: MRR 0.791 → 0.885 (paired bootstrap 95% CI +0.029~+0.162, 12승/3패) Top-1 0.681 → 0.830 (CI +0.043~+0.277, 8승/1패) Recall 0.936 → 0.979 후보 풀 :cand 은 손대지 않았다 — 측정한 구성이 cand = top_k 였고, 바꾸면 측정하지 않은 것을 배포하는 셈이 된다. 회귀 테스트는 벡터만으로는 top_k 밖인 청크를 키워드로만 끌어올리게 만들어 두 절반을 구분한다. 미끼를 top_k 만큼 채우지 않으면 벡터가 어차피 전부 반환해 AND 에서도 통과한다(처음에 그렇게 써서 변별력이 없었다). 기존 헬퍼 vector(head) 는 0번 차원의 크기만 바꿔 모든 벡터가 평행이라 코사인 거리가 언제나 0이었다 — 직교 단위벡터 헬퍼 axis(dim) 를 추가했다. AND 로 되돌리면 이 테스트가 실패하는 것을 확인했다.
서비스 대상을 취준생 전반(개발 8 + 비개발 12 직군)으로 넓히면서 평가
패널은 직군별로 확장했는데, 질문 생성·꼬리질문·첫인상·문서분석 프롬프트는
"IT 직군" 페르소나로 고정돼 있었다.
그 상태의 영업·인사 지원자 면접은 이렇게 흐른다: IT 렌즈로 이력서가
요약되고 → IT 채용 담당자 페르소나가 → 'CS 기초'·'기술 선택' 카테고리로
질문을 만들고 → IT 면접관이 꼬리질문을 단다. 직군에 맞는 것은 평가뿐이다.
카테고리 자체가 개발 전용인 것이 핵심이다. 문구만 중립화하면 LLM 은 여전히
CS_FUNDAMENTAL 을 고른다. DOMAIN_KNOWLEDGE(직무 지식·업무 도구·업계 이해)를
추가하고, 비개발이면 CS_FUNDAMENTAL·TECH_CHOICE 를 쓰지 말라고 명시한다.
Core 는 category 를 문자열로만 저장하므로(V9, CHECK 없음) 마이그레이션이
필요 없고 프론트는 라벨만 더한다.
- job_category.py 에 ENGINEERING_CATEGORIES + is_engineering 을 직군 목록과
같은 파일에 둔다. 목록만 늘리고 집합을 빠뜨리면 그 직군이 조용히 반대
취급을 받는다 — 검증에서 튕기지 않아 아무도 모른다.
- _format_job_guide 가 개발/비개발/혼합 3분기 지침을 {job_guide} 로 주입한다.
패널의 _DOMAIN_TECH_GUIDE 와 같은 이유로 라벨이 아니라 무엇을 묻고 무엇을
묻지 말지를 문장으로 준다. 직군이 비면 개발을 가정하지 않는다 — 틀렸을 때
비개발 지원자에게 기술 질문이 나가는 쪽이 반대보다 나쁘다.
- followup·self_intro 프롬프트는 예전부터 {job_category} 를 받고 있었는데
쓰지 않았다. 받은 값을 페르소나에 넣었다.
- document_analysis 는 업로드 시점이라 직군을 모른다. 페르소나를 중립화하고
tech_stack 의 의미를 "개발이면 기술 스택, 아니면 그 직무의 실무 역량·도구·
자격"으로 넓혔다. 이게 가장 상류다 — 분석 마크다운이 RAG·질문·피드백
전부의 근거다.
운영 사용 현황은 BACKEND 64 / FRONTEND 39 로 비개발 세션이 0건이다.
라이브 회귀를 고친 것이 아니라 미검증 경로를 연 것이다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
문제
면접 직군을 비개발 12종까지 넓혔는데(PR #266/#267), 확장된 건 평가 패널뿐이었습니다. 질문 생성·꼬리질문·첫인상·문서분석 프롬프트는 여전히 IT 고정입니다.
그래서 영업·인사 지원자의 면접은 이렇게 흐릅니다:
카테고리 자체가 개발 전용인 것이 핵심입니다. 선택지가
CS_FUNDAMENTAL / PROJECT_DEEP_DIVE / TECH_CHOICE / BEHAVIORAL네 개라, 문구만 중립화하면 LLM 은 여전히CS_FUNDAMENTAL을 고릅니다.그리고
followup·self_intro프롬프트는 예전부터{job_category}를 받고 있었습니다 — 받아 놓고 안 썼고, 페르소나만 IT 로 박혀 있어 서로 모순이었습니다.수정
DOMAIN_KNOWLEDGE카테고리 추가 (직무 지식·업무 도구·업계 이해). Core 는 category 를 문자열로만 저장하므로(V9, CHECK 없음) 마이그레이션이 없고, 프론트는categoryLabel에 라벨만 더합니다._format_job_guide가 직군 지침을 주입 — 개발/비개발/혼합 3분기. 패널의_DOMAIN_TECH_GUIDE와 같은 이유로 라벨이 아니라 무엇을 묻고 무엇을 묻지 말지를 문장으로 줍니다.CS_FUNDAMENTAL·TECH_CHOICE적극,DOMAIN_KNOWLEDGE미사용)CS_FUNDAMENTAL·TECH_CHOICE금지, 실무 역량·도구를 직군별로 예시(마케팅 GA4·재무 결산·생산 불량률·법무 계약검토…), 성과는 숫자로, "GitHub 레포가 없는 것이 정상"직군이 비면 개발을 가정하지 않습니다 — 가정이 틀렸을 때 비개발 지원자에게 기술 질문이 나가는 쪽이 반대보다 나쁩니다.
ENGINEERING_CATEGORIES(8개)를 직군 목록과 같은 파일에 뒀습니다. 그 파일의 존재 이유와 같습니다 — 목록만 늘리고 집합을 빠뜨리면 그 직군이 조용히 반대 취급을 받고, 검증에서 튕기지 않아 아무도 모릅니다.document_analysis는 업로드 시점이라 직군을 모릅니다. 페르소나를 중립화하고tech_stack의 의미를 "개발이면 기술 스택, 아니면 그 직무의 실무 역량·도구·자격"으로 넓혔습니다(필드명 때문에 없는 기술을 지어내지 말라고 명시). 이게 가장 상류입니다 — 분석 마크다운이 RAG·질문·피드백 전부의 근거입니다.영향 범위
운영 사용 현황은
BACKEND64 /FRONTEND39 로 비개발 세션이 0건입니다. 라이브 회귀를 고친 게 아니라 미검증 경로를 연 것입니다. 개발 직군 동작은 지침이 현행과 같아 변하지 않습니다(테스트로 고정).테스트
tests/test_non_engineering_interview.py16건:CS_FUNDAMENTAL금지·DOMAIN_KNOWLEDGE사용·"레포 없음이 정상"을 포함DOMAIN_KNOWLEDGE가QuestionCategoryLiteral 에 있음 — 없으면 LLM 이 지침대로 골라도 검증에서 튕겨 생성이 통째로 실패합니다"IT 직군"문자열이 없음프롬프트가 새 변수로 실제 조립되는지도 확인했습니다(
format_messages로 전 변수 주입).uv run pytest479건 ·flake8·black --check· 프론트type-check/lint/테스트 통과.🤖 Generated with Claude Code