Skip to content

feat: 세부 역량 태그 추출 v1_baseline 구현 + v2_postscore variant 검증 (#7)#10

Merged
gyesswhat merged 24 commits into
mainfrom
feat/#7-tagging-v1
May 18, 2026
Merged

feat: 세부 역량 태그 추출 v1_baseline 구현 + v2_postscore variant 검증 (#7)#10
gyesswhat merged 24 commits into
mainfrom
feat/#7-tagging-v1

Conversation

@gyesswhat

@gyesswhat gyesswhat commented May 18, 2026

Copy link
Copy Markdown
Contributor

요약

  • 심화 STAR 기록 제출 시점에 호출되는 세부 역량 태그 추출 기능을 v1_baseline 으로 처음 구현하고, 운영 효율을 위한 v2_postscore variant 까지 측정·검증했다. 평균 일치율 53% → 63%, 1건 비용 약 8원 → 3.6원, 재시도 6/10 → 0/10 으로 v2 효과가 일관되게 확인됨.

변경 사항

  • 기능
  • 버그 수정
  • 리팩토링 (가중치 표 LLM 외부 후처리로 분리)
  • 문서 (README §실험결과기록 컨벤션 따른 결과 .md 작성)
  • 테스트
  • 기타 (평가 fixture / eval 스크립트 / 결과 자동 생성 인프라)

세부 작업

1) 도메인·계약

  • JobRole / PrimaryCategory enum + 한글 라벨 매핑 (app/schemas/common.py)
  • TaggingRequest / TaggingResponse (camelCase alias, 300자 가드)
  • 66개 태그 풀 (ALL_TAGS · TAGS_BY_CATEGORY · TAG_TO_CATEGORY)

2) 프롬프트 / 설정

  • app/prompts/tagging/v1_baseline.md — zero-shot 분류기 (66 태그풀 + High/Mid/Low 가중치 표 + JSON 출력 강제)
  • Settings.tagging_variant (env: TAGGING_VARIANT) — 활성 variant 토글, default v1_baseline

3) 서비스 / 라우터

  • app/services/tagging/v1_baseline.pyrun() + corrective 재시도 + 검증 (풀·갯수·중복·JSON)
  • app/services/tagging/__init__.pytagging_variant lazy resolve dispatch
  • POST /v1/tagging — 실제 LLM 호출, X-Internal-Token 보호, LLM/검증 예외 → 502/503/422 매핑
  • POST /api/tagging — Spring 합의 안정 경로, 현재 고정 더미 응답 (TODO: cutover 시 service 호출로 교체)

4) 평가 인프라

  • experiments/tagging/fixtures/eval_set_v1.jsonl.claude/test_case.txt 10케이스 (직군 3종 × 5대 역량)
  • experiments/tagging/eval_v1_baseline.py — 활성 variant 측정 (corrective 포함), raw JSON dump + .md 자동 생성
  • experiments/tagging/_template.md<!-- AUTO:START/END METRICS --> 마커 박힌 템플릿. 재측정 시 메트릭만 갱신, 사람이 적은 "관찰/결정" 보존
  • 첫 v1 결과: experiments/tagging/2026-05-17_v1_baseline.md

5) v2_postscore variant
v1 측정에서 드러난 한계를 종합 해소한 두 번째 variant. 변경 세 가지:

  • ① 백틱 strip 정규식 확장 — back-ref \1 로 1·2·3개 백틱 모두 strip (v1 에서 Haiku 의 single backtick 응답이 재시도 6/10 발동시킨 단일 원인 해결)
  • ② 가중치 표를 LLM 프롬프트에서 제거 — LLM 은 본문 근거 강한 순으로 5~7개 후보만 출력, 코드가 tag_score() 로 직군 가중치 점수 매겨 상위 3개로 자른다 (deterministic 후처리)
  • ③ 프롬프트 본문 정리
  • app/services/tagging/data.pyTagWeight enum + WEIGHTS_BY_TAG (66 entry) + tag_score() 함수 추가
  • v2 결과: experiments/tagging/2026-05-18_v2_postscore.md

v1 vs v2 측정 비교 (10케이스 실측)

항목 v1_baseline v2_postscore 변화
평균 일치율 53.3% (exact 2 · partial 7 · none 1) 63.3% (exact 2 · partial 8 · none 0) +10%p
평균 응답시간 2,035ms 1,713ms -16%
평균 입력 토큰 5,431 2,310 -57%
1건 비용 $0.0057 (≈ 8원) $0.0026 (≈ 3.6원) -55%
월 1,000건 비용 $5.69 (≈ 7,970원) $2.58 (≈ 3,613원) -55%
corrective 발생 6 / 10 0 / 10 완전 회수
LLM 호출 실패 0 0
최종 422 0 0

