mem0ai-azure-mysql 0.1.115__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. mem0/__init__.py +6 -0
  2. mem0/client/__init__.py +0 -0
  3. mem0/client/main.py +1535 -0
  4. mem0/client/project.py +860 -0
  5. mem0/client/utils.py +29 -0
  6. mem0/configs/__init__.py +0 -0
  7. mem0/configs/base.py +90 -0
  8. mem0/configs/dbs/__init__.py +4 -0
  9. mem0/configs/dbs/base.py +41 -0
  10. mem0/configs/dbs/mysql.py +25 -0
  11. mem0/configs/embeddings/__init__.py +0 -0
  12. mem0/configs/embeddings/base.py +108 -0
  13. mem0/configs/enums.py +7 -0
  14. mem0/configs/llms/__init__.py +0 -0
  15. mem0/configs/llms/base.py +152 -0
  16. mem0/configs/prompts.py +333 -0
  17. mem0/configs/vector_stores/__init__.py +0 -0
  18. mem0/configs/vector_stores/azure_ai_search.py +59 -0
  19. mem0/configs/vector_stores/baidu.py +29 -0
  20. mem0/configs/vector_stores/chroma.py +40 -0
  21. mem0/configs/vector_stores/elasticsearch.py +47 -0
  22. mem0/configs/vector_stores/faiss.py +39 -0
  23. mem0/configs/vector_stores/langchain.py +32 -0
  24. mem0/configs/vector_stores/milvus.py +43 -0
  25. mem0/configs/vector_stores/mongodb.py +25 -0
  26. mem0/configs/vector_stores/opensearch.py +41 -0
  27. mem0/configs/vector_stores/pgvector.py +37 -0
  28. mem0/configs/vector_stores/pinecone.py +56 -0
  29. mem0/configs/vector_stores/qdrant.py +49 -0
  30. mem0/configs/vector_stores/redis.py +26 -0
  31. mem0/configs/vector_stores/supabase.py +44 -0
  32. mem0/configs/vector_stores/upstash_vector.py +36 -0
  33. mem0/configs/vector_stores/vertex_ai_vector_search.py +27 -0
  34. mem0/configs/vector_stores/weaviate.py +43 -0
  35. mem0/dbs/__init__.py +4 -0
  36. mem0/dbs/base.py +68 -0
  37. mem0/dbs/configs.py +21 -0
  38. mem0/dbs/mysql.py +321 -0
  39. mem0/embeddings/__init__.py +0 -0
  40. mem0/embeddings/aws_bedrock.py +100 -0
  41. mem0/embeddings/azure_openai.py +43 -0
  42. mem0/embeddings/base.py +31 -0
  43. mem0/embeddings/configs.py +30 -0
  44. mem0/embeddings/gemini.py +39 -0
  45. mem0/embeddings/huggingface.py +41 -0
  46. mem0/embeddings/langchain.py +35 -0
  47. mem0/embeddings/lmstudio.py +29 -0
  48. mem0/embeddings/mock.py +11 -0
  49. mem0/embeddings/ollama.py +53 -0
  50. mem0/embeddings/openai.py +49 -0
  51. mem0/embeddings/together.py +31 -0
  52. mem0/embeddings/vertexai.py +54 -0
  53. mem0/graphs/__init__.py +0 -0
  54. mem0/graphs/configs.py +96 -0
  55. mem0/graphs/neptune/__init__.py +0 -0
  56. mem0/graphs/neptune/base.py +410 -0
  57. mem0/graphs/neptune/main.py +372 -0
  58. mem0/graphs/tools.py +371 -0
  59. mem0/graphs/utils.py +97 -0
  60. mem0/llms/__init__.py +0 -0
  61. mem0/llms/anthropic.py +64 -0
  62. mem0/llms/aws_bedrock.py +270 -0
  63. mem0/llms/azure_openai.py +114 -0
  64. mem0/llms/azure_openai_structured.py +76 -0
  65. mem0/llms/base.py +32 -0
  66. mem0/llms/configs.py +34 -0
  67. mem0/llms/deepseek.py +85 -0
  68. mem0/llms/gemini.py +201 -0
  69. mem0/llms/groq.py +88 -0
  70. mem0/llms/langchain.py +65 -0
  71. mem0/llms/litellm.py +87 -0
  72. mem0/llms/lmstudio.py +53 -0
  73. mem0/llms/ollama.py +94 -0
  74. mem0/llms/openai.py +124 -0
  75. mem0/llms/openai_structured.py +52 -0
  76. mem0/llms/sarvam.py +89 -0
  77. mem0/llms/together.py +88 -0
  78. mem0/llms/vllm.py +89 -0
  79. mem0/llms/xai.py +52 -0
  80. mem0/memory/__init__.py +0 -0
  81. mem0/memory/base.py +63 -0
  82. mem0/memory/graph_memory.py +632 -0
  83. mem0/memory/main.py +1843 -0
  84. mem0/memory/memgraph_memory.py +630 -0
  85. mem0/memory/setup.py +56 -0
  86. mem0/memory/storage.py +218 -0
  87. mem0/memory/telemetry.py +90 -0
  88. mem0/memory/utils.py +133 -0
  89. mem0/proxy/__init__.py +0 -0
  90. mem0/proxy/main.py +194 -0
  91. mem0/utils/factory.py +132 -0
  92. mem0/vector_stores/__init__.py +0 -0
  93. mem0/vector_stores/azure_ai_search.py +383 -0
  94. mem0/vector_stores/baidu.py +368 -0
  95. mem0/vector_stores/base.py +58 -0
  96. mem0/vector_stores/chroma.py +229 -0
  97. mem0/vector_stores/configs.py +60 -0
  98. mem0/vector_stores/elasticsearch.py +235 -0
  99. mem0/vector_stores/faiss.py +473 -0
  100. mem0/vector_stores/langchain.py +179 -0
  101. mem0/vector_stores/milvus.py +245 -0
  102. mem0/vector_stores/mongodb.py +293 -0
  103. mem0/vector_stores/opensearch.py +281 -0
  104. mem0/vector_stores/pgvector.py +294 -0
  105. mem0/vector_stores/pinecone.py +373 -0
  106. mem0/vector_stores/qdrant.py +240 -0
  107. mem0/vector_stores/redis.py +295 -0
  108. mem0/vector_stores/supabase.py +237 -0
  109. mem0/vector_stores/upstash_vector.py +293 -0
  110. mem0/vector_stores/vertex_ai_vector_search.py +629 -0
  111. mem0/vector_stores/weaviate.py +316 -0
  112. mem0ai_azure_mysql-0.1.115.data/data/README.md +169 -0
  113. mem0ai_azure_mysql-0.1.115.dist-info/METADATA +224 -0
  114. mem0ai_azure_mysql-0.1.115.dist-info/RECORD +116 -0
  115. mem0ai_azure_mysql-0.1.115.dist-info/WHEEL +4 -0
  116. mem0ai_azure_mysql-0.1.115.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,373 @@
