dnj0 commited on
Commit
a6e26b8
Β·
verified Β·
1 Parent(s): dd7abcc

Update src/vector_store.py

Browse files
Files changed (1) hide show
  1. src/vector_store.py +86 -33
src/vector_store.py CHANGED
@@ -1,20 +1,22 @@
1
  """
2
- Vector Store and Embeddings Module using ChromaDB with CLIP embeddings
 
3
  """
4
  import os
5
  import json
6
  from typing import List, Dict
7
  import chromadb
8
- from chromadb.config import Settings
9
  from sentence_transformers import SentenceTransformer
10
  import numpy as np
11
  from config import CHROMA_DB_PATH, EMBEDDING_MODEL, EMBEDDING_DIM
12
 
13
 
14
  class CLIPEmbedder:
15
- """Custom embedder using CLIP model for multimodal content"""
16
  def __init__(self, model_name: str = EMBEDDING_MODEL):
 
17
  self.model = SentenceTransformer(model_name)
 
18
 
19
  def embed(self, text: str) -> List[float]:
20
  """Generate embedding for text"""
@@ -36,21 +38,39 @@ class CLIPEmbedder:
36
 
37
 
38
  class VectorStore:
39
- """Vector store manager using ChromaDB"""
40
  def __init__(self):
41
  self.persist_directory = CHROMA_DB_PATH
42
  self.embedder = CLIPEmbedder()
43
 
44
- # Initialize ChromaDB with persistent storage
45
- self.client = chromadb.PersistentClient(
46
- path=self.persist_directory
47
- )
 
 
 
 
 
 
 
 
 
 
48
 
49
  # Get or create collection
50
- self.collection = self.client.get_or_create_collection(
51
- name="multimodal_rag",
52
- metadata={"hnsw:space": "cosine"}
53
- )
 
 
 
 
 
 
 
 
54
 
55
  def add_documents(self, documents: List[Dict], doc_id: str):
56
  """Add documents to vector store"""
@@ -58,6 +78,8 @@ class VectorStore:
58
  metadatas = []
59
  ids = []
60
 
 
 
61
  # Add text chunks
62
  if 'text' in documents and documents['text']:
63
  chunks = self._chunk_text(documents['text'], chunk_size=1000, overlap=200)
@@ -69,9 +91,11 @@ class VectorStore:
69
  'chunk_idx': str(idx)
70
  })
71
  ids.append(f"{doc_id}_text_{idx}")
 
72
 
73
  # Add image descriptions and OCR text
74
  if 'images' in documents:
 
75
  for idx, image_data in enumerate(documents['images']):
76
  if image_data.get('ocr_text'):
77
  texts.append(f"Image {idx}: {image_data['ocr_text']}")
@@ -82,31 +106,44 @@ class VectorStore:
82
  'image_path': image_data.get('path', '')
83
  })
84
  ids.append(f"{doc_id}_image_{idx}")
 
 
 
85
 
86
  # Add table content
87
  if 'tables' in documents:
 
88
  for idx, table_data in enumerate(documents['tables']):
89
- texts.append(f"Table {idx}: {table_data.get('content', '')}")
90
- metadatas.append({
91
- 'doc_id': doc_id,
92
- 'type': 'table',
93
- 'table_idx': str(idx)
94
- })
95
- ids.append(f"{doc_id}_table_{idx}")
 
 
 
 
96
 
97
  if texts:
98
  # Generate embeddings
 
99
  embeddings = self.embedder.embed_batch(texts)
100
 
101
  # Add to collection
102
- self.collection.add(
103
- ids=ids,
104
- documents=texts,
105
- embeddings=embeddings,
106
- metadatas=metadatas
107
- )
108
-
109
- print(f"Added {len(texts)} documents to vector store for {doc_id}")
 
 
 
 
110
 
111
  def search(self, query: str, n_results: int = 5) -> List[Dict]:
112
  """Search vector store for similar documents"""
@@ -154,7 +191,8 @@ class VectorStore:
154
  return {
155
  'name': 'multimodal_rag',
156
  'count': count,
157
- 'status': 'active'
 
158
  }
159
  except Exception as e:
160
  print(f"Error getting collection info: {e}")
@@ -167,14 +205,29 @@ class VectorStore:
167
  results = self.collection.get(where={'doc_id': doc_id})
168
  if results['ids']:
169
  self.collection.delete(ids=results['ids'])
170
- print(f"Deleted {len(results['ids'])} documents for {doc_id}")
 
 
171
  except Exception as e:
172
  print(f"Error deleting documents: {e}")
173
 
174
  def persist(self):
175
- """Persist vector store to disk"""
 
 
 
 
 
 
 
 
176
  try:
177
- self.client.persist()
178
- print("Vector store persisted to disk")
 
 
 
 
 
179
  except Exception as e:
180
- print(f"Error persisting vector store: {e}")
 
1
  """
2
+ Vector Store and Embeddings Module using ChromaDB with sentence-transformers
3
+ UPDATED for ChromaDB v0.4.22+ (auto-persist, no manual persist needed)
4
  """
5
  import os
6
  import json
7
  from typing import List, Dict
8
  import chromadb
 
9
  from sentence_transformers import SentenceTransformer
10
  import numpy as np
11
  from config import CHROMA_DB_PATH, EMBEDDING_MODEL, EMBEDDING_DIM
12
 
13
 
14
  class CLIPEmbedder:
15
+ """Custom embedder using sentence-transformers for multimodal content"""
16
  def __init__(self, model_name: str = EMBEDDING_MODEL):
17
+ print(f"πŸ”„ Loading embedding model: {model_name}")
18
  self.model = SentenceTransformer(model_name)
19
+ print(f"βœ… Model loaded successfully")
20
 
