htm 0.0.1 → 0.0.2

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.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.tbls.yml +30 -0
  4. data/CHANGELOG.md +30 -0
  5. data/SETUP.md +132 -101
  6. data/db/migrate/20250125000001_add_content_hash_to_nodes.rb +14 -0
  7. data/db/migrate/20250125000002_create_robot_nodes.rb +35 -0
  8. data/db/migrate/20250125000003_remove_source_and_robot_id_from_nodes.rb +28 -0
  9. data/db/migrate/20250126000001_create_working_memories.rb +19 -0
  10. data/db/migrate/20250126000002_remove_unused_columns.rb +12 -0
  11. data/db/schema.sql +226 -43
  12. data/docs/api/database.md +20 -232
  13. data/docs/api/embedding-service.md +1 -7
  14. data/docs/api/htm.md +195 -449
  15. data/docs/api/index.md +1 -7
  16. data/docs/api/long-term-memory.md +342 -590
  17. data/docs/architecture/adrs/001-postgresql-timescaledb.md +1 -1
  18. data/docs/architecture/adrs/003-ollama-embeddings.md +1 -1
  19. data/docs/architecture/adrs/010-redis-working-memory-rejected.md +2 -27
  20. data/docs/architecture/adrs/index.md +2 -13
  21. data/docs/architecture/hive-mind.md +165 -166
  22. data/docs/architecture/index.md +2 -2
  23. data/docs/architecture/overview.md +5 -171
  24. data/docs/architecture/two-tier-memory.md +1 -35
  25. data/docs/assets/images/adr-010-current-architecture.svg +37 -0
  26. data/docs/assets/images/adr-010-proposed-architecture.svg +48 -0
  27. data/docs/assets/images/adr-dependency-tree.svg +93 -0
  28. data/docs/assets/images/class-hierarchy.svg +55 -0
  29. data/docs/assets/images/exception-hierarchy.svg +45 -0
  30. data/docs/assets/images/htm-architecture-overview.svg +83 -0
  31. data/docs/assets/images/htm-complete-memory-flow.svg +160 -0
  32. data/docs/assets/images/htm-context-assembly-flow.svg +148 -0
  33. data/docs/assets/images/htm-eviction-process.svg +141 -0
  34. data/docs/assets/images/htm-memory-addition-flow.svg +138 -0
  35. data/docs/assets/images/htm-memory-recall-flow.svg +152 -0
  36. data/docs/assets/images/htm-node-states.svg +123 -0
  37. data/docs/assets/images/project-structure.svg +78 -0
  38. data/docs/assets/images/test-directory-structure.svg +38 -0
  39. data/{dbdoc → docs/database}/README.md +5 -3
  40. data/{dbdoc → docs/database}/public.node_tags.md +4 -5
  41. data/docs/database/public.node_tags.svg +106 -0
  42. data/{dbdoc → docs/database}/public.nodes.md +3 -8
  43. data/docs/database/public.nodes.svg +152 -0
  44. data/docs/database/public.robot_nodes.md +44 -0
  45. data/docs/database/public.robot_nodes.svg +121 -0
  46. data/{dbdoc → docs/database}/public.robots.md +1 -2
  47. data/docs/database/public.robots.svg +106 -0
  48. data/docs/database/public.working_memories.md +40 -0
  49. data/docs/database/public.working_memories.svg +112 -0
  50. data/{dbdoc → docs/database}/schema.json +342 -110
  51. data/docs/database/schema.svg +223 -0
  52. data/docs/development/index.md +1 -29
  53. data/docs/development/schema.md +84 -324
  54. data/docs/development/testing.md +1 -9
  55. data/docs/getting-started/index.md +47 -0
  56. data/docs/{installation.md → getting-started/installation.md} +2 -2
  57. data/docs/{quick-start.md → getting-started/quick-start.md} +5 -5
  58. data/docs/guides/adding-memories.md +221 -655
  59. data/docs/guides/search-strategies.md +85 -51
  60. data/docs/images/htm-er-diagram.svg +156 -0
  61. data/docs/index.md +16 -31
  62. data/docs/multi_framework_support.md +4 -4
  63. data/examples/basic_usage.rb +18 -16
  64. data/examples/cli_app/htm_cli.rb +86 -8
  65. data/examples/custom_llm_configuration.rb +1 -2
  66. data/examples/example_app/app.rb +11 -14
  67. data/examples/sinatra_app/Gemfile +1 -0
  68. data/examples/sinatra_app/Gemfile.lock +166 -0
  69. data/examples/sinatra_app/app.rb +219 -24
  70. data/lib/htm/active_record_config.rb +10 -3
  71. data/lib/htm/configuration.rb +265 -78
  72. data/lib/htm/{sinatra.rb → integrations/sinatra.rb} +87 -12
  73. data/lib/htm/job_adapter.rb +10 -3
  74. data/lib/htm/long_term_memory.rb +220 -57
  75. data/lib/htm/models/node.rb +36 -7
  76. data/lib/htm/models/robot.rb +30 -4
  77. data/lib/htm/models/robot_node.rb +50 -0
  78. data/lib/htm/models/tag.rb +52 -0
  79. data/lib/htm/models/working_memory_entry.rb +88 -0
  80. data/lib/htm/tasks.rb +4 -0
  81. data/lib/htm/version.rb +1 -1
  82. data/lib/htm.rb +34 -13
  83. data/lib/tasks/htm.rake +32 -1
  84. data/lib/tasks/jobs.rake +7 -3
  85. data/lib/tasks/tags.rake +34 -0
  86. data/mkdocs.yml +56 -9
  87. metadata +61 -31
  88. data/dbdoc/public.node_tags.svg +0 -112
  89. data/dbdoc/public.nodes.svg +0 -118
  90. data/dbdoc/public.robots.svg +0 -90
  91. data/dbdoc/schema.svg +0 -154
  92. /data/{dbdoc → docs/database}/public.node_stats.md +0 -0
  93. /data/{dbdoc → docs/database}/public.node_stats.svg +0 -0
  94. /data/{dbdoc → docs/database}/public.nodes_tags.md +0 -0
  95. /data/{dbdoc → docs/database}/public.nodes_tags.svg +0 -0
  96. /data/{dbdoc → docs/database}/public.ontology_structure.md +0 -0
  97. /data/{dbdoc → docs/database}/public.ontology_structure.svg +0 -0
  98. /data/{dbdoc → docs/database}/public.operations_log.md +0 -0
  99. /data/{dbdoc → docs/database}/public.operations_log.svg +0 -0
  100. /data/{dbdoc → docs/database}/public.relationships.md +0 -0
  101. /data/{dbdoc → docs/database}/public.relationships.svg +0 -0
  102. /data/{dbdoc → docs/database}/public.robot_activity.md +0 -0
  103. /data/{dbdoc → docs/database}/public.robot_activity.svg +0 -0
  104. /data/{dbdoc → docs/database}/public.schema_migrations.md +0 -0
  105. /data/{dbdoc → docs/database}/public.schema_migrations.svg +0 -0
  106. /data/{dbdoc → docs/database}/public.tags.md +0 -0
  107. /data/{dbdoc → docs/database}/public.tags.svg +0 -0
  108. /data/{dbdoc → docs/database}/public.topic_relationships.md +0 -0
  109. /data/{dbdoc → docs/database}/public.topic_relationships.svg +0 -0
