raix 0.8.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08737974243ed41d4db2406405a4d081e31972cf173cfc3b2859cb97eabf0848'
4
- data.tar.gz: 0d78927f5a35fad586f300bff4d86ce773d7bb7cd9f6787320e1cff6297f1aed
3
+ metadata.gz: 2de11b289a7c245c49e865735e1abc67ff671f02a9f23fb89d262d3ff83e6157
4
+ data.tar.gz: f8cd493f6f018ddd6b981f944786635b6800ca9beac4480e0a4c3c08bb7b8392
5
5
  SHA512:
6
- metadata.gz: c0eec6ef99a37cd8ba69dfec62c8be70c9a8f6ed0be78b24ed184bde364c78f5189ccac71e3196f56af4c85390844b044c30be1b69172fe4e0f3c584903ea7c0
7
- data.tar.gz: 90f084213b11dd737b55ed89fd21e75cf23b4c0ef5ab0daca8652f974b9fdb0f40a68ee07ea2abcd0b6af715ae3edc684643034b7e7e3455f7d05fae9ee1e473
6
+ metadata.gz: 4d26f6ffad99abb7eaf6c8ef072393d75625e4762206d0d1f94c811e9d44747fa2e9048d5a8951484ded2861ecd5ebac69ea39bf6163432a411e2f9e427b0533
7
+ data.tar.gz: 893d062ab1f23b6c6a47dc715a7c98a3886dbe092645642e74bdb97ad80b2b4f637305b95acc6e6a8984cfe6defcdf020410233f5f818cba16bbbd0c5f49b5ed
data/CHANGELOG.md CHANGED
@@ -1,4 +1,7 @@
1
- ## [0.8.0] - 2024-05-08
1
+ ## [0.8.1] - 2025-04-24
2
+ Added ability to filter tool functions (or disable completely) when calling `chat_completion`. Thanks to @parruda for the contribution.
3
+
4
+ ## [0.8.0] - 2025-04-23
2
5
  ### Added
3
6
  * **MCP integration (Experimental)** — new `Raix::MCP` concern and `mcp` DSL for declaring remote MCP servers.
4
7
  * Automatically fetches `tools/list`, registers remote tools as OpenAI‑compatible function schemas, and defines proxy methods that forward `tools/call`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- raix (0.8.0)
4
+ raix (0.8.1)
5
5
  activesupport (>= 6.0)
6
6
  faraday-retry (~> 2.0)
7
7
  open_router (~> 0.2)
data/README.md CHANGED
@@ -134,6 +134,41 @@ end
134
134
 
135
135
  Note that for security reasons, dispatching functions only works with functions implemented using `Raix::FunctionDispatch#function` or directly on the class.
136
136
 
137
+ #### Tool Filtering
138
+
139
+ You can control which tools are available to the AI on a given chat completion request using the `tools` parameter in the `chat_completion` method:
140
+
141
+ ```ruby
142
+ class WeatherAndTime
143
+ include Raix::ChatCompletion
144
+ include Raix::FunctionDispatch
145
+
146
+ function :check_weather, "Check the weather for a location", location: { type: "string" } do |arguments|
147
+ "The weather in #{arguments[:location]} is sunny"
148
+ end
149
+
150
+ function :get_time, "Get the current time" do |_arguments|
151
+ "The time is 12:00 PM"
152
+ end
153
+ end
154
+
155
+ weather = WeatherAndTime.new
156
+
157
+ # Don't pass any tools to the LLM
158
+ weather.chat_completion(tools: false)
159
+
160
+ # Only pass specific tools to the LLM
161
+ weather.chat_completion(tools: [:check_weather])
162
+
163
+ # Pass all declared tools (default behavior)
164
+ weather.chat_completion
165
+ ```
166
+
167
+ The `tools` parameter accepts three types of values:
168
+ - `false`: No tools are passed to the LLM
169
+ - An array of symbols: Only the specified tools are passed (raises `Raix::UndeclaredToolError` if any tool is not declared)
170
+ - Not provided: All declared tools are passed (default behavior)
171
+
137
172
  #### Multiple Tool Calls
