feat(memory): optimize relationship taxonomy#121
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughRestructures relationship taxonomy into "authorable" vs. system-generated types, adds normalization/expansion utilities, exposes relation taxonomy for runtime wiring, and propagates normalized relation types/kinds through recall, consolidation, graph, and API blueprints. Documentation, tests, and test doubles updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as "API Blueprints"
participant Config as "Relation Registry"
participant Graph as "Graph DB"
participant Consolidator
Client->>API: POST /associate or GET /recall (relation types)
API->>Config: validate / canonicalize requested types
Config-->>API: AUTHORABLE/FILTERABLE/DEFAULT_EXPAND sets + normalized types
API->>Graph: query/merge using expanded normalized types (include kind metadata)
Graph-->>API: rows with (type, strength, kind, related)
API->>Consolidator: normalization results for discovered associations
Consolidator->>Graph: MERGE edges with rel_type, kind, origin, confidence
API-->>Client: normalized relation responses (types, kinds, strengths)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
automem/api/recall.py (1)
1925-1940:⚠️ Potential issue | 🟡 MinorFix extraneous f-string prefix (static analysis finding).
Line 1927 contains
f']-'within the string interpolation, which has no placeholders. Thefprefix is unnecessary.🔧 Proposed fix
rel_pattern = ":" + "|".join(query_relation_types) if query_relation_types else "" query = f""" - MATCH (m:Memory {{id: $id}}){'-[r' + rel_pattern + f']-' if rel_pattern else '-[r]-'}(related:Memory) + MATCH (m:Memory {{id: $id}}){'-[r' + rel_pattern + ']-' if rel_pattern else '-[r]-'}(related:Memory) WHERE m.id <> related.id🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@automem/api/recall.py` around lines 1925 - 1940, The f-string prefix on the static literal segment is unnecessary: change the concatenation that builds the Cypher fragment from "-[r' + rel_pattern + f']-'" to use a normal string for the trailing part (e.g., "-[r" + rel_pattern + "]-" or combine with rel_pattern via f"...{rel_pattern}..."), in the construction of rel_pattern and query (refer to variables rel_pattern, query and query_relation_types) so the interpolation has no stray f'' prefix and the resulting Cypher remains the same.
🧹 Nitpick comments (3)
automem/config.py (1)
364-364: Consider usingfrozensetforALLOWED_RELATIONSfor consistency.
ALLOWED_RELATIONSis defined as a mutablesetwhile other derived collections usefrozenset. This inconsistency could lead to accidental mutations.♻️ Suggested fix
-ALLOWED_RELATIONS = set(FILTERABLE_RELATIONS) +ALLOWED_RELATIONS = frozenset(FILTERABLE_RELATIONS)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@automem/config.py` at line 364, ALLOWED_RELATIONS is currently a mutable set which is inconsistent with other derived collections; change its definition to use an immutable frozenset by constructing ALLOWED_RELATIONS from FILTERABLE_RELATIONS (e.g., replace set(FILTERABLE_RELATIONS) with frozenset(FILTERABLE_RELATIONS)) so it cannot be mutated at runtime and matches the immutability of related constants.consolidation.py (1)
735-745: Consider movingallowed_labelsto a shared constant.The
allowed_labelsset duplicates knowledge about valid relation types. Consider importing or deriving this fromFILTERABLE_RELATIONSinautomem/config.pyfor consistency.♻️ Suggested approach
+from automem.config import FILTERABLE_RELATIONS, normalize_relation_type -from automem.config import normalize_relation_type ... - allowed_labels = { - "DISCOVERED", - "CONTRADICTS", - "RELATES_TO", - "SIMILAR_TO", - "PRECEDED_BY", - "DERIVED_FROM", - "PART_OF", - } - if rel_type not in allowed_labels: + if rel_type not in FILTERABLE_RELATIONS: rel_type = "RELATES_TO"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@consolidation.py` around lines 735 - 745, Replace the local allowed_labels set with the canonical FILTERABLE_RELATIONS constant from automem.config: import FILTERABLE_RELATIONS and use it (or a set(FILTERABLE_RELATIONS) if needed) in place of allowed_labels when checking rel_type; keep the existing fallback assignment rel_type = "RELATES_TO" if rel_type not in the imported set so behavior remains the same. Ensure you reference the symbol FILTERABLE_RELATIONS and update the check that currently uses allowed_labels to use that imported constant.automem/api/recall.py (1)
1628-1629: Consider narrowing the type hints.The union type
List[str] | set[str] | tuple[str, ...] | Anyeffectively becomesAnydue to theAnyinclusion. If flexibility is needed, considerIterable[str] | Noneinstead for clearer intent.♻️ Suggested type hint refinement
- filterable_relations: List[str] | set[str] | tuple[str, ...] | Any = (), - default_expand_relations: List[str] | set[str] | tuple[str, ...] | Any = (), + filterable_relations: Iterable[str] | None = None, + default_expand_relations: Iterable[str] | None = None,This would require updating the default handling in lines 1654-1661 accordingly.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@automem/api/recall.py` around lines 1628 - 1629, The parameters filterable_relations and default_expand_relations are overly broad because including Any defeats the type check; change their annotations from "List[str] | set[str] | tuple[str, ...] | Any" to "Iterable[str] | None" and set their defaults to None. Then update the function logic that normalizes these params (the block that currently treats empty tuples as defaults) to treat None as meaning "no relations" (e.g., convert None to an empty list/tuple where needed) so downstream code using filterable_relations and default_expand_relations behaves the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@automem/api/recall.py`:
- Around line 1925-1940: The f-string prefix on the static literal segment is
unnecessary: change the concatenation that builds the Cypher fragment from "-[r'
+ rel_pattern + f']-'" to use a normal string for the trailing part (e.g., "-[r"
+ rel_pattern + "]-" or combine with rel_pattern via f"...{rel_pattern}..."), in
the construction of rel_pattern and query (refer to variables rel_pattern, query
and query_relation_types) so the interpolation has no stray f'' prefix and the
resulting Cypher remains the same.
---
Nitpick comments:
In `@automem/api/recall.py`:
- Around line 1628-1629: The parameters filterable_relations and
default_expand_relations are overly broad because including Any defeats the type
check; change their annotations from "List[str] | set[str] | tuple[str, ...] |
Any" to "Iterable[str] | None" and set their defaults to None. Then update the
function logic that normalizes these params (the block that currently treats
empty tuples as defaults) to treat None as meaning "no relations" (e.g., convert
None to an empty list/tuple where needed) so downstream code using
filterable_relations and default_expand_relations behaves the same.
In `@automem/config.py`:
- Line 364: ALLOWED_RELATIONS is currently a mutable set which is inconsistent
with other derived collections; change its definition to use an immutable
frozenset by constructing ALLOWED_RELATIONS from FILTERABLE_RELATIONS (e.g.,
replace set(FILTERABLE_RELATIONS) with frozenset(FILTERABLE_RELATIONS)) so it
cannot be mutated at runtime and matches the immutability of related constants.
In `@consolidation.py`:
- Around line 735-745: Replace the local allowed_labels set with the canonical
FILTERABLE_RELATIONS constant from automem.config: import FILTERABLE_RELATIONS
and use it (or a set(FILTERABLE_RELATIONS) if needed) in place of allowed_labels
when checking rel_type; keep the existing fallback assignment rel_type =
"RELATES_TO" if rel_type not in the imported set so behavior remains the same.
Ensure you reference the symbol FILTERABLE_RELATIONS and update the check that
currently uses allowed_labels to use that imported constant.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 94c8cc98-9ed5-4536-b3e4-6f57d6ad1ac9
📒 Files selected for processing (20)
INSTALLATION.mdREADME.mdapp.pyautomem/api/graph.pyautomem/api/memory.pyautomem/api/recall.pyautomem/api/runtime_bootstrap.pyautomem/api/runtime_recall_routes.pyautomem/config.pyautomem/consolidation/runtime_routes.pyautomem/runtime_wiring.pyautomem/search/runtime_relations.pyconsolidation.pydocs/API.mddocs/MCP_SSE.mdmcp-sse-server/server.jsscripts/bench/compare_branch.shtests/support/fake_graph.pytests/test_api_endpoints.pytests/test_consolidation_engine.py
- Remove unnecessary f-string prefixes on static Cypher fragments - Narrow type annotations from `Any` union to `Iterable[str] | None` - Make ALLOWED_RELATIONS a frozenset for immutability consistency - Replace hardcoded allowed_labels with canonical FILTERABLE_RELATIONS
🤖 I have created a release *beep* *boop* --- ## [0.15.0](v0.14.0...v0.15.0) (2026-03-12) ### Features * **bench:** add opt-in LoCoMo cat5 judge ([#119](#119)) ([8b7915c](8b7915c)) * **memory:** optimize relationship taxonomy ([#121](#121)) ([605633e](605633e)) ### Bug Fixes * **benchmarks:** correct evaluator bugs, add agent guidelines, establish honest baseline ([#117](#117)) ([d9cbecb](d9cbecb)) * **recall:** priority_ids parameter only boosts relevance ([#79](#79)) ([#125](#125)) ([5d3708c](5d3708c)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Summary
DISCOVEREDcompatibilitybench-compare-branchValidation
make testnpm test(inmcp-sse-server)make bench-compare-branch BRANCH=main CONFIG=baseline BENCH=locomo-mini89.36% (210/235)on this branch vs89.36% (210/235)onmain0.0%across single-hop, temporal, multi-hop, open-domain, and complex reasoningNotes
locomoeval also completed locally at85.21% (1314/1542)with judge off