AI 출판과제 - 저작권 침해 여부 판단
Go to file
hbyang b73d27a850 feat: split author/admin detect views and add case matching KPI basis
월례회의 자료(2026-09-18) p.7 파이프라인의 3단계 「저자 화면에는 케이스 코드를
노출하지 않는다」를 구현하고, 후속 합의에 필요한 문서를 함께 남긴다.

- DetectOptions.audience(admin 기본 / author). author 직렬화에서 case_id,
  case_candidates, tags, legal_risk, is_infringement 을 제외하고 ccl_basis 를
  코드 없는 문장으로 대체한다. 일치 위치와 점수는 유지한다.
- is_infringement 는 필수 bool 로 둔다. run_precision_eval.py 등 소비자가 bool
  로 읽으므로 선택 필드로 두면 None 이 조용히 흘러간다. 제외는 직렬화에서만 한다.
- publication_verdict 필드 추가. 컴북스 코드표 미확보이므로 39건 전부 null 이며
  null 을 출간 허용으로 해석하지 않는다. enum 과 대표값 선정은 코드표 수령 후.
- request_id / taxonomy_version 을 응답에 싣는다. 관리자 확정 로그와 연결된다.
- engine_version 기본값을 2.2.1-cases-v1.3 으로 맞춘다. 직전 값(2.0.1)이 King
  운영값 2.2.0-persistent-cpu 보다 낮아 성적서 대조 시 뒤집혀 보였다.

케이스 정의는 39건(A 27건)을 유지한다. 회의 자료의 40건(A 28건)과 1건 차이가
있으나 아카이빙 DB v2.3 원본을 받기 전까지 추측해 채우지 않는다.

7,786편 운영 재검사는 모집단 불일치(현재 6,343건)로 중단했고 부분 실행은 집계하지
않는다. 별도 평가셋 재측정은 기존 testset_v2 수치(precision 98.4032%)를 그대로
재현했으며 새 독립 시험 결과가 아니다. 상세는 reports/CASE_MATCHING_EVAL_*.json.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 16:16:33 +09:00
app feat: split author/admin detect views and add case matching KPI basis 2026-09-18 16:16:33 +09:00
data feat: split author/admin detect views and add case matching KPI basis 2026-09-18 16:16:33 +09:00
docs feat: split author/admin detect views and add case matching KPI basis 2026-09-18 16:16:33 +09:00
reports feat: split author/admin detect views and add case matching KPI basis 2026-09-18 16:16:33 +09:00
scripts chore: drop superseded eval visualizer and duplicate ROUGE helper 2026-09-18 09:48:12 +09:00
tests feat: split author/admin detect views and add case matching KPI basis 2026-09-18 16:16:33 +09:00
.dockerignore chore: 수기집 원본을 저장소와 이미지에서 제외 2026-08-20 17:25:54 +09:00
.env.example feat: 수령 자서전 데이터 파이프라인과 맞춤 요약 추가 2026-08-20 16:59:17 +09:00
.gitignore feat: add precision test harness and 2-1년차 test plan 2026-09-14 14:56:02 +09:00
docker-compose.yml 3.5만 에피소드 기반 표절·AI·판례 분석 파이프라인 구현 2026-08-10 16:12:15 +09:00
Dockerfile Claude 리뷰 기반 운영 안정성 보강 2026-08-10 16:42:17 +09:00
Dockerfile.eval feat: add precision test harness and 2-1년차 test plan 2026-09-14 14:56:02 +09:00
Dockerfile.gpu-embed feat: add isolated gpu embedding review batch 2026-09-02 09:58:59 +09:00
Dockerfile.ner feat: add KLUE NER training for metadata F1 metric 2026-09-15 10:54:37 +09:00
README.md API Key 인증 완전 제거 2026-05-14 08:58:28 +09:00
requirements.txt fix: 평가환경(python 3.9)에서 임포트 실패 해결 2026-08-19 14:02:29 +09:00

O2O 저작권 침해 여부 탐지 API