1
+ import logging
2
+ import os
3
+ from typing import Any, Dict, List, Optional, Union
4
+
5
+ from pydantic import BaseModel
6
+
7
+ try:
8
+ from pinecone import Pinecone, PodSpec, ServerlessSpec, Vector
9
+ except ImportError:
10
+ raise ImportError(
11
+ "Pinecone requires extra dependencies. Install with `pip install pinecone pinecone-text`"
12
+ ) from None
13
+
14
+ from mem0.vector_stores.base import VectorStoreBase
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class OutputData(BaseModel):
20
+ id: Optional[str] # memory id
21
+ score: Optional[float] # distance
22
+ payload: Optional[Dict] # metadata
23
+
24
+
25
+ class PineconeDB(VectorStoreBase):
26
+ def __init__(
27
+ self,
28
+ collection_name: str,
29
+ embedding_model_dims: int,
30
+ client: Optional["Pinecone"],
31
+ api_key: Optional[str],
32
+ environment: Optional[str],
33
+ serverless_config: Optional[Dict[str, Any]],
34
+ pod_config: Optional[Dict[str, Any]],
35
+ hybrid_search: bool,
36
+ metric: str,
37
+ batch_size: int,
38
+ extra_params: Optional[Dict[str, Any]],
39
+ ):
40
+ """
41
+ Initialize the Pinecone vector store.
42
+
43
+ Args:
44
+ collection_name (str): Name of the index/collection.
45
+ embedding_model_dims (int): Dimensions of the embedding model.
46
+ client (Pinecone, optional): Existing Pinecone client instance. Defaults to None.
47
+ api_key (str, optional): API key for Pinecone. Defaults to None.
48
+ environment (str, optional): Pinecone environment. Defaults to None.
49
+ serverless_config (Dict, optional): Configuration for serverless deployment. Defaults to None.
50
+ pod_config (Dict, optional): Configuration for pod-based deployment. Defaults to None.
51
+ hybrid_search (bool, optional): Whether to enable hybrid search. Defaults to False.
52
+ metric (str, optional): Distance metric for vector similarity. Defaults to "cosine".
53
+ batch_size (int, optional): Batch size for operations. Defaults to 100.
54
+ extra_params (Dict, optional): Additional parameters for Pinecone client. Defaults to None.
55
+ """
56
+ if client:
57
+ self.client = client
58
+ else:
59
+ api_key = api_key or os.environ.get("PINECONE_API_KEY")
60
+ if not api_key:
61
+ raise ValueError(
62
+ "Pinecone API key must be provided either as a parameter or as an environment variable"
63
+ )
64
+
65
+ params = extra_params or {}
66
+ self.client = Pinecone(api_key=api_key, **params)
67
+
68
+ self.collection_name = collection_name
69
+ self.embedding_model_dims = embedding_model_dims
70
+ self.environment = environment
71
+ self.serverless_config = serverless_config
72
+ self.pod_config = pod_config
73
+ self.hybrid_search = hybrid_search
74
+ self.metric = metric
75
+ self.batch_size = batch_size
76
+
77
+ self.sparse_encoder = None
78
+ if self.hybrid_search:
79
+ try:
80
+ from pinecone_text.sparse import BM25Encoder
81
+
82
+ logger.info("Initializing BM25Encoder for sparse vectors...")
83
+ self.sparse_encoder = BM25Encoder.default()
84
+ except ImportError:
85
+ logger.warning("pinecone-text not installed. Hybrid search will be disabled.")
86
+ self.hybrid_search = False
87
+
88
+ self.create_col(embedding_model_dims, metric)
89
+
90
+ def create_col(self, vector_size: int, metric: str = "cosine"):
91
+ """
92
+ Create a new index/collection.
93
+
94
+ Args:
95
+ vector_size (int): Size of the vectors to be stored.
96
+ metric (str, optional): Distance metric for vector similarity. Defaults to "cosine".
97
+ """
98
+ existing_indexes = self.list_cols().names()
99
+
100
+ if self.collection_name in existing_indexes:
101
+ logger.debug(f"Index {self.collection_name} already exists. Skipping creation.")
102
+ self.index = self.client.Index(self.collection_name)
103
+ return
104
+
105
+ if self.serverless_config:
106
+ spec = ServerlessSpec(**self.serverless_config)
107
+ elif self.pod_config:
108
+ spec = PodSpec(**self.pod_config)
109
+ else:
110
+ spec = ServerlessSpec(cloud="aws", region="us-west-2")
111
+
112
+ self.client.create_index(
113
+ name=self.collection_name,
114
+ dimension=vector_size,
115
+ metric=metric,
116
+ spec=spec,
117
+ )
118
+
119
+ self.index = self.client.Index(self.collection_name)
120
+
121
+ def insert(
122
+ self,
123
+ vectors: List[List[float]],
124
+ payloads: Optional[List[Dict]] = None,
125
+ ids: Optional[List[Union[str, int]]] = None,
126
+ ):
127
+ """
128
+ Insert vectors into an index.
129
+
130
+ Args:
131
+ vectors (list): List of vectors to insert.
132
+ payloads (list, optional): List of payloads corresponding to vectors. Defaults to None.
133
+ ids (list, optional): List of IDs corresponding to vectors. Defaults to None.
134
+ """
135
+ logger.info(f"Inserting {len(vectors)} vectors into index {self.collection_name}")
136
+ items = []
137
+
138
+ for idx, vector in enumerate(vectors):
139
+ item_id = str(ids[idx]) if ids is not None else str(idx)
140
+ payload = payloads[idx] if payloads else {}
141
+
142
+ vector_record = {"id": item_id, "values": vector, "metadata": payload}
143
+
144
+ if self.hybrid_search and self.sparse_encoder and "text" in payload:
145
+ sparse_vector = self.sparse_encoder.encode_documents(payload["text"])
146
+ vector_record["sparse_values"] = sparse_vector
147
+
148
+ items.append(vector_record)
149
+
150
+ if len(items) >= self.batch_size:
151
+ self.index.upsert(vectors=items)
152
+ items = []
153
+
154
+ if items:
155
+ self.index.upsert(vectors=items)
156
+
157
+ def _parse_output(self, data: Dict) -> List[OutputData]:
158
+ """
159
+ Parse the output data from Pinecone search results.
160
+
161
+ Args:
162
+ data (Dict): Output data from Pinecone query.
163
+
164
+ Returns:
165
+ List[OutputData]: Parsed output data.
166
+ """
167
+ if isinstance(data, Vector):
168
+ result = OutputData(
169
+ id=data.id,
170
+ score=0.0,
171
+ payload=data.metadata,
172
+ )
173
+ return result
174
+ else:
175
+ result = []
176
+ for match in data:
177
+ entry = OutputData(
178
+ id=match.get("id"),
179
+ score=match.get("score"),
180
+ payload=match.get("metadata"),
181
+ )
182
+ result.append(entry)
183
+
184
+ return result
185
+
186
+ def _create_filter(self, filters: Optional[Dict]) -> Dict:
187
+ """
188
+ Create a filter dictionary from the provided filters.
189
+ """
190
+ if not filters:
191
+ return {}
192
+
193
+ pinecone_filter = {}
194
+
195
+ for key, value in filters.items():
196
+ if isinstance(value, dict) and "gte" in value and "lte" in value:
197
+ pinecone_filter[key] = {"$gte": value["gte"], "$lte": value["lte"]}
198
+ else:
199
+ pinecone_filter[key] = {"$eq": value}
200
+
201
+ return pinecone_filter
202
+
203
+ def search(
204
+ self, query: str, vectors: List[float], limit: int = 5, filters: Optional[Dict] = None
205
+ ) -> List[OutputData]:
206
+ """
207
+ Search for similar vectors.
208
+
209
+ Args:
210
+ query (str): Query.
211
+ vectors (list): List of vectors to search.
212
+ limit (int, optional): Number of results to return. Defaults to 5.
213
+ filters (dict, optional): Filters to apply to the search. Defaults to None.
214
+
215
+ Returns:
216
+ list: Search results.
217
+ """
218
+ filter_dict = self._create_filter(filters) if filters else None
219
+
220
+ query_params = {
221
+ "vector": vectors,
222
+ "top_k": limit,
223
+ "include_metadata": True,
224
+ "include_values": False,
225
+ }
226
+
227
+ if filter_dict:
228
+ query_params["filter"] = filter_dict
229
+
230
+ if self.hybrid_search and self.sparse_encoder and "text" in filters:
231
+ query_text = filters.get("text")
232
+ if query_text:
233
+ sparse_vector = self.sparse_encoder.encode_queries(query_text)
234
+ query_params["sparse_vector"] = sparse_vector
235
+
236
+ response = self.index.query(**query_params)
237
+
238
+ results = self._parse_output(response.matches)
239
+ return results
240
+
241
+ def delete(self, vector_id: Union[str, int]):
242
+ """
243
+ Delete a vector by ID.
244
+
245
+ Args:
246
+ vector_id (Union[str, int]): ID of the vector to delete.
247
+ """
248
+ self.index.delete(ids=[str(vector_id)])
249
+
250
+ def update(self, vector_id: Union[str, int], vector: Optional[List[float]] = None, payload: Optional[Dict] = None):
251
+ """
252
+ Update a vector and its payload.
253
+
254
+ Args:
255
+ vector_id (Union[str, int]): ID of the vector to update.
256
+ vector (list, optional): Updated vector. Defaults to None.
257
+ payload (dict, optional): Updated payload. Defaults to None.
258
+ """
259
+ item = {
260
+ "id": str(vector_id),
261
+ }
262
+
263
+ if vector is not None:
264
+ item["values"] = vector
265
+
266
+ if payload is not None:
267
+ item["metadata"] = payload
268
+
269
+ if self.hybrid_search and self.sparse_encoder and "text" in payload:
270
+ sparse_vector = self.sparse_encoder.encode_documents(payload["text"])
271
+ item["sparse_values"] = sparse_vector
272
+
273
+ self.index.upsert(vectors=[item])
274
+
275
+ def get(self, vector_id: Union[str, int]) -> OutputData:
276
+ """
277
+ Retrieve a vector by ID.
278
+
279
+ Args:
280
+ vector_id (Union[str, int]): ID of the vector to retrieve.
281
+
282
+ Returns:
283
+ dict: Retrieved vector or None if not found.
284
+ """
285
+ try:
286
+ response = self.index.fetch(ids=[str(vector_id)])
287
+ if str(vector_id) in response.vectors:
288
+ return self._parse_output(response.vectors[str(vector_id)])
289
+ return None
290
+ except Exception as e:
291
+ logger.error(f"Error retrieving vector {vector_id}: {e}")
292
+ return None
293
+
294
+ def list_cols(self):
295
+ """
296
+ List all indexes/collections.
297
+
298
+ Returns:
299
+ list: List of index information.
300
+ """
301
+ return self.client.list_indexes()
302
+
303
+ def delete_col(self):
304
+ """Delete an index/collection."""
305
+ try:
306
+ self.client.delete_index(self.collection_name)
307
+ logger.info(f"Index {self.collection_name} deleted successfully")
308
+ except Exception as e:
309
+ logger.error(f"Error deleting index {self.collection_name}: {e}")
310
+
311
+ def col_info(self) -> Dict:
312
+ """
313
+ Get information about an index/collection.
314
+
315
+ Returns:
316
+ dict: Index information.
317
+ """
318
+ return self.client.describe_index(self.collection_name)
319
+
320
+ def list(self, filters: Optional[Dict] = None, limit: int = 100) -> List[OutputData]:
321
+ """
322
+ List vectors in an index with optional filtering.
323
+
324
+ Args:
325
+ filters (dict, optional): Filters to apply to the list. Defaults to None.
326
+ limit (int, optional): Number of vectors to return. Defaults to 100.
327
+
328
+ Returns:
329
+ dict: List of vectors with their metadata.
330
+ """
331
+ filter_dict = self._create_filter(filters) if filters else None
332
+
333
+ stats = self.index.describe_index_stats()
334
+ dimension = stats.dimension
335
+
336
+ zero_vector = [0.0] * dimension
337
+
338
+ query_params = {
339
+ "vector": zero_vector,
340
+ "top_k": limit,
341
+ "include_metadata": True,
342
+ "include_values": True,
343
+ }
344
+
345
+ if filter_dict:
346
+ query_params["filter"] = filter_dict
347
+
348
+ try:
349
+ response = self.index.query(**query_params)
350
+ response = response.to_dict()
351
+ results = self._parse_output(response["matches"])
352
+ return [results]
353
+ except Exception as e:
354
+ logger.error(f"Error listing vectors: {e}")
355
+ return {"points": [], "next_page_token": None}
356
+
357
+ def count(self) -> int:
358
+ """
359
+ Count number of vectors in the index.
360
+
361
+ Returns:
362
+ int: Total number of vectors.
363
+ """
364
+ stats = self.index.describe_index_stats()
365
+ return stats.total_vector_count
366
+
367
+ def reset(self):
368
+ """
369
+ Reset the index by deleting and recreating it.
370
+ """
371
+ logger.warning(f"Resetting index {self.collection_name}...")
372
+ self.delete_col()
373
+ self.create_col(self.embedding_model_dims, self.metric)
@@ -0,0 +1,240 @@
1
+ import logging
2
+ import os
3
+ import shutil
4
+
5
+ from qdrant_client import QdrantClient
6
+ from qdrant_client.models import (
7
+ Distance,
8
+ FieldCondition,
9
+ Filter,
10
+ MatchValue,
11
+ PointIdsList,
12
+ PointStruct,
13
+ Range,
14
+ VectorParams,
15
+ )
16
+
17
+ from mem0.vector_stores.base import VectorStoreBase
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class Qdrant(VectorStoreBase):
23
+ def __init__(
24
+ self,
25
+ collection_name: str,
26
+ embedding_model_dims: int,
27
+ client: QdrantClient = None,
28
+ host: str = None,
29
+ port: int = None,
30
+ path: str = None,
31
+ url: str = None,
32
+ api_key: str = None,
33
+ on_disk: bool = False,
34
+ ):
35
+ """
36
+ Initialize the Qdrant vector store.
37
+
38
+ Args:
39
+ collection_name (str): Name of the collection.
40
+ embedding_model_dims (int): Dimensions of the embedding model.
41
+ client (QdrantClient, optional): Existing Qdrant client instance. Defaults to None.
42
+ host (str, optional): Host address for Qdrant server. Defaults to None.
43
+ port (int, optional): Port for Qdrant server. Defaults to None.
44
+ path (str, optional): Path for local Qdrant database. Defaults to None.
45
+ url (str, optional): Full URL for Qdrant server. Defaults to None.
46
+ api_key (str, optional): API key for Qdrant server. Defaults to None.
47
+ on_disk (bool, optional): Enables persistent storage. Defaults to False.
48
+ """
49
+ if client:
50
+ self.client = client
51
+ else:
52
+ params = {}
53
+ if api_key:
54
+ params["api_key"] = api_key
55
+ if url:
56
+ params["url"] = url
57
+ if host and port:
58
+ params["host"] = host
59
+ params["port"] = port
60
+ if not params:
61
+ params["path"] = path
62
+ if not on_disk:
63
+ if os.path.exists(path) and os.path.isdir(path):
64
+ shutil.rmtree(path)
65
+
66
+ self.client = QdrantClient(**params)
67
+
68
+ self.collection_name = collection_name
69
+ self.embedding_model_dims = embedding_model_dims
70
+ self.on_disk = on_disk
71
+ self.create_col(embedding_model_dims, on_disk)
72
+
73
+ def create_col(self, vector_size: int, on_disk: bool, distance: Distance = Distance.COSINE):
74
+ """
75
+ Create a new collection.
76
+
77
+ Args:
78
+ vector_size (int): Size of the vectors to be stored.
79
+ on_disk (bool): Enables persistent storage.
80
+ distance (Distance, optional): Distance metric for vector similarity. Defaults to Distance.COSINE.
81
+ """
82
+ # Skip creating collection if already exists
83
+ response = self.list_cols()
84
+ for collection in response.collections:
85
+ if collection.name == self.collection_name:
86
+ logger.debug(f"Collection {self.collection_name} already exists. Skipping creation.")
87
+ return
88
+
89
+ self.client.create_collection(
90
+ collection_name=self.collection_name,
91
+ vectors_config=VectorParams(size=vector_size, distance=distance, on_disk=on_disk),
92
+ )
93
+
94
+ def insert(self, vectors: list, payloads: list = None, ids: list = None):
95
+ """
96
+ Insert vectors into a collection.
97
+
98
+ Args:
99
+ vectors (list): List of vectors to insert.
100
+ payloads (list, optional): List of payloads corresponding to vectors. Defaults to None.
101
+ ids (list, optional): List of IDs corresponding to vectors. Defaults to None.
102
+ """
103
+ logger.info(f"Inserting {len(vectors)} vectors into collection {self.collection_name}")
104
+ points = [
105
+ PointStruct(
106
+ id=idx if ids is None else ids[idx],
107
+ vector=vector,
108
+ payload=payloads[idx] if payloads else {},
109
+ )
110
+ for idx, vector in enumerate(vectors)
111
+ ]
112
+ self.client.upsert(collection_name=self.collection_name, points=points)
113
+
114
+ def _create_filter(self, filters: dict) -> Filter:
115
+ """
116
+ Create a Filter object from the provided filters.
117
+
118
+ Args:
119
+ filters (dict): Filters to apply.
120
+
121
+ Returns:
122
+ Filter: The created Filter object.
123
+ """
124
+ conditions = []
125
+ for key, value in filters.items():
126
+ if isinstance(value, dict) and "gte" in value and "lte" in value:
127
+ conditions.append(FieldCondition(key=key, range=Range(gte=value["gte"], lte=value["lte"])))
128
+ else:
129
+ conditions.append(FieldCondition(key=key, match=MatchValue(value=value)))
130
+ return Filter(must=conditions) if conditions else None
131
+
132
+ def search(self, query: str, vectors: list, limit: int = 5, filters: dict = None) -> list:
133
+ """
134
+ Search for similar vectors.
135
+
136
+ Args:
137
+ query (str): Query.
138
+ vectors (list): Query vector.
139
+ limit (int, optional): Number of results to return. Defaults to 5.
140
+ filters (dict, optional): Filters to apply to the search. Defaults to None.
141
+
142
+ Returns:
143
+ list: Search results.
144
+ """
145
+ query_filter = self._create_filter(filters) if filters else None
146
+ hits = self.client.query_points(
147
+ collection_name=self.collection_name,
148
+ query=vectors,
149
+ query_filter=query_filter,
150
+ limit=limit,
151
+ )
152
+ return hits.points
153
+
154
+ def delete(self, vector_id: int):
155
+ """
156
+ Delete a vector by ID.
157
+
158
+ Args:
159
+ vector_id (int): ID of the vector to delete.
160
+ """
161
+ self.client.delete(
162
+ collection_name=self.collection_name,
163
+ points_selector=PointIdsList(
164
+ points=[vector_id],
165
+ ),
166
+ )
167
+
168
+ def update(self, vector_id: int, vector: list = None, payload: dict = None):
169
+ """
170
+ Update a vector and its payload.
171
+
172
+ Args:
173
+ vector_id (int): ID of the vector to update.
174
+ vector (list, optional): Updated vector. Defaults to None.
175
+ payload (dict, optional): Updated payload. Defaults to None.
176
+ """
177
+ point = PointStruct(id=vector_id, vector=vector, payload=payload)
178
+ self.client.upsert(collection_name=self.collection_name, points=[point])
179
+
180
+ def get(self, vector_id: int) -> dict:
181
+ """
182
+ Retrieve a vector by ID.
183
+
184
+ Args:
185
+ vector_id (int): ID of the vector to retrieve.
186
+
187
+ Returns:
188
+ dict: Retrieved vector.
189
+ """
190
+ result = self.client.retrieve(collection_name=self.collection_name, ids=[vector_id], with_payload=True)
191
+ return result[0] if result else None
192
+
193
+ def list_cols(self) -> list:
194
+ """
195
+ List all collections.
196
+
197
+ Returns:
198
+ list: List of collection names.
199
+ """
200
+ return self.client.get_collections()
201
+
202
+ def delete_col(self):
203
+ """Delete a collection."""
204
+ self.client.delete_collection(collection_name=self.collection_name)
205
+
206
+ def col_info(self) -> dict:
207
+ """
208
+ Get information about a collection.
209
+
210
+ Returns:
211
+ dict: Collection information.
212
+ """
213
+ return self.client.get_collection(collection_name=self.collection_name)
214
+
215
+ def list(self, filters: dict = None, limit: int = 100) -> list:
216
+ """
217
+ List all vectors in a collection.
218
+
219
+ Args:
220
+ filters (dict, optional): Filters to apply to the list. Defaults to None.
221
+ limit (int, optional): Number of vectors to return. Defaults to 100.
222
+
223
+ Returns:
224
+ list: List of vectors.
225
+ """
226
+ query_filter = self._create_filter(filters) if filters else None
227
+ result = self.client.scroll(
228
+ collection_name=self.collection_name,
229
+ scroll_filter=query_filter,
230
+ limit=limit,
231
+ with_payload=True,
232
+ with_vectors=False,
233
+ )
234
+ return result
235
+
236
+ def reset(self):
237
+ """Reset the index by deleting and recreating it."""
238
+ logger.warning(f"Resetting index {self.collection_name}...")
239
+ self.delete_col()
240
+ self.create_col(self.embedding_model_dims, self.on_disk)