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
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
# HTM Multi-Framework Support
|
|
2
|
+
|
|
3
|
+
HTM works seamlessly in three types of applications:
|
|
4
|
+
1. **CLI Applications** - Command-line tools with synchronous execution
|
|
5
|
+
2. **Sinatra Applications** - Web apps with Sidekiq background jobs
|
|
6
|
+
3. **Rails Applications** - Full Rails integration with ActiveJob
|
|
7
|
+
|
|
8
|
+
## Quick Start by Framework
|
|
9
|
+
|
|
10
|
+
### CLI Applications
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
#!/usr/bin/env ruby
|
|
14
|
+
require 'htm'
|
|
15
|
+
|
|
16
|
+
# Configure for CLI (synchronous execution)
|
|
17
|
+
HTM.configure do |config|
|
|
18
|
+
config.job_backend = :inline # Jobs run immediately
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
htm = HTM.new(robot_name: "cli_assistant")
|
|
22
|
+
|
|
23
|
+
# Store information (waits for embedding + tags)
|
|
24
|
+
node_id = htm.remember("PostgreSQL is great for time-series data")
|
|
25
|
+
puts "Stored as node #{node_id}"
|
|
26
|
+
|
|
27
|
+
# Search memories
|
|
28
|
+
memories = htm.recall("PostgreSQL", limit: 10)
|
|
29
|
+
puts "Found #{memories.length} memories"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Example:** [`examples/cli_app/htm_cli.rb`](https://github.com/madbomber/htm/blob/main/examples/cli_app/htm_cli.rb)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### Sinatra Applications
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
require 'sinatra'
|
|
40
|
+
require 'htm'
|
|
41
|
+
require 'htm/sinatra'
|
|
42
|
+
|
|
43
|
+
class MyApp < Sinatra::Base
|
|
44
|
+
# Automatically configures HTM with Sidekiq
|
|
45
|
+
register_htm
|
|
46
|
+
|
|
47
|
+
enable :sessions
|
|
48
|
+
|
|
49
|
+
before do
|
|
50
|
+
init_htm(robot_name: session[:user_id] || 'guest')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
post '/remember' do
|
|
54
|
+
node_id = remember(params[:content], source: 'user')
|
|
55
|
+
json status: 'ok', node_id: node_id
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
get '/recall' do
|
|
59
|
+
memories = recall(params[:topic], limit: 10)
|
|
60
|
+
json memories: memories
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Example:** [`examples/sinatra_app/app.rb`](https://github.com/madbomber/htm/blob/main/examples/sinatra_app/app.rb)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Rails Applications
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
# HTM automatically configures itself in Rails
|
|
73
|
+
|
|
74
|
+
# app/controllers/memories_controller.rb
|
|
75
|
+
class MemoriesController < ApplicationController
|
|
76
|
+
def create
|
|
77
|
+
htm = HTM.new(robot_name: "user_#{current_user.id}")
|
|
78
|
+
node_id = htm.remember(params[:content], source: 'user')
|
|
79
|
+
|
|
80
|
+
render json: { status: 'ok', node_id: node_id }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def index
|
|
84
|
+
htm = HTM.new(robot_name: "user_#{current_user.id}")
|
|
85
|
+
memories = htm.recall(params[:topic], limit: 10)
|
|
86
|
+
|
|
87
|
+
render json: { memories: memories }
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Rails auto-configuration happens via `HTM::Railtie`:
|
|
93
|
+
- Uses Rails.logger
|
|
94
|
+
- Uses ActiveJob for background jobs
|
|
95
|
+
- Inline jobs in test environment
|
|
96
|
+
- Rake tasks auto-loaded
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Job Backend Comparison
|
|
101
|
+
|
|
102
|
+
| Backend | Best For | Speed | Infrastructure | Use Case |
|
|
103
|
+
|---------|----------|-------|----------------|----------|
|
|
104
|
+
| `:inline` | CLI, Tests | Slow (synchronous) | None | Development, testing, CLI tools |
|
|
105
|
+
| `:thread` | Simple apps | Fast | None | Quick prototypes, standalone |
|
|
106
|
+
| `:sidekiq` | Sinatra | Fast | Redis required | Microservices, Sinatra apps |
|
|
107
|
+
| `:active_job` | Rails | Fast | Rails required | Rails applications |
|
|
108
|
+
|
|
109
|
+
### Performance Characteristics
|
|
110
|
+
|
|
111
|
+
**:inline (Synchronous)**
|
|
112
|
+
```ruby
|
|
113
|
+
# User waits for completion
|
|
114
|
+
node_id = htm.remember("text") # ~1-3 seconds
|
|
115
|
+
# Embedding and tags already generated
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**:sidekiq/:active_job (Asynchronous)**
|
|
119
|
+
```ruby
|
|
120
|
+
# User gets immediate response
|
|
121
|
+
node_id = htm.remember("text") # ~15ms
|
|
122
|
+
# Embedding and tags generated in background (~1 second)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
### Auto-Detection
|
|
130
|
+
|
|
131
|
+
HTM automatically detects the appropriate backend:
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
# Test environment → :inline
|
|
135
|
+
ENV['RAILS_ENV'] = 'test'
|
|
136
|
+
HTM.configuration.job_backend # => :inline
|
|
137
|
+
|
|
138
|
+
# Rails app → :active_job
|
|
139
|
+
defined?(ActiveJob)
|
|
140
|
+
HTM.configuration.job_backend # => :active_job
|
|
141
|
+
|
|
142
|
+
# Sidekiq available → :sidekiq
|
|
143
|
+
defined?(Sidekiq)
|
|
144
|
+
HTM.configuration.job_backend # => :sidekiq
|
|
145
|
+
|
|
146
|
+
# Default → :thread
|
|
147
|
+
HTM.configuration.job_backend # => :thread
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Manual Override
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
HTM.configure do |config|
|
|
154
|
+
config.job_backend = :inline # Force synchronous
|
|
155
|
+
end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Environment Variable
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
export HTM_JOB_BACKEND=inline # Override auto-detection
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Framework-Specific Features
|
|
167
|
+
|
|
168
|
+
### CLI Applications
|
|
169
|
+
|
|
170
|
+
**Features:**
|
|
171
|
+
- Synchronous execution (`:inline` backend)
|
|
172
|
+
- Progress feedback in terminal
|
|
173
|
+
- No background infrastructure needed
|
|
174
|
+
- Simple error handling
|
|
175
|
+
|
|
176
|
+
**Best Practices:**
|
|
177
|
+
```ruby
|
|
178
|
+
# Use inline backend
|
|
179
|
+
HTM.configure do |config|
|
|
180
|
+
config.job_backend = :inline
|
|
181
|
+
|
|
182
|
+
# CLI-friendly logging
|
|
183
|
+
config.logger.formatter = proc do |severity, datetime, progname, msg|
|
|
184
|
+
case severity
|
|
185
|
+
when 'INFO' then "[✓] #{msg}\n"
|
|
186
|
+
when 'ERROR' then "[✗] #{msg}\n"
|
|
187
|
+
else "[•] #{msg}\n"
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Sinatra Applications
|
|
196
|
+
|
|
197
|
+
**Features:**
|
|
198
|
+
- Sidekiq background jobs
|
|
199
|
+
- Session-based robot identification
|
|
200
|
+
- Thread-safe request handling
|
|
201
|
+
- RESTful API integration
|
|
202
|
+
|
|
203
|
+
**Setup:**
|
|
204
|
+
```ruby
|
|
205
|
+
# Gemfile
|
|
206
|
+
gem 'sinatra'
|
|
207
|
+
gem 'sidekiq'
|
|
208
|
+
gem 'redis'
|
|
209
|
+
gem 'htm'
|
|
210
|
+
|
|
211
|
+
# app.rb
|
|
212
|
+
require 'htm/sinatra'
|
|
213
|
+
|
|
214
|
+
class MyApp < Sinatra::Base
|
|
215
|
+
register_htm # Auto-configures HTM
|
|
216
|
+
|
|
217
|
+
enable :sessions
|
|
218
|
+
|
|
219
|
+
before do
|
|
220
|
+
robot_name = session[:user_id] || 'guest'
|
|
221
|
+
init_htm(robot_name: "user_#{robot_name}")
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Deployment:**
|
|
227
|
+
```bash
|
|
228
|
+
# Start Redis
|
|
229
|
+
redis-server
|
|
230
|
+
|
|
231
|
+
# Start Sidekiq worker
|
|
232
|
+
bundle exec sidekiq -r ./app.rb
|
|
233
|
+
|
|
234
|
+
# Start web server
|
|
235
|
+
bundle exec ruby app.rb
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Rails Applications
|
|
241
|
+
|
|
242
|
+
**Features:**
|
|
243
|
+
- Automatic configuration via Railtie
|
|
244
|
+
- ActiveJob integration
|
|
245
|
+
- Rails logger integration
|
|
246
|
+
- Rake tasks loaded automatically
|
|
247
|
+
- Test environment auto-configured
|
|
248
|
+
|
|
249
|
+
**Setup:**
|
|
250
|
+
```ruby
|
|
251
|
+
# Gemfile
|
|
252
|
+
gem 'htm'
|
|
253
|
+
|
|
254
|
+
# config/initializers/htm.rb (optional)
|
|
255
|
+
HTM.configure do |config|
|
|
256
|
+
config.embedding_model = 'nomic-embed-text'
|
|
257
|
+
config.tag_model = 'llama3'
|
|
258
|
+
end
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Usage in Controllers:**
|
|
262
|
+
```ruby
|
|
263
|
+
class MemoriesController < ApplicationController
|
|
264
|
+
def create
|
|
265
|
+
htm = HTM.new(robot_name: "user_#{current_user.id}")
|
|
266
|
+
node_id = htm.remember(params[:content])
|
|
267
|
+
|
|
268
|
+
# Job enqueued via ActiveJob
|
|
269
|
+
# Returns immediately
|
|
270
|
+
|
|
271
|
+
render json: { node_id: node_id }
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Testing:**
|
|
277
|
+
```ruby
|
|
278
|
+
# test/test_helper.rb or spec/rails_helper.rb
|
|
279
|
+
|
|
280
|
+
# Jobs run synchronously in tests (auto-configured)
|
|
281
|
+
RSpec.describe MemoriesController do
|
|
282
|
+
it "creates memory" do
|
|
283
|
+
post :create, params: { content: "Test memory" }
|
|
284
|
+
|
|
285
|
+
# Embedding and tags already generated (inline in tests)
|
|
286
|
+
node = HTM::Models::Node.last
|
|
287
|
+
expect(node.embedding).to be_present
|
|
288
|
+
expect(node.tags).not_to be_empty
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Thread Safety
|
|
296
|
+
|
|
297
|
+
HTM is thread-safe for concurrent web requests:
|
|
298
|
+
|
|
299
|
+
✅ **Thread-Safe Components:**
|
|
300
|
+
- `HTM::WorkingMemory` - Per-instance state
|
|
301
|
+
- `HTM::LongTermMemory` - Connection pooling
|
|
302
|
+
- Database operations - PostgreSQL ACID compliance
|
|
303
|
+
- Job enqueueing - Atomic operations
|
|
304
|
+
|
|
305
|
+
⚠️ **Considerations:**
|
|
306
|
+
- Each HTM instance is independent
|
|
307
|
+
- Connection pool sized appropriately (`db_pool_size`)
|
|
308
|
+
- Concurrent node creation is safe
|
|
309
|
+
- Shared memory across robots (by design)
|
|
310
|
+
|
|
311
|
+
**Example: Concurrent Requests**
|
|
312
|
+
```ruby
|
|
313
|
+
# Sinatra/Rails - Multiple requests simultaneously
|
|
314
|
+
# Request 1:
|
|
315
|
+
htm1 = HTM.new(robot_name: "user_123")
|
|
316
|
+
htm1.remember("Message 1") # ✓ Thread-safe
|
|
317
|
+
|
|
318
|
+
# Request 2 (concurrent):
|
|
319
|
+
htm2 = HTM.new(robot_name: "user_456")
|
|
320
|
+
htm2.remember("Message 2") # ✓ Thread-safe
|
|
321
|
+
|
|
322
|
+
# Separate instances, no conflicts
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Database Connection Management
|
|
328
|
+
|
|
329
|
+
### CLI Applications
|
|
330
|
+
```ruby
|
|
331
|
+
# Single connection, simple usage
|
|
332
|
+
htm = HTM.new
|
|
333
|
+
# Connection established once
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Sinatra Applications
|
|
337
|
+
```ruby
|
|
338
|
+
# Connection pooling handled by middleware
|
|
339
|
+
class MyApp < Sinatra::Base
|
|
340
|
+
use HTM::Sinatra::Middleware # Manages connections
|
|
341
|
+
end
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Rails Applications
|
|
345
|
+
```ruby
|
|
346
|
+
# Rails manages connections automatically
|
|
347
|
+
# HTM shares Rails' connection pool
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Connection Pool Settings
|
|
351
|
+
```ruby
|
|
352
|
+
htm = HTM.new(
|
|
353
|
+
db_pool_size: 10, # Max connections
|
|
354
|
+
db_query_timeout: 30_000 # 30 seconds
|
|
355
|
+
)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Troubleshooting
|
|
361
|
+
|
|
362
|
+
### Jobs Not Running (Sinatra)
|
|
363
|
+
|
|
364
|
+
**Problem:** Memories created but no embeddings/tags
|
|
365
|
+
|
|
366
|
+
**Solution:**
|
|
367
|
+
```bash
|
|
368
|
+
# Check Sidekiq is running
|
|
369
|
+
ps aux | grep sidekiq
|
|
370
|
+
|
|
371
|
+
# Start Sidekiq worker
|
|
372
|
+
bundle exec sidekiq -r ./app.rb -q htm
|
|
373
|
+
|
|
374
|
+
# Check Redis
|
|
375
|
+
redis-cli ping
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Jobs Not Running (Rails)
|
|
379
|
+
|
|
380
|
+
**Problem:** Background jobs not processing
|
|
381
|
+
|
|
382
|
+
**Solution:**
|
|
383
|
+
```bash
|
|
384
|
+
# Check ActiveJob backend configured
|
|
385
|
+
# config/application.rb
|
|
386
|
+
config.active_job.queue_adapter = :sidekiq
|
|
387
|
+
|
|
388
|
+
# Start Sidekiq
|
|
389
|
+
bundle exec sidekiq
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Slow CLI Performance
|
|
393
|
+
|
|
394
|
+
**Problem:** CLI operations take too long
|
|
395
|
+
|
|
396
|
+
**Solution:**
|
|
397
|
+
```ruby
|
|
398
|
+
# Use faster/smaller models
|
|
399
|
+
HTM.configure do |config|
|
|
400
|
+
config.embedding_model = 'all-minilm' # Smaller, faster
|
|
401
|
+
config.tag_model = 'gemma2:2b' # Smaller model
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Or disable features
|
|
405
|
+
HTM.configure do |config|
|
|
406
|
+
config.tag_extractor = ->(_text, _ontology) { [] } # Skip tags
|
|
407
|
+
end
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Thread Safety Issues
|
|
411
|
+
|
|
412
|
+
**Problem:** Concurrent request errors
|
|
413
|
+
|
|
414
|
+
**Solution:**
|
|
415
|
+
```ruby
|
|
416
|
+
# Increase connection pool
|
|
417
|
+
htm = HTM.new(db_pool_size: 20)
|
|
418
|
+
|
|
419
|
+
# Check for shared state (anti-pattern)
|
|
420
|
+
# DON'T:
|
|
421
|
+
$htm = HTM.new # Global shared instance
|
|
422
|
+
|
|
423
|
+
# DO:
|
|
424
|
+
def htm
|
|
425
|
+
@htm ||= HTM.new(robot_name: current_user.id)
|
|
426
|
+
end
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Migration Guide
|
|
432
|
+
|
|
433
|
+
### Existing CLI Apps
|
|
434
|
+
|
|
435
|
+
```ruby
|
|
436
|
+
# Before (blocking):
|
|
437
|
+
# Jobs run in threads (may not complete)
|
|
438
|
+
|
|
439
|
+
# After (explicit inline):
|
|
440
|
+
HTM.configure do |config|
|
|
441
|
+
config.job_backend = :inline
|
|
442
|
+
end
|
|
443
|
+
# Jobs run synchronously, guaranteed to complete
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Existing Sinatra Apps
|
|
447
|
+
|
|
448
|
+
```ruby
|
|
449
|
+
# Before:
|
|
450
|
+
require 'htm'
|
|
451
|
+
# Threads used (not production-ready)
|
|
452
|
+
|
|
453
|
+
# After:
|
|
454
|
+
require 'htm/sinatra'
|
|
455
|
+
register_htm # Auto-configures Sidekiq
|
|
456
|
+
# Production-ready background jobs
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Existing Rails Apps
|
|
460
|
+
|
|
461
|
+
```ruby
|
|
462
|
+
# Before:
|
|
463
|
+
# Manual configuration required
|
|
464
|
+
|
|
465
|
+
# After:
|
|
466
|
+
# Just add gem 'htm' - auto-configures via Railtie
|
|
467
|
+
# Uses ActiveJob automatically
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Best Practices
|
|
473
|
+
|
|
474
|
+
### CLI Applications
|
|
475
|
+
1. Use `:inline` backend for predictability
|
|
476
|
+
2. Add progress indicators for user feedback
|
|
477
|
+
3. Handle Ollama connection errors gracefully
|
|
478
|
+
4. Consider caching for repeated queries
|
|
479
|
+
|
|
480
|
+
### Sinatra Applications
|
|
481
|
+
1. Use `register_htm` for auto-configuration
|
|
482
|
+
2. Always use sessions for robot identification
|
|
483
|
+
3. Run Sidekiq workers in production
|
|
484
|
+
4. Monitor Redis memory usage
|
|
485
|
+
|
|
486
|
+
### Rails Applications
|
|
487
|
+
1. Create initializer for custom configuration
|
|
488
|
+
2. Use per-user robot names
|
|
489
|
+
3. Let Rails manage database connections
|
|
490
|
+
4. Use ActiveJob for all background processing
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Examples
|
|
495
|
+
|
|
496
|
+
See working examples in the repository:
|
|
497
|
+
|
|
498
|
+
- **CLI:** [`examples/cli_app/htm_cli.rb`](https://github.com/madbomber/htm/blob/main/examples/cli_app/htm_cli.rb)
|
|
499
|
+
- **Sinatra:** [`examples/sinatra_app/app.rb`](https://github.com/madbomber/htm/blob/main/examples/sinatra_app/app.rb)
|
|
500
|
+
- **Rails:** `examples/rails_app/` (full Rails 7 app)
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Summary
|
|
505
|
+
|
|
506
|
+
| Feature | CLI | Sinatra | Rails |
|
|
507
|
+
|---------|-----|---------|-------|
|
|
508
|
+
| Job Backend | inline | sidekiq | active_job |
|
|
509
|
+
| Setup Complexity | Low | Medium | Low (auto) |
|
|
510
|
+
| Infrastructure | Database only | +Redis | +Rails |
|
|
511
|
+
| Response Time | Slow (1-3s) | Fast (15ms) | Fast (15ms) |
|
|
512
|
+
| Production Ready | ✓ (small scale) | ✓ | ✓ |
|
|
513
|
+
| Background Jobs | No | Yes | Yes |
|
|
514
|
+
| Auto-Configuration | Manual | `register_htm` | Railtie |
|
|
515
|
+
|
|
516
|
+
**Recommendation:**
|
|
517
|
+
- CLI tools → Use `:inline` backend
|
|
518
|
+
- Sinatra apps → Use `:sidekiq` backend
|
|
519
|
+
- Rails apps → Use `:active_job` backend (default)
|