memorygraphMCP 0.11.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- memorygraph/__init__.py +50 -0
- memorygraph/__main__.py +12 -0
- memorygraph/advanced_tools.py +509 -0
- memorygraph/analytics/__init__.py +46 -0
- memorygraph/analytics/advanced_queries.py +727 -0
- memorygraph/backends/__init__.py +21 -0
- memorygraph/backends/base.py +179 -0
- memorygraph/backends/cloud.py +75 -0
- memorygraph/backends/cloud_backend.py +858 -0
- memorygraph/backends/factory.py +577 -0
- memorygraph/backends/falkordb_backend.py +749 -0
- memorygraph/backends/falkordblite_backend.py +746 -0
- memorygraph/backends/ladybugdb_backend.py +242 -0
- memorygraph/backends/memgraph_backend.py +327 -0
- memorygraph/backends/neo4j_backend.py +298 -0
- memorygraph/backends/sqlite_fallback.py +463 -0
- memorygraph/backends/turso.py +448 -0
- memorygraph/cli.py +743 -0
- memorygraph/cloud_database.py +297 -0
- memorygraph/config.py +295 -0
- memorygraph/database.py +933 -0
- memorygraph/graph_analytics.py +631 -0
- memorygraph/integration/__init__.py +69 -0
- memorygraph/integration/context_capture.py +426 -0
- memorygraph/integration/project_analysis.py +583 -0
- memorygraph/integration/workflow_tracking.py +492 -0
- memorygraph/intelligence/__init__.py +59 -0
- memorygraph/intelligence/context_retrieval.py +447 -0
- memorygraph/intelligence/entity_extraction.py +386 -0
- memorygraph/intelligence/pattern_recognition.py +420 -0
- memorygraph/intelligence/temporal.py +374 -0
- memorygraph/migration/__init__.py +27 -0
- memorygraph/migration/manager.py +579 -0
- memorygraph/migration/models.py +142 -0
- memorygraph/migration/scripts/__init__.py +17 -0
- memorygraph/migration/scripts/bitemporal_migration.py +595 -0
- memorygraph/migration/scripts/multitenancy_migration.py +452 -0
- memorygraph/migration_tools_module.py +146 -0
- memorygraph/models.py +684 -0
- memorygraph/proactive/__init__.py +46 -0
- memorygraph/proactive/outcome_learning.py +444 -0
- memorygraph/proactive/predictive.py +410 -0
- memorygraph/proactive/session_briefing.py +399 -0
- memorygraph/relationships.py +668 -0
- memorygraph/server.py +883 -0
- memorygraph/sqlite_database.py +1876 -0
- memorygraph/tools/__init__.py +59 -0
- memorygraph/tools/activity_tools.py +262 -0
- memorygraph/tools/memory_tools.py +315 -0
- memorygraph/tools/migration_tools.py +181 -0
- memorygraph/tools/relationship_tools.py +147 -0
- memorygraph/tools/search_tools.py +406 -0
- memorygraph/tools/temporal_tools.py +339 -0
- memorygraph/utils/__init__.py +10 -0
- memorygraph/utils/context_extractor.py +429 -0
- memorygraph/utils/error_handling.py +151 -0
- memorygraph/utils/export_import.py +425 -0
- memorygraph/utils/graph_algorithms.py +200 -0
- memorygraph/utils/pagination.py +149 -0
- memorygraph/utils/project_detection.py +133 -0
- memorygraphmcp-0.11.7.dist-info/METADATA +970 -0
- memorygraphmcp-0.11.7.dist-info/RECORD +65 -0
- memorygraphmcp-0.11.7.dist-info/WHEEL +4 -0
- memorygraphmcp-0.11.7.dist-info/entry_points.txt +2 -0
- memorygraphmcp-0.11.7.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Advanced relationship management for Claude Code Memory Server.
|
|
3
|
+
|
|
4
|
+
This module implements the full 35-relationship type system with weighted
|
|
5
|
+
relationships, graph analytics, and intelligent relationship evolution.
|
|
6
|
+
|
|
7
|
+
Phase 4 Implementation - Advanced Relationship System
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Dict, List, Optional, Tuple, Set, Any
|
|
12
|
+
from datetime import datetime, timedelta, timezone
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
import logging
|
|
15
|
+
|
|
16
|
+
from .models import (
|
|
17
|
+
RelationshipType,
|
|
18
|
+
RelationshipProperties,
|
|
19
|
+
Relationship,
|
|
20
|
+
Memory,
|
|
21
|
+
RelationshipError
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RelationshipCategory(str, Enum):
|
|
28
|
+
"""
|
|
29
|
+
Categories that group related relationship types together.
|
|
30
|
+
|
|
31
|
+
Each category represents a different semantic dimension of how
|
|
32
|
+
memories can relate to each other.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
CAUSAL = "causal" # Cause-and-effect relationships
|
|
36
|
+
SOLUTION = "solution" # Problem-solving relationships
|
|
37
|
+
CONTEXT = "context" # Environmental/situational relationships
|
|
38
|
+
LEARNING = "learning" # Knowledge building relationships
|
|
39
|
+
SIMILARITY = "similarity" # Similarity and analogy relationships
|
|
40
|
+
WORKFLOW = "workflow" # Sequential and dependency relationships
|
|
41
|
+
QUALITY = "quality" # Effectiveness and preference relationships
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class RelationshipTypeMetadata:
|
|
46
|
+
"""
|
|
47
|
+
Metadata describing a relationship type's characteristics.
|
|
48
|
+
|
|
49
|
+
Attributes:
|
|
50
|
+
category: The category this relationship belongs to
|
|
51
|
+
description: Human-readable description of the relationship
|
|
52
|
+
bidirectional: Whether the relationship implies a reverse relationship
|
|
53
|
+
default_strength: Default strength value (0.0 to 1.0)
|
|
54
|
+
default_confidence: Default confidence value (0.0 to 1.0)
|
|
55
|
+
inverse_type: The inverse relationship type (if bidirectional)
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
category: RelationshipCategory
|
|
59
|
+
description: str
|
|
60
|
+
bidirectional: bool = False
|
|
61
|
+
default_strength: float = 0.5
|
|
62
|
+
default_confidence: float = 0.8
|
|
63
|
+
inverse_type: Optional[RelationshipType] = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Complete metadata for all 35 relationship types
|
|
67
|
+
RELATIONSHIP_TYPE_METADATA: Dict[RelationshipType, RelationshipTypeMetadata] = {
|
|
68
|
+
# Causal relationships (5 types)
|
|
69
|
+
RelationshipType.CAUSES: RelationshipTypeMetadata(
|
|
70
|
+
category=RelationshipCategory.CAUSAL,
|
|
71
|
+
description="Memory A causes or directly triggers Memory B",
|
|
72
|
+
bidirectional=False,
|
|
73
|
+
default_strength=0.8,
|
|
74
|
+
default_confidence=0.7,
|
|
75
|
+
),
|
|
76
|
+
RelationshipType.TRIGGERS: RelationshipTypeMetadata(
|
|
77
|
+
category=RelationshipCategory.CAUSAL,
|
|
78
|
+
description="Memory A initiates or activates Memory B",
|
|
79
|
+
bidirectional=False,
|
|
80
|
+
default_strength=0.7,
|
|
81
|
+
default_confidence=0.7,
|
|
82
|
+
),
|
|
83
|
+
RelationshipType.LEADS_TO: RelationshipTypeMetadata(
|
|
84
|
+
category=RelationshipCategory.CAUSAL,
|
|
85
|
+
description="Memory A eventually results in Memory B",
|
|
86
|
+
bidirectional=False,
|
|
87
|
+
default_strength=0.6,
|
|
88
|
+
default_confidence=0.6,
|
|
89
|
+
),
|
|
90
|
+
RelationshipType.PREVENTS: RelationshipTypeMetadata(
|
|
91
|
+
category=RelationshipCategory.CAUSAL,
|
|
92
|
+
description="Memory A prevents or blocks Memory B from occurring",
|
|
93
|
+
bidirectional=False,
|
|
94
|
+
default_strength=0.7,
|
|
95
|
+
default_confidence=0.7,
|
|
96
|
+
),
|
|
97
|
+
RelationshipType.BREAKS: RelationshipTypeMetadata(
|
|
98
|
+
category=RelationshipCategory.CAUSAL,
|
|
99
|
+
description="Memory A breaks or disrupts Memory B",
|
|
100
|
+
bidirectional=False,
|
|
101
|
+
default_strength=0.8,
|
|
102
|
+
default_confidence=0.7,
|
|
103
|
+
),
|
|
104
|
+
|
|
105
|
+
# Solution relationships (5 types)
|
|
106
|
+
RelationshipType.SOLVES: RelationshipTypeMetadata(
|
|
107
|
+
category=RelationshipCategory.SOLUTION,
|
|
108
|
+
description="Memory A solves the problem described in Memory B",
|
|
109
|
+
bidirectional=False,
|
|
110
|
+
default_strength=0.9,
|
|
111
|
+
default_confidence=0.8,
|
|
112
|
+
),
|
|
113
|
+
RelationshipType.ADDRESSES: RelationshipTypeMetadata(
|
|
114
|
+
category=RelationshipCategory.SOLUTION,
|
|
115
|
+
description="Memory A addresses or partially solves Memory B",
|
|
116
|
+
bidirectional=False,
|
|
117
|
+
default_strength=0.7,
|
|
118
|
+
default_confidence=0.7,
|
|
119
|
+
),
|
|
120
|
+
RelationshipType.ALTERNATIVE_TO: RelationshipTypeMetadata(
|
|
121
|
+
category=RelationshipCategory.SOLUTION,
|
|
122
|
+
description="Memory A is an alternative approach to Memory B",
|
|
123
|
+
bidirectional=True,
|
|
124
|
+
default_strength=0.6,
|
|
125
|
+
default_confidence=0.7,
|
|
126
|
+
inverse_type=RelationshipType.ALTERNATIVE_TO,
|
|
127
|
+
),
|
|
128
|
+
RelationshipType.IMPROVES: RelationshipTypeMetadata(
|
|
129
|
+
category=RelationshipCategory.SOLUTION,
|
|
130
|
+
description="Memory A improves upon Memory B",
|
|
131
|
+
bidirectional=False,
|
|
132
|
+
default_strength=0.7,
|
|
133
|
+
default_confidence=0.7,
|
|
134
|
+
),
|
|
135
|
+
RelationshipType.REPLACES: RelationshipTypeMetadata(
|
|
136
|
+
category=RelationshipCategory.SOLUTION,
|
|
137
|
+
description="Memory A replaces or supersedes Memory B",
|
|
138
|
+
bidirectional=False,
|
|
139
|
+
default_strength=0.8,
|
|
140
|
+
default_confidence=0.8,
|
|
141
|
+
),
|
|
142
|
+
|
|
143
|
+
# Context relationships (5 types)
|
|
144
|
+
RelationshipType.OCCURS_IN: RelationshipTypeMetadata(
|
|
145
|
+
category=RelationshipCategory.CONTEXT,
|
|
146
|
+
description="Memory A occurs within the context of Memory B",
|
|
147
|
+
bidirectional=False,
|
|
148
|
+
default_strength=0.6,
|
|
149
|
+
default_confidence=0.8,
|
|
150
|
+
),
|
|
151
|
+
RelationshipType.APPLIES_TO: RelationshipTypeMetadata(
|
|
152
|
+
category=RelationshipCategory.CONTEXT,
|
|
153
|
+
description="Memory A applies to or is relevant in Memory B context",
|
|
154
|
+
bidirectional=False,
|
|
155
|
+
default_strength=0.6,
|
|
156
|
+
default_confidence=0.7,
|
|
157
|
+
),
|
|
158
|
+
RelationshipType.WORKS_WITH: RelationshipTypeMetadata(
|
|
159
|
+
category=RelationshipCategory.CONTEXT,
|
|
160
|
+
description="Memory A works together with Memory B",
|
|
161
|
+
bidirectional=True,
|
|
162
|
+
default_strength=0.7,
|
|
163
|
+
default_confidence=0.7,
|
|
164
|
+
inverse_type=RelationshipType.WORKS_WITH,
|
|
165
|
+
),
|
|
166
|
+
RelationshipType.REQUIRES: RelationshipTypeMetadata(
|
|
167
|
+
category=RelationshipCategory.CONTEXT,
|
|
168
|
+
description="Memory A requires Memory B to function",
|
|
169
|
+
bidirectional=False,
|
|
170
|
+
default_strength=0.8,
|
|
171
|
+
default_confidence=0.8,
|
|
172
|
+
),
|
|
173
|
+
RelationshipType.USED_IN: RelationshipTypeMetadata(
|
|
174
|
+
category=RelationshipCategory.CONTEXT,
|
|
175
|
+
description="Memory A is used within Memory B",
|
|
176
|
+
bidirectional=False,
|
|
177
|
+
default_strength=0.6,
|
|
178
|
+
default_confidence=0.7,
|
|
179
|
+
),
|
|
180
|
+
|
|
181
|
+
# Learning relationships (5 types)
|
|
182
|
+
RelationshipType.BUILDS_ON: RelationshipTypeMetadata(
|
|
183
|
+
category=RelationshipCategory.LEARNING,
|
|
184
|
+
description="Memory A builds upon knowledge from Memory B",
|
|
185
|
+
bidirectional=False,
|
|
186
|
+
default_strength=0.7,
|
|
187
|
+
default_confidence=0.8,
|
|
188
|
+
),
|
|
189
|
+
RelationshipType.CONTRADICTS: RelationshipTypeMetadata(
|
|
190
|
+
category=RelationshipCategory.LEARNING,
|
|
191
|
+
description="Memory A contradicts information in Memory B",
|
|
192
|
+
bidirectional=True,
|
|
193
|
+
default_strength=0.8,
|
|
194
|
+
default_confidence=0.6,
|
|
195
|
+
inverse_type=RelationshipType.CONTRADICTS,
|
|
196
|
+
),
|
|
197
|
+
RelationshipType.CONFIRMS: RelationshipTypeMetadata(
|
|
198
|
+
category=RelationshipCategory.LEARNING,
|
|
199
|
+
description="Memory A confirms or validates Memory B",
|
|
200
|
+
bidirectional=False,
|
|
201
|
+
default_strength=0.7,
|
|
202
|
+
default_confidence=0.8,
|
|
203
|
+
),
|
|
204
|
+
RelationshipType.GENERALIZES: RelationshipTypeMetadata(
|
|
205
|
+
category=RelationshipCategory.LEARNING,
|
|
206
|
+
description="Memory A is a generalization of Memory B",
|
|
207
|
+
bidirectional=False,
|
|
208
|
+
default_strength=0.6,
|
|
209
|
+
default_confidence=0.7,
|
|
210
|
+
inverse_type=RelationshipType.SPECIALIZES,
|
|
211
|
+
),
|
|
212
|
+
RelationshipType.SPECIALIZES: RelationshipTypeMetadata(
|
|
213
|
+
category=RelationshipCategory.LEARNING,
|
|
214
|
+
description="Memory A is a specialization of Memory B",
|
|
215
|
+
bidirectional=False,
|
|
216
|
+
default_strength=0.6,
|
|
217
|
+
default_confidence=0.7,
|
|
218
|
+
inverse_type=RelationshipType.GENERALIZES,
|
|
219
|
+
),
|
|
220
|
+
|
|
221
|
+
# Similarity relationships (5 types)
|
|
222
|
+
RelationshipType.SIMILAR_TO: RelationshipTypeMetadata(
|
|
223
|
+
category=RelationshipCategory.SIMILARITY,
|
|
224
|
+
description="Memory A is similar to Memory B",
|
|
225
|
+
bidirectional=True,
|
|
226
|
+
default_strength=0.6,
|
|
227
|
+
default_confidence=0.7,
|
|
228
|
+
inverse_type=RelationshipType.SIMILAR_TO,
|
|
229
|
+
),
|
|
230
|
+
RelationshipType.VARIANT_OF: RelationshipTypeMetadata(
|
|
231
|
+
category=RelationshipCategory.SIMILARITY,
|
|
232
|
+
description="Memory A is a variant or version of Memory B",
|
|
233
|
+
bidirectional=False,
|
|
234
|
+
default_strength=0.7,
|
|
235
|
+
default_confidence=0.7,
|
|
236
|
+
),
|
|
237
|
+
RelationshipType.RELATED_TO: RelationshipTypeMetadata(
|
|
238
|
+
category=RelationshipCategory.SIMILARITY,
|
|
239
|
+
description="Memory A is related to Memory B in some way",
|
|
240
|
+
bidirectional=True,
|
|
241
|
+
default_strength=0.5,
|
|
242
|
+
default_confidence=0.6,
|
|
243
|
+
inverse_type=RelationshipType.RELATED_TO,
|
|
244
|
+
),
|
|
245
|
+
RelationshipType.ANALOGY_TO: RelationshipTypeMetadata(
|
|
246
|
+
category=RelationshipCategory.SIMILARITY,
|
|
247
|
+
description="Memory A serves as an analogy for Memory B",
|
|
248
|
+
bidirectional=False,
|
|
249
|
+
default_strength=0.5,
|
|
250
|
+
default_confidence=0.6,
|
|
251
|
+
),
|
|
252
|
+
RelationshipType.OPPOSITE_OF: RelationshipTypeMetadata(
|
|
253
|
+
category=RelationshipCategory.SIMILARITY,
|
|
254
|
+
description="Memory A is the opposite or inverse of Memory B",
|
|
255
|
+
bidirectional=True,
|
|
256
|
+
default_strength=0.7,
|
|
257
|
+
default_confidence=0.7,
|
|
258
|
+
inverse_type=RelationshipType.OPPOSITE_OF,
|
|
259
|
+
),
|
|
260
|
+
|
|
261
|
+
# Workflow relationships (5 types)
|
|
262
|
+
RelationshipType.FOLLOWS: RelationshipTypeMetadata(
|
|
263
|
+
category=RelationshipCategory.WORKFLOW,
|
|
264
|
+
description="Memory A follows Memory B in a sequence",
|
|
265
|
+
bidirectional=False,
|
|
266
|
+
default_strength=0.7,
|
|
267
|
+
default_confidence=0.8,
|
|
268
|
+
),
|
|
269
|
+
RelationshipType.DEPENDS_ON: RelationshipTypeMetadata(
|
|
270
|
+
category=RelationshipCategory.WORKFLOW,
|
|
271
|
+
description="Memory A depends on Memory B being completed first",
|
|
272
|
+
bidirectional=False,
|
|
273
|
+
default_strength=0.8,
|
|
274
|
+
default_confidence=0.8,
|
|
275
|
+
),
|
|
276
|
+
RelationshipType.ENABLES: RelationshipTypeMetadata(
|
|
277
|
+
category=RelationshipCategory.WORKFLOW,
|
|
278
|
+
description="Memory A enables or allows Memory B to occur",
|
|
279
|
+
bidirectional=False,
|
|
280
|
+
default_strength=0.7,
|
|
281
|
+
default_confidence=0.7,
|
|
282
|
+
),
|
|
283
|
+
RelationshipType.BLOCKS: RelationshipTypeMetadata(
|
|
284
|
+
category=RelationshipCategory.WORKFLOW,
|
|
285
|
+
description="Memory A blocks or prevents Memory B from proceeding",
|
|
286
|
+
bidirectional=False,
|
|
287
|
+
default_strength=0.8,
|
|
288
|
+
default_confidence=0.7,
|
|
289
|
+
),
|
|
290
|
+
RelationshipType.PARALLEL_TO: RelationshipTypeMetadata(
|
|
291
|
+
category=RelationshipCategory.WORKFLOW,
|
|
292
|
+
description="Memory A can occur in parallel with Memory B",
|
|
293
|
+
bidirectional=True,
|
|
294
|
+
default_strength=0.6,
|
|
295
|
+
default_confidence=0.7,
|
|
296
|
+
inverse_type=RelationshipType.PARALLEL_TO,
|
|
297
|
+
),
|
|
298
|
+
|
|
299
|
+
# Quality relationships (5 types)
|
|
300
|
+
RelationshipType.EFFECTIVE_FOR: RelationshipTypeMetadata(
|
|
301
|
+
category=RelationshipCategory.QUALITY,
|
|
302
|
+
description="Memory A is effective for solving Memory B",
|
|
303
|
+
bidirectional=False,
|
|
304
|
+
default_strength=0.8,
|
|
305
|
+
default_confidence=0.7,
|
|
306
|
+
),
|
|
307
|
+
RelationshipType.INEFFECTIVE_FOR: RelationshipTypeMetadata(
|
|
308
|
+
category=RelationshipCategory.QUALITY,
|
|
309
|
+
description="Memory A is ineffective for solving Memory B",
|
|
310
|
+
bidirectional=False,
|
|
311
|
+
default_strength=0.7,
|
|
312
|
+
default_confidence=0.7,
|
|
313
|
+
),
|
|
314
|
+
RelationshipType.PREFERRED_OVER: RelationshipTypeMetadata(
|
|
315
|
+
category=RelationshipCategory.QUALITY,
|
|
316
|
+
description="Memory A is preferred over Memory B",
|
|
317
|
+
bidirectional=False,
|
|
318
|
+
default_strength=0.7,
|
|
319
|
+
default_confidence=0.7,
|
|
320
|
+
),
|
|
321
|
+
RelationshipType.DEPRECATED_BY: RelationshipTypeMetadata(
|
|
322
|
+
category=RelationshipCategory.QUALITY,
|
|
323
|
+
description="Memory A is deprecated by Memory B",
|
|
324
|
+
bidirectional=False,
|
|
325
|
+
default_strength=0.8,
|
|
326
|
+
default_confidence=0.8,
|
|
327
|
+
inverse_type=RelationshipType.REPLACES,
|
|
328
|
+
),
|
|
329
|
+
RelationshipType.VALIDATED_BY: RelationshipTypeMetadata(
|
|
330
|
+
category=RelationshipCategory.QUALITY,
|
|
331
|
+
description="Memory A is validated or proven by Memory B",
|
|
332
|
+
bidirectional=False,
|
|
333
|
+
default_strength=0.8,
|
|
334
|
+
default_confidence=0.8,
|
|
335
|
+
),
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
class RelationshipManager:
|
|
340
|
+
"""
|
|
341
|
+
Manages advanced relationship operations including creation,
|
|
342
|
+
validation, evolution, and graph analytics.
|
|
343
|
+
|
|
344
|
+
This class provides high-level relationship management on top of
|
|
345
|
+
the backend storage layer.
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
def __init__(self):
|
|
349
|
+
"""Initialize the relationship manager."""
|
|
350
|
+
self.metadata = RELATIONSHIP_TYPE_METADATA
|
|
351
|
+
|
|
352
|
+
def get_relationship_metadata(
|
|
353
|
+
self,
|
|
354
|
+
relationship_type: RelationshipType
|
|
355
|
+
) -> RelationshipTypeMetadata:
|
|
356
|
+
"""
|
|
357
|
+
Get metadata for a relationship type.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
relationship_type: The relationship type to look up
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Metadata for the relationship type
|
|
364
|
+
|
|
365
|
+
Raises:
|
|
366
|
+
ValueError: If relationship type is not recognized
|
|
367
|
+
"""
|
|
368
|
+
if relationship_type not in self.metadata:
|
|
369
|
+
raise ValueError(f"Unknown relationship type: {relationship_type}")
|
|
370
|
+
|
|
371
|
+
return self.metadata[relationship_type]
|
|
372
|
+
|
|
373
|
+
def get_relationship_category(
|
|
374
|
+
self,
|
|
375
|
+
relationship_type: RelationshipType
|
|
376
|
+
) -> RelationshipCategory:
|
|
377
|
+
"""
|
|
378
|
+
Get the category for a relationship type.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
relationship_type: The relationship type
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
The category this relationship belongs to
|
|
385
|
+
"""
|
|
386
|
+
metadata = self.get_relationship_metadata(relationship_type)
|
|
387
|
+
return metadata.category
|
|
388
|
+
|
|
389
|
+
def get_types_by_category(
|
|
390
|
+
self,
|
|
391
|
+
category: RelationshipCategory
|
|
392
|
+
) -> List[RelationshipType]:
|
|
393
|
+
"""
|
|
394
|
+
Get all relationship types in a category.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
category: The relationship category
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
List of relationship types in that category
|
|
401
|
+
"""
|
|
402
|
+
return [
|
|
403
|
+
rel_type for rel_type, meta in self.metadata.items()
|
|
404
|
+
if meta.category == category
|
|
405
|
+
]
|
|
406
|
+
|
|
407
|
+
def create_relationship_properties(
|
|
408
|
+
self,
|
|
409
|
+
relationship_type: RelationshipType,
|
|
410
|
+
strength: Optional[float] = None,
|
|
411
|
+
confidence: Optional[float] = None,
|
|
412
|
+
context: Optional[str] = None,
|
|
413
|
+
**kwargs
|
|
414
|
+
) -> RelationshipProperties:
|
|
415
|
+
"""
|
|
416
|
+
Create relationship properties with appropriate defaults.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
relationship_type: The type of relationship
|
|
420
|
+
strength: Custom strength value (uses default if None)
|
|
421
|
+
confidence: Custom confidence value (uses default if None)
|
|
422
|
+
context: Optional context information
|
|
423
|
+
**kwargs: Additional property values
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
RelationshipProperties instance with appropriate defaults
|
|
427
|
+
"""
|
|
428
|
+
metadata = self.get_relationship_metadata(relationship_type)
|
|
429
|
+
|
|
430
|
+
return RelationshipProperties(
|
|
431
|
+
strength=strength if strength is not None else metadata.default_strength,
|
|
432
|
+
confidence=confidence if confidence is not None else metadata.default_confidence,
|
|
433
|
+
context=context,
|
|
434
|
+
**kwargs
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
def validate_relationship(
|
|
438
|
+
self,
|
|
439
|
+
from_memory_id: str,
|
|
440
|
+
to_memory_id: str,
|
|
441
|
+
relationship_type: RelationshipType
|
|
442
|
+
) -> Tuple[bool, Optional[str]]:
|
|
443
|
+
"""
|
|
444
|
+
Validate a relationship before creation.
|
|
445
|
+
|
|
446
|
+
Args:
|
|
447
|
+
from_memory_id: Source memory ID
|
|
448
|
+
to_memory_id: Target memory ID
|
|
449
|
+
relationship_type: Type of relationship
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Tuple of (is_valid, error_message)
|
|
453
|
+
"""
|
|
454
|
+
# Check for self-relationships
|
|
455
|
+
if from_memory_id == to_memory_id:
|
|
456
|
+
return False, "Cannot create relationship from memory to itself"
|
|
457
|
+
|
|
458
|
+
# Validate relationship type exists
|
|
459
|
+
if relationship_type not in self.metadata:
|
|
460
|
+
return False, f"Unknown relationship type: {relationship_type}"
|
|
461
|
+
|
|
462
|
+
# All basic validations passed
|
|
463
|
+
return True, None
|
|
464
|
+
|
|
465
|
+
def should_create_inverse(
|
|
466
|
+
self,
|
|
467
|
+
relationship_type: RelationshipType
|
|
468
|
+
) -> Tuple[bool, Optional[RelationshipType]]:
|
|
469
|
+
"""
|
|
470
|
+
Check if an inverse relationship should be created.
|
|
471
|
+
|
|
472
|
+
Args:
|
|
473
|
+
relationship_type: The relationship type
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
Tuple of (should_create, inverse_type)
|
|
477
|
+
"""
|
|
478
|
+
metadata = self.get_relationship_metadata(relationship_type)
|
|
479
|
+
|
|
480
|
+
if metadata.bidirectional and metadata.inverse_type:
|
|
481
|
+
return True, metadata.inverse_type
|
|
482
|
+
|
|
483
|
+
return False, None
|
|
484
|
+
|
|
485
|
+
def calculate_relationship_strength(
|
|
486
|
+
self,
|
|
487
|
+
base_strength: float,
|
|
488
|
+
evidence_count: int,
|
|
489
|
+
success_rate: Optional[float] = None,
|
|
490
|
+
age_days: Optional[float] = None,
|
|
491
|
+
decay_rate: float = 0.01
|
|
492
|
+
) -> float:
|
|
493
|
+
"""
|
|
494
|
+
Calculate effective relationship strength considering multiple factors.
|
|
495
|
+
|
|
496
|
+
Args:
|
|
497
|
+
base_strength: Base strength value
|
|
498
|
+
evidence_count: Number of times relationship has been observed
|
|
499
|
+
success_rate: Success rate for solution relationships (0.0-1.0)
|
|
500
|
+
age_days: Age of relationship in days
|
|
501
|
+
decay_rate: Daily decay rate for strength
|
|
502
|
+
|
|
503
|
+
Returns:
|
|
504
|
+
Calculated effective strength (0.0-1.0)
|
|
505
|
+
"""
|
|
506
|
+
strength = base_strength
|
|
507
|
+
|
|
508
|
+
# Boost based on evidence count (logarithmic)
|
|
509
|
+
if evidence_count > 1:
|
|
510
|
+
evidence_boost = min(0.2, 0.05 * (evidence_count - 1) ** 0.5)
|
|
511
|
+
strength = min(1.0, strength + evidence_boost)
|
|
512
|
+
|
|
513
|
+
# Adjust based on success rate
|
|
514
|
+
if success_rate is not None:
|
|
515
|
+
strength = strength * (0.5 + 0.5 * success_rate)
|
|
516
|
+
|
|
517
|
+
# Apply time-based decay
|
|
518
|
+
if age_days is not None and age_days > 0:
|
|
519
|
+
decay_factor = max(0.5, 1.0 - (decay_rate * age_days))
|
|
520
|
+
strength = strength * decay_factor
|
|
521
|
+
|
|
522
|
+
# Ensure within bounds
|
|
523
|
+
return max(0.0, min(1.0, strength))
|
|
524
|
+
|
|
525
|
+
def reinforce_relationship_properties(
|
|
526
|
+
self,
|
|
527
|
+
properties: RelationshipProperties,
|
|
528
|
+
success: bool = True,
|
|
529
|
+
strength_increase: float = 0.05,
|
|
530
|
+
confidence_increase: float = 0.03
|
|
531
|
+
) -> RelationshipProperties:
|
|
532
|
+
"""
|
|
533
|
+
Reinforce relationship properties based on successful use.
|
|
534
|
+
|
|
535
|
+
Args:
|
|
536
|
+
properties: Current relationship properties
|
|
537
|
+
success: Whether this reinforcement is from a success
|
|
538
|
+
strength_increase: How much to increase strength
|
|
539
|
+
confidence_increase: How much to increase confidence
|
|
540
|
+
|
|
541
|
+
Returns:
|
|
542
|
+
Updated relationship properties
|
|
543
|
+
"""
|
|
544
|
+
new_evidence = properties.evidence_count + 1
|
|
545
|
+
new_validation = properties.validation_count + (1 if success else 0)
|
|
546
|
+
new_counter = properties.counter_evidence_count + (0 if success else 1)
|
|
547
|
+
|
|
548
|
+
# Calculate new success rate
|
|
549
|
+
total_evidence = new_validation + new_counter
|
|
550
|
+
new_success_rate = new_validation / total_evidence if total_evidence > 0 else None
|
|
551
|
+
|
|
552
|
+
# Adjust strength and confidence
|
|
553
|
+
if success:
|
|
554
|
+
new_strength = min(1.0, properties.strength + strength_increase)
|
|
555
|
+
new_confidence = min(1.0, properties.confidence + confidence_increase)
|
|
556
|
+
else:
|
|
557
|
+
new_strength = max(0.1, properties.strength - strength_increase * 0.5)
|
|
558
|
+
new_confidence = max(0.1, properties.confidence - confidence_increase * 0.5)
|
|
559
|
+
|
|
560
|
+
return RelationshipProperties(
|
|
561
|
+
strength=new_strength,
|
|
562
|
+
confidence=new_confidence,
|
|
563
|
+
context=properties.context,
|
|
564
|
+
evidence_count=new_evidence,
|
|
565
|
+
success_rate=new_success_rate,
|
|
566
|
+
created_at=properties.created_at,
|
|
567
|
+
last_validated=datetime.now(timezone.utc),
|
|
568
|
+
validation_count=new_validation,
|
|
569
|
+
counter_evidence_count=new_counter
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
def find_contradictory_relationships(
|
|
573
|
+
self,
|
|
574
|
+
relationships: List[Relationship]
|
|
575
|
+
) -> List[Tuple[Relationship, Relationship]]:
|
|
576
|
+
"""
|
|
577
|
+
Find pairs of relationships that may be contradictory.
|
|
578
|
+
|
|
579
|
+
Args:
|
|
580
|
+
relationships: List of relationships to analyze
|
|
581
|
+
|
|
582
|
+
Returns:
|
|
583
|
+
List of contradictory relationship pairs
|
|
584
|
+
"""
|
|
585
|
+
contradictions = []
|
|
586
|
+
|
|
587
|
+
# Look for explicit contradictions
|
|
588
|
+
for i, rel1 in enumerate(relationships):
|
|
589
|
+
for rel2 in relationships[i+1:]:
|
|
590
|
+
# Same nodes, contradictory types
|
|
591
|
+
if (rel1.from_memory_id == rel2.from_memory_id and
|
|
592
|
+
rel1.to_memory_id == rel2.to_memory_id):
|
|
593
|
+
|
|
594
|
+
# Check for contradictory relationship types
|
|
595
|
+
contradictory_pairs = [
|
|
596
|
+
(RelationshipType.SOLVES, RelationshipType.INEFFECTIVE_FOR),
|
|
597
|
+
(RelationshipType.CONFIRMS, RelationshipType.CONTRADICTS),
|
|
598
|
+
(RelationshipType.EFFECTIVE_FOR, RelationshipType.INEFFECTIVE_FOR),
|
|
599
|
+
(RelationshipType.ENABLES, RelationshipType.BLOCKS),
|
|
600
|
+
(RelationshipType.PREVENTS, RelationshipType.CAUSES),
|
|
601
|
+
]
|
|
602
|
+
|
|
603
|
+
for type_a, type_b in contradictory_pairs:
|
|
604
|
+
if ((rel1.type == type_a and rel2.type == type_b) or
|
|
605
|
+
(rel1.type == type_b and rel2.type == type_a)):
|
|
606
|
+
contradictions.append((rel1, rel2))
|
|
607
|
+
|
|
608
|
+
return contradictions
|
|
609
|
+
|
|
610
|
+
def suggest_relationship_type(
|
|
611
|
+
self,
|
|
612
|
+
from_memory: Memory,
|
|
613
|
+
to_memory: Memory,
|
|
614
|
+
context: Optional[str] = None
|
|
615
|
+
) -> List[Tuple[RelationshipType, float]]:
|
|
616
|
+
"""
|
|
617
|
+
Suggest appropriate relationship types based on memory types.
|
|
618
|
+
|
|
619
|
+
Args:
|
|
620
|
+
from_memory: Source memory
|
|
621
|
+
to_memory: Target memory
|
|
622
|
+
context: Optional context information
|
|
623
|
+
|
|
624
|
+
Returns:
|
|
625
|
+
List of (relationship_type, confidence) tuples, sorted by confidence
|
|
626
|
+
"""
|
|
627
|
+
suggestions: List[Tuple[RelationshipType, float]] = []
|
|
628
|
+
|
|
629
|
+
# Problem -> Solution relationships
|
|
630
|
+
if from_memory.type.value == "solution" and to_memory.type.value == "problem":
|
|
631
|
+
suggestions.append((RelationshipType.SOLVES, 0.8))
|
|
632
|
+
suggestions.append((RelationshipType.ADDRESSES, 0.7))
|
|
633
|
+
|
|
634
|
+
# Error -> Fix relationships
|
|
635
|
+
if from_memory.type.value == "fix" and to_memory.type.value == "error":
|
|
636
|
+
suggestions.append((RelationshipType.SOLVES, 0.9))
|
|
637
|
+
|
|
638
|
+
# Technology relationships
|
|
639
|
+
if (from_memory.type.value == "technology" and
|
|
640
|
+
to_memory.type.value == "technology"):
|
|
641
|
+
suggestions.append((RelationshipType.WORKS_WITH, 0.6))
|
|
642
|
+
suggestions.append((RelationshipType.ALTERNATIVE_TO, 0.5))
|
|
643
|
+
|
|
644
|
+
# Workflow relationships
|
|
645
|
+
if from_memory.type.value == "task" and to_memory.type.value == "task":
|
|
646
|
+
suggestions.append((RelationshipType.FOLLOWS, 0.6))
|
|
647
|
+
suggestions.append((RelationshipType.DEPENDS_ON, 0.5))
|
|
648
|
+
suggestions.append((RelationshipType.PARALLEL_TO, 0.4))
|
|
649
|
+
|
|
650
|
+
# Code pattern relationships
|
|
651
|
+
if (from_memory.type.value == "code_pattern" and
|
|
652
|
+
to_memory.type.value == "code_pattern"):
|
|
653
|
+
suggestions.append((RelationshipType.SIMILAR_TO, 0.6))
|
|
654
|
+
suggestions.append((RelationshipType.VARIANT_OF, 0.5))
|
|
655
|
+
suggestions.append((RelationshipType.IMPROVES, 0.4))
|
|
656
|
+
|
|
657
|
+
# Default fallback
|
|
658
|
+
if not suggestions:
|
|
659
|
+
suggestions.append((RelationshipType.RELATED_TO, 0.5))
|
|
660
|
+
|
|
661
|
+
# Sort by confidence descending
|
|
662
|
+
suggestions.sort(key=lambda x: x[1], reverse=True)
|
|
663
|
+
|
|
664
|
+
return suggestions
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
# Singleton instance for easy access
|
|
668
|
+
relationship_manager = RelationshipManager()
|