feat(ingestion): supporto multi-documento in unica collection ChromaDB

Aggiunge la possibilità di unire più documenti in una singola collection
ChromaDB, con chunk_id prefissati per stem e metadato source per filtrare.

- ingest.py: --stems doc1 doc2 --collection nome (nuovo), --stem (invariato)
- rag.py / retrieve.py: --collection, source nei chunk, verbose mostra [source]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-12 11:21:17 +02:00
parent b630316936
commit 606fad9e09
3 changed files with 137 additions and 73 deletions
+21 -9
View File
@@ -85,6 +85,7 @@ def retrieve(collection: chromadb.Collection, query: str, top_k: int) -> list[di
chunks.append({
"rank": rank,
"similarity": round(1 - dist, 4),
"source": meta.get("source", ""),
"sezione": meta.get("sezione", ""),
"titolo": meta.get("titolo", ""),
"text": text,
@@ -97,10 +98,11 @@ def retrieve(collection: chromadb.Collection, query: str, top_k: int) -> list[di
def print_results(chunks: list[dict], full: bool = False) -> None:
print(f"── {len(chunks)} chunk recuperati ─────────────────────────────────\n")
for c in chunks:
src = f"[{c['source']}] " if c.get("source") else ""
loc = c["sezione"]
if c["titolo"]:
loc += f" > {c['titolo']}"
print(f" [{c['rank']}] similarità: {c['similarity']:.4f} | {loc}")
print(f" [{c['rank']}] similarità: {c['similarity']:.4f} | {src}{loc}")
if full:
print()
print(c["text"])
@@ -177,8 +179,11 @@ def main() -> int:
)
parser.add_argument(
"--stem",
required=True,
help="Nome della collection ChromaDB da interrogare.",
help="Collection di un singolo documento (retrocompatibile)",
)
parser.add_argument(
"--collection",
help="Collection multi-documento creata con: ingest.py --collection <nome> --stems ...",
)
parser.add_argument(
"--top-k",
@@ -189,8 +194,12 @@ def main() -> int:
)
args = parser.parse_args()
collection_name = args.collection or args.stem
if not collection_name:
parser.error("specifica --stem <nome> oppure --collection <nome>")
print("─── Retrieval puro ──────────────────────────────────────────\n")
print(f" Documento : {args.stem}")
print(f" Collection : {collection_name}")
print(f" Embed model : {EMBED_MODEL}")
print(f" Top-K : {args.top_k}")
print()
@@ -201,13 +210,16 @@ def main() -> int:
client = chromadb.PersistentClient(path=str(CHROMA_DIR))
collections = [c.name for c in client.list_collections()]
if args.stem not in collections:
print(f"❌ Collection '{args.stem}' non trovata in chroma_db/", file=sys.stderr)
print(f" → python ingestion/ingest.py --stem {args.stem}", file=sys.stderr)
if collection_name not in collections:
print(f"❌ Collection '{collection_name}' non trovata in chroma_db/", file=sys.stderr)
if args.stem:
print(f" → python ingestion/ingest.py --stem {collection_name}", file=sys.stderr)
else:
print(f" → python ingestion/ingest.py --collection {collection_name} --stems doc1 doc2 ...", file=sys.stderr)
return 1
collection = client.get_collection(args.stem)
print(f"✅ Collection '{args.stem}' caricata ({collection.count()} chunk)\n")
collection = client.get_collection(collection_name)
print(f"✅ Collection '{collection_name}' caricata ({collection.count()} chunk)\n")
run_loop(collection, args.top_k)
return 0