o2o-plagiarism-ai/docs/API_SPEC_BAIKAL.md
hbyang fefb393234 저작권 탭 UI 매핑(review_summary) + AI 생성 의심도 스텁 추가
나누구 앱 저작권 탭 연동을 위해 detect 응답에 두 블록 추가:
- review_summary: 독창성%/유사도%/유사문장 건수/대조 건수/의심 유무/AI 의심도
  (독창성 환산 캘리브레이션 포함 — 무관한 글은 유사도 0~5%로 눌러 표시)
- ai_generation: AI 생성 의심도 스텁(요청마다 더미, is_stub=true).
  워터마킹+언어특징 분류 정식 구현 전까지 계약 확정용.

바이칼 연동용 API 양식서(docs/API_SPEC_BAIKAL.md) 추가.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 13:15:07 +09:00

206 lines
8.3 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 필드 매핑 (핵심)
나누구 저작권 탭의 각 표시 항목은 아래 필드에서 그대로 읽으면 된다. **별도 계산 불필요**
— 독창성 환산(점수 변환)까지 오투오가 완료해 `review_summary`로 제공한다.
| 화면 표시 | 예시 | API 필드 |
|---|---|---|
| 독창성 **98%** | 98 | `review_summary.originality_percent` |
| 저작권 · 유사도 **2%** | 2 | `review_summary.similarity_percent` |
| 유사 문장 **0건** | 0 | `review_summary.similar_sentence_count` |
| 나누구 에피소드 **3.5만 건**과 대조 | 35000 | `review_summary.compared_count` |
| 표절 의심 구간 **없음** | false | `review_summary.has_suspicion` |
| AI 생성 의심도 **낮음** | low | `review_summary.ai_suspicion_level` |
> `ai_suspicion_level` 값 매핑: `low`=낮음, `medium`=중간, `high`=높음
> **⚠️ AI 생성 의심도는 현재 더미(스텁) 값입니다.** UI 연동 계약 확정용이며, 정식 판별
> 로직(워터마킹+언어특징 분류) 적용 전까지 `ai_generation.is_stub=true` 로 반환됩니다.
> UI는 지금 그대로 붙여두면 되고, 정식 구현 시 값만 실제로 바뀝니다.
---
## 2. 표절 탐지 — `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,
"note": "더미 응답 — 실제 AI 생성 판별 결과가 아님"
},
"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": "low", "score": 0.06, "is_stub": true, "note": "더미 응답 — 실제 AI 생성 판별 결과가 아님" },
"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 | 표절 판정 여부 (= `review_summary.has_suspicion`) |
| `confidence` | float | 최상위 매칭 결합 유사도 원값(0~1). **화면 표시는 `review_summary` 사용 권장** |
| `review_summary` | object | **저작권 탭 UI 직접 매핑** (§1 표 참조) |
| `ai_generation` | object | AI 생성 의심도 상세. `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 | 엔진 버전 |
---
## 3. 부가 엔드포인트
| 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` | 엔진 상태·코퍼스 크기·버전 |
---
## 4. 에러 포맷
FastAPI 표준. HTTP 상태코드 + `detail`.
```json
{ "detail": "에러 메시지" }
```
| 코드 | 상황 |
|---|---|
| 400 | 잘못된 요청(빈 본문 등) |
| 404 | 배치 job_id 없음 |
| 422 | 스키마 검증 실패 |
| 503 | 분류체계 미로딩 |
---
## 5. 연동 시 주의
1. **AI 생성 의심도는 현재 더미** — `is_stub` 로 판별 후, UI에는 표시하되 "참고용"으로 둘 것.
출판 승인/거절 게이트로 쓰지 말 것(오탐 리스크).
2. **화면 값은 `review_summary` 사용** — `confidence`(원값)는 임베딩 성분 때문에 무관한 글도
높게 나오므로 직접 표시 금지. 독창성 환산은 오투오가 `review_summary`에서 완료해 제공.
3. **개인정보** — 실사용자 자서전 본문은 개인정보. 실서비스는 온프레미스(Docker) 납품으로
전환 예정. 개발 단계 REST 호출 시에도 테스트 데이터 사용 권장.
4. `compared_count` 는 현재 로딩된 코퍼스 크기. 실데이터 적재 후 실제 대조 건수로 표시됨.