htm 0.0.14 → 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/CHANGELOG.md +33 -0
- data/README.md +269 -79
- 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 +41 -29
- 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 +11 -23
- data/docs/api/yard/index.csv +102 -25
- data/docs/api/yard-reference.md +8 -0
- 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 +13 -0
- data/docs/development/rake-tasks.md +1068 -0
- 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 +7 -0
- 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/index.md +30 -26
- data/examples/robot_groups/robot_worker.rb +1 -2
- data/examples/robot_groups/same_process.rb +1 -4
- data/lib/htm/robot_group.rb +721 -0
- data/lib/htm/version.rb +1 -1
- data/lib/htm/working_memory_channel.rb +250 -0
- data/lib/htm.rb +2 -0
- data/mkdocs.yml +2 -0
- metadata +18 -9
- data/db/migrate/00009_add_working_memory_to_robot_nodes.rb +0 -12
- data/db/migrate/00010_add_soft_delete_to_associations.rb +0 -29
- data/db/migrate/00011_add_performance_indexes.rb +0 -21
- data/db/migrate/00012_add_tags_trigram_index.rb +0 -18
- data/db/migrate/00013_enable_lz4_compression.rb +0 -43
- data/examples/robot_groups/lib/robot_group.rb +0 -419
- data/examples/robot_groups/lib/working_memory_channel.rb +0 -140
data/db/schema.sql
CHANGED
|
@@ -108,7 +108,7 @@ CREATE TABLE public.node_tags (
|
|
|
108
108
|
node_id bigint NOT NULL,
|
|
109
109
|
tag_id bigint NOT NULL,
|
|
110
110
|
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
111
|
-
deleted_at timestamp
|
|
111
|
+
deleted_at timestamp with time zone
|
|
112
112
|
);
|
|
113
113
|
|
|
114
114
|
--
|
|
@@ -135,6 +135,12 @@ COMMENT ON COLUMN public.node_tags.tag_id IS 'ID of the tag being applied';
|
|
|
135
135
|
|
|
136
136
|
COMMENT ON COLUMN public.node_tags.created_at IS 'When this association was created';
|
|
137
137
|
|
|
138
|
+
--
|
|
139
|
+
-- Name: COLUMN node_tags.deleted_at; Type: COMMENT; Schema: public; Owner: -
|
|
140
|
+
--
|
|
141
|
+
|
|
142
|
+
COMMENT ON COLUMN public.node_tags.deleted_at IS 'Soft delete timestamp';
|
|
143
|
+
|
|
138
144
|
--
|
|
139
145
|
-- Name: node_tags_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
140
146
|
--
|
|
@@ -288,10 +294,10 @@ CREATE TABLE public.robot_nodes (
|
|
|
288
294
|
first_remembered_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
289
295
|
last_remembered_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
290
296
|
remember_count integer DEFAULT 1 NOT NULL,
|
|
297
|
+
working_memory boolean DEFAULT false NOT NULL,
|
|
291
298
|
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
292
299
|
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
293
|
-
|
|
294
|
-
deleted_at timestamp(6) without time zone
|
|
300
|
+
deleted_at timestamp with time zone
|
|
295
301
|
);
|
|
296
302
|
|
|
297
303
|
--
|
|
@@ -336,6 +342,12 @@ COMMENT ON COLUMN public.robot_nodes.remember_count IS 'Number of times this rob
|
|
|
336
342
|
|
|
337
343
|
COMMENT ON COLUMN public.robot_nodes.working_memory IS 'True if this node is currently in the robot working memory';
|
|
338
344
|
|
|
345
|
+
--
|
|
346
|
+
-- Name: COLUMN robot_nodes.deleted_at; Type: COMMENT; Schema: public; Owner: -
|
|
347
|
+
--
|
|
348
|
+
|
|
349
|
+
COMMENT ON COLUMN public.robot_nodes.deleted_at IS 'Soft delete timestamp';
|
|
350
|
+
|
|
339
351
|
--
|
|
340
352
|
-- Name: robot_nodes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
341
353
|
--
|
|
@@ -421,7 +433,7 @@ CREATE TABLE public.tags (
|
|
|
421
433
|
id bigint NOT NULL,
|
|
422
434
|
name text NOT NULL,
|
|
423
435
|
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP,
|
|
424
|
-
deleted_at timestamp
|
|
436
|
+
deleted_at timestamp with time zone
|
|
425
437
|
);
|
|
426
438
|
|
|
427
439
|
--
|
|
@@ -442,6 +454,12 @@ COMMENT ON COLUMN public.tags.name IS 'Hierarchical tag in format: root:level1:l
|
|
|
442
454
|
|
|
443
455
|
COMMENT ON COLUMN public.tags.created_at IS 'When this tag was created';
|
|
444
456
|
|
|
457
|
+
--
|
|
458
|
+
-- Name: COLUMN tags.deleted_at; Type: COMMENT; Schema: public; Owner: -
|
|
459
|
+
--
|
|
460
|
+
|
|
461
|
+
COMMENT ON COLUMN public.tags.deleted_at IS 'Soft delete timestamp';
|
|
462
|
+
|
|
445
463
|
--
|
|
446
464
|
-- Name: tags_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
447
465
|
--
|
|
@@ -562,6 +580,12 @@ CREATE INDEX idx_file_sources_last_synced ON public.file_sources USING btree (la
|
|
|
562
580
|
|
|
563
581
|
CREATE UNIQUE INDEX idx_file_sources_path_unique ON public.file_sources USING btree (file_path);
|
|
564
582
|
|
|
583
|
+
--
|
|
584
|
+
-- Name: idx_node_tags_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
585
|
+
--
|
|
586
|
+
|
|
587
|
+
CREATE INDEX idx_node_tags_deleted_at ON public.node_tags USING btree (deleted_at);
|
|
588
|
+
|
|
565
589
|
--
|
|
566
590
|
-- Name: idx_node_tags_node_id; Type: INDEX; Schema: public; Owner: -
|
|
567
591
|
--
|
|
@@ -592,12 +616,6 @@ CREATE INDEX idx_nodes_access_count ON public.nodes USING btree (access_count);
|
|
|
592
616
|
|
|
593
617
|
CREATE INDEX idx_nodes_active ON public.nodes USING btree (id) WHERE (deleted_at IS NULL);
|
|
594
618
|
|
|
595
|
-
--
|
|
596
|
-
-- Name: INDEX idx_nodes_active; Type: COMMENT; Schema: public; Owner: -
|
|
597
|
-
--
|
|
598
|
-
|
|
599
|
-
COMMENT ON INDEX public.idx_nodes_active IS 'Partial index for active (non-deleted) node queries';
|
|
600
|
-
|
|
601
619
|
--
|
|
602
620
|
-- Name: idx_nodes_active_with_embedding; Type: INDEX; Schema: public; Owner: -
|
|
603
621
|
--
|
|
@@ -676,6 +694,12 @@ CREATE INDEX idx_nodes_source_id ON public.nodes USING btree (source_id);
|
|
|
676
694
|
|
|
677
695
|
CREATE INDEX idx_nodes_updated_at ON public.nodes USING btree (updated_at);
|
|
678
696
|
|
|
697
|
+
--
|
|
698
|
+
-- Name: idx_robot_nodes_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
699
|
+
--
|
|
700
|
+
|
|
701
|
+
CREATE INDEX idx_robot_nodes_deleted_at ON public.robot_nodes USING btree (deleted_at);
|
|
702
|
+
|
|
679
703
|
--
|
|
680
704
|
-- Name: idx_robot_nodes_last_remembered_at; Type: INDEX; Schema: public; Owner: -
|
|
681
705
|
--
|
|
@@ -706,6 +730,12 @@ CREATE UNIQUE INDEX idx_robot_nodes_unique ON public.robot_nodes USING btree (ro
|
|
|
706
730
|
|
|
707
731
|
CREATE INDEX idx_robot_nodes_working_memory ON public.robot_nodes USING btree (robot_id, working_memory) WHERE (working_memory = true);
|
|
708
732
|
|
|
733
|
+
--
|
|
734
|
+
-- Name: idx_tags_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
735
|
+
--
|
|
736
|
+
|
|
737
|
+
CREATE INDEX idx_tags_deleted_at ON public.tags USING btree (deleted_at);
|
|
738
|
+
|
|
709
739
|
--
|
|
710
740
|
-- Name: idx_tags_name_pattern; Type: INDEX; Schema: public; Owner: -
|
|
711
741
|
--
|
|
@@ -724,24 +754,6 @@ CREATE INDEX idx_tags_name_trgm ON public.tags USING gin (name public.gin_trgm_o
|
|
|
724
754
|
|
|
725
755
|
CREATE UNIQUE INDEX idx_tags_name_unique ON public.tags USING btree (name);
|
|
726
756
|
|
|
727
|
-
--
|
|
728
|
-
-- Name: index_node_tags_on_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
729
|
-
--
|
|
730
|
-
|
|
731
|
-
CREATE INDEX index_node_tags_on_deleted_at ON public.node_tags USING btree (deleted_at);
|
|
732
|
-
|
|
733
|
-
--
|
|
734
|
-
-- Name: index_robot_nodes_on_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
735
|
-
--
|
|
736
|
-
|
|
737
|
-
CREATE INDEX index_robot_nodes_on_deleted_at ON public.robot_nodes USING btree (deleted_at);
|
|
738
|
-
|
|
739
|
-
--
|
|
740
|
-
-- Name: index_tags_on_deleted_at; Type: INDEX; Schema: public; Owner: -
|
|
741
|
-
--
|
|
742
|
-
|
|
743
|
-
CREATE INDEX index_tags_on_deleted_at ON public.tags USING btree (deleted_at);
|
|
744
|
-
|
|
745
757
|
--
|
|
746
758
|
-- Name: nodes fk_rails_920ad16d08; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
747
759
|
--
|
|
@@ -781,4 +793,4 @@ ALTER TABLE ONLY public.robot_nodes
|
|
|
781
793
|
-- PostgreSQL database dump complete
|
|
782
794
|
--
|
|
783
795
|
|
|
784
|
-
\unrestrict
|
|
796
|
+
\unrestrict 4WlUqnJzNHaNhcr67XLIIhAvRPidZODUPGkM34l27SvmC0zu6dIsQdJ8dtu589Z
|
|
@@ -81,6 +81,21 @@ Returns the value of attribute bedrock_region.
|
|
|
81
81
|
## bedrock_secret_key[RW] {: #attribute-i-bedrock_secret_key }
|
|
82
82
|
Returns the value of attribute bedrock_secret_key.
|
|
83
83
|
|
|
84
|
+
## chunk_overlap[RW] {: #attribute-i-chunk_overlap }
|
|
85
|
+
Character overlap between chunks (default: 64)
|
|
86
|
+
|
|
87
|
+
## chunk_size[RW] {: #attribute-i-chunk_size }
|
|
88
|
+
Chunking configuration (for file loading)
|
|
89
|
+
|
|
90
|
+
## circuit_breaker_failure_threshold[RW] {: #attribute-i-circuit_breaker_failure_threshold }
|
|
91
|
+
Circuit breaker configuration
|
|
92
|
+
|
|
93
|
+
## circuit_breaker_half_open_max_calls[RW] {: #attribute-i-circuit_breaker_half_open_max_calls }
|
|
94
|
+
Successes to close (default: 3)
|
|
95
|
+
|
|
96
|
+
## circuit_breaker_reset_timeout[RW] {: #attribute-i-circuit_breaker_reset_timeout }
|
|
97
|
+
Seconds before half-open (default: 60)
|
|
98
|
+
|
|
84
99
|
## connection_timeout[RW] {: #attribute-i-connection_timeout }
|
|
85
100
|
Returns the value of attribute connection_timeout.
|
|
86
101
|
|
|
@@ -102,6 +117,9 @@ Returns the value of attribute embedding_provider.
|
|
|
102
117
|
## embedding_timeout[RW] {: #attribute-i-embedding_timeout }
|
|
103
118
|
Returns the value of attribute embedding_timeout.
|
|
104
119
|
|
|
120
|
+
## extract_propositions[RW] {: #attribute-i-extract_propositions }
|
|
121
|
+
Returns the value of attribute extract_propositions.
|
|
122
|
+
|
|
105
123
|
## gemini_api_key[RW] {: #attribute-i-gemini_api_key }
|
|
106
124
|
Returns the value of attribute gemini_api_key.
|
|
107
125
|
|
|
@@ -114,6 +132,12 @@ Returns the value of attribute job_backend.
|
|
|
114
132
|
## logger[RW] {: #attribute-i-logger }
|
|
115
133
|
Returns the value of attribute logger.
|
|
116
134
|
|
|
135
|
+
## max_embedding_dimension[RW] {: #attribute-i-max_embedding_dimension }
|
|
136
|
+
Limit configuration
|
|
137
|
+
|
|
138
|
+
## max_tag_depth[RW] {: #attribute-i-max_tag_depth }
|
|
139
|
+
Max tag hierarchy depth (default: 4)
|
|
140
|
+
|
|
117
141
|
## ollama_url[RW] {: #attribute-i-ollama_url }
|
|
118
142
|
Returns the value of attribute ollama_url.
|
|
119
143
|
|
|
@@ -129,6 +153,33 @@ Provider-specific API keys and endpoints
|
|
|
129
153
|
## openrouter_api_key[RW] {: #attribute-i-openrouter_api_key }
|
|
130
154
|
Returns the value of attribute openrouter_api_key.
|
|
131
155
|
|
|
156
|
+
## proposition_extractor[RW] {: #attribute-i-proposition_extractor }
|
|
157
|
+
Returns the value of attribute proposition_extractor.
|
|
158
|
+
|
|
159
|
+
## proposition_model[RW] {: #attribute-i-proposition_model }
|
|
160
|
+
Returns the value of attribute proposition_model.
|
|
161
|
+
|
|
162
|
+
## proposition_provider[RW] {: #attribute-i-proposition_provider }
|
|
163
|
+
Returns the value of attribute proposition_provider.
|
|
164
|
+
|
|
165
|
+
## proposition_timeout[RW] {: #attribute-i-proposition_timeout }
|
|
166
|
+
Returns the value of attribute proposition_timeout.
|
|
167
|
+
|
|
168
|
+
## relevance_access_weight[RW] {: #attribute-i-relevance_access_weight }
|
|
169
|
+
Access frequency weight (default: 0.1)
|
|
170
|
+
|
|
171
|
+
## relevance_recency_half_life_hours[RW] {: #attribute-i-relevance_recency_half_life_hours }
|
|
172
|
+
Decay half-life in hours (default: 168 = 1 week)
|
|
173
|
+
|
|
174
|
+
## relevance_recency_weight[RW] {: #attribute-i-relevance_recency_weight }
|
|
175
|
+
Temporal freshness weight (default: 0.1)
|
|
176
|
+
|
|
177
|
+
## relevance_semantic_weight[RW] {: #attribute-i-relevance_semantic_weight }
|
|
178
|
+
Relevance scoring weights (must sum to 1.0)
|
|
179
|
+
|
|
180
|
+
## relevance_tag_weight[RW] {: #attribute-i-relevance_tag_weight }
|
|
181
|
+
Tag overlap weight (default: 0.3)
|
|
182
|
+
|
|
132
183
|
## tag_extractor[RW] {: #attribute-i-tag_extractor }
|
|
133
184
|
Returns the value of attribute tag_extractor.
|
|
134
185
|
|
|
@@ -141,6 +192,9 @@ Returns the value of attribute tag_provider.
|
|
|
141
192
|
## tag_timeout[RW] {: #attribute-i-tag_timeout }
|
|
142
193
|
Returns the value of attribute tag_timeout.
|
|
143
194
|
|
|
195
|
+
## telemetry_enabled[RW] {: #attribute-i-telemetry_enabled }
|
|
196
|
+
Enable OpenTelemetry metrics (default: false)
|
|
197
|
+
|
|
144
198
|
## token_counter[RW] {: #attribute-i-token_counter }
|
|
145
199
|
Returns the value of attribute token_counter.
|
|
146
200
|
|
|
@@ -8,20 +8,23 @@ initialization
|
|
|
8
8
|
|
|
9
9
|
# Class Methods
|
|
10
10
|
## default_config() {: #method-c-default_config }
|
|
11
|
-
Get default database configuration
|
|
12
|
-
|
|
11
|
+
Get default database configuration (respects RAILS_ENV)
|
|
12
|
+
|
|
13
|
+
Uses ActiveRecordConfig which reads from config/database.yml and respects
|
|
14
|
+
RAILS_ENV for environment-specific database selection.
|
|
15
|
+
**`@return`** [Hash, nil] Connection configuration hash with PG-style keys
|
|
13
16
|
|
|
14
17
|
## drop(db_url nil) {: #method-c-drop }
|
|
15
|
-
Drop all HTM tables
|
|
16
|
-
**`@param`** [String] Database connection URL (uses
|
|
18
|
+
Drop all HTM tables (respects RAILS_ENV)
|
|
19
|
+
**`@param`** [String] Database connection URL (uses default_config if not provided)
|
|
17
20
|
|
|
18
21
|
**`@return`** [void]
|
|
19
22
|
|
|
20
23
|
## dump_schema(db_url nil) {: #method-c-dump_schema }
|
|
21
|
-
Dump current database schema to db/schema.sql
|
|
24
|
+
Dump current database schema to db/schema.sql (respects RAILS_ENV)
|
|
22
25
|
|
|
23
26
|
Uses pg_dump to create a clean SQL schema file without data
|
|
24
|
-
**`@param`** [String] Database connection URL (uses
|
|
27
|
+
**`@param`** [String] Database connection URL (uses default_config if not provided)
|
|
25
28
|
|
|
26
29
|
**`@return`** [void]
|
|
27
30
|
|
|
@@ -39,16 +42,16 @@ comprehensive database documentation including:
|
|
|
39
42
|
**`@return`** [void]
|
|
40
43
|
|
|
41
44
|
## info(db_url nil) {: #method-c-info }
|
|
42
|
-
Show database info
|
|
43
|
-
**`@param`** [String] Database connection URL (uses
|
|
45
|
+
Show database info (respects RAILS_ENV)
|
|
46
|
+
**`@param`** [String] Database connection URL (uses default_config if not provided)
|
|
44
47
|
|
|
45
48
|
**`@return`** [void]
|
|
46
49
|
|
|
47
50
|
## load_schema(db_url nil) {: #method-c-load_schema }
|
|
48
|
-
Load schema from db/schema.sql
|
|
51
|
+
Load schema from db/schema.sql (respects RAILS_ENV)
|
|
49
52
|
|
|
50
53
|
Uses psql to load the schema file
|
|
51
|
-
**`@param`** [String] Database connection URL (uses
|
|
54
|
+
**`@param`** [String] Database connection URL (uses default_config if not provided)
|
|
52
55
|
|
|
53
56
|
**`@return`** [void]
|
|
54
57
|
|
|
@@ -39,8 +39,12 @@ Generate embedding with validation and processing
|
|
|
39
39
|
storage_dimension: Integer # Padded dimension (2000)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
## max_dimension() {: #method-c-max_dimension }
|
|
43
|
+
Maximum embedding dimension (configurable, default 2000)
|
|
44
|
+
**`@return`** [Integer] Max dimensions for pgvector HNSW index
|
|
45
|
+
|
|
42
46
|
## pad_embedding(embedding ) {: #method-c-pad_embedding }
|
|
43
|
-
Pad embedding to
|
|
47
|
+
Pad embedding to max_dimension with zeros
|
|
44
48
|
**`@param`** [Array<Float>] Original embedding
|
|
45
49
|
|
|
46
50
|
**`@return`** [Array<Float>] Padded embedding
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Class: HTM::LongTermMemory
|
|
2
2
|
**Inherits:** Object
|
|
3
3
|
|
|
4
|
+
**Includes:** FulltextSearch, HybridSearch, NodeOperations, RelevanceScorer, RobotOperations, TagOperations, VectorSearch
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
Long-term Memory - PostgreSQL/TimescaleDB-backed permanent storage
|
|
6
8
|
|
|
@@ -13,6 +15,21 @@ LongTermMemory provides durable storage for all memory nodes with:
|
|
|
13
15
|
* ActiveRecord ORM for data access
|
|
14
16
|
* Query result caching for efficiency
|
|
15
17
|
|
|
18
|
+
This class uses standalone utility classes and modules:
|
|
19
|
+
|
|
20
|
+
Standalone classes (used via class methods or instances):
|
|
21
|
+
* HTM::SqlBuilder: SQL condition building helpers (class methods)
|
|
22
|
+
* HTM::QueryCache: Query result caching (instantiated as @cache)
|
|
23
|
+
|
|
24
|
+
Included modules:
|
|
25
|
+
* RelevanceScorer: Dynamic relevance scoring
|
|
26
|
+
* NodeOperations: Node CRUD operations
|
|
27
|
+
* RobotOperations: Robot registration and activity
|
|
28
|
+
* TagOperations: Tag management
|
|
29
|
+
* VectorSearch: Vector similarity search
|
|
30
|
+
* FulltextSearch: Full-text search
|
|
31
|
+
* HybridSearch: Combined search strategies
|
|
32
|
+
|
|
16
33
|
|
|
17
34
|
# Attributes
|
|
18
35
|
## query_timeout[RW] {: #attribute-i-query_timeout }
|
|
@@ -20,104 +37,11 @@ Returns the value of attribute query_timeout.
|
|
|
20
37
|
|
|
21
38
|
|
|
22
39
|
# Instance Methods
|
|
23
|
-
## add(content:, token_count:0, robot_id:, embedding:nil, metadata:{}) {: #method-i-add }
|
|
24
|
-
Add a node to long-term memory (with deduplication)
|
|
25
|
-
|
|
26
|
-
If content already exists (by content_hash), links the robot to the existing
|
|
27
|
-
node and updates timestamps. Otherwise creates a new node.
|
|
28
|
-
|
|
29
|
-
**`@param`** [String] Conversation message/utterance
|
|
30
|
-
|
|
31
|
-
**`@param`** [Integer] Token count
|
|
32
|
-
|
|
33
|
-
**`@param`** [Integer] Robot identifier
|
|
34
|
-
|
|
35
|
-
**`@param`** [Array<Float>, nil] Pre-generated embedding vector
|
|
36
|
-
|
|
37
|
-
**`@param`** [Hash] Flexible metadata for the node (default: {})
|
|
38
|
-
|
|
39
|
-
**`@return`** [Hash] { node_id:, is_new:, robot_node: }
|
|
40
|
-
|
|
41
|
-
## add_tag(node_id:, tag:) {: #method-i-add_tag }
|
|
42
|
-
Add a tag to a node
|
|
43
|
-
|
|
44
|
-
**`@param`** [Integer] Node database ID
|
|
45
|
-
|
|
46
|
-
**`@param`** [String] Tag name
|
|
47
|
-
|
|
48
|
-
**`@return`** [void]
|
|
49
|
-
|
|
50
|
-
## batch_load_node_tags(node_ids) {: #method-i-batch_load_node_tags }
|
|
51
|
-
Batch load tags for multiple nodes (avoids N+1 queries)
|
|
52
|
-
|
|
53
|
-
**`@param`** [Array<Integer>] Node database IDs
|
|
54
|
-
|
|
55
|
-
**`@return`** [Hash<Integer, Array<String>>] Map of node_id to array of tag names
|
|
56
|
-
|
|
57
|
-
## calculate_relevance(node:, query_tags:[], vector_similarity:nil, node_tags:nil) {: #method-i-calculate_relevance }
|
|
58
|
-
Calculate dynamic relevance score for a node given query context
|
|
59
|
-
|
|
60
|
-
Combines multiple signals:
|
|
61
|
-
* Vector similarity (semantic match)
|
|
62
|
-
* Tag overlap (categorical match)
|
|
63
|
-
* Recency (freshness)
|
|
64
|
-
* Access frequency (popularity/utility)
|
|
65
|
-
|
|
66
|
-
**`@param`** [Hash] Node data with similarity, tags, created_at, access_count
|
|
67
|
-
|
|
68
|
-
**`@param`** [Array<String>] Tags associated with the query
|
|
69
|
-
|
|
70
|
-
**`@param`** [Float, nil] Pre-computed vector similarity (0-1)
|
|
71
|
-
|
|
72
|
-
**`@param`** [Array<String>, nil] Pre-loaded tags for this node (avoids N+1 query)
|
|
73
|
-
|
|
74
|
-
**`@return`** [Float] Composite relevance score (0-10)
|
|
75
|
-
|
|
76
40
|
## clear_cache!() {: #method-i-clear_cache! }
|
|
77
|
-
Clear the query cache
|
|
78
|
-
|
|
79
|
-
Call this after any operation that modifies data (soft delete, restore, etc.)
|
|
80
|
-
to ensure subsequent queries see fresh results.
|
|
81
|
-
|
|
82
|
-
**`@return`** [void]
|
|
83
|
-
|
|
84
|
-
## delete(node_id) {: #method-i-delete }
|
|
85
|
-
Delete a node
|
|
86
|
-
|
|
87
|
-
**`@param`** [Integer] Node database ID
|
|
41
|
+
Clear the query result cache
|
|
88
42
|
|
|
89
43
|
**`@return`** [void]
|
|
90
44
|
|
|
91
|
-
## exists?(node_id) {: #method-i-exists? }
|
|
92
|
-
Check if a node exists
|
|
93
|
-
|
|
94
|
-
**`@param`** [Integer] Node database ID
|
|
95
|
-
|
|
96
|
-
**`@return`** [Boolean] True if node exists
|
|
97
|
-
|
|
98
|
-
## find_query_matching_tags(query, include_extracted:false) {: #method-i-find_query_matching_tags }
|
|
99
|
-
Find tags that match terms in the query
|
|
100
|
-
|
|
101
|
-
Searches the tags table for tags where any hierarchy level matches query
|
|
102
|
-
words. For example, query "PostgreSQL database" would match tags like
|
|
103
|
-
"database:postgresql", "database:sql", etc. Find tags matching a query using
|
|
104
|
-
semantic extraction
|
|
105
|
-
|
|
106
|
-
**`@param`** [String] Search query
|
|
107
|
-
|
|
108
|
-
**`@param`** [Boolean] If true, returns hash with :extracted and :matched keys
|
|
109
|
-
|
|
110
|
-
**`@return`** [Array<String>] Matching tag names (default)
|
|
111
|
-
|
|
112
|
-
**`@return`** [Hash] If include_extracted: { extracted: [...], matched: [...] }
|
|
113
|
-
|
|
114
|
-
## get_node_tags(node_id) {: #method-i-get_node_tags }
|
|
115
|
-
Get tags for a specific node
|
|
116
|
-
|
|
117
|
-
**`@param`** [Integer] Node database ID
|
|
118
|
-
|
|
119
|
-
**`@return`** [Array<String>] Tag names
|
|
120
|
-
|
|
121
45
|
## initialize(config, pool_size:nil, query_timeout:DEFAULT_QUERY_TIMEOUT, cache_size:DEFAULT_CACHE_SIZE, cache_ttl:DEFAULT_CACHE_TTL) {: #method-i-initialize }
|
|
122
46
|
Initialize long-term memory storage
|
|
123
47
|
|
|
@@ -146,160 +70,9 @@ ltm = LongTermMemory.new(config, cache_size: 500, cache_ttl: 600)
|
|
|
146
70
|
```ruby
|
|
147
71
|
ltm = LongTermMemory.new(config, cache_size: 0)
|
|
148
72
|
```
|
|
149
|
-
## link_robot_to_node(robot_id:, node:, working_memory:false) {: #method-i-link_robot_to_node }
|
|
150
|
-
Link a robot to a node (create or update robot_node record)
|
|
151
|
-
|
|
152
|
-
**`@param`** [Integer] Robot ID
|
|
153
|
-
|
|
154
|
-
**`@param`** [HTM::Models::Node] Node to link
|
|
155
|
-
|
|
156
|
-
**`@param`** [Boolean] Whether node is in working memory (default: false)
|
|
157
|
-
|
|
158
|
-
**`@return`** [HTM::Models::RobotNode] The robot_node link record
|
|
159
|
-
|
|
160
|
-
## mark_evicted(robot_id:, node_ids:) {: #method-i-mark_evicted }
|
|
161
|
-
Mark nodes as evicted from working memory
|
|
162
|
-
|
|
163
|
-
Sets working_memory = false on the robot_nodes join table for the specified
|
|
164
|
-
robot and node IDs.
|
|
165
|
-
|
|
166
|
-
**`@param`** [Integer] Robot ID whose working memory is being evicted
|
|
167
|
-
|
|
168
|
-
**`@param`** [Array<Integer>] Node IDs to mark as evicted
|
|
169
|
-
|
|
170
|
-
**`@return`** [void]
|
|
171
|
-
|
|
172
|
-
## node_topics(node_id) {: #method-i-node_topics }
|
|
173
|
-
Get topics for a specific node
|
|
174
|
-
|
|
175
|
-
**`@param`** [Integer] Node database ID
|
|
176
|
-
|
|
177
|
-
**`@return`** [Array<String>] Topic paths
|
|
178
|
-
|
|
179
|
-
## nodes_by_topic(topic_path, exact:false, limit:50) {: #method-i-nodes_by_topic }
|
|
180
|
-
Retrieve nodes by ontological topic
|
|
181
|
-
|
|
182
|
-
**`@param`** [String] Topic hierarchy path
|
|
183
|
-
|
|
184
|
-
**`@param`** [Boolean] Exact match or prefix match
|
|
185
|
-
|
|
186
|
-
**`@param`** [Integer] Maximum results
|
|
187
|
-
|
|
188
|
-
**`@return`** [Array<Hash>] Matching nodes
|
|
189
|
-
|
|
190
|
-
## ontology_structure() {: #method-i-ontology_structure }
|
|
191
|
-
Get ontology structure view
|
|
192
|
-
|
|
193
|
-
**`@return`** [Array<Hash>] Ontology structure
|
|
194
|
-
|
|
195
73
|
## pool_size() {: #method-i-pool_size }
|
|
196
74
|
For backwards compatibility with tests/code that expect pool_size
|
|
197
75
|
|
|
198
|
-
## popular_tags(limit:20, timeframe:nil) {: #method-i-popular_tags }
|
|
199
|
-
Get most popular tags
|
|
200
|
-
|
|
201
|
-
**`@param`** [Integer] Number of tags to return
|
|
202
|
-
|
|
203
|
-
**`@param`** [Range, nil] Optional time range filter
|
|
204
|
-
|
|
205
|
-
**`@return`** [Array<Hash>] Tags with usage counts
|
|
206
|
-
|
|
207
|
-
## register_robot(robot_name) {: #method-i-register_robot }
|
|
208
|
-
Register a robot
|
|
209
|
-
|
|
210
|
-
**`@param`** [String] Robot identifier
|
|
211
|
-
|
|
212
|
-
**`@param`** [String] Robot name
|
|
213
|
-
|
|
214
|
-
**`@return`** [void]
|
|
215
|
-
|
|
216
|
-
## retrieve(node_id) {: #method-i-retrieve }
|
|
217
|
-
Retrieve a node by ID
|
|
218
|
-
|
|
219
|
-
Automatically tracks access by incrementing access_count and updating
|
|
220
|
-
last_accessed
|
|
221
|
-
|
|
222
|
-
**`@param`** [Integer] Node database ID
|
|
223
|
-
|
|
224
|
-
**`@return`** [Hash, nil] Node data or nil
|
|
225
|
-
|
|
226
|
-
## search(timeframe:, query:, limit:, embedding_service:, metadata:{}) {: #method-i-search }
|
|
227
|
-
Vector similarity search
|
|
228
|
-
|
|
229
|
-
**`@param`** [nil, Range, Array<Range>] Time range(s) to search (nil = no filter)
|
|
230
|
-
|
|
231
|
-
**`@param`** [String] Search query
|
|
232
|
-
|
|
233
|
-
**`@param`** [Integer] Maximum results
|
|
234
|
-
|
|
235
|
-
**`@param`** [Object] Service to generate embeddings
|
|
236
|
-
|
|
237
|
-
**`@param`** [Hash] Filter by metadata fields (default: {})
|
|
238
|
-
|
|
239
|
-
**`@return`** [Array<Hash>] Matching nodes
|
|
240
|
-
|
|
241
|
-
## search_by_tags(tags:, match_all:false, timeframe:nil, limit:20) {: #method-i-search_by_tags }
|
|
242
|
-
Search nodes by tags
|
|
243
|
-
|
|
244
|
-
**`@param`** [Array<String>] Tags to search for
|
|
245
|
-
|
|
246
|
-
**`@param`** [Boolean] If true, match ALL tags; if false, match ANY tag
|
|
247
|
-
|
|
248
|
-
**`@param`** [Range, nil] Optional time range filter
|
|
249
|
-
|
|
250
|
-
**`@param`** [Integer] Maximum results
|
|
251
|
-
|
|
252
|
-
**`@return`** [Array<Hash>] Matching nodes with relevance scores
|
|
253
|
-
|
|
254
|
-
## search_fulltext(timeframe:, query:, limit:, metadata:{}) {: #method-i-search_fulltext }
|
|
255
|
-
Full-text search
|
|
256
|
-
|
|
257
|
-
**`@param`** [Range] Time range to search
|
|
258
|
-
|
|
259
|
-
**`@param`** [String] Search query
|
|
260
|
-
|
|
261
|
-
**`@param`** [Integer] Maximum results
|
|
262
|
-
|
|
263
|
-
**`@param`** [Hash] Filter by metadata fields (default: {})
|
|
264
|
-
|
|
265
|
-
**`@return`** [Array<Hash>] Matching nodes
|
|
266
|
-
|
|
267
|
-
## search_hybrid(timeframe:, query:, limit:, embedding_service:, prefilter_limit:100, metadata:{}) {: #method-i-search_hybrid }
|
|
268
|
-
Hybrid search (full-text + vector)
|
|
269
|
-
|
|
270
|
-
**`@param`** [Range] Time range to search
|
|
271
|
-
|
|
272
|
-
**`@param`** [String] Search query
|
|
273
|
-
|
|
274
|
-
**`@param`** [Integer] Maximum results
|
|
275
|
-
|
|
276
|
-
**`@param`** [Object] Service to generate embeddings
|
|
277
|
-
|
|
278
|
-
**`@param`** [Integer] Candidates to consider (default: 100)
|
|
279
|
-
|
|
280
|
-
**`@param`** [Hash] Filter by metadata fields (default: {})
|
|
281
|
-
|
|
282
|
-
**`@return`** [Array<Hash>] Matching nodes
|
|
283
|
-
|
|
284
|
-
## search_with_relevance(timeframe:, query:nil, query_tags:[], limit:20, embedding_service:nil, metadata:{}) {: #method-i-search_with_relevance }
|
|
285
|
-
Search with dynamic relevance scoring
|
|
286
|
-
|
|
287
|
-
Returns nodes with calculated relevance scores based on query context
|
|
288
|
-
|
|
289
|
-
**`@param`** [nil, Range, Array<Range>] Time range(s) to search (nil = no filter)
|
|
290
|
-
|
|
291
|
-
**`@param`** [String, nil] Search query
|
|
292
|
-
|
|
293
|
-
**`@param`** [Array<String>] Tags to match
|
|
294
|
-
|
|
295
|
-
**`@param`** [Integer] Maximum results
|
|
296
|
-
|
|
297
|
-
**`@param`** [Object, nil] Service to generate embeddings
|
|
298
|
-
|
|
299
|
-
**`@param`** [Hash] Filter by metadata fields (default: {})
|
|
300
|
-
|
|
301
|
-
**`@return`** [Array<Hash>] Nodes with relevance scores
|
|
302
|
-
|
|
303
76
|
## shutdown() {: #method-i-shutdown }
|
|
304
77
|
Shutdown - no-op with ActiveRecord (connection pool managed by ActiveRecord)
|
|
305
78
|
|
|
@@ -308,35 +81,3 @@ Get memory statistics
|
|
|
308
81
|
|
|
309
82
|
**`@return`** [Hash] Statistics
|
|
310
83
|
|
|
311
|
-
## topic_relationships(min_shared_nodes:2, limit:50) {: #method-i-topic_relationships }
|
|
312
|
-
Get topic relationships (co-occurrence)
|
|
313
|
-
|
|
314
|
-
**`@param`** [Integer] Minimum shared nodes
|
|
315
|
-
|
|
316
|
-
**`@param`** [Integer] Maximum relationships
|
|
317
|
-
|
|
318
|
-
**`@return`** [Array<Hash>] Topic relationships
|
|
319
|
-
|
|
320
|
-
## track_access(node_ids) {: #method-i-track_access }
|
|
321
|
-
Track access for multiple nodes (bulk operation)
|
|
322
|
-
|
|
323
|
-
Updates access_count and last_accessed for all nodes in the array
|
|
324
|
-
|
|
325
|
-
**`@param`** [Array<Integer>] Node IDs that were accessed
|
|
326
|
-
|
|
327
|
-
**`@return`** [void]
|
|
328
|
-
|
|
329
|
-
## update_last_accessed(node_id) {: #method-i-update_last_accessed }
|
|
330
|
-
Update last_accessed timestamp
|
|
331
|
-
|
|
332
|
-
**`@param`** [Integer] Node database ID
|
|
333
|
-
|
|
334
|
-
**`@return`** [void]
|
|
335
|
-
|
|
336
|
-
## update_robot_activity(robot_id) {: #method-i-update_robot_activity }
|
|
337
|
-
Update robot activity timestamp
|
|
338
|
-
|
|
339
|
-
**`@param`** [String] Robot identifier
|
|
340
|
-
|
|
341
|
-
**`@return`** [void]
|
|
342
|
-
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Exception: HTM::PropositionError
|
|
2
|
+
**Inherits:** HTM::Error
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Raised when proposition extraction fails
|
|
6
|
+
|
|
7
|
+
Common causes:
|
|
8
|
+
* LLM provider API errors
|
|
9
|
+
* Invalid proposition response format
|
|
10
|
+
* Network connectivity issues
|
|
11
|
+
* Model not available
|
|
12
|
+
|
|
13
|
+
Note: This error is distinct from CircuitBreakerOpenError. PropositionError
|
|
14
|
+
indicates a single failure, while CircuitBreakerOpenError indicates repeated
|
|
15
|
+
failures have triggered protective circuit breaking.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|