2026-05-11 14:44:16 +02:00
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
---
2026-04-13 08:02:48 +02:00
2026-05-20 14:04:12 +02:00
## Lingua e comportamento
2026-04-13 08:02:48 +02:00
2026-04-15 11:38:45 +02:00
- **Lingua:** Rispondi sempre in italiano.
2026-05-20 14:04:12 +02:00
- **Prima di eseguire qualsiasi istruzione**, esponi:
2026-05-20 14:21:16 +02:00
1. Come intendi procedere (approccio, file coinvolti).
2026-05-20 14:04:12 +02:00
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).
2026-05-11 14:44:16 +02:00
---
2026-05-20 14:04:12 +02:00
## Missione
2026-06-09 10:24:51 +02:00
Pipeline RAG su documenti PDF, interamente in locale. La conversione PDF → Markdown è delegata a **MinerU ** (tool esterno). Questo repository si occupa di: chunking, vettorizzazione, retrieval/generazione e GUI desktop.
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
Il PDF viene convertito da MinerU in Markdown strutturato. Il chunker lo analizza e produce chunk semantici. Il modulo di ingest genera gli embedding tramite Ollama e li indicizza in ChromaDB. Infine `rag/rag.py` (o la GUI) riceve la domanda, recupera i chunk più rilevanti e genera la risposta.
2026-05-20 14:04:12 +02:00
---
## Regole invarianti
2026-05-11 14:44:16 +02:00
2026-05-20 14:04:12 +02:00
- **Venv:** Usa `.venv/bin/python` . Mai `pip` /`python` di sistema.
2026-05-20 14:21:16 +02:00
- **Niente LLM nella pipeline:** chunking e pulizia devono essere rule-based e riproducibili.
2026-06-09 10:24:51 +02:00
- **Input immutabile:** Non modificare mai i file in `sources/` . Il chunker scrive solo in `chunks/<stem>/` .
2026-05-20 14:21:16 +02:00
---
## Input — struttura MinerU
```
2026-06-04 14:39:12 +02:00
sources/<stem>_output/auto/<stem>.md ← Markdown strutturato (input della pipeline)
sources/<stem>_output/auto/images/ ← immagini estratte
2026-05-20 14:21:16 +02:00
```
2026-06-09 10:24:51 +02:00
`<stem>` = nome del documento, usato come identificatore in tutti i comandi.
2026-05-11 14:44:16 +02:00
---
## Comandi
``` bash
2026-05-20 14:04:12 +02:00
# Setup
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
2026-06-04 14:39:12 +02:00
# Chunking
2026-05-20 14:21:16 +02:00
.venv/bin/python chunks/chunker.py --stem <stem>
2026-06-09 10:24:51 +02:00
.venv/bin/python chunks/chunker.py # tutti gli stem in sources/
.venv/bin/python chunks/chunker.py --stem <stem> --force # rigenera anche se già presente
2026-05-11 14:44:16 +02:00
2026-05-20 14:04:12 +02:00
# Vettorizzazione (richiede Ollama attivo)
2026-05-20 14:21:16 +02:00
.venv/bin/python ingestion/ingest.py --stem <stem>
2026-06-09 10:24:51 +02:00
.venv/bin/python ingestion/ingest.py --collection <nome> --stems doc1 doc2 doc3
2026-05-20 14:21:16 +02:00
.venv/bin/python ingestion/ingest.py --stem <stem> --force
2026-05-11 14:44:16 +02:00
2026-05-20 14:04:12 +02:00
# RAG interattivo
2026-06-09 10:24:51 +02:00
.venv/bin/python rag/rag.py --collection <nome>
.venv/bin/python rag/rag.py --stem <stem>
# Retrieval puro (debug senza LLM)
.venv/bin/python rag/retrieve.py --stem <stem>
.venv/bin/python rag/retrieve.py --collection <nome> --top-k 10
# GUI desktop
.venv/bin/python gui/main.py
.venv/bin/python gui/main.py --collection <nome>
# Verifica ambiente Ollama
.venv/bin/python ollama/check_env.py
2026-05-20 14:04:12 +02:00
```
2026-04-13 08:02:48 +02:00
2026-04-15 11:38:45 +02:00
---
2026-05-11 14:44:16 +02:00
## Architettura
2026-05-20 14:21:16 +02:00
### Chunking — `chunks/`
2026-04-15 11:38:45 +02:00
2026-05-20 14:21:16 +02:00
| File | Responsabilità |
|------|---------------|
2026-06-09 10:24:51 +02:00
| `chunker.py` | Entry point: legge `<stem>.md` , orchestra parser → segmenter → packer → validator |
| `parser.py` | Markdown → AST di `Block` tramite markdown-it-py |
| `segmenter.py` | AST → sequenza di `Block` con header_path e contesto heading |
| `packer.py` | `Block[]` → `Chunk[]` con packing min/target/max |
| `validator.py` | Verifica integrità e coerenza dei chunk prodotti |
| `models.py` | Dataclass: `Block` , `Chunk` , `Diagnostics` , `ChunkingResult` |
| `config.py` | `ChunkerConfig` : `max_chars` , `min_chars` , `target_chars` , `context_depth` , `skip_headings` , `atomic_types` |
Output per stem: `chunks/<stem>/chunks.json` , `chunks/<stem>/meta.json` , `chunks/<stem>/report.json`
**Schema chunk ** (`chunks.json` ):
| Campo | Descrizione |
|-------|-------------|
| `chunk_id` | Identificatore univoco |
| `content_for_embedding` | Testo con prefisso heading, usato per generare il vettore |
| `content_original` | Testo originale senza prefisso, memorizzato in ChromaDB |
| `header_path` | Lista di dict `{level, text}` — gerarchia heading del chunk |
| `content_type` | Tipo blocco dominante (`paragraph` , `table` , `code` , ecc.) |
| `flags` | Dict: `has_code` , `has_table` , `has_math` , `is_overflow` |
| `chunk_index` | Posizione ordinale nel documento |
| `start_line` / `end_line` | Righe sorgente nel Markdown |
| `chars` | Lunghezza in caratteri di `content_original` |
### Vettorizzazione — `ingestion/`
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
| File | Responsabilità |
|------|---------------|
| `ingest.py` | Legge `chunks.json` , genera embedding via Ollama, indicizza in ChromaDB |
| `config.py` | `EMBED_MODEL` (default: `bge-m3` ), `EMBED_MAX_CHARS` , `OLLAMA_URL` |
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
ChromaDB persistente in `chroma_db/` . Supporta collection multi-documento (`--collection` ).
2026-04-13 08:02:48 +02:00
2026-06-09 10:24:51 +02:00
### RAG — `rag/`
2026-05-11 14:44:16 +02:00
2026-05-20 14:04:12 +02:00
| File | Responsabilità |
|------|---------------|
2026-05-20 14:21:16 +02:00
| `rag.py` | Loop interattivo: retrieval + generazione Ollama |
| `retrieve.py` | Retrieval puro (debug senza LLM) |
2026-06-09 10:24:51 +02:00
| `config.py` | `TOP_K` , `TEMPERATURE` , `NO_THINK` , `OLLAMA_MODEL` , `OLLAMA_URL` , `SYSTEM_PROMPT` |
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
### GUI — `gui/`
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
| File | Responsabilità |
|------|---------------|
| `main.py` | Entry point PySide6, argparse `--collection` |
| `chat_window.py` | `QMainWindow` : top bar (combo collection + toggle tema), `QWebEngineView` , input bar |
| `worker.py` | `QThread` : esegue retrieve + build_prompt + call_ollama in background |
| `chat.html` | Template HTML con marked.js + KaTeX (CDN); funzioni JS: `addMessage` , `addThinking` , `removeThinking` , `setTheme` |
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
Temi light/dark gestiti via CSS custom properties in `chat.html` e stylesheet Qt in `chat_window.py` .
2026-05-11 14:44:16 +02:00
2026-06-09 10:24:51 +02:00
### Utility — `ollama/`
2026-04-15 11:38:45 +02:00
2026-06-09 10:24:51 +02:00
| File | Responsabilità |
|------|---------------|
| `check_env.py` | Verifica che Ollama sia attivo e i modelli configurati siano disponibili |
| `test_ollama.py` | Test embedding e generazione end-to-end |