Commit Graph

66 Commits

Author SHA1 Message Date
1e56bdf1c0 reports 수정 및 script 수정 . 2026-09-07 10:45:33 +09:00
6b27fff509 feat: query life writing at segment level
생활수기는 문서 단위로만 검사되고 있었다. 코퍼스에는 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>
2026-09-04 14:40:53 +09:00
4e650d59ad fix: dedup only same-author duplicates
중복 제거를 텍스트만 보고 하던 것을 작성자까지 보게 고친다. 저자가 같으면
같은 사람 글이 두 번 적재된 것이라 침해가 아니지만, 저자가 다르면 그 중복
자체가 침해 후보다. 앞서는 이를 구분하지 않아 256건을 모두 뺐고, 그중
17건이 서로 다른 작성자의 글이었다.

같은 작성자 그룹만 제외하도록 목록을 다시 만들어(239건) 재실행하니 검사
대상 6104건, 침해의심 106건이다. 80 -> 106 의 증가분은 되살린 17건 전부와,
그 17건이 색인에 돌아오며 새로 매칭된 9건이다. 빠진 건은 없다.
106건 전수 확인 결과 매칭 상대의 작성자는 모두 다르다.

판정 사유 표기도 바로잡는다. 행 단위 대표값으로 재현하면 서로 다른 후보가
각기 다른 조건을 충족한 3건이 '사유 미상' 으로 빠졌다. 후보 판정재료를
쓰도록 고쳤다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 17:00:05 +09:00
94a660dc35 feat: finalize report at 9-eojeol threshold
기준을 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>
2026-09-03 14:29:30 +09:00
bf3bd5b99b feat: sweep exact-span threshold from 3 to 9 eojeol
상무님 요청대로 어절 기준을 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>
2026-09-03 13:27:10 +09:00
f4fab1089e feat: fold duplicate analysis into the report workbook
별도 파일을 늘리지 않고 기존 결과보고 워크북에 '중복 원고' 시트로 넣는다.
중복 제거 후 재실행하면 28건이 결과에서 사라지므로, 사라지기 전에 어떤
문서 사이의 중복이었는지 원문째로 남겨야 나중에 같은 제출자의 재제출인지
다른 제출자의 표절인지 확인할 수 있다.

--no-excerpt-sheet 로 원문 대조 시트 없이 중복 시트만 붙일 수 있게 했다.
결과보고는 원문 없는 배포판이라 이 경로를 쓴다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 10:44:18 +09:00
76c710c6ef feat: support dedup rerun and configurable exact-span threshold
상무님 지적 두 가지를 검증 가능한 형태로 만든다.

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>
2026-09-03 10:29:27 +09:00
e89cd23ed6 feat: report original text and judgment criteria for review
검토자가 침해 여부를 눈으로 판별하려면 원문이 있어야 하고, 어떤 조건으로
걸렸는지 알아야 한다. 두 가지를 워크북에 싣는다.

- 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>
2026-09-03 09:49:50 +09:00
aed8cd6b48 docs: add 2nd embedding batch results and reporting workbook
2차 GPU 임베딩(KoSimCSE) 배치 6343건 전수 결과와, 이를 보고용으로
재구성한 워크북을 추가한다. 모든 문서는 가명 처리되어 있으며 원문
텍스트와 실명은 포함하지 않는다.

