22
33Advanced techniques for optimizing memory recall queries.
44
5- ## Query Expansion
5+ ## Semantic vs Text Search
66
7- Improve recall by expanding queries with related terms :
7+ The library provides two search modes :
88
99``` python
1010from git_notes_memory import get_recall_service
11- from git_notes_memory.search import get_optimizer
1211
1312recall = get_recall_service()
14- optimizer = get_optimizer()
1513
16- # Original query
17- query = " database connection "
14+ # Semantic search (vector similarity) - best for conceptual queries
15+ results = recall.search( " authentication flow " , k = 10 )
1816
19- # Expanded with related terms
20- expanded = optimizer.expand_query(query)
21- # Result: "database connection pool timeout postgres sql"
22-
23- results = recall.search(expanded, limit = 10 )
17+ # Text search (FTS5 keyword matching) - best for exact terms
18+ results = recall.search_text(" JWT token" , limit = 10 )
2419```
2520
26- ## Hybrid Search Strategy
27-
28- Combine semantic and keyword search for best results:
29-
30- ``` python
31- from git_notes_memory.search import get_optimizer
32-
33- optimizer = get_optimizer()
34-
35- # Hybrid search combines:
36- # 1. Vector similarity (semantic meaning)
37- # 2. BM25 keyword matching (exact terms)
38- # 3. Recency weighting (newer memories preferred)
39-
40- results = optimizer.search(
41- query = " authentication JWT tokens" ,
42- semantic_weight = 0.6 , # 60% semantic
43- keyword_weight = 0.3 , # 30% keyword
44- recency_weight = 0.1 , # 10% recency
45- limit = 10
46- )
47- ```
21+ | Mode | Method | Best For |
22+ | ------| --------| ----------|
23+ | Semantic | ` search() ` | Conceptual queries, finding related ideas |
24+ | Text | ` search_text() ` | Exact terms, specific identifiers |
4825
4926## Threshold Tuning
5027
51- Adjust relevance thresholds based on context:
28+ Adjust relevance thresholds based on context using ` min_similarity ` :
5229
5330| Scenario | Threshold | Rationale |
5431| ----------| -----------| -----------|
@@ -58,6 +35,20 @@ Adjust relevance thresholds based on context:
5835| Troubleshooting | 0.55 | Include related issues |
5936
6037``` python
38+ # High precision for direct questions
39+ results = recall.search(
40+ query = " why did we choose PostgreSQL" ,
41+ k = 5 ,
42+ min_similarity = 0.8
43+ )
44+
45+ # Broader search for exploration
46+ results = recall.search(
47+ query = " database" ,
48+ k = 10 ,
49+ min_similarity = 0.5
50+ )
51+
6152# Dynamic threshold based on query type
6253def get_threshold (query_type ):
6354 thresholds = {
@@ -77,22 +68,57 @@ Target specific memory types for faster, more relevant results:
7768# For decision inquiries
7869results = recall.search(
7970 query = " why redis" ,
80- namespace = " decisions " ,
81- limit = 5
71+ k = 5 ,
72+ namespace = " decisions "
8273)
8374
8475# For troubleshooting
8576results = recall.search(
8677 query = " timeout error" ,
87- namespace = " learnings " ,
88- limit = 10
78+ k = 10 ,
79+ namespace = " learnings "
8980)
9081
91- # Multi-namespace search
82+ # For spec-specific context
9283results = recall.search(
93- query = " database" ,
84+ query = " authentication" ,
85+ k = 10 ,
86+ namespace = " decisions" ,
87+ spec = " my-project"
88+ )
89+ ```
90+
91+ ## Multi-Namespace Search
92+
93+ To search across multiple namespaces, query each and merge results:
94+
95+ ``` python
96+ def search_multiple_namespaces (query , namespaces , k_per_ns = 5 ):
97+ """ Search across multiple namespaces, merging results."""
98+ all_results = []
99+
100+ for ns in namespaces:
101+ results = recall.search(query = query, namespace = ns, k = k_per_ns)
102+ all_results.extend(results)
103+
104+ # Sort by score (lower distance = better)
105+ all_results.sort(key = lambda r : r.distance)
106+
107+ # Deduplicate by ID
108+ seen = set ()
109+ unique = []
110+ for r in all_results:
111+ if r.id not in seen:
112+ seen.add(r.id)
113+ unique.append(r)
114+
115+ return unique
116+
117+ # Example: search decisions and patterns together
118+ results = search_multiple_namespaces(
119+ " database" ,
94120 namespaces = [" decisions" , " patterns" ],
95- limit = 10
121+ k_per_ns = 5
96122)
97123```
98124
@@ -110,7 +136,7 @@ def format_for_context(memories, max_chars=500):
110136 content = content[:max_chars] + " ..."
111137 formatted.append({
112138 ' type' : m.namespace,
113- ' summary' : m.title or content[: 50 ] ,
139+ ' summary' : m.summary ,
114140 ' score' : m.score,
115141 ' content' : content
116142 })
@@ -125,9 +151,10 @@ Cache frequent queries for faster recall:
125151from functools import lru_cache
126152
127153@lru_cache (maxsize = 100 )
128- def cached_search (query , namespace = None , limit = 5 ):
154+ def cached_search (query , namespace = None , k = 5 ):
129155 recall = get_recall_service()
130- return recall.search(query, namespace = namespace, limit = limit)
156+ # Convert results to tuple for hashability
157+ return tuple (recall.search(query, namespace = namespace, k = k))
131158
132159# Clear cache when new memories added
133160def on_memory_captured ():
@@ -142,6 +169,7 @@ Monitor search performance:
142169import time
143170
144171def timed_search (query , ** kwargs ):
172+ recall = get_recall_service()
145173 start = time.time()
146174 results = recall.search(query, ** kwargs)
147175 duration = time.time() - start
@@ -157,7 +185,31 @@ def timed_search(query, **kwargs):
157185## Best Practices
158186
1591871 . ** Start specific, then broaden** : Begin with focused queries, expand if no results
160- 2 . ** Use namespace hints** : When query implies a type (e.g., "why" → decisions)
188+ 2 . ** Use namespace hints** : When query implies a type (e.g., "why" -> decisions)
1611893 . ** Limit results** : Surface 3-5 highly relevant memories, not all matches
1621904 . ** Cache common queries** : Project-specific terms are queried repeatedly
1631915 . ** Monitor relevance** : Track which recalled memories users actually reference
192+ 6 . ** Use appropriate search mode** : Semantic for concepts, text for exact matches
193+ 7 . ** Combine with hydration** : Use ` recall_context() ` for search + hydration in one call
194+
195+ ## Convenience Methods
196+
197+ The RecallService provides convenience methods for common patterns:
198+
199+ ``` python
200+ # Search and hydrate in one call
201+ from git_notes_memory.models import HydrationLevel
202+
203+ hydrated = recall.recall_context(
204+ query = " error handling" ,
205+ k = 5 ,
206+ hydration_level = HydrationLevel.FULL
207+ )
208+
209+ # Find similar memories
210+ memory = recall.get(" decisions:abc123:0" )
211+ similar = recall.recall_similar(memory, k = 3 )
212+
213+ # List recent memories
214+ recent = recall.list_recent(limit = 10 , namespace = " learnings" )
215+ ```
0 commit comments