Files
rag-from-scratch/CLAUDE.md
T
davide 9e0e1a131e docs: aggiorna CLAUDE.md per riflettere la struttura attuale del repo
Allinea comandi, architettura e schema chunk alla struttura reale:
percorsi rag/, gui/, ingestion/ corretti; pipeline chunking documentata
nei 5 moduli; config split ingestion/rag; sezione GUI aggiunta.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 10:24:51 +02:00

142 lines
5.5 KiB
Markdown

# 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).
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).
---
## Missione
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.
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.
---
## Regole invarianti
- **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 i file in `sources/`. Il chunker scrive solo in `chunks/<stem>/`.
---
## Input — struttura MinerU
```
sources/<stem>_output/auto/<stem>.md ← Markdown strutturato (input della pipeline)
sources/<stem>_output/auto/images/ ← immagini estratte
```
`<stem>` = nome del documento, usato come identificatore in tutti i comandi.
---
## Comandi
```bash
# Setup
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
# Chunking
.venv/bin/python chunks/chunker.py --stem <stem>
.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
# Vettorizzazione (richiede Ollama attivo)
.venv/bin/python ingestion/ingest.py --stem <stem>
.venv/bin/python ingestion/ingest.py --collection <nome> --stems doc1 doc2 doc3
.venv/bin/python ingestion/ingest.py --stem <stem> --force
# RAG interattivo
.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
```
---
## Architettura
### Chunking — `chunks/`
| File | Responsabilità |
|------|---------------|
| `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/`
| 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` |
ChromaDB persistente in `chroma_db/`. Supporta collection multi-documento (`--collection`).
### RAG — `rag/`
| File | Responsabilità |
|------|---------------|
| `rag.py` | Loop interattivo: retrieval + generazione Ollama |
| `retrieve.py` | Retrieval puro (debug senza LLM) |
| `config.py` | `TOP_K`, `TEMPERATURE`, `NO_THINK`, `OLLAMA_MODEL`, `OLLAMA_URL`, `SYSTEM_PROMPT` |
### GUI — `gui/`
| 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` |
Temi light/dark gestiti via CSS custom properties in `chat.html` e stylesheet Qt in `chat_window.py`.
### Utility — `ollama/`
| 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 |