htm 0.0.1 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.aigcm_msg +1 -0
- data/.architecture/reviews/comprehensive-codebase-review.md +577 -0
- data/.claude/settings.local.json +92 -0
- data/.envrc +1 -0
- data/.irbrc +283 -80
- data/.tbls.yml +31 -0
- data/CHANGELOG.md +314 -16
- data/CLAUDE.md +603 -0
- data/README.md +76 -5
- data/Rakefile +5 -0
- data/SETUP.md +132 -101
- data/db/migrate/{20250101000001_enable_extensions.rb → 00001_enable_extensions.rb} +0 -1
- data/db/migrate/00002_create_robots.rb +11 -0
- data/db/migrate/00003_create_file_sources.rb +20 -0
- data/db/migrate/00004_create_nodes.rb +65 -0
- data/db/migrate/00005_create_tags.rb +13 -0
- data/db/migrate/00006_create_node_tags.rb +18 -0
- data/db/migrate/00007_create_robot_nodes.rb +26 -0
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +12 -0
- data/db/schema.sql +390 -36
- data/docs/api/database.md +19 -232
- data/docs/api/embedding-service.md +1 -7
- data/docs/api/htm.md +305 -364
- data/docs/api/index.md +1 -7
- data/docs/api/long-term-memory.md +342 -590
- data/docs/api/yard/HTM/ActiveRecordConfig.md +23 -0
- data/docs/api/yard/HTM/AuthorizationError.md +11 -0
- data/docs/api/yard/HTM/CircuitBreaker.md +92 -0
- data/docs/api/yard/HTM/CircuitBreakerOpenError.md +34 -0
- data/docs/api/yard/HTM/Configuration.md +175 -0
- data/docs/api/yard/HTM/Database.md +99 -0
- data/docs/api/yard/HTM/DatabaseError.md +14 -0
- data/docs/api/yard/HTM/EmbeddingError.md +18 -0
- data/docs/api/yard/HTM/EmbeddingService.md +58 -0
- data/docs/api/yard/HTM/Error.md +11 -0
- data/docs/api/yard/HTM/JobAdapter.md +39 -0
- data/docs/api/yard/HTM/LongTermMemory.md +342 -0
- data/docs/api/yard/HTM/NotFoundError.md +17 -0
- data/docs/api/yard/HTM/Observability.md +107 -0
- data/docs/api/yard/HTM/QueryTimeoutError.md +19 -0
- data/docs/api/yard/HTM/Railtie.md +27 -0
- data/docs/api/yard/HTM/ResourceExhaustedError.md +13 -0
- data/docs/api/yard/HTM/TagError.md +18 -0
- data/docs/api/yard/HTM/TagService.md +67 -0
- data/docs/api/yard/HTM/Timeframe/Result.md +24 -0
- data/docs/api/yard/HTM/Timeframe.md +40 -0
- data/docs/api/yard/HTM/TimeframeExtractor/Result.md +24 -0
- data/docs/api/yard/HTM/TimeframeExtractor.md +45 -0
- data/docs/api/yard/HTM/ValidationError.md +20 -0
- data/docs/api/yard/HTM/WorkingMemory.md +131 -0
- data/docs/api/yard/HTM.md +80 -0
- data/docs/api/yard/index.csv +179 -0
- data/docs/api/yard-reference.md +51 -0
- data/docs/architecture/adrs/001-postgresql-timescaledb.md +1 -1
- data/docs/architecture/adrs/003-ollama-embeddings.md +1 -1
- data/docs/architecture/adrs/010-redis-working-memory-rejected.md +2 -27
- data/docs/architecture/adrs/index.md +2 -13
- data/docs/architecture/hive-mind.md +165 -166
- data/docs/architecture/index.md +2 -2
- data/docs/architecture/overview.md +5 -171
- data/docs/architecture/two-tier-memory.md +1 -35
- data/docs/assets/images/adr-010-current-architecture.svg +37 -0
- data/docs/assets/images/adr-010-proposed-architecture.svg +48 -0
- data/docs/assets/images/adr-dependency-tree.svg +93 -0
- data/docs/assets/images/class-hierarchy.svg +55 -0
- data/docs/assets/images/exception-hierarchy.svg +45 -0
- data/docs/assets/images/htm-architecture-overview.svg +83 -0
- data/docs/assets/images/htm-complete-memory-flow.svg +160 -0
- data/docs/assets/images/htm-context-assembly-flow.svg +148 -0
- data/docs/assets/images/htm-eviction-process.svg +141 -0
- data/docs/assets/images/htm-memory-addition-flow.svg +138 -0
- data/docs/assets/images/htm-memory-recall-flow.svg +152 -0
- data/docs/assets/images/htm-node-states.svg +123 -0
- data/docs/assets/images/project-structure.svg +78 -0
- data/docs/assets/images/test-directory-structure.svg +38 -0
- data/{dbdoc → docs/database}/README.md +127 -125
- data/docs/database/public.file_sources.md +42 -0
- data/docs/database/public.file_sources.svg +211 -0
- data/{dbdoc → docs/database}/public.node_tags.md +7 -8
- data/docs/database/public.node_tags.svg +239 -0
- data/{dbdoc → docs/database}/public.nodes.md +22 -17
- data/docs/database/public.nodes.svg +271 -0
- data/docs/database/public.robot_nodes.md +46 -0
- data/docs/database/public.robot_nodes.svg +243 -0
- data/{dbdoc → docs/database}/public.robots.md +2 -3
- data/docs/database/public.robots.svg +161 -0
- data/docs/database/public.tags.svg +139 -0
- data/{dbdoc → docs/database}/schema.json +941 -630
- data/docs/database/schema.svg +282 -0
- data/docs/development/index.md +1 -29
- data/docs/development/schema.md +134 -309
- data/docs/development/testing.md +1 -9
- data/docs/getting-started/index.md +47 -0
- data/docs/{installation.md → getting-started/installation.md} +2 -2
- data/docs/{quick-start.md → getting-started/quick-start.md} +5 -5
- data/docs/guides/adding-memories.md +295 -643
- data/docs/guides/recalling-memories.md +36 -1
- data/docs/guides/search-strategies.md +85 -51
- data/docs/images/htm-er-diagram.svg +156 -0
- data/docs/index.md +16 -31
- data/docs/multi_framework_support.md +4 -4
- data/examples/README.md +280 -0
- data/examples/basic_usage.rb +18 -16
- data/examples/cli_app/htm_cli.rb +146 -8
- data/examples/cli_app/temp.log +93 -0
- data/examples/custom_llm_configuration.rb +1 -2
- data/examples/example_app/app.rb +11 -14
- data/examples/file_loader_usage.rb +177 -0
- data/examples/robot_groups/lib/robot_group.rb +419 -0
- data/examples/robot_groups/lib/working_memory_channel.rb +140 -0
- data/examples/robot_groups/multi_process.rb +286 -0
- data/examples/robot_groups/robot_worker.rb +136 -0
- data/examples/robot_groups/same_process.rb +229 -0
- data/examples/sinatra_app/Gemfile +1 -0
- data/examples/sinatra_app/Gemfile.lock +166 -0
- data/examples/sinatra_app/app.rb +219 -24
- data/examples/timeframe_demo.rb +276 -0
- data/lib/htm/active_record_config.rb +10 -3
- data/lib/htm/circuit_breaker.rb +202 -0
- data/lib/htm/configuration.rb +313 -80
- data/lib/htm/database.rb +67 -36
- data/lib/htm/embedding_service.rb +39 -2
- data/lib/htm/errors.rb +131 -11
- data/lib/htm/{sinatra.rb → integrations/sinatra.rb} +87 -12
- data/lib/htm/job_adapter.rb +10 -3
- data/lib/htm/jobs/generate_embedding_job.rb +5 -4
- data/lib/htm/jobs/generate_tags_job.rb +4 -0
- data/lib/htm/loaders/markdown_loader.rb +263 -0
- data/lib/htm/loaders/paragraph_chunker.rb +112 -0
- data/lib/htm/long_term_memory.rb +601 -321
- data/lib/htm/models/file_source.rb +99 -0
- data/lib/htm/models/node.rb +116 -12
- data/lib/htm/models/robot.rb +53 -4
- data/lib/htm/models/robot_node.rb +51 -0
- data/lib/htm/models/tag.rb +302 -0
- data/lib/htm/observability.rb +395 -0
- data/lib/htm/tag_service.rb +60 -3
- data/lib/htm/tasks.rb +29 -0
- data/lib/htm/timeframe.rb +194 -0
- data/lib/htm/timeframe_extractor.rb +307 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory.rb +165 -70
- data/lib/htm.rb +352 -133
- data/lib/tasks/doc.rake +300 -0
- data/lib/tasks/files.rake +299 -0
- data/lib/tasks/htm.rake +188 -2
- data/lib/tasks/jobs.rake +10 -12
- data/lib/tasks/tags.rake +194 -0
- data/mkdocs.yml +91 -9
- data/notes/ARCHITECTURE_REVIEW.md +1167 -0
- data/notes/IMPLEMENTATION_SUMMARY.md +606 -0
- data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +451 -0
- data/notes/next_steps.md +100 -0
- data/notes/plan.md +627 -0
- data/notes/tag_ontology_enhancement_ideas.md +222 -0
- data/notes/timescaledb_removal_summary.md +200 -0
- metadata +177 -37
- data/db/migrate/20250101000002_create_robots.rb +0 -14
- data/db/migrate/20250101000003_create_nodes.rb +0 -42
- data/db/migrate/20250101000005_create_tags.rb +0 -38
- data/db/migrate/20250101000007_add_node_vector_indexes.rb +0 -30
- data/dbdoc/public.node_tags.svg +0 -112
- data/dbdoc/public.nodes.svg +0 -118
- data/dbdoc/public.robots.svg +0 -90
- data/dbdoc/public.tags.svg +0 -60
- data/dbdoc/schema.svg +0 -154
- data/{dbdoc → docs/database}/public.node_stats.md +0 -0
- data/{dbdoc → docs/database}/public.node_stats.svg +0 -0
- data/{dbdoc → docs/database}/public.nodes_tags.md +0 -0
- data/{dbdoc → docs/database}/public.nodes_tags.svg +0 -0
- data/{dbdoc → docs/database}/public.ontology_structure.md +0 -0
- data/{dbdoc → docs/database}/public.ontology_structure.svg +0 -0
- data/{dbdoc → docs/database}/public.operations_log.md +0 -0
- data/{dbdoc → docs/database}/public.operations_log.svg +0 -0
- data/{dbdoc → docs/database}/public.relationships.md +0 -0
- data/{dbdoc → docs/database}/public.relationships.svg +0 -0
- data/{dbdoc → docs/database}/public.robot_activity.md +0 -0
- data/{dbdoc → docs/database}/public.robot_activity.svg +0 -0
- data/{dbdoc → docs/database}/public.schema_migrations.md +0 -0
- data/{dbdoc → docs/database}/public.schema_migrations.svg +0 -0
- data/{dbdoc → docs/database}/public.tags.md +3 -3
- /data/{dbdoc → docs/database}/public.topic_relationships.md +0 -0
- /data/{dbdoc → docs/database}/public.topic_relationships.svg +0 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
# HTM Implementation Summary
|
|
2
|
+
## Logger, Rake Tasks, and Architecture Improvements
|
|
3
|
+
|
|
4
|
+
**Date**: 2025-10-29
|
|
5
|
+
**Focus**: Logger dependency injection, async job management, and ActiveRecord consistency
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This implementation addressed key architecture review recommendations:
|
|
12
|
+
|
|
13
|
+
1. ✅ **Logger Dependency Injection** - Configurable logging with sensible defaults
|
|
14
|
+
2. ✅ **Rake Tasks for Job Management** - 7 new tasks for async job monitoring and processing
|
|
15
|
+
3. ✅ **Consistent Logger Usage** - All components use `HTM.logger`
|
|
16
|
+
4. ✅ **Token Counter Configuration** - Configurable token counting
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Logger Dependency Injection
|
|
21
|
+
|
|
22
|
+
### Implementation
|
|
23
|
+
|
|
24
|
+
**File**: `lib/htm/configuration.rb`
|
|
25
|
+
|
|
26
|
+
Added logger configuration to `HTM::Configuration`:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
HTM.configure do |config|
|
|
30
|
+
config.logger = Rails.logger # Custom logger
|
|
31
|
+
# Or use default (STDOUT with INFO level)
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Default Logger**:
|
|
36
|
+
- Output: `STDOUT`
|
|
37
|
+
- Level: Configurable via `ENV['HTM_LOG_LEVEL']` (default: `INFO`)
|
|
38
|
+
- Format: `[YYYY-MM-DD HH:MM:SS] LEVEL -- HTM: message`
|
|
39
|
+
|
|
40
|
+
**Access**:
|
|
41
|
+
```ruby
|
|
42
|
+
HTM.logger.info "Message"
|
|
43
|
+
HTM.logger.warn "Warning"
|
|
44
|
+
HTM.logger.error "Error"
|
|
45
|
+
HTM.logger.debug "Debug info"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Updated Components
|
|
49
|
+
|
|
50
|
+
**Job Classes**:
|
|
51
|
+
- `lib/htm/jobs/generate_embedding_job.rb` - Uses `HTM.logger`
|
|
52
|
+
- `lib/htm/jobs/generate_tags_job.rb` - Uses `HTM.logger`
|
|
53
|
+
|
|
54
|
+
**HTM Main Class**:
|
|
55
|
+
- `lib/htm.rb` - Logs node creation, job enqueueing
|
|
56
|
+
|
|
57
|
+
**Logging Levels**:
|
|
58
|
+
- `DEBUG`: Job start/completion, job enqueueing, node skipping
|
|
59
|
+
- `INFO`: Successful operations (node created, embedding generated, tags extracted)
|
|
60
|
+
- `WARN`: Recoverable issues (node not found, no tags extracted)
|
|
61
|
+
- `ERROR`: Failures (embedding generation failed, tag extraction failed)
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 2. Rake Tasks for Async Job Management
|
|
66
|
+
|
|
67
|
+
### Implementation
|
|
68
|
+
|
|
69
|
+
**File**: `lib/tasks/jobs.rake`
|
|
70
|
+
|
|
71
|
+
Created 7 new rake tasks for managing async jobs:
|
|
72
|
+
|
|
73
|
+
### Task: `htm:jobs:stats`
|
|
74
|
+
|
|
75
|
+
Show statistics for nodes and async job processing.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
rake htm:jobs:stats
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Output**:
|
|
82
|
+
```
|
|
83
|
+
HTM Async Job Statistics
|
|
84
|
+
============================================================
|
|
85
|
+
Total nodes: 1250
|
|
86
|
+
Nodes with embeddings: 1200 (96.0%)
|
|
87
|
+
Nodes without embeddings: 50 (4.0%)
|
|
88
|
+
Nodes with tags: 1180 (94.4%)
|
|
89
|
+
Nodes without tags: 70 (5.6%)
|
|
90
|
+
|
|
91
|
+
Total tags in ontology: 342
|
|
92
|
+
Average tags per node: 2.8
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Task: `htm:jobs:process_embeddings`
|
|
96
|
+
|
|
97
|
+
Process all pending embedding jobs synchronously.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
rake htm:jobs:process_embeddings
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Behavior**:
|
|
104
|
+
- Finds all nodes without embeddings
|
|
105
|
+
- Generates embeddings using configured generator
|
|
106
|
+
- Processes sequentially with progress output
|
|
107
|
+
- Reports success/failure counts
|
|
108
|
+
|
|
109
|
+
### Task: `htm:jobs:process_tags`
|
|
110
|
+
|
|
111
|
+
Process all pending tag extraction jobs synchronously.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
rake htm:jobs:process_tags
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Behavior**:
|
|
118
|
+
- Finds all nodes without tags
|
|
119
|
+
- Extracts tags using configured extractor
|
|
120
|
+
- Processes sequentially with progress output
|
|
121
|
+
- Reports success/failure counts
|
|
122
|
+
|
|
123
|
+
### Task: `htm:jobs:process_all`
|
|
124
|
+
|
|
125
|
+
Process both embeddings and tags in sequence.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
rake htm:jobs:process_all
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Task: `htm:jobs:reprocess_embeddings`
|
|
132
|
+
|
|
133
|
+
Force regenerate embeddings for ALL nodes.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
rake htm:jobs:reprocess_embeddings
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Behavior**:
|
|
140
|
+
- Prompts for confirmation (`yes` required)
|
|
141
|
+
- Clears all existing embeddings
|
|
142
|
+
- Regenerates embeddings for every node
|
|
143
|
+
- Useful for model upgrades or testing
|
|
144
|
+
|
|
145
|
+
### Task: `htm:jobs:failed`
|
|
146
|
+
|
|
147
|
+
Show nodes that may have failed async processing.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
rake htm:jobs:failed
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Output**:
|
|
154
|
+
```
|
|
155
|
+
Nodes with Processing Issues
|
|
156
|
+
============================================================
|
|
157
|
+
|
|
158
|
+
Nodes without embeddings (>1 hour old):
|
|
159
|
+
Node 1234: created 2 hours ago
|
|
160
|
+
Node 1235: created 3 hours ago
|
|
161
|
+
... and 8 more
|
|
162
|
+
|
|
163
|
+
Nodes without tags (>1 hour old):
|
|
164
|
+
Node 1240: created 1 hour ago
|
|
165
|
+
... and 5 more
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Task: `htm:jobs:clear_all`
|
|
169
|
+
|
|
170
|
+
Clear all embeddings and tags (for testing/development).
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
rake htm:jobs:clear_all
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Behavior**:
|
|
177
|
+
- Prompts for confirmation (`yes` required)
|
|
178
|
+
- Clears all embeddings and dimensions
|
|
179
|
+
- Deletes all tags and associations
|
|
180
|
+
- **Destructive** - use only in development
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 3. Token Counter Configuration
|
|
185
|
+
|
|
186
|
+
### Implementation
|
|
187
|
+
|
|
188
|
+
Added token counting to `HTM::Configuration`:
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
HTM.configure do |config|
|
|
192
|
+
config.token_counter = ->(text) {
|
|
193
|
+
MyApp::Tokenizer.count(text)
|
|
194
|
+
}
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Default Implementation**:
|
|
199
|
+
- Uses Tiktoken with GPT-3.5-turbo encoding
|
|
200
|
+
- Lazy-loads Tiktoken only when needed
|
|
201
|
+
- Returns integer token count
|
|
202
|
+
|
|
203
|
+
**Usage**:
|
|
204
|
+
```ruby
|
|
205
|
+
token_count = HTM.count_tokens("Some text content")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Updated**:
|
|
209
|
+
- `lib/htm.rb` - Now uses `HTM.count_tokens(content)` instead of instance variable
|
|
210
|
+
- Removed direct Tiktoken dependency from HTM class
|
|
211
|
+
- Consistent with other configurable dependencies
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 4. Configuration Validation
|
|
216
|
+
|
|
217
|
+
### Enhanced Validation
|
|
218
|
+
|
|
219
|
+
**File**: `lib/htm/configuration.rb`
|
|
220
|
+
|
|
221
|
+
Added comprehensive validation for all configured callables:
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
def validate!
|
|
225
|
+
unless @embedding_generator.respond_to?(:call)
|
|
226
|
+
raise HTM::ValidationError, "embedding_generator must be callable"
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
unless @tag_extractor.respond_to?(:call)
|
|
230
|
+
raise HTM::ValidationError, "tag_extractor must be callable"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
unless @token_counter.respond_to?(:call)
|
|
234
|
+
raise HTM::ValidationError, "token_counter must be callable"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
unless @logger.respond_to?(:info) && @logger.respond_to?(:warn) && @logger.respond_to?(:error)
|
|
238
|
+
raise HTM::ValidationError, "logger must respond to :info, :warn, and :error"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Validation Occurs**:
|
|
244
|
+
- During `HTM.configure` (raises error immediately)
|
|
245
|
+
- Clear error messages for misconfiguration
|
|
246
|
+
- Prevents runtime failures
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 5. Updated Task Loader
|
|
251
|
+
|
|
252
|
+
### Implementation
|
|
253
|
+
|
|
254
|
+
**File**: `lib/htm/tasks.rb`
|
|
255
|
+
|
|
256
|
+
Updated to load both database and job management tasks:
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
if defined?(Rake)
|
|
260
|
+
load File.expand_path('../tasks/htm.rake', __dir__)
|
|
261
|
+
load File.expand_path('../tasks/jobs.rake', __dir__)
|
|
262
|
+
end
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Documentation**:
|
|
266
|
+
- Lists all 9 database tasks
|
|
267
|
+
- Lists all 7 job management tasks
|
|
268
|
+
- Clear descriptions for each task
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Usage Examples
|
|
273
|
+
|
|
274
|
+
### Example 1: Custom Logger
|
|
275
|
+
|
|
276
|
+
```ruby
|
|
277
|
+
# config/initializers/htm.rb
|
|
278
|
+
require 'htm'
|
|
279
|
+
|
|
280
|
+
HTM.configure do |config|
|
|
281
|
+
# Use Rails logger
|
|
282
|
+
config.logger = Rails.logger
|
|
283
|
+
|
|
284
|
+
# Configure other settings
|
|
285
|
+
config.embedding_model = 'nomic-embed-text'
|
|
286
|
+
config.tag_model = 'llama3'
|
|
287
|
+
end
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Example 2: Monitor Async Jobs
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Check job statistics
|
|
294
|
+
rake htm:jobs:stats
|
|
295
|
+
|
|
296
|
+
# If nodes are stuck without embeddings
|
|
297
|
+
rake htm:jobs:process_embeddings
|
|
298
|
+
|
|
299
|
+
# If nodes are stuck without tags
|
|
300
|
+
rake htm:jobs:process_tags
|
|
301
|
+
|
|
302
|
+
# Check for failures
|
|
303
|
+
rake htm:jobs:failed
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Example 3: Development Workflow
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# Clear all enrichments for testing
|
|
310
|
+
rake htm:jobs:clear_all
|
|
311
|
+
|
|
312
|
+
# Add test data
|
|
313
|
+
# (your application code creates nodes)
|
|
314
|
+
|
|
315
|
+
# Process jobs synchronously
|
|
316
|
+
rake htm:jobs:process_all
|
|
317
|
+
|
|
318
|
+
# Verify results
|
|
319
|
+
rake htm:jobs:stats
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Example 4: Production Monitoring
|
|
323
|
+
|
|
324
|
+
```ruby
|
|
325
|
+
# In your monitoring/alerting system
|
|
326
|
+
def check_htm_health
|
|
327
|
+
nodes_without_embeddings = HTM::Models::Node
|
|
328
|
+
.where(embedding: nil)
|
|
329
|
+
.where('created_at < ?', 1.hour.ago)
|
|
330
|
+
.count
|
|
331
|
+
|
|
332
|
+
if nodes_without_embeddings > 100
|
|
333
|
+
alert("HTM: #{nodes_without_embeddings} nodes stuck without embeddings")
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Architecture Benefits
|
|
341
|
+
|
|
342
|
+
### 1. Observability ✅
|
|
343
|
+
|
|
344
|
+
**Before**:
|
|
345
|
+
- No way to monitor async job health
|
|
346
|
+
- Failures logged to STDOUT/STDERR inconsistently
|
|
347
|
+
- No statistics or metrics
|
|
348
|
+
|
|
349
|
+
**After**:
|
|
350
|
+
- Centralized logging through `HTM.logger`
|
|
351
|
+
- `rake htm:jobs:stats` provides instant overview
|
|
352
|
+
- `rake htm:jobs:failed` identifies stuck jobs
|
|
353
|
+
- Configurable log levels for debugging
|
|
354
|
+
|
|
355
|
+
### 2. Operability ✅
|
|
356
|
+
|
|
357
|
+
**Before**:
|
|
358
|
+
- Manual database queries to find stuck nodes
|
|
359
|
+
- No way to reprocess failed jobs
|
|
360
|
+
- Testing required database inspection
|
|
361
|
+
|
|
362
|
+
**After**:
|
|
363
|
+
- `rake htm:jobs:process_*` tasks for reprocessing
|
|
364
|
+
- `rake htm:jobs:clear_all` for testing
|
|
365
|
+
- `rake htm:jobs:reprocess_embeddings` for model upgrades
|
|
366
|
+
- Safe confirmations for destructive operations
|
|
367
|
+
|
|
368
|
+
### 3. Flexibility ✅
|
|
369
|
+
|
|
370
|
+
**Before**:
|
|
371
|
+
- Hardcoded logging to STDOUT
|
|
372
|
+
- Fixed token counting with Tiktoken
|
|
373
|
+
- No control over log format or level
|
|
374
|
+
|
|
375
|
+
**After**:
|
|
376
|
+
- Configurable logger (Rails.logger, custom logger, etc.)
|
|
377
|
+
- Configurable token counter (any tokenization strategy)
|
|
378
|
+
- Environment-based log level (`HTM_LOG_LEVEL`)
|
|
379
|
+
- Custom log formatting possible
|
|
380
|
+
|
|
381
|
+
### 4. Production Readiness ✅
|
|
382
|
+
|
|
383
|
+
**Before**:
|
|
384
|
+
- Difficult to diagnose production issues
|
|
385
|
+
- No tools for recovering from failures
|
|
386
|
+
- Manual intervention required
|
|
387
|
+
|
|
388
|
+
**After**:
|
|
389
|
+
- Comprehensive logging for debugging
|
|
390
|
+
- Rake tasks for operational tasks
|
|
391
|
+
- Health check queries available
|
|
392
|
+
- Recovery procedures documented
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Configuration Reference
|
|
397
|
+
|
|
398
|
+
### Complete Configuration Example
|
|
399
|
+
|
|
400
|
+
```ruby
|
|
401
|
+
HTM.configure do |config|
|
|
402
|
+
# LLM Configuration
|
|
403
|
+
config.embedding_generator = ->(text) { MyLLM.embed(text) }
|
|
404
|
+
config.tag_extractor = ->(text, ont) { MyLLM.extract_tags(text, ont) }
|
|
405
|
+
config.token_counter = ->(text) { MyTokenizer.count(text) }
|
|
406
|
+
|
|
407
|
+
# Logger Configuration
|
|
408
|
+
config.logger = Rails.logger # Or Logger.new($stdout)
|
|
409
|
+
|
|
410
|
+
# Provider Settings (for defaults)
|
|
411
|
+
config.embedding_provider = :ollama
|
|
412
|
+
config.embedding_model = 'nomic-embed-text'
|
|
413
|
+
config.tag_provider = :ollama
|
|
414
|
+
config.tag_model = 'llama3'
|
|
415
|
+
config.ollama_url = ENV['OLLAMA_URL'] || 'http://localhost:11434'
|
|
416
|
+
end
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Environment Variables
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
# Log level (DEBUG, INFO, WARN, ERROR)
|
|
423
|
+
export HTM_LOG_LEVEL=INFO
|
|
424
|
+
|
|
425
|
+
# Ollama URL for default providers
|
|
426
|
+
export OLLAMA_URL=http://localhost:11434
|
|
427
|
+
|
|
428
|
+
# Database connection (if not using default)
|
|
429
|
+
export HTM_DBURL=postgresql://user:pass@host:port/dbname
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## Testing
|
|
435
|
+
|
|
436
|
+
### Unit Testing Logger Configuration
|
|
437
|
+
|
|
438
|
+
```ruby
|
|
439
|
+
# test/htm/configuration_test.rb
|
|
440
|
+
class ConfigurationTest < Minitest::Test
|
|
441
|
+
def test_default_logger
|
|
442
|
+
config = HTM::Configuration.new
|
|
443
|
+
assert config.logger.respond_to?(:info)
|
|
444
|
+
assert config.logger.respond_to?(:warn)
|
|
445
|
+
assert config.logger.respond_to?(:error)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def test_custom_logger
|
|
449
|
+
custom_logger = Logger.new(StringIO.new)
|
|
450
|
+
HTM.configure { |c| c.logger = custom_logger }
|
|
451
|
+
assert_equal custom_logger, HTM.logger
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
def test_validates_logger
|
|
455
|
+
assert_raises(HTM::ValidationError) do
|
|
456
|
+
HTM.configure { |c| c.logger = "not a logger" }
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Integration Testing Rake Tasks
|
|
463
|
+
|
|
464
|
+
```ruby
|
|
465
|
+
# test/rake/jobs_test.rb
|
|
466
|
+
require 'rake'
|
|
467
|
+
|
|
468
|
+
class JobsRakeTest < Minitest::Test
|
|
469
|
+
def setup
|
|
470
|
+
Rake.application.rake_require('tasks/jobs')
|
|
471
|
+
Rake::Task.define_task(:environment)
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def test_stats_task_exists
|
|
475
|
+
assert Rake::Task.task_defined?('htm:jobs:stats')
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def test_process_embeddings_task_exists
|
|
479
|
+
assert Rake::Task.task_defined?('htm:jobs:process_embeddings')
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Migration Guide
|
|
487
|
+
|
|
488
|
+
### For Existing HTM Applications
|
|
489
|
+
|
|
490
|
+
**Step 1**: Update HTM gem
|
|
491
|
+
|
|
492
|
+
```ruby
|
|
493
|
+
# Gemfile
|
|
494
|
+
gem 'htm', '~> 0.4.0' # Or latest version
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Step 2**: Add configuration (optional - uses defaults)
|
|
498
|
+
|
|
499
|
+
```ruby
|
|
500
|
+
# config/initializers/htm.rb
|
|
501
|
+
HTM.configure do |config|
|
|
502
|
+
config.logger = Rails.logger if defined?(Rails)
|
|
503
|
+
end
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
**Step 3**: Require rake tasks (optional - for job management)
|
|
507
|
+
|
|
508
|
+
```ruby
|
|
509
|
+
# Rakefile
|
|
510
|
+
require 'htm/tasks'
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**Step 4**: Update any direct Tiktoken usage
|
|
514
|
+
|
|
515
|
+
```ruby
|
|
516
|
+
# Before
|
|
517
|
+
@tokenizer = Tiktoken.encoding_for_model("gpt-3.5-turbo")
|
|
518
|
+
count = @tokenizer.encode(text).length
|
|
519
|
+
|
|
520
|
+
# After
|
|
521
|
+
count = HTM.count_tokens(text)
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**Step 5**: Replace warn/debug_me with HTM.logger
|
|
525
|
+
|
|
526
|
+
```ruby
|
|
527
|
+
# Before
|
|
528
|
+
warn "Something happened"
|
|
529
|
+
debug_me "Debug info"
|
|
530
|
+
|
|
531
|
+
# After
|
|
532
|
+
HTM.logger.warn "Something happened"
|
|
533
|
+
HTM.logger.debug "Debug info"
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Next Steps
|
|
539
|
+
|
|
540
|
+
### Recommended Enhancements
|
|
541
|
+
|
|
542
|
+
1. **Add monitoring instrumentation**:
|
|
543
|
+
- Prometheus/StatsD metrics
|
|
544
|
+
- Track embedding/tag generation duration
|
|
545
|
+
- Monitor job failure rates
|
|
546
|
+
|
|
547
|
+
2. **Add retry logic with exponential backoff**:
|
|
548
|
+
- Retry failed embedding jobs 3 times
|
|
549
|
+
- Use exponential backoff (10s, 30s, 60s)
|
|
550
|
+
- Implement dead letter queue for permanent failures
|
|
551
|
+
|
|
552
|
+
3. **Add circuit breaker pattern**:
|
|
553
|
+
- Detect when LLM provider is down
|
|
554
|
+
- Stop job processing temporarily
|
|
555
|
+
- Auto-resume when provider recovers
|
|
556
|
+
|
|
557
|
+
4. **Refactor LongTermMemory**:
|
|
558
|
+
- Use ActiveRecord consistently (no raw SQL)
|
|
559
|
+
- Use Arel for complex queries
|
|
560
|
+
- Improve testability
|
|
561
|
+
|
|
562
|
+
5. **Add tag hierarchy columns**:
|
|
563
|
+
- `root_tag`, `parent_tag`, `depth`
|
|
564
|
+
- Enable efficient hierarchical queries
|
|
565
|
+
- Support tag canonicalization
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## Files Modified
|
|
570
|
+
|
|
571
|
+
### Created
|
|
572
|
+
|
|
573
|
+
1. `lib/tasks/jobs.rake` - 7 new rake tasks for job management
|
|
574
|
+
2. `IMPLEMENTATION_SUMMARY.md` - This document
|
|
575
|
+
|
|
576
|
+
### Modified
|
|
577
|
+
|
|
578
|
+
1. `lib/htm/configuration.rb` - Added logger and token_counter
|
|
579
|
+
2. `lib/htm/tasks.rb` - Load jobs.rake
|
|
580
|
+
3. `lib/htm.rb` - Use `HTM.count_tokens` and `HTM.logger`
|
|
581
|
+
4. `lib/htm/jobs/generate_embedding_job.rb` - Use `HTM.logger`
|
|
582
|
+
5. `lib/htm/jobs/generate_tags_job.rb` - Use `HTM.logger`
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Summary
|
|
587
|
+
|
|
588
|
+
This implementation successfully addresses 4 key architecture review recommendations:
|
|
589
|
+
|
|
590
|
+
✅ **Logger Dependency Injection** - Flexible, configurable logging
|
|
591
|
+
✅ **Rake Tasks** - Operational tools for job management
|
|
592
|
+
✅ **Consistent Logging** - All components use `HTM.logger`
|
|
593
|
+
✅ **Token Counter Configuration** - Flexible token counting
|
|
594
|
+
|
|
595
|
+
**Impact**:
|
|
596
|
+
- **Observability**: Can now monitor async job health
|
|
597
|
+
- **Operability**: Tools for managing and recovering jobs
|
|
598
|
+
- **Flexibility**: Applications control logging and tokenization
|
|
599
|
+
- **Production Ready**: Comprehensive logging and recovery procedures
|
|
600
|
+
|
|
601
|
+
**Lines of Code**:
|
|
602
|
+
- Added: ~350 lines
|
|
603
|
+
- Modified: ~50 lines
|
|
604
|
+
- Total effort: ~3 hours
|
|
605
|
+
|
|
606
|
+
**Next Priority**: Implement retry logic with exponential backoff and circuit breaker pattern (from architecture review Section 2.1).
|