Spaces:
Sleeping
Sleeping
Merge branch 'main' of https://github.com/Deepesh70/Book_Model into deep
Browse files- .gitignore +3 -0
- Data/Abraham-Silberschatz-Henry-F.-Korth-S.-Sudarshan-Database-System-Concepts-McGraw-Hill-Education-2019.pdf +0 -3
- Data/Fundamentals_of_Database_Systems_6th_Edition-1.pdf +0 -3
- Data/Hands On Machine Learning with Scikit Learn and TensorFlow.pdf +0 -3
- Data/dbms-peter-rob.pdf +0 -3
- Data/machine_learning.txt +0 -15
- Data/python_intro.txt +0 -13
- quick_test.py +86 -0
- src/cleaner.py +50 -0
- src/data_loader.py +16 -1
- src/embedding.py +59 -10
- src/vectorstore.py +7 -2
.gitignore
CHANGED
|
@@ -24,5 +24,8 @@ __pycache__/
|
|
| 24 |
# faiss_store/
|
| 25 |
vector_store/
|
| 26 |
|
|
|
|
|
|
|
|
|
|
| 27 |
# LangGraph
|
| 28 |
.langgraph_api/
|
|
|
|
| 24 |
# faiss_store/
|
| 25 |
vector_store/
|
| 26 |
|
| 27 |
+
# Keep raw source books local only
|
| 28 |
+
Data/
|
| 29 |
+
|
| 30 |
# LangGraph
|
| 31 |
.langgraph_api/
|
Data/Abraham-Silberschatz-Henry-F.-Korth-S.-Sudarshan-Database-System-Concepts-McGraw-Hill-Education-2019.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:dfbdff8a0b2eb32035f68105cf823ab788743d08036416fe81e2e19214e44aaf
|
| 3 |
-
size 17163073
|
|
|
|
|
|
|
|
|
|
|
|
Data/Fundamentals_of_Database_Systems_6th_Edition-1.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:e3f0d7d7cd8bfe6973d12acc9301a9b175932c281aac12e452b1100a0ccbfcaa
|
| 3 |
-
size 9118471
|
|
|
|
|
|
|
|
|
|
|
|
Data/Hands On Machine Learning with Scikit Learn and TensorFlow.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:bcbfb1a52ec75e8d248f54de2d8de74fed3985dbd99a9e15c057361fb2398e7a
|
| 3 |
-
size 7551093
|
|
|
|
|
|
|
|
|
|
|
|
Data/dbms-peter-rob.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:59fe9d07abffc730b68dfcd851652299ec437fc0821852bb5c1fb221382c7062
|
| 3 |
-
size 56581782
|
|
|
|
|
|
|
|
|
|
|
|
Data/machine_learning.txt
DELETED
|
@@ -1,15 +0,0 @@
|
|
| 1 |
-
Machine Learning Basics
|
| 2 |
-
|
| 3 |
-
Machine learning is a subset of artificial intelligence that enables systems to learn and improve
|
| 4 |
-
from experience without being explicitly programmed. It focuses on developing computer programs
|
| 5 |
-
that can access data and use it to learn for themselves.
|
| 6 |
-
|
| 7 |
-
Types of Machine Learning:
|
| 8 |
-
1. Supervised Learning: Learning with labeled data
|
| 9 |
-
2. Unsupervised Learning: Finding patterns in unlabeled data
|
| 10 |
-
3. Reinforcement Learning: Learning through rewards and penalties
|
| 11 |
-
|
| 12 |
-
Applications include image recognition, speech processing, and recommendation systems
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Data/python_intro.txt
DELETED
|
@@ -1,13 +0,0 @@
|
|
| 1 |
-
Python Programming Introduction
|
| 2 |
-
|
| 3 |
-
Python is a high-level, interpreted programming language known for its simplicity and readability.
|
| 4 |
-
Created by Guido van Rossum and first released in 1991, Python has become one of the most popular
|
| 5 |
-
programming languages in the world.
|
| 6 |
-
|
| 7 |
-
Key Features:
|
| 8 |
-
- Easy to learn and use
|
| 9 |
-
- Extensive standard library
|
| 10 |
-
- Cross-platform compatibility
|
| 11 |
-
- Strong community support
|
| 12 |
-
|
| 13 |
-
Python is widely used in web development, data science, artificial intelligence, and automation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
quick_test.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Quick test to verify the updated embedding pipeline works correctly."""
|
| 2 |
+
import sys
|
| 3 |
+
import os
|
| 4 |
+
sys.path.insert(0, os.getcwd())
|
| 5 |
+
|
| 6 |
+
from langchain_core.documents import Document
|
| 7 |
+
from src.embedding import EmbeddingPipeline
|
| 8 |
+
from src.vectorstore import FaissVectorStore
|
| 9 |
+
from src.cleaner import DocumentCleaner
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
def test_pipeline():
|
| 13 |
+
print("=" * 60)
|
| 14 |
+
print("QUICK PIPELINE VERIFICATION TEST")
|
| 15 |
+
print("=" * 60)
|
| 16 |
+
|
| 17 |
+
# 1. Test DocumentCleaner
|
| 18 |
+
print("\n--- Test 1: DocumentCleaner ---")
|
| 19 |
+
cleaner = DocumentCleaner(min_length=10)
|
| 20 |
+
|
| 21 |
+
test_docs = [
|
| 22 |
+
Document(page_content="This is a valid document with real content about databases."),
|
| 23 |
+
Document(page_content="Short"), # too short
|
| 24 |
+
Document(page_content=""), # empty
|
| 25 |
+
Document(page_content=None), # None - this would crash old code
|
| 26 |
+
Document(page_content="Another valid document explaining SQL queries and joins."),
|
| 27 |
+
Document(page_content=" \n\n\t "), # whitespace only
|
| 28 |
+
]
|
| 29 |
+
|
| 30 |
+
cleaned = cleaner.clean_documents(test_docs)
|
| 31 |
+
print(f" Input: {len(test_docs)} docs -> Cleaned: {len(cleaned)} docs")
|
| 32 |
+
assert len(cleaned) == 2, f"Expected 2 valid docs, got {len(cleaned)}"
|
| 33 |
+
print(" ✅ DocumentCleaner works correctly!")
|
| 34 |
+
|
| 35 |
+
# 2. Test EmbeddingPipeline with cleaning + batching
|
| 36 |
+
print("\n--- Test 2: EmbeddingPipeline (clean + chunk + embed) ---")
|
| 37 |
+
|
| 38 |
+
# Create realistic documents like what PyPDFLoader returns
|
| 39 |
+
docs = [
|
| 40 |
+
Document(page_content="Database Management Systems provide an organized way to store and manage data. " * 5),
|
| 41 |
+
Document(page_content="SQL is a standard language for accessing and manipulating databases. " * 5),
|
| 42 |
+
Document(page_content=None), # Simulates a bad PDF page
|
| 43 |
+
Document(page_content="Machine Learning is a branch of artificial intelligence focused on algorithms. " * 5),
|
| 44 |
+
Document(page_content=""), # Empty page
|
| 45 |
+
Document(page_content="x"), # Too short - should be cleaned
|
| 46 |
+
]
|
| 47 |
+
|
| 48 |
+
pipe = EmbeddingPipeline(chunk_size=200, chunk_overlap=50)
|
| 49 |
+
chunks = pipe.chunk_documents(docs)
|
| 50 |
+
print(f" Chunks created: {len(chunks)}")
|
| 51 |
+
|
| 52 |
+
embeddings, valid_chunks = pipe.embed_chunks(chunks, batch_size=2)
|
| 53 |
+
print(f" Embeddings shape: {embeddings.shape}")
|
| 54 |
+
print(f" Valid chunks: {len(valid_chunks)}")
|
| 55 |
+
assert embeddings.shape[0] == len(valid_chunks), "Embeddings and chunks count must match!"
|
| 56 |
+
assert embeddings.shape[0] > 0, "Should have some embeddings!"
|
| 57 |
+
print(" ✅ EmbeddingPipeline works correctly!")
|
| 58 |
+
|
| 59 |
+
# 3. Test FaissVectorStore integration
|
| 60 |
+
print("\n--- Test 3: FaissVectorStore build + query ---")
|
| 61 |
+
test_store_dir = "test_faiss_store"
|
| 62 |
+
store = FaissVectorStore(persist_dir=test_store_dir, chunk_size=200, chunk_overlap=50)
|
| 63 |
+
store.build_from_documents(docs)
|
| 64 |
+
|
| 65 |
+
if store.index is not None:
|
| 66 |
+
results = store.query("What is a database?", top_k=2)
|
| 67 |
+
print(f" Query returned {len(results)} results")
|
| 68 |
+
for r in results:
|
| 69 |
+
snippet = r['metadata']['texts'][:80] if r.get('metadata') and r['metadata'].get('texts') else "None"
|
| 70 |
+
print(f" Distance: {r['distance']:.4f} | {snippet}...")
|
| 71 |
+
print(" ✅ FaissVectorStore works correctly!")
|
| 72 |
+
else:
|
| 73 |
+
print(" ⚠️ Vector store index is empty")
|
| 74 |
+
|
| 75 |
+
# Cleanup
|
| 76 |
+
import shutil
|
| 77 |
+
if os.path.exists(test_store_dir):
|
| 78 |
+
shutil.rmtree(test_store_dir)
|
| 79 |
+
|
| 80 |
+
print("\n" + "=" * 60)
|
| 81 |
+
print("🎉 ALL TESTS PASSED! Pipeline is working correctly.")
|
| 82 |
+
print("=" * 60)
|
| 83 |
+
print("\nYou can now run: python main.py")
|
| 84 |
+
|
| 85 |
+
if __name__ == "__main__":
|
| 86 |
+
test_pipeline()
|
src/cleaner.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from typing import List, Any
|
| 3 |
+
import logging
|
| 4 |
+
|
| 5 |
+
logger = logging.getLogger(__name__)
|
| 6 |
+
|
| 7 |
+
class DocumentCleaner:
|
| 8 |
+
def __init__(self, min_length: int = 50):
|
| 9 |
+
self.min_length = min_length
|
| 10 |
+
# Regex for common PDF artifacts or excessive whitespace
|
| 11 |
+
self.whitespace_pattern = re.compile(r'\s+')
|
| 12 |
+
self.control_chars_pattern = re.compile(r'[\x00-\x1f\x7f-\x9f]')
|
| 13 |
+
|
| 14 |
+
def clean_text(self, text: str) -> str:
|
| 15 |
+
if not text:
|
| 16 |
+
return ""
|
| 17 |
+
|
| 18 |
+
# Safely remove surrogate code points that crash Windows terminals
|
| 19 |
+
text = text.encode('utf-8', 'ignore').decode('utf-8')
|
| 20 |
+
|
| 21 |
+
# Remove control characters
|
| 22 |
+
text = self.control_chars_pattern.sub('', text)
|
| 23 |
+
|
| 24 |
+
# Normalize whitespace (replace newlines/tabs with space and collapse)
|
| 25 |
+
text = self.whitespace_pattern.sub(' ', text).strip()
|
| 26 |
+
|
| 27 |
+
return text
|
| 28 |
+
|
| 29 |
+
def clean_documents(self, documents: List[Any]) -> List[Any]:
|
| 30 |
+
"""
|
| 31 |
+
Cleans a list of LangChain Document objects.
|
| 32 |
+
Filters out documents that are too short after cleaning.
|
| 33 |
+
"""
|
| 34 |
+
cleaned_docs = []
|
| 35 |
+
for doc in documents:
|
| 36 |
+
if not hasattr(doc, 'page_content') or doc.page_content is None:
|
| 37 |
+
continue
|
| 38 |
+
|
| 39 |
+
cleaned_text = self.clean_text(str(doc.page_content))
|
| 40 |
+
|
| 41 |
+
if len(cleaned_text) >= self.min_length:
|
| 42 |
+
# Update the document content with cleaned version
|
| 43 |
+
doc.page_content = cleaned_text
|
| 44 |
+
cleaned_docs.append(doc)
|
| 45 |
+
|
| 46 |
+
print(f"[INFO] Data Cleaning: {len(documents)} -> {len(cleaned_docs)} documents (filtered {len(documents) - len(cleaned_docs)})")
|
| 47 |
+
return cleaned_docs
|
| 48 |
+
|
| 49 |
+
def get_default_cleaner():
|
| 50 |
+
return DocumentCleaner()
|
src/data_loader.py
CHANGED
|
@@ -118,7 +118,22 @@ def load_all_documents(data_dir: str) -> List[Any] :
|
|
| 118 |
|
| 119 |
|
| 120 |
print(f"[DEBUG] Total Loaded Documents : {len(document)}")
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
|
| 124 |
if __name__ == '__main__':
|
|
|
|
| 118 |
|
| 119 |
|
| 120 |
print(f"[DEBUG] Total Loaded Documents : {len(document)}")
|
| 121 |
+
|
| 122 |
+
# Filter out documents with None or non-string page_content
|
| 123 |
+
valid_documents = []
|
| 124 |
+
invalid_count = 0
|
| 125 |
+
for doc in document:
|
| 126 |
+
content = getattr(doc, 'page_content', None)
|
| 127 |
+
if content is not None and isinstance(content, str):
|
| 128 |
+
valid_documents.append(doc)
|
| 129 |
+
else:
|
| 130 |
+
invalid_count += 1
|
| 131 |
+
|
| 132 |
+
if invalid_count > 0:
|
| 133 |
+
print(f"[WARNING] Filtered out {invalid_count} documents with invalid page_content (None or non-string)")
|
| 134 |
+
|
| 135 |
+
print(f"[DEBUG] Valid Documents after filtering : {len(valid_documents)}")
|
| 136 |
+
return valid_documents
|
| 137 |
|
| 138 |
|
| 139 |
if __name__ == '__main__':
|
src/embedding.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import List, Any, Optional
|
|
| 2 |
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
| 3 |
from sentence_transformers import SentenceTransformer
|
| 4 |
import numpy as np
|
| 5 |
-
from src.
|
| 6 |
|
| 7 |
class EmbeddingPipeline:
|
| 8 |
def __init__(self, model_name: str = 'all-MiniLM-L6-v2', chunk_size: int = 1000, chunk_overlap: int = 200):
|
|
@@ -10,26 +10,75 @@ class EmbeddingPipeline:
|
|
| 10 |
self.chunk_size = chunk_size
|
| 11 |
self.chunk_overlap = chunk_overlap
|
| 12 |
self.model = SentenceTransformer(model_name)
|
|
|
|
| 13 |
print(f"[INFO] Loaded embedding model: {model_name}")
|
| 14 |
|
| 15 |
def chunk_documents(self, documents: List[Any]) -> List[Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
splitter = RecursiveCharacterTextSplitter(
|
| 17 |
chunk_size=self.chunk_size,
|
| 18 |
chunk_overlap=self.chunk_overlap,
|
| 19 |
length_function=len,
|
| 20 |
-
separators=["\n\n", "\n", " "
|
| 21 |
)
|
| 22 |
|
| 23 |
-
chunks = splitter.split_documents(
|
| 24 |
-
print(f"[INFO] Split {len(
|
| 25 |
return chunks
|
| 26 |
|
| 27 |
-
def embed_chunks(self, chunks: List[Any]) -> np.ndarray:
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
if __name__ == "__main__":
|
| 35 |
docs = load_all_documents('Research/data/pdf')
|
|
|
|
| 2 |
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
| 3 |
from sentence_transformers import SentenceTransformer
|
| 4 |
import numpy as np
|
| 5 |
+
from src.cleaner import get_default_cleaner
|
| 6 |
|
| 7 |
class EmbeddingPipeline:
|
| 8 |
def __init__(self, model_name: str = 'all-MiniLM-L6-v2', chunk_size: int = 1000, chunk_overlap: int = 200):
|
|
|
|
| 10 |
self.chunk_size = chunk_size
|
| 11 |
self.chunk_overlap = chunk_overlap
|
| 12 |
self.model = SentenceTransformer(model_name)
|
| 13 |
+
self.cleaner = get_default_cleaner()
|
| 14 |
print(f"[INFO] Loaded embedding model: {model_name}")
|
| 15 |
|
| 16 |
def chunk_documents(self, documents: List[Any]) -> List[Any]:
|
| 17 |
+
# 1. Clean documents first
|
| 18 |
+
cleaned_docs = self.cleaner.clean_documents(documents)
|
| 19 |
+
|
| 20 |
+
# 2. Split into chunks
|
| 21 |
splitter = RecursiveCharacterTextSplitter(
|
| 22 |
chunk_size=self.chunk_size,
|
| 23 |
chunk_overlap=self.chunk_overlap,
|
| 24 |
length_function=len,
|
| 25 |
+
separators=["\n\n", "\n", " "]
|
| 26 |
)
|
| 27 |
|
| 28 |
+
chunks = splitter.split_documents(cleaned_docs)
|
| 29 |
+
print(f"[INFO] Split {len(cleaned_docs)} documents into {len(chunks)} chunks.")
|
| 30 |
return chunks
|
| 31 |
|
| 32 |
+
def embed_chunks(self, chunks: List[Any], batch_size: int = 500) -> tuple[np.ndarray, List[Any]]:
|
| 33 |
+
"""
|
| 34 |
+
Embeds chunks in batches for stability and better error reporting.
|
| 35 |
+
Returns a tuple of (embeddings_array, valid_chunks_list).
|
| 36 |
+
"""
|
| 37 |
+
valid_chunks = []
|
| 38 |
+
all_embeddings = []
|
| 39 |
+
|
| 40 |
+
print(f"[INFO] Generating embeddings for {len(chunks)} chunks in batches of {batch_size}...")
|
| 41 |
+
|
| 42 |
+
for i in range(0, len(chunks), batch_size):
|
| 43 |
+
batch = chunks[i:i+batch_size]
|
| 44 |
+
batch_texts = []
|
| 45 |
+
current_batch_chunks = []
|
| 46 |
+
|
| 47 |
+
# Additional validation per chunk
|
| 48 |
+
for chunk in batch:
|
| 49 |
+
content = getattr(chunk, 'page_content', None)
|
| 50 |
+
if content is not None and isinstance(content, str) and content.strip():
|
| 51 |
+
batch_texts.append(content)
|
| 52 |
+
current_batch_chunks.append(chunk)
|
| 53 |
+
|
| 54 |
+
if not batch_texts:
|
| 55 |
+
continue
|
| 56 |
+
|
| 57 |
+
try:
|
| 58 |
+
batch_embeddings = self.model.encode(batch_texts, show_progress_bar=False)
|
| 59 |
+
all_embeddings.append(batch_embeddings)
|
| 60 |
+
valid_chunks.extend(current_batch_chunks)
|
| 61 |
+
except Exception as e:
|
| 62 |
+
print(f"[ERROR] Failed to embed batch starting at index {i}. Error: {e}")
|
| 63 |
+
print("[INFO] Attempting to identify problematic chunk in batch...")
|
| 64 |
+
for j, text in enumerate(batch_texts):
|
| 65 |
+
try:
|
| 66 |
+
self.model.encode([text], show_progress_bar=False)
|
| 67 |
+
except Exception as ex:
|
| 68 |
+
print(f"[ERROR] Problematic chunk found at original index {i+j}!")
|
| 69 |
+
# Safely encode for windows terminal printing to avoid crashes
|
| 70 |
+
safe_text = text[:100].encode('ascii', 'replace').decode('ascii')
|
| 71 |
+
print(f"[DEBUG] Content snippet: {safe_text}...")
|
| 72 |
+
# We skip this specific chunk and continue
|
| 73 |
+
continue
|
| 74 |
+
|
| 75 |
+
if not all_embeddings:
|
| 76 |
+
print("[WARNING] No embeddings were generated.")
|
| 77 |
+
return np.array([]), []
|
| 78 |
+
|
| 79 |
+
final_embeddings = np.vstack(all_embeddings)
|
| 80 |
+
print(f"[INFO] Total valid embeddings: {final_embeddings.shape[0]} / {len(chunks)}")
|
| 81 |
+
return final_embeddings, valid_chunks
|
| 82 |
|
| 83 |
if __name__ == "__main__":
|
| 84 |
docs = load_all_documents('Research/data/pdf')
|
src/vectorstore.py
CHANGED
|
@@ -32,8 +32,13 @@ class FaissVectorStore:
|
|
| 32 |
chunk_overlap=self.chunk_overlap,
|
| 33 |
)
|
| 34 |
chunks = emb_pipe.chunk_documents(documents)
|
| 35 |
-
embeddings = emb_pipe.embed_chunks(chunks)
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
self.add_embeddings(np.array(embeddings).astype("float32"), metadatas)
|
| 38 |
self.save()
|
| 39 |
print(f"[INFO] Vector Store built and saved to {self.persist_dir}")
|
|
|
|
| 32 |
chunk_overlap=self.chunk_overlap,
|
| 33 |
)
|
| 34 |
chunks = emb_pipe.chunk_documents(documents)
|
| 35 |
+
embeddings, valid_chunks = emb_pipe.embed_chunks(chunks)
|
| 36 |
+
|
| 37 |
+
if len(valid_chunks) == 0:
|
| 38 |
+
print("[WARNING] No valid chunks were embedded. Vector store will not be updated.")
|
| 39 |
+
return
|
| 40 |
+
|
| 41 |
+
metadatas = [{"texts": chunk.page_content} for chunk in valid_chunks]
|
| 42 |
self.add_embeddings(np.array(embeddings).astype("float32"), metadatas)
|
| 43 |
self.save()
|
| 44 |
print(f"[INFO] Vector Store built and saved to {self.persist_dir}")
|