Rifqi Hafizuddin
[NOTICKET] feat(knowledge_extraction): paid extraction stage + validate, diff, queue
ab5ea78
Raw
History Blame
1.55 kB
"""Detect contradictory definitions within one cluster.
Token overlap, not embeddings: cheaper, needs no model, and — the reason that
matters — **explainable to the reviewer who has to act on it**.
This module deliberately does NOT pick a winner. Two contradictory definitions
of the same term is a decision only the expert can make, and it is only
detectable at all because clustering puts all the evidence in one call.
"""
from __future__ import annotations
import re
from ..settings import CONFLICT_OVERLAP_THRESHOLD
def tokens(text: str) -> set[str]:
return {t for t in re.findall(r"\w+", (text or "").casefold()) if len(t) > 2}
def overlap(a: str, b: str) -> float:
ta, tb = tokens(a), tokens(b)
if not ta or not tb:
return 0.0
return len(ta & tb) / min(len(ta), len(tb))
def find_conflicts(definitions: list[str]) -> tuple[bool, list[str]]:
"""Returns (conflicting, variants). Definitions that share little vocabulary
are treated as competing rather than as rewordings of each other."""
present = [d.strip() for d in definitions if d and d.strip()]
unique: list[str] = []
for definition in present:
if not any(overlap(definition, seen) >= 0.9 for seen in unique):
unique.append(definition)
if len(unique) < 2:
return False, []
conflicting = any(
overlap(unique[i], unique[j]) < CONFLICT_OVERLAP_THRESHOLD
for i in range(len(unique))
for j in range(i + 1, len(unique))
)
return conflicting, unique if conflicting else []