engine-space / core /ingestion.py
GodRad's picture
Upload 6 files
0087f82 verified
Raw History Blame Contribute Delete
2.26 kB
import os
import hashlib
from typing import List
import pypdf
from docx import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from .config import settings
class DocumentProcessor:
def __init__(self):
self.embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
self.vector_store = Chroma(
persist_directory=settings.CHROMA_DB_PATH,
embedding_function=self.embeddings
)
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=settings.CHUNK_SIZE,
chunk_overlap=settings.CHUNK_OVERLAP
)
def get_file_checksum(self, file_path: str) -> str:
with open(file_path, "rb") as f:
return hashlib.md5(f.read()).hexdigest()
def extract_text(self, file_path: str) -> str:
ext = os.path.splitext(file_path)[1].lower()
text = ""
if ext == ".pdf":
with open(file_path, "rb") as f:
reader = pypdf.PdfReader(f)
for page in reader.pages:
text += page.extract_text() + "\n"
elif ext == ".docx":
doc = Document(file_path)
for para in doc.paragraphs:
text += para.text + "\n"
elif ext == ".txt":
with open(file_path, "r", encoding="utf-8") as f:
text = f.read()
return text
def ingest_document(self, file_path: str, metadata: dict = None):
text = self.extract_text(file_path)
if not text.strip():
return None
chunks = self.text_splitter.split_text(text)
metadatas = [metadata or {} for _ in chunks]
for meta in metadatas:
meta["source"] = os.path.basename(file_path)
meta["checksum"] = self.get_file_checksum(file_path)
self.vector_store.add_texts(texts=chunks, metadatas=metadatas)
return len(chunks)
def search(self, query: str, k: int = 5):
return self.vector_store.similarity_search(query, k=k)
processor = DocumentProcessor()