OpenSearch를 이용한 자체 호스팅 표절 탐지

발행: (2026년 1월 31일 오후 02:26 GMT+9)
1 min read
원문: Dev.to

Source: Dev.to

두 단계 접근법

more_like_this 로 후보 찾기

search = cls.search().filter(
    "nested", path="answers",
    query={"term": {"answers.question_id": str(question_id)}}
)
search = search.exclude("term", user_id=user_id)
search = search.query(
    "nested",
    path="answers",
    query={
        "more_like_this": {
            "fields": ["answers.answer"],
            "like": text,
            "min_term_freq": 1,
            "minimum_should_match": "1%",
        }
    },
)
response = search.execute()

문자 n‑gram 으로 재정렬

def normalize(t):
    return re.sub(r"\s+", "", t.strip())

def char_ngrams(t, n=3):
    return set(t[i:i+n] for i in range(len(t)-n+1))

norm_text = normalize(text)
text_ngrams = char_ngrams(norm_text)

for hit in response.hits:
    norm_answer = normalize(hit.answer)
    answer_ngrams = char_ngrams(norm_answer)

    intersection = len(text_ngrams & answer_ngrams)
    union = len(text_ngrams | answer_ngrams)
    ratio = int((intersection / union) * 100)

    if ratio >= 60:
        # flag as similar

꽤 괜찮게 동작합니다—시도와 오류를 통해 약 60 % 유사도 임계값을 찾았습니다.
셀프‑호스팅, 간단한 연산, 그리고 기존 검색 인프라를 재사용합니다.

전체 구현

https://github.com/cobel1024/minima

Back to Blog

관련 글

더 보기 »