o2o-plagiarism-ai/docs/API_SPEC_BAIKAL.md

215 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 저작권 탐지 API 양식서 (오투오 → 바이칼)
> 나누구 앱 **저작권 탭** 연동용 API 계약. 본문 입력 → 표절 탐지 결과 + 저작권 탭
> 표시 항목을 반환한다. 본 문서 기준으로 UI를 연동하면 된다.
> 엔진: `o2o-plagiarism-api`
---
## 0. 기본 정보
| 항목 | 값 |
|---|---|
| Base URL (개발/통합 테스트) | `https://plagiarism.o2o.kr` |
| 프로토콜 | HTTPS, `Content-Type: application/json` (UTF-8) |
| 인증 | 개발 단계 없음 → **운영 전 API 키/토큰 추가 예정** |
| Swagger(자동 명세) | `{BASE}/docs` — 실시간 스키마 확인 가능 |
| 실서비스 배포 | 개인정보(자서전) 보호를 위해 **Docker 온프레미스 납품** 예정 (실사용자 본문은 오투오 서버로 전송 안 함) |
---
## 1. 저작권 탭 화면 ↔ API 필드 매핑 (핵심)
나누구 저작권 탭의 각 표시 항목은 경량 응답에서 그대로 읽으면 된다. **별도 계산 불필요**
— 독창성 환산과 한글 라벨까지 서버가 완료해 제공한다.
| 화면 표시 | 예시 | API 필드 |
|---|---|---|
| 독창성 **98%** | 98 | `copyright.originality_percent` |
| 저작권 · 유사도 **2%** | 2 | `copyright.similarity_percent` |
| 유사 문장 **0건** | 0건 | `similar_sentences.label` |
| 대조 결과 설명 | 문장 | `copyright.description` |
| 표절 의심 구간 **없음** | false | `copyright.has_suspicion` |
| AI 생성 의심도 **낮음** | 낮음 | `ai_generation_suspicion.label` |
| 판례 판단 | 침해 의심 낮음 | `legal_judgment.label` |
| 판례 근거 | 사건번호 포함 문장 | `legal_judgment.summary` |
> `ai_generation_suspicion.level` 값은 `low`, `medium`, `high`, `unknown`이며,
> 화면은 함께 반환되는 한글 `label`을 그대로 표시한다.
---
## 2. 저작권 탭 경량 검사 — `POST /v1/plagiarism/review`
모바일 저작권 탭은 이 API를 사용한다. 내부 상세 탐지 결과 중 화면에 필요한
독창성, 유사도, 대조 건수, 유사 문장 수, AI 의심도, 판례 판단만 반환한다.
요청 형식은 기존 `POST /v1/plagiarism/detect`와 동일하며 응답 계약은
`docs/API_GUIDE_BAIKAL.md`를 따른다.
## 3. 상세 표절 탐지 — `POST /v1/plagiarism/detect`
본문 1건을 검사한다.
### 요청
```json
{
"doc_id": "episode-001",
"text": "창밖으로 보이는 숲은 오늘따라 유난히 푸르게 보였다. ...",
"metadata": { "title": "에피소드 1", "author": "홍길동", "genre": "자서전" },
"options": {
"return_evidence": true,
"threshold": null,
"top_k": 5,
"autobiography_mode": null
}
}
```
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| `doc_id` | string | ✅ | 호출측 문서 식별자 (응답에 그대로 반환) |
| `text` | string | ✅ | 검사할 본문 (1자 이상) |
| `metadata` | object | | `title`/`author`/`genre`/`publisher`/`publication_year` (모두 선택) |
| `options.return_evidence` | bool | | 일치 구간 하이라이트 반환 (기본 true) |
| `options.threshold` | float\|null | | 판정 임계값. null이면 서버 기본(0.85) |
| `options.top_k` | int | | 최대 매칭 수 (기본 5) |
| `options.autobiography_mode` | bool\|null | | 자서전 특화 전처리. null이면 서버 설정 |
### 응답 (저작권 탭에 표시되는 "깨끗한 글" 예시)
```json
{
"doc_id": "episode-001",
"is_infringement": false,
"confidence": 0.32,
"review_summary": {
"originality_percent": 98,
"similarity_percent": 2,
"similar_sentence_count": 0,
"compared_count": 35000,
"has_suspicion": false,
"ai_suspicion_level": "low"
},
"ai_generation": {
"suspicion_level": "low",
"score": 0.06,
"is_stub": true,
"available": false,
"model_version": "unavailable",
"note": "학습된 모델이 없어 채점하지 않음"
},
"matches": [],
"extracted_elements": {
"characters": [], "motifs": [], "genre": "자서전", "keywords": ["정원", "숲"]
},
"ccl_basis": null,
"autobiography_mode": true,
"candidates_before_filter": 0,
"engine_version": "o2o-plagiarism-2.1.0-kosimcse",
"analyzed_at": "2026-08-04T09:30:00Z"
}
```
### 응답 (표절이 탐지된 경우 — matches가 채워짐)
```json
{
"doc_id": "episode-002",
"is_infringement": true,
"confidence": 0.88,
"review_summary": {
"originality_percent": 45,
"similarity_percent": 55,
"similar_sentence_count": 1,
"compared_count": 35000,
"has_suspicion": true,
"ai_suspicion_level": "low"
},
"ai_generation": { "suspicion_level": "unknown", "score": null, "available": false, "is_stub": false, "model_version": "unavailable", "note": "학습된 모델이 없어 채점하지 않음" },
"matches": [
{
"source_doc": "auto-0003",
"source_title": "○○○ 자서전",
"similarity": 0.88,
"tags": [
{ "tag": "reproduction", "role": "primary", "label_ko": "복제권" },
{ "tag": "citation_missing", "role": "primary", "label_ko": "인용 표시 누락" }
],
"case_id": "A6",
"case_title": "유명인 자서전 일부 베끼기",
"infringement_type": "copy",
"evidence_spans": [ { "start": 12, "end": 48, "matched": "일치한 본문 구간 ..." } ],
"score_breakdown": { "text_sim": 0.86, "lemma_sim": 0.94, "character_sim": 0.8, "motif_sim": 0.7, "lsh_jaccard": 0.62 },
"partial_signal": {
"cluster_id": 2, "verdict": "element_swap_plagiarism", "signature_score": 0.74,
"per_element": { "lemmas": 0.92, "keywords": 0.88, "characters": 0.0, "motifs": 0.1 },
"retained_elements": ["lemmas", "keywords"], "changed_elements": ["characters", "motifs"]
}
}
],
"ccl_basis": "'○○○ 자서전'와 결합 유사도 88%로 매칭. 주 침해 태그: 복제권, 인용 표시 누락. 추정 케이스 A6 ...",
"autobiography_mode": true,
"candidates_before_filter": 4,
"engine_version": "o2o-plagiarism-2.1.0-kosimcse",
"analyzed_at": "2026-08-04T09:31:00Z"
}
```
### 응답 필드 상세
| 필드 | 타입 | 설명 |
|---|---|---|
| `is_infringement` | bool | 후방호환용 임계 초과 매칭 여부. 법적 침해 확정 아님 |
| `confidence` | float | 최상위 매칭 결합 유사도 원값(0~1). **화면 표시는 `review_summary` 사용 권장** |
| `review_summary` | object | **저작권 탭 UI 직접 매핑** (§1 표 참조) |
| `ai_generation` | object | AI 생성 의심도 상세. 미학습이면 `available=false`, 휴리스틱이면 `is_stub=true` |
| `matches[]` | array | 매칭된 원본별 상세 (표절 시). 태그·케이스·근거 구간 포함 |
| `matches[].tags[]` | array | 법령 태그. `role`: `primary`(주)/`secondary`(보조), `label_ko` 한글 표기 |
| `matches[].case_id` | string | 39종 침해 케이스 ID (예: A6) |
| `matches[].evidence_spans[]` | array | 본문 내 일치 구간 `{start, end, matched}` — 하이라이트용 |
| `matches[].partial_signal` | object | 군집화 기반 부분 표절(인물만 교체 등) 분해 — 침해요소 DB 적재용 |
| `ccl_basis` | string\|null | 사람이 읽는 판정 근거 문장 |
| `engine_version` | string | 엔진 버전 |
---
## 4. 부가 엔드포인트
| Method | Path | 용도 |
|---|---|---|
| POST | `/v1/plagiarism/batch` | 배치 검사(≤500건). `202` + `job_id` 반환 → 아래 상태 조회 |
| GET | `/v1/plagiarism/batch/{job_id}` | 배치 상태·결과 조회 |
| POST | `/v1/summary` | 스토리 요약 (과제2 ②) |
| GET | `/v1/taxonomy` | 10종 법령 태그 + 39 케이스 정의 (동일 라벨 공유용) |
| GET | `/v1/health` | 엔진 상태·코퍼스 크기·버전 |
---
## 5. 에러 포맷
FastAPI 표준. HTTP 상태코드 + `detail`.
```json
{ "detail": "에러 메시지" }
```
| 코드 | 상황 |
|---|---|
| 400 | 잘못된 요청(빈 본문 등) |
| 404 | 배치 job_id 없음 |
| 422 | 스키마 검증 실패 |
| 503 | 분류체계 미로딩 |
---
## 6. 연동 시 주의
1. **AI 생성 의심도는 확정값이 아님**`available`/`is_stub`/`model_version`을 확인하고 사람 검토 우선순위로만 사용할 것.
출판 승인/거절 게이트로 쓰지 말 것(오탐 리스크).
2. **화면 값은 `review_summary` 사용**`confidence`(원값)는 임베딩 성분 때문에 무관한 글도
높게 나오므로 직접 표시 금지. 독창성 환산은 오투오가 `review_summary`에서 완료해 제공.
3. **개인정보** — 실사용자 자서전 본문은 개인정보. 실서비스는 온프레미스(Docker) 납품으로
전환 예정. 개발 단계 REST 호출 시에도 테스트 데이터 사용 권장.
4. `compared_count` 는 현재 로딩된 코퍼스 크기. 실데이터 적재 후 실제 대조 건수로 표시됨.