Rabbook / rag /ingest.py
Matcry's picture
Deploy snapshot
c76423f
Raw
History Blame Contribute Delete
4.47 kB
from pathlib import Path
from dotenv import load_dotenv
from langchain_chroma import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from core.config import (
DATA_DIR,
DB_DIR,
DEFAULT_CHUNK_OVERLAP,
DEFAULT_CHUNK_SIZE,
DEFAULT_SEMANTIC_PERCENTILE,
REGISTRY_PATH,
)
from rag.chunking import split_documents
from rag.loaders import load_documents
from rag.metadata import enrich_chunk_metadata, enrich_document_metadata
from rag.registry import update_chunk_registry
def build_vectorstore(chunks, embeddings, persist_dir):
"""
Build a Chroma vector store from the provided document chunks and embeddings.
"""
return Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory=persist_dir,
)
def prepare_chunks(documents, embeddings):
"""
Run the ingestion preparation pipeline before writing to Chroma.
"""
documents = enrich_document_metadata(documents)
chunks = split_documents(
documents,
embeddings=embeddings,
chunk_size=DEFAULT_CHUNK_SIZE,
chunk_overlap=DEFAULT_CHUNK_OVERLAP,
percentile=DEFAULT_SEMANTIC_PERCENTILE,
)
return enrich_chunk_metadata(chunks)
def add_documents_to_vectorstore(data_dir, embeddings, persist_dir):
"""
Add new documents into the existing Chroma vector store.
"""
documents = load_documents(data_dir)
return add_loaded_documents_to_vectorstore(documents, embeddings, persist_dir)
def add_loaded_documents_to_vectorstore(documents, embeddings, persist_dir):
"""
Add already-loaded documents into the existing Chroma vector store.
"""
enriched_chunks = prepare_chunks(documents, embeddings)
if not enriched_chunks:
raise ValueError("No supported documents were found to ingest.")
persist_path = Path(persist_dir)
if persist_path.exists() and any(persist_path.iterdir()):
vector_db = Chroma(
embedding_function=embeddings,
persist_directory=str(persist_path),
)
vector_db.add_documents(enriched_chunks)
update_chunk_registry(enriched_chunks)
return vector_db
vector_db = build_vectorstore(enriched_chunks, embeddings, str(persist_path))
update_chunk_registry(enriched_chunks)
return vector_db
def reingest_directory(data_dir, embeddings, persist_dir, registry_path=REGISTRY_PATH):
"""
Rebuild Chroma and the chunk registry from a directory of uploaded files.
"""
documents = load_documents(data_dir)
enriched_chunks = prepare_chunks(documents, embeddings)
persist_path = Path(persist_dir)
persist_path.mkdir(parents=True, exist_ok=True)
vector_db = None
if any(persist_path.iterdir()):
vector_db = Chroma(
embedding_function=embeddings,
persist_directory=str(persist_path),
)
existing = vector_db._collection.get()
existing_ids = existing.get("ids", [])
if existing_ids:
vector_db._collection.delete(ids=existing_ids)
registry_file = Path(registry_path)
registry_file.write_text(
'{"by_document": {}, "by_chunk_id": {}}',
encoding="utf-8",
)
if not enriched_chunks:
return {
"document_count": len(documents),
"chunk_count": 0,
}
if vector_db is not None:
vector_db.add_documents(enriched_chunks)
else:
build_vectorstore(enriched_chunks, embeddings, str(persist_path))
update_chunk_registry(enriched_chunks, registry_path=registry_path)
return {
"document_count": len(documents),
"chunk_count": len(enriched_chunks),
}
def main():
load_dotenv() # Load environment variables from .env file
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
print("Starting ingestion process...")
documents = load_documents(DATA_DIR)
enriched_chunks = prepare_chunks(documents, embeddings)
build_vectorstore(enriched_chunks, embeddings, str(DB_DIR))
update_chunk_registry(enriched_chunks)
print(f"Loaded {len(documents)} documents")
print(f"Created {len(enriched_chunks)} chunks")
print(f"Saved vector DB to {DB_DIR}")
print("Ingestion completed.")
if __name__ == "__main__":
raise SystemExit(
"Run this from the project root with `python ingest_docs.py`, not `python rag/ingest.py`."
)