From 98653464dde376c5ce2ac72d9bf02f1abdd6c22e Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Wed, 20 May 2026 16:08:00 +0200 Subject: [PATCH] docs: README dettagliato MinerU + CLAUDE.md aggiornato per pipeline Stage 1+2 README.md: sezione MinerU espansa con requisiti di sistema, installazione (pip/conda/Docker), CLI completo con tutti i flag, tabella comparativa backend (pipeline/hybrid-auto-engine/vlm-auto-engine), configurazione avanzata, struttura output e limitazioni note. CLAUDE.md: aggiornato diagramma pipeline, input RICHIESTO/RACCOMANDATO, comandi con --force e --skip-optimize, architettura chunker/md_optimizer. Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 41 +++-- README.md | 481 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 335 insertions(+), 187 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c24148b..56f5b42 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,11 +19,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Pipeline RAG su documenti accademici. La conversione PDF → Markdown è delegata a **MinerU** (tool esterno). Questo repository si occupa solo di: pulizia Markdown, chunking, vettorizzazione e retrieval/generazione. ``` -MinerU (esterno) → sources//auto/.md +MinerU (esterno) → sources//auto/ ↓ - /prepare-md (pulizia) - ↓ - chunker.py (chunking adattivo) + chunker.py (Stage 1: _clean.md + Stage 2: chunks.json) ↓ ingest.py (embedding → ChromaDB) ↓ @@ -36,7 +34,7 @@ MinerU (esterno) → sources//auto/.md - **Venv:** Usa `.venv/bin/python`. Mai `pip`/`python` di sistema. - **Niente LLM nella pipeline:** chunking e pulizia devono essere rule-based e riproducibili. -- **Input immutabile:** Non modificare mai `sources//auto/.md` direttamente — usare `/prepare-md` che lavora su una copia. +- **Input immutabile:** Non modificare mai i file originali in `sources//auto/`. Il `chunker.py` scrive solo `_clean.md` (prodotto derivato) nella stessa cartella e `chunks.json` in `chunks//`. --- @@ -45,9 +43,10 @@ MinerU (esterno) → sources//auto/.md MinerU produce una cartella per ogni documento. Posizionarla in `sources/`: ``` -sources//auto/.md ← Markdown principale (input pipeline) -sources//auto/_content_list_v2.json ← struttura ricca (chunk, bbox, tipo) -sources//auto/_middle.json ← dati intermedi di layout +sources//auto/_content_list_v2.json ← struttura ricca (tipo, livello, bbox) [RICHIESTO] +sources//auto/_model.json ← label di layout (doc_title, abstract…) [RACCOMANDATO] +sources//auto/.md ← Markdown grezzo (non usato dalla pipeline) +sources//auto/_middle.json ← dati intermedi (non usato) sources//auto/images/ ← immagini estratte ``` @@ -61,9 +60,18 @@ sources//auto/images/ ← immagini estratte # Setup python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt -# Chunking (legge sources//auto/.md) +# Chunking unificato: Stage 1 (_clean.md) + Stage 2 (chunks.json) .venv/bin/python chunks/chunker.py --stem -.venv/bin/python chunks/chunker.py # tutti gli stem +.venv/bin/python chunks/chunker.py # tutti gli stem in sources/ +.venv/bin/python chunks/chunker.py --stem --force # rigenera tutto +.venv/bin/python chunks/chunker.py --stem --skip-optimize # salta Stage 1 + +# Solo Stage 1 (se serve rigenerare solo il _clean.md) +.venv/bin/python chunks/md_optimizer.py --stem --force + +# Verifica e correzione chunk +.venv/bin/python chunks/verify_chunks.py --stem +.venv/bin/python chunks/fix_chunks.py --stem # Vettorizzazione (richiede Ollama attivo) .venv/bin/python ingestion/ingest.py --stem @@ -71,7 +79,7 @@ python -m venv .venv && source .venv/bin/activate && pip install -r requirements # RAG interattivo .venv/bin/python rag.py --stem -.venv/bin/python retrieve.py --stem # retrieval puro, senza LLM +.venv/bin/python retrieve.py --stem # retrieval puro, senza LLM ``` --- @@ -82,10 +90,13 @@ python -m venv .venv && source .venv/bin/activate && pip install -r requirements | File | Responsabilità | |------|---------------| -| `chunker.py` | Chunking adattivo del Markdown; legge `structure_profile.json` per scegliere la strategia | -| `config.py` | Parametri: `TARGET_CHARS`, `OVERLAP_SENTENCES`, `CHUNK_TOLERANCE`, `STRATEGY_OVERRIDES` | -| `verify_chunks.py` | Verifica qualità chunk (copertura, lunghezze, overlap) | -| `fix_chunks.py` | Correzioni post-chunking | +| `chunker.py` | Entry point unificato: chiama `md_optimizer` (Stage 1) poi esegue il chunking (Stage 2) | +| `md_optimizer.py` | Modulo Stage 1: `_content_list_v2.json` + `_model.json` → `_clean.md` | +| `config.py` | Tutti i parametri: `MAX_CHARS`, `MIN_CHARS`, `OVERLAP_SENTENCES`, `FRONTMATTER_HEADINGS`, `SOMMARIO_PATTERNS`, label sets model.json | +| `verify_chunks.py` | Verifica qualità chunk (lunghezze, frasi spezzate, prefissi) | +| `fix_chunks.py` | Correzioni post-chunking (merge incompleti, split lunghi) | + +`md_optimizer.py` è generico rispetto al documento: usa le strutture comuni di tutti gli output MinerU (`_content_list_v2.json` e `_model.json`) senza dipendere da pattern testuali lingua-specifici. I parametri documento-specifici (es. `FRONTMATTER_HEADINGS` per documenti italiani) sono in `config.py`. Output: `chunks//chunks.json`, `chunks//meta.json`, `chunks//report.json` diff --git a/README.md b/README.md index 2bc00e0..a4d8b26 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,176 @@ -# PDF → Chunk RAG-ready +# RAG su documenti accademici -Converte PDF digitali in chunk semantici pronti per la vettorizzazione RAG, -senza LLM né OCR. +Pipeline completa per trasformare PDF accademici in un sistema RAG interrogabile in linguaggio naturale. -**Pipeline:** PDF → Markdown strutturato → chunk semantici → embedding ChromaDB -**Stack:** Python · PyMuPDF · pdfplumber -**Non supportati:** PDF scansionati (solo immagini), PDF protetti da password. +**Stack:** Python · MinerU · ChromaDB · Ollama +**Chunking:** rule-based, deterministico, senza LLM +**Embedding + Generazione:** Ollama (locale) + +--- + +## Prerequisiti + +### 1. MinerU — conversione PDF → Markdown strutturato + +MinerU è il tool esterno che converte i PDF in Markdown + metadati strutturati. +Repository: [https://github.com/opendatalab/MinerU](https://github.com/opendatalab/MinerU) + +#### Requisiti di sistema + +| Risorsa | Minimo | Raccomandato | +|---------|--------|--------------| +| Python | 3.10–3.13 | 3.11 | +| RAM | 16 GB | 32 GB+ | +| Disco | 20 GB (modelli inclusi) | 40 GB+ | +| GPU | opzionale | 4–8 GB VRAM (CUDA) | +| OS | Linux, macOS, Windows | Linux / WSL2 per Docker | + +#### Installazione + +**pip (raccomandato):** + +```bash +pip install mineru[all] +# oppure con uv (più veloce): +uv pip install -U "mineru[all]" +``` + +**conda:** + +```bash +conda create -n mineru python=3.11 +conda activate mineru +pip install mineru[all] +``` + +**Docker (Linux / WSL2 only):** + +```bash +# CPU +docker run --rm -v /percorso/locale:/data opendatalab/mineru mineru -p /data/doc.pdf -o /data/output + +# GPU (richiede nvidia-container-toolkit) +docker run --rm --gpus all -v /percorso/locale:/data opendatalab/mineru:cuda mineru -p /data/doc.pdf -o /data/output +``` + +Al primo avvio MinerU scarica automaticamente i modelli (~15 GB). Per forzare il download manuale: + +```bash +mineru-models-download +``` + +#### Uso — CLI + +```bash +mineru -p -o [opzioni] +``` + +| Flag | Descrizione | Default | +|------|-------------|---------| +| `-p` | Percorso PDF, cartella di PDF, o URL | — | +| `-o` | Cartella di output | — | +| `-b` | Backend di conversione (vedi sotto) | `pipeline` | +| `-m` | Metodo di estrazione: `auto`, `txt`, `ocr` | `auto` | +| `-l` | Lingua per OCR (es. `it`, `en`, `zh`) | `en` | +| `-s` | Pagina iniziale (0-based) | 0 | +| `-e` | Pagina finale (0-based, inclusa) | ultima | +| `--formula` | Attiva/disattiva riconoscimento formule | config | +| `--table` | Attiva/disattiva riconoscimento tabelle | config | + +**Esempio tipico:** + +```bash +mineru -p articolo.pdf -o sources/articolo/ +# Output in sources/articolo/auto/ +``` + +Per estrarre solo alcune pagine: + +```bash +mineru -p documento.pdf -o sources/documento/ -s 10 -e 50 +``` + +#### Backend di conversione + +| Backend | Descrizione | Accuratezza | GPU richiesta | +|---------|-------------|-------------|---------------| +| `pipeline` | CPU-only, modelli leggeri | ~86% | No | +| `hybrid-auto-engine` | Combina pipeline + VLM selettivo | ~95%+ | Raccomandato | +| `vlm-auto-engine` | VLM completo su tutte le pagine | massima | Sì | +| `pipeline-http` / `vlm-http` | Come sopra ma via API remota | — | Remota | + +```bash +# Raccomandato se si ha una GPU con ≥ 4 GB VRAM +mineru -p doc.pdf -o output/ -b hybrid-auto-engine + +# Solo CPU +mineru -p doc.pdf -o output/ -b pipeline +``` + +#### Configurazione avanzata + +File di configurazione utente: `~/mineru.json` + +Variabili d'ambiente principali: + +| Variabile | Valori | Effetto | +|-----------|--------|---------| +| `MINERU_FORMULA_ENABLE` | `0` / `1` | Abilita/disabilita OCR formule matematiche | +| `MINERU_TABLE_ENABLE` | `0` / `1` | Abilita/disabilita riconoscimento tabelle | +| `MINERU_DEVICE` | `cpu`, `cuda`, `mps` | Forza il dispositivo di inferenza | + +#### Output di MinerU + +MinerU produce per ogni PDF una cartella con questa struttura: + +``` +/ +└── auto/ + ├── .md ← Markdown grezzo (non usato dalla pipeline) + ├── _content_list_v2.json ← struttura ricca: tipo, livello, bbox [RICHIESTO] + ├── _model.json ← label di layout: doc_title, abstract… [RACCOMANDATO] + ├── _middle.json ← dati intermedi (non usato) + ├── _content_list.json ← formato v1 flat (non usato) + ├── _layout.pdf ← PDF annotato con i bounding box + ├── _span.pdf ← PDF con span di testo evidenziati + └── images/ ← immagini estratte +``` + +`` è il nome del documento, usato come identificatore in tutta la pipeline. + +I file usati dalla pipeline di questo repository sono: + +- **`_content_list_v2.json`** ← struttura ad albero: ogni blocco ha `type` (title/paragraph/table/list/image), `level` (per i titoli: 1=capitolo, 2=sezione), `content` con il testo, e `bbox` per la posizione sulla pagina. +- **`_model.json`** ← label semantiche per bounding box: `doc_title`, `paragraph_title`, `abstract`, `header`, `number`, `text`, `aside_text`… Usato per arricchire la classificazione del testo (es. riconoscere SOMMARIO interni, prefissi di capitolo). + +#### Limitazioni note di MinerU + +- **Testo verticale** (CJK ruotato, riviste asiatiche): qualità ridotta. +- **Testo scritto a mano**: accuratezza molto bassa. +- **Fumetti e album d'arte**: non supportati. +- **Blocchi di codice**: non sempre preservati correttamente (indentazione può essere persa). +- **PDF scansionati senza OCR**: richiede backend con OCR attivo (`-m ocr`). +- **Formule matematiche complesse**: dipendono dalla qualità del rendering PDF originale. + +### 2. Ollama — embedding e generazione + +Scarica e avvia [Ollama](https://ollama.com), poi installa i modelli: + +```bash +ollama pull nomic-embed-text # embedding (obbligatorio) +ollama pull qwen3.5:4b # generazione LLM (o altro modello) +``` --- ## Setup ```bash +git clone +cd rag + python -m venv .venv -source .venv/bin/activate +source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt ``` @@ -21,226 +178,206 @@ pip install -r requirements.txt ## Flusso completo -### 1. Posiziona il PDF - ``` -sources/.pdf +PDF + │ + ▼ (MinerU — esterno) +sources//auto/ + │ + ▼ python chunks/chunker.py --stem + │ Stage 1: _content_list_v2.json + _model.json → _clean.md + │ Stage 2: _clean.md → chunks//chunks.json + │ + ▼ python chunks/verify_chunks.py --stem + │ Verifica qualità chunk + │ + ▼ python chunks/fix_chunks.py --stem [se necessario] + │ Correzioni automatiche + │ + ▼ python ingestion/ingest.py --stem + │ Embedding → ChromaDB + │ + ▼ python rag.py --stem + Interrogazione in linguaggio naturale ``` -### 2. Converti il PDF in Markdown +--- + +### Passo 1 — Converti il PDF con MinerU + +Usa MinerU per convertire il PDF e posiziona la cartella di output in `sources/`: + +``` +sources/ +└── / + └── auto/ + ├── _content_list_v2.json + ├── _model.json + └── ... +``` + +### Passo 2 — Chunking (Stage 1 + Stage 2) + +Un singolo comando esegue entrambe le fasi: ```bash # Singolo documento -.venv/bin/python conversione/ --stem +.venv/bin/python chunks/chunker.py --stem -# Tutti i PDF in sources/ -.venv/bin/python conversione/ +# Tutti i documenti in sources/ +.venv/bin/python chunks/chunker.py -# Forza riesecuzione (sovrascrive output esistente) -.venv/bin/python conversione/ --stem --force +# Rigenera tutto da zero +.venv/bin/python chunks/chunker.py --stem --force + +# Salta Stage 1 (usa il _clean.md già presente) +.venv/bin/python chunks/chunker.py --stem --skip-optimize ``` -Output in `conversione//`: +**Stage 1 — Ottimizzazione Markdown** (`md_optimizer.py` interno): +- Legge `_content_list_v2.json` e `_model.json` +- Riconosce la gerarchia heading (H1 = capitolo, H2 = sezione, H3 = sottosezione) +- Fonde titoli di capitolo multipli: `CAPITOLO 2` + `Il titolo` → `# CAPITOLO 2 — Il titolo` +- Rimuove TOC, frontespizio, copyright, indici e sommari interni +- Produce `sources//auto/_clean.md` -| File | Descrizione | -|------|-------------| -| `raw.md` | Markdown grezzo — **non modificare** | -| `clean.md` | Markdown pulito — input per il chunker | -| `structure_profile.json` | Struttura rilevata e strategia di chunking | -| `report.json` | Metriche di qualità della conversione | +**Stage 2 — Chunking semantico**: +- Un chunk per paragrafo — mai due paragrafi nello stesso chunk +- Split a confine di frase se il paragrafo supera `MAX_CHARS` (default 1200 chars) +- Overlap di 1 frase tra chunk consecutivi per continuità contestuale +- Tabelle e liste sono blocchi atomici (non vengono mai spezzati) +- Ogni chunk include un prefisso `[Sezione > Titolo]` per il retrieval -### 3. Verifica la qualità del Markdown (opzionale) +Output in `chunks//`: + +| File | Contenuto | +|------|-----------| +| `chunks.json` | Lista di chunk con testo, sezione, titolo, n_chars | +| `meta.json` | Parametri usati (max_chars, overlap, strategia) | +| `report.json` | Statistiche e anomalie (generato da verify) | + +### Passo 3 — Verifica i chunk ```bash -.venv/bin/python conversione/ validate --detail +.venv/bin/python chunks/verify_chunks.py --stem ``` -Se lo score è ≥ 80 e `valid=true`, procedi. Altrimenti usa `/prepare-md` per -correzioni manuali (sillabazione residua, header malformati, ecc.). - -### 4. Genera i chunk - -```bash -.venv/bin/python chunks/chunker.py --stem - -# Forza riesecuzione -.venv/bin/python chunks/chunker.py --stem --force -``` - -La strategia di chunking (`h3_aware`, `h2_paragraph_split`, `paragraph`, -`sliding_window`) viene scelta automaticamente da `structure_profile.json`. - -Output in `chunks//`: - -| File | Descrizione | -|------|-------------| -| `chunks.json` | Lista di chunk con testo, sezione, titolo e metadati | -| `report.json` | Statistiche e anomalie del chunking | - -### 5. Verifica i chunk - -```bash -.venv/bin/python chunks/verify_chunks.py --stem -``` - -Verdict possibili: - | Verdict | Significato | Cosa fare | |---------|-------------|-----------| | `ok` | Nessun problema | Procedi alla vettorizzazione | -| `warnings_only` | Solo avvisi minori | Puoi procedere o eseguire il fix | -| `blocked` | Problemi bloccanti (chunk incompleti) | Esegui il fix | +| `warnings_only` | Solo avvisi minori (frasi lunghe) | Puoi procedere | +| `blocked` | Chunk incompleti o senza prefisso | Esegui il fix | -### 6. Correggi i problemi (se necessario) +### Passo 4 — Correggi i problemi (se verdict = `blocked`) ```bash -# Anteprima delle correzioni senza applicarle -.venv/bin/python chunks/fix_chunks.py --stem --dry-run +# Anteprima senza applicare +.venv/bin/python chunks/fix_chunks.py --stem --dry-run -# Applica le correzioni (ricorsivo, fino a 3 iterazioni) -.venv/bin/python chunks/fix_chunks.py --stem +# Applica le correzioni +.venv/bin/python chunks/fix_chunks.py --stem ``` -Il fix gestisce automaticamente: chunk incompleti (frase spezzata), chunk -troppo corti (accorpa al successivo), chunk eccessivamente lunghi (spezza -su punteggiatura). Ogni chunk termina sempre su un confine di frase. +Il fix risolve automaticamente: chunk incompleti (frase spezzata), chunk troppo corti (accorpati al successivo), chunk troppo lunghi (spezzati su punteggiatura). Itera fino alla convergenza o per un massimo di `FIX_MAX_ITERATIONS` passate. -### 7. Esegui l'ingestion +### Passo 5 — Vettorizzazione -Prima verifica che Ollama e i modelli siano pronti: +Verifica che Ollama sia attivo, poi: ```bash -.venv/bin/python ollama/check_env.py -``` - -Poi genera gli embedding e salva in ChromaDB: - -```bash -# Singolo documento → collection con lo stesso nome -.venv/bin/python ingestion/ingest.py --stem +# Singolo documento → collection omonima +.venv/bin/python ingestion/ingest.py --stem # Più documenti → un'unica collection condivisa -.venv/bin/python ingestion/ingest.py --collection --stems doc1 doc2 doc3 +.venv/bin/python ingestion/ingest.py --collection --stems doc1 doc2 doc3 -# Tutti i documenti in chunks/ → collection separate -.venv/bin/python ingestion/ingest.py - -# Rigenera dopo aver cambiato modello o aggiornato i chunk -.venv/bin/python ingestion/ingest.py --stem --force +# Rigenera dopo aver aggiornato i chunk o cambiato modello embedding +.venv/bin/python ingestion/ingest.py --stem --force ``` -Con `--collection` i chunk di documenti diversi vengono uniti in una singola -collection. Il metadato `source` identifica il documento di provenienza di ogni chunk. +> Se cambi `EMBED_MODEL` in `config.py`, devi rilanciare l'ingestion con `--force`. -Output in `chroma_db/` (ignorata da git). - ---- - -## Configurazione del chunking - -Tutti i parametri sono in [`chunks/config.py`](chunks/config.py): - -```python -TARGET_CHARS = 600 # dimensione target dei chunk -CHUNK_TOLERANCE = 0.25 # ±25% → range accettabile [450, 750] -OVERLAP_SENTENCES = 1 # frasi di overlap tra chunk consecutivi -PROTECT_TABLES = True # tabelle emesse come chunk atomici -FIX_MAX_ITERATIONS = 3 # iterazioni massime del fix ricorsivo -``` - -Per ogni strategia è possibile definire valori diversi tramite `STRATEGY_OVERRIDES`. -Modificare solo questo file — chunker, verify e fix si aggiornano automaticamente. - ---- - -## Configurazione modelli - -Tutti i parametri LLM e embedding sono in [`config.py`](config.py): - -```python -OLLAMA_MODEL = "qwen3.5:4b" # modello LLM per la generazione -EMBED_MODEL = "nomic-embed-text" # modello embedding (deve coincidere con l'ingestion) -TEMPERATURE = 0.2 # 0.0 = deterministico, valori alti = più creativo -NO_THINK = True # True = risposta diretta (più veloce), False = con ragionamento -TOP_K = 6 # numero di chunk recuperati per ogni domanda -OLLAMA_URL = "http://localhost:11434" -``` - -> Se cambi `EMBED_MODEL` devi rieseguire l'ingestion con `--force` — gli embedding -> devono essere prodotti dallo stesso modello usato nel retrieval. - ---- - -## Testare il modello (senza RAG) - -Verifica che il modello LLM risponda correttamente prima di coinvolgere la pipeline: +### Passo 6 — Interrogazione ```bash -.venv/bin/python ollama/test_ollama.py +# RAG interattivo +.venv/bin/python rag.py --stem +.venv/bin/python rag.py --collection + +# Retrieval puro (debug, senza generazione LLM) +.venv/bin/python retrieve.py --stem +.venv/bin/python retrieve.py --stem --top-k 10 ``` -Il modello usato è quello configurato in `config.py` (`OLLAMA_MODEL`). -Digita `exit` per uscire. +Comandi nel loop interattivo di `retrieve.py`: ---- - -## Retrieval puro (senza generazione) - -Utile per verificare che i chunk giusti vengano recuperati prima di diagnosticare -risposte sbagliate: - -```bash -# Singolo documento -.venv/bin/python retrieve.py --stem - -# Collection multi-documento -.venv/bin/python retrieve.py --collection - -# Modifica il numero di chunk restituiti -.venv/bin/python retrieve.py --stem --top-k 10 -``` - -Nel loop interattivo: - -| Comando | Effetto | -|---------|---------| -| `` | Mostra i chunk più simili con score di similarità (testo troncato) | +| Input | Effetto | +|-------|---------| +| `` | Chunk più simili con score (testo troncato) | | ` -f` | Testo completo dei chunk | | `exit` | Termina | --- -## RAG interattivo +## Configurazione -Risponde a domande in linguaggio naturale usando i chunk indicizzati in ChromaDB: +### Parametri di chunking — `chunks/config.py` -```bash -# Singolo documento -.venv/bin/python rag.py --stem +| Parametro | Default | Descrizione | +|-----------|---------|-------------| +| `MAX_CHARS` | 1200 | Lunghezza massima chunk in caratteri | +| `MIN_CHARS` | 80 | Soglia minima (warning sotto questa soglia) | +| `OVERLAP_SENTENCES` | 1 | Frasi di overlap tra chunk consecutivi | +| `MIN_CONTENT_CHARS` | 2500 | Soglia per distinguere frontespizio da contenuto reale | +| `FRONTMATTER_HEADINGS` | set italiano | Sezioni da rimuovere (Sommario, Indice, Autori…) — svuotare per documenti non italiani | +| `SOMMARIO_PATTERNS` | 5 lingue | Pattern regex per sommari interni da saltare | +| `CHAPTER_PREFIX_PATTERNS` | 4 lingue | Pattern per prefissi di capitolo come paragrafi separati | +| `MODEL_SKIP_LABELS` | set | Label `_model.json` da ignorare (header, number…) | -# Collection multi-documento -.venv/bin/python rag.py --collection -``` +### Parametri RAG — `config.py` -Nel loop interattivo: - -| Comando | Effetto | -|---------|---------| -| `` | Risposta generata dal LLM con contesto dai chunk | -| ` -v` | Risposta + chunk recuperati con score di similarità e documento sorgente | -| `exit` | Termina | +| Parametro | Default | Descrizione | +|-----------|---------|-------------| +| `OLLAMA_MODEL` | `qwen3.5:4b` | Modello LLM per la generazione | +| `EMBED_MODEL` | `nomic-embed-text` | Modello embedding | +| `TOP_K` | 6 | Chunk recuperati per domanda | +| `TEMPERATURE` | 0.2 | Creatività del modello (0 = deterministico) | +| `OLLAMA_URL` | `localhost:11434` | URL server Ollama | --- -## Test +## Struttura del repository -```bash -.venv/bin/python -m pytest tests/ +``` +rag/ +├── sources/ ← output di MinerU (una cartella per documento) +│ └── /auto/ +├── chunks/ +│ ├── chunker.py ← pipeline unificata (Stage 1 + Stage 2) +│ ├── md_optimizer.py ← Stage 1: JSON MinerU → _clean.md +│ ├── config.py ← tutti i parametri di chunking +│ ├── verify_chunks.py ← verifica qualità +│ └── fix_chunks.py ← correzioni automatiche +├── ingestion/ +│ └── ingest.py ← embedding → ChromaDB +├── ollama/ +│ └── check_env.py ← verifica ambiente Ollama +├── chroma_db/ ← database vettoriale (ignorato da git) +├── config.py ← parametri RAG (modelli, TOP_K, prompt) +├── rag.py ← loop RAG interattivo +└── retrieve.py ← retrieval puro (debug) ``` --- -## Riferimenti +## Note su generalità e adattamento -- [`conversione/README.md`](conversione/README.md) — dettagli sulla pipeline PDF→Markdown e sui tipi di documento supportati -- [`ingestion/README.md`](ingestion/README.md) — configurazione embedding, scelta modello, regole --force +La pipeline è progettata per funzionare con **qualsiasi output MinerU**, non solo per documenti in italiano. MinerU produce sempre la stessa struttura di file (`_content_list_v2.json`, `_model.json`) indipendentemente dal documento sorgente. + +Per adattare a documenti in altre lingue o con struttura diversa, modificare in `chunks/config.py`: + +- **`FRONTMATTER_HEADINGS`**: impostare `set()` per disabilitare, o aggiungere i nomi delle sezioni da rimuovere nella lingua del documento +- **`SOMMARIO_PATTERNS`**: aggiungere/rimuovere pattern regex per i sommari interni +- **`CHAPTER_PREFIX_PATTERNS`**: aggiungere pattern per la lingua del documento +- **`MIN_CONTENT_CHARS`**: alzare se il documento ha lunghe sezioni di copyright/prefazione da escludere +- **`MIN_TOC_HEADINGS`**: abbassare se il documento ha pochi capitoli (es. 3-4)