htm 0.0.1

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 (155) hide show
  1. checksums.yaml +7 -0
  2. data/.architecture/decisions/adrs/001-use-postgresql-timescaledb-storage.md +227 -0
  3. data/.architecture/decisions/adrs/002-two-tier-memory-architecture.md +322 -0
  4. data/.architecture/decisions/adrs/003-ollama-default-embedding-provider.md +339 -0
  5. data/.architecture/decisions/adrs/004-multi-robot-shared-memory-hive-mind.md +374 -0
  6. data/.architecture/decisions/adrs/005-rag-based-retrieval-with-hybrid-search.md +443 -0
  7. data/.architecture/decisions/adrs/006-context-assembly-strategies.md +444 -0
  8. data/.architecture/decisions/adrs/007-working-memory-eviction-strategy.md +461 -0
  9. data/.architecture/decisions/adrs/008-robot-identification-system.md +550 -0
  10. data/.architecture/decisions/adrs/009-never-forget-explicit-deletion-only.md +570 -0
  11. data/.architecture/decisions/adrs/010-redis-working-memory-rejected.md +323 -0
  12. data/.architecture/decisions/adrs/011-database-side-embedding-generation-with-pgai.md +585 -0
  13. data/.architecture/decisions/adrs/012-llm-driven-ontology-topic-extraction.md +583 -0
  14. data/.architecture/decisions/adrs/013-activerecord-orm-and-many-to-many-tagging.md +299 -0
  15. data/.architecture/decisions/adrs/014-client-side-embedding-generation-workflow.md +569 -0
  16. data/.architecture/decisions/adrs/015-hierarchical-tag-ontology-and-llm-extraction.md +701 -0
  17. data/.architecture/decisions/adrs/016-async-embedding-and-tag-generation.md +694 -0
  18. data/.architecture/members.yml +144 -0
  19. data/.architecture/reviews/2025-10-29-llm-configuration-and-async-processing-review.md +1137 -0
  20. data/.architecture/reviews/initial-system-analysis.md +330 -0
  21. data/.envrc +32 -0
  22. data/.irbrc +145 -0
  23. data/CHANGELOG.md +150 -0
  24. data/COMMITS.md +196 -0
  25. data/LICENSE +21 -0
  26. data/README.md +1347 -0
  27. data/Rakefile +51 -0
  28. data/SETUP.md +268 -0
  29. data/config/database.yml +67 -0
  30. data/db/migrate/20250101000001_enable_extensions.rb +14 -0
  31. data/db/migrate/20250101000002_create_robots.rb +14 -0
  32. data/db/migrate/20250101000003_create_nodes.rb +42 -0
  33. data/db/migrate/20250101000005_create_tags.rb +38 -0
  34. data/db/migrate/20250101000007_add_node_vector_indexes.rb +30 -0
  35. data/db/schema.sql +473 -0
  36. data/db/seed_data/README.md +100 -0
  37. data/db/seed_data/presidents.md +136 -0
  38. data/db/seed_data/states.md +151 -0
  39. data/db/seeds.rb +208 -0
  40. data/dbdoc/README.md +173 -0
  41. data/dbdoc/public.node_stats.md +48 -0
  42. data/dbdoc/public.node_stats.svg +41 -0
  43. data/dbdoc/public.node_tags.md +40 -0
  44. data/dbdoc/public.node_tags.svg +112 -0
  45. data/dbdoc/public.nodes.md +54 -0
  46. data/dbdoc/public.nodes.svg +118 -0
  47. data/dbdoc/public.nodes_tags.md +39 -0
  48. data/dbdoc/public.nodes_tags.svg +112 -0
  49. data/dbdoc/public.ontology_structure.md +48 -0
  50. data/dbdoc/public.ontology_structure.svg +38 -0
  51. data/dbdoc/public.operations_log.md +42 -0
  52. data/dbdoc/public.operations_log.svg +130 -0
  53. data/dbdoc/public.relationships.md +39 -0
  54. data/dbdoc/public.relationships.svg +41 -0
  55. data/dbdoc/public.robot_activity.md +46 -0
  56. data/dbdoc/public.robot_activity.svg +35 -0
  57. data/dbdoc/public.robots.md +35 -0
  58. data/dbdoc/public.robots.svg +90 -0
  59. data/dbdoc/public.schema_migrations.md +29 -0
  60. data/dbdoc/public.schema_migrations.svg +26 -0
  61. data/dbdoc/public.tags.md +35 -0
  62. data/dbdoc/public.tags.svg +60 -0
  63. data/dbdoc/public.topic_relationships.md +45 -0
  64. data/dbdoc/public.topic_relationships.svg +32 -0
  65. data/dbdoc/schema.json +1437 -0
  66. data/dbdoc/schema.svg +154 -0
  67. data/docs/api/database.md +806 -0
  68. data/docs/api/embedding-service.md +532 -0
  69. data/docs/api/htm.md +797 -0
  70. data/docs/api/index.md +259 -0
  71. data/docs/api/long-term-memory.md +1096 -0
  72. data/docs/api/working-memory.md +665 -0
  73. data/docs/architecture/adrs/001-postgresql-timescaledb.md +314 -0
  74. data/docs/architecture/adrs/002-two-tier-memory.md +411 -0
  75. data/docs/architecture/adrs/003-ollama-embeddings.md +421 -0
  76. data/docs/architecture/adrs/004-hive-mind.md +437 -0
  77. data/docs/architecture/adrs/005-rag-retrieval.md +531 -0
  78. data/docs/architecture/adrs/006-context-assembly.md +496 -0
  79. data/docs/architecture/adrs/007-eviction-strategy.md +645 -0
  80. data/docs/architecture/adrs/008-robot-identification.md +625 -0
  81. data/docs/architecture/adrs/009-never-forget.md +648 -0
  82. data/docs/architecture/adrs/010-redis-working-memory-rejected.md +323 -0
  83. data/docs/architecture/adrs/011-pgai-integration.md +494 -0
  84. data/docs/architecture/adrs/index.md +215 -0
  85. data/docs/architecture/hive-mind.md +736 -0
  86. data/docs/architecture/index.md +351 -0
  87. data/docs/architecture/overview.md +538 -0
  88. data/docs/architecture/two-tier-memory.md +873 -0
  89. data/docs/assets/css/custom.css +83 -0
  90. data/docs/assets/images/htm-core-components.svg +63 -0
  91. data/docs/assets/images/htm-database-schema.svg +93 -0
  92. data/docs/assets/images/htm-hive-mind-architecture.svg +125 -0
  93. data/docs/assets/images/htm-importance-scoring-framework.svg +83 -0
  94. data/docs/assets/images/htm-layered-architecture.svg +71 -0
  95. data/docs/assets/images/htm-long-term-memory-architecture.svg +115 -0
  96. data/docs/assets/images/htm-working-memory-architecture.svg +120 -0
  97. data/docs/assets/images/htm.jpg +0 -0
  98. data/docs/assets/images/htm_demo.gif +0 -0
  99. data/docs/assets/js/mathjax.js +18 -0
  100. data/docs/assets/videos/htm_video.mp4 +0 -0
  101. data/docs/database_rake_tasks.md +322 -0
  102. data/docs/development/contributing.md +787 -0
  103. data/docs/development/index.md +336 -0
  104. data/docs/development/schema.md +596 -0
  105. data/docs/development/setup.md +719 -0
  106. data/docs/development/testing.md +819 -0
  107. data/docs/guides/adding-memories.md +824 -0
  108. data/docs/guides/context-assembly.md +1009 -0
  109. data/docs/guides/getting-started.md +577 -0
  110. data/docs/guides/index.md +118 -0
  111. data/docs/guides/long-term-memory.md +941 -0
  112. data/docs/guides/multi-robot.md +866 -0
  113. data/docs/guides/recalling-memories.md +927 -0
  114. data/docs/guides/search-strategies.md +953 -0
  115. data/docs/guides/working-memory.md +717 -0
  116. data/docs/index.md +214 -0
  117. data/docs/installation.md +477 -0
  118. data/docs/multi_framework_support.md +519 -0
  119. data/docs/quick-start.md +655 -0
  120. data/docs/setup_local_database.md +302 -0
  121. data/docs/using_rake_tasks_in_your_app.md +383 -0
  122. data/examples/basic_usage.rb +93 -0
  123. data/examples/cli_app/README.md +317 -0
  124. data/examples/cli_app/htm_cli.rb +270 -0
  125. data/examples/custom_llm_configuration.rb +183 -0
  126. data/examples/example_app/Rakefile +71 -0
  127. data/examples/example_app/app.rb +206 -0
  128. data/examples/sinatra_app/Gemfile +21 -0
  129. data/examples/sinatra_app/app.rb +335 -0
  130. data/lib/htm/active_record_config.rb +113 -0
  131. data/lib/htm/configuration.rb +342 -0
  132. data/lib/htm/database.rb +594 -0
  133. data/lib/htm/embedding_service.rb +115 -0
  134. data/lib/htm/errors.rb +34 -0
  135. data/lib/htm/job_adapter.rb +154 -0
  136. data/lib/htm/jobs/generate_embedding_job.rb +65 -0
  137. data/lib/htm/jobs/generate_tags_job.rb +82 -0
  138. data/lib/htm/long_term_memory.rb +965 -0
  139. data/lib/htm/models/node.rb +109 -0
  140. data/lib/htm/models/node_tag.rb +33 -0
  141. data/lib/htm/models/robot.rb +52 -0
  142. data/lib/htm/models/tag.rb +76 -0
  143. data/lib/htm/railtie.rb +76 -0
  144. data/lib/htm/sinatra.rb +157 -0
  145. data/lib/htm/tag_service.rb +135 -0
  146. data/lib/htm/tasks.rb +38 -0
  147. data/lib/htm/version.rb +5 -0
  148. data/lib/htm/working_memory.rb +182 -0
  149. data/lib/htm.rb +400 -0
  150. data/lib/tasks/db.rake +19 -0
  151. data/lib/tasks/htm.rake +147 -0
  152. data/lib/tasks/jobs.rake +312 -0
  153. data/mkdocs.yml +190 -0
  154. data/scripts/install_local_database.sh +309 -0
  155. metadata +341 -0
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Custom LLM Configuration for HTM
5
+ #
6
+ # This example demonstrates how to configure HTM with custom LLM methods
7
+ # for embedding generation and tag extraction, as well as using defaults.
8
+
9
+ require_relative '../lib/htm'
10
+
11
+ puts "HTM Custom LLM Configuration Example"
12
+ puts "=" * 50
13
+
14
+ # Example 1: Use Default Configuration (RubyLLM with Ollama)
15
+ puts "\n1. Using Default Configuration (RubyLLM + Ollama)"
16
+ puts "-" * 50
17
+
18
+ HTM.configure # Uses defaults
19
+
20
+ htm = HTM.new(robot_name: "DefaultBot")
21
+ puts "✓ HTM initialized with default LLM configuration"
22
+ puts " Embedding provider: #{HTM.configuration.embedding_provider}"
23
+ puts " Embedding model: #{HTM.configuration.embedding_model}"
24
+ puts " Tag provider: #{HTM.configuration.tag_provider}"
25
+ puts " Tag model: #{HTM.configuration.tag_model}"
26
+
27
+ # Example 2: Custom Configuration with Lambdas
28
+ puts "\n2. Custom Configuration with Lambdas"
29
+ puts "-" * 50
30
+
31
+ HTM.configure do |config|
32
+ # Custom embedding generator
33
+ config.embedding_generator = lambda do |text|
34
+ puts " → Custom embedding generator called for: #{text[0..50]}..."
35
+ # Simulate custom embedding service
36
+ # In real application, this would call your LLM infrastructure
37
+ Array.new(768) { rand } # Returns 768-dimensional random vector
38
+ end
39
+
40
+ # Custom tag extractor
41
+ config.tag_extractor = lambda do |text, existing_ontology|
42
+ puts " → Custom tag extractor called for: #{text[0..50]}..."
43
+ puts " → Existing ontology size: #{existing_ontology.size}"
44
+ # Simulate custom tag extraction
45
+ # In real application, this would call your LLM infrastructure
46
+ ['custom:tag:example', 'test:automated']
47
+ end
48
+ end
49
+
50
+ htm = HTM.new(robot_name: "CustomBot")
51
+ puts "✓ HTM initialized with custom LLM configuration"
52
+
53
+ # Test the custom methods
54
+ embedding = HTM.embed("This is a test message")
55
+ puts "✓ Custom embedding generated: #{embedding.length} dimensions"
56
+
57
+ tags = HTM.extract_tags("PostgreSQL is a powerful database", existing_ontology: ['database:sql'])
58
+ puts "✓ Custom tags extracted: #{tags.join(', ')}"
59
+
60
+ # Example 3: Configure with Custom Class
61
+ puts "\n3. Custom Configuration with Service Object"
62
+ puts "-" * 50
63
+
64
+ # Define a custom LLM service class
65
+ class MyAppLLMService
66
+ def self.embed(text)
67
+ puts " → MyAppLLMService.embed called"
68
+ # Your application's embedding logic here
69
+ # Could integrate with LangChain, LlamaIndex, or custom infrastructure
70
+ Array.new(1024) { rand } # 1024-dimensional embeddings
71
+ end
72
+
73
+ def self.extract_tags(text, ontology)
74
+ puts " → MyAppLLMService.extract_tags called"
75
+ # Your application's tag extraction logic here
76
+ ['app:feature:memory', 'app:component:llm']
77
+ end
78
+ end
79
+
80
+ HTM.configure do |config|
81
+ config.embedding_generator = ->(text) { MyAppLLMService.embed(text) }
82
+ config.tag_extractor = ->(text, ontology) { MyAppLLMService.extract_tags(text, ontology) }
83
+ end
84
+
85
+ htm = HTM.new(robot_name: "ServiceBot")
86
+ puts "✓ HTM initialized with service object configuration"
87
+
88
+ embedding = HTM.embed("Another test message")
89
+ puts "✓ Service embedding generated: #{embedding.length} dimensions"
90
+
91
+ # Example 4: Mixed Configuration (Custom Embedding, Default Tags)
92
+ puts "\n4. Mixed Configuration (Custom + Default)"
93
+ puts "-" * 50
94
+
95
+ HTM.configure do |config|
96
+ # Use custom embedding
97
+ config.embedding_generator = ->(text) {
98
+ puts " → Using custom embedder"
99
+ Array.new(512) { rand }
100
+ }
101
+
102
+ # Keep default tag extraction
103
+ # (Already set by default, but showing explicit control)
104
+ config.reset_to_defaults # Reset both
105
+
106
+ # Then override just embedding
107
+ config.embedding_generator = ->(text) {
108
+ puts " → Using custom embedder with default tagger"
109
+ Array.new(512) { rand }
110
+ }
111
+ end
112
+
113
+ htm = HTM.new(robot_name: "MixedBot")
114
+ puts "✓ HTM initialized with mixed configuration"
115
+
116
+ # Example 5: Configure Provider Settings for Defaults
117
+ puts "\n5. Configuring Default Provider Settings"
118
+ puts "-" * 50
119
+
120
+ HTM.configure do |config|
121
+ # Customize the default RubyLLM configuration
122
+ config.embedding_provider = :ollama
123
+ config.embedding_model = 'nomic-embed-text'
124
+ config.embedding_dimensions = 768
125
+
126
+ config.tag_provider = :ollama
127
+ config.tag_model = 'llama3'
128
+
129
+ config.ollama_url = ENV['OLLAMA_URL'] || 'http://localhost:11434'
130
+
131
+ # Reset to use these new settings with default implementations
132
+ config.reset_to_defaults
133
+ end
134
+
135
+ htm = HTM.new(robot_name: "ConfiguredDefaultBot")
136
+ puts "✓ HTM initialized with configured default settings"
137
+ puts " Embedding model: #{HTM.configuration.embedding_model}"
138
+ puts " Tag model: #{HTM.configuration.tag_model}"
139
+ puts " Ollama URL: #{HTM.configuration.ollama_url}"
140
+
141
+ # Example 6: Integration with HTM Operations
142
+ puts "\n6. Using Custom Configuration in HTM Operations"
143
+ puts "-" * 50
144
+
145
+ # Configure with test implementation
146
+ HTM.configure do |config|
147
+ config.embedding_generator = ->(text) {
148
+ puts " → Embedding: #{text[0..40]}..."
149
+ Array.new(768) { rand }
150
+ }
151
+
152
+ config.tag_extractor = ->(text, ontology) {
153
+ puts " → Tagging: #{text[0..40]}..."
154
+ ['example:ruby:gem', 'memory:llm']
155
+ }
156
+ end
157
+
158
+ htm = HTM.new(robot_name: "IntegrationBot")
159
+
160
+ # Remember information - will use custom LLM configuration
161
+ puts "\nRemembering information in HTM..."
162
+ node_id = htm.remember(
163
+ "PostgreSQL with pgvector enables efficient vector similarity search",
164
+ source: 'user'
165
+ )
166
+
167
+ puts "✓ Information remembered with node_id: #{node_id}"
168
+ puts " Note: Embedding and LLM-generated tags will be processed asynchronously"
169
+
170
+ # The async jobs will call:
171
+ # - HTM.embed(content) for embedding generation
172
+ # - HTM.extract_tags(content, existing_ontology) for tag extraction
173
+
174
+ puts "\n" + "=" * 50
175
+ puts "Configuration Summary"
176
+ puts "=" * 50
177
+ puts "Applications can configure HTM by:"
178
+ puts "1. Using HTM.configure with a block"
179
+ puts "2. Providing embedding_generator callable (String → Array<Float>)"
180
+ puts "3. Providing tag_extractor callable (String, Array<String> → Array<String>)"
181
+ puts "4. Or using sensible defaults with RubyLLM + Ollama"
182
+ puts "\nHTM delegates all LLM operations to these configured methods,"
183
+ puts "allowing complete flexibility in LLM infrastructure."
@@ -0,0 +1,71 @@
1
+ # Example Application Rakefile
2
+ #
3
+ # This demonstrates how to integrate HTM rake tasks into your application.
4
+ # Simply require 'htm/tasks' and all database management tasks become available.
5
+
6
+ require 'bundler/setup'
7
+
8
+ # Load HTM database tasks - that's it!
9
+ require 'htm/tasks'
10
+
11
+ # Your application's custom tasks
12
+ namespace :app do
13
+ desc "Start the example application"
14
+ task :start do
15
+ puts "\n=== Starting Example HTM Application ==="
16
+ puts "Database configured: #{ENV['HTM_DBURL'] ? 'Yes' : 'No'}"
17
+ puts "\nRun 'rake -T' to see all available tasks"
18
+ puts "Run 'rake -T htm:db' to see HTM database tasks\n\n"
19
+
20
+ # Your app code here
21
+ require_relative 'app'
22
+ ExampleApp.run
23
+ end
24
+
25
+ desc "Bootstrap application (setup database + start)"
26
+ task :bootstrap => ['htm:db:setup', :start]
27
+ end
28
+
29
+ namespace :dev do
30
+ desc "Reset database for development (WARNING: destructive!)"
31
+ task :reset => ['htm:db:reset', 'htm:db:seed']
32
+ end
33
+
34
+ # Default task
35
+ task default: 'app:start'
36
+
37
+ # Show usage help
38
+ desc "Show usage help"
39
+ task :help do
40
+ puts <<~HELP
41
+
42
+ Example HTM Application - Available Commands
43
+ ============================================
44
+
45
+ Setup & Start:
46
+ rake app:bootstrap Bootstrap app (setup DB + start)
47
+ rake app:start Start the application (default)
48
+
49
+ Database Management:
50
+ rake htm:db:setup Set up HTM database schema
51
+ rake htm:db:migrate Run pending migrations
52
+ rake htm:db:status Show migration status
53
+ rake htm:db:info Show database information
54
+ rake htm:db:test Test database connection
55
+ rake htm:db:console Open PostgreSQL console
56
+ rake htm:db:seed Seed with sample data
57
+
58
+ Development:
59
+ rake dev:reset Reset database (drop/create/seed)
60
+
61
+ Destructive (Use with caution!):
62
+ rake htm:db:drop Drop all HTM tables
63
+ rake htm:db:reset Drop and recreate database
64
+
65
+ Environment:
66
+ export HTM_DBURL="postgresql://user:pass@host:port/dbname"
67
+
68
+ See docs/using_rake_tasks_in_your_app.md for more information.
69
+
70
+ HELP
71
+ end
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env ruby
2
+ # Example HTM Application
3
+ #
4
+ # This demonstrates a simple application using the HTM gem with full RubyLLM integration.
5
+
6
+ require_relative '../../lib/htm'
7
+ require 'ruby_llm'
8
+ require 'logger'
9
+
10
+ class ExampleApp
11
+ def self.run
12
+ puts "\n=== HTM Full-Featured Example Application ==="
13
+ puts "\nChecking database connection..."
14
+
15
+ # Check if database is configured
16
+ config = HTM::Database.default_config
17
+ unless config
18
+ puts "\n⚠ Database not configured!"
19
+ puts "Set HTM_DBURL environment variable:"
20
+ puts " export HTM_DBURL='postgresql://user:pass@host:port/dbname'"
21
+ puts "\nOr run: rake app:bootstrap"
22
+ return
23
+ end
24
+
25
+ puts "✓ Database configured: #{config[:dbname]} @ #{config[:host]}"
26
+
27
+ # Configure HTM with RubyLLM for embeddings and tag generation
28
+ puts "\nConfiguring HTM with RubyLLM..."
29
+ HTM.configure do |c|
30
+ # Configure logger
31
+ c.logger = Logger.new($stdout)
32
+ c.logger.level = Logger::INFO
33
+
34
+ # Configure embedding generation (using Ollama)
35
+ c.embedding_provider = :ollama
36
+ c.embedding_model = 'nomic-embed-text'
37
+ c.embedding_dimensions = 768
38
+ c.ollama_url = ENV['OLLAMA_URL'] || 'http://localhost:11434'
39
+
40
+ # Configure tag extraction (using Ollama - using smaller/faster model)
41
+ c.tag_provider = :ollama
42
+ c.tag_model = 'gemma3' # Smaller model (3.3GB) for faster tag generation
43
+
44
+ # Apply default implementations
45
+ c.reset_to_defaults
46
+ end
47
+
48
+ puts "✓ Configured with Ollama:"
49
+ puts " - Embeddings: #{HTM.configuration.embedding_model}"
50
+ puts " - Tags: #{HTM.configuration.tag_model}"
51
+ puts " - Ollama URL: #{HTM.configuration.ollama_url}"
52
+
53
+ # Check if Ollama is running
54
+ puts "\nChecking Ollama connection..."
55
+ begin
56
+ require 'net/http'
57
+ uri = URI(HTM.configuration.ollama_url)
58
+ response = Net::HTTP.get_response(uri)
59
+ puts "✓ Ollama is running"
60
+ rescue StandardError => e
61
+ puts "⚠ Warning: Cannot connect to Ollama (#{e.message})"
62
+ puts " Embeddings and tags will not be generated."
63
+ puts " Install Ollama: https://ollama.ai"
64
+ end
65
+
66
+ # Create HTM instance
67
+ puts "\nInitializing HTM..."
68
+ htm = HTM.new(robot_name: "Example App Robot")
69
+
70
+ # Remember some conversation (simulating a conversation)
71
+ puts "\nRemembering example conversation..."
72
+ puts "(Tags will be auto-extracted by LLM in background)"
73
+
74
+ node_1 = htm.remember(
75
+ "HTM provides intelligent memory management for LLM-based applications",
76
+ source: "assistant"
77
+ )
78
+
79
+ node_2 = htm.remember(
80
+ "The two-tier architecture includes working memory and long-term storage",
81
+ source: "assistant"
82
+ )
83
+
84
+ node_3 = htm.remember(
85
+ "Can you explain how the working memory eviction algorithm works?",
86
+ source: "user"
87
+ )
88
+
89
+ puts "✓ Remembered 3 conversation messages (nodes #{node_1}, #{node_2}, #{node_3})"
90
+ puts " Embeddings and tags are being generated asynchronously..."
91
+
92
+ # Wait for background jobs to complete
93
+ # Note: Tag generation with LLM can take 10-15 seconds depending on model size
94
+ puts "\nWaiting for background jobs to complete (15 seconds)..."
95
+ puts "(Embeddings are fast, but tag generation requires LLM inference)"
96
+ sleep 15
97
+
98
+ # Check what was generated
99
+ puts "\n--- Generated Tags ---"
100
+ [node_1, node_2, node_3].each do |node_id|
101
+ node = HTM::Models::Node.includes(:tags).find(node_id)
102
+ if node.tags.any?
103
+ puts "Node #{node_id}:"
104
+ node.tags.each { |tag| puts " - #{tag.name}" }
105
+ else
106
+ puts "Node #{node_id}: (no tags yet)"
107
+ end
108
+ end
109
+
110
+ # Check embeddings
111
+ puts "\n--- Embedding Status ---"
112
+ [node_1, node_2, node_3].each do |node_id|
113
+ node = HTM::Models::Node.find(node_id)
114
+ if node.embedding
115
+ dimensions = node.embedding.is_a?(Array) ? node.embedding.size : node.embedding_dimension
116
+ status = "✓ Generated (#{dimensions} dimensions)"
117
+ else
118
+ status = "⏳ Pending"
119
+ end
120
+ puts "Node #{node_id}: #{status}"
121
+ end
122
+
123
+ # Demonstrate different recall strategies
124
+ puts "\n--- Recall Strategies Comparison ---"
125
+
126
+ # 1. Full-text search (doesn't require embeddings)
127
+ puts "\n1. Full-text Search for 'memory':"
128
+ fulltext_memories = htm.recall(
129
+ "memory",
130
+ timeframe: (Time.now - 3600)..Time.now,
131
+ strategy: :fulltext,
132
+ limit: 3
133
+ )
134
+ puts "Found #{fulltext_memories.length} memories:"
135
+ fulltext_memories.each do |memory|
136
+ puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
137
+ end
138
+
139
+ # 2. Vector search (requires embeddings)
140
+ puts "\n2. Vector Search for 'intelligent memory system':"
141
+ begin
142
+ vector_memories = htm.recall(
143
+ "intelligent memory system",
144
+ timeframe: (Time.now - 3600)..Time.now,
145
+ strategy: :vector,
146
+ limit: 3
147
+ )
148
+ puts "Found #{vector_memories.length} memories:"
149
+ vector_memories.each do |memory|
150
+ puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
151
+ end
152
+ rescue StandardError => e
153
+ puts " ⚠ Vector search error: #{e.message}"
154
+ puts " #{e.class}: #{e.backtrace.first}"
155
+ end
156
+
157
+ # 3. Hybrid search (combines both)
158
+ puts "\n3. Hybrid Search for 'working memory architecture':"
159
+ begin
160
+ hybrid_memories = htm.recall(
161
+ "working memory architecture",
162
+ timeframe: (Time.now - 3600)..Time.now,
163
+ strategy: :hybrid,
164
+ limit: 3
165
+ )
166
+ puts "Found #{hybrid_memories.length} memories:"
167
+ hybrid_memories.each do |memory|
168
+ puts " - Node #{memory['id']}: #{memory['content'][0..60]}..."
169
+ end
170
+ rescue StandardError => e
171
+ puts " ⚠ Hybrid search error: #{e.message}"
172
+ puts " #{e.class}: #{e.backtrace.first}"
173
+ end
174
+
175
+ # Summary
176
+ puts "\n" + "="*60
177
+ puts "✓ Demo Complete!"
178
+ puts "="*60
179
+ puts "\nThe HTM API provides 3 core methods:"
180
+ puts " 1. htm.remember(content, source:)"
181
+ puts " - Stores information in long-term memory"
182
+ puts " - Adds to working memory for immediate use"
183
+ puts " - Generates embeddings and tags in background"
184
+ puts ""
185
+ puts " 2. htm.recall(timeframe:, topic:, strategy:, limit:)"
186
+ puts " - Retrieves relevant memories"
187
+ puts " - Strategies: :fulltext, :vector, :hybrid"
188
+ puts " - Results added to working memory"
189
+ puts ""
190
+ puts " 3. htm.forget(node_id, confirm: :confirmed)"
191
+ puts " - Permanently deletes a memory node"
192
+ puts " - Requires explicit confirmation"
193
+ puts ""
194
+ puts "Background Features:"
195
+ puts " - Automatic embedding generation (#{HTM.configuration.embedding_model})"
196
+ puts " - Automatic hierarchical tag extraction (#{HTM.configuration.tag_model})"
197
+ puts " - Token counting for context management"
198
+ puts " - Multi-robot shared memory (hive mind)"
199
+ puts ""
200
+ end
201
+ end
202
+
203
+ # Run directly if called as script
204
+ if __FILE__ == $0
205
+ ExampleApp.run
206
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Web framework
6
+ gem 'sinatra', '~> 3.0'
7
+ gem 'puma', '~> 6.0'
8
+
9
+ # Background jobs
10
+ gem 'sidekiq', '~> 7.0'
11
+ gem 'redis', '~> 5.0'
12
+
13
+ # HTM (use local development version)
14
+ gem 'htm', path: '../..'
15
+
16
+ # JSON handling
17
+ gem 'multi_json'
18
+
19
+ group :development do
20
+ gem 'rerun' # Auto-reload on file changes
21
+ end