htm 0.0.14 → 0.0.15
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +269 -79
- data/db/migrate/00003_create_file_sources.rb +5 -0
- data/db/migrate/00004_create_nodes.rb +17 -0
- data/db/migrate/00005_create_tags.rb +7 -0
- data/db/migrate/00006_create_node_tags.rb +2 -0
- data/db/migrate/00007_create_robot_nodes.rb +7 -0
- data/db/schema.sql +41 -29
- data/docs/api/yard/HTM/Configuration.md +54 -0
- data/docs/api/yard/HTM/Database.md +13 -10
- data/docs/api/yard/HTM/EmbeddingService.md +5 -1
- data/docs/api/yard/HTM/LongTermMemory.md +18 -277
- data/docs/api/yard/HTM/PropositionError.md +18 -0
- data/docs/api/yard/HTM/PropositionService.md +66 -0
- data/docs/api/yard/HTM/QueryCache.md +88 -0
- data/docs/api/yard/HTM/RobotGroup.md +481 -0
- data/docs/api/yard/HTM/SqlBuilder.md +108 -0
- data/docs/api/yard/HTM/TagService.md +4 -0
- data/docs/api/yard/HTM/Telemetry/NullInstrument.md +13 -0
- data/docs/api/yard/HTM/Telemetry/NullMeter.md +15 -0
- data/docs/api/yard/HTM/Telemetry.md +109 -0
- data/docs/api/yard/HTM/WorkingMemoryChannel.md +176 -0
- data/docs/api/yard/HTM.md +11 -23
- data/docs/api/yard/index.csv +102 -25
- data/docs/api/yard-reference.md +8 -0
- data/docs/assets/images/multi-provider-failover.svg +51 -0
- data/docs/assets/images/robot-group-architecture.svg +65 -0
- data/docs/database/README.md +3 -3
- data/docs/database/public.file_sources.svg +29 -21
- data/docs/database/public.node_tags.md +2 -0
- data/docs/database/public.node_tags.svg +53 -41
- data/docs/database/public.nodes.md +2 -0
- data/docs/database/public.nodes.svg +52 -40
- data/docs/database/public.robot_nodes.md +2 -0
- data/docs/database/public.robot_nodes.svg +30 -22
- data/docs/database/public.robots.svg +16 -12
- data/docs/database/public.tags.md +3 -0
- data/docs/database/public.tags.svg +41 -33
- data/docs/database/schema.json +66 -0
- data/docs/database/schema.svg +60 -48
- data/docs/development/index.md +13 -0
- data/docs/development/rake-tasks.md +1068 -0
- data/docs/getting-started/quick-start.md +144 -155
- data/docs/guides/adding-memories.md +2 -3
- data/docs/guides/context-assembly.md +185 -184
- data/docs/guides/getting-started.md +154 -148
- data/docs/guides/index.md +7 -0
- data/docs/guides/long-term-memory.md +60 -92
- data/docs/guides/mcp-server.md +617 -0
- data/docs/guides/multi-robot.md +249 -345
- data/docs/guides/recalling-memories.md +153 -163
- data/docs/guides/robot-groups.md +604 -0
- data/docs/guides/search-strategies.md +61 -58
- data/docs/guides/working-memory.md +103 -136
- data/docs/index.md +30 -26
- data/examples/robot_groups/robot_worker.rb +1 -2
- data/examples/robot_groups/same_process.rb +1 -4
- data/lib/htm/robot_group.rb +721 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory_channel.rb +250 -0
- data/lib/htm.rb +2 -0
- data/mkdocs.yml +2 -0
- metadata +18 -9
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +0 -12
- data/db/migrate/00010_add_soft_delete_to_associations.rb +0 -29
- data/db/migrate/00011_add_performance_indexes.rb +0 -21
- data/db/migrate/00012_add_tags_trigram_index.rb +0 -18
- data/db/migrate/00013_enable_lz4_compression.rb +0 -43
- data/examples/robot_groups/lib/robot_group.rb +0 -419
- data/examples/robot_groups/lib/working_memory_channel.rb +0 -140
|
@@ -106,94 +106,79 @@ puts "Robot ID: #{htm.robot_id}"
|
|
|
106
106
|
|
|
107
107
|
```ruby
|
|
108
108
|
# Add a fact about the user
|
|
109
|
-
htm.
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
importance: 8.0, # Importance score (0-10)
|
|
114
|
-
tags: ["user", "identity"] # Tags for categorization
|
|
109
|
+
node_id = htm.remember(
|
|
110
|
+
"The user's name is Alice", # Content
|
|
111
|
+
tags: ["user", "identity"], # Tags for categorization
|
|
112
|
+
metadata: { category: "fact" } # Metadata for priority/categorization
|
|
115
113
|
)
|
|
116
114
|
|
|
117
|
-
puts "Memory added
|
|
115
|
+
puts "Memory added with ID: #{node_id}"
|
|
118
116
|
```
|
|
119
117
|
|
|
120
|
-
###
|
|
118
|
+
### Using Tags and Metadata
|
|
121
119
|
|
|
122
|
-
HTM
|
|
120
|
+
HTM uses hierarchical tags and flexible metadata to categorize memories:
|
|
123
121
|
|
|
124
122
|
```ruby
|
|
125
123
|
# Facts: Immutable truths
|
|
126
|
-
htm.
|
|
127
|
-
"fact_001",
|
|
124
|
+
htm.remember(
|
|
128
125
|
"The user lives in San Francisco",
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
tags: ["user:location"],
|
|
127
|
+
metadata: { category: "fact", priority: "high" }
|
|
131
128
|
)
|
|
132
129
|
|
|
133
130
|
# Context: Conversation state
|
|
134
|
-
htm.
|
|
135
|
-
"context_001",
|
|
131
|
+
htm.remember(
|
|
136
132
|
"Currently discussing database architecture for a new project",
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
tags: ["conversation:topic"],
|
|
134
|
+
metadata: { category: "context" }
|
|
139
135
|
)
|
|
140
136
|
|
|
141
137
|
# Preferences: User preferences
|
|
142
|
-
htm.
|
|
143
|
-
"pref_001",
|
|
138
|
+
htm.remember(
|
|
144
139
|
"User prefers Ruby over Python for scripting",
|
|
145
|
-
|
|
146
|
-
|
|
140
|
+
tags: ["user:preference", "language:ruby"],
|
|
141
|
+
metadata: { category: "preference" }
|
|
147
142
|
)
|
|
148
143
|
|
|
149
144
|
# Decisions: Design decisions
|
|
150
|
-
htm.
|
|
151
|
-
"decision_001",
|
|
145
|
+
htm.remember(
|
|
152
146
|
"Decided to use PostgreSQL instead of MongoDB for better consistency",
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
tags: ["architecture", "database"]
|
|
147
|
+
tags: ["architecture", "database:postgresql"],
|
|
148
|
+
metadata: { category: "decision", priority: "critical" }
|
|
156
149
|
)
|
|
157
150
|
|
|
158
151
|
# Code: Code snippets
|
|
159
|
-
htm.
|
|
160
|
-
"code_001",
|
|
152
|
+
htm.remember(
|
|
161
153
|
"def greet(name)\n puts \"Hello, \#{name}!\"\nend",
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
tags: ["ruby", "functions"]
|
|
154
|
+
tags: ["code:ruby", "pattern:function"],
|
|
155
|
+
metadata: { category: "code", language: "ruby" }
|
|
165
156
|
)
|
|
166
157
|
|
|
167
158
|
# Questions: Unresolved questions
|
|
168
|
-
htm.
|
|
169
|
-
"question_001",
|
|
159
|
+
htm.remember(
|
|
170
160
|
"Should we add Redis caching to improve performance?",
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
tags: ["performance", "caching"]
|
|
161
|
+
tags: ["performance", "caching"],
|
|
162
|
+
metadata: { category: "question", resolved: false }
|
|
174
163
|
)
|
|
175
164
|
```
|
|
176
165
|
|
|
177
|
-
!!! tip "
|
|
178
|
-
- Use
|
|
179
|
-
- Use
|
|
180
|
-
-
|
|
181
|
-
- Use `:decision` for important architectural choices
|
|
182
|
-
- Use `:code` for code examples and snippets
|
|
183
|
-
- Use `:question` for tracking open questions
|
|
166
|
+
!!! tip "Organizing Memories"
|
|
167
|
+
- Use hierarchical tags (e.g., `user:preference`, `database:postgresql`)
|
|
168
|
+
- Use metadata for structured data (priority, category, resolved status)
|
|
169
|
+
- Combine tags and metadata for powerful filtering
|
|
184
170
|
|
|
185
171
|
### Retrieving Memories
|
|
186
172
|
|
|
187
|
-
Retrieve a specific memory by its
|
|
173
|
+
Retrieve a specific memory by its ID:
|
|
188
174
|
|
|
189
175
|
```ruby
|
|
190
|
-
|
|
176
|
+
# Retrieve by ID (returned from remember())
|
|
177
|
+
memory = htm.long_term_memory.retrieve(node_id)
|
|
191
178
|
|
|
192
179
|
if memory
|
|
193
|
-
puts "Found: #{memory
|
|
194
|
-
puts "
|
|
195
|
-
puts "Created: #{memory['created_at']}"
|
|
196
|
-
puts "Importance: #{memory['importance']}"
|
|
180
|
+
puts "Found: #{memory.content}"
|
|
181
|
+
puts "Created: #{memory.created_at}"
|
|
197
182
|
end
|
|
198
183
|
```
|
|
199
184
|
|
|
@@ -204,13 +189,14 @@ Use HTM's RAG capabilities to recall relevant memories:
|
|
|
204
189
|
```ruby
|
|
205
190
|
# Recall memories about databases from the last week
|
|
206
191
|
memories = htm.recall(
|
|
192
|
+
"database architecture", # Topic is first positional argument
|
|
207
193
|
timeframe: "last week",
|
|
208
|
-
|
|
209
|
-
|
|
194
|
+
limit: 10,
|
|
195
|
+
raw: true # Get full hash with similarity scores
|
|
210
196
|
)
|
|
211
197
|
|
|
212
198
|
memories.each do |memory|
|
|
213
|
-
puts "- #{memory['
|
|
199
|
+
puts "- #{memory['content']}"
|
|
214
200
|
puts " Similarity: #{memory['similarity']}"
|
|
215
201
|
puts
|
|
216
202
|
end
|
|
@@ -225,7 +211,7 @@ Assemble working memory into context for your LLM:
|
|
|
225
211
|
|
|
226
212
|
```ruby
|
|
227
213
|
# Get a balanced mix of important and recent memories
|
|
228
|
-
context = htm.
|
|
214
|
+
context = htm.working_memory.assemble_context(
|
|
229
215
|
strategy: :balanced,
|
|
230
216
|
max_tokens: 50_000
|
|
231
217
|
)
|
|
@@ -260,27 +246,22 @@ class ConversationTracker
|
|
|
260
246
|
@turn += 1
|
|
261
247
|
|
|
262
248
|
# Store user message
|
|
263
|
-
@htm.
|
|
264
|
-
"turn_#{@turn}_user",
|
|
249
|
+
@htm.remember(
|
|
265
250
|
user_message,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
tags: ["conversation", "user"]
|
|
251
|
+
tags: ["conversation", "user", "turn:#{@turn}"],
|
|
252
|
+
metadata: { category: "context", turn: @turn, role: "user" }
|
|
269
253
|
)
|
|
270
254
|
|
|
271
255
|
# Store assistant response
|
|
272
|
-
@htm.
|
|
273
|
-
"turn_#{@turn}_assistant",
|
|
256
|
+
@htm.remember(
|
|
274
257
|
assistant_response,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
tags: ["conversation", "assistant"],
|
|
278
|
-
related_to: ["turn_#{@turn}_user"]
|
|
258
|
+
tags: ["conversation", "assistant", "turn:#{@turn}"],
|
|
259
|
+
metadata: { category: "context", turn: @turn, role: "assistant" }
|
|
279
260
|
)
|
|
280
261
|
end
|
|
281
262
|
|
|
282
263
|
def recall_context
|
|
283
|
-
@htm.
|
|
264
|
+
@htm.working_memory.assemble_context(strategy: :recent, max_tokens: 10_000)
|
|
284
265
|
end
|
|
285
266
|
end
|
|
286
267
|
```
|
|
@@ -295,22 +276,19 @@ class KnowledgeBase
|
|
|
295
276
|
@htm = HTM.new(robot_name: "Knowledge Bot")
|
|
296
277
|
end
|
|
297
278
|
|
|
298
|
-
def add_fact(
|
|
299
|
-
@htm.
|
|
300
|
-
key,
|
|
279
|
+
def add_fact(fact, category:, tags: [])
|
|
280
|
+
@htm.remember(
|
|
301
281
|
fact,
|
|
302
|
-
|
|
303
|
-
category: category,
|
|
304
|
-
importance: 8.0,
|
|
305
|
-
tags: tags
|
|
282
|
+
tags: tags,
|
|
283
|
+
metadata: { category: category, priority: "high" }
|
|
306
284
|
)
|
|
307
285
|
end
|
|
308
286
|
|
|
309
287
|
def query(question)
|
|
310
288
|
# Search all time for relevant facts
|
|
311
289
|
@htm.recall(
|
|
290
|
+
question,
|
|
312
291
|
timeframe: "last 10 years", # Effectively all memories
|
|
313
|
-
topic: question,
|
|
314
292
|
limit: 5
|
|
315
293
|
)
|
|
316
294
|
end
|
|
@@ -319,7 +297,6 @@ end
|
|
|
319
297
|
# Usage
|
|
320
298
|
kb = KnowledgeBase.new
|
|
321
299
|
kb.add_fact(
|
|
322
|
-
"ruby_version",
|
|
323
300
|
"Ruby 3.0 introduced Ractors for parallel execution",
|
|
324
301
|
category: "programming",
|
|
325
302
|
tags: ["ruby", "concurrency"]
|
|
@@ -339,8 +316,6 @@ class DecisionJournal
|
|
|
339
316
|
end
|
|
340
317
|
|
|
341
318
|
def record_decision(title, rationale, alternatives: [], tags: [])
|
|
342
|
-
key = "decision_#{Time.now.to_i}"
|
|
343
|
-
|
|
344
319
|
decision = <<~DECISION
|
|
345
320
|
Decision: #{title}
|
|
346
321
|
|
|
@@ -349,20 +324,19 @@ class DecisionJournal
|
|
|
349
324
|
#{alternatives.any? ? "Alternatives considered: #{alternatives.join(', ')}" : ''}
|
|
350
325
|
DECISION
|
|
351
326
|
|
|
352
|
-
@htm.
|
|
353
|
-
key,
|
|
327
|
+
@htm.remember(
|
|
354
328
|
decision,
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
tags: tags + ["decision"]
|
|
329
|
+
tags: tags + ["decision"],
|
|
330
|
+
metadata: { category: "decision", priority: "critical" }
|
|
358
331
|
)
|
|
359
332
|
end
|
|
360
333
|
|
|
361
334
|
def get_decision_history(topic)
|
|
362
335
|
@htm.recall(
|
|
336
|
+
topic,
|
|
363
337
|
timeframe: "last year",
|
|
364
|
-
|
|
365
|
-
|
|
338
|
+
limit: 20,
|
|
339
|
+
raw: true
|
|
366
340
|
).sort_by { |d| d['created_at'] }
|
|
367
341
|
end
|
|
368
342
|
end
|
|
@@ -379,11 +353,9 @@ puts "Nodes in working memory: #{wm.node_count}"
|
|
|
379
353
|
puts "Tokens used: #{wm.token_count} / #{wm.max_tokens}"
|
|
380
354
|
puts "Utilization: #{wm.utilization_percentage}%"
|
|
381
355
|
|
|
382
|
-
# Get comprehensive stats
|
|
383
|
-
|
|
384
|
-
puts "
|
|
385
|
-
puts "Active robots: #{stats[:active_robots]}"
|
|
386
|
-
puts "Database size: #{stats[:database_size] / (1024.0 * 1024.0)} MB"
|
|
356
|
+
# Get comprehensive stats using ActiveRecord
|
|
357
|
+
puts "Total nodes in long-term: #{HTM::Models::Node.count}"
|
|
358
|
+
puts "Active robots: #{HTM::Models::Robot.count}"
|
|
387
359
|
```
|
|
388
360
|
|
|
389
361
|
!!! tip
|
|
@@ -391,73 +363,103 @@ puts "Database size: #{stats[:database_size] / (1024.0 * 1024.0)} MB"
|
|
|
391
363
|
|
|
392
364
|
## Best Practices for Beginners
|
|
393
365
|
|
|
394
|
-
### 1. Use
|
|
366
|
+
### 1. Use Descriptive Content
|
|
395
367
|
|
|
396
368
|
```ruby
|
|
397
|
-
# Good:
|
|
398
|
-
htm.
|
|
369
|
+
# Good: Clear, self-contained content
|
|
370
|
+
htm.remember(
|
|
371
|
+
"User prefers dark theme for all interfaces",
|
|
372
|
+
tags: ["user:preference", "ui:theme"],
|
|
373
|
+
metadata: { category: "preference" }
|
|
374
|
+
)
|
|
399
375
|
|
|
400
|
-
# Bad:
|
|
401
|
-
htm.
|
|
376
|
+
# Bad: Vague or context-dependent
|
|
377
|
+
htm.remember("prefers dark", tags: ["pref"])
|
|
402
378
|
```
|
|
403
379
|
|
|
404
|
-
### 2.
|
|
380
|
+
### 2. Use Metadata for Priority
|
|
405
381
|
|
|
406
382
|
```ruby
|
|
407
|
-
# Critical facts
|
|
408
|
-
htm.
|
|
383
|
+
# Critical facts
|
|
384
|
+
htm.remember(
|
|
385
|
+
"Production API endpoint: https://api.example.com",
|
|
386
|
+
tags: ["api", "production"],
|
|
387
|
+
metadata: { priority: "critical", category: "fact" }
|
|
388
|
+
)
|
|
409
389
|
|
|
410
|
-
# Important decisions
|
|
411
|
-
htm.
|
|
390
|
+
# Important decisions
|
|
391
|
+
htm.remember(
|
|
392
|
+
"Using microservices architecture for scalability",
|
|
393
|
+
tags: ["architecture", "decision"],
|
|
394
|
+
metadata: { priority: "high", category: "decision" }
|
|
395
|
+
)
|
|
412
396
|
|
|
413
|
-
# Contextual information
|
|
414
|
-
htm.
|
|
397
|
+
# Contextual information
|
|
398
|
+
htm.remember(
|
|
399
|
+
"Currently discussing weather API integration",
|
|
400
|
+
tags: ["context", "conversation"],
|
|
401
|
+
metadata: { priority: "medium", category: "context" }
|
|
402
|
+
)
|
|
415
403
|
|
|
416
|
-
# Temporary notes
|
|
417
|
-
htm.
|
|
404
|
+
# Temporary notes
|
|
405
|
+
htm.remember(
|
|
406
|
+
"Remember to check server logs after deployment",
|
|
407
|
+
tags: ["todo", "temporary"],
|
|
408
|
+
metadata: { priority: "low", category: "note" }
|
|
409
|
+
)
|
|
418
410
|
```
|
|
419
411
|
|
|
420
412
|
### 3. Use Tags Liberally
|
|
421
413
|
|
|
422
414
|
```ruby
|
|
423
|
-
htm.
|
|
424
|
-
"
|
|
425
|
-
"Chose PostgreSQL for data persistence",
|
|
426
|
-
type: :decision,
|
|
427
|
-
importance: 9.0,
|
|
415
|
+
htm.remember(
|
|
416
|
+
"Chose PostgreSQL for data persistence due to ACID compliance",
|
|
428
417
|
tags: [
|
|
429
418
|
"database",
|
|
430
419
|
"architecture",
|
|
431
420
|
"backend",
|
|
432
421
|
"persistence",
|
|
433
|
-
"postgresql"
|
|
434
|
-
]
|
|
422
|
+
"database:postgresql"
|
|
423
|
+
],
|
|
424
|
+
metadata: { category: "decision", priority: "high" }
|
|
435
425
|
)
|
|
436
426
|
```
|
|
437
427
|
|
|
438
|
-
### 4.
|
|
428
|
+
### 4. Use Hierarchical Tags for Relationships
|
|
439
429
|
|
|
440
430
|
```ruby
|
|
441
|
-
# Add related memories
|
|
442
|
-
htm.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
"
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
431
|
+
# Add related memories using hierarchical tags
|
|
432
|
+
htm.remember(
|
|
433
|
+
"Use PostgreSQL for primary data storage",
|
|
434
|
+
tags: ["decision:database", "database:postgresql"],
|
|
435
|
+
metadata: { category: "decision" }
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
htm.remember(
|
|
439
|
+
"PG.connect(host: 'localhost', dbname: 'app_production')",
|
|
440
|
+
tags: ["code:ruby", "database:postgresql", "decision:database"],
|
|
441
|
+
metadata: { category: "code", language: "ruby" }
|
|
449
442
|
)
|
|
443
|
+
|
|
444
|
+
# Find related by shared tags
|
|
445
|
+
htm.recall("database:postgresql", timeframe: "last month", limit: 10)
|
|
450
446
|
```
|
|
451
447
|
|
|
452
448
|
### 5. Clean Up When Needed
|
|
453
449
|
|
|
454
450
|
```ruby
|
|
455
|
-
#
|
|
456
|
-
htm.
|
|
451
|
+
# Store the node_id when creating memories you may want to remove
|
|
452
|
+
node_id = htm.remember("Temporary calculation result", tags: ["scratch"])
|
|
453
|
+
|
|
454
|
+
# Later, soft delete (recoverable)
|
|
455
|
+
htm.forget(node_id)
|
|
456
|
+
|
|
457
|
+
# Or permanently delete with confirmation
|
|
458
|
+
htm.forget(node_id, soft: false, confirm: :confirmed)
|
|
457
459
|
```
|
|
458
460
|
|
|
459
461
|
!!! warning
|
|
460
|
-
|
|
462
|
+
Permanent deletion requires explicit confirmation to prevent accidental data loss. Use soft delete (default) when possible - you can always restore with `htm.restore(node_id)`.
|
|
461
463
|
|
|
462
464
|
## Troubleshooting
|
|
463
465
|
|
|
@@ -493,12 +495,22 @@ end
|
|
|
493
495
|
### Memory Not Found
|
|
494
496
|
|
|
495
497
|
```ruby
|
|
496
|
-
|
|
498
|
+
# Retrieve by node_id (returned from remember())
|
|
499
|
+
node_id = 123 # Use the ID you saved when creating the memory
|
|
500
|
+
memory = htm.long_term_memory.retrieve(node_id)
|
|
497
501
|
|
|
498
502
|
if memory.nil?
|
|
499
|
-
puts "Memory not found. Check the
|
|
503
|
+
puts "Memory not found. Check the node ID."
|
|
500
504
|
else
|
|
501
|
-
puts "Found: #{memory
|
|
505
|
+
puts "Found: #{memory.content}"
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
# Or search for memories by content
|
|
509
|
+
results = htm.recall("what I'm looking for", timeframe: "last month", limit: 5)
|
|
510
|
+
if results.empty?
|
|
511
|
+
puts "No matching memories found."
|
|
512
|
+
else
|
|
513
|
+
puts "Found #{results.length} matches"
|
|
502
514
|
end
|
|
503
515
|
```
|
|
504
516
|
|
|
@@ -525,53 +537,47 @@ htm = HTM.new(
|
|
|
525
537
|
)
|
|
526
538
|
|
|
527
539
|
# Add various memories
|
|
528
|
-
htm.
|
|
529
|
-
"user_001",
|
|
540
|
+
htm.remember(
|
|
530
541
|
"User's name is Alice and she's a software engineer",
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
tags: ["user", "identity", "profession"]
|
|
542
|
+
tags: ["user", "identity", "profession"],
|
|
543
|
+
metadata: { category: "fact", priority: "high" }
|
|
534
544
|
)
|
|
535
545
|
|
|
536
|
-
htm.
|
|
537
|
-
"decision_001",
|
|
546
|
+
htm.remember(
|
|
538
547
|
"Decided to use HTM for managing conversation memory",
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
tags: ["architecture", "memory"]
|
|
548
|
+
tags: ["architecture", "memory", "decision"],
|
|
549
|
+
metadata: { category: "decision", priority: "critical" }
|
|
542
550
|
)
|
|
543
551
|
|
|
544
|
-
htm.
|
|
545
|
-
"pref_001",
|
|
552
|
+
htm.remember(
|
|
546
553
|
"Alice prefers detailed explanations with examples",
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
tags: ["user", "communication"],
|
|
550
|
-
related_to: ["user_001"]
|
|
554
|
+
tags: ["user", "communication", "user:preference"],
|
|
555
|
+
metadata: { category: "preference" }
|
|
551
556
|
)
|
|
552
557
|
|
|
553
558
|
# Recall relevant memories
|
|
554
559
|
memories = htm.recall(
|
|
560
|
+
"user preferences", # Topic is positional
|
|
555
561
|
timeframe: "last 7 days",
|
|
556
|
-
|
|
557
|
-
|
|
562
|
+
limit: 5,
|
|
563
|
+
raw: true # Get full hash with similarity scores
|
|
558
564
|
)
|
|
559
565
|
|
|
560
566
|
puts "Found #{memories.length} relevant memories:"
|
|
561
567
|
memories.each do |m|
|
|
562
|
-
puts "- #{m['
|
|
568
|
+
puts "- #{m['content']}"
|
|
563
569
|
end
|
|
564
570
|
|
|
565
571
|
# Create context for LLM
|
|
566
|
-
context = htm.
|
|
572
|
+
context = htm.working_memory.assemble_context(strategy: :balanced)
|
|
567
573
|
puts "\nContext length: #{context.length} characters"
|
|
568
574
|
|
|
569
575
|
# Check stats
|
|
570
|
-
|
|
576
|
+
wm = htm.working_memory
|
|
571
577
|
puts "\nMemory statistics:"
|
|
572
|
-
puts "- Total nodes: #{
|
|
573
|
-
puts "- Working memory: #{
|
|
574
|
-
puts "-
|
|
578
|
+
puts "- Total nodes in database: #{HTM::Models::Node.count}"
|
|
579
|
+
puts "- Working memory nodes: #{wm.node_count}"
|
|
580
|
+
puts "- Working memory: #{wm.utilization_percentage}% full"
|
|
575
581
|
```
|
|
576
582
|
|
|
577
583
|
Happy coding with HTM!
|
data/docs/guides/index.md
CHANGED
|
@@ -36,6 +36,12 @@ Dive deeper into HTM's powerful capabilities.
|
|
|
36
36
|
- [**Search Strategies**](search-strategies.md) - Vector, full-text, and hybrid search
|
|
37
37
|
- [**Context Assembly**](context-assembly.md) - Creating optimized context for LLMs
|
|
38
38
|
|
|
39
|
+
### Integrations
|
|
40
|
+
|
|
41
|
+
Connect HTM to external tools and services.
|
|
42
|
+
|
|
43
|
+
- [**MCP Server**](mcp-server.md) - Use HTM with Claude Desktop, Claude Code, and AIA
|
|
44
|
+
|
|
39
45
|
## Learning Path
|
|
40
46
|
|
|
41
47
|
We recommend the following progression:
|
|
@@ -68,6 +74,7 @@ We recommend the following progression:
|
|
|
68
74
|
- **Create LLM context**: See [Context Assembly](context-assembly.md#basic-usage)
|
|
69
75
|
- **Monitor memory usage**: See [Working Memory](working-memory.md#monitoring-utilization)
|
|
70
76
|
- **Multi-robot setup**: See [Multi-Robot Usage](multi-robot.md#setting-up-multiple-robots)
|
|
77
|
+
- **Use with Claude/AIA**: See [MCP Server](mcp-server.md#client-configuration)
|
|
71
78
|
|
|
72
79
|
### Memory Types
|
|
73
80
|
|