@@ -59,6 +59,7 @@ class HTMCli
59
59
  puts "Commands:"
60
60
  puts " remember <text> - Store information"
61
61
  puts " recall <topic> - Search memories"
62
+ puts " tags - List all tags with linked nodes"
62
63
  puts " stats - Show memory statistics"
63
64
  puts " help - Show this help"
64
65
  puts " exit - Quit"
@@ -91,6 +92,8 @@ class HTMCli
91
92
  handle_remember(args)
92
93
  when 'recall'
93
94
  handle_recall(args)
95
+ when 'tags'
96
+ handle_tags(args)
94
97
  when 'stats'
95
98
  handle_stats
96
99
  when 'help'
@@ -113,7 +116,7 @@ class HTMCli
113
116
  puts "Processing..."
114
117
 
115
118
  start_time = Time.now
116
- node_id = @htm.remember(text, source: 'cli_user')
119
+ node_id = @htm.remember(text)
117
120
  duration = ((Time.now - start_time) * 1000).round(2)
118
121
 
119
122
  puts "[✓] Stored as node #{node_id} (#{duration}ms)"
@@ -141,7 +144,15 @@ class HTMCli
141
144
  end
142
145
 
143
146
  puts "\nSearching for: \"#{topic}\""
144
- puts "Strategy: hybrid (vector + fulltext)"
147
+ puts "Strategy: hybrid (vector + fulltext + tags)"
148
+
149
+ # Show which tags match the query
150
+ matching_tags = @htm.long_term_memory.find_query_matching_tags(topic)
151
+ if matching_tags.any?
152
+ puts "Matching tags: #{matching_tags.join(', ')}"
153
+ else
154
+ puts "Matching tags: (none found)"
155
+ end
145
156
 
