robot_lab 0.0.1 → 0.0.6
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/.github/workflows/deploy-github-pages.yml +9 -9
- data/.irbrc +6 -0
- data/CHANGELOG.md +140 -0
- data/README.md +263 -48
- data/Rakefile +71 -1
- data/docs/api/core/index.md +53 -46
- data/docs/api/core/memory.md +200 -154
- data/docs/api/core/network.md +13 -3
- data/docs/api/core/robot.md +490 -130
- data/docs/api/core/state.md +55 -73
- data/docs/api/core/tool.md +205 -209
- data/docs/api/index.md +7 -28
- data/docs/api/mcp/client.md +119 -48
- data/docs/api/mcp/index.md +75 -60
- data/docs/api/mcp/server.md +120 -136
- data/docs/api/mcp/transports.md +172 -184
- data/docs/api/messages/index.md +35 -20
- data/docs/api/messages/text-message.md +67 -21
- data/docs/api/messages/tool-call-message.md +80 -41
- data/docs/api/messages/tool-result-message.md +119 -50
- data/docs/api/messages/user-message.md +48 -24
- data/docs/api/streaming/context.md +157 -74
- data/docs/api/streaming/events.md +114 -166
- data/docs/api/streaming/index.md +74 -72
- data/docs/architecture/core-concepts.md +360 -116
- data/docs/architecture/index.md +97 -59
- data/docs/architecture/message-flow.md +138 -129
- data/docs/architecture/network-orchestration.md +197 -50
- data/docs/architecture/robot-execution.md +199 -146
- data/docs/architecture/state-management.md +255 -187
- data/docs/concepts.md +311 -49
- data/docs/examples/basic-chat.md +89 -77
- data/docs/examples/index.md +222 -47
- data/docs/examples/mcp-server.md +207 -203
- data/docs/examples/multi-robot-network.md +129 -35
- data/docs/examples/rails-application.md +159 -160
- data/docs/examples/tool-usage.md +295 -204
- data/docs/getting-started/configuration.md +347 -154
- data/docs/getting-started/index.md +1 -1
- data/docs/getting-started/installation.md +22 -13
- data/docs/getting-started/quick-start.md +166 -121
- data/docs/guides/building-robots.md +418 -212
- data/docs/guides/creating-networks.md +143 -24
- data/docs/guides/index.md +0 -5
- data/docs/guides/mcp-integration.md +152 -113
- data/docs/guides/memory.md +220 -164
- data/docs/guides/rails-integration.md +244 -162
- data/docs/guides/streaming.md +137 -187
- data/docs/guides/using-tools.md +259 -212
- data/docs/index.md +46 -41
- data/examples/01_simple_robot.rb +6 -9
- data/examples/02_tools.rb +6 -9
- data/examples/03_network.rb +19 -17
- data/examples/04_mcp.rb +5 -8
- data/examples/05_streaming.rb +5 -8
- data/examples/06_prompt_templates.rb +42 -37
- data/examples/07_network_memory.rb +13 -14
- data/examples/08_llm_config.rb +169 -0
- data/examples/09_chaining.rb +262 -0
- data/examples/10_memory.rb +331 -0
- data/examples/11_network_introspection.rb +253 -0
- data/examples/12_message_bus.rb +74 -0
- data/examples/13_spawn.rb +90 -0
- data/examples/14_rusty_circuit/comic.rb +143 -0
- data/examples/14_rusty_circuit/display.rb +203 -0
- data/examples/14_rusty_circuit/heckler.rb +63 -0
- data/examples/14_rusty_circuit/open_mic.rb +123 -0
- data/examples/14_rusty_circuit/prompts/open_mic_comic.md +20 -0
- data/examples/14_rusty_circuit/prompts/open_mic_heckler.md +23 -0
- data/examples/14_rusty_circuit/prompts/open_mic_scout.md +20 -0
- data/examples/14_rusty_circuit/scout.rb +156 -0
- data/examples/14_rusty_circuit/scout_notes.md +89 -0
- data/examples/14_rusty_circuit/show.log +234 -0
- data/examples/15_memory_network_and_bus/editor_in_chief.rb +24 -0
- data/examples/15_memory_network_and_bus/editorial_pipeline.rb +206 -0
- data/examples/15_memory_network_and_bus/linux_writer.rb +80 -0
- data/examples/15_memory_network_and_bus/os_editor.rb +46 -0
- data/examples/15_memory_network_and_bus/os_writer.rb +46 -0
- data/examples/15_memory_network_and_bus/output/combined_article.md +13 -0
- data/examples/15_memory_network_and_bus/output/final_article.md +15 -0
- data/examples/15_memory_network_and_bus/output/linux_draft.md +5 -0
- data/examples/15_memory_network_and_bus/output/mac_draft.md +7 -0
- data/examples/15_memory_network_and_bus/output/memory.json +13 -0
- data/examples/15_memory_network_and_bus/output/revision_1.md +19 -0
- data/examples/15_memory_network_and_bus/output/revision_2.md +15 -0
- data/examples/15_memory_network_and_bus/output/windows_draft.md +7 -0
- data/examples/15_memory_network_and_bus/prompts/os_advocate.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_chief.md +13 -0
- data/examples/15_memory_network_and_bus/prompts/os_editor.md +13 -0
- data/examples/16_writers_room/display.rb +158 -0
- data/examples/16_writers_room/output/.gitignore +2 -0
- data/examples/16_writers_room/output/opus_001.md +263 -0
- data/examples/16_writers_room/output/opus_001_notes.log +470 -0
- data/examples/16_writers_room/prompts/writer.md +37 -0
- data/examples/16_writers_room/room.rb +150 -0
- data/examples/16_writers_room/tools.rb +162 -0
- data/examples/16_writers_room/writer.rb +121 -0
- data/examples/16_writers_room/writers_room.rb +162 -0
- data/examples/README.md +197 -0
- data/examples/prompts/{assistant/system.txt.erb → assistant.md} +3 -0
- data/examples/prompts/{billing/system.txt.erb → billing.md} +3 -0
- data/examples/prompts/{classifier/system.txt.erb → classifier.md} +3 -0
- data/examples/prompts/comedian.md +6 -0
- data/examples/prompts/comedy_critic.md +10 -0
- data/examples/prompts/configurable.md +9 -0
- data/examples/prompts/dispatcher.md +12 -0
- data/examples/prompts/{entity_extractor/system.txt.erb → entity_extractor.md} +3 -0
- data/examples/prompts/{escalation/system.txt.erb → escalation.md} +7 -0
- data/examples/prompts/frontmatter_mcp_test.md +9 -0
- data/examples/prompts/frontmatter_named_test.md +5 -0
- data/examples/prompts/frontmatter_tools_test.md +6 -0
- data/examples/prompts/{general/system.txt.erb → general.md} +3 -0
- data/examples/prompts/{github_assistant/system.txt.erb → github_assistant.md} +8 -0
- data/examples/prompts/{helper/system.txt.erb → helper.md} +3 -0
- data/examples/prompts/{keyword_extractor/system.txt.erb → keyword_extractor.md} +3 -0
- data/examples/prompts/llm_config_demo.md +20 -0
- data/examples/prompts/{order_support/system.txt.erb → order_support.md} +8 -0
- data/examples/prompts/os_advocate.md +13 -0
- data/examples/prompts/os_chief.md +13 -0
- data/examples/prompts/os_editor.md +13 -0
- data/examples/prompts/{product_support/system.txt.erb → product_support.md} +7 -0
- data/examples/prompts/{sentiment_analyzer/system.txt.erb → sentiment_analyzer.md} +3 -0
- data/examples/prompts/{synthesizer/system.txt.erb → synthesizer.md} +3 -0
- data/examples/prompts/{technical/system.txt.erb → technical.md} +3 -0
- data/examples/prompts/{triage/system.txt.erb → triage.md} +6 -0
- data/lib/generators/robot_lab/templates/initializer.rb.tt +0 -13
- data/lib/robot_lab/ask_user.rb +75 -0
- data/lib/robot_lab/config/defaults.yml +121 -0
- data/lib/robot_lab/config.rb +183 -0
- data/lib/robot_lab/error.rb +6 -0
- data/lib/robot_lab/mcp/client.rb +1 -1
- data/lib/robot_lab/memory.rb +10 -34
- data/lib/robot_lab/network.rb +13 -20
- data/lib/robot_lab/robot/bus_messaging.rb +239 -0
- data/lib/robot_lab/robot/mcp_management.rb +88 -0
- data/lib/robot_lab/robot/template_rendering.rb +130 -0
- data/lib/robot_lab/robot.rb +240 -330
- data/lib/robot_lab/robot_message.rb +44 -0
- data/lib/robot_lab/robot_result.rb +1 -0
- data/lib/robot_lab/run_config.rb +184 -0
- data/lib/robot_lab/state_proxy.rb +2 -12
- data/lib/robot_lab/streaming/context.rb +1 -1
- data/lib/robot_lab/task.rb +8 -1
- data/lib/robot_lab/tool.rb +108 -172
- data/lib/robot_lab/tool_config.rb +1 -1
- data/lib/robot_lab/tool_manifest.rb +2 -18
- data/lib/robot_lab/utils.rb +39 -0
- data/lib/robot_lab/version.rb +1 -1
- data/lib/robot_lab.rb +89 -57
- data/mkdocs.yml +0 -11
- metadata +121 -135
- data/docs/api/adapters/anthropic.md +0 -121
- data/docs/api/adapters/gemini.md +0 -133
- data/docs/api/adapters/index.md +0 -104
- data/docs/api/adapters/openai.md +0 -134
- data/docs/api/history/active-record-adapter.md +0 -195
- data/docs/api/history/config.md +0 -191
- data/docs/api/history/index.md +0 -132
- data/docs/api/history/thread-manager.md +0 -144
- data/docs/guides/history.md +0 -359
- data/examples/prompts/assistant/user.txt.erb +0 -1
- data/examples/prompts/billing/user.txt.erb +0 -1
- data/examples/prompts/classifier/user.txt.erb +0 -1
- data/examples/prompts/entity_extractor/user.txt.erb +0 -3
- data/examples/prompts/escalation/user.txt.erb +0 -34
- data/examples/prompts/general/user.txt.erb +0 -1
- data/examples/prompts/github_assistant/user.txt.erb +0 -1
- data/examples/prompts/helper/user.txt.erb +0 -1
- data/examples/prompts/keyword_extractor/user.txt.erb +0 -3
- data/examples/prompts/order_support/user.txt.erb +0 -22
- data/examples/prompts/product_support/user.txt.erb +0 -32
- data/examples/prompts/sentiment_analyzer/user.txt.erb +0 -3
- data/examples/prompts/synthesizer/user.txt.erb +0 -15
- data/examples/prompts/technical/user.txt.erb +0 -1
- data/examples/prompts/triage/user.txt.erb +0 -17
- data/lib/robot_lab/adapters/anthropic.rb +0 -163
- data/lib/robot_lab/adapters/base.rb +0 -85
- data/lib/robot_lab/adapters/gemini.rb +0 -193
- data/lib/robot_lab/adapters/openai.rb +0 -159
- data/lib/robot_lab/adapters/registry.rb +0 -81
- data/lib/robot_lab/configuration.rb +0 -143
- data/lib/robot_lab/errors.rb +0 -70
- data/lib/robot_lab/history/active_record_adapter.rb +0 -146
- data/lib/robot_lab/history/config.rb +0 -115
- data/lib/robot_lab/history/thread_manager.rb +0 -93
- data/lib/robot_lab/robotic_model.rb +0 -324
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RobotLab
|
|
4
|
-
# Thread-local storage for capturing tool executions during RubyLLM auto-execution.
|
|
5
|
-
#
|
|
6
|
-
# Stores tool execution records in thread-local storage so they can be
|
|
7
|
-
# retrieved after an LLM inference call completes.
|
|
8
|
-
#
|
|
9
|
-
class ToolExecutionCapture
|
|
10
|
-
# Returns the captured tool executions for the current thread.
|
|
11
|
-
#
|
|
12
|
-
# @return [Array<Hash>] array of execution records
|
|
13
|
-
def self.captured
|
|
14
|
-
Thread.current[:robot_lab_tool_executions] ||= []
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Clears the captured tool executions for the current thread.
|
|
18
|
-
#
|
|
19
|
-
# @return [Array] empty array
|
|
20
|
-
def self.clear!
|
|
21
|
-
Thread.current[:robot_lab_tool_executions] = []
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Records a tool execution.
|
|
25
|
-
#
|
|
26
|
-
# @param tool_name [String] name of the executed tool
|
|
27
|
-
# @param tool_id [String] unique identifier for this execution
|
|
28
|
-
# @param input [Hash] input parameters passed to the tool
|
|
29
|
-
# @param output [Object] the tool's return value
|
|
30
|
-
# @return [Array<Hash>] the updated captured array
|
|
31
|
-
def self.record(tool_name:, tool_id:, input:, output:)
|
|
32
|
-
captured << {
|
|
33
|
-
tool_name: tool_name,
|
|
34
|
-
tool_id: tool_id,
|
|
35
|
-
input: input,
|
|
36
|
-
output: output
|
|
37
|
-
}
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Wrapper around ruby_llm for LLM inference
|
|
42
|
-
#
|
|
43
|
-
# RoboticModel provides a unified interface for LLM calls, handling:
|
|
44
|
-
# - Message format conversion via adapters
|
|
45
|
-
# - Tool registration and execution
|
|
46
|
-
# - Streaming support
|
|
47
|
-
#
|
|
48
|
-
# @example Basic usage
|
|
49
|
-
# model = RoboticModel.new("claude-sonnet-4", provider: :anthropic)
|
|
50
|
-
# messages = [TextMessage.new(role: :user, content: "Hello!")]
|
|
51
|
-
# response = model.infer(messages, [])
|
|
52
|
-
#
|
|
53
|
-
# @example With tools
|
|
54
|
-
# model.infer(messages, [weather_tool], tool_choice: "auto")
|
|
55
|
-
#
|
|
56
|
-
class RoboticModel
|
|
57
|
-
# @!attribute [r] model_id
|
|
58
|
-
# @return [String] the LLM model identifier
|
|
59
|
-
# @!attribute [r] provider
|
|
60
|
-
# @return [Symbol] the LLM provider (:anthropic, :openai, :gemini, etc.)
|
|
61
|
-
# @!attribute [r] adapter
|
|
62
|
-
# @return [Adapters::Base] the adapter for message conversion
|
|
63
|
-
attr_reader :model_id, :provider, :adapter
|
|
64
|
-
|
|
65
|
-
# Creates a new RoboticModel instance.
|
|
66
|
-
#
|
|
67
|
-
# @param model_id [String] the model identifier
|
|
68
|
-
# @param provider [Symbol, nil] the provider (auto-detected if not specified)
|
|
69
|
-
def initialize(model_id, provider: nil)
|
|
70
|
-
@model_id = model_id
|
|
71
|
-
@provider = provider || detect_provider(model_id)
|
|
72
|
-
@adapter = Adapters::Registry.for(@provider)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Perform inference with messages and optional tools
|
|
76
|
-
#
|
|
77
|
-
# @param messages [Array<Message>] Conversation messages
|
|
78
|
-
# @param tools [Array<Tool>] Available tools
|
|
79
|
-
# @param tool_choice [String, Symbol] Tool selection mode
|
|
80
|
-
# @param streaming [Proc, nil] Streaming callback
|
|
81
|
-
# @return [InferenceResponse]
|
|
82
|
-
#
|
|
83
|
-
def infer(messages, tools = [], tool_choice: "auto", streaming: nil, &block)
|
|
84
|
-
chat = create_chat
|
|
85
|
-
|
|
86
|
-
# Register tools if any
|
|
87
|
-
if tools.any?
|
|
88
|
-
ruby_llm_tools = create_ruby_llm_tools(tools)
|
|
89
|
-
chat = chat.with_tools(*ruby_llm_tools)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Add system message if present
|
|
93
|
-
system_content = @adapter.extract_system_message(messages)
|
|
94
|
-
chat = chat.with_instructions(system_content) if system_content
|
|
95
|
-
|
|
96
|
-
# Build conversation (excluding the last user message since ask() will add it)
|
|
97
|
-
conversation = @adapter.conversation_messages(messages)
|
|
98
|
-
conversation[0...-1].each do |msg|
|
|
99
|
-
add_message_to_chat(chat, msg)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Make the request (ask adds the user message)
|
|
103
|
-
user_content = conversation.last&.content || ""
|
|
104
|
-
|
|
105
|
-
# Clear tool execution capture before making the request
|
|
106
|
-
ToolExecutionCapture.clear!
|
|
107
|
-
|
|
108
|
-
response = if block_given? || streaming
|
|
109
|
-
chat.ask(user_content, &(block || streaming))
|
|
110
|
-
else
|
|
111
|
-
chat.ask(user_content)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# Parse response
|
|
115
|
-
output = @adapter.parse_response(response)
|
|
116
|
-
|
|
117
|
-
# Build captured tool results from auto-executed tools
|
|
118
|
-
captured_tool_results = build_captured_tool_results(tools)
|
|
119
|
-
|
|
120
|
-
InferenceResponse.new(
|
|
121
|
-
output: output,
|
|
122
|
-
raw: response,
|
|
123
|
-
model: model_id,
|
|
124
|
-
provider: provider,
|
|
125
|
-
captured_tool_results: captured_tool_results
|
|
126
|
-
)
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# Quick ask without full message array
|
|
130
|
-
#
|
|
131
|
-
# @param prompt [String] User prompt
|
|
132
|
-
# @param system [String, nil] System prompt
|
|
133
|
-
# @param tools [Array<Tool>] Available tools
|
|
134
|
-
# @return [InferenceResponse]
|
|
135
|
-
#
|
|
136
|
-
def ask(prompt, system: nil, tools: [], &block)
|
|
137
|
-
messages = []
|
|
138
|
-
messages << TextMessage.new(role: "system", content: system) if system
|
|
139
|
-
messages << TextMessage.new(role: "user", content: prompt)
|
|
140
|
-
|
|
141
|
-
infer(messages, tools, &block)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
private
|
|
145
|
-
|
|
146
|
-
def create_chat
|
|
147
|
-
RubyLLM.chat(model: model_id, provider: provider)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def create_ruby_llm_tools(tools)
|
|
151
|
-
tools.map do |tool|
|
|
152
|
-
# Create a dynamic RubyLLM::Tool subclass
|
|
153
|
-
create_tool_class(tool)
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def create_tool_class(tool)
|
|
158
|
-
# Build a RubyLLM::Tool subclass dynamically
|
|
159
|
-
tool_definition = tool
|
|
160
|
-
tool_name = tool.name
|
|
161
|
-
|
|
162
|
-
klass = Class.new(RubyLLM::Tool) do
|
|
163
|
-
description tool_definition.description || ""
|
|
164
|
-
|
|
165
|
-
# Add parameters from schema
|
|
166
|
-
schema = tool_definition.to_json_schema
|
|
167
|
-
if schema[:parameters] && schema[:parameters][:properties]
|
|
168
|
-
schema[:parameters][:properties].each do |prop_name, prop_def|
|
|
169
|
-
required = schema[:parameters][:required]&.include?(prop_name.to_s)
|
|
170
|
-
param prop_name.to_sym,
|
|
171
|
-
type: prop_def[:type] || "string",
|
|
172
|
-
desc: prop_def[:description],
|
|
173
|
-
required: required
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
define_method(:execute) do |**kwargs|
|
|
178
|
-
# This is called by ruby_llm when the tool is invoked
|
|
179
|
-
# Call the handler directly (bypassing Tool#call which requires context)
|
|
180
|
-
# Handlers should use **_context pattern to accept but ignore context
|
|
181
|
-
output = tool_definition.handler.call(kwargs, robot: nil, network: nil, step: nil)
|
|
182
|
-
|
|
183
|
-
# Record the execution for later retrieval
|
|
184
|
-
ToolExecutionCapture.record(
|
|
185
|
-
tool_name: tool_name,
|
|
186
|
-
tool_id: SecureRandom.uuid,
|
|
187
|
-
input: kwargs,
|
|
188
|
-
output: output
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
output
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
# Set the class name so RubyLLM can identify the tool
|
|
196
|
-
# RubyLLM converts class names to snake_case for tool identification
|
|
197
|
-
class_name = tool_name.split("_").map(&:capitalize).join
|
|
198
|
-
klass.define_singleton_method(:name) { class_name }
|
|
199
|
-
|
|
200
|
-
# Also define instance method for name (used by some RubyLLM code paths)
|
|
201
|
-
klass.define_method(:name) { tool_name }
|
|
202
|
-
|
|
203
|
-
# Store reference to our tool for later execution
|
|
204
|
-
klass.define_singleton_method(:robot_lab_tool) { tool_definition }
|
|
205
|
-
klass
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
def build_captured_tool_results(tools)
|
|
209
|
-
ToolExecutionCapture.captured.map do |capture|
|
|
210
|
-
_tool = tools.find { |t| t.name == capture[:tool_name] }
|
|
211
|
-
tool_message = ToolMessage.new(
|
|
212
|
-
id: capture[:tool_id],
|
|
213
|
-
name: capture[:tool_name],
|
|
214
|
-
input: capture[:input]
|
|
215
|
-
)
|
|
216
|
-
ToolResultMessage.new(
|
|
217
|
-
tool: tool_message,
|
|
218
|
-
content: { data: capture[:output] }
|
|
219
|
-
)
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def add_message_to_chat(chat, msg)
|
|
224
|
-
case msg
|
|
225
|
-
when TextMessage
|
|
226
|
-
if msg.user?
|
|
227
|
-
chat.add_message(role: :user, content: msg.content)
|
|
228
|
-
elsif msg.assistant?
|
|
229
|
-
chat.add_message(role: :assistant, content: msg.content)
|
|
230
|
-
end
|
|
231
|
-
when ToolResultMessage
|
|
232
|
-
# Tool results are handled by ruby_llm internally
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def detect_provider(model_id)
|
|
237
|
-
case model_id.to_s.downcase
|
|
238
|
-
when /^claude/, /^anthropic/
|
|
239
|
-
:anthropic
|
|
240
|
-
when /^gpt/, /^o1/, /^o3/, /^chatgpt/
|
|
241
|
-
:openai
|
|
242
|
-
when /^gemini/
|
|
243
|
-
:gemini
|
|
244
|
-
when /^llama/, /^mistral/, /^mixtral/
|
|
245
|
-
:ollama
|
|
246
|
-
else
|
|
247
|
-
RobotLab.configuration.default_provider
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
# Response from LLM inference.
|
|
253
|
-
#
|
|
254
|
-
# Contains the parsed output, raw response, and any captured tool results.
|
|
255
|
-
#
|
|
256
|
-
class InferenceResponse
|
|
257
|
-
# @!attribute [r] output
|
|
258
|
-
# @return [Array<Message>] parsed output messages
|
|
259
|
-
# @!attribute [r] raw
|
|
260
|
-
# @return [Object] the raw response from RubyLLM
|
|
261
|
-
# @!attribute [r] model
|
|
262
|
-
# @return [String] the model that generated the response
|
|
263
|
-
# @!attribute [r] provider
|
|
264
|
-
# @return [Symbol] the provider that handled the request
|
|
265
|
-
# @!attribute [r] captured_tool_results
|
|
266
|
-
# @return [Array<ToolResultMessage>] tool executions that were auto-executed
|
|
267
|
-
attr_reader :output, :raw, :model, :provider, :captured_tool_results
|
|
268
|
-
|
|
269
|
-
# Creates a new InferenceResponse instance.
|
|
270
|
-
#
|
|
271
|
-
# @param output [Array<Message>] parsed output messages
|
|
272
|
-
# @param raw [Object] raw response from RubyLLM
|
|
273
|
-
# @param model [String] model identifier
|
|
274
|
-
# @param provider [Symbol] provider identifier
|
|
275
|
-
# @param captured_tool_results [Array<ToolResultMessage>] captured results
|
|
276
|
-
def initialize(output:, raw:, model:, provider:, captured_tool_results: [])
|
|
277
|
-
@output = output
|
|
278
|
-
@raw = raw
|
|
279
|
-
@model = model
|
|
280
|
-
@provider = provider
|
|
281
|
-
@captured_tool_results = captured_tool_results
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
# Get the stop reason from the last output message
|
|
285
|
-
#
|
|
286
|
-
# @return [String, nil]
|
|
287
|
-
#
|
|
288
|
-
def stop_reason
|
|
289
|
-
output.last&.stop_reason
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
# Check if inference stopped naturally
|
|
293
|
-
#
|
|
294
|
-
# @return [Boolean]
|
|
295
|
-
#
|
|
296
|
-
def stopped?
|
|
297
|
-
stop_reason == "stop"
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
# Check if inference wants to call tools
|
|
301
|
-
#
|
|
302
|
-
# @return [Boolean]
|
|
303
|
-
#
|
|
304
|
-
def wants_tools?
|
|
305
|
-
stop_reason == "tool" || output.any?(&:tool_call?)
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
# Get all tool calls from the response
|
|
309
|
-
#
|
|
310
|
-
# @return [Array<ToolMessage>]
|
|
311
|
-
#
|
|
312
|
-
def tool_calls
|
|
313
|
-
output.select(&:tool_call?).flat_map(&:tools)
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
# Get the text content
|
|
317
|
-
#
|
|
318
|
-
# @return [String, nil]
|
|
319
|
-
#
|
|
320
|
-
def text_content
|
|
321
|
-
output.select(&:text?).map(&:content).join
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|