-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtext_processor.py
More file actions
111 lines (81 loc) · 3.38 KB
/
Copy pathtext_processor.py
File metadata and controls
111 lines (81 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""Text processing utilities for chunking and cleaning text."""
from typing import List, Dict, Any
from document_loader import Document
class TextChunk:
"""Represents a chunk of text with metadata."""
def __init__(self, text: str, metadata: Dict[str, Any], chunk_id: int):
self.text = text
self.metadata = metadata
self.chunk_id = chunk_id
def __repr__(self):
return f"TextChunk(id={self.chunk_id}, source={self.metadata.get('source', 'unknown')})"
class TextProcessor:
"""Process documents into smaller chunks for embedding."""
def __init__(self, chunk_size: int = 500, chunk_overlap: int = 100):
"""
Initialize text processor.
Args:
chunk_size: Maximum number of characters per chunk
chunk_overlap: Number of characters to overlap between chunks
"""
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
def _split_text(self, text: str) -> List[str]:
"""Split text into chunks with overlap."""
if len(text) <= self.chunk_size:
return [text]
chunks = []
start = 0
while start < len(text):
end = start + self.chunk_size
# Try to break at sentence boundary (., !, ?)
if end < len(text):
# Look for sentence boundary within last 100 chars
search_start = max(start, end - 100)
last_period = text.rfind('.', search_start, end)
last_exclaim = text.rfind('!', search_start, end)
last_question = text.rfind('?', search_start, end)
sentence_end = max(last_period, last_exclaim, last_question)
if sentence_end > start:
end = sentence_end + 1
chunk = text[start:end].strip()
if chunk:
chunks.append(chunk)
# Move start position with overlap
start = end - self.chunk_overlap
return chunks
def process_documents(self, documents: List[Document]) -> List[TextChunk]:
"""
Process documents into text chunks.
Args:
documents: List of documents to process
Returns:
List of text chunks with metadata
"""
chunks = []
chunk_counter = 0
for doc in documents:
# Split document content into chunks
text_chunks = self._split_text(doc.content)
# Create TextChunk objects with metadata
for i, chunk_text in enumerate(text_chunks):
chunk_metadata = {
**doc.metadata,
'chunk_index': i,
'total_chunks': len(text_chunks)
}
chunks.append(TextChunk(chunk_text, chunk_metadata, chunk_counter))
chunk_counter += 1
print(f"Created {len(chunks)} chunks from {len(documents)} documents")
return chunks
if __name__ == "__main__":
# Test the processor
from document_loader import DocumentLoader
loader = DocumentLoader()
docs = loader.load_documents()
processor = TextProcessor(chunk_size=500, chunk_overlap=100)
chunks = processor.process_documents(docs)
print(f"\nSample chunk:")
print(f"Chunk ID: {chunks[0].chunk_id}")
print(f"Source: {chunks[0].metadata.get('source')}")
print(f"Text: {chunks[0].text[:200]}...")