KOCCA 출판환경변화 과제 2단계 - 오투오 산출물. 자서전 본문을 입력하면 저작권 침해 여부를 판정해 법령 기반 메타 태그와 케이스 ID로 반환합니다.

기능

  • 삼중 유사도 탐지 — 표면(임베딩) + 구조(형태소 lemma 교집합) + 요소(인물·모티프) 결합 판정
  • 3단 캐스케이딩 — MinHash+LSH 1차 필터 → 정밀 비교 → 침해 유형 분류
  • 법령 기반 10종 메타 태그 — 복제권 / 공중송신권 / 배포권 / 2차적저작물작성권 / 공표권 / 성명표시권 / 동일성유지권 / 인용 표시 누락 / 자기 창작인 양 표시 / 2차적저작물 미달 가공
  • 39개 침해 케이스 자동 매핑 — 그룹 A(저자 가해) ~ X(분류체계 외)
  • 자서전 특화 처리 — 공통 표현 사전 제거 + NER 마스킹으로 오탐 방지
  • 검토 콘솔 웹 UI — 브라우저에서 본문 입력·검사·결과 분석, 코퍼스 관리
  • 코퍼스 직접 관리 — 사용자가 자서전을 직접 업로드/삭제, 인덱스 자동 재빌드
  • 배치 처리 — 비동기 잡으로 최대 500건 일괄 검사

빠른 시작

Docker

cp .env.example .env
# .env 에서 HOST/PORT/LOG_LEVEL/OPENAI_API_KEY 등 조정 (선택)
docker compose up --build

로컬 (Python 3.13 권장)

python3.13 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# .env 의 HOST/PORT 따라 실행
python -m app.main

# 또는 일회성 override
PORT=9000 LOG_LEVEL=debug python -m app.main

# 또는 uvicorn 직접
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

접속:

  • http://localhost:{PORT}/ — 검토 콘솔 (브라우저용)
  • http://localhost:{PORT}/docs — API 명세 (Swagger)

.env 의 서버 바인딩 변수:

변수 기본 설명
HOST 0.0.0.0 바인딩 호스트
PORT 8000 포트
LOG_LEVEL info debug/info/warning/error
RELOAD false 파일 변경 시 자동 재시작 (개발용)

사용법

1. 브라우저에서 사용 (검토 콘솔)

http://localhost:8000/ 접속.

[탐지 검토] 탭

  1. 본문 텍스트 붙여넣기 (또는 샘플 시나리오 버튼 클릭)
  2. "검사 시작" → 결과 표시
    • 큰 판정 배지 (침해 여부 + 결합 유사도 %)
    • 점수 분석 (text / lemma / character / motif 4개 막대)
    • 매칭된 레퍼런스 + 법령 태그 chip (주/보조) + 케이스 ID
    • 본문에 일치 구간 하이라이트

[코퍼스 관리] 탭

  1. 좌측 폼에서 자서전 신규 등록 (제목 + 본문 또는 .txt 파일)
  2. 우측 테이블에서 등록된 자서전 확인 / 삭제
  3. 업로드/삭제 시 인덱스 자동 재빌드

2. API로 사용 (curl)

# 탐지
curl -X POST http://localhost:8000/v1/plagiarism/detect \
  -H "Content-Type: application/json" \
  -d '{
    "doc_id": "test-001",
    "text": "검사할 본문 텍스트…",
    "metadata": {"title": "작품명", "author": "저자"}
  }'

# 자서전 업로드
curl -X POST http://localhost:8000/v1/corpus \
  -H "Content-Type: application/json" \
  -d '{"title": "김OO 자서전", "text": "본문…"}'

# .txt 파일 업로드
curl -X POST http://localhost:8000/v1/corpus/file \
  -F "title=김OO 자서전" \
  -F "file=@autobiography.txt"

# 코퍼스 목록
curl http://localhost:8000/v1/corpus

# 분류체계 조회 (10종 태그 + 39 케이스)
curl http://localhost:8000/v1/taxonomy

엔드포인트 요약

