fix(memory): centralize entity cleanup and skip malformed LLM relation dicts (#4515)
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import pytest
|
||||
from mem0.memory.utils import remove_spaces_from_entities, sanitize_relationship_for_cypher
|
||||
|
||||
|
||||
class TestRemoveSpacesFromEntities:
|
||||
"""
|
||||
Covers behavior used by Neo4j, Memgraph (sanitize_relationship=True),
|
||||
Kuzu, and Neptune (sanitize_relationship=False). All backends delegate here.
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"sanitize",
|
||||
[True, False],
|
||||
ids=["cypher_sanitized", "plain"],
|
||||
)
|
||||
def test_filters_empty_and_incomplete_dicts(self, sanitize):
|
||||
mixed = [
|
||||
{},
|
||||
{"source": "a"},
|
||||
{"source": "a", "relationship": "r"},
|
||||
{"source": "x", "relationship": "rel", "destination": "y"},
|
||||
]
|
||||
out = remove_spaces_from_entities(mixed, sanitize_relationship=sanitize)
|
||||
assert len(out) == 1
|
||||
assert out[0]["source"] == "x"
|
||||
assert out[0]["destination"] == "y"
|
||||
|
||||
@pytest.mark.parametrize("sanitize", [True, False])
|
||||
def test_all_empty_returns_empty(self, sanitize):
|
||||
assert remove_spaces_from_entities([{}, {}, {}], sanitize_relationship=sanitize) == []
|
||||
|
||||
def test_skips_non_dict_entries(self):
|
||||
assert remove_spaces_from_entities([None, "not-a-dict", 123, {"source": "a", "relationship": "r", "destination": "b"}]) == [
|
||||
{"source": "a", "relationship": "r", "destination": "b"}
|
||||
]
|
||||
|
||||
def test_sanitize_true_relationship_uses_sanitizer(self):
|
||||
"""Neo4j / Memgraph path: special characters mapped via sanitize_relationship_for_cypher."""
|
||||
entities = [{"source": "A", "relationship": "x/y", "destination": "B"}]
|
||||
out = remove_spaces_from_entities(entities, sanitize_relationship=True)
|
||||
assert out[0]["relationship"] == sanitize_relationship_for_cypher("x/y".lower().replace(" ", "_"))
|
||||
|
||||
def test_sanitize_false_relationship_plain_only(self):
|
||||
"""Kuzu / Neptune path: only lowercase and spaces to underscores."""
|
||||
entities = [{"source": "A", "relationship": "Works At", "destination": "B Co"}]
|
||||
out = remove_spaces_from_entities(entities, sanitize_relationship=False)
|
||||
assert out[0]["relationship"] == "works_at"
|
||||
assert out[0]["source"] == "a"
|
||||
assert out[0]["destination"] == "b_co"
|
||||
|
||||
def test_sanitize_true_vs_false_slash_in_relationship(self):
|
||||
"""Slash is rewritten when sanitizing (Cypher path); kept as-is for plain path."""
|
||||
base = {"source": "s", "relationship": "a/b", "destination": "d"}
|
||||
t = remove_spaces_from_entities([dict(base)], sanitize_relationship=True)[0]["relationship"]
|
||||
f = remove_spaces_from_entities([dict(base)], sanitize_relationship=False)[0]["relationship"]
|
||||
assert t == sanitize_relationship_for_cypher("a/b")
|
||||
assert f == "a/b"
|
||||
Reference in New Issue
Block a user