[Bug]: SimplePropertyGraphStore.get_rel_map returns duplicate triplets when the graph has cycles
Bug Description
SimplePropertyGraphStore.get_rel_map walks the graph depth by depth and tracks visited triplets in seen_triplets, but the seen-set starts empty and is only updated with the next depth's triplets:
graph_triplets = self.get_triplets(ids=[gn.id for gn in graph_nodes])
seen_triplets = set()
while len(graph_triplets) > 0 and cur_depth < depth:
triplets.extend(graph_triplets)
graph_triplets = self.get_triplets(entity_names=[t[2].id for t in graph_triplets])
graph_triplets = [t for t in graph_triplets if str(t) not in seen_triplets]
seen_triplets.update([str(t) for t in graph_triplets])
cur_depth += 1
Any path that loops back to an already-visited depth - a two-way relation, a self-loop, or any longer cycle - gets collected again at every later depth, because the starting triplets are never recorded as seen. With a simple A <-> B pair, depth=2 returns each triplet twice (see Steps to Reproduce).
The rel map is fed directly into LLM context by the property-graph sub-retrievers (indices/property_graph/sub_retrievers/llm_synonym.py, vector.py), so every duplicate is repeated relation text: wasted tokens and a skewed picture of the graph.
Proposed fix: seed seen_triplets with the starting triplets so each triplet is collected at most once across all depths. One line plus regression tests - happy to send the PR.
Version
llama-index-core 0.14.24 (also verified on current main, fd4a517)
Steps to Reproduce
from llama_index.core.graph_stores.simple_labelled import SimplePropertyGraphStore
from llama_index.core.graph_stores.types import EntityNode, Relation
store = SimplePropertyGraphStore()
a = EntityNode(name="a")
b = EntityNode(name="b")
c = EntityNode(name="c")
store.upsert_nodes([a, b, c])
store.upsert_relations([
Relation(label="knows", source_id=a.id, target_id=b.id),
Relation(label="knows", source_id=b.id, target_id=a.id),
Relation(label="likes", source_id=b.id, target_id=c.id),
])
rel_map = store.get_rel_map([a], depth=2, limit=30)
for t in rel_map:
print(t[0].name, t[1].id, t[2].name)
Output (5 triplets, the two knows relations each appear twice; expected 3 unique):
a knows b
b knows a
b likes c
a knows b
b knows a
Source: run-llama/llama_index