fix(verify): PUNCT_END generico e frasi spezzate come warning
PUNCT_END esteso con terminatori comuni in documenti tecnici: - $ e } per formule LaTeX inline e blocchi - > per tag HTML (</table>, </td>, ecc.) - \\ per line break LaTeX - · (punto centrato, U+00B7) per notazione matematica Caratteri unicode scritti con chr() per evitare SyntaxError Python 3.12+ con curly quotes nel sorgente. Frasi spezzate spostate da blockers a warnings: il chunker le risolve automaticamente con merge_broken_sentences; i casi residui sono perlopiù falsi positivi (frontespizi, entità proprie senza punto finale). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+28
-16
@@ -32,13 +32,27 @@ import config as cfg
|
||||
MIN_CHARS = cfg.MIN_CHARS
|
||||
MAX_CHARS = cfg.MAX_CHARS
|
||||
|
||||
_PUNCT_CLS = (
|
||||
"[.!?"
|
||||
+ chr(0xBB) + ")\\]"
|
||||
+ chr(0x2018) + chr(0x2019)
|
||||
+ chr(0x201C) + chr(0x201D)
|
||||
+ "\"'"
|
||||
+ chr(0x2014) + chr(0x2013) + chr(0x2026)
|
||||
+ chr(0xB7) # punto centrato LaTeX
|
||||
+ "]$"
|
||||
)
|
||||
PUNCT_END = re.compile(
|
||||
r"[.!?\xbb)\]'’\"“”‘—–…]$"
|
||||
r"|/$" # URL che finisce con /
|
||||
r"|\|$" # riga di tabella Markdown
|
||||
r"|;$" # fine clausola legale
|
||||
r"|:$" # introduzione a lista o formula
|
||||
r"|\d[\d.,/]*$" # numero, anno, versione, riferimento normativo
|
||||
_PUNCT_CLS
|
||||
+ r"|/$"
|
||||
+ r"|\|$"
|
||||
+ r"|;$"
|
||||
+ r"|:$"
|
||||
+ r"|\d[\d.,/]*$"
|
||||
+ r"|\$$"
|
||||
+ r"|\}$"
|
||||
+ r"|>$"
|
||||
+ r"|\\\\$"
|
||||
)
|
||||
_HEX_END = re.compile(r"[0-9a-fA-F]{8,}$")
|
||||
_URL_TAIL = re.compile(r"(https?://|www\.)\S+(\s+\S+){0,3}$")
|
||||
@@ -312,13 +326,13 @@ def verify_stem(stem: str, project_root: Path, min_chars: int, max_chars: int) -
|
||||
print(f" → Causa probabile: sezioni senza testo nel clean.md")
|
||||
|
||||
if incomplete:
|
||||
print(f"\n 🔴 {len(incomplete)} chunk con FRASE SPEZZATA:")
|
||||
print(f"\n 🟡 {len(incomplete)} chunk con FRASE SPEZZATA (warning):")
|
||||
for c in incomplete[:5]:
|
||||
last_line = c.get("text", "").rstrip().split("\n")[-1][-80:]
|
||||
print(f" [{c.get('chunk_id', '?')}] ...{last_line!r}")
|
||||
if len(incomplete) > 5:
|
||||
print(f" ... e altri {len(incomplete) - 5}")
|
||||
print(f" → Soluzione: python chunks/fix_chunks.py --stem {stem}")
|
||||
print(f" → Soluzione: correggi il sorgente .md e rigenera con chunker.py --force")
|
||||
|
||||
# ── Warnings ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -350,12 +364,12 @@ def verify_stem(stem: str, project_root: Path, min_chars: int, max_chars: int) -
|
||||
print(f" [{e['chunk_id']}] ≡ [{e['duplicate_of']}] «{e['last_text'][:60]}»")
|
||||
if len(duplicates) > 5:
|
||||
print(f" ... e altri {len(duplicates) - 5}")
|
||||
print(f" → Causa probabile: fix_chunks merge multipli o sezioni ripetute")
|
||||
print(f" → Causa probabile: sezioni ripetute nel sorgente .md")
|
||||
|
||||
# ── Report.json ───────────────────────────────────────────────────────────
|
||||
|
||||
blockers = empty_chunks + no_prefix + malformed_prefix + body_empty + incomplete
|
||||
warnings = too_short + too_long + incomplete_math + broken_tables
|
||||
blockers = empty_chunks + no_prefix + malformed_prefix + body_empty
|
||||
warnings = too_short + too_long + incomplete + incomplete_math + broken_tables
|
||||
|
||||
verdict = "blocked" if blockers else ("warnings_only" if (warnings or duplicates) else "ok")
|
||||
|
||||
@@ -418,18 +432,16 @@ def verify_stem(stem: str, project_root: Path, min_chars: int, max_chars: int) -
|
||||
print(f" python ingestion/ingest.py --stem {stem}")
|
||||
if too_short or too_long:
|
||||
print()
|
||||
print(f" Per ottimizzare prima:")
|
||||
print(f" python chunks/fix_chunks.py --stem {stem} --dry-run")
|
||||
print(f" python chunks/fix_chunks.py --stem {stem}")
|
||||
print(f" Per ottimizzare: correggi il sorgente .md e rigenera con --force")
|
||||
|
||||
else:
|
||||
print(f" 🔴 {len(blockers)} problemi bloccanti — correggi prima di procedere:")
|
||||
if empty_chunks or body_empty:
|
||||
print(f" • chunk vuoti/senza corpo → controlla sources/{stem}/auto/{stem}_clean.md")
|
||||
if no_prefix or malformed_prefix:
|
||||
print(f" • prefisso mancante/malformato → controlla gli heading in {stem}_clean.md")
|
||||
print(f" • prefisso mancante/malformato → controlla gli heading in sources/{stem}.md")
|
||||
if incomplete:
|
||||
print(f" • frasi spezzate → python chunks/fix_chunks.py --stem {stem}")
|
||||
print(f" • frasi spezzate → correggi il sorgente e rigenera con --force")
|
||||
print()
|
||||
print(f" Dopo le correzioni:")
|
||||
print(f" python chunks/chunker.py --stem {stem} --force")
|
||||
|
||||
Reference in New Issue
Block a user