146
157
  start_time = Time.now
147
158
  memories = @htm.recall(
@@ -161,15 +172,74 @@ class HTMCli
161
172
 
162
173
  memories.each_with_index do |memory, index|
163
174
  puts
164
- puts "#{index + 1}. Node #{memory['id']} (#{memory['source']})"
175
+ puts "#{index + 1}. Node #{memory['id']}"
165
176
  puts " Created: #{memory['created_at']}"
166
177
  puts " Content: #{memory['content']}"
167
178
 
179
+ # Show scores from hybrid search
180
+ if memory['combined_score']
181
+ similarity = (memory['similarity'].to_f * 100).round(1)
182
+ tag_boost = (memory['tag_boost'].to_f * 100).round(1)
183
+ combined = (memory['combined_score'].to_f * 100).round(1)
184
+ puts " Scores: similarity=#{similarity}%, tag_boost=#{tag_boost}%, combined=#{combined}%"
185
+ end
186
+
168
187
  # Show tags if any
169
188
  node = HTM::Models::Node.includes(:tags).find(memory['id'])
170
189
  if node.tags.any?
171
190
  puts " Tags: #{node.tags.map(&:name).join(', ')}"
191
+ else
192
+ puts " Tags: (none)"
193
+ end
194
+ end
195
+ end
196
+
197
+ def handle_tags(filter = nil)
198
+ puts "\nTags Overview:"
199
+ puts
200
+
201
+ # Get all tags with their nodes, optionally filtered by prefix
202
+ tags_query = HTM::Models::Tag.includes(:nodes).order(:name)
203
+ tags_query = tags_query.where("name LIKE ?", "#{filter}%") if filter && !filter.empty?
204
+
205
+ tags = tags_query.to_a
206
+
207
+ if tags.empty?
208
+ if filter
209
+ puts "[•] No tags found matching '#{filter}'"
210
+ else
211
+ puts "[•] No tags in database"
172
212
  end
213
+ return
214
+ end
215
+
216
+ puts "[✓] Found #{tags.length} tags#{filter ? " matching '#{filter}'" : ""}"
217
+ puts
218
+
219
+ tags.each do |tag|
220
+ nodes = tag.nodes.to_a
221
+ puts "━" * 60
222
+ puts "Tag: #{tag.name}"
223
+ puts " Nodes: #{nodes.length}"
224
+ puts
225
+
226
+ if nodes.any?
227
+ nodes.each do |node|
228
+ content_preview = node.content.to_s[0..70]
229
+ content_preview += "..." if node.content.to_s.length > 70
230
+ puts " [#{node.id}] #{content_preview}"
231
+ end
232
+ else
233
+ puts " (no nodes linked)"
234
+ end
235
+ puts
236
+ end
237
+
238
+ # Show tag hierarchy summary
239
+ root_tags = tags.map { |t| t.name.split(':').first }.uniq.sort
240
+ if root_tags.length > 1
241
+ puts "━" * 60
242
+ puts "Root categories: #{root_tags.join(', ')}"
173
243
  end
174
244
  end
175
245
 
@@ -201,7 +271,7 @@ class HTMCli
201
271
  puts
202
272
 
203
273
  puts "Current Robot (#{@htm.robot_name}):"
204
- robot_nodes = HTM::Models::Node.where(robot_id: @htm.robot_id).count
274
+ robot_nodes = HTM::Models::RobotNode.where(robot_id: @htm.robot_id).count
205
275
  puts " Nodes: #{robot_nodes}"
206
276
  end
207
277
 
@@ -216,8 +286,17 @@ class HTMCli
216
286
  puts
217
287
  puts " recall <topic>"
218
288
  puts " Search for relevant memories using hybrid search"
219
- puts " Combines vector similarity and full-text search"
289
+ puts " Combines vector similarity, full-text search, and tag matching"
290
+ puts " Shows matching tags, scores (similarity, tag_boost, combined)"
220
291
  puts " Example: recall PostgreSQL"
292
+ puts " Example: recall database optimization"
293
+ puts
294
+ puts " tags [prefix]"
295
+ puts " List all tags with their linked node content"
296
+ puts " Optionally filter by tag prefix"
297
+ puts " Example: tags"
298
+ puts " Example: tags database"
299
+ puts " Example: tags ai:machine"
221
300
  puts
222
301
  puts " stats"
223
302
  puts " Show memory statistics and current state"
@@ -242,10 +321,9 @@ unless ENV['HTM_DBURL']
242
321
  puts "[✗] Error: HTM_DBURL environment variable not set"
243
322
  puts
244
323
  puts "Please set your database connection URL:"
245
- puts " export HTM_DBURL='postgresql://user:pass@host:port/dbname'"
324
+ puts " export HTM_DBURL='postgresql://postgres@localhost:5432/htm_development'"
246
325
  puts
247
- puts "Or source your environment configuration:"
248
- puts " source ~/.bashrc__tiger"
326
+ puts "See SETUP.md for database setup instructions."
249
327
  puts
250
328
  exit 1
251
329
  end
@@ -160,8 +160,7 @@ htm = HTM.new(robot_name: "IntegrationBot")
160
160
  # Remember information - will use custom LLM configuration
161
161
  puts "\nRemembering information in HTM..."
162
162
  node_id = htm.remember(
163
- "PostgreSQL with pgvector enables efficient vector similarity search",
164
- source: 'user'
163
+ "PostgreSQL with pgvector enables efficient vector similarity search"
165
164
  )
166
165
 
167
166
  puts "✓ Information remembered with node_id: #{node_id}"
@@ -72,18 +72,15 @@ class ExampleApp
72
72
  puts "(Tags will be auto-extracted by LLM in background)"
73
73
 
74
74
  node_1 = htm.remember(
75
- "HTM provides intelligent memory management for LLM-based applications",
76
- source: "assistant"
75
+ "HTM provides intelligent memory management for LLM-based applications"
77
76
  )
78
77
 
79
78
  node_2 = htm.remember(
80
- "The two-tier architecture includes working memory and long-term storage",
81
- source: "assistant"
79
+ "The two-tier architecture includes working memory and long-term storage"
82
80
  )
83
81
 
84
82
  node_3 = htm.remember(
85
- "Can you explain how the working memory eviction algorithm works?",
86
- source: "user"
83
+ "Can you explain how the working memory eviction algorithm works?"
87
84
  )
88
85
 
89
86
  puts "✓ Remembered 3 conversation messages (nodes #{node_1}, #{node_2}, #{node_3})"
@@ -132,8 +129,8 @@ class ExampleApp
132
129
  limit: 3
133
130
  )