138
173
 
139
174
  Some AI models (like GPT-4) can make multiple tool calls in a single response. When this happens, Raix will automatically handle all the function calls sequentially.
@@ -9,6 +9,8 @@ require "openai"
9
9
  require_relative "message_adapters/base"
10
10
 
11
11
  module Raix
12
+ class UndeclaredToolError < StandardError; end
13
+
12
14
  # The `ChatCompletion`` module is a Rails concern that provides a way to interact
13
15
  # with the OpenRouter Chat Completion API via its client. The module includes a few
14
16
  # methods that allow you to build a transcript of messages and then send them to
@@ -44,8 +46,9 @@ module Raix
44
46
  # @option params [Boolean] :openai (false) Whether to use OpenAI's API instead of OpenRouter's.
45
47
  # @option params [Boolean] :raw (false) Whether to return the raw response or dig the text content.
46
48
  # @option params [Array] :messages (nil) An array of messages to use instead of the transcript.
49
+ # @option tools [Array|false] :tools (nil) Tools to pass to the LLM. If false, no tools are passed. If an array, only declared tools in the array are passed.
47
50
  # @return [String|Hash] The completed chat response.
48
- def chat_completion(params: {}, loop: false, json: false, raw: false, openai: false, save_response: true, messages: nil)
51
+ def chat_completion(params: {}, loop: false, json: false, raw: false, openai: false, save_response: true, messages: nil, tools: nil)
49
52
  # set params to default values if not provided
50
53
  params[:cache_at] ||= cache_at.presence
51
54
  params[:frequency_penalty] ||= frequency_penalty.presence
@@ -63,7 +66,13 @@ module Raix
63
66
  params[:stop] ||= stop.presence
64
67
  params[:temperature] ||= temperature.presence || Raix.configuration.temperature
65
68
  params[:tool_choice] ||= tool_choice.presence
66
- params[:tools] ||= tools.presence
69
+ params[:tools] = if tools == false
70
+ nil
71
+ elsif tools.is_a?(Array)
72
+ filtered_tools(tools)
73
+ else
74
+ self.tools.presence
75
+ end
67
76
  params[:top_a] ||= top_a.presence
68
77
  params[:top_k] ||= top_k.presence
69
78
  params[:top_logprobs] ||= top_logprobs.presence
@@ -182,6 +191,18 @@ module Raix
182
191
 
183
192
  private
184
193
 
194
+ def filtered_tools(tool_names)
195
+ return nil if tool_names.blank?
196
+
197
+ requested_tools = tool_names.map(&:to_sym)
198
+ available_tool_names = tools.map { |tool| tool.dig(:function, :name).to_sym }
199
+
200
+ undeclared_tools = requested_tools - available_tool_names
201
+ raise UndeclaredToolError, "Undeclared tools: #{undeclared_tools.join(", ")}" if undeclared_tools.any?
202
+
203
+ tools.select { |tool| requested_tools.include?(tool.dig(:function, :name).to_sym) }
204
+ end
205
+
185
206
  def openai_request(params:, model:, messages:)
186
207
  if params[:prediction]
187
208
  params.delete(:max_completion_tokens)
@@ -94,10 +94,7 @@ module Raix
94
94
  end
95
95
 
96
96
  def chat_completion(**chat_completion_args)
97
- raise "No functions defined" if self.class.functions.blank?
98
-
99
97
  self.chat_completion_args = chat_completion_args
100
-
101
98
  super
102
99
  end
103
100
 
@@ -109,6 +106,8 @@ module Raix
109
106
  end
110
107
 
111
108
  def tools
109
+ return [] unless self.class.functions
110
+
112
111
  self.class.functions.map { |function| { type: "function", function: } }
113
112
  end
114
113
  end
data/lib/raix/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Raix
4
- VERSION = "0.8.0"
4
+ VERSION = "0.8.1"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: raix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Obie Fernandez
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-23 00:00:00.000000000 Z
10
+ date: 2025-04-25 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport