robot_lab 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.architecture/AGENTS.md +32 -0
- data/.architecture/config.yml +8 -0
- data/.architecture/members.yml +60 -0
- data/.architecture/reviews/feature-free-will.md +490 -0
- data/.architecture/reviews/overall-codebase.md +427 -0
- data/.claude/settings.local.json +57 -0
- data/.codex/config.toml +2 -0
- data/.irbrc +2 -2
- data/.rubocop.yml +172 -0
- data/CHANGELOG.md +72 -0
- data/CLAUDE.md +139 -0
- data/README.md +91 -95
- data/Rakefile +109 -3
- data/agent2agent_review.md +192 -0
- data/agentf_improvements.md +253 -0
- data/agents.md +14 -0
- data/docs/examples/index.md +37 -2
- data/docs/getting-started/configuration.md +20 -7
- data/docs/guides/index.md +16 -16
- data/docs/guides/knowledge.md +7 -1
- data/docs/guides/observability.md +132 -0
- data/docs/index.md +30 -3
- data/docs/superpowers/plans/2026-05-06-agentskills.md +1303 -0
- data/docs/superpowers/specs/2026-05-06-agentskills-design.md +247 -0
- data/examples/.envrc +1 -0
- data/examples/01_simple_robot.rb +5 -9
- data/examples/02_tools.rb +5 -9
- data/examples/03_network.rb +8 -9
- data/examples/04_mcp.rb +21 -29
- data/examples/05_streaming.rb +12 -18
- data/examples/06_prompt_templates.rb +11 -19
- data/examples/07_network_memory.rb +16 -31
- data/examples/08_llm_config.rb +10 -22
- data/examples/09_chaining.rb +16 -27
- data/examples/10_memory.rb +12 -28
- data/examples/11_network_introspection.rb +15 -29
- data/examples/12_message_bus.rb +5 -12
- data/examples/13_spawn.rb +5 -10
- data/examples/14_rusty_circuit/.envrc +1 -0
- data/examples/14_rusty_circuit/comic.rb +2 -0
- data/examples/14_rusty_circuit/heckler.rb +1 -1
- data/examples/14_rusty_circuit/open_mic.rb +1 -3
- data/examples/14_rusty_circuit/scout.rb +2 -0
- data/examples/15_memory_network_and_bus/.envrc +1 -0
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +6 -3
- data/examples/15_memory_network_and_bus/linux_writer.rb +1 -1
- data/examples/15_memory_network_and_bus/output/combined_article.md +6 -6
- data/examples/15_memory_network_and_bus/output/final_article.md +6 -8
- data/examples/15_memory_network_and_bus/output/linux_draft.md +4 -2
- data/examples/15_memory_network_and_bus/output/mac_draft.md +3 -3
- data/examples/15_memory_network_and_bus/output/memory.json +6 -6
- data/examples/15_memory_network_and_bus/output/revision_1.md +10 -11
- data/examples/15_memory_network_and_bus/output/revision_2.md +6 -8
- data/examples/15_memory_network_and_bus/output/windows_draft.md +3 -3
- data/examples/16_writers_room/.envrc +1 -0
- data/examples/16_writers_room/writers_room.rb +2 -4
- data/examples/17_skills.rb +8 -17
- data/examples/18_rails/Gemfile +1 -0
- data/examples/19_token_tracking.rb +9 -15
- data/examples/20_circuit_breaker.rb +10 -19
- data/examples/21_learning_loop.rb +11 -20
- data/examples/22_context_compression.rb +6 -13
- data/examples/23_convergence.rb +6 -17
- data/examples/24_structured_delegation.rb +11 -15
- data/examples/25_history_search.rb +5 -12
- data/examples/26_document_store.rb +6 -13
- data/examples/27_incident_response/incident_response.rb +4 -5
- data/examples/28_mcp_discovery.rb +8 -11
- data/examples/29_ractor_tools.rb +4 -9
- data/examples/30_ractor_network.rb +10 -19
- data/examples/31_launch_assessment.rb +10 -23
- data/examples/32_newsletter_reader.rb +188 -0
- data/examples/33_stock_generator.rb +80 -0
- data/examples/33_stock_predictor.rb +306 -0
- data/examples/34_agentskills.rb +72 -0
- data/examples/README.md +1 -1
- data/examples/common.rb +76 -0
- data/examples/ruboruby.md +423 -0
- data/examples/temp.md +51 -0
- data/lib/robot_lab/agent_skill.rb +63 -0
- data/lib/robot_lab/agent_skill_catalog.rb +74 -0
- data/lib/robot_lab/ask_user.rb +2 -2
- data/lib/robot_lab/bus_poller.rb +12 -5
- data/lib/robot_lab/config.rb +1 -12
- data/lib/robot_lab/delegation_future.rb +1 -1
- data/lib/robot_lab/doom_loop_detector.rb +98 -0
- data/lib/robot_lab/history_compressor.rb +4 -10
- data/lib/robot_lab/mcp/client.rb +1 -2
- data/lib/robot_lab/mcp/connection_poller.rb +3 -3
- data/lib/robot_lab/mcp/server.rb +1 -1
- data/lib/robot_lab/mcp/server_discovery.rb +0 -2
- data/lib/robot_lab/memory.rb +32 -27
- data/lib/robot_lab/memory_change.rb +2 -2
- data/lib/robot_lab/message.rb +4 -4
- data/lib/robot_lab/network.rb +11 -6
- data/lib/robot_lab/robot/agent_skill_matching.rb +99 -0
- data/lib/robot_lab/robot/bus_messaging.rb +9 -27
- data/lib/robot_lab/robot/history_search.rb +4 -1
- data/lib/robot_lab/robot/mcp_management.rb +5 -11
- data/lib/robot_lab/robot/template_rendering.rb +60 -40
- data/lib/robot_lab/robot.rb +323 -206
- data/lib/robot_lab/robot_result.rb +6 -5
- data/lib/robot_lab/run_config.rb +5 -11
- data/lib/robot_lab/script_tool.rb +76 -0
- data/lib/robot_lab/state_proxy.rb +7 -5
- data/lib/robot_lab/tool.rb +3 -3
- data/lib/robot_lab/tool_config.rb +1 -1
- data/lib/robot_lab/tool_manifest.rb +5 -7
- data/lib/robot_lab/user_message.rb +2 -2
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab/waiter.rb +1 -1
- data/lib/robot_lab.rb +41 -52
- data/logfile +8 -0
- data/mkdocs.yml +2 -3
- data/robot_concurrency.md +38 -0
- data/simple_acp_review.md +298 -0
- data/site/404.html +2300 -0
- data/site/api/core/index.html +2706 -0
- data/site/api/core/memory/index.html +3793 -0
- data/site/api/core/network/index.html +3500 -0
- data/site/api/core/robot/index.html +4566 -0
- data/site/api/core/state/index.html +3390 -0
- data/site/api/core/tool/index.html +3843 -0
- data/site/api/index.html +2635 -0
- data/site/api/mcp/client/index.html +3435 -0
- data/site/api/mcp/index.html +2783 -0
- data/site/api/mcp/server/index.html +3252 -0
- data/site/api/mcp/transports/index.html +3352 -0
- data/site/api/messages/index.html +2641 -0
- data/site/api/messages/text-message/index.html +3087 -0
- data/site/api/messages/tool-call-message/index.html +3159 -0
- data/site/api/messages/tool-result-message/index.html +3252 -0
- data/site/api/messages/user-message/index.html +3212 -0
- data/site/api/streaming/context/index.html +3282 -0
- data/site/api/streaming/events/index.html +3347 -0
- data/site/api/streaming/index.html +2738 -0
- data/site/architecture/core-concepts/index.html +3757 -0
- data/site/architecture/index.html +2797 -0
- data/site/architecture/message-flow/index.html +3238 -0
- data/site/architecture/network-orchestration/index.html +3433 -0
- data/site/architecture/robot-execution/index.html +3140 -0
- data/site/architecture/state-management/index.html +3498 -0
- data/site/assets/css/custom.css +56 -0
- data/site/assets/images/favicon.png +0 -0
- data/site/assets/images/robot_lab.jpg +0 -0
- data/site/assets/javascripts/bundle.79ae519e.min.js +16 -0
- data/site/assets/javascripts/bundle.79ae519e.min.js.map +7 -0
- data/site/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
- data/site/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
- data/site/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
- data/site/assets/javascripts/lunr/tinyseg.js +206 -0
- data/site/assets/javascripts/lunr/wordcut.js +6708 -0
- data/site/assets/javascripts/workers/search.2c215733.min.js +42 -0
- data/site/assets/javascripts/workers/search.2c215733.min.js.map +7 -0
- data/site/assets/stylesheets/main.484c7ddc.min.css +1 -0
- data/site/assets/stylesheets/main.484c7ddc.min.css.map +1 -0
- data/site/assets/stylesheets/palette.ab4e12ef.min.css +1 -0
- data/site/assets/stylesheets/palette.ab4e12ef.min.css.map +1 -0
- data/site/concepts/index.html +3455 -0
- data/site/examples/basic-chat/index.html +2880 -0
- data/site/examples/index.html +2907 -0
- data/site/examples/mcp-server/index.html +3018 -0
- data/site/examples/multi-robot-network/index.html +3131 -0
- data/site/examples/rails-application/index.html +3329 -0
- data/site/examples/tool-usage/index.html +3085 -0
- data/site/getting-started/configuration/index.html +3745 -0
- data/site/getting-started/index.html +2572 -0
- data/site/getting-started/installation/index.html +2981 -0
- data/site/getting-started/quick-start/index.html +2942 -0
- data/site/guides/building-robots/index.html +4290 -0
- data/site/guides/creating-networks/index.html +3858 -0
- data/site/guides/index.html +2586 -0
- data/site/guides/mcp-integration/index.html +3581 -0
- data/site/guides/memory/index.html +3586 -0
- data/site/guides/rails-integration/index.html +4019 -0
- data/site/guides/streaming/index.html +3157 -0
- data/site/guides/using-tools/index.html +3802 -0
- data/site/index.html +2671 -0
- data/site/search/search_index.json +1 -0
- data/site/sitemap.xml +183 -0
- data/site/sitemap.xml.gz +0 -0
- data/site/tags.json +1 -0
- data/temp.md +6 -0
- data/tool_manifest_plan.md +155 -0
- metadata +154 -92
- data/docs/examples/rails-application.md +0 -419
- data/docs/guides/ractor-parallelism.md +0 -364
- data/docs/guides/rails-integration.md +0 -681
- data/docs/superpowers/plans/2026-04-14-ractor-integration.md +0 -1538
- data/docs/superpowers/specs/2026-04-14-ractor-integration-design.md +0 -258
- data/lib/generators/robot_lab/install_generator.rb +0 -90
- data/lib/generators/robot_lab/job_generator.rb +0 -40
- data/lib/generators/robot_lab/robot_generator.rb +0 -55
- data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -42
- data/lib/generators/robot_lab/templates/job.rb.tt +0 -21
- data/lib/generators/robot_lab/templates/migration.rb.tt +0 -32
- data/lib/generators/robot_lab/templates/result_model.rb.tt +0 -52
- data/lib/generators/robot_lab/templates/robot.rb.tt +0 -31
- data/lib/generators/robot_lab/templates/robot_job.rb.tt +0 -18
- data/lib/generators/robot_lab/templates/robot_test.rb.tt +0 -34
- data/lib/generators/robot_lab/templates/routing_robot.rb.tt +0 -59
- data/lib/generators/robot_lab/templates/thread_model.rb.tt +0 -40
- data/lib/robot_lab/document_store.rb +0 -155
- data/lib/robot_lab/ractor_boundary.rb +0 -42
- data/lib/robot_lab/ractor_job.rb +0 -37
- data/lib/robot_lab/ractor_memory_proxy.rb +0 -85
- data/lib/robot_lab/ractor_network_scheduler.rb +0 -154
- data/lib/robot_lab/ractor_worker_pool.rb +0 -117
- data/lib/robot_lab/rails_integration/engine.rb +0 -29
- data/lib/robot_lab/rails_integration/job.rb +0 -158
- data/lib/robot_lab/rails_integration/railtie.rb +0 -51
- data/lib/robot_lab/rails_integration/turbo_stream_callbacks.rb +0 -72
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# win_writer Draft
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Windows is the strongest all-around choice for a home AI research lab because it gives you the best combination of raw GPU support, hardware flexibility, and practical developer workflow. For LLM fine-tuning, image generation, and local inference, NVIDIA CUDA support on Windows is first-class: PyTorch, TensorFlow, xFormers, bitsandbytes, TensorRT, ONNX Runtime, and popular tools like Ollama, LM Studio, ComfyUI, AUTOMATIC1111, and Stable Diffusion WebUI all have strong Windows paths. If you want the highest-performance consumer GPUs for AI work, Windows pairs especially well with NVIDIA RTX hardware, from a single 4070 Ti Super up to multi-GPU prosumer setups. And if you need Linux-native scripts or package workflows, WSL2 gives you a near-seamless Ubuntu environment on the same machine, so you can run Hugging Face Transformers, PEFT, DeepSpeed, vLLM, llama.cpp, JupyterLab, and CUDA-enabled Linux tooling without giving up native Windows apps.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Windows also wins on hardware compatibility and ecosystem breadth. A home lab often mixes gaming-class GPUs, high-core-count CPUs, fast NVMe storage, USB devices, capture cards, and sometimes unusual motherboard or networking gear; Windows consistently offers the widest driver support and easiest setup across that mix. Beyond CUDA, Windows also supports DirectML, which broadens acceleration options on AMD and Intel hardware for local inference and experimentation. On the tooling side, it integrates cleanly with Visual Studio Code, Visual Studio, Docker Desktop, PowerShell, Windows Terminal, Git for Windows, and enterprise-friendly tools for remote access, file sharing, backup, and virtualization. In practice, that means you can fine-tune a LoRA in WSL2, monitor GPUs with native Windows utilities, manage datasets on NTFS storage, launch ComfyUI or LM Studio from the desktop, and still have access to familiar scripting and automation.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Just as important, Windows has massive community support for home AI builders. Most consumer AI guides now assume either native Windows or Windows plus WSL2, especially for Stable Diffusion workflows, local LLM front ends, and single-node fine-tuning recipes. Troubleshooting is easier when there are abundant guides for CUDA driver versions, PyTorch wheels, Flash Attention builds, and model-serving stacks on common RTX cards. For someone building a serious home AI lab, Windows offers the most practical balance: top-tier NVIDIA performance, Linux compatibility when you need it, broad hardware support, and a mature tool ecosystem that scales from casual experimentation to disciplined research workflows.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export ROBOT_LAB_TEMPLATE_PATH="${PWD}/prompts"
|
|
@@ -35,14 +35,12 @@
|
|
|
35
35
|
ENV["ROBOT_LAB_TEMPLATE_PATH"] ||= File.join(__dir__, "prompts")
|
|
36
36
|
|
|
37
37
|
require "json"
|
|
38
|
-
require_relative "
|
|
38
|
+
require_relative "../common"
|
|
39
39
|
require_relative "display"
|
|
40
40
|
require_relative "tools"
|
|
41
41
|
require_relative "room"
|
|
42
42
|
require_relative "writer"
|
|
43
43
|
|
|
44
|
-
RubyLLM.configure { |c| c.logger = Logger.new(File::NULL) }
|
|
45
|
-
|
|
46
44
|
# ── Mode Descriptors ────────────────────────────────────────
|
|
47
45
|
|
|
48
46
|
BOOK_MODE = {
|
|
@@ -128,7 +126,7 @@ FileUtils.mkdir_p(OUTPUT_DIR)
|
|
|
128
126
|
display = Display.new(log_path: log_path)
|
|
129
127
|
|
|
130
128
|
shared_config = RobotLab::RunConfig.new(
|
|
131
|
-
model:
|
|
129
|
+
model: LLM[:default].model,
|
|
132
130
|
temperature: 0.7
|
|
133
131
|
)
|
|
134
132
|
|
data/examples/17_skills.rb
CHANGED
|
@@ -40,10 +40,7 @@
|
|
|
40
40
|
# ├── pii_redactor.md — Leaf skill: redact PII
|
|
41
41
|
# └── audit_trail.md — Leaf skill: audit metadata in every response
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
ENV['ROBOT_LAB_TEMPLATE_PATH'] ||= File.join(__dir__, "prompts")
|
|
45
|
-
|
|
46
|
-
require_relative "../lib/robot_lab"
|
|
43
|
+
require_relative "common"
|
|
47
44
|
|
|
48
45
|
# Send logger output to a file instead of stdout
|
|
49
46
|
require 'logger'
|
|
@@ -120,10 +117,7 @@ ALERTS = [
|
|
|
120
117
|
# Build the Incident Responder with Composable Skills
|
|
121
118
|
# =============================================================================
|
|
122
119
|
|
|
123
|
-
|
|
124
|
-
puts "RobotLab Skills Demo — SRE Incident Response System"
|
|
125
|
-
puts "=" * 70
|
|
126
|
-
puts
|
|
120
|
+
banner "RobotLab Skills Demo — SRE Incident Response System"
|
|
127
121
|
|
|
128
122
|
# Show the skill composition
|
|
129
123
|
puts "Skill composition:"
|
|
@@ -142,6 +136,7 @@ puts
|
|
|
142
136
|
# - sre_compliance: Recursive skill — auto-expands to include pii_redactor
|
|
143
137
|
# and audit_trail before its own compliance instructions
|
|
144
138
|
responder = RobotLab.build(
|
|
139
|
+
model: LLM[:default].model,
|
|
145
140
|
name: "incident_responder",
|
|
146
141
|
template: :incident_responder,
|
|
147
142
|
skills: [:runbook_protocol, :structured_output, :sre_compliance],
|
|
@@ -165,13 +160,13 @@ messages = chat.instance_variable_get(:@messages)
|
|
|
165
160
|
system_msg = messages.find { |m| m.role.to_s == "system" }
|
|
166
161
|
if system_msg
|
|
167
162
|
prompt = system_msg.content
|
|
168
|
-
|
|
163
|
+
hr
|
|
169
164
|
puts "Assembled system prompt (#{prompt.length} chars, #{prompt.lines.count} lines):"
|
|
170
|
-
|
|
165
|
+
hr
|
|
171
166
|
prompt.lines.each_with_index do |line, i|
|
|
172
167
|
puts " %3d %s" % [i + 1, line]
|
|
173
168
|
end
|
|
174
|
-
|
|
169
|
+
hr
|
|
175
170
|
end
|
|
176
171
|
|
|
177
172
|
# =============================================================================
|
|
@@ -179,6 +174,7 @@ end
|
|
|
179
174
|
# =============================================================================
|
|
180
175
|
|
|
181
176
|
plain_responder = RobotLab.build(
|
|
177
|
+
model: LLM[:default].model,
|
|
182
178
|
name: "plain_responder",
|
|
183
179
|
template: :incident_responder,
|
|
184
180
|
context: {
|
|
@@ -202,11 +198,7 @@ end
|
|
|
202
198
|
# =============================================================================
|
|
203
199
|
|
|
204
200
|
ALERTS.each_with_index do |alert, index|
|
|
205
|
-
|
|
206
|
-
puts "=" * 70
|
|
207
|
-
puts "Incident #{index + 1}: #{alert[:label]}"
|
|
208
|
-
puts "=" * 70
|
|
209
|
-
puts
|
|
201
|
+
section "Incident #{index + 1}: #{alert[:label]}"
|
|
210
202
|
|
|
211
203
|
result = responder.run(alert[:data])
|
|
212
204
|
content = result.output.first&.content.to_s
|
|
@@ -217,7 +209,6 @@ ALERTS.each_with_index do |alert, index|
|
|
|
217
209
|
puts
|
|
218
210
|
end
|
|
219
211
|
|
|
220
|
-
puts "=" * 70
|
|
221
212
|
puts
|
|
222
213
|
puts <<~FOOTER
|
|
223
214
|
This example demonstrates:
|
data/examples/18_rails/Gemfile
CHANGED
|
@@ -20,9 +20,7 @@
|
|
|
20
20
|
# Usage:
|
|
21
21
|
# ANTHROPIC_API_KEY=your_key ruby examples/19_token_tracking.rb
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
require_relative "../lib/robot_lab"
|
|
23
|
+
require_relative "common"
|
|
26
24
|
|
|
27
25
|
# Anthropic claude-haiku-4-5 pricing (as of early 2026)
|
|
28
26
|
HAIKU_INPUT_CPM = 0.80 # $ per 1M input tokens
|
|
@@ -41,15 +39,12 @@ def first_line(text)
|
|
|
41
39
|
text&.strip&.lines&.first&.strip || ""
|
|
42
40
|
end
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
puts "Example 19: Per-Robot Token & Cost Tracking"
|
|
46
|
-
puts "=" * 60
|
|
47
|
-
puts
|
|
42
|
+
banner "Per-Robot Token & Cost Tracking"
|
|
48
43
|
|
|
49
44
|
robot = RobotLab.build(
|
|
45
|
+
model: LLM[:default].model,
|
|
50
46
|
name: "analyst",
|
|
51
|
-
system_prompt: "You are a concise technical analyst. Keep every reply under 40 words."
|
|
52
|
-
model: "claude-haiku-4-5-20251001"
|
|
47
|
+
system_prompt: "You are a concise technical analyst. Keep every reply under 40 words."
|
|
53
48
|
)
|
|
54
49
|
|
|
55
50
|
prompts = [
|
|
@@ -71,7 +66,7 @@ prompts.each_with_index do |prompt, i|
|
|
|
71
66
|
puts
|
|
72
67
|
end
|
|
73
68
|
|
|
74
|
-
|
|
69
|
+
hr
|
|
75
70
|
puts "After #{prompts.size} runs:"
|
|
76
71
|
puts " Total tokens: #{token_summary(robot.total_input_tokens, robot.total_output_tokens)}"
|
|
77
72
|
puts " Total cost: #{run_cost(robot.total_input_tokens, robot.total_output_tokens)}"
|
|
@@ -106,14 +101,14 @@ puts
|
|
|
106
101
|
# To start truly fresh (new context, new counter), build a new robot.
|
|
107
102
|
# ---------------------------------------------------------------
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
hr
|
|
110
105
|
puts "Fresh robot — genuinely zero context:"
|
|
111
106
|
puts
|
|
112
107
|
|
|
113
108
|
fresh = RobotLab.build(
|
|
109
|
+
model: LLM[:default].model,
|
|
114
110
|
name: "analyst2",
|
|
115
|
-
system_prompt: "You are a concise technical analyst. Keep every reply under 40 words."
|
|
116
|
-
model: "claude-haiku-4-5-20251001"
|
|
111
|
+
system_prompt: "You are a concise technical analyst. Keep every reply under 40 words."
|
|
117
112
|
)
|
|
118
113
|
|
|
119
114
|
result = fresh.run("What is memoization?")
|
|
@@ -123,6 +118,5 @@ puts " This run: #{token_summary(result.input_tokens, result.output_tokens)}"
|
|
|
123
118
|
puts " Cumulative: #{token_summary(fresh.total_input_tokens, fresh.total_output_tokens)}"
|
|
124
119
|
puts
|
|
125
120
|
|
|
126
|
-
|
|
121
|
+
hr
|
|
127
122
|
puts "Token tracking demo complete."
|
|
128
|
-
puts "=" * 60
|
|
@@ -25,9 +25,7 @@
|
|
|
25
25
|
# Usage:
|
|
26
26
|
# ANTHROPIC_API_KEY=your_key ruby examples/20_circuit_breaker.rb
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
require_relative "../lib/robot_lab"
|
|
28
|
+
require_relative "common"
|
|
31
29
|
|
|
32
30
|
# -------------------------------------------------------------------------
|
|
33
31
|
# A tool that always says "more steps remain" — designed to induce looping
|
|
@@ -62,10 +60,7 @@ class MultiStepProcessor < RubyLLM::Tool
|
|
|
62
60
|
end
|
|
63
61
|
end
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
puts "Example 20: Tool Loop Circuit Breaker"
|
|
67
|
-
puts "=" * 60
|
|
68
|
-
puts
|
|
63
|
+
banner "Tool Loop Circuit Breaker"
|
|
69
64
|
|
|
70
65
|
TASK = "Run the batch process from step 1 using the MultiStepProcessor tool. " \
|
|
71
66
|
"Execute every step sequentially until the process reports 'complete'."
|
|
@@ -78,15 +73,14 @@ TASK = "Run the batch process from step 1 using the MultiStepProcessor tool. " \
|
|
|
78
73
|
# history. Call clear_messages to flush the broken context before reuse.
|
|
79
74
|
# -------------------------------------------------------------------------
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
puts
|
|
76
|
+
section "Part 1: Circuit Breaker Fires (max_tool_rounds: 5)"
|
|
83
77
|
|
|
84
78
|
robot = RobotLab.build(
|
|
79
|
+
model: LLM[:default].model,
|
|
85
80
|
name: "process_runner",
|
|
86
81
|
system_prompt: "You are a process runner. Execute tasks exactly as instructed.",
|
|
87
82
|
local_tools: [MultiStepProcessor],
|
|
88
|
-
max_tool_rounds: 5
|
|
89
|
-
model: "claude-haiku-4-5-20251001"
|
|
83
|
+
max_tool_rounds: 5
|
|
90
84
|
)
|
|
91
85
|
|
|
92
86
|
begin
|
|
@@ -106,8 +100,7 @@ puts
|
|
|
106
100
|
# Only the conversation history is cleared — the robot is then reusable.
|
|
107
101
|
# -------------------------------------------------------------------------
|
|
108
102
|
|
|
109
|
-
|
|
110
|
-
puts
|
|
103
|
+
section "Part 2: Recover with clear_messages"
|
|
111
104
|
|
|
112
105
|
robot.clear_messages
|
|
113
106
|
puts "Chat flushed. Robot config (tools, max_tool_rounds) is unchanged."
|
|
@@ -125,8 +118,7 @@ puts
|
|
|
125
118
|
# not a tax on well-behaved tool interactions.
|
|
126
119
|
# -------------------------------------------------------------------------
|
|
127
120
|
|
|
128
|
-
|
|
129
|
-
puts
|
|
121
|
+
section "Part 3: No Circuit Breaker — Task Terminates Naturally"
|
|
130
122
|
|
|
131
123
|
class SingleStep < RubyLLM::Tool
|
|
132
124
|
description "Doubles a number and returns the result immediately."
|
|
@@ -138,16 +130,15 @@ class SingleStep < RubyLLM::Tool
|
|
|
138
130
|
end
|
|
139
131
|
|
|
140
132
|
unguarded = RobotLab.build(
|
|
133
|
+
model: LLM[:default].model,
|
|
141
134
|
name: "calculator",
|
|
142
135
|
system_prompt: "Use the provided tool to answer questions.",
|
|
143
|
-
local_tools: [SingleStep]
|
|
144
|
-
model: "claude-haiku-4-5-20251001"
|
|
136
|
+
local_tools: [SingleStep]
|
|
145
137
|
)
|
|
146
138
|
|
|
147
139
|
result = unguarded.run("Double the number 21 using the tool.")
|
|
148
140
|
puts "Result: #{result.reply&.strip}"
|
|
149
141
|
puts
|
|
150
142
|
|
|
151
|
-
|
|
143
|
+
hr
|
|
152
144
|
puts "Circuit breaker demo complete."
|
|
153
|
-
puts "=" * 60
|
|
@@ -19,9 +19,7 @@
|
|
|
19
19
|
# Usage:
|
|
20
20
|
# ANTHROPIC_API_KEY=your_key ruby examples/21_learning_loop.rb
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
require_relative "../lib/robot_lab"
|
|
22
|
+
require_relative "common"
|
|
25
23
|
|
|
26
24
|
SNIPPETS = [
|
|
27
25
|
{
|
|
@@ -66,20 +64,17 @@ SNIPPETS = [
|
|
|
66
64
|
}
|
|
67
65
|
].freeze
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
puts "Example 21: Learning Accumulation Loop"
|
|
71
|
-
puts "=" * 65
|
|
72
|
-
puts
|
|
67
|
+
banner "Learning Accumulation Loop"
|
|
73
68
|
|
|
74
69
|
robot = RobotLab.build(
|
|
70
|
+
model: LLM[:default].model,
|
|
75
71
|
name: "code_reviewer",
|
|
76
|
-
system_prompt: <<~PROMPT
|
|
72
|
+
system_prompt: <<~PROMPT
|
|
77
73
|
You are a concise Ruby code reviewer. For each snippet:
|
|
78
74
|
1. Identify the main issue (one sentence).
|
|
79
75
|
2. Show the improved version (code block).
|
|
80
76
|
Keep responses under 80 words total.
|
|
81
77
|
PROMPT
|
|
82
|
-
model: "claude-haiku-4-5-20251001"
|
|
83
78
|
)
|
|
84
79
|
|
|
85
80
|
SNIPPETS.each_with_index do |item, i|
|
|
@@ -88,7 +83,7 @@ SNIPPETS.each_with_index do |item, i|
|
|
|
88
83
|
# ---------------------------------------------------------------
|
|
89
84
|
# Show what learnings are active going into this run
|
|
90
85
|
# ---------------------------------------------------------------
|
|
91
|
-
|
|
86
|
+
section "Run #{run_number}"
|
|
92
87
|
if robot.learnings.empty?
|
|
93
88
|
puts "Learnings: (none yet)"
|
|
94
89
|
else
|
|
@@ -117,16 +112,14 @@ end
|
|
|
117
112
|
# ---------------------------------------------------------------
|
|
118
113
|
# Show the full accumulated learning list
|
|
119
114
|
# ---------------------------------------------------------------
|
|
120
|
-
|
|
121
|
-
puts "Accumulated learnings (#{robot.learnings.size} total):"
|
|
115
|
+
section "Accumulated Learnings (#{robot.learnings.size} total)"
|
|
122
116
|
robot.learnings.each_with_index { |l, i| puts " #{i + 1}. #{l}" }
|
|
123
117
|
puts
|
|
124
118
|
|
|
125
119
|
# ---------------------------------------------------------------
|
|
126
120
|
# Demonstrate superset dedup: a broader learning replaces narrower ones
|
|
127
121
|
# ---------------------------------------------------------------
|
|
128
|
-
|
|
129
|
-
puts
|
|
122
|
+
section "Deduplication Demo"
|
|
130
123
|
robot2 = RobotLab.build(name: "reviewer2", system_prompt: "You review code.")
|
|
131
124
|
|
|
132
125
|
robot2.learn("avoid using puts")
|
|
@@ -140,14 +133,13 @@ puts
|
|
|
140
133
|
# Demonstrate persistence: learnings survive a robot rebuild using
|
|
141
134
|
# the same Memory object
|
|
142
135
|
# ---------------------------------------------------------------
|
|
143
|
-
|
|
144
|
-
puts
|
|
136
|
+
section "Persistence Across Rebuild"
|
|
145
137
|
|
|
146
138
|
shared_memory = robot.instance_variable_get(:@memory)
|
|
147
139
|
rebuilt = RobotLab.build(
|
|
140
|
+
model: LLM[:default].model,
|
|
148
141
|
name: "code_reviewer",
|
|
149
|
-
system_prompt: "You review code."
|
|
150
|
-
model: "claude-haiku-4-5-20251001"
|
|
142
|
+
system_prompt: "You review code."
|
|
151
143
|
)
|
|
152
144
|
rebuilt.instance_variable_set(:@memory, shared_memory)
|
|
153
145
|
|
|
@@ -159,6 +151,5 @@ puts "Learnings on rebuilt robot (#{rebuilt.learnings.size}):"
|
|
|
159
151
|
rebuilt.learnings.each_with_index { |l, i| puts " #{i + 1}. #{l}" }
|
|
160
152
|
puts
|
|
161
153
|
|
|
162
|
-
|
|
154
|
+
hr
|
|
163
155
|
puts "Learning loop demo complete."
|
|
164
|
-
puts "=" * 65
|
|
@@ -22,9 +22,7 @@
|
|
|
22
22
|
# Usage:
|
|
23
23
|
# ANTHROPIC_API_KEY=your_key ruby examples/22_context_compression.rb
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
require_relative "../lib/robot_lab"
|
|
25
|
+
require_relative "common"
|
|
28
26
|
|
|
29
27
|
# ---------------------------------------------------------------------------
|
|
30
28
|
# Check optional dependency
|
|
@@ -47,15 +45,13 @@ def approx_tokens(messages)
|
|
|
47
45
|
end
|
|
48
46
|
end
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
puts "Example 22: Context Window Compression"
|
|
52
|
-
puts "=" * 60
|
|
53
|
-
puts
|
|
48
|
+
banner "Context Window Compression"
|
|
54
49
|
|
|
55
50
|
# ---------------------------------------------------------------------------
|
|
56
51
|
# Build a robot and simulate a long conversation on two topics
|
|
57
52
|
# ---------------------------------------------------------------------------
|
|
58
53
|
bot = RobotLab.build(
|
|
54
|
+
model: LLM[:default].model,
|
|
59
55
|
name: "assistant",
|
|
60
56
|
system_prompt: "You are a concise Ruby expert. Reply in 2-3 sentences."
|
|
61
57
|
)
|
|
@@ -157,12 +153,10 @@ puts
|
|
|
157
153
|
# ---------------------------------------------------------------------------
|
|
158
154
|
# Show the LLM summarizer pattern (not executed — requires API key)
|
|
159
155
|
# ---------------------------------------------------------------------------
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
puts "=" * 60
|
|
163
|
-
puts <<~RUBY
|
|
164
|
-
|
|
156
|
+
section "LLM Summarizer Pattern (requires API key)"
|
|
157
|
+
show_code <<~RUBY
|
|
165
158
|
summarizer_bot = RobotLab.build(
|
|
159
|
+
model: "gpt-5.4",
|
|
166
160
|
name: "summarizer",
|
|
167
161
|
system_prompt: "Summarize the following text in one sentence."
|
|
168
162
|
)
|
|
@@ -173,7 +167,6 @@ puts <<~RUBY
|
|
|
173
167
|
drop_threshold: 0.2,
|
|
174
168
|
summarizer: ->(text) { summarizer_bot.run("Summarize: \#{text}").reply }
|
|
175
169
|
)
|
|
176
|
-
|
|
177
170
|
RUBY
|
|
178
171
|
|
|
179
172
|
puts "Done."
|
data/examples/23_convergence.rb
CHANGED
|
@@ -19,9 +19,7 @@
|
|
|
19
19
|
# Usage:
|
|
20
20
|
# ANTHROPIC_API_KEY=your_key ruby examples/23_convergence.rb
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
require_relative "../lib/robot_lab"
|
|
22
|
+
require_relative "common"
|
|
25
23
|
|
|
26
24
|
# ---------------------------------------------------------------------------
|
|
27
25
|
# Check optional dependency
|
|
@@ -34,10 +32,7 @@ rescue LoadError
|
|
|
34
32
|
exit 1
|
|
35
33
|
end
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
puts "Example 23: Debate Convergence Detection"
|
|
39
|
-
puts "=" * 60
|
|
40
|
-
puts
|
|
35
|
+
banner "Debate Convergence Detection"
|
|
41
36
|
|
|
42
37
|
# ---------------------------------------------------------------------------
|
|
43
38
|
# Similarity scoring
|
|
@@ -61,8 +56,7 @@ pairs = {
|
|
|
61
56
|
]
|
|
62
57
|
}
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
puts "-" * 60
|
|
59
|
+
section "Similarity Scores"
|
|
66
60
|
pairs.each do |label, (a, b)|
|
|
67
61
|
score = RobotLab::Convergence.similarity(a, b)
|
|
68
62
|
converged = RobotLab::Convergence.detected?(a, b, threshold: 0.6)
|
|
@@ -74,11 +68,8 @@ end
|
|
|
74
68
|
# ---------------------------------------------------------------------------
|
|
75
69
|
# Router fast-path pattern
|
|
76
70
|
# ---------------------------------------------------------------------------
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
puts "=" * 60
|
|
80
|
-
puts <<~RUBY
|
|
81
|
-
|
|
71
|
+
section "Router Fast-Path Pattern"
|
|
72
|
+
show_code <<~RUBY
|
|
82
73
|
# Two verifier robots run in parallel and store their replies in shared memory.
|
|
83
74
|
# The router checks convergence before dispatching to the expensive reconciler.
|
|
84
75
|
|
|
@@ -100,14 +91,12 @@ puts <<~RUBY
|
|
|
100
91
|
)
|
|
101
92
|
|
|
102
93
|
result = network.run(message: "Is this claim accurate?")
|
|
103
|
-
|
|
104
94
|
RUBY
|
|
105
95
|
|
|
106
96
|
# ---------------------------------------------------------------------------
|
|
107
97
|
# Demonstrate with simulated verifier outputs
|
|
108
98
|
# ---------------------------------------------------------------------------
|
|
109
|
-
|
|
110
|
-
puts "-" * 60
|
|
99
|
+
section "Simulating Verifier Fast-Path"
|
|
111
100
|
|
|
112
101
|
verifier_outputs = [
|
|
113
102
|
{
|
|
@@ -20,29 +20,27 @@
|
|
|
20
20
|
# Usage:
|
|
21
21
|
# ANTHROPIC_API_KEY=your_key ruby examples/24_structured_delegation.rb
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
require_relative "common"
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
puts "=" * 60
|
|
28
|
-
puts "Example 24: Structured Delegation"
|
|
29
|
-
puts "=" * 60
|
|
30
|
-
puts
|
|
25
|
+
banner "Structured Delegation"
|
|
31
26
|
|
|
32
27
|
# ---------------------------------------------------------------------------
|
|
33
28
|
# Build a manager and two specialist robots
|
|
34
29
|
# ---------------------------------------------------------------------------
|
|
35
30
|
manager = RobotLab.build(
|
|
31
|
+
model: LLM[:default].model,
|
|
36
32
|
name: "manager",
|
|
37
33
|
system_prompt: "You are a project manager. Delegate tasks concisely."
|
|
38
34
|
)
|
|
39
35
|
|
|
40
36
|
summarizer = RobotLab.build(
|
|
37
|
+
model: LLM[:default].model,
|
|
41
38
|
name: "summarizer",
|
|
42
39
|
system_prompt: "You are a concise summarizer. Produce a 1-2 sentence summary."
|
|
43
40
|
)
|
|
44
41
|
|
|
45
42
|
analyst = RobotLab.build(
|
|
43
|
+
model: LLM[:default].model,
|
|
46
44
|
name: "analyst",
|
|
47
45
|
system_prompt: "You are a data analyst. Identify the key metric in one sentence."
|
|
48
46
|
)
|
|
@@ -59,13 +57,12 @@ TEXT
|
|
|
59
57
|
|
|
60
58
|
puts "Document:"
|
|
61
59
|
puts document
|
|
62
|
-
|
|
60
|
+
hr
|
|
63
61
|
|
|
64
62
|
# ---------------------------------------------------------------------------
|
|
65
63
|
# Synchronous delegation — sequential, blocks until each result arrives
|
|
66
64
|
# ---------------------------------------------------------------------------
|
|
67
|
-
|
|
68
|
-
puts
|
|
65
|
+
section "Synchronous (sequential)"
|
|
69
66
|
|
|
70
67
|
puts "Delegating to summarizer (blocking)..."
|
|
71
68
|
summary_result = manager.delegate(to: summarizer, task: "Summarize this report:\n\n#{document}")
|
|
@@ -88,15 +85,16 @@ puts
|
|
|
88
85
|
# ---------------------------------------------------------------------------
|
|
89
86
|
# Asynchronous delegation — parallel fan-out, results collected later
|
|
90
87
|
# ---------------------------------------------------------------------------
|
|
91
|
-
|
|
92
|
-
puts
|
|
88
|
+
section "Asynchronous (parallel fan-out)"
|
|
93
89
|
|
|
94
90
|
# Fresh robots — each delegate call should start from a clean slate
|
|
95
91
|
async_summarizer = RobotLab.build(
|
|
92
|
+
model: LLM[:default].model,
|
|
96
93
|
name: "summarizer",
|
|
97
94
|
system_prompt: "You are a concise summarizer. Produce a 1-2 sentence summary."
|
|
98
95
|
)
|
|
99
96
|
async_analyst = RobotLab.build(
|
|
97
|
+
model: LLM[:default].model,
|
|
100
98
|
name: "analyst",
|
|
101
99
|
system_prompt: "You are a data analyst. Identify the key metric in one sentence."
|
|
102
100
|
)
|
|
@@ -127,9 +125,7 @@ puts
|
|
|
127
125
|
# ---------------------------------------------------------------------------
|
|
128
126
|
# Contrast with the alternatives
|
|
129
127
|
# ---------------------------------------------------------------------------
|
|
130
|
-
|
|
131
|
-
puts "When to use delegate vs. the alternatives"
|
|
132
|
-
puts "=" * 60
|
|
128
|
+
section "When to Use delegate vs. the Alternatives"
|
|
133
129
|
puts <<~TEXT
|
|
134
130
|
|
|
135
131
|
bus messaging — fire-and-forget; no return value; async
|
|
@@ -13,19 +13,14 @@
|
|
|
13
13
|
# Usage:
|
|
14
14
|
# ruby examples/25_history_search.rb
|
|
15
15
|
|
|
16
|
-
ENV["ROBOT_LAB_TEMPLATE_PATH"] ||= File.join(__dir__, "prompts")
|
|
17
|
-
|
|
18
16
|
require "json"
|
|
19
|
-
require_relative "
|
|
17
|
+
require_relative "common"
|
|
20
18
|
|
|
21
19
|
CONVERSATION_TURNS = File.readlines(
|
|
22
20
|
File.join(__dir__, "25_history_search", "conversation.jsonl"), chomp: true
|
|
23
21
|
).map { |line| JSON.parse(line, symbolize_names: true) }.freeze
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
puts "Example 25: Chat History Search"
|
|
27
|
-
puts "=" * 60
|
|
28
|
-
puts
|
|
23
|
+
banner "Chat History Search"
|
|
29
24
|
|
|
30
25
|
# ---------------------------------------------------------------------------
|
|
31
26
|
# Minimal message stub — populates history without LLM calls
|
|
@@ -35,7 +30,7 @@ FakeMsg = Struct.new(:role, :content, :tool_calls)
|
|
|
35
30
|
# ---------------------------------------------------------------------------
|
|
36
31
|
# Build a robot and inject the conversation fixture
|
|
37
32
|
# ---------------------------------------------------------------------------
|
|
38
|
-
robot = RobotLab.build(name: "tech_lead", system_prompt: "You are a senior engineering advisor.")
|
|
33
|
+
robot = RobotLab.build(model: LLM[:default].model, name: "tech_lead", system_prompt: "You are a senior engineering advisor.")
|
|
39
34
|
|
|
40
35
|
messages = CONVERSATION_TURNS.map { |t| FakeMsg.new(t[:role], t[:content], nil) }
|
|
41
36
|
robot.instance_variable_get(:@chat).instance_variable_set(:@messages, messages)
|
|
@@ -88,7 +83,7 @@ end
|
|
|
88
83
|
# ---------------------------------------------------------------------------
|
|
89
84
|
# RAG pattern — retrieve the most relevant turns, then inject as context
|
|
90
85
|
# ---------------------------------------------------------------------------
|
|
91
|
-
|
|
86
|
+
section "RAG Pattern: Retrieve Context, Then Call LLM"
|
|
92
87
|
puts "(showing retrieved context — no actual LLM call)"
|
|
93
88
|
puts
|
|
94
89
|
|
|
@@ -111,9 +106,7 @@ puts
|
|
|
111
106
|
# ---------------------------------------------------------------------------
|
|
112
107
|
# When to use search_history
|
|
113
108
|
# ---------------------------------------------------------------------------
|
|
114
|
-
|
|
115
|
-
puts "When to use search_history"
|
|
116
|
-
puts "=" * 60
|
|
109
|
+
section "When to Use search_history"
|
|
117
110
|
puts <<~'TEXT'
|
|
118
111
|
|
|
119
112
|
Without search_history:
|
|
@@ -13,14 +13,10 @@
|
|
|
13
13
|
# ruby examples/26_document_store.rb
|
|
14
14
|
# (Downloads the ~23 MB ONNX model on first run; cached afterwards.)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
require_relative "common"
|
|
17
|
+
require "robot_lab/document_store"
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
puts "=" * 60
|
|
21
|
-
puts "Example 26: Embedding-Based Document Store"
|
|
22
|
-
puts "=" * 60
|
|
23
|
-
puts
|
|
19
|
+
banner "Embedding-Based Document Store"
|
|
24
20
|
puts "Note: First run downloads the fastembed model (~23 MB, cached)."
|
|
25
21
|
puts
|
|
26
22
|
|
|
@@ -97,7 +93,7 @@ end
|
|
|
97
93
|
# ---------------------------------------------------------------------------
|
|
98
94
|
# Delete and verify
|
|
99
95
|
# ---------------------------------------------------------------------------
|
|
100
|
-
|
|
96
|
+
section "Delete :redis_caching_guide, Re-run Cache Query"
|
|
101
97
|
store.delete(:redis_caching_guide)
|
|
102
98
|
results = store.search("Redis evicting keys unexpectedly", limit: 2)
|
|
103
99
|
puts " Remaining keys: #{store.keys.inspect}"
|
|
@@ -107,7 +103,7 @@ puts
|
|
|
107
103
|
# ---------------------------------------------------------------------------
|
|
108
104
|
# Memory integration
|
|
109
105
|
# ---------------------------------------------------------------------------
|
|
110
|
-
|
|
106
|
+
section "Memory Integration"
|
|
111
107
|
memory = RobotLab::Memory.new(enable_cache: false)
|
|
112
108
|
|
|
113
109
|
DOCUMENTS.each { |key, text| memory.store_document(key, text) }
|
|
@@ -124,10 +120,7 @@ puts
|
|
|
124
120
|
# ---------------------------------------------------------------------------
|
|
125
121
|
# RAG pattern
|
|
126
122
|
# ---------------------------------------------------------------------------
|
|
127
|
-
|
|
128
|
-
puts "RAG Pattern: retrieve relevant docs, then generate with LLM"
|
|
129
|
-
puts "=" * 60
|
|
130
|
-
puts
|
|
123
|
+
section "RAG Pattern: Retrieve Relevant Docs, Then Generate with LLM"
|
|
131
124
|
|
|
132
125
|
rag_query = "Our Sidekiq jobs exhaust retries and land in the dead queue after a Stripe outage."
|
|
133
126
|
|