robot_lab 0.2.8 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +65 -0
  3. data/README.md +16 -18
  4. data/lib/robot_lab/ask_user.rb +3 -3
  5. data/lib/robot_lab/config/defaults.yml +5 -5
  6. data/lib/robot_lab/config.rb +2 -2
  7. data/lib/robot_lab/mcp/transports/streamable_http.rb +2 -4
  8. data/lib/robot_lab/memory.rb +16 -7
  9. data/lib/robot_lab/robot/hooking.rb +26 -0
  10. data/lib/robot_lab/robot/result_building.rb +119 -0
  11. data/lib/robot_lab/robot.rb +37 -120
  12. data/lib/robot_lab/run_config.rb +52 -20
  13. data/lib/robot_lab/tool.rb +7 -12
  14. data/lib/robot_lab/version.rb +1 -1
  15. data/lib/robot_lab.rb +3 -3
  16. metadata +15 -274
  17. data/.architecture/AGENTS.md +0 -32
  18. data/.architecture/config.yml +0 -8
  19. data/.architecture/members.yml +0 -60
  20. data/.architecture/reviews/feature-free-will.md +0 -490
  21. data/.architecture/reviews/overall-codebase.md +0 -427
  22. data/.claude/settings.local.json +0 -57
  23. data/.codex/config.toml +0 -2
  24. data/.envrc +0 -6
  25. data/.github/workflows/deploy-github-pages.yml +0 -52
  26. data/.irbrc +0 -6
  27. data/.loki +0 -65
  28. data/.quality/reek_baseline.txt +0 -43
  29. data/.rubocop.yml +0 -10
  30. data/Archspec.rb +0 -44
  31. data/CLAUDE.md +0 -139
  32. data/COMMITS.md +0 -196
  33. data/Rakefile +0 -193
  34. data/_typos.toml +0 -21
  35. data/agent2agent_review.md +0 -192
  36. data/agentf_improvements.md +0 -253
  37. data/agents.md +0 -14
  38. data/docs/api/core/index.md +0 -147
  39. data/docs/api/core/memory.md +0 -578
  40. data/docs/api/core/network.md +0 -553
  41. data/docs/api/core/result.md +0 -211
  42. data/docs/api/core/robot.md +0 -1667
  43. data/docs/api/core/state.md +0 -145
  44. data/docs/api/core/tool.md +0 -520
  45. data/docs/api/errors.md +0 -323
  46. data/docs/api/hooks.md +0 -469
  47. data/docs/api/index.md +0 -137
  48. data/docs/api/mcp/client.md +0 -387
  49. data/docs/api/mcp/index.md +0 -267
  50. data/docs/api/mcp/server.md +0 -252
  51. data/docs/api/mcp/transports.md +0 -339
  52. data/docs/api/messages/index.md +0 -126
  53. data/docs/api/messages/text-message.md +0 -170
  54. data/docs/api/messages/tool-call-message.md +0 -206
  55. data/docs/api/messages/tool-result-message.md +0 -242
  56. data/docs/api/messages/user-message.md +0 -232
  57. data/docs/api/skills.md +0 -423
  58. data/docs/api/streaming/context.md +0 -280
  59. data/docs/api/streaming/events.md +0 -185
  60. data/docs/api/streaming/index.md +0 -156
  61. data/docs/api/support.md +0 -846
  62. data/docs/architecture/core-concepts.md +0 -575
  63. data/docs/architecture/index.md +0 -252
  64. data/docs/architecture/message-flow.md +0 -366
  65. data/docs/architecture/network-orchestration.md +0 -478
  66. data/docs/architecture/robot-execution.md +0 -396
  67. data/docs/architecture/state-management.md +0 -410
  68. data/docs/assets/css/custom.css +0 -56
  69. data/docs/assets/images/robot_lab.jpg +0 -0
  70. data/docs/concepts.md +0 -641
  71. data/docs/examples/basic-chat.md +0 -258
  72. data/docs/examples/index.md +0 -425
  73. data/docs/examples/mcp-server.md +0 -403
  74. data/docs/examples/multi-robot-network.md +0 -476
  75. data/docs/examples/tool-usage.md +0 -468
  76. data/docs/getting-started/configuration.md +0 -645
  77. data/docs/getting-started/index.md +0 -56
  78. data/docs/getting-started/installation.md +0 -200
  79. data/docs/getting-started/quick-start.md +0 -293
  80. data/docs/guides/building-robots.md +0 -1187
  81. data/docs/guides/creating-networks.md +0 -736
  82. data/docs/guides/hooks.md +0 -1206
  83. data/docs/guides/index.md +0 -78
  84. data/docs/guides/knowledge.md +0 -219
  85. data/docs/guides/mcp-integration.md +0 -740
  86. data/docs/guides/memory.md +0 -458
  87. data/docs/guides/observability.md +0 -733
  88. data/docs/guides/streaming.md +0 -323
  89. data/docs/guides/using-tools.md +0 -780
  90. data/docs/index.md +0 -280
  91. data/docs/superpowers/plans/2026-05-06-agentskills.md +0 -1303
  92. data/docs/superpowers/specs/2026-05-06-agentskills-design.md +0 -247
  93. data/examples/.envrc +0 -1
  94. data/examples/01_simple_robot.rb +0 -31
  95. data/examples/02_tools.rb +0 -109
  96. data/examples/03_network.rb +0 -118
  97. data/examples/04_mcp.rb +0 -215
  98. data/examples/05_streaming.rb +0 -137
  99. data/examples/06_prompt_templates.rb +0 -325
  100. data/examples/07_network_memory.rb +0 -313
  101. data/examples/08_llm_config.rb +0 -162
  102. data/examples/09_chaining.rb +0 -251
  103. data/examples/10_memory.rb +0 -315
  104. data/examples/11_network_introspection.rb +0 -239
  105. data/examples/12_message_bus.rb +0 -67
  106. data/examples/13_spawn.rb +0 -85
  107. data/examples/14_rusty_circuit/.envrc +0 -1
  108. data/examples/14_rusty_circuit/.gitignore +0 -1
  109. data/examples/14_rusty_circuit/README.md +0 -1
  110. data/examples/14_rusty_circuit/comic.rb +0 -149
  111. data/examples/14_rusty_circuit/display.rb +0 -217
  112. data/examples/14_rusty_circuit/heckler.rb +0 -65
  113. data/examples/14_rusty_circuit/open_mic.rb +0 -132
  114. data/examples/14_rusty_circuit/prompts/open_mic_comic.md +0 -20
  115. data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +0 -23
  116. data/examples/14_rusty_circuit/prompts/open_mic_scout.md +0 -20
  117. data/examples/14_rusty_circuit/scout.rb +0 -165
  118. data/examples/14_rusty_circuit/show.log +0 -234
  119. data/examples/15_memory_network_and_bus/.envrc +0 -1
  120. data/examples/15_memory_network_and_bus/editor_in_chief.rb +0 -24
  121. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +0 -213
  122. data/examples/15_memory_network_and_bus/linux_writer.rb +0 -80
  123. data/examples/15_memory_network_and_bus/os_editor.rb +0 -48
  124. data/examples/15_memory_network_and_bus/os_writer.rb +0 -49
  125. data/examples/15_memory_network_and_bus/output/combined_article.md +0 -13
  126. data/examples/15_memory_network_and_bus/output/final_article.md +0 -13
  127. data/examples/15_memory_network_and_bus/output/linux_draft.md +0 -7
  128. data/examples/15_memory_network_and_bus/output/mac_draft.md +0 -7
  129. data/examples/15_memory_network_and_bus/output/memory.json +0 -13
  130. data/examples/15_memory_network_and_bus/output/revision_1.md +0 -18
  131. data/examples/15_memory_network_and_bus/output/revision_2.md +0 -13
  132. data/examples/15_memory_network_and_bus/output/windows_draft.md +0 -7
  133. data/examples/15_memory_network_and_bus/prompts/os_advocate.md +0 -13
  134. data/examples/15_memory_network_and_bus/prompts/os_chief.md +0 -13
  135. data/examples/15_memory_network_and_bus/prompts/os_editor.md +0 -13
  136. data/examples/16_writers_room/.envrc +0 -1
  137. data/examples/16_writers_room/display.rb +0 -158
  138. data/examples/16_writers_room/output/.gitignore +0 -4
  139. data/examples/16_writers_room/output/README.md +0 -69
  140. data/examples/16_writers_room/output/opus_001.md +0 -263
  141. data/examples/16_writers_room/output/opus_001_notes.log +0 -470
  142. data/examples/16_writers_room/output/opus_002.md +0 -245
  143. data/examples/16_writers_room/output/opus_002_notes.log +0 -546
  144. data/examples/16_writers_room/output/opus_002_screenplay.md +0 -7989
  145. data/examples/16_writers_room/output/opus_002_screenplay_notes.md +0 -993
  146. data/examples/16_writers_room/prompts/screenplay_writer.md +0 -66
  147. data/examples/16_writers_room/prompts/writer.md +0 -37
  148. data/examples/16_writers_room/room.rb +0 -186
  149. data/examples/16_writers_room/tools.rb +0 -173
  150. data/examples/16_writers_room/writer.rb +0 -121
  151. data/examples/16_writers_room/writers_room.rb +0 -256
  152. data/examples/17_skills.rb +0 -234
  153. data/examples/18_rails/.envrc +0 -3
  154. data/examples/18_rails/.gitignore +0 -5
  155. data/examples/18_rails/Gemfile +0 -11
  156. data/examples/18_rails/README.md +0 -67
  157. data/examples/18_rails/Rakefile +0 -4
  158. data/examples/18_rails/app/controllers/application_controller.rb +0 -4
  159. data/examples/18_rails/app/controllers/chat_controller.rb +0 -50
  160. data/examples/18_rails/app/jobs/application_job.rb +0 -4
  161. data/examples/18_rails/app/jobs/robot_run_job.rb +0 -25
  162. data/examples/18_rails/app/models/application_record.rb +0 -5
  163. data/examples/18_rails/app/models/robot_lab_result.rb +0 -36
  164. data/examples/18_rails/app/models/robot_lab_thread.rb +0 -23
  165. data/examples/18_rails/app/robots/chat_robot.rb +0 -25
  166. data/examples/18_rails/app/tools/time_tool.rb +0 -9
  167. data/examples/18_rails/app/views/chat/_user_message.html.erb +0 -1
  168. data/examples/18_rails/app/views/chat/index.html.erb +0 -67
  169. data/examples/18_rails/app/views/layouts/application.html.erb +0 -49
  170. data/examples/18_rails/bin/dev +0 -7
  171. data/examples/18_rails/bin/rails +0 -6
  172. data/examples/18_rails/bin/setup +0 -15
  173. data/examples/18_rails/config/application.rb +0 -33
  174. data/examples/18_rails/config/cable.yml +0 -2
  175. data/examples/18_rails/config/database.yml +0 -5
  176. data/examples/18_rails/config/environment.rb +0 -4
  177. data/examples/18_rails/config/initializers/robot_lab.rb +0 -11
  178. data/examples/18_rails/config/routes.rb +0 -6
  179. data/examples/18_rails/config.ru +0 -4
  180. data/examples/18_rails/db/migrate/001_create_robot_lab_tables.rb +0 -32
  181. data/examples/19_token_tracking.rb +0 -138
  182. data/examples/20_circuit_breaker.rb +0 -147
  183. data/examples/21_learning_loop.rb +0 -181
  184. data/examples/22_context_compression.rb +0 -172
  185. data/examples/23_convergence.rb +0 -133
  186. data/examples/24_structured_delegation.rb +0 -151
  187. data/examples/25_history_search/conversation.jsonl +0 -30
  188. data/examples/25_history_search.rb +0 -133
  189. data/examples/26_document_store/api_versioning_adr.md +0 -52
  190. data/examples/26_document_store/incident_postmortem.md +0 -46
  191. data/examples/26_document_store/postgres_runbook.md +0 -49
  192. data/examples/26_document_store/redis_caching_guide.md +0 -48
  193. data/examples/26_document_store/sidekiq_guide.md +0 -51
  194. data/examples/26_document_store.rb +0 -140
  195. data/examples/27_incident_response/incident_response.rb +0 -261
  196. data/examples/28_mcp_discovery.rb +0 -113
  197. data/examples/29_ractor_tools.rb +0 -240
  198. data/examples/30_ractor_network.rb +0 -252
  199. data/examples/31_launch_assessment.rb +0 -246
  200. data/examples/32_newsletter_reader.rb +0 -193
  201. data/examples/33_stock_generator.rb +0 -80
  202. data/examples/33_stock_predictor.rb +0 -327
  203. data/examples/34_agentskills.rb +0 -76
  204. data/examples/35_hooks.rb +0 -266
  205. data/examples/README.md +0 -533
  206. data/examples/common.rb +0 -148
  207. data/examples/prompts/assistant.md +0 -5
  208. data/examples/prompts/audit_trail.md +0 -8
  209. data/examples/prompts/billing.md +0 -10
  210. data/examples/prompts/classifier.md +0 -7
  211. data/examples/prompts/comedian.md +0 -6
  212. data/examples/prompts/comedy_critic.md +0 -10
  213. data/examples/prompts/configurable.md +0 -9
  214. data/examples/prompts/dispatcher.md +0 -12
  215. data/examples/prompts/entity_extractor.md +0 -14
  216. data/examples/prompts/escalation.md +0 -42
  217. data/examples/prompts/frontmatter_mcp_test.md +0 -9
  218. data/examples/prompts/frontmatter_named_test.md +0 -5
  219. data/examples/prompts/frontmatter_tools_test.md +0 -6
  220. data/examples/prompts/general.md +0 -7
  221. data/examples/prompts/github_assistant.md +0 -14
  222. data/examples/prompts/helper.md +0 -4
  223. data/examples/prompts/incident_responder.md +0 -18
  224. data/examples/prompts/keyword_extractor.md +0 -11
  225. data/examples/prompts/llm_config_demo.md +0 -20
  226. data/examples/prompts/order_support.md +0 -35
  227. data/examples/prompts/os_advocate.md +0 -13
  228. data/examples/prompts/os_chief.md +0 -13
  229. data/examples/prompts/os_editor.md +0 -13
  230. data/examples/prompts/parameterized_main_test.md +0 -6
  231. data/examples/prompts/pii_redactor.md +0 -7
  232. data/examples/prompts/product_support.md +0 -37
  233. data/examples/prompts/runbook_protocol.md +0 -12
  234. data/examples/prompts/sentiment_analyzer.md +0 -12
  235. data/examples/prompts/skill_a_test.md +0 -4
  236. data/examples/prompts/skill_b_test.md +0 -4
  237. data/examples/prompts/skill_config_test.md +0 -5
  238. data/examples/prompts/skill_cycle_a_test.md +0 -6
  239. data/examples/prompts/skill_cycle_b_test.md +0 -6
  240. data/examples/prompts/skill_description_test.md +0 -4
  241. data/examples/prompts/skill_leaf_test.md +0 -4
  242. data/examples/prompts/skill_nested_test.md +0 -6
  243. data/examples/prompts/skill_refs_main_test.md +0 -6
  244. data/examples/prompts/skill_self_ref_test.md +0 -6
  245. data/examples/prompts/skill_with_mcp_test.md +0 -9
  246. data/examples/prompts/skill_with_params_test.md +0 -6
  247. data/examples/prompts/skill_with_robot_name_test.md +0 -5
  248. data/examples/prompts/skill_with_tools_test.md +0 -6
  249. data/examples/prompts/sre_compliance.md +0 -10
  250. data/examples/prompts/structured_output.md +0 -7
  251. data/examples/prompts/synthesizer.md +0 -17
  252. data/examples/prompts/technical.md +0 -10
  253. data/examples/prompts/template_with_skills_test.md +0 -6
  254. data/examples/prompts/triage.md +0 -22
  255. data/examples/ruboruby.md +0 -423
  256. data/examples/xyzzy.rb +0 -97
  257. data/logfile +0 -8
  258. data/mkdocs.yml +0 -209
  259. data/robot_concurrency.md +0 -38
  260. data/simple_acp_review.md +0 -298
  261. data/temp.md +0 -6
  262. data/tool_manifest_plan.md +0 -155