Method Path 용도
GET / 검토 콘솔 (HTML)
GET /docs Swagger UI
GET /v1/health 헬스체크 + 엔진 정보
GET /v1/taxonomy 분류체계 조회
POST /v1/plagiarism/detect 단건 동기 탐지
POST /v1/plagiarism/batch 배치 잡 등록 (≤500건)
GET /v1/plagiarism/batch/{job_id} 배치 결과 조회
GET /v1/corpus 코퍼스 목록
POST /v1/corpus JSON 업로드
POST /v1/corpus/file .txt 파일 업로드
DELETE /v1/corpus/{doc_id} 삭제

응답 스키마 (탐지 결과)

{
  "doc_id": "test-001",
  "is_infringement": true,
  "confidence": 0.85,
  "extracted_elements": {
    "characters": ["..."],
    "motifs": ["..."],
    "genre": "...",
    "keywords": ["..."]
  },
  "matches": [{
    "source_doc": "ref-0001",
    "source_title": "원본 작품명",
    "similarity": 0.85,
    "tags": [
      {"tag": "reproduction", "role": "primary", "label_ko": "복제권"},
      {"tag": "citation_missing", "role": "primary", "label_ko": "인용 표시 누락"},
      {"tag": "public_transmission", "role": "secondary", "label_ko": "공중송신권"}
    ],
    "case_id": "A1",
    "case_title": "시·노래 가사 본문 무단 인용",
    "evidence_spans": [{"start": 21, "end": 34, "matched": "…"}],
    "score_breakdown": {
      "text_sim": 0.43, "lemma_sim": 0.75,
      "character_sim": 0.0, "motif_sim": 0.67,
      "lsh_jaccard": 0.07
    }
  }],
  "ccl_basis": "…",
  "autobiography_mode": true,
  "engine_version": "o2o-plagiarism-2.0.0-pdf-v1.2"
}

환경변수 (.env)

변수 기본 설명
SIMILARITY_THRESHOLD 0.85 침해 판정 임계값 (정밀도 우선)
AUTOBIOGRAPHY_MODE true 자서전 특화 전처리 (공통표현+NER)
USE_LSH_FILTER true MinHash+LSH 1차 필터
USE_LLM_EXTRACTOR false OpenAI 기반 요소 추출 (키 필요)
USE_EMBEDDING_SIMILARITY false OpenAI 임베딩 유사도 (키 필요)
OPENAI_API_KEY (빈값) 비우면 룰 기반 + TF-IDF 폴백
WEIGHT_TEXT_SIM 0.30/0.45/0.15/0.10 삼중 유사도 가중치 (합 1.0)

요청 단위 override 가능 항목:

  • options.threshold — 임계값
  • options.autobiography_mode — 자서전 모드 ON/OFF

테스트

pytest tests/ -v
# 31 passed — API, 삼중 유사도, 형태소 분석, PDF 분류체계, LSH, 자서전 필터, 다중 태그 부여

디렉토리 구조

app/
├── main.py                       # FastAPI 앱
├── api/{routes,schemas}.py       # 엔드포인트 + Pydantic 모델
├── core/{config,auth}.py         # 설정 + API Key 인증
├── engine/
│   ├── detector.py               # 탐지 파이프라인 오케스트레이션
│   ├── extractor.py              # 콘텐츠 요소 추출 (룰 또는 OpenAI)
│   ├── similarity.py             # 삼중 유사도 + TF-IDF/임베딩 백엔드
│   ├── structural.py             # 형태소 lemma 교집합
│   ├── lsh_filter.py             # MinHash+LSH 1차 필터
│   ├── autobiography_filter.py   # 자서전 공통표현 제거 + NER 마스킹
│   ├── corpus.py                 # 코퍼스 CRUD
│   └── taxonomy.py               # 10종 태그 + 39 케이스 매핑
├── jobs/store.py                 # 배치 잡 in-memory 스토어
└── static/index.html             # 검토 콘솔 UI
data/
├── reference/                    # 자서전 코퍼스 (업로드 저장 위치)
├── taxonomy/{meta_tags,cases}.json   # PDF v1.2 분류체계
└── autobiography/common_patterns.txt # 자서전 빈출 표현 사전