- Unifica deps.py + checker.py + converter.py in extract.py (fronte PDF) - Sposta transforms/ in _pipeline/ (struttura piatta, no sottocartelle) - Aggiunge spinner animato (thread) durante conversione opendataloader-pdf - Aggiunge progresso step-by-step [i/37] per apply_transforms via callback - Mostra punteggio qualità (score/100 grade) a fine elaborazione - Fix: _DOTLEADER_RE spostata in _constants.py (non più definita inline) - Fix: report.py importa regex da _constants invece di ridefinirle - Fix: _t_remove_urls ora conta e ritorna le rimozioni effettive Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Missione
Convertire PDF digitali in Markdown perfetto per la vettorizzazione RAG, senza revisione manuale. L'output deve essere testo pulito, strutturato in sezioni semanticamente coerenti, privo di artefatti, pronto per chunking e indicizzazione in un vector store.
Non supportato: PDF scansionati (immagini), PDF protetti da password.
Regole invarianti
- Lingua: Rispondi sempre in italiano.
- Venv: Usa
.venv/bin/pythonosource .venv/bin/activate. Maipip/pythondi sistema. raw.mdimmutabile: Non modificare mairaw.md. La copia di lavoro è sempreclean.md.- Obiettivo zero revisioni: ogni miglioramento alla pipeline deve ridurre i casi in cui il
clean.mdrichiede correzioni manuali.
Setup
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Java 11+ richiesto da opendataloader-pdf
sudo apt install default-jdk # Ubuntu/Debian/WSL
java -version
Comandi
# Converti un PDF (posizionalo prima in sources/<nome>.pdf)
.venv/bin/python conversione/ --stem <nome>
# Tutti i PDF in sources/
.venv/bin/python conversione/
# Forza riesecuzione (sovrascrive clean.md esistente)
.venv/bin/python conversione/ --stem <nome> --force
# Validazione batch di tutti gli stem
.venv/bin/python conversione/ validate
# Validazione con dettaglio penalità
.venv/bin/python conversione/ validate <stem> --detail
# Rimuove l'output di uno stem
bash conversione/clear.sh <nome>
--stem = nome file PDF senza estensione.
Architettura
Il codice è organizzato in conversione/__main__.py (entry point) e il package conversione/_pipeline/ (logica modulare).
conversione/
├── __main__.py # Entry point unificato: convert + validate
├── clear.sh # Rimuove output di uno stem
└── _pipeline/
├── __init__.py # Re-export pubblico
├── extract.py # _check_deps() + validate_pdf() + convert_pdf()
├── runner.py # run() — orchestrazione 4 fasi
├── structure.py # analyze() + rilevamento lingua e struttura
├── report.py # build_report() → report.json
├── validator.py # validate() + _score() + _grade()
├── _apply.py # apply_transforms() — orchestratore in ordine semantico
├── _constants.py # Regex compilate e mappe statiche condivise
├── _encoding.py # Gruppo 1: PUA font Symbol, accenti LaTeX, simboli SI
├── _artifacts.py # Gruppo 2: immagini, BR, footnote, URL, righe ricorrenti, watermark
├── _headers.py # Gruppo 3: normalizzazione livelli, concat, bold, ALLCAPS
├── _structure.py # Gruppo 4: TOC, ALLCAPS→##, sezioni numerate, math, articoli
├── _text.py # Gruppo 5: merge paragrafi, whitespace, poesia, versi
├── _finish.py # Gruppo 6: header vuoti/garbage, formula-header, frontmatter
└── _helpers.py # Funzioni pure condivise (_sentence_case, _is_allcaps_line, ecc.)
__main__.py — entry point unificato
CLI con due modalità: conversione (default, --stem, --force) e validazione (subcommand validate, con stems opzionali e --detail). Aggiunge conversione/ a sys.path e delega a _pipeline. Uso: python conversione/ [--stem X] [--force] oppure python conversione/ validate [X] [--detail].
_pipeline/extract.py — fronte PDF
Raggruppa in un unico modulo le tre responsabilità legate al PDF: _check_deps() verifica che opendataloader-pdf e Java 11+ siano disponibili; validate_pdf(pdf_path) -> (bool, str) controlla esistenza, dimensione e presenza di testo digitale; convert_pdf(pdf_path, out_dir) -> Path invoca opendataloader-pdf con i parametri RAG-ottimali e restituisce il percorso del .md prodotto. Auto-rileva i PDF taggati (Word/InDesign) per attivare use_struct_tree.
_pipeline/_apply.py — cuore della pipeline
Contiene apply_transforms(text) -> (text, stats) che chiama ~35 trasformazioni atomiche (_t_*) in ordine semantico fisso — non modificare l'ordine senza capire le dipendenze tra gruppi. Ogni _t_* vive nel modulo del suo gruppo; le costanti regex compilate stanno in _constants.py.
Ordine logico dei gruppi:
- Encoding (
_encoding.py) — PUA font Symbol, accenti backtick LaTeX, moltiplicazione, micro - Pulizia artefatti (
_artifacts.py) — immagini,<br>, footnote superscript, URL, box symbol, righe ricorrenti, watermark - Struttura header (
_headers.py) — fix header+body concatenati, Capitolo inline, normalizzazione livelli numerati,####→###, bold, ALL-CAPS - Costruzione struttura (
_structure.py) — TOC rimosso, ALL-CAPS→##, sezioni numerate→###, ambienti matematici, articoli - Testo (
_text.py) — merge paragrafi spezzati, whitespace, blank lines, poesia, versi - Rifinitura (
_finish.py) — header vuoti, garbage header, merge titoli isolati, frontmatter
Flag automatico: se il testo contiene "Esercizi/Problems/Homework", _t_numbered_sections non converte - N. testo in header (sono numerazioni di esercizi, non titoli).
_pipeline/structure.py — analisi struttura
analyze(md_path) -> dict conta #/##/###, rileva lingua (it/en/fr/de/es), sceglie strategia_chunking:
| Strategia | Condizione |
|---|---|
h3_aware |
≥5 ### |
h2_paragraph_split |
≥3 ##, pochi ### |
paragraph |
struttura rada |
sliding_window |
testo piatto |
_pipeline/report.py — metriche qualità
build_report() genera report.json con: statistiche trasformazioni, struttura, distribuzione lunghezze sezioni (min/p25/mediana/p75/max), anomalie (bare headers, sezioni corte/lunghe), residui con esempi (backtick, dot-leader, URL, <br>, simboli encoding, formule inline, footnote, PUA).
validate.py — scoring
Assegna un voto 0–100 (A/B/C/D/F) leggendo report.json. Penalità principali:
| Problema | Penalità | Cap |
|---|---|---|
| Struttura assente (livello 0) | −40 | — |
| Struttura piatta (livello 1) | −15 | — |
| Backtick residui | −2/cad | −20 |
| Caratteri PUA font Symbol | −2/cad | −20 |
| Dot-leader | −5/cad | −10 |
| URL/watermark | −5/cad | −15 |
<br> inline |
−2/cad | −15 |
| Bare headers | −3/cad | −15 |
Cosa rende un Markdown perfetto per la vettorizzazione
- Struttura semantica: header Markdown = confini naturali dei chunk; ogni sezione è un'unità concettuale.
- Testo pulito: nessun backtick, dot-leader, footnote superscript, carattere PUA,
<br>. - Paragrafi interi: nessuna frase troncata da salto pagina PDF.
- Formule e simboli: lettere greche e operatori in Unicode standard, non in font-encoding privato.
- Nessun rumore strutturale: TOC, header/footer ripetuti, URL, watermark — tutto rimosso.
- Gerarchia corretta: h1/h2/h3 riflettono la struttura logica, non il layout tipografico.
Linee guida per migliorare la pipeline
Quando si aggiunge una trasformazione in apply_transforms():
- Ogni
_t_*deve restituire(testo, n_modifiche)— il contatore alimentareport.json. - Implementare la funzione nel modulo del gruppo corretto (
_encoding.py,_artifacts.py, ecc.), importarla in_apply.pye inserire la coppia("stat_key", _t_nuova)nella lista_transformsnel punto logicamente corretto. - Compilare i pattern regex in
_constants.pycome costanti di modulo, mai dentro la funzione. - Testare con
.venv/bin/python conversione/ --stem <stem> --forcee confrontarereport.json. - Un nuovo tipo di artefatto: prima aggiungerlo come residuo in
report.py(funzione_scan), poi implementare la_t_*che lo rimuove. - I residui in
report.pyusano_MATH_SYMBOLS_RE,_EXERCISE_TRIGGER_REe_MATH_HDR_REdatransforms._constants— non ridefinirli localmente.
Skills custom
/prepare-md <path|stem>— correggeclean.mdquando la pipeline non basta: sillabazione, artefatti residui, header malformati, gerarchia incoerente.