1차 대비: 의심 81 -> 103 (공통 77, 2차 신규 26, 1차에서만 4).
다만 임베딩 교체로 전 건 결합유사도가 평균 +0.0914 상승한 반면
임계값은 동일하므로, 신규 26건 중 17건은 근거 스팬이 0이다.
건수 증가를 곧바로 탐지력 향상으로 해석하면 안 된다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 13:47:50 +09:00
87fc98119d feat: add reporting xlsx builder for infringement batches
배치 산출 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>
2026-09-02 13:46:31 +09:00
8717fa4425 feat: add isolated gpu embedding review batch 2026-09-02 09:58:59 +09:00
8762fce51e docs: add infringement batch report dataset 2026-09-02 09:48:43 +09:00
cbeb1e1084 feat: support sharded infringement batches 2026-09-02 09:28:38 +09:00
c35c5aabfc feat: add anonymized infringement batch reporting 2026-09-02 09:23:45 +09:00
d5e0f4346d docs: GPT 확장 AI 탐지 학습 결과 기록 2026-08-25 13:42:23 +09:00
16ce1c7d68 docs: 최신 API 연동 명세와 PDF 갱신 2026-08-25 09:54:48 +09:00
c5f66eff30 docs: Qwen 대조문 학습과 운영 결과 기록 2026-08-21 09:10:41 +09:00
9e365e6b68 feat: AI 의심도 모델의 학습 범위 노출 2026-08-21 09:06:26 +09:00
480f00702f feat: 전달 파일 전용 정책과 AI 표본 품질 감사 추가 2026-08-21 08:44:22 +09:00
fcfaaab965 chore: 수기집 원본을 저장소와 이미지에서 제외 2026-08-20 17:25:54 +09:00
58f5c63fdb chore: 생성 산출물을 Docker 빌드에서 제외 2026-08-20 17:25:11 +09:00
40eede2566 feat: 요약 검수 패킷과 수기집 원본 수집 도구 추가 2026-08-20 17:24:39 +09:00
9f62ed877a chore: AI 생성 설정 provenance 기록 2026-08-20 17:22:14 +09:00
d0b5876ae5 feat: GPU 생성 작업 샤딩 지원 2026-08-20 17:19:41 +09:00
78e9f8648a fix: AI 표본 생성 재개 시 목표 건수 보존 2026-08-20 17:18:03 +09:00
265a388389 fix: AI 표본 생성기의 pandas 의존 제거 2026-08-20 17:15:35 +09:00
aabd7844d8 feat: 로컬 GPU AI 표본 병렬 생성 지원 2026-08-20 17:13:19 +09:00
946e9e9474 feat: 수령 자서전 데이터 파이프라인과 맞춤 요약 추가 2026-08-20 16:59:17 +09:00
5386222f1b feat: 전체 판례 검색과 판례 탭 추가 2026-08-20 16:20:37 +09:00
fa15117df7 fix: 판례 등급을 런타임 인용에 반영 2026-08-20 16:05:24 +09:00
500a4a4600 feat: 프론트에 판례 적재·인용 현황 표시
판례가 적재돼 있는지, 이번 판단에 실제로 쓰였는지가 화면에 전혀 드러나지
않았다. 엔진은 적재본 545건을 모두 로드하고 판정마다 저작물 유형·법적 태그가
맞는 상위 5건을 인용하는데, 사용자는 "판례를 쓰고 있는가"를 알 수 없었다.

세 곳에 표시한다.
  헤더 배지   ● 정상 · 코퍼스 3건 · 판례 545건
  푸터        판례 적재: 545건
  판단 카드   관련 판례 사건번호   인용 3건 / 적재 545건

적재 수를 함께 보여 주는 것이 핵심이다. "인용 3건"만 있으면 판례를 3개만
쓰는 것처럼 읽히는데, "/ 적재 545건"이 붙어야 545건 중 이 건에 맞는 3건을
고른 결과임이 드러난다.

인용 0건과 판례 미적재도 구분했다. 겉보기엔 둘 다 판례가 없지만 앞은 정상
동작이고, 뒤는 엔진이 insufficient_precedent_data 를 내며 판단 자체를
보류하는 상태다. 설정 오류일 가능성이 높아 배지를 경고색으로 바꾼다.

API 는 이미 /v1/health 의 precedent_count 와 응답의 precedent_ids 로
필요한 값을 주고 있었다. 프론트만 쓰지 않고 있었으므로 서버 변경은 없다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 14:54:51 +09:00
a45c79211c docs: 적재본 545건의 출처 내역 추가 (컴북스 31 / 위원회 514)
문제: 리스트업이 선별 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>
2026-08-20 12:57:34 +09:00
ba1a0bbc2f docs: 판례 리스트업 배포용 Excel 추가
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>
2026-08-20 11:36:47 +09:00
66a21f8fd2 docs: 자서전·출판물 표절 판단 근거 판례 리스트업 추가
한국저작권위원회 운영 적재본 545건을 전수 검토해 A/B/C 3등급 57건을 선정하고
제외 사유와 데이터 공백을 함께 정리했다. 표는 scripts/build_precedent_listup.py로
JSONL에서 재생성한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 14:44:20 +09:00
28c9ad1ee7 fix: 평가환경(python 3.9)에서 임포트 실패 해결
계획서 p.24 가 No.3/4/7 의 평가환경을 python 3.9 로 못박았는데, 실제로는
성능지표 평가 스크립트 3종이 전부 3.9 에서 임포트조차 되지 않았다.
python:3.9-slim 컨테이너에서 재현·수정·재검증했다.

원인: config.py 와 schemas.py 가 `from __future__ import annotations` 없이
`str | None` (PEP 604) 을 썼다. 3.10 부터의 문법이라 클래스 본문이 실행되는
순간 인터프리터가 평가하며 TypeError 로 죽는다. 이 두 파일을 타고 detector /
extractor / clustering / taxonomy / jobs.store / routes / main 이 연쇄로 깨졌다.

  No.7 eval_rouge.py       → summarizer → core.config
  No.3 eval_metadata_f1.py → extractor  → api.schemas
  No.4 evaluate_pairs.py   → detector   → api.schemas

개발환경이 3.14 라 로컬에서는 전혀 드러나지 않았다. 정답셋을 받아 측정하는
시점에 발견했다면 일정이 밀렸을 문제다.

