docs-qa-backend / app /chunking.py
capcut8128's picture
Upload 12 files
0a19322 verified
Raw History Blame Contribute Delete
1.94 kB
"""Clean page text and split it into sentence-aware, overlapping chunks."""
import re
_SENT_SPLIT = re.compile(r"(?<=[.!?\u0964])\s+") # \u0964 = Hindi danda
def paragraphs(text: str) -> list[str]:
text = text.replace("\r", "")
text = re.sub(r"-\n(?=[a-z])", "", text) # join words hyphenated across lines
text = re.sub(r"[ \t\u00a0]+", " ", text)
paras = re.split(r"\n\s*\n", text)
paras = [re.sub(r"\s*\n\s*", " ", p).strip() for p in paras]
return [p for p in paras if p]
def _split_units(par: str, size: int) -> list[str]:
units: list[str] = []
for sent in _SENT_SPLIT.split(par):
sent = sent.strip()
while len(sent) > size: # one huge "sentence" (tables, code): cut at a space
cut = sent.rfind(" ", 0, size)
cut = cut if cut > size * 0.5 else size
units.append(sent[:cut].strip())
sent = sent[cut:].strip()
if sent:
units.append(sent)
return units
def chunk_text(text: str, size: int, overlap: int) -> list[str]:
units: list[str] = []
for par in paragraphs(text):
units.extend(_split_units(par, size))
chunks: list[str] = []
cur: list[str] = []
cur_len = 0
for u in units:
add = len(u) + (1 if cur else 0)
if cur and cur_len + add > size:
chunks.append(" ".join(cur))
keep: list[str] = [] # carry the last sentences over as overlap
keep_len = 0
for prev in reversed(cur):
if keep_len + len(prev) + 1 > overlap:
break
keep.insert(0, prev)
keep_len += len(prev) + 1
cur = keep
cur_len = sum(len(x) for x in cur) + max(0, len(cur) - 1)
add = len(u) + (1 if cur else 0)
cur.append(u)
cur_len += add
if cur:
chunks.append(" ".join(cur))
return [c for c in chunks if c.strip()]