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.
- checksums.yaml +7 -0
- data/.architecture/decisions/adrs/001-use-postgresql-timescaledb-storage.md +227 -0
- data/.architecture/decisions/adrs/002-two-tier-memory-architecture.md +322 -0
- data/.architecture/decisions/adrs/003-ollama-default-embedding-provider.md +339 -0
- data/.architecture/decisions/adrs/004-multi-robot-shared-memory-hive-mind.md +374 -0
- data/.architecture/decisions/adrs/005-rag-based-retrieval-with-hybrid-search.md +443 -0
- data/.architecture/decisions/adrs/006-context-assembly-strategies.md +444 -0
- data/.architecture/decisions/adrs/007-working-memory-eviction-strategy.md +461 -0
- data/.architecture/decisions/adrs/008-robot-identification-system.md +550 -0
- data/.architecture/decisions/adrs/009-never-forget-explicit-deletion-only.md +570 -0
- data/.architecture/decisions/adrs/010-redis-working-memory-rejected.md +323 -0
- data/.architecture/decisions/adrs/011-database-side-embedding-generation-with-pgai.md +585 -0
- data/.architecture/decisions/adrs/012-llm-driven-ontology-topic-extraction.md +583 -0
- data/.architecture/decisions/adrs/013-activerecord-orm-and-many-to-many-tagging.md +299 -0
- data/.architecture/decisions/adrs/014-client-side-embedding-generation-workflow.md +569 -0
- data/.architecture/decisions/adrs/015-hierarchical-tag-ontology-and-llm-extraction.md +701 -0
- data/.architecture/decisions/adrs/016-async-embedding-and-tag-generation.md +694 -0
- data/.architecture/members.yml +144 -0
- data/.architecture/reviews/2025-10-29-llm-configuration-and-async-processing-review.md +1137 -0
- data/.architecture/reviews/initial-system-analysis.md +330 -0
- data/.envrc +32 -0
- data/.irbrc +145 -0
- data/CHANGELOG.md +150 -0
- data/COMMITS.md +196 -0
- data/LICENSE +21 -0
- data/README.md +1347 -0
- data/Rakefile +51 -0
- data/SETUP.md +268 -0
- data/config/database.yml +67 -0
- data/db/migrate/20250101000001_enable_extensions.rb +14 -0
- data/db/migrate/20250101000002_create_robots.rb +14 -0
- data/db/migrate/20250101000003_create_nodes.rb +42 -0
- data/db/migrate/20250101000005_create_tags.rb +38 -0
- data/db/migrate/20250101000007_add_node_vector_indexes.rb +30 -0
- data/db/schema.sql +473 -0
- data/db/seed_data/README.md +100 -0
- data/db/seed_data/presidents.md +136 -0
- data/db/seed_data/states.md +151 -0
- data/db/seeds.rb +208 -0
- data/dbdoc/README.md +173 -0
- data/dbdoc/public.node_stats.md +48 -0
- data/dbdoc/public.node_stats.svg +41 -0
- data/dbdoc/public.node_tags.md +40 -0
- data/dbdoc/public.node_tags.svg +112 -0
- data/dbdoc/public.nodes.md +54 -0
- data/dbdoc/public.nodes.svg +118 -0
- data/dbdoc/public.nodes_tags.md +39 -0
- data/dbdoc/public.nodes_tags.svg +112 -0
- data/dbdoc/public.ontology_structure.md +48 -0
- data/dbdoc/public.ontology_structure.svg +38 -0
- data/dbdoc/public.operations_log.md +42 -0
- data/dbdoc/public.operations_log.svg +130 -0
- data/dbdoc/public.relationships.md +39 -0
- data/dbdoc/public.relationships.svg +41 -0
- data/dbdoc/public.robot_activity.md +46 -0
- data/dbdoc/public.robot_activity.svg +35 -0
- data/dbdoc/public.robots.md +35 -0
- data/dbdoc/public.robots.svg +90 -0
- data/dbdoc/public.schema_migrations.md +29 -0
- data/dbdoc/public.schema_migrations.svg +26 -0
- data/dbdoc/public.tags.md +35 -0
- data/dbdoc/public.tags.svg +60 -0
- data/dbdoc/public.topic_relationships.md +45 -0
- data/dbdoc/public.topic_relationships.svg +32 -0
- data/dbdoc/schema.json +1437 -0
- data/dbdoc/schema.svg +154 -0
- data/docs/api/database.md +806 -0
- data/docs/api/embedding-service.md +532 -0
- data/docs/api/htm.md +797 -0
- data/docs/api/index.md +259 -0
- data/docs/api/long-term-memory.md +1096 -0
- data/docs/api/working-memory.md +665 -0
- data/docs/architecture/adrs/001-postgresql-timescaledb.md +314 -0
- data/docs/architecture/adrs/002-two-tier-memory.md +411 -0
- data/docs/architecture/adrs/003-ollama-embeddings.md +421 -0
- data/docs/architecture/adrs/004-hive-mind.md +437 -0
- data/docs/architecture/adrs/005-rag-retrieval.md +531 -0
- data/docs/architecture/adrs/006-context-assembly.md +496 -0
- data/docs/architecture/adrs/007-eviction-strategy.md +645 -0
- data/docs/architecture/adrs/008-robot-identification.md +625 -0
- data/docs/architecture/adrs/009-never-forget.md +648 -0
- data/docs/architecture/adrs/010-redis-working-memory-rejected.md +323 -0
- data/docs/architecture/adrs/011-pgai-integration.md +494 -0
- data/docs/architecture/adrs/index.md +215 -0
- data/docs/architecture/hive-mind.md +736 -0
- data/docs/architecture/index.md +351 -0
- data/docs/architecture/overview.md +538 -0
- data/docs/architecture/two-tier-memory.md +873 -0
- data/docs/assets/css/custom.css +83 -0
- data/docs/assets/images/htm-core-components.svg +63 -0
- data/docs/assets/images/htm-database-schema.svg +93 -0
- data/docs/assets/images/htm-hive-mind-architecture.svg +125 -0
- data/docs/assets/images/htm-importance-scoring-framework.svg +83 -0
- data/docs/assets/images/htm-layered-architecture.svg +71 -0
- data/docs/assets/images/htm-long-term-memory-architecture.svg +115 -0
- data/docs/assets/images/htm-working-memory-architecture.svg +120 -0
- data/docs/assets/images/htm.jpg +0 -0
- data/docs/assets/images/htm_demo.gif +0 -0
- data/docs/assets/js/mathjax.js +18 -0
- data/docs/assets/videos/htm_video.mp4 +0 -0
- data/docs/database_rake_tasks.md +322 -0
- data/docs/development/contributing.md +787 -0
- data/docs/development/index.md +336 -0
- data/docs/development/schema.md +596 -0
- data/docs/development/setup.md +719 -0
- data/docs/development/testing.md +819 -0
- data/docs/guides/adding-memories.md +824 -0
- data/docs/guides/context-assembly.md +1009 -0
- data/docs/guides/getting-started.md +577 -0
- data/docs/guides/index.md +118 -0
- data/docs/guides/long-term-memory.md +941 -0
- data/docs/guides/multi-robot.md +866 -0
- data/docs/guides/recalling-memories.md +927 -0
- data/docs/guides/search-strategies.md +953 -0
- data/docs/guides/working-memory.md +717 -0
- data/docs/index.md +214 -0
- data/docs/installation.md +477 -0
- data/docs/multi_framework_support.md +519 -0
- data/docs/quick-start.md +655 -0
- data/docs/setup_local_database.md +302 -0
- data/docs/using_rake_tasks_in_your_app.md +383 -0
- data/examples/basic_usage.rb +93 -0
- data/examples/cli_app/README.md +317 -0
- data/examples/cli_app/htm_cli.rb +270 -0
- data/examples/custom_llm_configuration.rb +183 -0
- data/examples/example_app/Rakefile +71 -0
- data/examples/example_app/app.rb +206 -0
- data/examples/sinatra_app/Gemfile +21 -0
- data/examples/sinatra_app/app.rb +335 -0
- data/lib/htm/active_record_config.rb +113 -0
- data/lib/htm/configuration.rb +342 -0
- data/lib/htm/database.rb +594 -0
- data/lib/htm/embedding_service.rb +115 -0
- data/lib/htm/errors.rb +34 -0
- data/lib/htm/job_adapter.rb +154 -0
- data/lib/htm/jobs/generate_embedding_job.rb +65 -0
- data/lib/htm/jobs/generate_tags_job.rb +82 -0
- data/lib/htm/long_term_memory.rb +965 -0
- data/lib/htm/models/node.rb +109 -0
- data/lib/htm/models/node_tag.rb +33 -0
- data/lib/htm/models/robot.rb +52 -0
- data/lib/htm/models/tag.rb +76 -0
- data/lib/htm/railtie.rb +76 -0
- data/lib/htm/sinatra.rb +157 -0
- data/lib/htm/tag_service.rb +135 -0
- data/lib/htm/tasks.rb +38 -0
- data/lib/htm/version.rb +5 -0
- data/lib/htm/working_memory.rb +182 -0
- data/lib/htm.rb +400 -0
- data/lib/tasks/db.rake +19 -0
- data/lib/tasks/htm.rake +147 -0
- data/lib/tasks/jobs.rake +312 -0
- data/mkdocs.yml +190 -0
- data/scripts/install_local_database.sh +309 -0
- metadata +341 -0
data/lib/tasks/htm.rake
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# HTM Database Management Tasks
|
|
4
|
+
#
|
|
5
|
+
# These tasks are available to any application using the HTM gem.
|
|
6
|
+
# Add to your application's Rakefile:
|
|
7
|
+
#
|
|
8
|
+
# require 'htm/tasks'
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
# Add lib directory to load path for development
|
|
12
|
+
# This allows the tasks to work both during gem development and when installed
|
|
13
|
+
lib_path = File.expand_path('../../lib', __dir__)
|
|
14
|
+
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
|
|
15
|
+
|
|
16
|
+
namespace :htm do
|
|
17
|
+
namespace :db do
|
|
18
|
+
desc "Set up HTM database schema and run migrations (set DUMP_SCHEMA=true to auto-dump schema after)"
|
|
19
|
+
task :setup do
|
|
20
|
+
require 'htm'
|
|
21
|
+
dump_schema = ENV['DUMP_SCHEMA'] == 'true'
|
|
22
|
+
HTM::Database.setup(dump_schema: dump_schema)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "Run pending database migrations"
|
|
26
|
+
task :migrate do
|
|
27
|
+
require 'htm'
|
|
28
|
+
HTM::Database.migrate
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
desc "Show migration status"
|
|
32
|
+
task :status do
|
|
33
|
+
require 'htm'
|
|
34
|
+
HTM::Database.migration_status
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
desc "Drop all HTM tables (WARNING: destructive! Set CONFIRM=yes to skip prompt)"
|
|
38
|
+
task :drop do
|
|
39
|
+
require 'htm'
|
|
40
|
+
if ENV['CONFIRM'] == 'yes'
|
|
41
|
+
HTM::Database.drop
|
|
42
|
+
else
|
|
43
|
+
print "Are you sure you want to drop all tables? This cannot be undone! (yes/no): "
|
|
44
|
+
response = STDIN.gets&.chomp
|
|
45
|
+
if response&.downcase == 'yes'
|
|
46
|
+
HTM::Database.drop
|
|
47
|
+
else
|
|
48
|
+
puts "Cancelled."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc "Drop and recreate database (WARNING: destructive! Set CONFIRM=yes to skip prompt)"
|
|
54
|
+
task :reset do
|
|
55
|
+
require 'htm'
|
|
56
|
+
if ENV['CONFIRM'] == 'yes'
|
|
57
|
+
HTM::Database.drop
|
|
58
|
+
HTM::Database.setup(dump_schema: true)
|
|
59
|
+
else
|
|
60
|
+
print "Are you sure you want to drop all tables? This cannot be undone! (yes/no): "
|
|
61
|
+
response = STDIN.gets&.chomp
|
|
62
|
+
if response&.downcase == 'yes'
|
|
63
|
+
HTM::Database.drop
|
|
64
|
+
HTM::Database.setup(dump_schema: true)
|
|
65
|
+
else
|
|
66
|
+
puts "Cancelled."
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
desc "Test database connection"
|
|
72
|
+
task :test do
|
|
73
|
+
require 'htm'
|
|
74
|
+
config = HTM::Database.default_config
|
|
75
|
+
raise "Database not configured. Set HTM_DBURL environment variable." unless config
|
|
76
|
+
|
|
77
|
+
puts "Testing HTM database connection..."
|
|
78
|
+
puts " Host: #{config[:host]}"
|
|
79
|
+
puts " Port: #{config[:port]}"
|
|
80
|
+
puts " Database: #{config[:dbname]}"
|
|
81
|
+
puts " User: #{config[:user]}"
|
|
82
|
+
|
|
83
|
+
begin
|
|
84
|
+
require 'pg'
|
|
85
|
+
conn = PG.connect(config)
|
|
86
|
+
|
|
87
|
+
# Check pgvector
|
|
88
|
+
pgvector = conn.exec("SELECT extversion FROM pg_extension WHERE extname='vector'").first
|
|
89
|
+
if pgvector
|
|
90
|
+
puts " ✓ pgvector version: #{pgvector['extversion']}"
|
|
91
|
+
else
|
|
92
|
+
puts " ⚠ Warning: pgvector extension not found"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
conn.close
|
|
96
|
+
puts "✓ Connection successful!"
|
|
97
|
+
rescue PG::Error => e
|
|
98
|
+
puts "✗ Connection failed: #{e.message}"
|
|
99
|
+
exit 1
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
desc "Open PostgreSQL console"
|
|
104
|
+
task :console do
|
|
105
|
+
require 'htm'
|
|
106
|
+
config = HTM::Database.default_config
|
|
107
|
+
raise "Database not configured. Set HTM_DBURL environment variable." unless config
|
|
108
|
+
|
|
109
|
+
exec "psql", "-h", config[:host],
|
|
110
|
+
"-p", config[:port].to_s,
|
|
111
|
+
"-U", config[:user],
|
|
112
|
+
"-d", config[:dbname]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
desc "Seed database with sample data"
|
|
116
|
+
task :seed do
|
|
117
|
+
require 'htm'
|
|
118
|
+
HTM::Database.seed
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
desc "Show database info (size, tables, extensions)"
|
|
122
|
+
task :info do
|
|
123
|
+
require 'htm'
|
|
124
|
+
HTM::Database.info
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
namespace :schema do
|
|
128
|
+
desc "Dump current schema to db/schema.sql"
|
|
129
|
+
task :dump do
|
|
130
|
+
require 'htm'
|
|
131
|
+
HTM::Database.dump_schema
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
desc "Load schema from db/schema.sql"
|
|
135
|
+
task :load do
|
|
136
|
+
require 'htm'
|
|
137
|
+
HTM::Database.load_schema
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
desc "Generate/update database documentation in dbdoc/"
|
|
142
|
+
task :doc do
|
|
143
|
+
require 'htm'
|
|
144
|
+
HTM::Database.generate_docs
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
data/lib/tasks/jobs.rake
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :htm do
|
|
4
|
+
namespace :jobs do
|
|
5
|
+
desc "Show statistics for nodes and async job processing"
|
|
6
|
+
task :stats => :environment do
|
|
7
|
+
require 'htm'
|
|
8
|
+
|
|
9
|
+
# Establish connection
|
|
10
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
11
|
+
|
|
12
|
+
puts "HTM Async Job Statistics"
|
|
13
|
+
puts "=" * 60
|
|
14
|
+
|
|
15
|
+
# Total nodes
|
|
16
|
+
total_nodes = HTM::Models::Node.count
|
|
17
|
+
puts "Total nodes: #{total_nodes}"
|
|
18
|
+
|
|
19
|
+
# Nodes with embeddings
|
|
20
|
+
with_embeddings = HTM::Models::Node.where.not(embedding: nil).count
|
|
21
|
+
puts "Nodes with embeddings: #{with_embeddings} (#{percentage(with_embeddings, total_nodes)}%)"
|
|
22
|
+
|
|
23
|
+
# Nodes without embeddings (pending embedding jobs)
|
|
24
|
+
without_embeddings = HTM::Models::Node.where(embedding: nil).count
|
|
25
|
+
puts "Nodes without embeddings: #{without_embeddings} (#{percentage(without_embeddings, total_nodes)}%)"
|
|
26
|
+
|
|
27
|
+
# Nodes with tags
|
|
28
|
+
nodes_with_tags = HTM::Models::Node
|
|
29
|
+
.joins(:node_tags)
|
|
30
|
+
.distinct
|
|
31
|
+
.count
|
|
32
|
+
puts "Nodes with tags: #{nodes_with_tags} (#{percentage(nodes_with_tags, total_nodes)}%)"
|
|
33
|
+
|
|
34
|
+
# Nodes without tags
|
|
35
|
+
nodes_without_tags = total_nodes - nodes_with_tags
|
|
36
|
+
puts "Nodes without tags: #{nodes_without_tags} (#{percentage(nodes_without_tags, total_nodes)}%)"
|
|
37
|
+
|
|
38
|
+
# Total tags
|
|
39
|
+
total_tags = HTM::Models::Tag.count
|
|
40
|
+
puts "\nTotal tags in ontology: #{total_tags}"
|
|
41
|
+
|
|
42
|
+
# Tags by depth
|
|
43
|
+
if total_tags > 0
|
|
44
|
+
puts "\nTag hierarchy breakdown:"
|
|
45
|
+
HTM::Models::Tag.all.each do |tag|
|
|
46
|
+
depth = tag.name.count(':')
|
|
47
|
+
puts " Depth #{depth}: #{tag.name.count(':', depth)} tags" if depth <= 3
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Average tags per node
|
|
52
|
+
if nodes_with_tags > 0
|
|
53
|
+
avg_tags = HTM::Models::NodeTag.count.to_f / nodes_with_tags
|
|
54
|
+
puts "\nAverage tags per node: #{avg_tags.round(2)}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
desc "Process pending embedding jobs for nodes without embeddings"
|
|
61
|
+
task :process_embeddings => :environment do
|
|
62
|
+
require 'htm'
|
|
63
|
+
|
|
64
|
+
# Establish connection and configure HTM
|
|
65
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
66
|
+
HTM.configure # Use default configuration
|
|
67
|
+
|
|
68
|
+
# Find nodes without embeddings
|
|
69
|
+
pending_nodes = HTM::Models::Node.where(embedding: nil)
|
|
70
|
+
total = pending_nodes.count
|
|
71
|
+
|
|
72
|
+
if total.zero?
|
|
73
|
+
puts "No pending embedding jobs"
|
|
74
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
75
|
+
exit 0
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
puts "Processing #{total} pending embedding jobs..."
|
|
79
|
+
|
|
80
|
+
processed = 0
|
|
81
|
+
failed = 0
|
|
82
|
+
|
|
83
|
+
pending_nodes.find_each do |node|
|
|
84
|
+
begin
|
|
85
|
+
# Use the service class directly (same as job)
|
|
86
|
+
result = HTM::EmbeddingService.generate(node.content)
|
|
87
|
+
node.update!(
|
|
88
|
+
embedding: result[:storage_embedding],
|
|
89
|
+
embedding_dimension: result[:dimension]
|
|
90
|
+
)
|
|
91
|
+
processed += 1
|
|
92
|
+
print "\rProcessed: #{processed}/#{total}"
|
|
93
|
+
rescue StandardError => e
|
|
94
|
+
failed += 1
|
|
95
|
+
HTM.logger.error "Failed to process node #{node.id}: #{e.message}"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
puts "\n\nCompleted:"
|
|
100
|
+
puts " Processed: #{processed}"
|
|
101
|
+
puts " Failed: #{failed}"
|
|
102
|
+
|
|
103
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
desc "Process pending tag extraction jobs for nodes without tags"
|
|
107
|
+
task :process_tags => :environment do
|
|
108
|
+
require 'htm'
|
|
109
|
+
|
|
110
|
+
# Establish connection and configure HTM
|
|
111
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
112
|
+
HTM.configure # Use default configuration
|
|
113
|
+
|
|
114
|
+
# Find nodes without any tags
|
|
115
|
+
nodes_without_tags = HTM::Models::Node
|
|
116
|
+
.left_joins(:node_tags)
|
|
117
|
+
.where(node_tags: { id: nil })
|
|
118
|
+
|
|
119
|
+
total = nodes_without_tags.count
|
|
120
|
+
|
|
121
|
+
if total.zero?
|
|
122
|
+
puts "No pending tag extraction jobs"
|
|
123
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
124
|
+
exit 0
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
puts "Processing #{total} pending tag extraction jobs..."
|
|
128
|
+
|
|
129
|
+
processed = 0
|
|
130
|
+
failed = 0
|
|
131
|
+
|
|
132
|
+
nodes_without_tags.find_each do |node|
|
|
133
|
+
begin
|
|
134
|
+
# Use the service class directly (same as job)
|
|
135
|
+
existing_ontology = HTM::Models::Tag.order(created_at: :desc).limit(100).pluck(:name)
|
|
136
|
+
tag_names = HTM::TagService.extract(node.content, existing_ontology: existing_ontology)
|
|
137
|
+
|
|
138
|
+
tag_names.each do |tag_name|
|
|
139
|
+
tag = HTM::Models::Tag.find_or_create_by!(name: tag_name)
|
|
140
|
+
HTM::Models::NodeTag.find_or_create_by!(node_id: node.id, tag_id: tag.id)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
processed += 1
|
|
144
|
+
print "\rProcessed: #{processed}/#{total}"
|
|
145
|
+
rescue StandardError => e
|
|
146
|
+
failed += 1
|
|
147
|
+
HTM.logger.error "Failed to process node #{node.id}: #{e.message}"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
puts "\n\nCompleted:"
|
|
152
|
+
puts " Processed: #{processed}"
|
|
153
|
+
puts " Failed: #{failed}"
|
|
154
|
+
|
|
155
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
desc "Process all pending jobs (embeddings and tags)"
|
|
159
|
+
task :process_all => [:process_embeddings, :process_tags] do
|
|
160
|
+
puts "\nAll pending jobs processed!"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
desc "Reprocess embeddings for all nodes (force regeneration)"
|
|
164
|
+
task :reprocess_embeddings => :environment do
|
|
165
|
+
require 'htm'
|
|
166
|
+
|
|
167
|
+
print "This will regenerate embeddings for ALL nodes. Are you sure? (yes/no): "
|
|
168
|
+
confirmation = $stdin.gets.chomp
|
|
169
|
+
|
|
170
|
+
unless confirmation.downcase == 'yes'
|
|
171
|
+
puts "Cancelled."
|
|
172
|
+
exit 0
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Establish connection and configure HTM
|
|
176
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
177
|
+
HTM.configure # Use default configuration
|
|
178
|
+
|
|
179
|
+
total = HTM::Models::Node.count
|
|
180
|
+
|
|
181
|
+
puts "Reprocessing embeddings for #{total} nodes..."
|
|
182
|
+
|
|
183
|
+
processed = 0
|
|
184
|
+
failed = 0
|
|
185
|
+
|
|
186
|
+
HTM::Models::Node.find_each do |node|
|
|
187
|
+
begin
|
|
188
|
+
# Use the service class directly to regenerate
|
|
189
|
+
result = HTM::EmbeddingService.generate(node.content)
|
|
190
|
+
node.update!(
|
|
191
|
+
embedding: result[:storage_embedding],
|
|
192
|
+
embedding_dimension: result[:dimension]
|
|
193
|
+
)
|
|
194
|
+
processed += 1
|
|
195
|
+
print "\rProcessed: #{processed}/#{total}"
|
|
196
|
+
rescue StandardError => e
|
|
197
|
+
failed += 1
|
|
198
|
+
HTM.logger.error "Failed to reprocess node #{node.id}: #{e.message}"
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
puts "\n\nCompleted:"
|
|
203
|
+
puts " Processed: #{processed}"
|
|
204
|
+
puts " Failed: #{failed}"
|
|
205
|
+
|
|
206
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
desc "Show nodes that failed async processing"
|
|
210
|
+
task :failed => :environment do
|
|
211
|
+
require 'htm'
|
|
212
|
+
|
|
213
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
214
|
+
|
|
215
|
+
puts "Nodes with Processing Issues"
|
|
216
|
+
puts "=" * 60
|
|
217
|
+
|
|
218
|
+
# Old nodes without embeddings (created more than 1 hour ago)
|
|
219
|
+
old_without_embeddings = HTM::Models::Node
|
|
220
|
+
.where(embedding: nil)
|
|
221
|
+
.where('created_at < ?', 1.hour.ago)
|
|
222
|
+
|
|
223
|
+
if old_without_embeddings.any?
|
|
224
|
+
puts "\nNodes without embeddings (>1 hour old):"
|
|
225
|
+
old_without_embeddings.limit(10).each do |node|
|
|
226
|
+
puts " Node #{node.id}: created #{time_ago(node.created_at)}"
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
if old_without_embeddings.count > 10
|
|
230
|
+
puts " ... and #{old_without_embeddings.count - 10} more"
|
|
231
|
+
end
|
|
232
|
+
else
|
|
233
|
+
puts "\n✓ No old nodes without embeddings"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Old nodes without tags
|
|
237
|
+
old_without_tags = HTM::Models::Node
|
|
238
|
+
.left_joins(:node_tags)
|
|
239
|
+
.where(node_tags: { id: nil })
|
|
240
|
+
.where('nodes.created_at < ?', 1.hour.ago)
|
|
241
|
+
|
|
242
|
+
if old_without_tags.any?
|
|
243
|
+
puts "\nNodes without tags (>1 hour old):"
|
|
244
|
+
old_without_tags.limit(10).each do |node|
|
|
245
|
+
puts " Node #{node.id}: created #{time_ago(node.created_at)}"
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
if old_without_tags.count > 10
|
|
249
|
+
puts " ... and #{old_without_tags.count - 10} more"
|
|
250
|
+
end
|
|
251
|
+
else
|
|
252
|
+
puts "\n✓ No old nodes without tags"
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
desc "Clear all embeddings and tags (for testing/development)"
|
|
259
|
+
task :clear_all => :environment do
|
|
260
|
+
require 'htm'
|
|
261
|
+
|
|
262
|
+
print "This will clear ALL embeddings and tags. Are you sure? (yes/no): "
|
|
263
|
+
confirmation = $stdin.gets.chomp
|
|
264
|
+
|
|
265
|
+
unless confirmation.downcase == 'yes'
|
|
266
|
+
puts "Cancelled."
|
|
267
|
+
exit 0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
HTM::ActiveRecordConfig.establish_connection!
|
|
271
|
+
|
|
272
|
+
puts "Clearing embeddings..."
|
|
273
|
+
HTM::Models::Node.update_all(embedding: nil, embedding_dimension: nil)
|
|
274
|
+
|
|
275
|
+
puts "Clearing tags..."
|
|
276
|
+
HTM::Models::NodeTag.delete_all
|
|
277
|
+
HTM::Models::Tag.delete_all
|
|
278
|
+
|
|
279
|
+
puts "Done! All embeddings and tags cleared."
|
|
280
|
+
|
|
281
|
+
HTM::ActiveRecordConfig.disconnect!
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Helper methods
|
|
285
|
+
def percentage(part, whole)
|
|
286
|
+
return 0 if whole.zero?
|
|
287
|
+
((part.to_f / whole) * 100).round(1)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def time_ago(time)
|
|
291
|
+
seconds = Time.now - time
|
|
292
|
+
case seconds
|
|
293
|
+
when 0..59
|
|
294
|
+
"#{seconds.to_i} seconds ago"
|
|
295
|
+
when 60..3599
|
|
296
|
+
"#{(seconds / 60).to_i} minutes ago"
|
|
297
|
+
when 3600..86399
|
|
298
|
+
"#{(seconds / 3600).to_i} hours ago"
|
|
299
|
+
else
|
|
300
|
+
"#{(seconds / 86400).to_i} days ago"
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Add :environment task if not already defined (for standalone usage)
|
|
307
|
+
unless Rake::Task.task_defined?(:environment)
|
|
308
|
+
task :environment do
|
|
309
|
+
# No-op for standalone usage
|
|
310
|
+
# Applications can override this to set up their environment
|
|
311
|
+
end
|
|
312
|
+
end
|
data/mkdocs.yml
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# MkDocs Configuration for HTM Documentation
|
|
2
|
+
site_name: HTM - Hierarchical Temporary Memory
|
|
3
|
+
site_description: Intelligent memory management for LLM robots with two-tier architecture and RAG-based retrieval
|
|
4
|
+
site_author: Dewayne VanHoozer
|
|
5
|
+
site_url: https://madbomber.github.io/htm
|
|
6
|
+
copyright: Copyright © 2025 Dewayne VanHoozer
|
|
7
|
+
|
|
8
|
+
# Repository information
|
|
9
|
+
repo_name: madbomber/htm
|
|
10
|
+
repo_url: https://github.com/madbomber/htm
|
|
11
|
+
edit_uri: edit/main/docs/
|
|
12
|
+
|
|
13
|
+
# Configuration
|
|
14
|
+
theme:
|
|
15
|
+
name: material
|
|
16
|
+
|
|
17
|
+
# Color scheme - Default to light mode
|
|
18
|
+
palette:
|
|
19
|
+
# Palette toggle for light mode (default)
|
|
20
|
+
- scheme: default
|
|
21
|
+
primary: blue
|
|
22
|
+
accent: blue
|
|
23
|
+
toggle:
|
|
24
|
+
icon: material/brightness-7
|
|
25
|
+
name: Switch to dark mode
|
|
26
|
+
|
|
27
|
+
# Palette toggle for dark mode
|
|
28
|
+
- scheme: slate
|
|
29
|
+
primary: blue
|
|
30
|
+
accent: blue
|
|
31
|
+
toggle:
|
|
32
|
+
icon: material/brightness-4
|
|
33
|
+
name: Switch to light mode
|
|
34
|
+
|
|
35
|
+
# Typography
|
|
36
|
+
font:
|
|
37
|
+
text: Roboto
|
|
38
|
+
code: Roboto Mono
|
|
39
|
+
|
|
40
|
+
# Theme features
|
|
41
|
+
features:
|
|
42
|
+
# Navigation
|
|
43
|
+
- navigation.instant
|
|
44
|
+
- navigation.tracking
|
|
45
|
+
- navigation.tabs
|
|
46
|
+
- navigation.tabs.sticky
|
|
47
|
+
- navigation.sections
|
|
48
|
+
- navigation.path
|
|
49
|
+
- navigation.indexes
|
|
50
|
+
- navigation.top
|
|
51
|
+
|
|
52
|
+
# Table of contents
|
|
53
|
+
- toc.follow
|
|
54
|
+
|
|
55
|
+
# Search
|
|
56
|
+
- search.suggest
|
|
57
|
+
- search.highlight
|
|
58
|
+
- search.share
|
|
59
|
+
|
|
60
|
+
# Header
|
|
61
|
+
- header.autohide
|
|
62
|
+
|
|
63
|
+
# Content
|
|
64
|
+
- content.code.copy
|
|
65
|
+
- content.code.annotate
|
|
66
|
+
- content.tabs.link
|
|
67
|
+
- content.tooltips
|
|
68
|
+
- content.action.edit
|
|
69
|
+
- content.action.view
|
|
70
|
+
|
|
71
|
+
# Plugins
|
|
72
|
+
plugins:
|
|
73
|
+
- search:
|
|
74
|
+
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
|
|
75
|
+
|
|
76
|
+
# Extensions
|
|
77
|
+
markdown_extensions:
|
|
78
|
+
# Python Markdown
|
|
79
|
+
- abbr
|
|
80
|
+
- admonition
|
|
81
|
+
- attr_list
|
|
82
|
+
- def_list
|
|
83
|
+
- footnotes
|
|
84
|
+
- md_in_html
|
|
85
|
+
- toc:
|
|
86
|
+
permalink: true
|
|
87
|
+
title: On this page
|
|
88
|
+
|
|
89
|
+
# Python Markdown Extensions
|
|
90
|
+
- pymdownx.arithmatex:
|
|
91
|
+
generic: true
|
|
92
|
+
- pymdownx.betterem:
|
|
93
|
+
smart_enable: all
|
|
94
|
+
- pymdownx.caret
|
|
95
|
+
- pymdownx.details
|
|
96
|
+
- pymdownx.emoji:
|
|
97
|
+
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
|
98
|
+
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
|
99
|
+
- pymdownx.highlight:
|
|
100
|
+
anchor_linenums: true
|
|
101
|
+
line_spans: __span
|
|
102
|
+
pygments_lang_class: true
|
|
103
|
+
- pymdownx.inlinehilite
|
|
104
|
+
- pymdownx.keys
|
|
105
|
+
- pymdownx.magiclink:
|
|
106
|
+
repo_url_shorthand: true
|
|
107
|
+
user: madbomber
|
|
108
|
+
repo: htm
|
|
109
|
+
- pymdownx.mark
|
|
110
|
+
- pymdownx.smartsymbols
|
|
111
|
+
- pymdownx.superfences:
|
|
112
|
+
custom_fences:
|
|
113
|
+
- name: mermaid
|
|
114
|
+
class: mermaid
|
|
115
|
+
format: !!python/name:pymdownx.superfences.fence_code_format
|
|
116
|
+
- pymdownx.tabbed:
|
|
117
|
+
alternate_style: true
|
|
118
|
+
- pymdownx.tasklist:
|
|
119
|
+
custom_checkbox: true
|
|
120
|
+
- pymdownx.tilde
|
|
121
|
+
|
|
122
|
+
# Extra CSS and JavaScript
|
|
123
|
+
extra_css:
|
|
124
|
+
- assets/css/custom.css
|
|
125
|
+
|
|
126
|
+
extra_javascript:
|
|
127
|
+
- assets/js/mathjax.js
|
|
128
|
+
- https://polyfill.io/v3/polyfill.min.js?features=es6
|
|
129
|
+
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
|
|
130
|
+
|
|
131
|
+
# Social media and extra configuration
|
|
132
|
+
extra:
|
|
133
|
+
social:
|
|
134
|
+
- icon: fontawesome/brands/github
|
|
135
|
+
link: https://github.com/madbomber/htm
|
|
136
|
+
name: HTM on GitHub
|
|
137
|
+
- icon: fontawesome/solid/gem
|
|
138
|
+
link: https://rubygems.org/gems/htm
|
|
139
|
+
name: HTM on RubyGems
|
|
140
|
+
|
|
141
|
+
# Navigation
|
|
142
|
+
nav:
|
|
143
|
+
- Home: index.md
|
|
144
|
+
- Installation: installation.md
|
|
145
|
+
- Quick Start: quick-start.md
|
|
146
|
+
- Architecture:
|
|
147
|
+
- architecture/index.md
|
|
148
|
+
- Overview: architecture/overview.md
|
|
149
|
+
- Two-Tier Memory: architecture/two-tier-memory.md
|
|
150
|
+
- Hive Mind: architecture/hive-mind.md
|
|
151
|
+
- ADRs:
|
|
152
|
+
- architecture/adrs/index.md
|
|
153
|
+
- ADR-001 PostgreSQL & TimescaleDB: architecture/adrs/001-postgresql-timescaledb.md
|
|
154
|
+
- ADR-002 Two-Tier Memory: architecture/adrs/002-two-tier-memory.md
|
|
155
|
+
- ADR-003 Ollama Embeddings: architecture/adrs/003-ollama-embeddings.md
|
|
156
|
+
- ADR-004 Hive Mind: architecture/adrs/004-hive-mind.md
|
|
157
|
+
- ADR-005 RAG Retrieval: architecture/adrs/005-rag-retrieval.md
|
|
158
|
+
- ADR-006 Context Assembly: architecture/adrs/006-context-assembly.md
|
|
159
|
+
- ADR-007 Eviction Strategy: architecture/adrs/007-eviction-strategy.md
|
|
160
|
+
- ADR-008 Robot Identification: architecture/adrs/008-robot-identification.md
|
|
161
|
+
- ADR-009 Never-Forget Philosophy: architecture/adrs/009-never-forget.md
|
|
162
|
+
- ADR-010 Redis Working Memory (Rejected): architecture/adrs/010-redis-working-memory-rejected.md
|
|
163
|
+
- ADR-011 pgai Integration: architecture/adrs/011-pgai-integration.md
|
|
164
|
+
- Guides:
|
|
165
|
+
- guides/index.md
|
|
166
|
+
- Getting Started: guides/getting-started.md
|
|
167
|
+
- Adding Memories: guides/adding-memories.md
|
|
168
|
+
- Recalling Memories: guides/recalling-memories.md
|
|
169
|
+
- Working Memory: guides/working-memory.md
|
|
170
|
+
- Long-Term Memory: guides/long-term-memory.md
|
|
171
|
+
- Multi-Robot Usage: guides/multi-robot.md
|
|
172
|
+
- Search Strategies: guides/search-strategies.md
|
|
173
|
+
- Context Assembly: guides/context-assembly.md
|
|
174
|
+
- API Reference:
|
|
175
|
+
- api/index.md
|
|
176
|
+
- HTM Class: api/htm.md
|
|
177
|
+
- Working Memory: api/working-memory.md
|
|
178
|
+
- Long-Term Memory: api/long-term-memory.md
|
|
179
|
+
- Embedding Service: api/embedding-service.md
|
|
180
|
+
- Database: api/database.md
|
|
181
|
+
- Development:
|
|
182
|
+
- development/index.md
|
|
183
|
+
- Setup: development/setup.md
|
|
184
|
+
- Testing: development/testing.md
|
|
185
|
+
- Contributing: development/contributing.md
|
|
186
|
+
- Database Schema: development/schema.md
|
|
187
|
+
- Multi-Framework Support: multi_framework_support.md
|
|
188
|
+
- Database Rake Tasks: database_rake_tasks.md
|
|
189
|
+
- Using Rake Tasks: using_rake_tasks_in_your_app.md
|
|
190
|
+
- Setup Local Database: setup_local_database.md
|