15
15
from __future__ import annotations
16
16
17
17
import logging
18
+ import warnings
18
19
from typing import List , Literal , Optional
19
20
20
21
import neo4j
23
24
from neo4j_graphrag .neo4j_queries import (
24
25
UPSERT_VECTOR_ON_NODE_QUERY ,
25
26
UPSERT_VECTOR_ON_RELATIONSHIP_QUERY ,
27
+ UPSERT_VECTORS_ON_NODE_QUERY ,
28
+ UPSERT_VECTORS_ON_RELATIONSHIP_QUERY ,
26
29
)
27
30
28
31
from .exceptions import Neo4jIndexError , Neo4jInsertionError
29
- from .types import FulltextIndexModel , VectorIndexModel
32
+ from .types import EntityType , FulltextIndexModel , VectorIndexModel
30
33
31
34
logger = logging .getLogger (__name__ )
32
35
@@ -245,6 +248,86 @@ def drop_index_if_exists(
245
248
raise Neo4jIndexError (f"Dropping Neo4j index failed: { e .message } " ) from e
246
249
247
250
251
+ def upsert_vectors (
252
+ driver : neo4j .Driver ,
253
+ ids : List [str ],
254
+ embedding_property : str ,
255
+ embeddings : List [List [float ]],
256
+ neo4j_database : Optional [str ] = None ,
257
+ entity_type : EntityType = EntityType .NODE ,
258
+ ) -> None :
259
+ """
260
+ This method constructs a Cypher query and executes it to upsert
261
+ (insert or update) embeddings on a set of nodes or relationships.
262
+
263
+ Example:
264
+
265
+ .. code-block:: python
266
+
267
+ from neo4j import GraphDatabase
268
+ from neo4j_graphrag.indexes import upsert_vectors
269
+
270
+ URI = "neo4j://localhost:7687"
271
+ AUTH = ("neo4j", "password")
272
+
273
+ # Connect to Neo4j database
274
+ driver = GraphDatabase.driver(URI, auth=AUTH)
275
+
276
+ # Upsert embeddings data for several nodes
277
+ upsert_vectors(
278
+ driver,
279
+ ids=['123', '456', '789'],
280
+ embedding_property="vectorProperty",
281
+ embeddings=[
282
+ [0.12, 0.34, 0.56],
283
+ [0.78, 0.90, 0.12],
284
+ [0.34, 0.56, 0.78],
285
+ ],
286
+ neo4j_database="neo4j",
287
+ entity_type='NODE',
288
+ )
289
+
290
+ Args:
291
+ driver (neo4j.Driver): Neo4j Python driver instance.
292
+ ids (List[int]): The element IDs of the nodes or relationships.
293
+ embedding_property (str): The name of the property to store the vectors in.
294
+ embeddings (List[List[float]]): The list of vectors to store, one per ID.
295
+ neo4j_database (Optional[str]): The name of the Neo4j database.
296
+ If not provided, defaults to the server's default database. 'neo4j' by default.
297
+ entity_type (EntityType): Specifies whether to upsert to nodes ('NODE') or relationships ('RELATIONSHIP').
298
+ Defaults to 'NODE'.
299
+
300
+ Raises:
301
+ ValueError: If the lengths of IDs and embeddings do not match, or if embeddings are not of uniform dimension.
302
+ Neo4jInsertionError: If an error occurs while attempting to upsert the vectors in Neo4j.
303
+ """
304
+ if entity_type == EntityType .NODE :
305
+ query = UPSERT_VECTORS_ON_NODE_QUERY
306
+ elif entity_type == EntityType .RELATIONSHIP :
307
+ query = UPSERT_VECTORS_ON_RELATIONSHIP_QUERY
308
+ else :
309
+ raise ValueError ("entity_type must be either 'NODE' or 'RELATIONSHIP'" )
310
+ if len (ids ) != len (embeddings ):
311
+ raise ValueError ("ids and embeddings must be the same length" )
312
+ if not all (len (embedding ) == len (embeddings [0 ]) for embedding in embeddings ):
313
+ raise ValueError ("All embeddings must be of the same size" )
314
+ try :
315
+ parameters = {
316
+ "rows" : [
317
+ {"id" : id , "embedding" : embedding }
318
+ for id , embedding in zip (ids , embeddings )
319
+ ],
320
+ "embedding_property" : embedding_property ,
321
+ }
322
+ driver .execute_query (
323
+ query_ = query , parameters_ = parameters , database_ = neo4j_database
324
+ )
325
+ except neo4j .exceptions .ClientError as e :
326
+ raise Neo4jInsertionError (
327
+ f"Upserting vectors to Neo4j failed: { e .message } "
328
+ ) from e
329
+
330
+
248
331
def upsert_vector (
249
332
driver : neo4j .Driver ,
250
333
node_id : int ,
@@ -253,6 +336,9 @@ def upsert_vector(
253
336
neo4j_database : Optional [str ] = None ,
254
337
) -> None :
255
338
"""
339
+ .. warning::
340
+ 'upsert_vector' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead.
341
+
256
342
This method constructs a Cypher query and executes it to upsert (insert or update) a vector property on a specific node.
257
343
258
344
Example:
@@ -286,6 +372,11 @@ def upsert_vector(
286
372
Raises:
287
373
Neo4jInsertionError: If upserting of the vector fails.
288
374
"""
375
+ warnings .warn (
376
+ "'upsert_vector' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead." ,
377
+ DeprecationWarning ,
378
+ stacklevel = 2 ,
379
+ )
289
380
try :
290
381
parameters = {
291
382
"node_element_id" : node_id ,
@@ -309,6 +400,9 @@ def upsert_vector_on_relationship(
309
400
neo4j_database : Optional [str ] = None ,
310
401
) -> None :
311
402
"""
403
+ .. warning::
404
+ 'upsert_vector_on_relationship' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead.
405
+
312
406
This method constructs a Cypher query and executes it to upsert (insert or update) a vector property on a specific relationship.
313
407
314
408
Example:
@@ -342,6 +436,11 @@ def upsert_vector_on_relationship(
342
436
Raises:
343
437
Neo4jInsertionError: If upserting of the vector fails.
344
438
"""
439
+ warnings .warn (
440
+ "'upsert_vector_on_relationship' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead." ,
441
+ DeprecationWarning ,
442
+ stacklevel = 2 ,
443
+ )
345
444
try :
346
445
parameters = {
347
446
"rel_element_id" : rel_id ,
@@ -365,6 +464,9 @@ async def async_upsert_vector(
365
464
neo4j_database : Optional [str ] = None ,
366
465
) -> None :
367
466
"""
467
+ .. warning::
468
+ 'async_upsert_vector' is deprecated and will be removed in a future version.
469
+
368
470
This method constructs a Cypher query and asynchronously executes it
369
471
to upsert (insert or update) a vector property on a specific node.
370
472
@@ -399,6 +501,11 @@ async def async_upsert_vector(
399
501
Raises:
400
502
Neo4jInsertionError: If upserting of the vector fails.
401
503
"""
504
+ warnings .warn (
505
+ "'async_upsert_vector' is deprecated and will be removed in a future version." ,
506
+ DeprecationWarning ,
507
+ stacklevel = 2 ,
508
+ )
402
509
try :
403
510
parameters = {
404
511
"node_id" : node_id ,
@@ -422,6 +529,9 @@ async def async_upsert_vector_on_relationship(
422
529
neo4j_database : Optional [str ] = None ,
423
530
) -> None :
424
531
"""
532
+ .. warning::
533
+ 'async_upsert_vector_on_relationship' is deprecated and will be removed in a future version.
534
+
425
535
This method constructs a Cypher query and asynchronously executes it
426
536
to upsert (insert or update) a vector property on a specific relationship.
427
537
@@ -456,6 +566,11 @@ async def async_upsert_vector_on_relationship(
456
566
Raises:
457
567
Neo4jInsertionError: If upserting of the vector fails.
458
568
"""
569
+ warnings .warn (
570
+ "'async_upsert_vector_on_relationship' is deprecated and will be removed in a future version." ,
571
+ DeprecationWarning ,
572
+ stacklevel = 2 ,
573
+ )
459
574
try :
460
575
parameters = {
461
576
"rel_id" : rel_id ,
0 commit comments