DocuChat / src /data_loader.py
Prateet Mishra
Fix Railway deployment: add built frontend/dist, fix railway.toml
0e78e4d
Raw
History Blame Contribute Delete
6.16 kB
from pathlib import Path
from typing import List, Any
from langchain_community.document_loaders import PyPDFLoader, TextLoader, CSVLoader
from langchain_community.document_loaders import PyMuPDFLoader
from langchain_community.document_loaders import Docx2txtLoader
from langchain_community.document_loaders.excel import UnstructuredExcelLoader
from langchain_community.document_loaders import JSONLoader
SUPPORTED_EXTENSIONS = {".pdf", ".txt", ".csv", ".xlsx", ".docx", ".json"}
def load_single_file(file_path: str, assets_dir: str = "") -> dict:
"""
Load a single file and return text Documents plus multimodal chunks.
Returns:
{
"documents": List[Document], # LangChain docs for text chunking
"multimodal_chunks": List[dict], # table/image chunks (already text, skip splitter)
}
"""
path = Path(file_path).resolve()
suffix = path.suffix.lower()
if suffix not in SUPPORTED_EXTENSIONS:
raise ValueError(f"Unsupported file type: {suffix}")
loader_map = {
".pdf": lambda p: PyMuPDFLoader(str(p)),
".txt": lambda p: TextLoader(str(p)),
".csv": lambda p: CSVLoader(str(p)),
".xlsx": lambda p: UnstructuredExcelLoader(str(p)),
".docx": lambda p: Docx2txtLoader(str(p)),
".json": lambda p: JSONLoader(str(p), jq_schema=".", text_content=False),
}
loader = loader_map[suffix](path)
docs = loader.load()
for doc in docs:
doc.metadata["source_file"] = path.name
doc.metadata["file_type"] = suffix.lstrip(".")
doc.metadata["chunk_type"] = "text"
if "page" not in doc.metadata:
doc.metadata["page"] = 0
# Extract tables and images for PDFs
multimodal_chunks = []
if suffix == ".pdf" and assets_dir:
try:
from src.multimodal_extractor import extract_tables_and_images
multimodal_chunks = extract_tables_and_images(
pdf_path=str(path),
assets_dir=assets_dir,
source_file=path.name,
)
except Exception as e:
print(f"[WARN] Multimodal extraction failed for {path.name}: {e}")
print(f"[INFO] Loaded {len(docs)} text docs + {len(multimodal_chunks)} multimodal chunks from {path.name}")
return {
"documents": docs,
"multimodal_chunks": multimodal_chunks,
}
def load_all_documents(data_dir: str) -> List[Any]:
"""
Load all supported files from the data directory and convert to LangChain document structure.
Supported: PDF, TXT, CSV, Excel, Word, JSON
"""
data_path = Path(data_dir).resolve()
print(f"[DEBUG] Data path: {data_path}")
documents = []
pdf_files = list(data_path.glob('**/*.pdf'))
print(f"[DEBUG] Found {len(pdf_files)} PDF files: {[str(f) for f in pdf_files]}")
for pdf_file in pdf_files:
print(f"[DEBUG] Loading PDF: {pdf_file}")
try:
loader = PyPDFLoader(str(pdf_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} PDF docs from {pdf_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load PDF {pdf_file}: {e}")
txt_files = list(data_path.glob('**/*.txt'))
print(f"[DEBUG] Found {len(txt_files)} TXT files: {[str(f) for f in txt_files]}")
for txt_file in txt_files:
print(f"[DEBUG] Loading TXT: {txt_file}")
try:
loader = TextLoader(str(txt_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} TXT docs from {txt_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load TXT {txt_file}: {e}")
csv_files = list(data_path.glob('**/*.csv'))
print(f"[DEBUG] Found {len(csv_files)} CSV files: {[str(f) for f in csv_files]}")
for csv_file in csv_files:
print(f"[DEBUG] Loading CSV: {csv_file}")
try:
loader = CSVLoader(str(csv_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} CSV docs from {csv_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load CSV {csv_file}: {e}")
xlsx_files = list(data_path.glob('**/*.xlsx'))
print(f"[DEBUG] Found {len(xlsx_files)} Excel files: {[str(f) for f in xlsx_files]}")
for xlsx_file in xlsx_files:
print(f"[DEBUG] Loading Excel: {xlsx_file}")
try:
loader = UnstructuredExcelLoader(str(xlsx_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} Excel docs from {xlsx_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load Excel {xlsx_file}: {e}")
docx_files = list(data_path.glob('**/*.docx'))
print(f"[DEBUG] Found {len(docx_files)} Word files: {[str(f) for f in docx_files]}")
for docx_file in docx_files:
print(f"[DEBUG] Loading Word: {docx_file}")
try:
loader = Docx2txtLoader(str(docx_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} Word docs from {docx_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load Word {docx_file}: {e}")
json_files = list(data_path.glob('**/*.json'))
print(f"[DEBUG] Found {len(json_files)} JSON files: {[str(f) for f in json_files]}")
for json_file in json_files:
print(f"[DEBUG] Loading JSON: {json_file}")
try:
loader = JSONLoader(str(json_file))
loaded = loader.load()
print(f"[DEBUG] Loaded {len(loaded)} JSON docs from {json_file}")
documents.extend(loaded)
except Exception as e:
print(f"[ERROR] Failed to load JSON {json_file}: {e}")
print(f"[DEBUG] Total loaded documents: {len(documents)}")
return documents
if __name__ == "__main__":
docs = load_all_documents("data")
print(f"Loaded {len(docs)} documents.")
print("Example document:", docs[0] if docs else None)