21
  def embed(self, text: str) -> List[float]:
22
  """Generate embedding for text"""
 
38
 
39
 
40
  class VectorStore:
41
+ """Vector store manager using ChromaDB (v0.4.22+ with auto-persist)"""
42
  def __init__(self):
43
  self.persist_directory = CHROMA_DB_PATH
44
  self.embedder = CLIPEmbedder()
45
 
46
+ print(f"\nπŸ”„ Initializing ChromaDB at: {self.persist_directory}")
47
+
48
+ # NEW ChromaDB v0.4.22+ - PersistentClient auto-persists
49
+ try:
50
+ self.client = chromadb.PersistentClient(
51
+ path=self.persist_directory
52
+ )
53
+ print(f"βœ… ChromaDB PersistentClient initialized")
54
+ except Exception as e:
55
+ print(f"❌ Error initializing ChromaDB: {e}")
56
+ print(f"Trying fallback initialization...")
57
+ self.client = chromadb.PersistentClient(
58
+ path=self.persist_directory
59
+ )
60
 
61
  # Get or create collection
62
+ try:
63
+ self.collection = self.client.get_or_create_collection(
64
+ name="multimodal_rag",
65
+ metadata={"hnsw:space": "cosine"}
66
+ )
67
+ count = self.collection.count()
68
+ print(f"βœ… Collection loaded: {count} items in store")
69
+ except Exception as e:
70
+ print(f"Error with collection: {e}")
71
+ self.collection = self.client.get_or_create_collection(
72
+ name="multimodal_rag"
73
+ )
74
 
75
  def add_documents(self, documents: List[Dict], doc_id: str):
76
  """Add documents to vector store"""
 
78
  metadatas = []
79
  ids = []
80
 
81
+ print(f"\nπŸ“š Adding documents for: {doc_id}")
82
+
83
  # Add text chunks
84
  if 'text' in documents and documents['text']:
85
  chunks = self._chunk_text(documents['text'], chunk_size=1000, overlap=200)
 
91
  'chunk_idx': str(idx)
92
  })
93
  ids.append(f"{doc_id}_text_{idx}")
94
+ print(f" βœ… Text: {len(chunks)} chunks")
95
 
96
  # Add image descriptions and OCR text
97
  if 'images' in documents:
98
+ image_count = 0
99
  for idx, image_data in enumerate(documents['images']):
100
  if image_data.get('ocr_text'):
101
  texts.append(f"Image {idx}: {image_data['ocr_text']}")
 
106
  'image_path': image_data.get('path', '')
107
  })
108
  ids.append(f"{doc_id}_image_{idx}")
109
+ image_count += 1
110
+ if image_count > 0:
111
+ print(f" βœ… Images: {image_count} with OCR text")
112
 
113
  # Add table content
114
  if 'tables' in documents:
115
+ table_count = 0
116
  for idx, table_data in enumerate(documents['tables']):
117
+ if table_data.get('content'):
118
+ texts.append(f"Table {idx}: {table_data.get('content', '')}")
119
+ metadatas.append({
120
+ 'doc_id': doc_id,
121
+ 'type': 'table',
122
+ 'table_idx': str(idx)
123
+ })
124
+ ids.append(f"{doc_id}_table_{idx}")
125
+ table_count += 1
126
+ if table_count > 0:
127
+ print(f" βœ… Tables: {table_count}")
128
 
129
  if texts:
130
  # Generate embeddings
131
+ print(f" πŸ”„ Generating {len(texts)} embeddings...")
132
  embeddings = self.embedder.embed_batch(texts)
133
 
134
  # Add to collection
135
+ try:
136
+ self.collection.add(
137
+ ids=ids,
138
+ documents=texts,
139
+ embeddings=embeddings,
140
+ metadatas=metadatas
141
+ )
142
+ print(f"βœ… Successfully added {len(texts)} items to vector store")
143
+ # Auto-persist happens here
144
+ print(f"βœ… Data persisted automatically to: {self.persist_directory}")
145
+ except Exception as e:
146
+ print(f"❌ Error adding to collection: {e}")
147
 
148
  def search(self, query: str, n_results: int = 5) -> List[Dict]:
149
  """Search vector store for similar documents"""
 
191
  return {
192
  'name': 'multimodal_rag',
193
  'count': count,
194
+ 'status': 'active',
195
+ 'persist_path': self.persist_directory
196
  }
197
  except Exception as e:
198
  print(f"Error getting collection info: {e}")
 
205
  results = self.collection.get(where={'doc_id': doc_id})
206
  if results['ids']:
207
  self.collection.delete(ids=results['ids'])
208
+ print(f"βœ… Deleted {len(results['ids'])} documents for {doc_id}")
209
+ # Auto-persist on delete
210
+ print(f"βœ… Changes persisted automatically")
211
  except Exception as e:
212
  print(f"Error deleting documents: {e}")
213
 
214
  def persist(self):
215
+ """
216
+ No-op for compatibility with older code.
217
+ ChromaDB v0.4.22+ uses PersistentClient which auto-persists.
218
+ This method kept for backward compatibility.
219
+ """
220
+ print("βœ… Vector store is using auto-persist (no manual persist needed)")
221
+
222
+ def clear_all(self):
223
+ """Clear all documents from collection"""
224
  try:
225
+ # Delete collection and recreate
226
+ self.client.delete_collection(name="multimodal_rag")
227
+ self.collection = self.client.get_or_create_collection(
228
+ name="multimodal_rag",
229
+ metadata={"hnsw:space": "cosine"}
230
+ )
231
+ print("βœ… Collection cleared and reset")
232
  except Exception as e:
233
+ print(f"Error clearing collection: {e}")