Production_Rag / duplicate_detector.py
TharaKavin's picture
Upload 17 files
6f94597 verified
Raw
History Blame Contribute Delete
1.94 kB
from typing import List, Dict, Any, Set, Optional
from datasketch import MinHash, MinHashLSH
class DuplicateDetector:
def __init__(self, threshold: float = 0.92, num_perm: int = 128, ngram_size: int = 5):
self.threshold = threshold
self.num_perm = num_perm
self.ngram_size = ngram_size
self.lsh = MinHashLSH(threshold=threshold, num_perm=num_perm)
self.seen_ids: Set[str] = set()
def _text_to_shingles(self, text: str) -> Set[str]:
tokens = text.lower().split()
shingles: Set[str] = set()
n = self.ngram_size
if len(tokens) < n:
shingles.add(" ".join(tokens))
return shingles
for i in range(len(tokens) - n + 1):
shingles.add(" ".join(tokens[i : i + n]))
return shingles
def _compute_minhash(self, text: str) -> MinHash:
shingles = self._text_to_shingles(text)
m = MinHash(num_perm=self.num_perm)
for s in shingles:
m.update(s.encode("utf-8"))
return m
def is_duplicate(self, doc_id: str, text: str) -> bool:
if doc_id in self.seen_ids:
return True
m = self._compute_minhash(text)
candidates = self.lsh.query(m)
if candidates:
return True
self.lsh.insert(doc_id, m)
self.seen_ids.add(doc_id)
return False
def filter_duplicates(self, documents: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
unique: List[Dict[str, Any]] = []
for doc in documents:
doc_id = doc.get("chunk_id") or doc.get("node_id") or ""
text = doc.get("text", "")
if not text:
continue
if not self.is_duplicate(doc_id, text):
unique.append(doc)
return unique
def reset(self):
self.lsh = MinHashLSH(threshold=self.threshold, num_perm=self.num_perm)
self.seen_ids.clear()