ARslan-Ahamd's picture
Deploy from GitHub commit 9c1d82a
465b477 verified
Raw History Blame Contribute Delete
2.32 kB
"""Anchoring model-produced quotes to exact character offsets in source chunks.
A quote is accepted only if, after light normalisation (Unicode NFKC, whitespace
collapse, typographic quotes/dashes folded, case kept), it occurs verbatim in the
chunk. Quotes containing an ellipsis are accepted when every fragment of at least
three words occurs in order; they are flagged ``elided``. There is no fuzzy matching:
a paraphrase is a fabricated quote.
"""
from __future__ import annotations
import re
import unicodedata
_FOLD = str.maketrans(
{
"‘": "'",
"’": "'",
"“": '"',
"”": '"',
"–": "-",
"—": "-",
"−": "-",
" ": " ",
}
)
_ELLIPSIS = re.compile(r"\s*(?:\.\.\.|…|\[\.\.\.\])\s*")
def _normalise_with_map(text: str) -> tuple[str, list[int]]:
"""Normalised text plus, for each normalised char, its index in the original."""
out: list[str] = []
idx: list[int] = []
prev_space = True
for i, ch in enumerate(text):
for c in unicodedata.normalize("NFKC", ch).translate(_FOLD):
if c.isspace():
if prev_space:
continue
c = " "
prev_space = True
else:
prev_space = False
out.append(c)
idx.append(i)
while out and out[-1] == " ":
out.pop()
idx.pop()
return "".join(out), idx
def normalise(text: str) -> str:
return _normalise_with_map(text)[0]
def locate(quote: str, source: str) -> tuple[int, int, bool] | None:
"""Return (start, end, elided) offsets of ``quote`` in ``source`` or None."""
q = normalise(quote).strip(" \"'")
if len(q) < 8:
return None
norm, back = _normalise_with_map(source)
pos = norm.find(q)
if pos >= 0:
return back[pos], back[pos + len(q) - 1] + 1, False
fragments = [f.strip(" \"'") for f in _ELLIPSIS.split(q) if f.strip(" \"'")]
if len(fragments) < 2 or any(len(f.split()) < 3 for f in fragments):
return None
cursor, start = 0, None
for f in fragments:
p = norm.find(f, cursor)
if p < 0:
return None
if start is None:
start = p
cursor = p + len(f)
return back[start], back[cursor - 1] + 1, True