htm 0.0.11 → 0.0.15
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/.dictate.toml +46 -0
- data/.envrc +2 -0
- data/CHANGELOG.md +85 -2
- data/README.md +348 -79
- data/Rakefile +14 -2
- data/bin/htm_mcp.rb +94 -0
- data/config/database.yml +20 -13
- data/db/migrate/00003_create_file_sources.rb +5 -0
- data/db/migrate/00004_create_nodes.rb +17 -0
- data/db/migrate/00005_create_tags.rb +7 -0
- data/db/migrate/00006_create_node_tags.rb +2 -0
- data/db/migrate/00007_create_robot_nodes.rb +7 -0
- data/db/schema.sql +69 -100
- data/docs/api/index.md +1 -1
- data/docs/api/yard/HTM/Configuration.md +54 -0
- data/docs/api/yard/HTM/Database.md +13 -10
- data/docs/api/yard/HTM/EmbeddingService.md +5 -1
- data/docs/api/yard/HTM/LongTermMemory.md +18 -277
- data/docs/api/yard/HTM/PropositionError.md +18 -0
- data/docs/api/yard/HTM/PropositionService.md +66 -0
- data/docs/api/yard/HTM/QueryCache.md +88 -0
- data/docs/api/yard/HTM/RobotGroup.md +481 -0
- data/docs/api/yard/HTM/SqlBuilder.md +108 -0
- data/docs/api/yard/HTM/TagService.md +4 -0
- data/docs/api/yard/HTM/Telemetry/NullInstrument.md +13 -0
- data/docs/api/yard/HTM/Telemetry/NullMeter.md +15 -0
- data/docs/api/yard/HTM/Telemetry.md +109 -0
- data/docs/api/yard/HTM/WorkingMemoryChannel.md +176 -0
- data/docs/api/yard/HTM.md +8 -22
- data/docs/api/yard/index.csv +102 -25
- data/docs/api/yard-reference.md +8 -0
- data/docs/architecture/index.md +1 -1
- data/docs/assets/images/multi-provider-failover.svg +51 -0
- data/docs/assets/images/robot-group-architecture.svg +65 -0
- data/docs/database/README.md +3 -3
- data/docs/database/public.file_sources.svg +29 -21
- data/docs/database/public.node_tags.md +2 -0
- data/docs/database/public.node_tags.svg +53 -41
- data/docs/database/public.nodes.md +2 -0
- data/docs/database/public.nodes.svg +52 -40
- data/docs/database/public.robot_nodes.md +2 -0
- data/docs/database/public.robot_nodes.svg +30 -22
- data/docs/database/public.robots.svg +16 -12
- data/docs/database/public.tags.md +3 -0
- data/docs/database/public.tags.svg +41 -33
- data/docs/database/schema.json +66 -0
- data/docs/database/schema.svg +60 -48
- data/docs/development/index.md +14 -1
- data/docs/development/rake-tasks.md +1068 -0
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/quick-start.md +144 -155
- data/docs/guides/adding-memories.md +2 -3
- data/docs/guides/context-assembly.md +185 -184
- data/docs/guides/getting-started.md +154 -148
- data/docs/guides/index.md +8 -1
- data/docs/guides/long-term-memory.md +60 -92
- data/docs/guides/mcp-server.md +617 -0
- data/docs/guides/multi-robot.md +249 -345
- data/docs/guides/recalling-memories.md +153 -163
- data/docs/guides/robot-groups.md +604 -0
- data/docs/guides/search-strategies.md +61 -58
- data/docs/guides/working-memory.md +103 -136
- data/docs/images/telemetry-architecture.svg +153 -0
- data/docs/index.md +30 -26
- data/docs/telemetry.md +391 -0
- data/examples/README.md +46 -1
- data/examples/cli_app/README.md +1 -1
- data/examples/cli_app/htm_cli.rb +1 -1
- data/examples/robot_groups/robot_worker.rb +1 -2
- data/examples/robot_groups/same_process.rb +1 -4
- data/examples/sinatra_app/app.rb +1 -1
- data/examples/telemetry/README.md +147 -0
- data/examples/telemetry/SETUP_README.md +169 -0
- data/examples/telemetry/demo.rb +498 -0
- data/examples/telemetry/grafana/dashboards/htm-metrics.json +457 -0
- data/lib/htm/configuration.rb +261 -70
- data/lib/htm/database.rb +46 -22
- data/lib/htm/embedding_service.rb +24 -14
- data/lib/htm/errors.rb +15 -1
- data/lib/htm/jobs/generate_embedding_job.rb +19 -0
- data/lib/htm/jobs/generate_propositions_job.rb +103 -0
- data/lib/htm/jobs/generate_tags_job.rb +24 -0
- data/lib/htm/loaders/markdown_chunker.rb +79 -0
- data/lib/htm/loaders/markdown_loader.rb +41 -15
- data/lib/htm/long_term_memory/fulltext_search.rb +138 -0
- data/lib/htm/long_term_memory/hybrid_search.rb +324 -0
- data/lib/htm/long_term_memory/node_operations.rb +209 -0
- data/lib/htm/long_term_memory/relevance_scorer.rb +355 -0
- data/lib/htm/long_term_memory/robot_operations.rb +34 -0
- data/lib/htm/long_term_memory/tag_operations.rb +428 -0
- data/lib/htm/long_term_memory/vector_search.rb +109 -0
- data/lib/htm/long_term_memory.rb +51 -1153
- data/lib/htm/models/node.rb +35 -2
- data/lib/htm/models/node_tag.rb +31 -0
- data/lib/htm/models/robot_node.rb +31 -0
- data/lib/htm/models/tag.rb +44 -0
- data/lib/htm/proposition_service.rb +169 -0
- data/lib/htm/query_cache.rb +214 -0
- data/lib/htm/robot_group.rb +721 -0
- data/lib/htm/sql_builder.rb +178 -0
- data/lib/htm/tag_service.rb +16 -6
- data/lib/htm/tasks.rb +8 -2
- data/lib/htm/telemetry.rb +224 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory_channel.rb +250 -0
- data/lib/htm.rb +66 -3
- data/lib/tasks/doc.rake +1 -1
- data/lib/tasks/htm.rake +259 -13
- data/mkdocs.yml +98 -96
- metadata +55 -20
- data/.aigcm_msg +0 -1
- data/.claude/settings.local.json +0 -95
- data/CLAUDE.md +0 -603
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +0 -12
- data/examples/cli_app/temp.log +0 -93
- data/examples/robot_groups/lib/robot_group.rb +0 -419
- data/examples/robot_groups/lib/working_memory_channel.rb +0 -140
- data/lib/htm/loaders/paragraph_chunker.rb +0 -112
- data/notes/ARCHITECTURE_REVIEW.md +0 -1167
- data/notes/IMPLEMENTATION_SUMMARY.md +0 -606
- data/notes/MULTI_FRAMEWORK_IMPLEMENTATION.md +0 -451
- data/notes/next_steps.md +0 -100
- data/notes/plan.md +0 -627
- data/notes/tag_ontology_enhancement_ideas.md +0 -222
- data/notes/timescaledb_removal_summary.md +0 -200
data/docs/index.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
<div align="center">
|
|
3
|
-
<div style="background: linear-gradient(135deg, #
|
|
4
|
-
<p style="color: #
|
|
5
|
-
|
|
3
|
+
<div style="background: linear-gradient(135deg, #ffd93d 0%, #f5c800 100%); border: 4px solid #e6b800; border-radius: 12px; padding: 20px; margin: 20px auto; max-width: 800px; box-shadow: 0 8px 16px rgba(230, 184, 0, 0.3);">
|
|
4
|
+
<p style="color: #000000; font-size: 42px; font-weight: bold; margin: 0;">
|
|
5
|
+
💣 CAUTION 💣
|
|
6
6
|
</p>
|
|
7
|
-
<p style="color: #
|
|
8
|
-
This documentation
|
|
9
|
-
|
|
7
|
+
<p style="color: #000; font-size: 27px; font-weight: bold; margin: 10px 0 0 0; line-height: 1.6;">
|
|
8
|
+
This documentation may contain <strong>inaccuracies</strong>.<br/>
|
|
9
|
+
Verify critical details in the source code and example demos.
|
|
10
10
|
</p>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
@@ -63,14 +63,14 @@ HTM enables multiple AI robots to share a collective memory:
|
|
|
63
63
|
- Cross-robot context awareness and conversation continuity
|
|
64
64
|
- Query conversation timelines across multiple robots
|
|
65
65
|
|
|
66
|
-
### Knowledge Graph
|
|
66
|
+
### Pseudo Knowledge Graph
|
|
67
67
|
|
|
68
|
-
Build rich relationship networks between memories:
|
|
68
|
+
Build rich relationship networks between memories using a hierarchical taxonomy:
|
|
69
69
|
|
|
70
70
|
- Link related memories together
|
|
71
|
-
- Tag-based categorization
|
|
71
|
+
- Tag-based categorization with up to four levels of abstraction
|
|
72
72
|
- Importance scoring for prioritization
|
|
73
|
-
- Navigate memory
|
|
73
|
+
- Navigate memory relationship abstractions
|
|
74
74
|
|
|
75
75
|
## Quick Example
|
|
76
76
|
|
|
@@ -79,33 +79,36 @@ Here's how simple it is to get started with HTM:
|
|
|
79
79
|
```ruby
|
|
80
80
|
require 'htm'
|
|
81
81
|
|
|
82
|
+
# Configure HTM globally (optional - uses Ollama by default)
|
|
83
|
+
HTM.configure do |config|
|
|
84
|
+
config.embedding_provider = :ollama
|
|
85
|
+
config.embedding_model = 'nomic-embed-text:latest'
|
|
86
|
+
config.tag_provider = :ollama
|
|
87
|
+
config.tag_model = 'gemma3:latest'
|
|
88
|
+
end
|
|
89
|
+
|
|
82
90
|
# Initialize HTM for your robot
|
|
83
91
|
htm = HTM.new(
|
|
84
|
-
robot_name: "
|
|
85
|
-
working_memory_size: 128_000
|
|
86
|
-
embedding_service: :ollama, # Use Ollama for embeddings
|
|
87
|
-
embedding_model: 'gpt-oss' # Default embedding model
|
|
92
|
+
robot_name: "Chat Assistant",
|
|
93
|
+
working_memory_size: 128_000 # 128k tokens
|
|
88
94
|
)
|
|
89
95
|
|
|
90
|
-
#
|
|
91
|
-
htm.
|
|
92
|
-
"decision_001",
|
|
96
|
+
# Remember information (embeddings generated automatically in background)
|
|
97
|
+
node_id = htm.remember(
|
|
93
98
|
"We decided to use PostgreSQL for HTM storage",
|
|
94
|
-
|
|
95
|
-
category: "architecture",
|
|
96
|
-
importance: 9.0,
|
|
97
|
-
tags: ["database", "architecture"]
|
|
99
|
+
tags: ["database:postgresql", "architecture"],
|
|
100
|
+
metadata: { category: "architecture", priority: "high" }
|
|
98
101
|
)
|
|
99
102
|
|
|
100
103
|
# Recall memories from the past
|
|
101
104
|
memories = htm.recall(
|
|
105
|
+
"database decisions", # Topic (first positional argument)
|
|
102
106
|
timeframe: "last week",
|
|
103
|
-
topic: "database decisions",
|
|
104
107
|
strategy: :hybrid
|
|
105
108
|
)
|
|
106
109
|
|
|
107
|
-
# Create context for your LLM
|
|
108
|
-
context = htm.
|
|
110
|
+
# Create context for your LLM from working memory
|
|
111
|
+
context = htm.working_memory.assemble_context(
|
|
109
112
|
strategy: :balanced,
|
|
110
113
|
max_tokens: 50_000
|
|
111
114
|
)
|
|
@@ -117,8 +120,9 @@ response = llm.chat(
|
|
|
117
120
|
user: "What database did we decide to use?"
|
|
118
121
|
)
|
|
119
122
|
|
|
120
|
-
# Explicit deletion only when needed
|
|
121
|
-
htm.forget(
|
|
123
|
+
# Explicit deletion only when needed (soft delete by default)
|
|
124
|
+
htm.forget(node_id) # Soft delete (recoverable)
|
|
125
|
+
htm.forget(node_id, soft: false, confirm: :confirmed) # Permanent delete
|
|
122
126
|
```
|
|
123
127
|
|
|
124
128
|
## Use Cases
|
data/docs/telemetry.md
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# Telemetry (OpenTelemetry Metrics)
|
|
2
|
+
|
|
3
|
+
HTM includes optional OpenTelemetry-based metrics for production observability. This document provides detailed configuration and usage information.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
HTM uses [OpenTelemetry](https://opentelemetry.io/) for metrics collection, the industry-standard observability framework. This provides:
|
|
8
|
+
|
|
9
|
+
- **Universal compatibility**: Works with 50+ observability backends
|
|
10
|
+
- **Zero vendor lock-in**: Emit standard OTLP, route anywhere
|
|
11
|
+
- **Zero overhead when disabled**: Null object pattern ensures no performance impact
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Install Dependencies
|
|
16
|
+
|
|
17
|
+
Add the OpenTelemetry gems to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'opentelemetry-sdk'
|
|
21
|
+
gem 'opentelemetry-metrics-sdk'
|
|
22
|
+
gem 'opentelemetry-exporter-otlp' # For OTLP export
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. Enable Telemetry
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
HTM.configure do |config|
|
|
29
|
+
config.telemetry_enabled = true
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or via environment variable:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
export HTM_TELEMETRY_ENABLED="true"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. Configure Destination
|
|
40
|
+
|
|
41
|
+
Set standard OpenTelemetry environment variables:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
45
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration Options
|
|
49
|
+
|
|
50
|
+
### HTM Configuration
|
|
51
|
+
|
|
52
|
+
| Option | Type | Default | Description |
|
|
53
|
+
|--------|------|---------|-------------|
|
|
54
|
+
| `telemetry_enabled` | Boolean | `false` | Enable/disable telemetry |
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
HTM.configure do |config|
|
|
58
|
+
config.telemetry_enabled = true
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Environment Variables
|
|
63
|
+
|
|
64
|
+
#### HTM-specific
|
|
65
|
+
|
|
66
|
+
| Variable | Default | Description |
|
|
67
|
+
|----------|---------|-------------|
|
|
68
|
+
| `HTM_TELEMETRY_ENABLED` | `false` | Enable telemetry (`true`/`false`) |
|
|
69
|
+
|
|
70
|
+
#### OpenTelemetry Standard
|
|
71
|
+
|
|
72
|
+
These are standard OpenTelemetry environment variables (not HTM-specific):
|
|
73
|
+
|
|
74
|
+
| Variable | Example | Description |
|
|
75
|
+
|----------|---------|-------------|
|
|
76
|
+
| `OTEL_SERVICE_NAME` | `htm` | Service name in telemetry data |
|
|
77
|
+
| `OTEL_METRICS_EXPORTER` | `otlp` | Metrics exporter type |
|
|
78
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4318` | OTLP collector endpoint |
|
|
79
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | `Authorization=Bearer token` | Headers for OTLP requests |
|
|
80
|
+
|
|
81
|
+
## Available Metrics
|
|
82
|
+
|
|
83
|
+
### htm.jobs (Counter)
|
|
84
|
+
|
|
85
|
+
Counts job executions by type and outcome.
|
|
86
|
+
|
|
87
|
+
**Attributes:**
|
|
88
|
+
- `job`: Job type (`embedding`, `tags`)
|
|
89
|
+
- `status`: Outcome (`success`, `error`, `circuit_open`)
|
|
90
|
+
|
|
91
|
+
**Example queries (PromQL):**
|
|
92
|
+
```promql
|
|
93
|
+
# Jobs per minute by type
|
|
94
|
+
rate(htm_jobs_total[1m])
|
|
95
|
+
|
|
96
|
+
# Error rate for embedding jobs
|
|
97
|
+
rate(htm_jobs_total{job="embedding",status="error"}[5m])
|
|
98
|
+
/ rate(htm_jobs_total{job="embedding"}[5m])
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### htm.embedding.latency (Histogram)
|
|
102
|
+
|
|
103
|
+
Measures embedding generation time in milliseconds.
|
|
104
|
+
|
|
105
|
+
**Attributes:**
|
|
106
|
+
- `provider`: LLM provider (`ollama`, `openai`, etc.)
|
|
107
|
+
- `status`: Outcome (`success`, `error`)
|
|
108
|
+
|
|
109
|
+
**Example queries (PromQL):**
|
|
110
|
+
```promql
|
|
111
|
+
# p95 embedding latency
|
|
112
|
+
histogram_quantile(0.95, rate(htm_embedding_latency_bucket[5m]))
|
|
113
|
+
|
|
114
|
+
# Average latency by provider
|
|
115
|
+
rate(htm_embedding_latency_sum[5m]) / rate(htm_embedding_latency_count[5m])
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### htm.tag.latency (Histogram)
|
|
119
|
+
|
|
120
|
+
Measures tag extraction time in milliseconds.
|
|
121
|
+
|
|
122
|
+
**Attributes:**
|
|
123
|
+
- `provider`: LLM provider (`ollama`, `openai`, etc.)
|
|
124
|
+
- `status`: Outcome (`success`, `error`)
|
|
125
|
+
|
|
126
|
+
**Example queries (PromQL):**
|
|
127
|
+
```promql
|
|
128
|
+
# p99 tag extraction latency
|
|
129
|
+
histogram_quantile(0.99, rate(htm_tag_latency_bucket[5m]))
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### htm.search.latency (Histogram)
|
|
133
|
+
|
|
134
|
+
Measures search operation time in milliseconds.
|
|
135
|
+
|
|
136
|
+
**Attributes:**
|
|
137
|
+
- `strategy`: Search strategy (`vector`, `fulltext`, `hybrid`)
|
|
138
|
+
|
|
139
|
+
**Example queries (PromQL):**
|
|
140
|
+
```promql
|
|
141
|
+
# Search latency by strategy
|
|
142
|
+
histogram_quantile(0.95, rate(htm_search_latency_bucket[5m])) by (strategy)
|
|
143
|
+
|
|
144
|
+
# Hybrid search avg latency
|
|
145
|
+
rate(htm_search_latency_sum{strategy="hybrid"}[5m])
|
|
146
|
+
/ rate(htm_search_latency_count{strategy="hybrid"}[5m])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### htm.cache.operations (Counter)
|
|
150
|
+
|
|
151
|
+
Counts cache hits and misses.
|
|
152
|
+
|
|
153
|
+
**Attributes:**
|
|
154
|
+
- `operation`: Operation type (`hit`, `miss`)
|
|
155
|
+
|
|
156
|
+
**Example queries (PromQL):**
|
|
157
|
+
```promql
|
|
158
|
+
# Cache hit rate
|
|
159
|
+
rate(htm_cache_operations_total{operation="hit"}[5m])
|
|
160
|
+
/ (rate(htm_cache_operations_total{operation="hit"}[5m])
|
|
161
|
+
+ rate(htm_cache_operations_total{operation="miss"}[5m]))
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Compatible Backends
|
|
165
|
+
|
|
166
|
+
HTM metrics work with any OTLP-compatible platform:
|
|
167
|
+
|
|
168
|
+
### Open Source / Self-Hosted
|
|
169
|
+
|
|
170
|
+
| Platform | OTLP Support | Notes |
|
|
171
|
+
|----------|--------------|-------|
|
|
172
|
+
| **Jaeger** | Native (v1.35+) | Distributed tracing with metrics |
|
|
173
|
+
| **Prometheus** | Via receiver | Popular metrics platform |
|
|
174
|
+
| **Grafana Tempo** | Native | Traces with metrics correlation |
|
|
175
|
+
| **Grafana Mimir** | Native | Scalable Prometheus-compatible |
|
|
176
|
+
| **SigNoz** | Native | Full-stack observability |
|
|
177
|
+
| **Uptrace** | Native | Open source APM |
|
|
178
|
+
|
|
179
|
+
### Commercial / SaaS
|
|
180
|
+
|
|
181
|
+
| Platform | OTLP Support | Notes |
|
|
182
|
+
|----------|--------------|-------|
|
|
183
|
+
| **Datadog** | Native | Full-stack observability |
|
|
184
|
+
| **New Relic** | Native | APM and infrastructure |
|
|
185
|
+
| **Honeycomb** | Native (preferred) | High-cardinality observability |
|
|
186
|
+
| **Splunk APM** | Native | Enterprise observability |
|
|
187
|
+
| **Dynatrace** | Native | AI-powered monitoring |
|
|
188
|
+
| **AWS X-Ray** | Via ADOT | AWS native tracing |
|
|
189
|
+
| **Google Cloud Trace** | Native | GCP native tracing |
|
|
190
|
+
| **Azure Monitor** | Native | Azure native monitoring |
|
|
191
|
+
| **Grafana Cloud** | Native | Managed Grafana stack |
|
|
192
|
+
|
|
193
|
+
## Setup Examples
|
|
194
|
+
|
|
195
|
+
### Jaeger (Local Development)
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Start Jaeger with OTLP support
|
|
199
|
+
docker run -d --name jaeger \
|
|
200
|
+
-p 4318:4318 \
|
|
201
|
+
-p 16686:16686 \
|
|
202
|
+
jaegertracing/all-in-one:latest
|
|
203
|
+
|
|
204
|
+
# Configure HTM
|
|
205
|
+
export HTM_TELEMETRY_ENABLED="true"
|
|
206
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
207
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Prometheus (via OpenTelemetry Collector)
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
# otel-collector-config.yaml
|
|
214
|
+
receivers:
|
|
215
|
+
otlp:
|
|
216
|
+
protocols:
|
|
217
|
+
grpc:
|
|
218
|
+
http:
|
|
219
|
+
|
|
220
|
+
exporters:
|
|
221
|
+
prometheus:
|
|
222
|
+
endpoint: "0.0.0.0:8889"
|
|
223
|
+
|
|
224
|
+
service:
|
|
225
|
+
pipelines:
|
|
226
|
+
metrics:
|
|
227
|
+
receivers: [otlp]
|
|
228
|
+
exporters: [prometheus]
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
docker run -d \
|
|
233
|
+
-p 4317:4317 \
|
|
234
|
+
-p 4318:4318 \
|
|
235
|
+
-p 8889:8889 \
|
|
236
|
+
-v $(pwd)/otel-collector-config.yaml:/etc/otel-collector-config.yaml \
|
|
237
|
+
otel/opentelemetry-collector:latest \
|
|
238
|
+
--config=/etc/otel-collector-config.yaml
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Datadog
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
export HTM_TELEMETRY_ENABLED="true"
|
|
245
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
246
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otlp.datadoghq.com"
|
|
247
|
+
export OTEL_EXPORTER_OTLP_HEADERS="DD-API-KEY=your-api-key"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Honeycomb
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
export HTM_TELEMETRY_ENABLED="true"
|
|
254
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
255
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io"
|
|
256
|
+
export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key"
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### New Relic
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
export HTM_TELEMETRY_ENABLED="true"
|
|
263
|
+
export OTEL_METRICS_EXPORTER="otlp"
|
|
264
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otlp.nr-data.net"
|
|
265
|
+
export OTEL_EXPORTER_OTLP_HEADERS="api-key=your-license-key"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Architecture
|
|
269
|
+
|
|
270
|
+
### Null Object Pattern
|
|
271
|
+
|
|
272
|
+
HTM uses a null object pattern for telemetry. When disabled:
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
# This code runs identically whether telemetry is enabled or not
|
|
276
|
+
HTM::Telemetry.job_counter.add(1, attributes: { 'job' => 'embedding' })
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
When telemetry is disabled or the SDK is not installed:
|
|
280
|
+
- `HTM::Telemetry.meter` returns a `NullMeter`
|
|
281
|
+
- All instruments return `NullInstrument` instances
|
|
282
|
+
- All operations (`add`, `record`) are no-ops returning `nil`
|
|
283
|
+
- Zero memory allocation, zero CPU overhead
|
|
284
|
+
|
|
285
|
+
### Code Flow
|
|
286
|
+
|
|
287
|
+

|
|
288
|
+
|
|
289
|
+
### Instrumentation Points
|
|
290
|
+
|
|
291
|
+
HTM instruments these key operations:
|
|
292
|
+
|
|
293
|
+
| Component | Metrics Recorded |
|
|
294
|
+
|-----------|-----------------|
|
|
295
|
+
| `GenerateEmbeddingJob` | `htm.jobs`, `htm.embedding.latency` |
|
|
296
|
+
| `GenerateTagsJob` | `htm.jobs`, `htm.tag.latency` |
|
|
297
|
+
| `VectorSearch#search` | `htm.search.latency` (strategy: vector) |
|
|
298
|
+
| `FulltextSearch#search_fulltext` | `htm.search.latency` (strategy: fulltext) |
|
|
299
|
+
| `HybridSearch#search_hybrid` | `htm.search.latency` (strategy: hybrid) |
|
|
300
|
+
| `QueryCache#fetch` | `htm.cache.operations` |
|
|
301
|
+
|
|
302
|
+
## Testing
|
|
303
|
+
|
|
304
|
+
When writing tests, reset telemetry state between tests:
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
def setup
|
|
308
|
+
HTM::Telemetry.reset!
|
|
309
|
+
HTM.configuration.telemetry_enabled = false
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def teardown
|
|
313
|
+
HTM::Telemetry.reset!
|
|
314
|
+
end
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Verifying Metrics in Tests
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
def test_records_embedding_latency
|
|
321
|
+
# Create a mock histogram
|
|
322
|
+
recorded = []
|
|
323
|
+
mock_histogram = Object.new
|
|
324
|
+
mock_histogram.define_singleton_method(:record) do |value, **kwargs|
|
|
325
|
+
recorded << { value: value, attributes: kwargs[:attributes] }
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Inject mock (requires test helper)
|
|
329
|
+
HTM::Telemetry.instance_variable_set(:@embedding_latency, mock_histogram)
|
|
330
|
+
|
|
331
|
+
# Run operation
|
|
332
|
+
HTM::Jobs::GenerateEmbeddingJob.perform(node_id: node.id)
|
|
333
|
+
|
|
334
|
+
# Verify
|
|
335
|
+
assert recorded.any? { |r| r[:attributes]['status'] == 'success' }
|
|
336
|
+
end
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Troubleshooting
|
|
340
|
+
|
|
341
|
+
### Metrics Not Appearing
|
|
342
|
+
|
|
343
|
+
1. **Check telemetry is enabled:**
|
|
344
|
+
```ruby
|
|
345
|
+
puts HTM.configuration.telemetry_enabled # Should be true
|
|
346
|
+
puts HTM::Telemetry.enabled? # Should be true
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
2. **Check SDK is installed:**
|
|
350
|
+
```ruby
|
|
351
|
+
puts HTM::Telemetry.sdk_available? # Should be true
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
3. **Check environment variables:**
|
|
355
|
+
```bash
|
|
356
|
+
echo $OTEL_METRICS_EXPORTER
|
|
357
|
+
echo $OTEL_EXPORTER_OTLP_ENDPOINT
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
4. **Check collector is running:**
|
|
361
|
+
```bash
|
|
362
|
+
curl http://localhost:4318/v1/metrics # Should not 404
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### High Cardinality Issues
|
|
366
|
+
|
|
367
|
+
Avoid high-cardinality attributes in metrics. HTM uses low-cardinality attributes by design:
|
|
368
|
+
|
|
369
|
+
- `job`: 2-3 values (embedding, tags, propositions)
|
|
370
|
+
- `status`: 3 values (success, error, circuit_open)
|
|
371
|
+
- `provider`: ~10 values (ollama, openai, etc.)
|
|
372
|
+
- `strategy`: 3 values (vector, fulltext, hybrid)
|
|
373
|
+
- `operation`: 2 values (hit, miss)
|
|
374
|
+
|
|
375
|
+
### Performance Concerns
|
|
376
|
+
|
|
377
|
+
With telemetry disabled (default), there is zero overhead:
|
|
378
|
+
- No gem loading
|
|
379
|
+
- No object allocation
|
|
380
|
+
- No method calls beyond the null check
|
|
381
|
+
|
|
382
|
+
With telemetry enabled, overhead is minimal:
|
|
383
|
+
- ~1-5μs per metric recording
|
|
384
|
+
- Memory for histogram buckets (~1KB per histogram)
|
|
385
|
+
|
|
386
|
+
## References
|
|
387
|
+
|
|
388
|
+
- [OpenTelemetry Ruby SDK](https://github.com/open-telemetry/opentelemetry-ruby)
|
|
389
|
+
- [OpenTelemetry Metrics SDK](https://github.com/open-telemetry/opentelemetry-ruby/tree/main/metrics_sdk)
|
|
390
|
+
- [OpenTelemetry Specification](https://opentelemetry.io/docs/specs/otel/)
|
|
391
|
+
- [OTLP Protocol](https://opentelemetry.io/docs/specs/otlp/)
|
data/examples/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# HTM Examples
|
|
2
2
|
|
|
3
|
-
This directory contains example applications demonstrating various ways to use the HTM (Hierarchical
|
|
3
|
+
This directory contains example applications demonstrating various ways to use the HTM (Hierarchical Temporal Memory) gem.
|
|
4
4
|
|
|
5
5
|
## Prerequisites
|
|
6
6
|
|
|
@@ -11,6 +11,12 @@ All examples require:
|
|
|
11
11
|
export HTM_DBURL="postgresql://user@localhost:5432/htm_development"
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
> **Note**: Database selection now respects `RAILS_ENV`. If `RAILS_ENV` is set,
|
|
15
|
+
> HTM extracts the base name from `HTM_DBURL` and appends the environment suffix.
|
|
16
|
+
> For example, with `HTM_DBURL=...htm_development` and `RAILS_ENV=test`, HTM
|
|
17
|
+
> connects to `htm_test`. When `RAILS_ENV` is unset (typical for examples),
|
|
18
|
+
> behavior is unchanged.
|
|
19
|
+
|
|
14
20
|
2. **Ollama** (recommended for local LLM):
|
|
15
21
|
```bash
|
|
16
22
|
ollama pull nomic-embed-text # For embeddings
|
|
@@ -107,6 +113,39 @@ ruby examples/timeframe_demo.rb
|
|
|
107
113
|
|
|
108
114
|
---
|
|
109
115
|
|
|
116
|
+
### telemetry/
|
|
117
|
+
|
|
118
|
+
**Live Grafana dashboard for HTM metrics.**
|
|
119
|
+
|
|
120
|
+
A complete telemetry demo using Homebrew-installed Prometheus and Grafana to visualize HTM metrics in real-time graphs.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
cd examples/telemetry
|
|
124
|
+
ruby demo.rb
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The demo automatically:
|
|
128
|
+
- Checks/installs Prometheus and Grafana via Homebrew
|
|
129
|
+
- Starts both services if not running
|
|
130
|
+
- Configures Prometheus to scrape the demo's metrics
|
|
131
|
+
- Cleans up previous demo data
|
|
132
|
+
- Opens Grafana in your browser
|
|
133
|
+
|
|
134
|
+
**Features:**
|
|
135
|
+
- Live updating dashboard with job counts, latencies, cache hit rates
|
|
136
|
+
- Pre-built Grafana dashboard JSON
|
|
137
|
+
- No Docker required - uses native macOS services
|
|
138
|
+
|
|
139
|
+
**Dependencies:**
|
|
140
|
+
```bash
|
|
141
|
+
brew install prometheus grafana
|
|
142
|
+
gem install prometheus-client webrick
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [telemetry/README.md](telemetry/README.md) for detailed setup instructions.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
110
149
|
### mcp_server.rb & mcp_client.rb
|
|
111
150
|
|
|
112
151
|
**Model Context Protocol (MCP) integration for AI assistants.**
|
|
@@ -366,6 +405,11 @@ examples/
|
|
|
366
405
|
├── custom_llm_configuration.rb # LLM integration patterns
|
|
367
406
|
├── file_loader_usage.rb # Document loading
|
|
368
407
|
├── timeframe_demo.rb # Time-based filtering
|
|
408
|
+
├── telemetry/
|
|
409
|
+
│ ├── demo.rb # Live Grafana metrics dashboard
|
|
410
|
+
│ ├── README.md
|
|
411
|
+
│ ├── SETUP_README.md
|
|
412
|
+
│ └── grafana/dashboards/htm-metrics.json
|
|
369
413
|
├── mcp_server.rb # MCP server exposing HTM tools
|
|
370
414
|
├── mcp_client.rb # MCP client with chat interface
|
|
371
415
|
├── example_app/
|
|
@@ -397,6 +441,7 @@ examples/
|
|
|
397
441
|
| Custom LLM integration | `custom_llm_configuration.rb` |
|
|
398
442
|
| Loading documents/files | `file_loader_usage.rb` |
|
|
399
443
|
| Time-based queries | `timeframe_demo.rb` |
|
|
444
|
+
| Production observability | `telemetry/` |
|
|
400
445
|
| MCP server for AI assistants | `mcp_server.rb` |
|
|
401
446
|
| MCP client with chat interface | `mcp_client.rb` |
|
|
402
447
|
| Web application | `sinatra_app/` |
|
data/examples/cli_app/README.md
CHANGED
|
@@ -111,7 +111,7 @@ This means:
|
|
|
111
111
|
$ ruby htm_cli.rb
|
|
112
112
|
|
|
113
113
|
============================================================
|
|
114
|
-
HTM CLI - Hierarchical
|
|
114
|
+
HTM CLI - Hierarchical Temporal Memory Assistant
|
|
115
115
|
============================================================
|
|
116
116
|
|
|
117
117
|
Job Backend: inline (synchronous execution)
|
data/examples/cli_app/htm_cli.rb
CHANGED
|
@@ -67,7 +67,7 @@ class HTMCli
|
|
|
67
67
|
def run
|
|
68
68
|
puts
|
|
69
69
|
puts "=" * 60
|
|
70
|
-
puts "HTM CLI - Hierarchical
|
|
70
|
+
puts "HTM CLI - Hierarchical Temporal Memory Assistant"
|
|
71
71
|
puts "=" * 60
|
|
72
72
|
puts
|
|
73
73
|
puts "Job Backend: #{HTM.configuration.job_backend} (synchronous execution)"
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
require 'logger'
|
|
21
21
|
require 'json'
|
|
22
22
|
require_relative '../../lib/htm'
|
|
23
|
-
require_relative 'lib/working_memory_channel'
|
|
24
23
|
|
|
25
24
|
robot_name = ARGV[0]
|
|
26
25
|
group_name = ARGV[1]
|
|
@@ -53,7 +52,7 @@ htm = HTM.new(robot_name: robot_name, working_memory_size: 8000)
|
|
|
53
52
|
db_config = HTM::Database.default_config
|
|
54
53
|
|
|
55
54
|
# Setup channel for cross-process notifications
|
|
56
|
-
channel = WorkingMemoryChannel.new(group_name, db_config)
|
|
55
|
+
channel = HTM::WorkingMemoryChannel.new(group_name, db_config)
|
|
57
56
|
|
|
58
57
|
# Track notifications received
|
|
59
58
|
notifications_count = 0
|
|
@@ -26,9 +26,6 @@
|
|
|
26
26
|
require_relative '../../lib/htm'
|
|
27
27
|
require 'json'
|
|
28
28
|
|
|
29
|
-
require_relative 'lib/working_memory_channel'
|
|
30
|
-
require_relative 'lib/robot_group'
|
|
31
|
-
|
|
32
29
|
# =============================================================================
|
|
33
30
|
# Demo Script
|
|
34
31
|
# =============================================================================
|
|
@@ -59,7 +56,7 @@ begin
|
|
|
59
56
|
# ---------------------------------------------------------------------------
|
|
60
57
|
puts "\n2. Creating robot group with primary + standby..."
|
|
61
58
|
|
|
62
|
-
group = RobotGroup.new(
|
|
59
|
+
group = HTM::RobotGroup.new(
|
|
63
60
|
name: 'customer-support-ha',
|
|
64
61
|
active: ['support-primary'],
|
|
65
62
|
passive: ['support-standby'],
|
data/examples/sinatra_app/app.rb
CHANGED
|
@@ -281,7 +281,7 @@ __END__
|
|
|
281
281
|
</head>
|
|
282
282
|
<body>
|
|
283
283
|
<h1>HTM Sinatra Example</h1>
|
|
284
|
-
<p>Hierarchical
|
|
284
|
+
<p>Hierarchical Temporal Memory with tag-enhanced hybrid search and Sidekiq background jobs</p>
|
|
285
285
|
|
|
286
286
|
<div class="section">
|
|
287
287
|
<h2>Remember Information</h2>
|