Module: RubyLLM::Protocols::ChatCompletions::Tools
- Defined in:
- lib/ruby_llm/protocols/chat_completions/tools.rb
Overview
Tools methods of the OpenAI API integration
Constant Summary collapse
- EMPTY_PARAMETERS_SCHEMA =
{ 'type' => 'object', 'properties' => {}, 'required' => [], 'additionalProperties' => false, 'strict' => true }.freeze
Class Method Summary collapse
- .build_tool_choice(tool_choice) ⇒ Object
- .extract_tool_call_thought_signature(tool_call) ⇒ Object
- .format_tool_calls(tool_calls) ⇒ Object
- .parameters_schema_for(tool) ⇒ Object
- .parse_tool_call_arguments(tool_call, response: nil, finish_reason: nil) ⇒ Object
-
.parse_tool_calls(tool_calls, parse_arguments: true, response: nil, finish_reason: nil, stream_keys: false) ⇒ Object
Streaming deltas key by index so id-less argument fragments find their call even when a delta batches or interleaves several calls; complete responses key by id, which tool results join on.
- .schema_from_parameters(parameters) ⇒ Object
- .tool_for(tool) ⇒ Object
Class Method Details
.build_tool_choice(tool_choice) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 103 def build_tool_choice(tool_choice) case tool_choice when :auto, :none, :required tool_choice else { type: 'function', function: { name: tool_choice } } end end |
.extract_tool_call_thought_signature(tool_call) ⇒ Object
117 118 119 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 117 def extract_tool_call_thought_signature(tool_call) tool_call.dig('extra_content', 'google', 'thought_signature') end |
.format_tool_calls(tool_calls) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 47 def format_tool_calls(tool_calls) return nil unless tool_calls&.any? tool_calls.map do |_, tc| call = { id: tc.id, type: 'function', function: { name: tc.name, arguments: JSON.generate(tc.arguments) } } if tc.thought_signature call[:extra_content] = { google: { thought_signature: tc.thought_signature } } end call end end |
.parameters_schema_for(tool) ⇒ Object
20 21 22 23 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 20 def parameters_schema_for(tool) tool.parameters_schema || schema_from_parameters(tool.declared_parameters) end |
.parse_tool_call_arguments(tool_call, response: nil, finish_reason: nil) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 68 def parse_tool_call_arguments(tool_call, response: nil, finish_reason: nil) arguments = tool_call.dig('function', 'arguments') if arguments.nil? || arguments.empty? {} else JSON.parse(arguments) end rescue JSON::ParserError => e raise ToolCallParseError.new(response: response, finish_reason: finish_reason), cause: e end |
.parse_tool_calls(tool_calls, parse_arguments: true, response: nil, finish_reason: nil, stream_keys: false) ⇒ Object
Streaming deltas key by index so id-less argument fragments find their call even when a delta batches or interleaves several calls; complete responses key by id, which tool results join on.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 83 def parse_tool_calls(tool_calls, parse_arguments: true, response: nil, finish_reason: nil, stream_keys: false) return nil unless tool_calls&.any? tool_calls.to_h do |tc| [ stream_keys ? tc['index'] || tc['id'] : tc['id'], ToolCall.new( id: tc['id'], name: tc.dig('function', 'name'), arguments: if parse_arguments parse_tool_call_arguments(tc, response: response, finish_reason: finish_reason) else tc.dig('function', 'arguments') end, thought_signature: extract_tool_call_thought_signature(tc) ) ] end end |
.schema_from_parameters(parameters) ⇒ Object
25 26 27 28 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 25 def schema_from_parameters(parameters) schema_definition = RubyLLM::Tool::SchemaDefinition.from_parameters(parameters) schema_definition&.json_schema || EMPTY_PARAMETERS_SCHEMA end |
.tool_for(tool) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/ruby_llm/protocols/chat_completions/tools.rb', line 30 def tool_for(tool) parameters_schema = parameters_schema_for(tool) definition = { type: 'function', function: { name: tool.name, description: tool.description, parameters: parameters_schema } } return definition if tool..empty? RubyLLM::Support::Utils.deep_merge(definition, tool.) end |