visualize_eval.py 는 visualize_eval_v2.py 가 상위호환(OpenAI 메타 임베딩
baseline 포함)이고 문서·코드 참조가 없어 삭제한다. rouge_certificate_fn.py
(미추적) 도 app/engine/rouge.py 와 같은 수식을 재구현해 함께 정리했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
요약 항목도 같은 서식으로 준비한다. 정답셋이 없어 수치는 채울 수 없으므로
서식과 시현 절차만 확정하고, 결과 자리는 자리표시자로 둔다.
eval_rouge.py: 성적서 '4. 결과' 형식 JSON 출력(--out 으로 저장). 보고 대상이
ROUGE-1 recall 임을 reported_metric 으로 명시한다. 계획서 수식 분모가 참조
n-gram 수인데 전 차수 코드는 f1 을 반환해 정의가 어긋나 있었다.
show_summary_samples.py: 전 차수 '1. 데이터 준비' 의 {index, original} 형식
출력. 정답셋이 없으면 그 사실과 참조 문서를 알리고 종료한다.
시험방법 수정 두 곳 — 1,000건에서 300건으로(사람 작성 정답이 필요해 1,000건은
구축 비용 과다), 지표를 ROUGE-1 recall 로 명시.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성적서 '1. 데이터 준비' 는 비표절/표절 데이터를 각각 첫 건과 마지막 건만
{line_number, original_text} 형태로 싣고 중간을 ... 로 생략한 뒤 총 건수를
적는다. 그 형식으로 출력한다.
pairs.jsonl 의 실제 레코드를 읽으며 데이터를 새로 만들지 않는다. 표절 쪽
original_text 는 변형이 적용된 derived_text 다. 판정 대상이 그 글이기 때문이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성적서 '4. 모델 결과' 는 plagiarism_detection_performance 아래에
test_dataset / confusion_matrix / performance_metrics / threshold /
interpretation 을 담은 JSON 을 캡처해 싣는다. 그 형식으로 출력한다.
threshold 는 전 차수처럼 단일 수치가 아니라 세 조건(결합유사도 0.65 /
연속일치 35자 / 커버리지 0.30)의 조합이므로 객체로 둔다. 유사도만으로
판정하지 않는다는 점이 판정 기준의 핵심이라 수치 하나로 줄이면 오해를 준다.
interpretation 문구는 실제 confusion matrix 에서 계산한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성적서 '3. 테스트 데이터 예시' 는 평가 데이터 id 를 학습 데이터 뒤에 이어서
매기고(11480~), 바로 아래 '예측 결과 예시' 에 마지막 예시 문장의 태그 배열을
전체로 싣는다. 두 가지를 스크립트에서 바로 낼 수 있게 한다.
--id-offset : id 시작값. 미지정 시 validation 은 학습셋 크기만큼 이어서 매김
--predict : 마지막 예시 문장의 original_tags / predicted_tags 를 전체 배열로 출력
공백 토큰은 서브워드가 없어 word_ids 에서 빠지므로, 음절 수만큼 자리를 잡아
두고 word_id 위치에만 예측을 채워 정답과 길이를 맞춘다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
KLUE NER 의 라벨 id 순서는 B-DT(0) … I-TI(11), O(12) 로 'O' 가 맨 뒤다.
스크립트는 ["O"] + [B-/I- ...] 로 재구성해 써서 전체가 한 칸씩 밀렸다.
tokenize_and_align 은 데이터셋 id 를 그대로 넘기는데 build_metrics 가
어긋난 순서로 해석하면서, 실제 O 구간이 I-TI 엔티티로 집계됐다.
영향 — micro support 14,257(실제 엔티티 수) → 67,056 으로 부풀고
F1 도 함께 올랐다. 학습된 klue_ner_large 를 올바른 매핑으로 재평가하면
0.8123 이며 보고돼 온 0.8750 이 아니다. 전 차수 성적서의 support 62,760
(max_length 절단분 차이) 도 같은 상태였다.
모델 자체는 데이터셋 id 공간에서 일관되게 학습돼 재학습이 필요없다.
잘못된 것은 지표 해석뿐이다.
라벨 목록을 데이터셋에서 직접 가져와 유일한 출처로 삼는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성적서 "1. 데이터 준비" 는 KLUE NER 을 원본 배포 형식인 인라인 태그
(`<영동고속도로:LC>`) 로 싣는데, HuggingFace datasets 판은 tokens/ner_tags
배열이라 모양이 다르다. BIO 를 엔티티 단위로 묶어 원본 형식으로 되돌린다.
전 차수 성적서 8p 첫 예시와 문자 단위로 일치함을 확인했다.
열람 전용이며 학습 경로에는 관여하지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성능평가확인서 "4. 결과 측정" 은 최상위 precision/recall/f1_score 와
detailed_report 로 구성된 JSON 을 캡처해 싣는다. 기존 출력은
{model, f1, report} 라 그대로 붙일 수 없었다.
build_scorecard() 로 seqeval 리포트를 성적서 키 구성으로 재배열하고,
indent=4 JSON 을 터미널에도 출력해 캡처 한 장으로 끝나게 한다.
seqeval 의 dict 순서는 엔티티 등장 순서라 실행마다 달라지므로
태그 순서를 DT→LC→OG→PS→QT→TI 로 고정했다.
result.json 은 성적서 형식만 담고, 모델명·하이퍼파라미터는
run_meta.json 으로 분리한다.
전 차수 성적서(GERIR.CE.2511-02.009) 9p 실측값으로 형식 일치를 확인했다.
docs/PERF_EVIDENCE_CAPTURE_2026.md: 3.2.1/3.2.2 항목별 캡처 대상과
소스코드 위치를 HWP 슬롯 순서대로 정리.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성능지표 #3(메타 데이터 추출 F1) 을 측정할 수 있게 만든다. 전 차수 시험은
저장소의 요소 추출기가 아니라 KLUE NER 토큰 분류 과제였다. 성적서 7~8p 의
모델 구조(BertForTokenClassification, klue/bert-base, 13 labels)와 태그 6종
(DT/LC/OG/PS/QT/TI), 리포트 형식을 그대로 따른다.
재현 결과 support=62760 이 전 차수 성적서와 일치해 같은 과제·같은 측정임을
확인했다. 학습셋을 전체(21,008건) 로 쓰면 0.8113 -> 0.8324 로 오른다.
다만 0.8324 는 목표 0.83 과 0.24%p 차이라 재학습 시 미달 위험이 있어
klue/roberta-large 로 올린다. 0.8750 으로 여유가 생기고, 전 차수에 약했던
LC(0.7563->0.8209) 와 TI(0.7674->0.8308) 가 특히 개선된다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
성능지표 #4(표절 판별 정밀도) 를 공인시험에서 재현할 수 있게 시험셋 생성기,
평가 실행기, python 3.9 평가 컨테이너, 시험절차서를 둔다.
시험셋은 작성자 단위로 코퍼스를 나눠 만든다. 비표절 시료를 참조 코퍼스에서
뽑으면 인덱스가 자기 자신을 찾아 전부 오탐이 되므로, 인덱스에 없는 작성자의
글만 쓴다. 무관한 글만 넣으면 정밀도가 부풀려져 주제 근접 시료 150건을 따로
섞는다. 실제 오탐이 나는 유형이 그것이다.
대필(인칭 전환)은 제외한다. 원문이 그대로 남지만 표절 여부가 계약·동의로
갈려 텍스트만으로 판정할 수 없다.
자체 측정 결과 정밀도 0.9840 (TP=493 FP=8 TN=492 FN=7). 목표 0.97 을 넘고,
오탐 8건 중 7건이 주제 근접 시료에서 나와 난이도가 운영 조건을 반영한다.
시험셋에는 자서전 원문이 들어가므로 저장소에 두지 않는다. 시드가 manifest 에
고정돼 있어 생성기로 동일하게 재생성된다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
생활수기는 문서 단위로만 검사되고 있었다. 코퍼스에는 1694개 세그먼트가
적재돼 있는데 질의는 12개 문서를 통째로 던지는 방식이어서, 한 대목이
겹쳐도 글 전체 길이에 희석돼 유사도가 0.28~0.33 에 머물렀다. 그 상태의
미탐지 0건은 근거가 되지 못한다.
--life-writing-segments 를 주면 자서전과 같은 세그먼트 단위로 펼친다.
검사 대상 7786건(자서전 6092 + 생활수기 1694) 으로 재실행한 결과 생활수기
침해의심은 0건이다. 다만 이번 0건은 근거가 있다. 결합유사도 최대 0.5745,
평균 0.3677 로 임계값 0.65 에 못 미치고 0.6 이상도 없다. 연속일치·커버리지
조건을 충족한 건도 없다.
자서전 결과는 106건으로 변화 없다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
중복 제거를 텍스트만 보고 하던 것을 작성자까지 보게 고친다. 저자가 같으면
같은 사람 글이 두 번 적재된 것이라 침해가 아니지만, 저자가 다르면 그 중복
자체가 침해 후보다. 앞서는 이를 구분하지 않아 256건을 모두 뺐고, 그중
17건이 서로 다른 작성자의 글이었다.
같은 작성자 그룹만 제외하도록 목록을 다시 만들어(239건) 재실행하니 검사
대상 6104건, 침해의심 106건이다. 80 -> 106 의 증가분은 되살린 17건 전부와,
그 17건이 색인에 돌아오며 새로 매칭된 9건이다. 빠진 건은 없다.
106건 전수 확인 결과 매칭 상대의 작성자는 모두 다르다.
판정 사유 표기도 바로잡는다. 행 단위 대표값으로 재현하면 서로 다른 후보가
각기 다른 조건을 충족한 3건이 '사유 미상' 으로 빠졌다. 후보 판정재료를
쓰도록 고쳤다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기준을 9어절(35자)로 확정하고 문서를 그 기준으로 다시 만든다.
중복 제거 + 9어절 재실행 결과는 검사 대상 6087건, 침해의심 80건이다.
9어절 근거는 문서쌍 전수 대조다. 545문서 148,240쌍을 모두 대조하니
100어절(390자)까지 올려도 18쌍이 계속 겹친다. 겹침이 0이 되는 어절 수는
없다. 10~15어절에서 27쌍으로 고정되어 더 줄지 않는데, 오탐이라면 기준을
올릴수록 계속 줄어야 한다. 즉 그 지점부터 남는 것은 실제 유사 원고다.
상투어 노이즈는 4->5어절에서 대부분 걷히므로 9어절이 실질적 하한이다.
배포 파일을 하나로 합친다. 원문 대조 시트를 결과보고에 넣어 의심 80건의
원문을 같은 파일에서 볼 수 있게 하고, 숫자가 맞지 않는 중복 제거 전
파일 두 개는 배포 위치에서 내린다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
상무님 요청대로 어절 기준을 3~9로 바꿔가며 재판정한다. 기준값은 검색
후보를 바꾸지 않고 채택 여부만 정하므로, 후보 판정재료를 한 번 남겨두면
7회 실행 없이 오프라인에서 전부 계산할 수 있다. 27자로 재계산한 값이
실제 실행 결과 85건과 일치해 방식을 검증했다.
배치 스크립트에 하드코딩돼 있던 80 을 걷어낸다. --min-exact-span 을 줘도
이 줄이 설정을 읽지 않아 값이 적용되지 않았다.
겹침률 측정도 바로잡는다. 앞서 7어절 0% 로 봤던 것은 4만 쌍에서 히트가
0~1건이라 해상도가 없었고, 그 1건조차 같은 문서 내부의 반복이었다.
15만 쌍으로 늘리고 엔진과 같이 자기 문서 쌍을 빼면 9어절에서도 4.0% 다.
겹침이 사라지는 지점은 없으므로 '오탐 0 인 최저점' 논리는 성립하지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
별도 파일을 늘리지 않고 기존 결과보고 워크북에 '중복 원고' 시트로 넣는다.
중복 제거 후 재실행하면 28건이 결과에서 사라지므로, 사라지기 전에 어떤
문서 사이의 중복이었는지 원문째로 남겨야 나중에 같은 제출자의 재제출인지
다른 제출자의 표절인지 확인할 수 있다.
--no-excerpt-sheet 로 원문 대조 시트 없이 중복 시트만 붙일 수 있게 했다.
결과보고는 원문 없는 배포판이라 이 경로를 쓴다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
상무님 지적 두 가지를 검증 가능한 형태로 만든다.
1) 중복 원고: 코퍼스 6343건 중 247그룹 503건이 중복이고, 침해의심 103건
중 28건이 여기서 비롯됐다. 다만 247그룹 중 234그룹이 서로 다른 문서
사이의 중복이라 같은 제출자의 재제출인지 다른 제출자의 표절인지 아직
모른다. 지우기 전에 원문째로 남기도록 build_duplicate_report.py 를 둔다.
2) 연속 일치 기준 80자: 근거 없이 잡힌 초기값이다. 무관한 원고 4만 쌍을
대조해 재보니 3어절 100%, 4어절 99.8%, 5어절 47%, 7어절 0% 오탐이다
(한 건을 6343건과 대조하는 효과 반영). 관행인 3~5어절은 쓸 수 없고
7어절 = 공백 포함 27자가 오탐 0% 를 유지하는 최저점이다.
배치에 --exclude-segments 와 --min-exact-span 을 추가한다. 중복은 질의와
색인 양쪽에서 함께 빼야 한다. 한쪽만 빼면 지운 원고가 여전히 상대로 잡힌다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
검토자가 침해 여부를 눈으로 판별하려면 원문이 있어야 하고, 어떤 조건으로
걸렸는지 알아야 한다. 두 가지를 워크북에 싣는다.
- extract_suspected_excerpts.py: 코퍼스 DB(읽기 전용)에서 질의·상대 원문과
일치 구간을 뽑는다. 킹서버 기본 python 이 3.6 이라 이 파일만 구문을 맞췄다.
- '판정 기준' 시트: 3개 OR 조건과 결합유사도 가중치, 조건별 충족 현황
- '원문 대조' 시트: 판정 사유 컬럼으로 각 건이 걸린 조건을 표시
판례 표기도 바로잡는다. USE_LLM_LEGAL_JUDGE=false 는 LLM 법적 판단만
끈 것이고 판례 검색은 규칙 기반으로 늘 동작한다. legal_risk.assess() 가
점수 하한 없이 상위 5건을 붙이므로 매칭 미탐지 건에도 판례가 채워진다.
한 줄에 뭉쳐 두면 모순으로 읽혀 판례 검색과 법적 판단을 분리해 적었다.
원문이 담긴 산출물은 gitignore 로 제외한다. 필요하면 위 스크립트로
코퍼스에서 다시 뽑을 수 있어 저장소에 영구 보존할 이유가 없다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
배치 산출 JSONL은 엔진 내부 값(retrieval_backend, legal_judgment_method,
case_id 등 전 건 단일값 컬럼 포함)까지 22컬럼을 담고 있어 그대로 공유하면
오독을 부른다. 원본 JSONL을 건드리지 않고 보고에 필요한 컬럼만 추려
재생성하는 별도 스크립트를 추가한다.
- 침해 판별 결과: 전수 8컬럼, 의심 건 우선 정렬
- 의심 건 상세: 침해유형 한글화 + 관련 판례 연결
- 요약 통계: 근거 스팬 보유 건수와 해석 유의사항
- 1차_vs_2차 비교: 근거 스팬/커버리지 병기, 상위 N 절단 제거
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
문제: 리스트업이 선별 57건만 다뤄서, "표절 탐지에 실제로 쓰이는 판례가 무엇인가"에
답할 수 없었다. 엔진이 로드하는 것은 57건이 아니라 적재본 545건 전부이고
(PRECEDENTS_PATH), 판정 1건마다 유형·태그가 맞는 상위 5건을 인용한다.
또 컴북스 제공분이 얼마나 반영됐는지가 어디에도 기재돼 있지 않았다. 데이터에는
레코드의 excel_duplicate 필드로 남아 있는데 문서에 나오지 않아, 회의에서
"우리가 준 판례는 어떻게 됐나"라는 질문에 답할 수 없는 상태였다.
컴북스 제공 고유 사건번호 142
공식 상세 페이지 미확인 → 제외 -103
엔진 라벨 부족 → 제외 -8
엔진 적재본에 포함 31 (21.8%)
이 중 리스트업 선정 10 (A 3 · B 6 · C 1)
제외된 103건은 사건번호만으로는 인용 출처가 되지 않아 적재하지 못했다. 판결문
원문이나 확인 경로를 받으면 적재 가능하므로 컴북스에 회신을 요청해야 하고, 그
목록을 Excel 시트에 그대로 실었다.
Excel 에 시트 2개 추가:
적재본 전체 545건 전수. 출처(컴북스/위원회)와 리스트업 등급을 함께 표시
컴북스 제공분 단계별 반영 내역, 적재된 31건, 회신 요청할 103건 목록
주의로 남긴 것: 컴북스 목록의 주제 분류와 실제 판시가 어긋나는 건이 리스트업에도
흘러들어갔다. 컴북스 유래 A등급 3건 중 2012다73493(깃털 공예품)은 어문 사건이
아니며 2017다212095(게임)도 마찬가지다. 인용 전 원문 대조가 필요하다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CSV 는 UTF-8 BOM 이라 Excel 에서 열리기는 하지만 받는 쪽이 그대로 읽을 수 있는
형태가 아니다. 열 너비·줄바꿈·필터가 없어 판시 요약처럼 긴 칸이 한 줄로 뭉개지고
등급별로 훑어보기도 어렵다. 전달 첨부용 통합문서를 별도로 만든다.
docs/판례_리스트업.xlsx — 5개 시트
판례 목록 57건. 등급 색상 구분, 자동 필터, 사건번호까지 틀 고정, 출처 하이퍼링크
요약·방법 검토 단계별 건수(2,085 → 545 → 57), 등급 정의, 핵심 3건
제외 사유 수집 단계 제외분과 적재본에서 뺀 유형
데이터 공백 상담 전 해소가 필요한 4개 항목 + 선덕여왕 항소심 인용 주의
상담 질의 전문가 상담용 질의 5건
표 데이터는 precedent_listup.csv 에서 읽고, 서술 시트는 PRECEDENT_LISTUP.md 를
원본으로 옮겼다. 수치를 스크립트에서 새로 만들지 않는다.
법률 의견서가 아니라 데이터 정리 결과이며 등급·쟁점 요약은 적재 판시를 근거로
부여한 것이라는 단서를 요약 시트에 함께 넣었다. 전달 시 유지해야 한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
한국저작권위원회 운영 적재본 545건을 전수 검토해 A/B/C 3등급 57건을 선정하고
제외 사유와 데이터 공백을 함께 정리했다. 표는 scripts/build_precedent_listup.py로
JSONL에서 재생성한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
계획서 p.24 수식의 분모가 참조 n-gram 수이므로 지표는 recall 인데
eval_rouge.py 는 ROUGE-1 F1 을 목표 0.65 와 대조하고 있었다. 통상 시스템
요약이 참조보다 길면 recall > F1 이므로 우리에게 불리한 자체 기준으로
채점해 온 셈이다(내장 샘플에서 recall 0.5778 vs F1 0.5539).
같은 수식이 Σ_S∈{Reference Summaries} 로 다중 참조를 전제하는데 rouge_n /
rouge_l 은 참조를 문자열 하나만 받았다. 이제 문자열도 리스트도 받는다.
참조가 1개면 기존과 완전히 같은 값이 나오며 이를 테스트로 고정했다.
--iaa 모드를 추가했다. 사람 둘이 같은 글을 요약해도 ROUGE 는 100 이 안
나오고, 그 상한이 65 보다 낮으면 어떤 시스템도 목표를 달성할 수 없다.
정답셋 300건을 만들기 전에 파일럿 20건으로 상한을 먼저 재기 위한 것이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
보유 코퍼스 31,560건이 전부 human 라벨이라 이진 판별기를 학습할 수 없고
(train_ai_detector.py 가 exit 2 로 막는다), 조사 결과 공개된 한국어 AI 생성
판별 데이터셋도 확인되지 않았다. AI 쪽 절반을 직접 만든다.
build_ai_training_dataset.py 가 외부 호출을 금지하므로 생성은 별도 스크립트로
분리했다. 프롬프트는 이미 파생된 메타데이터만 쓰고 에피소드 본문은 어떤
경로로도 API 요청에 실리지 않는다. 주석만으로는 다음 사람이 META_COLUMNS 에
본문 컬럼을 한 줄 추가하는 것을 못 막으므로, assert_no_body_columns() 가
실행 시점에 차단하고 _build_prompt() 는 본문을 넘길 파라미터 자체가 없다.
- 길이 매칭: human 분포에서 목표 길이를 뽑아 지시하고 벗어난 결과는 버린다.
분량이 다르면 판별기가 문체가 아니라 길이를 배운다.
- 생성기 다중화: --model 반복 지정 시 라운드로빈. 1개면 그 모델만 잡는
판별기가 되므로 경고한다.
- 문체 6종을 결정적으로 배분해 한 모델의 한 문체 암기를 막는다.
- 생성문에도 human 과 같은 normalize_ocr 을 적용한다. 한쪽만 정규화하면
오염 방향만 뒤집힐 뿐이다.
- append 전용 + prompt_id 스킵으로 재개 가능. dry-run 은 파일시스템도
건드리지 않는다.
--base-url 로 사내 GPU 의 OpenAI 호환 서버를 쓰면 메타데이터조차 외부로
나가지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
학습·캘리브레이션에 쓰는 79권 코퍼스는 OCR 후처리본이라 저자 문체가 아닌
스캔·조판 흔적이 남아 있다. AI 생성 표본에는 그 흔적이 없으므로, 그대로 두면
분류기가 문체가 아니라 "OCR 흔적이 있으면 human"을 배운다. 그러면 운영에서
들어오는 깨끗한 인간 원고가 AI로 오판된다.
규칙은 추측이 아니라 코퍼스 34,105건 실측에서 뽑았다. 표본 3,000건 기준
숫자+공백+단위 94.8%, 한자 병기 99.4%, 낫표 100% 제거.
정상 한국어인 `America라는`·`3년` 형태는 건드리지 않는다.
숫자-단위 규칙은 정규식으로 밀어넣으면 `3 번지`를 `3번지`로 잘못 붙이므로
단위·접미사 화이트리스트로 판정한다.
멱등성과 "깨끗한 입력에 무해" 두 불변식을 테스트로 고정했다. 후자가 깨지면
운영 원고가 학습 코퍼스와 다르게 처리되어 정규화 자체가 새 편향이 된다.
calibrate_ai_detector_cuts.py 에 xlsx 입력과 OCR 정규화(기본 켜짐)를 추가했다.
79권 3,000건 실측 결과 low_cut 0.4286 / high_cut 0.5298, 인간 원고 기준
예상 high 비율 2.03%(설계 목표 2%)로 포화 없이 잡혔다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AI 생성 표본이 없어 정확도를 측정할 수 없는 상태에서, 규칙 기반 휴리스틱을
실제로 쓸 수 있게 만든다. 점수의 의미를 "AI일 확률"에서 "등록 코퍼스의 인간
저작물 대비 문체 이례도"로 재정의해, 라벨 없이도 참인 진술이 되도록 했다.
덤으로 high 배지 비율이 정의상 고정되어 검토 부하가 예측 가능해진다.
- ai_detector: low_cut/high_cut 주입 지원. 둘 다 주어질 때만 적용하고,
적용되면 model_version 에 +corpus-percentile 을 붙여 컷 출처를 드러낸다.
is_stub 은 여전히 true — 컷을 맞췄을 뿐 학습된 모델이 아니다.
- calibrate_cuts/percentile/score_text_heuristic 순수 함수 추가.
- scripts/calibrate_ai_detector_cuts.py: 코퍼스 표본의 점수 분포에서 백분위
컷을 산출하고 .env 두 줄을 출력한다.
- 규칙 점수가 상단에서 clip 되어 p90=p98 이 되면 그 컷은 high 배지를 영원히
0건으로 만든다. 이 경우 .env 를 출력하지 않고 exit 3 으로 중단하며
saturated_share/distinct_scores 진단을 남긴다. 유효 표본 100건 미만은 exit 2.
- kiwipiepy 유무가 점수를 바꾸므로 실제 사용 여부를 리포트에 기록하고 경고한다.
기본값은 그대로 비활성(AI_DETECTOR_ALLOW_HEURISTIC=false)이라 켜지 않으면
동작이 바뀌지 않는다. 컷 미설정 시에는 자리표시자임을 note 로 경고한다.
테스트 180건 통과 (신규 13건).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
컴북스 데이터 수령 전 가능한 작업을 선행 구현. 데이터 도착 즉시
학습·검증에 착수할 수 있도록 알고리즘·평가 하니스·문서를 준비.
알고리즘/파이프라인:
- engine/clustering.py: 군집화 기반 부분 표절(요소 교체) 판별,
detect 응답에 partial_signal 필드 노출 (계획서 2단계 표절검출 고도화)
- engine/summarizer.py + POST /v1/summary: TextRank 추출적 요약 +
통합(LLM) 골격 (과제2 ② 스토리 요약/분석)
- engine/preference.py + scripts/build_preference_dataset.py:
Human Feedback 선호학습(DPO) 데이터 파이프라인 골격
평가 하니스 (정답셋 도착 즉시 측정):
- engine/rouge.py + scripts/eval_rouge.py: 요약 ROUGE (지표 No.7)
- engine/metadata_eval.py + scripts/eval_metadata_f1.py: 메타 추출 F1
(지표 No.3, KLUE NER 호환)
- engine/case_coverage.py + scripts/analyze_case_coverage.py:
39 케이스 갭 분석 → 컴북스 데이터 요청 목록 (정밀도 97% 근거)
문서:
- docs/DATA_REQUEST_SPEC.md: 요청 데이터 스펙 + 요약 정답셋/HF 라벨 가이드
- docs/INTEGRATION_INTERFACE.md: 2단계 통합 인터페이스
- docs/SW_COPYRIGHT_REGISTRATION.md: SW 저작권 등록 준비
- docs/PHASE2_PROGRESS.md, docs/CASE_COVERAGE.md
테스트 31 → 67건 전부 통과.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>