88
99
1010embedder_config = EmbedderConfigFactory .model_validate (
11- {
12- "backend" : "sentence_transformer" ,
13- "config" : {
14- "model_name_or_path" : "nomic-ai/nomic-embed-text-v1.5" ,
15- },
16- }
11+ {"backend" : "ollama" , "config" : {"model_name_or_path" : "nomic-embed-text:latest" }}
1712)
1813embedder = EmbedderFactory .from_config (embedder_config )
1914
@@ -22,7 +17,7 @@ def embed_memory_item(memory: str) -> list[float]:
2217 return embedder .embed ([memory ])[0 ]
2318
2419
25- def example_1_paper (db_name : str = "paper" ):
20+ def example_multi_db (db_name : str = "paper" ):
2621 # Step 1: Build factory config
2722 config = GraphDBConfigFactory (
2823 backend = "neo4j" ,
@@ -33,6 +28,7 @@ def example_1_paper(db_name: str = "paper"):
3328 "db_name" : db_name ,
3429 "auto_create" : True ,
3530 "embedding_dimension" : 768 ,
31+ "use_multi_db" : True ,
3632 },
3733 )
3834
@@ -68,7 +64,7 @@ def example_1_paper(db_name: str = "paper"):
6864 )
6965
7066 graph .add_node (
71- id = topic .id , content = topic .memory , metadata = topic .metadata .model_dump (exclude_none = True )
67+ id = topic .id , memory = topic .memory , metadata = topic .metadata .model_dump (exclude_none = True )
7268 )
7369
7470 # Step 4: Define and write concept nodes
@@ -150,7 +146,7 @@ def example_1_paper(db_name: str = "paper"):
150146 for concept in concepts :
151147 graph .add_node (
152148 id = concept .id ,
153- content = concept .memory ,
149+ memory = concept .memory ,
154150 metadata = concept .metadata .model_dump (exclude_none = True ),
155151 )
156152 graph .add_edge (source_id = concept .id , target_id = topic .id , type = "RELATED" )
@@ -259,113 +255,101 @@ def example_1_paper(db_name: str = "paper"):
259255 print (graph .get_node (node_i ["id" ]))
260256
261257
262- def example_2_travel (db_name : str = "travel" ):
263- # Step 1: Build factory config
264- config = GraphDBConfigFactory (
265- backend = "neo4j" ,
266- config = {
267- "uri" : "bolt://localhost:7687" ,
268- "user" : "neo4j" ,
269- "password" : "12345678" ,
270- "db_name" : db_name ,
271- "auto_create" : True ,
272- "embedding_dimension" : 768 ,
273- },
274- )
275-
276- # Step 2: Instantiate the graph store
277- graph = GraphStoreFactory .from_config (config )
278- graph .clear ()
279-
280- # Step 3: Create topic node
281- topic = TextualMemoryItem (
282- memory = "Travel" ,
283- metadata = TreeNodeTextualMemoryMetadata (
284- memory_type = "LongTermMemory" ,
285- hierarchy_level = "topic" ,
286- status = "activated" ,
287- visibility = "public" ,
288- embedding = embed_memory_item ("Travel" ),
289- ),
290- )
291-
292- graph .add_node (
293- id = topic .id , content = topic .memory , metadata = topic .metadata .model_dump (exclude_none = True )
294- )
295-
296- concept1 = TextualMemoryItem (
297- memory = "Travel in Italy" ,
298- metadata = TreeNodeTextualMemoryMetadata (
299- memory_type = "LongTermMemory" ,
300- hierarchy_level = "concept" ,
301- status = "activated" ,
302- visibility = "public" ,
303- embedding = embed_memory_item ("Travel in Italy" ),
304- ),
305- )
258+ def example_shared_db (db_name : str = "shared-traval-group" ):
259+ """
260+ Example: Single(Shared)-DB multi-tenant (logical isolation)
261+ Multiple users' data in the same Neo4j DB with user_name as a tag.
262+ """
263+ # users
264+ user_list = ["travel_member_alice" , "travel_member_bob" ]
265+
266+ for user_name in user_list :
267+ # Step 1: Build factory config
268+ config = GraphDBConfigFactory (
269+ backend = "neo4j" ,
270+ config = {
271+ "uri" : "bolt://localhost:7687" ,
272+ "user" : "neo4j" ,
273+ "password" : "12345678" ,
274+ "db_name" : db_name ,
275+ "user_name" : user_name ,
276+ "use_multi_db" : False ,
277+ "auto_create" : True ,
278+ "embedding_dimension" : 768 ,
279+ },
280+ )
281+ # Step 2: Instantiate graph store
282+ graph = GraphStoreFactory .from_config (config )
283+ print (f"\n [INFO] Working in shared DB: { db_name } , for user: { user_name } " )
284+ graph .clear ()
285+
286+ # Step 3: Create topic node
287+ topic = TextualMemoryItem (
288+ memory = f"Travel notes for { user_name } " ,
289+ metadata = TreeNodeTextualMemoryMetadata (
290+ memory_type = "LongTermMemory" ,
291+ hierarchy_level = "topic" ,
292+ status = "activated" ,
293+ visibility = "public" ,
294+ embedding = embed_memory_item (f"Travel notes for { user_name } " ),
295+ ),
296+ )
306297
307- graph .add_node (
308- id = concept1 .id ,
309- content = concept1 .memory ,
310- metadata = concept1 .metadata .model_dump (exclude_none = True ),
311- )
312- graph .add_edge (source_id = topic .id , target_id = concept1 .id , type = "INCLUDE" )
298+ graph .add_node (
299+ id = topic .id , memory = topic .memory , metadata = topic .metadata .model_dump (exclude_none = True )
300+ )
313301
314- concept2 = TextualMemoryItem (
315- memory = "Traval plan" ,
316- metadata = TreeNodeTextualMemoryMetadata (
317- memory_type = "LongTermMemory" ,
318- hierarchy_level = "concept" ,
319- status = "activated" ,
320- visibility = "public" ,
321- embedding = embed_memory_item ("Traval plan" ),
322- ),
323- )
302+ # Step 4: Add a concept for each user
303+ concept = TextualMemoryItem (
304+ memory = f"Itinerary plan for { user_name } " ,
305+ metadata = TreeNodeTextualMemoryMetadata (
306+ memory_type = "LongTermMemory" ,
307+ hierarchy_level = "concept" ,
308+ status = "activated" ,
309+ visibility = "public" ,
310+ embedding = embed_memory_item (f"Itinerary plan for { user_name } " ),
311+ ),
312+ )
324313
325- graph .add_node (
326- id = concept2 .id ,
327- content = concept2 .memory ,
328- metadata = concept2 .metadata .model_dump (exclude_none = True ),
329- )
330- graph .add_edge (source_id = concept1 .id , target_id = concept2 .id , type = "INCLUDE" )
314+ graph .add_node (
315+ id = concept .id ,
316+ memory = concept .memory ,
317+ metadata = concept .metadata .model_dump (exclude_none = True ),
318+ )
331319
332- fact1 = TextualMemoryItem (
333- memory = "10-Day Itinerary for Traveling in Italy" ,
334- metadata = TreeNodeTextualMemoryMetadata (
335- memory_type = "WorkingMemory" ,
336- key = "Reward Components" ,
337- value = "Coverage gain, energy usage penalty, overlap penalty" ,
338- hierarchy_level = "fact" ,
339- type = "fact" ,
340- memory_time = "2024-01-01" ,
341- source = "file" ,
342- sources = ["paper://multi-uav-coverage/reward-details" ],
343- status = "activated" ,
344- confidence = 90.0 ,
345- tags = ["reward" , "overlap" , "multi-agent" ],
346- entities = ["coverage" , "energy" , "overlap" ],
347- visibility = "public" ,
348- embedding = embed_memory_item ("10-Day Itinerary for Traveling in Italy" ),
349- updated_at = datetime .now ().isoformat (),
350- ),
351- )
320+ # Link concept to topic
321+ graph .add_edge (source_id = concept .id , target_id = topic .id , type = "INCLUDE" )
352322
353- graph .add_node (
354- id = fact1 .id , content = fact1 .memory , metadata = fact1 .metadata .model_dump (exclude_none = True )
355- )
356- graph .add_edge (source_id = concept2 .id , target_id = fact1 .id , type = "INCLUDE" )
323+ print (f"[INFO] Added nodes for { user_name } " )
357324
325+ # Step 5: Query and print ALL for verification
326+ print ("\n === Export entire DB (for verification, includes ALL users) ===" )
327+ graph = GraphStoreFactory .from_config (config )
358328 all_graph_data = graph .export_graph ()
359329 print (all_graph_data )
360330
361- nodes = graph .search_by_embedding (vector = embed_memory_item ("what does FT reflect?" ), top_k = 1 )
362-
363- for node_i in nodes :
364- print (graph .get_node (node_i ["id" ]))
331+ # Step 6: Search for alice's data only
332+ print ("\n === Search for travel_member_alice ===" )
333+ config_alice = GraphDBConfigFactory (
334+ backend = "neo4j" ,
335+ config = {
336+ "uri" : "bolt://localhost:7687" ,
337+ "user" : "neo4j" ,
338+ "password" : "12345678" ,
339+ "db_name" : db_name ,
340+ "user_name" : user_list [0 ],
341+ "embedding_dimension" : 768 ,
342+ },
343+ )
344+ graph_alice = GraphStoreFactory .from_config (config_alice )
345+ nodes = graph_alice .search_by_embedding (vector = embed_memory_item ("travel itinerary" ), top_k = 1 )
346+ for node in nodes :
347+ print (graph_alice .get_node (node ["id" ]))
365348
366349
367350if __name__ == "__main__" :
368- example_1_paper (db_name = "paper" )
351+ print ("\n === Example: Multi-DB ===" )
352+ example_multi_db (db_name = "paper" )
369353
370- if __name__ == "__main__" :
371- example_2_travel (db_name = "traval" )
354+ print ( " \n === Example: Single-DB ===" )
355+ example_shared_db (db_name = "shared- traval-group11 " )
0 commit comments