Skip to content

Commit a975771

Browse files
committed
updated
1 parent 9ffaf5c commit a975771

1 file changed

Lines changed: 68 additions & 34 deletions

File tree

utils/vector_store.py

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,39 @@ def count(self) -> int:
8989
# ============================================================================
9090

9191
class PineconeCollection:
92-
"""Pinecone collection wrapper for production."""
92+
"""Pinecone collection wrapper for production with real embeddings."""
9393

94-
EMBEDDING_DIMENSION = 384 # Matches all-MiniLM-L6-v2
94+
EMBEDDING_DIMENSION = 1024 # multilingual-e5-large dimension
95+
EMBEDDING_MODEL = "multilingual-e5-large" # Pinecone's hosted model
9596

9697
def __init__(self, collection_name: str):
97-
"""Initialize Pinecone index."""
98+
"""Initialize Pinecone index with integrated inference."""
9899
from pinecone import Pinecone, ServerlessSpec
99100

100101
self.index_name = collection_name.lower().replace("_", "-")
101102

102103
# Initialize Pinecone client
103104
self.pc = Pinecone(api_key=PINECONE_API_KEY)
104105

105-
# Get or create index
106+
# Get or create index with correct dimension
106107
existing_indexes = [idx.name for idx in self.pc.list_indexes()]
107108

109+
if self.index_name in existing_indexes:
110+
# Check if existing index has correct dimension
111+
try:
112+
existing_index = self.pc.Index(self.index_name)
113+
stats = existing_index.describe_index_stats()
114+
# If dimension is wrong (384 vs 1024), delete and recreate
115+
index_info = self.pc.describe_index(self.index_name)
116+
if hasattr(index_info, 'dimension') and index_info.dimension != self.EMBEDDING_DIMENSION:
117+
logger.warning(f"Index dimension mismatch ({index_info.dimension} vs {self.EMBEDDING_DIMENSION}), recreating...")
118+
self.pc.delete_index(self.index_name)
119+
existing_indexes = [] # Force recreation
120+
except Exception as e:
121+
logger.warning(f"Could not check index dimension: {e}")
122+
108123
if self.index_name not in existing_indexes:
109-
logger.info(f"Creating Pinecone index: {self.index_name}")
124+
logger.info(f"Creating Pinecone index with {self.EMBEDDING_MODEL} embeddings: {self.index_name}")
110125
self.pc.create_index(
111126
name=self.index_name,
112127
dimension=self.EMBEDDING_DIMENSION,
@@ -116,42 +131,60 @@ def __init__(self, collection_name: str):
116131
region=os.getenv("PINECONE_ENVIRONMENT", "us-east-1")
117132
)
118133
)
134+
# Wait for index to be ready
135+
import time
136+
time.sleep(5)
119137

120138
self.index = self.pc.Index(self.index_name)
121-
logger.info(f"✅ Pinecone index '{self.index_name}' initialized (production mode)")
139+
140+
# Use Pinecone's inference API for embeddings
141+
self.use_inference_api = True
142+
logger.info(f"✅ Pinecone index '{self.index_name}' initialized with {self.EMBEDDING_MODEL} embeddings")
143+
144+
def _get_embeddings(self, texts: List[str]) -> List[List[float]]:
145+
"""Get embeddings using Pinecone's inference API."""
146+
try:
147+
# Use Pinecone's inference API
148+
embeddings_response = self.pc.inference.embed(
149+
model=self.EMBEDDING_MODEL,
150+
inputs=texts,
151+
parameters={"input_type": "passage"}
152+
)
153+
return [e.values for e in embeddings_response.data]
154+
except Exception as e:
155+
logger.warning(f"Pinecone inference failed: {e}, using fallback")
156+
return self._fallback_embeddings(texts)
122157

123-
def _text_to_vector(self, text: str) -> List[float]:
124-
"""
125-
Simple text embedding using hash-based approach.
126-
Lightweight alternative to loading ML models.
127-
"""
158+
def _fallback_embeddings(self, texts: List[str]) -> List[List[float]]:
159+
"""Fallback: simple keyword-based pseudo-embeddings."""
128160
import hashlib
129161
import math
130162

131-
text = text.lower().strip()
132-
vector = []
133-
134-
for i in range(self.EMBEDDING_DIMENSION):
135-
hash_input = f"{text}_{i}".encode('utf-8')
136-
hash_value = int(hashlib.md5(hash_input).hexdigest(), 16)
137-
normalized = (hash_value % 10000) / 5000 - 1.0
138-
vector.append(normalized)
139-
140-
# Normalize to unit length
141-
magnitude = math.sqrt(sum(x*x for x in vector))
142-
if magnitude > 0:
143-
vector = [x / magnitude for x in vector]
144-
145-
return vector
163+
embeddings = []
164+
for text in texts:
165+
text = text.lower().strip()
166+
vector = []
167+
for i in range(self.EMBEDDING_DIMENSION):
168+
hash_input = f"{text}_{i}".encode('utf-8')
169+
hash_value = int(hashlib.md5(hash_input).hexdigest(), 16)
170+
normalized = (hash_value % 10000) / 5000 - 1.0
171+
vector.append(normalized)
172+
magnitude = math.sqrt(sum(x*x for x in vector))
173+
if magnitude > 0:
174+
vector = [x / magnitude for x in vector]
175+
embeddings.append(vector)
176+
return embeddings
146177

147178
def add(self, ids: List[str], documents: List[str], metadatas: List[Dict] = None):
148-
"""Add documents to Pinecone."""
179+
"""Add documents to Pinecone with real embeddings."""
149180
if metadatas is None:
150181
metadatas = [{} for _ in ids]
151182

183+
# Get embeddings for all documents
184+
embeddings = self._get_embeddings(documents)
185+
152186
vectors = []
153-
for doc_id, doc, meta in zip(ids, documents, metadatas):
154-
embedding = self._text_to_vector(doc)
187+
for doc_id, doc, meta, embedding in zip(ids, documents, metadatas, embeddings):
155188
meta_with_doc = {**meta, "_document": doc[:1000]}
156189
vectors.append({
157190
"id": doc_id,
@@ -165,18 +198,19 @@ def add(self, ids: List[str], documents: List[str], metadatas: List[Dict] = None
165198
batch = vectors[i:i + batch_size]
166199
self.index.upsert(vectors=batch)
167200

168-
logger.info(f"✅ Added {len(ids)} documents to Pinecone")
201+
logger.info(f"✅ Added {len(ids)} documents to Pinecone with semantic embeddings")
169202

170203
def query(self, query_texts: List[str], n_results: int = 3) -> Dict[str, List]:
171-
"""Query Pinecone for similar documents."""
204+
"""Query Pinecone for similar documents using real embeddings."""
172205
all_ids = []
173206
all_documents = []
174207
all_metadatas = []
175208
all_distances = []
176209

177-
for query_text in query_texts:
178-
query_embedding = self._text_to_vector(query_text)
179-
210+
# Get query embeddings
211+
query_embeddings = self._get_embeddings(query_texts)
212+
213+
for query_embedding in query_embeddings:
180214
results = self.index.query(
181215
vector=query_embedding,
182216
top_k=n_results,

0 commit comments

Comments
 (0)