data/docs/guides/index.md DELETED
@@ -1,78 +0,0 @@
1
- # Guides
2
-
3
- Practical guides for building applications with RobotLab.
4
-
5
- ## Getting Started
6
-
7
- If you're new to RobotLab, start here:
8
-
9
- <div class="grid cards" markdown>
10
-
11
- - [:octicons-cpu-24: **Building Robots**](building-robots.md)
12
-
13
- Create specialized AI agents with personalities and tools
14
-
15
- - [:octicons-git-branch-24: **Creating Networks**](creating-networks.md)
16
-
17
- Orchestrate multiple robots for complex workflows
18
-
19
- </div>
20
-
21
- ## Core Features
22
-
23
- <div class="grid cards" markdown>
24
-
25
- - [:octicons-tools-24: **Using Tools**](using-tools.md)
26
-
27
- Give robots custom capabilities to interact with external systems
28
-
29
- - [:octicons-server-24: **MCP Integration**](mcp-integration.md)
30
-
31
- Connect to Model Context Protocol servers
32
-
33
- - [:octicons-broadcast-24: **Streaming Responses**](streaming.md)
34
-
35
- Real-time streaming of LLM responses
36
-
37
- - [:octicons-cpu-24: **Memory System**](memory.md)
38
-
39
- Share data between robots with the memory system
40
-
41
- - [:octicons-pulse-24: **Observability & Safety**](observability.md)
42
-
43
- Token tracking, circuit breakers, doom loop detection, auto compaction, and learning accumulation
44
-
45
- - [:octicons-zap-24: **Hook System**](hooks.md)
46
-
47
- Lifecycle hooks for instrumentation, response caching, extensions, and cross-cutting concerns
48
-
49
- - [:octicons-search-24: **Knowledge & Retrieval**](knowledge.md)
50
-
51
- Chat history search and embedding-based document store for RAG workflows
52
-
53
- </div>
54
-
55
- ## Guide Index
56
-
57
- | Guide | Description | Time |
58
- |-------|-------------|------|
59
- | [Building Robots](building-robots.md) | Create and configure robots | 10 min |
60
- | [Creating Networks](creating-networks.md) | Multi-robot orchestration | 15 min |
61
- | [Using Tools](using-tools.md) | Add custom capabilities | 10 min |
62
- | [MCP Integration](mcp-integration.md) | External tool servers | 10 min |
63
- | [Streaming](streaming.md) | Real-time responses | 5 min |
64
- | [Memory](memory.md) | Shared data store | 5 min |
65
- | [Observability & Safety](observability.md) | Token tracking, circuit breaker, doom loop detection, auto compaction, learning loop | 10 min |
66
- | [Hook System](hooks.md) | Lifecycle hooks, extensions, response caching, instrumentation | 15 min |
67
- | [Knowledge & Retrieval](knowledge.md) | Chat history search and embedding-based document store (RAG) | 10 min |
68
-
69
- ## Extension Gems
70
-
71
- Additional capabilities are available as separate gems:
72
-
73
- | Gem | Description | Docs |
74
- |-----|-------------|------|
75
- | [robot_lab-rails](https://github.com/MadBomber/robot_lab-rails) | Rails generators, background jobs, Turbo Stream broadcasting | [Rails Integration guide](https://github.com/MadBomber/robot_lab-rails/blob/main/docs/guides/rails-integration.md) |
76
- | [robot_lab-ractor](https://github.com/MadBomber/robot_lab-ractor) | True CPU parallelism for tools and robot pipelines via Ruby Ractors | [Ractor Parallelism guide](https://github.com/MadBomber/robot_lab-ractor/blob/main/docs/guides/ractor-parallelism.md) |
77
- | [robot_lab-durable](https://github.com/MadBomber/robot_lab-durable) | Cross-session knowledge persistence with YAML-backed storage | [robot_lab-durable README](https://github.com/MadBomber/robot_lab-durable) |
78
- | [robot_lab-document_store](https://github.com/MadBomber/robot_lab-document_store) | Embedding-based semantic document search via fastembed | [robot_lab-document_store README](https://github.com/MadBomber/robot_lab-document_store) |
@@ -1,219 +0,0 @@
1
- # Knowledge & Retrieval
2
-
3
- Facilities for searching and retrieving knowledge from a robot's history and from external documents:
4
-
5
- - **Chat History Search** — semantic search over accumulated conversation turns
6
- - **Embedding-Based Document Store** — lightweight RAG: store arbitrary text, search by meaning
7
-
8
- ---
9
-
10
- ## Chat History Search
11
-
12
- ### The Problem
13
-
14
- Long-running robots accumulate many conversation turns. When you need to recall what was discussed earlier on a specific topic, re-sending the full history wastes tokens. `search_history` gives you a focused slice of the most relevant past messages without touching the LLM.
15
-
16
- ### robot.search_history
17
-
18
- ```ruby
19
- results = robot.search_history(query, limit: 5)
20
- ```
21
-
22
- Scores every message in the robot's conversation history against `query` using stemmed term-frequency cosine similarity (via the `classifier` gem). Returns up to `limit` `HistoryResult` objects sorted by score descending.
23
-
24
- > [!NOTE]
25
- > **Every** message in `@chat.messages` is scored — there is no role filter.
26
- > Results routinely include the `:system` prompt and raw `:tool` result payloads
27
- > (often JSON) alongside `:user` and `:assistant` turns. Filter by role yourself
28
- > if you only want the conversation:
29
- >
30
- > ```ruby
31
- > hits = robot.search_history(query, limit: 20)
32
- > .select { |r| %i[user assistant].include?(r.role) }
33
- > .first(3)
34
- > ```
35
-
36
- ```ruby
37
- results = robot.search_history("quarterly revenue", limit: 3)
38
-
39
- results.each do |r|
40
- puts "[#{r.role}] score=#{r.score.round(3)} idx=#{r.index}"
41
- puts " #{r.text}"
42
- end
43
- ```
44
-
45
- ### HistoryResult Fields
46
-
47
- | Field | Type | Description |
48
- |-------|------|-------------|
49
- | `text` | String | The message text |
50
- | `role` | Symbol | The message's role — `:user`, `:assistant`, `:system`, or `:tool` |
51
- | `score` | Float (0.0–1.0) | Cosine similarity with the query |
52
- | `index` | Integer | Position in `@chat.messages` |
53
-
54
- ### Typical Scores
55
-
56
- | Relationship | Typical Score |
57
- |---|---|
58
- | Direct answer to the query | 0.50 – 0.80 |
59
- | Same topic, different phrasing | 0.20 – 0.50 |
60
- | Unrelated | < 0.10 |
61
-
62
- ### Short Messages
63
-
64
- Messages shorter than 20 characters are skipped — they produce no meaningful term vector.
65
-
66
- ### Full Example
67
-
68
- ```ruby
69
- robot = RobotLab.build(name: "analyst", system_prompt: "You are a financial analyst.")
70
-
71
- # … after several robot.run() calls …
72
-
73
- hits = robot.search_history("customer acquisition cost")
74
- hits.each { |r| puts "#{r.role} (#{r.score.round(2)}): #{r.text}" }
75
- ```
76
-
77
- ### RAG Pattern — Retrieve Then Generate
78
-
79
- Use `search_history` to inject only the relevant past context into the next call:
80
-
81
- ```ruby
82
- hits = robot.search_history(user_query, limit: 3)
83
- context = hits.map(&:text).join("\n")
84
-
85
- robot.run("Recall context:\n#{context}\n\nNew question: #{user_query}")
86
- ```
87
-
88
- ### Optional Dependency
89
-
90
- `search_history` requires the `classifier` gem:
91
-
92
- ```ruby
93
- gem "classifier", "~> 2.3"
94
- ```
95
-
96
- Without it, calling `search_history` raises `RobotLab::DependencyError` with an install hint.
97
-
98
- ---
99
-
100
- ## Embedding-Based Document Store
101
-
102
- ### The Problem
103
-
104
- Sometimes the knowledge you need isn't in the conversation history — it's in a README, a product spec, a changelog. `store_document` / `search_documents` embed arbitrary text and retrieve the most relevant chunk at query time. Embeddings come from `fastembed` when it is installed, and from a built-in TF-IDF fallback when it is not (see [Embedding Model](#embedding-model)).
105
-
106
- ### memory.store_document / memory.search_documents
107
-
108
- ```ruby
109
- memory.store_document(:readme, File.read("README.md"))
110
- memory.store_document(:changelog, File.read("CHANGELOG.md"))
111
-
112
- hits = memory.search_documents("how to configure redis", limit: 3)
113
- hits.each { |h| puts "#{h[:key]} (#{h[:score].round(3)}): #{h[:text][0..80]}" }
114
- ```
115
-
116
- Each result hash contains:
117
-
118
- | Key | Type | Description |
119
- |-----|------|-------------|
120
- | `:key` | Symbol | The key the document was stored under |
121
- | `:text` | String | The full stored text |
122
- | `:score` | Float (0.0–1.0) | Cosine similarity with the query |
123
-
124
- ### Standalone DocumentStore
125
-
126
- The `Memory` methods delegate to `RobotLab::DocumentStore`, which can also be used directly:
127
-
128
- ```ruby
129
- store = RobotLab::DocumentStore.new
130
- store.store(:doc_a, "Ruby on Rails is a full-stack web framework.")
131
- store.store(:doc_b, "Postgres is an advanced relational database.")
132
-
133
- results = store.search("relational database SQL", limit: 2)
134
- puts results.first[:key] # => :doc_b
135
- ```
136
-
137
- Management methods:
138
-
139
- ```ruby
140
- store.size # => 2
141
- store.keys # => [:doc_a, :doc_b]
142
- store.empty? # => false
143
- store.delete(:doc_a)
144
- store.clear
145
- ```
146
-
147
- ### Embedding Model
148
-
149
- Default: `BAAI/bge-small-en-v1.5` (~23 MB, downloaded on first use, cached in `~/.cache/fastembed/`).
150
-
151
- Documents and queries are embedded asymmetrically: stored text goes through `Fastembed::TextEmbedding#passage_embed`, query text through `#query_embed`. RobotLab does **not** prepend any literal `"passage: "` / `"query: "` string of its own — it hands the raw text to the two methods and lets fastembed handle whatever instruction prefixing the model expects.
152
-
153
- Custom model:
154
-
155
- ```ruby
156
- store = RobotLab::DocumentStore.new(model_name: "BAAI/bge-base-en-v1.5")
157
- ```
158
-
159
- ### TF-IDF Fallback
160
-
161
- `DocumentStore` decides once, at load time, whether `fastembed` is available
162
- (`RobotLab::DocumentStore::FASTEMBED_AVAILABLE`). When it is **not**, the store
163
- still works — it silently falls back to a stemmed, stop-word-filtered,
164
- L2-normalised term-frequency embedder and compares those sparse vectors by
165
- cosine similarity. Nothing is downloaded and everything runs offline, which
166
- makes it convenient for development and CI.
167
-
168
- > [!WARNING]
169
- > The fallback is **lexical, not semantic**. It matches shared word stems only,
170
- > so a query and a document that mean the same thing in different words score
171
- > `0.0`. There is no error, no warning, and no change to the API — only
172
- > noticeably worse results. Check `RobotLab::DocumentStore::FASTEMBED_AVAILABLE`
173
- > if you need to know which path you are on, and note that `model_name:` is
174
- > ignored entirely when it is `false`.
175
-
176
- ### RAG Pattern
177
-
178
- ```ruby
179
- # 1. Index your knowledge base at startup
180
- memory.store_document(:readme, File.read("README.md"))
181
- memory.store_document(:changelog, File.read("CHANGELOG.md"))
182
- memory.store_document(:api_docs, File.read("docs/api.md"))
183
-
184
- # 2. At query time, retrieve the most relevant chunks
185
- hits = memory.search_documents(user_query, limit: 3)
186
- context = hits.map { |h| h[:text] }.join("\n\n")
187
-
188
- # 3. Pass context to your robot
189
- result = robot.run("Use the following context:\n#{context}\n\nQuestion: #{user_query}")
190
- ```
191
-
192
- ### Memory API Summary
193
-
194
- | Method | Description |
195
- |--------|-------------|
196
- | `memory.store_document(key, text)` | Embed and store a document |
197
- | `memory.search_documents(query, limit: 5)` | Search by semantic similarity |
198
- | `memory.document_keys` | List stored keys |
199
- | `memory.delete_document(key)` | Remove a document |
200
-
201
- ### Dependency
202
-
203
- The embedding-based document store requires the [`robot_lab-document_store`](https://github.com/MadBomber/robot_lab-document_store) extension gem. Add it to your Gemfile:
204
-
205
- ```ruby
206
- gem "robot_lab-document_store"
207
- ```
208
-
209
- The gem uses `fastembed` for ONNX-based embeddings when it is installed: the `BAAI/bge-small-en-v1.5` model (~23 MB) is downloaded on first use and cached in `~/.cache/fastembed/`. If `fastembed` cannot be loaded, `DocumentStore` still works via the lexical [TF-IDF fallback](#tf-idf-fallback).
210
-
211
- Without `robot_lab-document_store` itself loaded, calling `memory.store_document`, `memory.search_documents`, `memory.document_keys`, or `memory.delete_document` raises `RobotLab::DependencyError`.
212
-
213
- ---
214
-
215
- ## See Also
216
-
217
- - [Observability Guide](observability.md)
218
- - [examples/25_history_search.rb](https://github.com/MadBomber/robot_lab/blob/main/examples/25_history_search.rb) — Chat History Search
219
- - [examples/26_document_store.rb](https://github.com/MadBomber/robot_lab/blob/main/examples/26_document_store.rb) — Embedding-Based Document Store