134
131
  puts "Found #{fulltext_memories.length} memories:"
135
- fulltext_memories.each do |memory|
136
- puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
132
+ fulltext_memories.each do |content|
133
+ puts " - #{content[0..60]}..."
137
134
  end
138
135
 
139
136
  # 2. Vector search (requires embeddings)
@@ -146,8 +143,8 @@ class ExampleApp
146
143
  limit: 3
147
144
  )
148
145
  puts "Found #{vector_memories.length} memories:"
149
- vector_memories.each do |memory|
150
- puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
146
+ vector_memories.each do |content|
147
+ puts " - #{content[0..60]}..."
151
148
  end
152
149
  rescue StandardError => e
153
150
  puts " ⚠ Vector search error: #{e.message}"
@@ -164,8 +161,8 @@ class ExampleApp
164
161
  limit: 3
165
162
  )
166
163
  puts "Found #{hybrid_memories.length} memories:"
167
- hybrid_memories.each do |memory|
168
- puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
164
+ hybrid_memories.each do |content|
165
+ puts " - #{content[0..60]}..."
169
166
  end
170
167
  rescue StandardError => e
171
168
  puts " ⚠ Hybrid search error: #{e.message}"
@@ -177,12 +174,12 @@ class ExampleApp
177
174
  puts "✓ Demo Complete!"
