컴북스 데이터 수령 전 가능한 작업을 선행 구현. 데이터 도착 즉시 학습·검증에 착수할 수 있도록 알고리즘·평가 하니스·문서를 준비. 알고리즘/파이프라인: - 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>
72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
from functools import lru_cache
|
|
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
|
|
|
|
# 서버 바인딩
|
|
host: str = "0.0.0.0"
|
|
port: int = 8000
|
|
log_level: str = "info" # debug / info / warning / error
|
|
reload: bool = False # 개발용 자동 재시작
|
|
root_path: str = "" # 리버스 프록시 sub-path (예: /plagiarism)
|
|
|
|
engine_version: str = "o2o-plagiarism-2.0.0-pdf-v1.2"
|
|
reference_corpus_dir: str = "./data/reference"
|
|
taxonomy_dir: str = "./data/taxonomy"
|
|
autobiography_patterns_path: str = "./data/autobiography/common_patterns.txt"
|
|
|
|
# PDF VII-4 권장: 정밀도 우선 보수적 임계값
|
|
similarity_threshold: float = 0.85
|
|
|
|
# KoSimCSE / KoSBERT (PDF VII-3 권장) - 한국어 오픈소스 임베딩
|
|
use_kosimcse: bool = True
|
|
kosimcse_model: str = "BM-K/KoSimCSE-roberta-multitask"
|
|
kosimcse_max_length: int = 512
|
|
|
|
# OpenAI (옵션 - 자체 모델 없을 때 폴백)
|
|
openai_api_key: str = ""
|
|
openai_extraction_model: str = "gpt-4o-mini"
|
|
openai_embedding_model: str = "text-embedding-3-small"
|
|
use_llm_extractor: bool = False
|
|
use_embedding_similarity: bool = False
|
|
|
|
# 삼중 유사도 가중치 (실측 기반)
|
|
weight_text_sim: float = 0.30
|
|
weight_lemma_sim: float = 0.45
|
|
weight_char_sim: float = 0.15
|
|
weight_motif_sim: float = 0.10
|
|
|
|
# PDF VII-3 캐스케이딩
|
|
use_lsh_filter: bool = True
|
|
lsh_threshold: float = 0.3 # 1차 필터는 느슨하게 (재현율 우선)
|
|
lsh_top_k: int = 50
|
|
|
|
# 2단계 고도화: 군집화 기반 부분 표절(요소 교체) 신호 (계획서 p.21)
|
|
use_clustering: bool = True
|
|
cluster_link_threshold: float = 0.35
|
|
|
|
# PDF VII-4 자서전 모드
|
|
autobiography_mode: bool = True
|
|
enable_entity_masking: bool = True
|
|
|
|
@property
|
|
def corpus_path(self) -> Path:
|
|
return Path(self.reference_corpus_dir).resolve()
|
|
|
|
@property
|
|
def taxonomy_path(self) -> Path:
|
|
return Path(self.taxonomy_dir).resolve()
|
|
|
|
@property
|
|
def has_openai(self) -> bool:
|
|
return bool(self.openai_api_key.strip())
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
return Settings()
|