수정은 두 가지가 모두 필요하다. future 임포트만 넣으면 pydantic 이 문자열
'str | None' 을 해석하지 못하고("Unable to evaluate type annotation"),
eval_type_backport 만 넣으면 인터프리터가 먼저 죽는다.

검증: 3.9 에서 eval_rouge.py / eval_metadata_f1.py 가 정상 실행되고 수치가
3.14 와 동일하다(ROUGE-1 recall 0.5778). evaluate_pairs.py 와 app.main 임포트도
통과. 3.14 회귀 없음.

재발 방지로 tests/test_py39_compat.py 를 추가했다. Pydantic 모델을 정의하는
모듈에 future 임포트가 있는지 AST 로 검사하므로 3.14 에서도 회귀를 잡는다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 14:02:29 +09:00
91aa077898 docs: 과업 범위·성능지표 정리와 AI 의심도 위상 명시
SCOPE_AND_METRICS.md 신규. 연구개발계획서(2-4 성능지표, 나-3 개발내용,
나 성과물 목표)를 대조해 오투오 몫을 정리했다.

- 성능지표 8개 중 우리가 수치를 책임지는 것은 No.3·4·7 세 개다.
- No.4 는 재현율이 아니라 정밀도라 애매하면 표절이라 말하지 않는 쪽이
  지표에 유리하다. 이 성질이 설계를 지배한다.
- 사용자 맞춤형 요약의 상세도·강조 내용 옵션이 계획서에 있는데 미구현이다.
- python 3.9 호환성 위험: 평가환경이 3.9 고정인데 config.py 와 schemas.py 가
  from __future__ import annotations 없이 PEP 604 를 쓴다. 둘 다 Pydantic
  모델이라 어노테이션이 런타임에 평가된다. 현재 개발환경이 3.14 라 안 드러난다.
- No.3 귀속이 오투오/고려대 사이에서 불분명해 확인이 필요하다.

AI_DETECTION.md 에 「위상과 기준」절 추가. AI 생성 판별은 성능지표 8개
어디에도 없고 계획서 개발내용에도 없다. "콘텐츠 표절 여부 AI 탐지 모듈"은
AI로 표절을 탐지하는 모듈이지 AI가 쓴 글을 탐지하는 모듈이 아니다.
따라서 정확도를 보고하지 않는다. 정답 라벨이 없는 대상에 정확도를 주장하면
검토자를 과신하게 만들 뿐이다. 대신 근거(79권 대비 문체 이례도)와
기준(실측 백분위 컷)을 명시하고, 할 수 있는 말과 없는 말을 표로 구분했다.
8장의 예시 컷이 자리표시자 값이라 실측값으로 갱신했다.

DATA_REQUEST_SPEC.md §5 요약 정답셋 가이드 보강. 다중 참조 포맷, 줄글 규격,
dev/test 분리(test 는 사람 직접 작성 — LLM 이 쓴 정답을 LLM 출력으로 맞히면
점수가 부풀고 방어할 수 없다), book 단위 누출 방지, §5.1 파일럿 절차,
§5.2 recall 정정 이력.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 13:54:40 +09:00
3da7a0a5f2 fix: 요약 ROUGE를 계획서 수식에 맞춤 (F1 → recall, 다중 참조)
계획서 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>
2026-08-19 13:54:22 +09:00
dc6c0f5d0f feat: AI 생성 표본 제작 스크립트
보유 코퍼스 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>
2026-08-19 13:54:21 +09:00
45355910fa feat: OCR·조판 아티팩트 정규화와 백분위 컷 캘리브레이션
학습·캘리브레이션에 쓰는 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>
2026-08-19 13:53:59 +09:00
7f18206f36 docs: API 가이드 부제와 갱신일 제거 2026-08-18 12:57:46 +09:00
6dd5fa4a2e feat: 저작권 탭 경량 응답 API 추가 2026-08-18 12:47:51 +09:00
91e356e4c1 fix: 판례 판단 시 사람 검토 안전장치 강제 2026-08-18 11:46:46 +09:00
3debc884c1 fix: 사용자 판단 문구에서 모델명 제거 2026-08-18 11:44:56 +09:00
2be4c39a97 fix: 판례 근거 중심으로 판단 문구 개선 2026-08-18 11:41:10 +09:00
3b549dc0c0 feat: 프론트에 GPT 판례 판단 표시 2026-08-18 11:29:04 +09:00
ee2f85a2d9 feat: 판례 GPT 판단과 연동 가이드 최신화 2026-08-18 11:10:02 +09:00
8427cf423b Merge remote-tracking branch 'origin/main' 2026-08-14 13:13:26 +09:00
4c7a16a4e3 판례 데이터 추가 . 2026-08-14 13:11:19 +09:00
a530d2139f AI 의심도 백분위 캘리브레이션 (학습·지표 없이 운영)
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>
2026-08-11 09:05:48 +09:00
f4461f39c7 feat: 프론트에 AI 생성 의심도 표시 2026-08-11 09:02:04 +09:00