178
175
  puts "="*60
179
176
  puts "\nThe HTM API provides 3 core methods:"
180
- puts " 1. htm.remember(content, source:)"
177
+ puts " 1. htm.remember(content, tags: [])"
181
178
  puts " - Stores information in long-term memory"
182
179
  puts " - Adds to working memory for immediate use"
183
180
  puts " - Generates embeddings and tags in background"
184
181
  puts ""
185
- puts " 2. htm.recall(timeframe:, topic:, strategy:, limit:)"
182
+ puts " 2. htm.recall(topic, timeframe:, strategy:, limit:)"
186
183
  puts " - Retrieves relevant memories"
187
184
  puts " - Strategies: :fulltext, :vector, :hybrid"
188
185
  puts " - Results added to working memory"
@@ -4,6 +4,7 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Web framework
6
6
  gem 'sinatra', '~> 3.0'
7
+ gem 'sinatra-contrib', '~> 3.0'
7
8
  gem 'puma', '~> 6.0'
8
9
 
9
10
  # Background jobs
@@ -0,0 +1,166 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ htm (0.0.2)
5
+ activerecord
6
+ lru_redux
7
+ neighbor
8
+ pg (>= 1.5.0)
9
+ ruby_llm
10
+ tiktoken_ruby
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activemodel (8.1.1)
16
+ activesupport (= 8.1.1)
17
+ activerecord (8.1.1)
18
+ activemodel (= 8.1.1)
19
+ activesupport (= 8.1.1)
20
+ timeout (>= 0.4.0)
21
+ activesupport (8.1.1)
22
+ base64
23
+ bigdecimal
24
+ concurrent-ruby (~> 1.0, >= 1.3.1)
25
+ connection_pool (>= 2.2.5)
26
+ drb
27
+ i18n (>= 1.6, < 2)
28
+ json
29
+ logger (>= 1.4.2)
30
+ minitest (>= 5.1)
31
+ securerandom (>= 0.3)
32
+ tzinfo (~> 2.0, >= 2.0.5)
33
+ uri (>= 0.13.1)
34
+ base64 (0.3.0)
35
+ bigdecimal (3.3.1)
36
+ concurrent-ruby (1.3.5)
37
+ connection_pool (2.5.5)
38
+ drb (2.2.3)
39
+ event_stream_parser (1.0.0)
40
+ faraday (2.14.0)
41
+ faraday-net_http (>= 2.0, < 3.5)
42
+ json
43
+ logger
44
+ faraday-multipart (1.1.1)
45
+ multipart-post (~> 2.0)
46
+ faraday-net_http (3.4.2)
47
+ net-http (~> 0.5)
48
+ faraday-retry (2.3.2)
49
+ faraday (~> 2.0)
50
+ ffi (1.17.2-aarch64-linux-gnu)
51
+ ffi (1.17.2-aarch64-linux-musl)
52
+ ffi (1.17.2-arm-linux-gnu)
53
+ ffi (1.17.2-arm-linux-musl)
54
+ ffi (1.17.2-arm64-darwin)
55
+ ffi (1.17.2-x86_64-darwin)
56
+ ffi (1.17.2-x86_64-linux-gnu)
57
+ ffi (1.17.2-x86_64-linux-musl)
58
+ i18n (1.14.7)
59
+ concurrent-ruby (~> 1.0)
60
+ json (2.16.0)
61
+ listen (3.9.0)
62
+ rb-fsevent (~> 0.10, >= 0.10.3)
63
+ rb-inotify (~> 0.9, >= 0.9.10)
64
+ logger (1.7.0)
65
+ lru_redux (1.1.0)
66
+ marcel (1.1.0)
67
+ minitest (5.26.2)
68
+ multi_json (1.17.0)
69
+ multipart-post (2.4.1)
70
+ mustermann (3.0.4)
71
+ ruby2_keywords (~> 0.0.1)
72
+ neighbor (0.6.0)
73
+ activerecord (>= 7.1)
74
+ net-http (0.8.0)
75
+ uri (>= 0.11.1)
76
+ nio4r (2.7.5)
77
+ pg (1.6.2)
78
+ pg (1.6.2-aarch64-linux)
79
+ pg (1.6.2-aarch64-linux-musl)
80
+ pg (1.6.2-arm64-darwin)
81
+ pg (1.6.2-x86_64-darwin)
82
+ pg (1.6.2-x86_64-linux)
83
+ pg (1.6.2-x86_64-linux-musl)
84
+ puma (6.6.1)
85
+ nio4r (~> 2.0)
86
+ rack (2.2.21)
87
+ rack-protection (3.2.0)
88
+ base64 (>= 0.1.0)
89
+ rack (~> 2.2, >= 2.2.4)
90
+ rb-fsevent (0.11.2)
91
+ rb-inotify (0.11.1)
92
+ ffi (~> 1.0)
93
+ redis (5.4.1)
94
+ redis-client (>= 0.22.0)
95
+ redis-client (0.26.1)
96
+ connection_pool
97
+ rerun (0.14.0)
98
+ listen (~> 3.0)
99
+ ruby2_keywords (0.0.5)
100
+ ruby_llm (1.9.1)
101
+ base64
102
+ event_stream_parser (~> 1)
103
+ faraday (>= 1.10.0)
104
+ faraday-multipart (>= 1)
105
+ faraday-net_http (>= 1)
106
+ faraday-retry (>= 1)
107
+ marcel (~> 1.0)
108
+ ruby_llm-schema (~> 0.2.1)
109
+ zeitwerk (~> 2)
110
+ ruby_llm-schema (0.2.5)
111
+ securerandom (0.4.1)
112
+ sidekiq (7.3.9)
113
+ base64
114
+ connection_pool (>= 2.3.0)
115
+ logger
116
+ rack (>= 2.2.4)
117
+ redis-client (>= 0.22.2)
118
+ sinatra (3.2.0)
119
+ mustermann (~> 3.0)
120
+ rack (~> 2.2, >= 2.2.4)
121
+ rack-protection (= 3.2.0)
122
+ tilt (~> 2.0)
123
+ sinatra-contrib (3.2.0)
124
+ multi_json (>= 0.0.2)
125
+ mustermann (~> 3.0)
126
+ rack-protection (= 3.2.0)
127
+ sinatra (= 3.2.0)
128
+ tilt (~> 2.0)
129
+ tiktoken_ruby (0.0.13-aarch64-linux)
130
+ tiktoken_ruby (0.0.13-arm-linux)
131
+ tiktoken_ruby (0.0.13-arm64-darwin)
132
+ tiktoken_ruby (0.0.13-x86_64-darwin)
133
+ tiktoken_ruby (0.0.13-x86_64-linux)
134
+ tiktoken_ruby (0.0.13-x86_64-linux-musl)
135
+ tilt (2.6.1)
136
+ timeout (0.4.4)
137
+ tzinfo (2.0.6)
138
+ concurrent-ruby (~> 1.0)
139
+ uri (1.1.1)
140
+ zeitwerk (2.7.3)
141
+
142
+ PLATFORMS
143
+ aarch64-linux
144
+ aarch64-linux-gnu
145
+ aarch64-linux-musl
146
+ arm-linux
147
+ arm-linux-gnu
148
+ arm-linux-musl
149
+ arm64-darwin
150
+ x86_64-darwin
151
+ x86_64-linux
152
+ x86_64-linux-gnu
153
+ x86_64-linux-musl
154
+
155
+ DEPENDENCIES
156
+ htm!
157
+ multi_json
158
+ puma (~> 6.0)
159
+ redis (~> 5.0)
160
+ rerun
161
+ sidekiq (~> 7.0)
162
+ sinatra (~> 3.0)
163
+ sinatra-contrib (~> 3.0)
164
+
165
+ BUNDLED WITH
166
+ 2.7.2