활성 default 는 아직 v1_baseline

이 PR 에서는 v2 측정 결과만 기록하고 default 전환은 별도 PR (관련 issue 의 결정란 참고).
운영 트래픽 영향 0 — /api/tagging 은 더미 응답 그대로.

테스트

  • 로컬 테스트 완료 (47 testcases green)

LLM 실측 평가 (수동, Anthropic API 키 필요)

# v1 측정
TAGGING_VARIANT=v1_baseline uv run python experiments/tagging/eval_v1_baseline.py

# v2 측정 (.env 에서 TAGGING_VARIANT=v2_postscore 로 바꾼 뒤 같은 스크립트)
uv run python experiments/tagging/eval_v1_baseline.py
  • stdout 에 케이스별 + 합산 메트릭 출력
  • experiments/tagging/results/<UTC_ts>_<variant>.json raw 저장
  • experiments/tagging/<date>_<variant>.md 자동 생성 (메트릭 마커 사이만 채워짐, "요약/관찰/결정" 은 개발자가 작성)
  • 같은 .md 재측정 시 마커 사이만 갱신 → 인사이트 보존

스크린샷/로그

  • v1 측정 분석: experiments/tagging/2026-05-17_v1_baseline.md
  • v2 측정 분석: experiments/tagging/2026-05-18_v2_postscore.md (요약·관찰·결정 채워져 있음)
  • raw 응답 전체: experiments/tagging/results/*.json

롤백/리스크

리스크 포인트

  • /api/tagging현재는 고정 더미 응답 (#문제해결 1개).
  • /v1/tagging 만 실 LLM 호출. 활성 variant 는 TAGGING_VARIANT env 따라감 (default v1_baseline).
  • LLM upstream 5xx/429/auth/badrequest 시 502 또는 503 매핑 → Spring 이 fallback 처리해야 함.

롤백 방법

  • revert

✅ 인수인계 관련 메모!

  • variant 추가 방법: README §"프롬프트 / 실험 버전 관리 컨벤션" 참고. 요약:
    1. app/prompts/tagging/v{N}_{strategy}.md 작성
    2. app/services/tagging/v{N}_{strategy}.py 에 동일 시그니처 run() 작성
    3. app/services/tagging/__init__.py::_resolve 분기 한 줄 추가
  • 활성 variant 토글: .envTAGGING_VARIANT=v{N}_{strategy}. prod 는 SSM /groute/ai/TAGGING_VARIANT.
  • 새 측정 흐름: uv run python experiments/tagging/eval_v1_baseline.py 실행. raw JSON + .md 자동 생성. .md 의 "요약/관찰/결정" 채워서 commit. 같은 날 같은 variant 재실행 = 메트릭만 자동 갱신 (인사이트 보존).
  • 이슈 feat: 세부 역량 태그 추출 (tagging) v1 baseline 구현 #7 결정란 후속 작업 후보 (v2 분석 .md §결정 참고):
    1. 점수 매핑 격차 (H/M/L = 3/2/1 → 5/2/1 등) — 동점 빈도 ↓
    2. LLM 후보 57 → 710 확장 — 정답 누락 회수
    3. 동점 처리에 LLM 응답 순서 결합
      위 1·2·3 묶음을 다음 measurement round 에서 같이 시도 권장. 그 뒤 default 전환 + /api/tagging cutover.

관련 이슈

Closes #7

Summary by CodeRabbit

  • 새로운 기능

    • STAR 회고에서 세부 역량 태그를 추출하는 태깅 엔드포인트 추가(공개 경로 및 v1 경로 제공)
    • 태깅 동작을 전환 가능한 두 가지 알고리즘 변형(v1_baseline, v2_postscore) 지원 및 설정 필드 추가
  • 문서

    • 두 변형용 프롬프트/템플릿과 실험 결과 문서(실측 메트릭 및 관찰) 추가
  • 테스트

    • 인증·유효성·재시도·오류 매핑 등 통합 및 단위 테스트 대거 추가

Review Change Stack

@gyesswhat
gyesswhat requested review from hyhy-j and parkdo0918 May 18, 2026 12:36
@gyesswhat gyesswhat self-assigned this May 18, 2026
@gyesswhat gyesswhat added feat 새로운 기능 추가 또는 기존 기능의 의미 있는 확장 status:review 작업 완료, 리뷰 또는 머지 대기 중 priority:high 즉시 처리 필요, 지연 시 영향 큼 labels May 18, 2026
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@gyesswhat has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 5 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bb493300-8287-4fca-984b-5ffefe7303a3

📥 Commits

Reviewing files that changed from the base of the PR and between 3d4459e and 0284dd5.

⛔ Files ignored due to path filters (1)
  • .env.example is excluded by !.env.example
📒 Files selected for processing (4)
  • app/api/v1/__init__.py
  • app/core/config.py
  • app/main.py
  • app/schemas/common.py
📝 Walkthrough

Walkthrough

STAR 회고(직군·주요역량·S/T/A/R)로부터 도메인 화이트리스트 기반 세부 태그를 추출하는 스키마·프롬프트·정적데이터·서비스(v1/v2)·안정/실험 API·테스트·실험 평가를 통합 추가했습니다. /api/tagging은 더미 안정 경로, /v1/tagging은 LLM 호출 실험 경로입니다.


세부 역량 태그 추출(Tagging) 기능

Layer / File(s) Summary
스키마 및 설정 정의
app/schemas/common.py, app/schemas/tagging.py, app/core/config.py
Spring과 동일한 JobRole/PrimaryCategory enum, 요청·응답 camelCase alias 및 길이 검증(300자), tagging_variant 설정 추가.
정적 데이터 및 도메인 예외
app/services/tagging/data.py, app/services/tagging/exceptions.py
5대 역량별 66개 태그 풀, ALL_TAGS·TAG_TO_CATEGORY, 태그·직군 가중치(TagWeight/WEIGHTS_BY_TAG), tag_score()TaggingValidationError.
프롬프트 템플릿
app/prompts/tagging/v1_baseline.md, app/prompts/tagging/v2_postscore.md
v1: 13개 제약·직군 친화도 표 주입·정확한 한 줄 JSON, v2: 57 후보 생성 후 점수·후처리으로 top3 선택 규칙.
서비스 레이어
app/services/tagging/__init__.py, app/services/tagging/v1_baseline.py, app/services/tagging/v2_postscore.py
variant 디스패처(lazy-load), LLM 호출→코드펜스 strip→JSON 파싱·검증→1회 corrective 재시도→최종 선택(top3) 로직.
API 라우터
app/api/tagging_public.py, app/api/v1/tagging.py, app/api/v1/__init__.py, app/main.py
/api/tagging(안정, 더미 응답), /v1/tagging(실험, LLM 호출), X-Internal-Token 의존성 적용, 예외→HTTP 매핑(422/502/503), STAR 본문 PII 미노출 보장.
테스트
tests/test_tagging.py
안정/실험 경로 인증·스키마·해피패스·corrective 재시도·이중 실패(422)·LLM 예외 매핑·PII 미노출·v2 유틸 유닛 테스트 포함.
실험 평가
experiments/tagging/eval_v1_baseline.py, experiments/tagging/fixtures/eval_set_v1.jsonl, experiments/tagging/_template.md, experiments/tagging/results/*, experiments/tagging/*.md
10케이스 일치율·토큰·지연·비용 수집, raw JSON 저장, 템플릿 기반 마크다운 자동 갱신(AUTO 메트릭 블록).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant PublicRouter as /api/tagging
  participant V1Router as /v1/tagging
  participant Service as tagging.run()
  participant LLM as LLMClient
  Client->>PublicRouter: POST TaggingRequest (validated)
  PublicRouter-->>Client: fixed TaggingResponse (dummy)
  Client->>V1Router: POST TaggingRequest (X-Internal-Token)
  V1Router->>Service: tagging.run(req, llm, model)
  Service->>LLM: 1st LLM call (system+user)
  LLM-->>Service: assistant response (text)
  Service->>Service: strip/parse/validate
  alt validation fail (1st)
    Service->>LLM: corrective 2nd call
    LLM-->>Service: assistant response
    Service->>Service: parse/validate
  end
  Service-->>V1Router: TaggingResponse or raise TaggingValidationError/LLMError
  V1Router-->>Client: HTTP 200 / 422 / 502 / 503
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

"태그 뽑는 AI, 심화 기록 위해" 🚀
직군·역량 근거로 1~3개 픽,
LLM 못하면 재시도,
안정·실험 갈라 cutover 준비,
PII는 절대 들통 안 나게!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(v1_baseline 구현 + v2_postscore 검증)을 명확하게 요약하고 있으며, 이슈 번호도 명시되어 있습니다.
Description check ✅ Passed PR 설명이 템플릿 구조를 대부분 따르고 있으며, 세부 작업·평가 결과·테스트 현황·롤백 방법·관련 이슈를 충분히 기술하고 있습니다.
Linked Issues check ✅ Passed 코드 변경사항이 #7의 모든 필수 요구사항(스키마·프롬프트·서비스·라우터·테스트·평가 인프라)을 완전히 충족하고 있으며, v2_postscore 검증까지 포함하여 범위를 초과 달성했습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #7의 범위(스키마·프롬프트·서비스·라우터·테스트·평가 인프라) 내에 있으며, 제외 대상(실제 LLM 연동·다른 provider·few-shot·캐싱·confidence 필드)은 포함되지 않았습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#7-tagging-v1

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 and usage tips.

@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

🧹 Nitpick comments (3)
tests/test_tagging.py (2)

226-233: ⚡ Quick win

dependency_overrides.clear() 대신 대상 키만 정리해 주세요 🧹

전체 clear는 다른 fixture/테스트가 세팅한 override까지 지워서 순서 의존 flaky를 만들 수 있습니다. 여기서는 get_llm_client만 제거하는 방식이 안전합니다.

🔧 제안 패치
-    finally:
-        app.dependency_overrides.clear()
+    finally:
+        app.dependency_overrides.pop(get_llm_client, None)
🤖 Prompt for 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.

In `@tests/test_tagging.py` around lines 226 - 233, The test currently calls
app.dependency_overrides.clear() which removes all overrides and can break other
tests; instead remove only the get_llm_client override by deleting or popping
that specific key from app.dependency_overrides (referencing get_llm_client and
_RaisingLLM in the test block) so the cleanup is targeted and other fixtures
remain intact.

83-87: ⚡ Quick win

/api/tagging 인증 실패 케이스도 같이 고정해두는 게 좋아요 ✅

안정 경로는 “토큰 보호”가 핵심 계약인데 현재 해피 패스만 검증합니다. 401/403 케이스를 추가해 두면 추후 cutover 때 보안 회귀를 빨리 잡을 수 있습니다.

➕ 테스트 추가 예시
 def test_api_tagging_dummy_returns_fixed_response(client: TestClient, token: str) -> None:
@@
     assert r.json() == {"primaryCategory": "PROBLEM_SOLVING", "detailTags": ["`#문제해결`"]}

+def test_api_tagging_missing_token_returns_401(client: TestClient) -> None:
+    r = client.post("/api/tagging", json=_PAYLOAD)
+    assert r.status_code == 401
+
+def test_api_tagging_wrong_token_returns_403(client: TestClient) -> None:
+    r = client.post("/api/tagging", json=_PAYLOAD, headers={"X-Internal-Token": "wrong"})
+    assert r.status_code == 403

As per coding guidelines tests/**: "해피 패스뿐 아니라 경계값·실패 케이스도 커버하는지 확인".

🤖 Prompt for 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.

In `@tests/test_tagging.py` around lines 83 - 87, Add negative auth tests for the
tagging endpoint: extend the test suite around
test_api_tagging_dummy_returns_fixed_response by adding at least two new tests
that call POST /api/tagging using TestClient and assert proper failure status
codes and responses when the X-Internal-Token header is missing and when an
invalid token is provided; reference the existing test function name
test_api_tagging_dummy_returns_fixed_response and the endpoint "/api/tagging" to
locate where to add tests, and assert expected 401/403 status codes (and any
standard error body your app returns) to ensure authentication failure behavior
is covered.
app/services/tagging/data.py (1)

167-256: ⚡ Quick win

🧪 태그/가중치 정합성 가드를 추가하면 드리프트를 바로 잡을 수 있어요.

현재 누락 매핑은 tag_score()에서 0으로 조용히 처리되어 품질 저하가 숨어버릴 수 있습니다. 모듈 로드 시점에 테이블 정합성을 검증하면 회귀를 빨리 탐지할 수 있습니다.

제안 수정안
 WEIGHTS_BY_TAG: dict[str, dict[JobRole, TagWeight]] = {
@@
 }
 """태그 × 직군 → 가중치 (tags.txt 26.05.01 표 그대로). 총 66 entry."""  # noqa: RUF001

+_missing = ALL_TAGS - WEIGHTS_BY_TAG.keys()
+_extra = WEIGHTS_BY_TAG.keys() - ALL_TAGS
+if _missing or _extra:
+    raise ValueError(
+        f"WEIGHTS_BY_TAG mismatch: missing={sorted(_missing)}, extra={sorted(_extra)}"
+    )
+
+for _tag, _role_weights in WEIGHTS_BY_TAG.items():
+    if set(_role_weights.keys()) != set(JobRole):
+        raise ValueError(f"Role weights incomplete for tag {_tag}: {_role_weights.keys()}")
+
 
 def tag_score(tag: str, role: JobRole) -> int:
🤖 Prompt for 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.

In `@app/services/tagging/data.py` around lines 167 - 256, Add a module-load
validation that checks WEIGHTS_BY_TAG covers all expected JobRole keys and that
each mapped TagWeight exists in _WEIGHT_SCORE; if any tag is missing a role
mapping or uses an invalid weight, raise an explicit exception (or log and
raise) so the mistake is caught at import time rather than silently returning 0
in tag_score. Implement this check in the same module (run once at import),
iterating over WEIGHTS_BY_TAG items, verifying for each tag that all JobRole
enum members are present and that weights are keys in _WEIGHT_SCORE, and surface
a clear error referencing the failing tag and role so regressions are detected
early.
🤖 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 `@app/api/v1/tagging.py`:
- Around line 47-49: Replace the assert-based dependency check for
request.state.llm_client with an explicit runtime exception: verify that client
= request.state.llm_client is an instance of LLMClient and if not raise a clear
exception (e.g., RuntimeError or TypeError) with the existing message so the
check works in optimized Python and yields a useful stack trace; update the code
around the client retrieval (the client variable, the isinstance(...) check and
the return) to use this explicit raise.

In `@app/core/config.py`:
- Around line 69-76: The tagging_variant Field currently accepts any string and
only raises RuntimeError later; add a startup fail-fast validation in the
settings class that owns tagging_variant (the Pydantic SettingsModel containing
the tagging_variant attribute) to verify the corresponding prompt and service
files exist (app/prompts/tagging/{tagging_variant}.md and
app/services/tagging/{tagging_variant}.py) and raise a clear ValidationError on
import if missing; implement this via a Pydantic validator/root_validator or
post_init hook for the settings class so invalid TAGGING_VARIANT values fail
fast during app boot rather than at request time.

In `@app/services/tagging/v1_baseline.py`:
- Around line 114-117: The current validation only checks against ALL_TAGS
(variable ALL_TAGS and list comprehension producing out_of_pool) so tags from a
different primaryCategory can slip through; update validate logic where
out_of_pool is computed to also check that each tag belongs to the allowed set
for the provided primaryCategory (use the primaryCategory input and the
category-to-tag mapping you have—e.g., a dict like CATEGORY_TAGS or method
get_allowed_tags_for_category) and raise TaggingValidationError listing tags
that are outside the selected primaryCategory as well as those not in ALL_TAGS
so the error message and thrown condition reflect both global and
category-specific violations.
- Around line 49-60: _render_prompt currently does chained .replace() calls that
let user text containing tokens like "{result}" or braces corrupt subsequent
replacements and enables prompt-injection; change to a single-pass, safe
substitution: introduce a sanitizer (e.g., sanitize_user_input) that escapes
braces/placeholder-like substrings in req.situation_task, req.action,
req.result, then build a single mapping dict of placeholders to sanitized values
and render _PROMPT_TEMPLATE in one pass (use string.Template or a single regex
replace over placeholders) instead of repeated .replace(); ensure
JOB_ROLE_LABELS_KO and PRIMARY_CATEGORY_LABELS_KO are used via the same mapping
and that placeholder names in _PROMPT_TEMPLATE are unique/unambiguous to avoid
collisions.

In `@app/services/tagging/v2_postscore.py`:
- Around line 64-71: _render_prompt currently inserts user fields directly into
_PROMPT_TEMPLATE using chained .replace calls which allows prompt-injection or
accidental re-replacement when user text contains placeholders; change it to
perform a single-pass templating (e.g., use Python str.format / Template with
named placeholders on _PROMPT_TEMPLATE) and ensure user-provided values from
TaggingRequest (situation_task, action, result) are boundary-escaped or
sanitized (e.g., wrap/quote values or escape placeholder tokens) before
formatting; keep lookup of JOB_ROLE_LABELS_KO[req.job_role] and
PRIMARY_CATEGORY_LABELS_KO[req.selected_competency] but do not allow user text
to contain template markers that could be re-interpreted by the templating step.

---

Nitpick comments:
In `@app/services/tagging/data.py`:
- Around line 167-256: Add a module-load validation that checks WEIGHTS_BY_TAG
covers all expected JobRole keys and that each mapped TagWeight exists in
_WEIGHT_SCORE; if any tag is missing a role mapping or uses an invalid weight,
raise an explicit exception (or log and raise) so the mistake is caught at
import time rather than silently returning 0 in tag_score. Implement this check
in the same module (run once at import), iterating over WEIGHTS_BY_TAG items,
verifying for each tag that all JobRole enum members are present and that
weights are keys in _WEIGHT_SCORE, and surface a clear error referencing the
failing tag and role so regressions are detected early.

In `@tests/test_tagging.py`:
- Around line 226-233: The test currently calls app.dependency_overrides.clear()
which removes all overrides and can break other tests; instead remove only the
get_llm_client override by deleting or popping that specific key from
app.dependency_overrides (referencing get_llm_client and _RaisingLLM in the test
block) so the cleanup is targeted and other fixtures remain intact.
- Around line 83-87: Add negative auth tests for the tagging endpoint: extend
the test suite around test_api_tagging_dummy_returns_fixed_response by adding at
least two new tests that call POST /api/tagging using TestClient and assert
proper failure status codes and responses when the X-Internal-Token header is
missing and when an invalid token is provided; reference the existing test
function name test_api_tagging_dummy_returns_fixed_response and the endpoint
"/api/tagging" to locate where to add tests, and assert expected 401/403 status
codes (and any standard error body your app returns) to ensure authentication
failure behavior is covered.
🪄 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: CHILL

Plan: Pro Plus

Run ID: b4f97a40-e10c-4409-afc9-b7c988081f4c

📥 Commits

Reviewing files that changed from the base of the PR and between eddd5e8 and df8bb60.

⛔ Files ignored due to path filters (2)
  • .env.example is excluded by !.env.example
  • .gitignore is excluded by !.gitignore
📒 Files selected for processing (23)
  • app/api/tagging_public.py
  • app/api/v1/__init__.py
  • app/api/v1/tagging.py
  • app/core/config.py
  • app/main.py
  • app/prompts/tagging/v1_baseline.md
  • app/prompts/tagging/v2_postscore.md
  • app/schemas/common.py
  • app/schemas/tagging.py
  • app/services/tagging/__init__.py
  • app/services/tagging/data.py
  • app/services/tagging/exceptions.py
  • app/services/tagging/v1_baseline.py
  • app/services/tagging/v2_postscore.py
  • experiments/tagging/2026-05-17_v1_baseline.md
  • experiments/tagging/2026-05-18_v2_postscore.md
  • experiments/tagging/_template.md
  • experiments/tagging/eval_v1_baseline.py
  • experiments/tagging/fixtures/eval_set_v1.jsonl
  • experiments/tagging/results/.gitkeep
  • experiments/tagging/results/2026-05-17T160028Z_v1_baseline.json
  • experiments/tagging/results/2026-05-18T121137Z_v2_postscore.json
  • tests/test_tagging.py

Comment thread app/api/v1/tagging.py Outdated
Comment thread app/core/config.py Outdated
Comment thread app/services/tagging/v1_baseline.py Outdated
Comment thread app/services/tagging/v1_baseline.py Outdated
Comment thread app/services/tagging/v2_postscore.py Outdated
Comment thread app/services/tagging/v2_postscore.py Outdated

@hyhy-j hyhy-j 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.

오오 일단 더 수정할 건 없는 것 같습니다!
인수인계 정리 감사합니당 👍
저희가 동시에 작업하느라 공동 파일에 충돌이 나서! 그것만 해결하고 머지하면 될 것 같습니다!

@gyesswhat
gyesswhat force-pushed the feat/#7-tagging-v1 branch from 22a813d to 3d4459e Compare May 18, 2026 16:25
@gyesswhat
gyesswhat merged commit cd64eb2 into main May 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 새로운 기능 추가 또는 기존 기능의 의미 있는 확장 priority:high 즉시 처리 필요, 지연 시 영향 큼 status:review 작업 완료, 리뷰 또는 머지 대기 중

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 세부 역량 태그 추출 (tagging) v1 baseline 구현

2 participants