# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. --- ## Lingua e comportamento - **Lingua:** Rispondi sempre in italiano. - **Prima di eseguire qualsiasi istruzione**, esponi: 1. Come intendi procedere (approccio, file coinvolti, stadi modificati). 2. Se l'istruzione ha problemi concettuali — e perché — con una proposta alternativa. 3. Aspetta conferma o correzione prima di toccare il codice, salvo che l'istruzione sia banale (rinomina, formattazione). Esempio di risposta corretta a "aggiungi OCR al parser": > "L'OCR contraddice il vincolo 'Niente LLM né OCR nella pipeline' di questo progetto, che richiede output deterministico e riproducibile. Se il problema sono i PDF scansionati, l'approccio corretto è rilevare il caso e restituire un errore esplicito. Procedo in questo senso?" --- ## Missione Ricostruire la struttura logica di PDF digitali e serializzarla in Markdown **stabile e valido per la vettorizzazione RAG**, senza LLM né OCR. ``` PDF → Structured Document Tree → Markdown → Chunks → ChromaDB → RAG ``` **Non supportato:** PDF scansionati (immagini), PDF protetti da password. --- ## Regole invarianti - **Venv:** Usa `.venv/bin/python`. Mai `pip`/`python` di sistema. - **`raw.md` immutabile:** Non modificare mai `raw.md`. La copia di lavoro è sempre `clean.md`. - **Niente LLM nella pipeline:** tutta la logica deve essere rule-based e riproducibile. - **Markdown generato solo dall'albero:** Mai da `Block` direttamente — sempre da `Section`. --- ## Comandi ```bash # Setup python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt # Converti un PDF (posizionalo prima in sources/.pdf) .venv/bin/python conversione/ --stem .venv/bin/python conversione/ --stem --force # sovrascrive output # Chunking .venv/bin/python chunks/chunker.py --stem # Vettorizzazione (richiede Ollama attivo) .venv/bin/python ingestion/ingest.py --stem # RAG interattivo .venv/bin/python rag.py --stem .venv/bin/python retrieve.py --stem # retrieval puro, senza LLM # Validazione .venv/bin/python conversione/ validate .venv/bin/python conversione/ validate --detail # Test .venv/bin/python -m pytest tests/ .venv/bin/python -m pytest tests/unit/test_stage4.py # singolo file # Pulizia output bash conversione/clear.sh ``` --- ## Architettura ### Pipeline di conversione — `conversione/_pipeline/` 9 stadi in sequenza, ognuno riceve l'output tipizzato del precedente: | Stage | File | Responsabilità | |-------|------|----------------| | 1 | `stage1_metadata.py` | Estrazione span da PyMuPDF (`get_text("dict")`), TOC, dimensioni pagina | | 2 | `stage2_layout.py` | Analisi layout, reading order, tipo blocco | | 3 | `stage3_font.py` | Font profile per documento (body size, cluster, header sizes) | | 4 | `stage4_headers.py` | Classificazione header_candidate (font+bold+numerazione+spacing) | | 5 | `stage5_hierarchy.py` | Inferenza livello H1/H2/H3 (priorità: numerazione > TOC > font size) | | 6 | `stage6_tree.py` | Costruzione albero `Section` con parent-child | | 7 | `stage7_markdown.py` | Serializzazione albero → Markdown raw | | 8 | `stage8_normalize.py` | Riparazione gerarchia (level jump, header vuoti, duplicati) | | 9 | `stage9_validate.py` | Validazione struttura finale | Orchestrazione: `runner.py`. Entry point: `conversione/__main__.py`. ### Modello dati — `conversione/_pipeline/models.py` ```python Block # span estratto: text, page, bbox, font_size, is_bold, block_type, level Section # nodo albero: title, level, content: list[Block], children: list[Section] FontProfile # body_size, cluster_map, header_sizes ``` ### Pipeline RAG — file radice | File | Responsabilità | |------|---------------| | `chunks/chunker.py` | Chunking adattivo da `clean.md` + `structure_profile.json` | | `chunks/config.py` | Parametri chunking (TARGET_CHARS, OVERLAP, STRATEGY_OVERRIDES) | | `ingestion/ingest.py` | Embedding Ollama → ChromaDB | | `retrieve.py` | Retrieval puro (debug retrieval senza LLM) | | `rag.py` | Loop RAG interattivo (retrieval + generazione Ollama) | | `config.py` | Parametri globali RAG (TOP_K, TEMPERATURE, OLLAMA_MODEL, EMBED_MODEL) | ### Output per stem ``` conversione//raw.md # immutabile, output stage 7 conversione//clean.md # con frontmatter YAML, output stage 8-9 conversione//structure_profile.json conversione//report.json chunks//chunks.json chroma_db// # collection ChromaDB ``` --- ## Linee guida per la pipeline - Le regex per header numbering vanno in `_constants.py`, mai inline. - PyMuPDF è il parser primario. pdfplumber solo per tabelle complesse. - Ogni stage deve essere indipendentemente testabile. - Prima di aggiungere un nuovo segnale a Stage 4, validarlo su almeno 3 PDF. ### Test richiesti | Categoria | Validazione attesa | |-----------|-------------------| | Header numerati | gerarchia corretta, no level skip | | TOC presente | markdown allineato al TOC del PDF | | Font inconsistenti | body non classificato come header | | Header multi-riga | header mergiati, markdown valido | | Tabelle | markdown table con colonne preservate | | Gerarchia rotta artificiale | riparazione automatica | --- ## Skills custom - `/prepare-md ` — corregge `clean.md` quando la pipeline non basta: sillabazione, artefatti, header malformati, gerarchia incoerente. - `/post-chunk` — verifica e perfeziona i chunk prima della vettorizzazione.