step-7: add check_env.py, README, update requirements
- check_env.py: verifica ollama, embedding model, LLM model, chromadb - Rileva qualsiasi modello embedding/LLM installato (non lista fissa) - step-7/README.md: guida installazione/disinstallazione Ollama, modelli, chromadb - requirements.txt: aggiunge chromadb per step-8
This commit is contained in:
@@ -470,29 +470,33 @@ Distribuzione lunghezze:
|
|||||||
**Tipo:** manuale (una volta sola)
|
**Tipo:** manuale (una volta sola)
|
||||||
**Input:** nessuno
|
**Input:** nessuno
|
||||||
**Output:** ambiente locale funzionante
|
**Output:** ambiente locale funzionante
|
||||||
|
**Script:** `step-7/check_env.py`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Installa Ollama
|
# Installa Ollama
|
||||||
curl -fsSL https://ollama.com/install.sh | sh
|
curl -fsSL https://ollama.com/install.sh | sh
|
||||||
|
|
||||||
# Scarica i modelli
|
# Scarica un modello di embedding e un LLM
|
||||||
ollama pull qwen3:8b # LLM — ~5 GB
|
ollama pull nomic-embed-text # Embedding — ~274 MB (consigliato)
|
||||||
ollama pull nomic-embed-text # Embedding — ~270 MB
|
ollama pull qwen3.5:4b # LLM — ~3.4 GB (consigliato per 8 GB RAM)
|
||||||
|
|
||||||
# Installa dipendenze Python
|
# Installa dipendenze Python nel venv
|
||||||
|
source .venv/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# Verifica
|
# Verifica tutto
|
||||||
ollama list
|
python step-7/check_env.py
|
||||||
# deve mostrare entrambi i modelli
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Modelli usati:**
|
**Modelli consigliati per 8 GB RAM:**
|
||||||
|
|
||||||
| Modello | Ruolo | Dimensione | RAM occupata |
|
| Modello | Ruolo | Dimensione |
|
||||||
|---|---|---|---|
|
|---|---|---|
|
||||||
| `nomic-embed-text` | Converte testo in vettori | 270 MB | ~500 MB |
|
| `nomic-embed-text` | Embedding | ~274 MB |
|
||||||
| `qwen3:8b` | Genera le risposte | 5 GB | ~6-7 GB |
|
| `qwen3.5:4b` | LLM | ~3.4 GB |
|
||||||
|
|
||||||
|
Per guide dettagliate su modelli alternativi, installazione e disinstallazione
|
||||||
|
di Ollama e ChromaDB, vedi [`step-7/README.md`](step-7/README.md).
|
||||||
|
|
||||||
Questo step si esegue una volta sola. Da questo momento
|
Questo step si esegue una volta sola. Da questo momento
|
||||||
Ollama è sempre disponibile sul sistema.
|
Ollama è sempre disponibile sul sistema.
|
||||||
|
|||||||
@@ -3,3 +3,6 @@ pdfplumber==0.11.9
|
|||||||
|
|
||||||
# Step 2 — Conversione PDF → Markdown
|
# Step 2 — Conversione PDF → Markdown
|
||||||
pymupdf4llm
|
pymupdf4llm
|
||||||
|
|
||||||
|
# Step 8 — Vettorizzazione
|
||||||
|
chromadb
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
# Step 7 — Verifica ambiente
|
||||||
|
|
||||||
|
Prima di procedere con la vettorizzazione (step 8) devi avere installato:
|
||||||
|
|
||||||
|
- **Ollama** — server locale per LLM e embedding
|
||||||
|
- un **modello di embedding** (es. `nomic-embed-text`, `bge-m3`)
|
||||||
|
- un **modello LLM** (es. `qwen3.5:4b`, `qwen3:4b`)
|
||||||
|
- **chromadb** — libreria Python per il vector store
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Installa Ollama
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://ollama.com/install.sh | sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifica che il servizio sia attivo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disinstalla Ollama
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ferma e rimuovi il servizio systemd
|
||||||
|
sudo systemctl stop ollama
|
||||||
|
sudo systemctl disable ollama
|
||||||
|
sudo rm /etc/systemd/system/ollama.service
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
|
||||||
|
# Rimuovi il binario
|
||||||
|
sudo rm /usr/local/bin/ollama
|
||||||
|
|
||||||
|
# Rimuovi modelli e dati (opzionale — occupa spazio su disco)
|
||||||
|
# I modelli sono salvati sotto l'utente di sistema "ollama", non nella tua home
|
||||||
|
sudo rm -rf /usr/share/ollama
|
||||||
|
|
||||||
|
# Rimuovi l'utente e il gruppo di sistema creati dall'installer (opzionale)
|
||||||
|
sudo userdel ollama
|
||||||
|
sudo groupdel ollama
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Scarica i modelli
|
||||||
|
|
||||||
|
### Modello di embedding
|
||||||
|
|
||||||
|
Per testo in italiano usa **`bge-m3`** — addestrato su 100+ lingue, gestisce l'italiano meglio dei modelli English-first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama pull bge-m3
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternativa leggera (principalmente inglese, ~274 MB):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama pull nomic-embed-text
|
||||||
|
```
|
||||||
|
|
||||||
|
| Modello | Dim | Dimensione | Lingue |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `bge-m3` | 1024 | ~1.2 GB | 100+ lingue incl. IT |
|
||||||
|
| `nomic-embed-text` | 768 | ~274 MB | principalmente EN |
|
||||||
|
| `mxbai-embed-large` | 1024 | ~670 MB | principalmente EN |
|
||||||
|
| `all-minilm` | 384 | ~46 MB | principalmente EN |
|
||||||
|
|
||||||
|
### Modello LLM
|
||||||
|
|
||||||
|
Scegli in base alla RAM disponibile:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama pull qwen3.5:4b # consigliato per 8 GB RAM
|
||||||
|
```
|
||||||
|
|
||||||
|
| Modello | RAM consigliata | Note |
|
||||||
|
|---|---|---|
|
||||||
|
| `qwen3:8b` | ≥ 10 GB | ottima qualità, troppo stretto su 8 GB |
|
||||||
|
| `qwen3.5:4b` | ≥ 5 GB | buon bilanciamento, **consigliato per 8 GB** |
|
||||||
|
| `qwen3:4b` | ≥ 5 GB | alternativa stabile |
|
||||||
|
| `phi4-mini` | ≥ 4 GB | ottimo per instruction following |
|
||||||
|
| `qwen3:1.7b` | ≥ 3 GB | leggero, qualità base |
|
||||||
|
|
||||||
|
Se usi un modello diverso da `qwen3.5:4b`, aggiorna la costante `LLM_MODEL` in `step-9/rag.py`.
|
||||||
|
|
||||||
|
### Disinstalla un modello
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama rm qwen3.5:4b
|
||||||
|
ollama rm nomic-embed-text
|
||||||
|
```
|
||||||
|
|
||||||
|
Per vedere tutti i modelli installati:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ollama list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Installa chromadb nel venv
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install chromadb
|
||||||
|
```
|
||||||
|
|
||||||
|
Aggiorna anche `requirements.txt`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip freeze | grep chromadb >> requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disinstalla chromadb
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
# Rimuovi il pacchetto e le dipendenze non più necessarie
|
||||||
|
pip uninstall chromadb -y
|
||||||
|
pip autoremove 2>/dev/null || pip uninstall $(pip-autoremove chromadb -l 2>/dev/null) -y 2>/dev/null
|
||||||
|
|
||||||
|
# Rimuovi i dati del vector store (opzionale — occupa spazio su disco)
|
||||||
|
rm -rf chroma_db/
|
||||||
|
```
|
||||||
|
|
||||||
|
> `pip autoremove` richiede il pacchetto `pip-autoremove` (`pip install pip-autoremove`).
|
||||||
|
> In alternativa, elimina e ricrea il venv per una pulizia completa:
|
||||||
|
> ```bash
|
||||||
|
> deactivate
|
||||||
|
> rm -rf .venv
|
||||||
|
> python -m venv .venv
|
||||||
|
> source .venv/bin/activate
|
||||||
|
> pip install -r requirements.txt
|
||||||
|
> ```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Verifica tutto
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
python step-7/check_env.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Output atteso se tutto è a posto:
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ ollama trovato nel PATH
|
||||||
|
✅ ollama risponde correttamente
|
||||||
|
✅ modello embedding trovato: nomic-embed-text:latest
|
||||||
|
✅ modello LLM trovato: qwen3.5:4b
|
||||||
|
|
||||||
|
✅ chromadb importabile
|
||||||
|
|
||||||
|
✅ Ambiente pronto — procedi con la vettorizzazione:
|
||||||
|
python step-8/ingest.py --stem <nome>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prossimo step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python step-8/ingest.py --stem nietzsche
|
||||||
|
```
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Step 7 — Verifica ambiente
|
||||||
|
|
||||||
|
Controlla che tutti i prerequisiti per la vettorizzazione siano soddisfatti:
|
||||||
|
1. ollama è nel PATH e risponde
|
||||||
|
2. Almeno un modello di embedding è scaricato
|
||||||
|
3. Almeno un modello LLM è scaricato
|
||||||
|
4. chromadb è importabile
|
||||||
|
|
||||||
|
Output: report a schermo con ✅ / ❌ per ogni componente.
|
||||||
|
Nessun file scritto. Exit 0 se tutto OK, 1 altrimenti.
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python step-7/check_env.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# Modelli riconosciuti come embedding (basta che uno sia presente)
|
||||||
|
# Tutto il resto viene considerato LLM
|
||||||
|
EMBED_MODELS = ["bge-m3", "nomic-embed-text", "mxbai-embed-large", "all-minilm"]
|
||||||
|
|
||||||
|
REQUIRED_LIBS = ["chromadb"]
|
||||||
|
|
||||||
|
|
||||||
|
# ─── Checks ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def check_ollama_in_path() -> bool:
|
||||||
|
"""Verifica che ollama sia nel PATH."""
|
||||||
|
found = shutil.which("ollama") is not None
|
||||||
|
if found:
|
||||||
|
print("✅ ollama trovato nel PATH")
|
||||||
|
else:
|
||||||
|
print("❌ ollama non trovato nel PATH")
|
||||||
|
print(" → Installa con: curl -fsSL https://ollama.com/install.sh | sh")
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def check_ollama_running() -> list[str] | None:
|
||||||
|
"""
|
||||||
|
Esegue 'ollama list' e ritorna la lista dei modelli disponibili.
|
||||||
|
Ritorna None se ollama non risponde.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["ollama", "list"],
|
||||||
|
capture_output=True, text=True, timeout=10
|
||||||
|
)
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("❌ ollama non risponde (errore all'avvio)")
|
||||||
|
print(" → Avvia il servizio con: ollama serve")
|
||||||
|
return None
|
||||||
|
lines = result.stdout.strip().splitlines()
|
||||||
|
models = []
|
||||||
|
for line in lines[1:]: # salta l'header
|
||||||
|
parts = line.split()
|
||||||
|
if parts:
|
||||||
|
models.append(parts[0])
|
||||||
|
print("✅ ollama risponde correttamente")
|
||||||
|
return models
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("❌ ollama non trovato (FileNotFoundError)")
|
||||||
|
return None
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print("❌ ollama non risponde (timeout)")
|
||||||
|
print(" → Avvia il servizio con: ollama serve")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _match(model_name: str, available: list[str]) -> str | None:
|
||||||
|
"""
|
||||||
|
Ritorna il nome completo del modello trovato in 'available' che corrisponde
|
||||||
|
a 'model_name' (confronto per prefisso), oppure None.
|
||||||
|
"""
|
||||||
|
for m in available:
|
||||||
|
if m == model_name or m.startswith(model_name + ":") or m.startswith(model_name + "-"):
|
||||||
|
return m
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def check_embed_model(available: list[str]) -> bool:
|
||||||
|
"""Verifica che almeno un modello di embedding sia presente."""
|
||||||
|
for candidate in EMBED_MODELS:
|
||||||
|
found = _match(candidate, available)
|
||||||
|
if found:
|
||||||
|
print(f"✅ modello embedding trovato: {found}")
|
||||||
|
return True
|
||||||
|
print("❌ nessun modello di embedding trovato")
|
||||||
|
print(f" → Consigliato per italiano: ollama pull bge-m3")
|
||||||
|
print(f" → Alternativa leggera: ollama pull nomic-embed-text")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_llm_model(available: list[str]) -> bool:
|
||||||
|
"""Verifica che almeno un modello non-embedding sia presente."""
|
||||||
|
llm_candidates = [
|
||||||
|
m for m in available
|
||||||
|
if not any(m == e or m.startswith(e + ":") or m.startswith(e + "-")
|
||||||
|
for e in EMBED_MODELS)
|
||||||
|
]
|
||||||
|
if llm_candidates:
|
||||||
|
print(f"✅ modello LLM trovato: {llm_candidates[0]}")
|
||||||
|
return True
|
||||||
|
print("❌ nessun modello LLM trovato")
|
||||||
|
print(f" → Consigliato per 8 GB RAM: ollama pull qwen3.5:4b")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_library(lib: str) -> bool:
|
||||||
|
"""Verifica che una libreria Python sia importabile."""
|
||||||
|
try:
|
||||||
|
__import__(lib)
|
||||||
|
print(f"✅ {lib} importabile")
|
||||||
|
return True
|
||||||
|
except ImportError:
|
||||||
|
print(f"❌ {lib} non importabile")
|
||||||
|
print(f" → Installa con: pip install {lib}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ─── Entry point ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
print("─── Step 7 — Verifica ambiente ───────────────────────────────────────\n")
|
||||||
|
|
||||||
|
results: list[bool] = []
|
||||||
|
|
||||||
|
# 1. ollama nel PATH
|
||||||
|
in_path = check_ollama_in_path()
|
||||||
|
results.append(in_path)
|
||||||
|
|
||||||
|
# 2. ollama risponde + modelli
|
||||||
|
if in_path:
|
||||||
|
available = check_ollama_running()
|
||||||
|
if available is None:
|
||||||
|
results.extend([False, False, False])
|
||||||
|
else:
|
||||||
|
results.append(True)
|
||||||
|
results.append(check_embed_model(available))
|
||||||
|
results.append(check_llm_model(available))
|
||||||
|
else:
|
||||||
|
results.extend([False, False, False])
|
||||||
|
print("⚠️ modelli non verificabili (ollama non trovato)")
|
||||||
|
|
||||||
|
# 3. Librerie Python
|
||||||
|
print()
|
||||||
|
for lib in REQUIRED_LIBS:
|
||||||
|
results.append(check_library(lib))
|
||||||
|
|
||||||
|
# ── Riepilogo ─────────────────────────────────────────────────────────────
|
||||||
|
print()
|
||||||
|
print("──────────────────────────────────────────────────────────────────────")
|
||||||
|
all_ok = all(results)
|
||||||
|
if all_ok:
|
||||||
|
print("✅ Ambiente pronto — procedi con la vettorizzazione:")
|
||||||
|
print(" python step-8/ingest.py --stem <nome>")
|
||||||
|
else:
|
||||||
|
n_fail = sum(1 for r in results if not r)
|
||||||
|
print(f"⚠️ {n_fail} problema/i rilevato/i — risolvi prima di procedere con step-8.")
|
||||||
|
|
||||||
|
return 0 if all_ok else 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user