Skip to content

Commit c4460c5

Browse files
authored
Merge pull request #132 from Dooders/similarity-search-validation
Similarity search validation
2 parents 17d7b05 + 87244f2 commit c4460c5

4 files changed

Lines changed: 171 additions & 35 deletions

File tree

memory/embeddings/vector_store.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,11 @@ def store_memory_vectors(
555555

556556
embeddings = memory_entry.get("embeddings", {})
557557
metadata = memory_entry.get("metadata", {})
558+
559+
# Include content data in the metadata to enable filtering on content.metadata fields
560+
if "content" in memory_entry and isinstance(memory_entry["content"], dict):
561+
metadata["content"] = memory_entry["content"]
562+
logger.debug(f"Including content in vector metadata for memory {memory_id}")
558563

559564
def store_vector(
560565
index,
@@ -674,18 +679,16 @@ def filter_fn(metadata):
674679

675680
# No match found for this key
676681
unmatched_keys.append((key, value))
677-
return False
678682

679683
if unmatched_keys:
680684
logger.debug(
681685
"No matches found for the following keys and values: %s",
682686
unmatched_keys,
683687
)
688+
return False
684689
else:
685690
logger.debug("All filter criteria matched")
686-
# All keys matched
687-
logger.debug("All filter criteria matched")
688-
return True
691+
return True
689692

690693
# Select the appropriate index based on tier
691694
if tier == "im":

memory/search/strategies/similarity.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def __init__(self, memory_system: AgentMemorySystem):
3535
self.vector_store = self.memory_system.vector_store
3636
self.embedding_engine = self.memory_system.embedding_engine
3737
self.config = self.memory_system.config
38+
# self.logger = self.memory_system.logger #! future use
3839

3940
def name(self) -> str:
4041
"""Return the name of the search strategy.

memory/utils/serialization.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,15 +468,18 @@ def load_memory_system_from_json(filepath: str, use_mock_redis: bool = False):
468468
}
469469

470470
# Store the vector
471-
vector_store.store_memory_vectors(memory_copy)
471+
472472

473473
# Determine the tier for the memory
474474
tier = memory_copy.get("tier")
475475
if tier == "stm":
476+
vector_store.store_memory_vectors(memory_copy, tier="stm")
476477
memory_agent.stm_store.store(agent_id, memory_copy)
477478
elif tier == "im":
479+
vector_store.store_memory_vectors(memory_copy, tier="im")
478480
memory_agent.im_store.store(agent_id, memory_copy)
479481
elif tier == "ltm":
482+
vector_store.store_memory_vectors(memory_copy, tier="ltm")
480483
memory_agent.ltm_store.store(memory_copy)
481484
else:
482485
logger.warning(f"Unknown tier '{tier}' for memory {memory_copy.get('memory_id')}")

validation/search/similarity/similarity_test_suite.py

Lines changed: 159 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ def run_basic_tests(self) -> None:
9494
"experiment results",
9595
expected_memory_ids=[
9696
"test-agent-similarity-search-1",
97-
"test-agent-similarity-search-6",
97+
"test-agent-similarity-search-13",
9898
],
99-
min_score=0.5,
99+
min_score=0.2,
100100
metadata_filter={"type": "experiment"},
101101
memory_checksum_map=self.memory_checksum_map,
102102
)
@@ -126,13 +126,10 @@ def run_basic_tests(self) -> None:
126126
# Test 6: Result limit test
127127
self.runner.run_test(
128128
"Limited Results Search",
129-
"data",
130-
expected_memory_ids=[
131-
"test-agent-similarity-search-3",
132-
"test-agent-similarity-search-9",
133-
],
129+
"machine learning model accuracy",
130+
expected_memory_ids=["test-agent-similarity-search-1"],
134131
min_score=0.4,
135-
limit=3,
132+
limit=1,
136133
memory_checksum_map=self.memory_checksum_map,
137134
)
138135

@@ -156,10 +153,10 @@ def run_advanced_tests(self) -> None:
156153
"test-agent-similarity-search-2",
157154
"test-agent-similarity-search-6",
158155
"test-agent-similarity-search-7",
159-
"test-agent-similarity-search-8",
156+
"test-agent-similarity-search-12",
160157
],
161158
tier=None, # Search all tiers
162-
min_score=0.4,
159+
min_score=0.3,
163160
memory_checksum_map=self.memory_checksum_map,
164161
)
165162

@@ -170,44 +167,33 @@ def run_advanced_tests(self) -> None:
170167
expected_memory_ids=[
171168
"test-agent-similarity-search-3",
172169
"test-agent-similarity-search-14",
170+
"test-agent-similarity-search-9",
173171
],
174172
tier="stm",
175173
metadata_filter={"type": "process"},
176174
min_score=0.4,
177175
memory_checksum_map=self.memory_checksum_map,
178176
)
179177

180-
# Test 4: Search with vector directly (instead of text or dictionary)
181-
# This would require getting a vector from somewhere - usually we'd mock this
182-
# Here we're assuming we have a test vector that matches certain memories
183-
test_vector = [0.1] * 384 # Mock vector for testing purposes
184-
self.runner.run_test(
185-
"Direct Vector Search",
186-
test_vector,
187-
expected_memory_ids=["test-agent-similarity-search-1"], # Placeholder
188-
memory_checksum_map=self.memory_checksum_map,
189-
)
190-
191-
# Test 5: Search with combined high threshold and limit
178+
# Test 4: Search with combined high threshold and limit
192179
self.runner.run_test(
193180
"High Threshold Limited Search",
194-
"model deployment pipeline",
195-
expected_memory_ids=["test-agent-similarity-search-10"],
196-
min_score=0.9,
181+
"security anomaly detection",
182+
expected_memory_ids=["test-agent-similarity-search-11"],
183+
min_score=0.7,
197184
limit=1,
198185
memory_checksum_map=self.memory_checksum_map,
199186
)
200187

201-
# Test 6: Search with high importance metadata filter
188+
# Test 5: Search with high importance metadata filter
202189
self.runner.run_test(
203190
"High Importance Filter Search",
204191
"machine learning model",
205192
expected_memory_ids=[
206193
"test-agent-similarity-search-1",
207-
"test-agent-similarity-search-2",
208-
"test-agent-similarity-search-6",
209194
],
210195
metadata_filter={"importance": "high"},
196+
min_score=0.4,
211197
memory_checksum_map=self.memory_checksum_map,
212198
)
213199

@@ -248,8 +234,9 @@ def run_edge_case_tests(self) -> None:
248234
"test-agent-similarity-search-1",
249235
"test-agent-similarity-search-2",
250236
"test-agent-similarity-search-3",
251-
"test-agent-similarity-search-4",
252237
"test-agent-similarity-search-12",
238+
"test-agent-similarity-search-13",
239+
"test-agent-similarity-search-7",
253240
],
254241
memory_checksum_map=self.memory_checksum_map,
255242
min_score=0.265,
@@ -303,7 +290,7 @@ def run_edge_case_tests(self) -> None:
303290
"test-agent-similarity-search-9",
304291
"test-agent-similarity-search-11",
305292
"test-agent-similarity-search-12",
306-
"test-agent-similarity-search-13",
293+
"test-agent-similarity-search-15",
307294
"test-agent-similarity-search-14",
308295
],
309296
min_score=0.1, # Very low threshold
@@ -320,6 +307,148 @@ def run_edge_case_tests(self) -> None:
320307
memory_checksum_map=self.memory_checksum_map,
321308
)
322309

310+
def run_memory_tier_transition_tests(self) -> None:
311+
"""Run tests for memory tier transition scenarios."""
312+
# Test 1: Memory in transition between tiers
313+
self.runner.run_test(
314+
"Memory in Tier Transition",
315+
"deep learning model",
316+
expected_memory_ids=["test-agent-similarity-search-15"],
317+
tier=None, # Search all tiers
318+
min_score=0.4,
319+
memory_checksum_map=self.memory_checksum_map,
320+
)
321+
322+
# Test 2: Memory recently moved to new tier
323+
self.runner.run_test(
324+
"Recently Moved Memory",
325+
"transformer model",
326+
expected_memory_ids=["test-agent-similarity-search-15"],
327+
tier="im", # Search in new tier
328+
min_score=0.4,
329+
memory_checksum_map=self.memory_checksum_map,
330+
)
331+
332+
def run_metadata_filtering_tests(self) -> None:
333+
"""Run tests for complex metadata filtering scenarios."""
334+
# Test 1: Multiple metadata conditions
335+
self.runner.run_test(
336+
"Multiple Metadata Conditions",
337+
"machine learning",
338+
expected_memory_ids=["test-agent-similarity-search-1"],
339+
metadata_filter={
340+
"type": "experiment",
341+
"importance": "high",
342+
"metrics.accuracy": {"$gt": 0.9},
343+
},
344+
min_score=0.4,
345+
memory_checksum_map=self.memory_checksum_map,
346+
)
347+
348+
# Test 2: Nested metadata filtering
349+
self.runner.run_test(
350+
"Nested Metadata Filter",
351+
"data processing",
352+
expected_memory_ids=["test-agent-similarity-search-3"],
353+
metadata_filter={
354+
"content.metadata.type": "process",
355+
"content.metadata.importance": "medium",
356+
},
357+
min_score=0.4,
358+
memory_checksum_map=self.memory_checksum_map,
359+
)
360+
361+
# Test 3: Array metadata filtering
362+
self.runner.run_test(
363+
"Array Metadata Filter",
364+
"machine learning",
365+
expected_memory_ids=[
366+
"test-agent-similarity-search-1",
367+
"test-agent-similarity-search-2",
368+
"test-agent-similarity-search-6",
369+
],
370+
metadata_filter={"content.metadata.tags": {"$in": ["ml", "training"]}},
371+
min_score=0.4,
372+
memory_checksum_map=self.memory_checksum_map,
373+
)
374+
375+
def run_content_structure_tests(self) -> None:
376+
"""Run tests for different content structure scenarios."""
377+
# Test 1: Nested content structure
378+
self.runner.run_test(
379+
"Nested Content Structure",
380+
"performance metrics",
381+
expected_memory_ids=["test-agent-similarity-search-4"],
382+
min_score=0.4,
383+
memory_checksum_map=self.memory_checksum_map,
384+
)
385+
386+
# Test 2: Special characters in content
387+
self.runner.run_test(
388+
"Special Characters Content",
389+
"model optimization & performance!",
390+
expected_memory_ids=["test-agent-similarity-search-12"],
391+
min_score=0.35,
392+
memory_checksum_map=self.memory_checksum_map,
393+
)
394+
395+
# Test 3: Mixed content types
396+
self.runner.run_test(
397+
"Mixed Content Types",
398+
"data validation pipeline",
399+
expected_memory_ids=["test-agent-similarity-search-14"],
400+
min_score=0.4,
401+
memory_checksum_map=self.memory_checksum_map,
402+
)
403+
404+
def run_memory_state_tests(self) -> None:
405+
"""Run tests for different memory states."""
406+
# Test 1: Different compression levels
407+
self.runner.run_test(
408+
"Compressed Memory Search",
409+
"deep learning model",
410+
expected_memory_ids=["test-agent-similarity-search-6"],
411+
min_score=0.4,
412+
memory_checksum_map=self.memory_checksum_map,
413+
)
414+
415+
# Test 2: Different importance scores
416+
self.runner.run_test(
417+
"High Importance Memory Search",
418+
"machine learning model",
419+
expected_memory_ids=[
420+
"test-agent-similarity-search-1",
421+
"test-agent-similarity-search-2",
422+
"test-agent-similarity-search-6",
423+
],
424+
metadata_filter={"importance_score": {"$gt": 0.9}},
425+
min_score=0.4,
426+
memory_checksum_map=self.memory_checksum_map,
427+
)
428+
429+
# Test 3: Different retrieval counts
430+
self.runner.run_test(
431+
"Frequently Retrieved Memory",
432+
"deep learning model",
433+
expected_memory_ids=["test-agent-similarity-search-6"],
434+
metadata_filter={"retrieval_count": {"$gt": 0}},
435+
min_score=0.4,
436+
memory_checksum_map=self.memory_checksum_map,
437+
)
438+
439+
def run_all_tests(self) -> None:
440+
"""Run all test suites."""
441+
self.run_basic_tests()
442+
self.run_advanced_tests()
443+
self.run_edge_case_tests()
444+
self.run_memory_tier_transition_tests()
445+
self.run_metadata_filtering_tests()
446+
self.run_content_structure_tests()
447+
self.run_memory_state_tests()
448+
449+
# Display summary of all test results
450+
self.runner.display_summary()
451+
323452

324453
def main():
325454
"""Run the similarity search test suite."""

0 commit comments

Comments
 (0)