raix 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/Gemfile.lock +6 -1
- data/README.md +1 -1
- data/lib/raix/chat_completion.rb +179 -0
- data/lib/raix/function_dispatch.rb +111 -0
- data/lib/raix/prompt_declarations.rb +118 -0
- data/lib/raix/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29e66d0046995dca8f9d093ccfd719e54905f94c62d5ee4e78588e1b40b0dadd
|
4
|
+
data.tar.gz: 7b1d4544576891124e209130d339be55fe35573e05dcb05474c526655e850390
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8989d6e4c4422054a2e452637ffc3205a7242a060f32c86fcf5c72ff1050f50d7bc6b20a9e4eb147398cdbc461c6fe80cf1f1426e0401fe944ce484ae70d4f9
|
7
|
+
data.tar.gz: 364ba4571799b8a7eea4abae9f4a905a32121303f62e22e66bff9f4663831b6311efa3eb9238f4eaa326456c2db467d7de0277000e42a11db710435c3e482679
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.2
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
raix (0.1
|
4
|
+
raix (0.3.1)
|
5
5
|
activesupport (>= 6.0)
|
6
6
|
open_router (~> 0.2)
|
7
7
|
|
@@ -41,6 +41,7 @@ GEM
|
|
41
41
|
faraday-retry (2.2.1)
|
42
42
|
faraday (~> 2.0)
|
43
43
|
ffi (1.17.0-arm64-darwin)
|
44
|
+
ffi (1.17.0-x86_64-linux-gnu)
|
44
45
|
formatador (1.1.0)
|
45
46
|
guard (2.18.1)
|
46
47
|
formatador (>= 0.2.4)
|
@@ -79,6 +80,8 @@ GEM
|
|
79
80
|
netrc (0.11.0)
|
80
81
|
nokogiri (1.16.6-arm64-darwin)
|
81
82
|
racc (~> 1.4)
|
83
|
+
nokogiri (1.16.6-x86_64-linux)
|
84
|
+
racc (~> 1.4)
|
82
85
|
notiffany (0.1.3)
|
83
86
|
nenv (~> 0.1)
|
84
87
|
shellany (~> 0.0)
|
@@ -164,6 +167,7 @@ GEM
|
|
164
167
|
sorbet-static (= 0.5.11447)
|
165
168
|
sorbet-runtime (0.5.11447)
|
166
169
|
sorbet-static (0.5.11447-universal-darwin)
|
170
|
+
sorbet-static (0.5.11447-x86_64-linux)
|
167
171
|
sorbet-static-and-runtime (0.5.11447)
|
168
172
|
sorbet (= 0.5.11447)
|
169
173
|
sorbet-runtime (= 0.5.11447)
|
@@ -194,6 +198,7 @@ GEM
|
|
194
198
|
|
195
199
|
PLATFORMS
|
196
200
|
arm64-darwin-21
|
201
|
+
x86_64-linux
|
197
202
|
|
198
203
|
DEPENDENCIES
|
199
204
|
activesupport (>= 6.0)
|
data/README.md
CHANGED
@@ -235,4 +235,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
235
235
|
|
236
236
|
## Code of Conduct
|
237
237
|
|
238
|
-
Everyone interacting in the Raix
|
238
|
+
Everyone interacting in the Raix project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[OlympiaAI]/raix/blob/main/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_support/core_ext/object/blank"
|
5
|
+
require "open_router"
|
6
|
+
require "openai"
|
7
|
+
|
8
|
+
module Raix
|
9
|
+
# The `ChatCompletion`` module is a Rails concern that provides a way to interact
|
10
|
+
# with the OpenRouter Chat Completion API via its client. The module includes a few
|
11
|
+
# methods that allow you to build a transcript of messages and then send them to
|
12
|
+
# the API for completion. The API will return a response that you can use however
|
13
|
+
# you see fit. If the response includes a function call, the module will dispatch
|
14
|
+
# the function call and return the result. Which implies that function calls need
|
15
|
+
# to be defined on the class that includes this module. (Note: You should probably
|
16
|
+
# use the `FunctionDispatch` module to define functions instead of doing it manually.)
|
17
|
+
module ChatCompletion
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
attr_accessor :frequency_penalty, :logit_bias, :logprobs, :loop, :min_p, :model, :presence_penalty,
|
21
|
+
:repetition_penalty, :response_format, :stream, :temperature, :max_tokens, :seed, :stop, :top_a,
|
22
|
+
:top_k, :top_logprobs, :top_p, :tools, :tool_choice, :provider
|
23
|
+
|
24
|
+
# This method performs chat completion based on the provided transcript and parameters.
|
25
|
+
#
|
26
|
+
# @param params [Hash] The parameters for chat completion.
|
27
|
+
# @option loop [Boolean] :loop (false) Whether to loop the chat completion after function calls.
|
28
|
+
# @option params [Boolean] :json (false) Whether to return the parse the response as a JSON object.
|
29
|
+
# @option params [Boolean] :openai (false) Whether to use OpenAI's API instead of OpenRouter's.
|
30
|
+
# @option params [Boolean] :raw (false) Whether to return the raw response or dig the text content.
|
31
|
+
# @return [String|Hash] The completed chat response.
|
32
|
+
def chat_completion(params: {}, loop: false, json: false, raw: false, openai: false)
|
33
|
+
messages = transcript.flatten.compact.map { |msg| transform_message_format(msg) }
|
34
|
+
raise "Can't complete an empty transcript" if messages.blank?
|
35
|
+
|
36
|
+
# used by FunctionDispatch
|
37
|
+
self.loop = loop
|
38
|
+
|
39
|
+
# set params to default values if not provided
|
40
|
+
params[:frequency_penalty] ||= frequency_penalty.presence
|
41
|
+
params[:logit_bias] ||= logit_bias.presence
|
42
|
+
params[:logprobs] ||= logprobs.presence
|
43
|
+
params[:max_tokens] ||= max_tokens.presence || Raix.configuration.max_tokens
|
44
|
+
params[:min_p] ||= min_p.presence
|
45
|
+
params[:presence_penalty] ||= presence_penalty.presence
|
46
|
+
params[:provider] ||= provider.presence
|
47
|
+
params[:repetition_penalty] ||= repetition_penalty.presence
|
48
|
+
params[:response_format] ||= response_format.presence
|
49
|
+
params[:seed] ||= seed.presence
|
50
|
+
params[:stop] ||= stop.presence
|
51
|
+
params[:temperature] ||= temperature.presence || Raix.configuration.temperature
|
52
|
+
params[:tool_choice] ||= tool_choice.presence
|
53
|
+
params[:tools] ||= tools.presence
|
54
|
+
params[:top_a] ||= top_a.presence
|
55
|
+
params[:top_k] ||= top_k.presence
|
56
|
+
params[:top_logprobs] ||= top_logprobs.presence
|
57
|
+
params[:top_p] ||= top_p.presence
|
58
|
+
|
59
|
+
if json
|
60
|
+
params[:provider] ||= {}
|
61
|
+
params[:provider][:require_parameters] = true
|
62
|
+
params[:response_format] ||= {}
|
63
|
+
params[:response_format][:type] = "json_object"
|
64
|
+
end
|
65
|
+
|
66
|
+
# set the model to the default if not provided
|
67
|
+
self.model ||= Raix.configuration.model
|
68
|
+
|
69
|
+
begin
|
70
|
+
response = if openai
|
71
|
+
openai_request(params:, model: openai,
|
72
|
+
messages:)
|
73
|
+
else
|
74
|
+
openrouter_request(
|
75
|
+
params:, model:, messages:
|
76
|
+
)
|
77
|
+
end
|
78
|
+
retry_count = 0
|
79
|
+
content = nil
|
80
|
+
|
81
|
+
# no need for additional processing if streaming
|
82
|
+
return if stream && response.blank?
|
83
|
+
|
84
|
+
# tuck the full response into a thread local in case needed
|
85
|
+
Thread.current[:chat_completion_response] = response.with_indifferent_access
|
86
|
+
|
87
|
+
# TODO: add a standardized callback hook for usage events
|
88
|
+
# broadcast(:usage_event, usage_subject, self.class.name.to_s, response, premium?)
|
89
|
+
|
90
|
+
# TODO: handle parallel tool calls
|
91
|
+
if (function = response.dig("choices", 0, "message", "tool_calls", 0, "function"))
|
92
|
+
@current_function = function["name"]
|
93
|
+
# dispatch the called function
|
94
|
+
arguments = JSON.parse(function["arguments"].presence || "{}")
|
95
|
+
arguments[:bot_message] = bot_message if respond_to?(:bot_message)
|
96
|
+
return send(function["name"], arguments.with_indifferent_access)
|
97
|
+
end
|
98
|
+
|
99
|
+
response.tap do |res|
|
100
|
+
content = res.dig("choices", 0, "message", "content")
|
101
|
+
if json
|
102
|
+
content = content.squish
|
103
|
+
return JSON.parse(content)
|
104
|
+
end
|
105
|
+
|
106
|
+
return content unless raw
|
107
|
+
end
|
108
|
+
rescue JSON::ParserError => e
|
109
|
+
if e.message.include?("not a valid") # blank JSON
|
110
|
+
puts "Retrying blank JSON response... (#{retry_count} attempts) #{e.message}"
|
111
|
+
retry_count += 1
|
112
|
+
sleep 1 * retry_count # backoff
|
113
|
+
retry if retry_count < 3
|
114
|
+
|
115
|
+
raise e # just fail if we can't get content after 3 attempts
|
116
|
+
end
|
117
|
+
|
118
|
+
# attempt to fix the JSON
|
119
|
+
JsonFixer.new.call(content, e.message)
|
120
|
+
rescue Faraday::BadRequestError => e
|
121
|
+
# make sure we see the actual error message on console or Honeybadger
|
122
|
+
puts "Chat completion failed!!!!!!!!!!!!!!!!: #{e.response[:body]}"
|
123
|
+
raise e
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# This method returns the transcript array.
|
128
|
+
# Manually add your messages to it in the following abbreviated format
|
129
|
+
# before calling `chat_completion`.
|
130
|
+
#
|
131
|
+
# { system: "You are a pumpkin" },
|
132
|
+
# { user: "Hey what time is it?" },
|
133
|
+
# { assistant: "Sorry, pumpkins do not wear watches" }
|
134
|
+
#
|
135
|
+
# to add a function result use the following format:
|
136
|
+
# { function: result, name: 'fancy_pants_function' }
|
137
|
+
#
|
138
|
+
# @return [Array] The transcript array.
|
139
|
+
def transcript
|
140
|
+
@transcript ||= []
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
def openai_request(params:, model:, messages:)
|
146
|
+
params[:stream] ||= stream.presence
|
147
|
+
Raix.configuration.openai_client.chat(parameters: params.compact.merge(model:, messages:))
|
148
|
+
end
|
149
|
+
|
150
|
+
def openrouter_request(params:, model:, messages:)
|
151
|
+
retry_count = 0
|
152
|
+
|
153
|
+
begin
|
154
|
+
Raix.configuration.openrouter_client.complete(messages, model:, extras: params.compact, stream:)
|
155
|
+
rescue OpenRouter::ServerError => e
|
156
|
+
if e.message.include?("retry")
|
157
|
+
puts "Retrying OpenRouter request... (#{retry_count} attempts) #{e.message}"
|
158
|
+
retry_count += 1
|
159
|
+
sleep 1 * retry_count # backoff
|
160
|
+
retry if retry_count < 5
|
161
|
+
end
|
162
|
+
|
163
|
+
raise e
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def transform_message_format(message)
|
168
|
+
return message if message[:role].present?
|
169
|
+
|
170
|
+
if message[:function].present?
|
171
|
+
{ role: "assistant", name: message.dig(:function, :name), content: message.dig(:function, :arguments).to_json }
|
172
|
+
elsif message[:result].present?
|
173
|
+
{ role: "function", name: message[:name], content: message[:result] }
|
174
|
+
else
|
175
|
+
{ role: message.first.first, content: message.first.last }
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
module Raix
|
5
|
+
# Provides declarative function definition for ChatCompletion classes.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# class MeaningOfLife
|
10
|
+
# include Raix::ChatCompletion
|
11
|
+
# include Raix::FunctionDispatch
|
12
|
+
#
|
13
|
+
# function :ask_deep_thought do
|
14
|
+
# wait 236_682_000_000_000
|
15
|
+
# "The meaning of life is 42"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def initialize
|
19
|
+
# transcript << { user: "What is the meaning of life?" }
|
20
|
+
# chat_completion
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
module FunctionDispatch
|
24
|
+
extend ActiveSupport::Concern
|
25
|
+
|
26
|
+
class_methods do
|
27
|
+
attr_reader :functions
|
28
|
+
|
29
|
+
# Defines a function that can be dispatched by the ChatCompletion module while
|
30
|
+
# processing the response from an AI model.
|
31
|
+
#
|
32
|
+
# Declaring a function here will automatically add it (in JSON Schema format) to
|
33
|
+
# the list of tools provided to the OpenRouter Chat Completion API. The function
|
34
|
+
# will be dispatched by name, so make sure the name is unique. The function's block
|
35
|
+
# argument will be executed in the instance context of the class that includes this module.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
# function :google_search, description: "Search Google for something", query: { type: "string" } do |arguments|
|
39
|
+
# GoogleSearch.new(arguments[:query]).search
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# @param name [Symbol] The name of the function.
|
43
|
+
# @param description [String] An optional description of the function.
|
44
|
+
# @param parameters [Hash] The parameters that the function accepts.
|
45
|
+
# @param block [Proc] The block of code to execute when the function is called.
|
46
|
+
def function(name, description = nil, **parameters, &block)
|
47
|
+
@functions ||= []
|
48
|
+
@functions << begin
|
49
|
+
{ name:, parameters: { type: "object", properties: {} } }.tap do |definition|
|
50
|
+
definition[:description] = description if description.present?
|
51
|
+
parameters.map do |key, value|
|
52
|
+
definition[:parameters][:properties][key] = value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
define_method(name) do |arguments|
|
58
|
+
id = SecureRandom.uuid[0, 23]
|
59
|
+
transcript << {
|
60
|
+
role: "assistant",
|
61
|
+
content: nil,
|
62
|
+
tool_calls: [
|
63
|
+
{
|
64
|
+
id:,
|
65
|
+
type: "function",
|
66
|
+
function: {
|
67
|
+
name:,
|
68
|
+
arguments: arguments.to_json
|
69
|
+
}
|
70
|
+
}
|
71
|
+
]
|
72
|
+
}
|
73
|
+
instance_exec(arguments, &block).tap do |content|
|
74
|
+
transcript << {
|
75
|
+
role: "tool",
|
76
|
+
tool_call_id: id,
|
77
|
+
name:,
|
78
|
+
content: content.to_s
|
79
|
+
}
|
80
|
+
# TODO: add on_error handler as optional parameter to function
|
81
|
+
end
|
82
|
+
|
83
|
+
chat_completion(**chat_completion_args) if loop
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
included do
|
89
|
+
attr_accessor :chat_completion_args
|
90
|
+
end
|
91
|
+
|
92
|
+
def chat_completion(**chat_completion_args)
|
93
|
+
raise "No functions defined" if self.class.functions.blank?
|
94
|
+
|
95
|
+
self.chat_completion_args = chat_completion_args
|
96
|
+
|
97
|
+
super
|
98
|
+
end
|
99
|
+
|
100
|
+
# Stops the looping of chat completion after function calls.
|
101
|
+
# Useful for manually halting processing in workflow components
|
102
|
+
# that do not require a final text response to an end user.
|
103
|
+
def stop_looping!
|
104
|
+
self.loop = false
|
105
|
+
end
|
106
|
+
|
107
|
+
def tools
|
108
|
+
self.class.functions.map { |function| { type: "function", function: } }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
|
5
|
+
module Raix
|
6
|
+
# The PromptDeclarations module provides a way to chain prompts and handle
|
7
|
+
# user responses in a serialized manner (in the order they were defined),
|
8
|
+
# with support for functions if the FunctionDispatch module is also included.
|
9
|
+
module PromptDeclarations
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
extend ChatCompletion
|
12
|
+
|
13
|
+
module ClassMethods # rubocop:disable Style/Documentation
|
14
|
+
# Adds a prompt to the list of prompts.
|
15
|
+
#
|
16
|
+
# @param system [Proc] A lambda that generates the system message.
|
17
|
+
# @param text [Proc] A lambda that generates the prompt text. (Required)
|
18
|
+
# @param success [Proc] The block of code to execute when the prompt is answered.
|
19
|
+
# @param parameters [Hash] Additional parameters for the completion API call
|
20
|
+
# @param stream [Boolean] Whether to stream the response.
|
21
|
+
def prompt(text:, system: nil, success: nil, params: {}, stream: false)
|
22
|
+
name = Digest::SHA256.hexdigest(text.inspect)[0..7]
|
23
|
+
prompts << begin
|
24
|
+
OpenStruct.new({ name:, system:, text:, success:, params:, stream: })
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method(name) do |response|
|
28
|
+
if Rails.env.local?
|
29
|
+
puts "_" * 80
|
30
|
+
puts "PromptDeclarations#response:"
|
31
|
+
puts "#{text.source_location} (#{name})"
|
32
|
+
puts response
|
33
|
+
puts "_" * 80
|
34
|
+
end
|
35
|
+
|
36
|
+
return response if success.nil?
|
37
|
+
return send(success, response) if success.is_a?(Symbol)
|
38
|
+
|
39
|
+
instance_exec(response, &success)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# the list of prompts declared at class level
|
44
|
+
def prompts
|
45
|
+
@prompts ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
# getter/setter for system prompt declared at class level
|
49
|
+
def system_prompt(prompt = nil)
|
50
|
+
prompt ? @system_prompt = prompt.squish : @system_prompt
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Executes the chat completion process based on the class-level declared prompts.
|
55
|
+
# The response to each prompt is added to the transcript automatically and returned.
|
56
|
+
#
|
57
|
+
# Prompts require at least a `text` lambda parameter.
|
58
|
+
#
|
59
|
+
# @param params [Hash] Parameters for the chat completion override those defined in the current prompt.
|
60
|
+
# @option params [Boolean] :raw (false) Whether to return the raw response or dig the text content.
|
61
|
+
#
|
62
|
+
# Uses system prompt in following order of priority:
|
63
|
+
# - system lambda specified in the prompt declaration
|
64
|
+
# - system_prompt instance method if defined
|
65
|
+
# - system_prompt class-level declaration if defined
|
66
|
+
#
|
67
|
+
# TODO: shortcut syntax passes just a string prompt if no other options are needed.
|
68
|
+
#
|
69
|
+
# @raise [RuntimeError] If no prompts are defined.
|
70
|
+
#
|
71
|
+
def chat_completion(params: {}, raw: false)
|
72
|
+
raise "No prompts defined" unless self.class.prompts.present?
|
73
|
+
|
74
|
+
current_prompts = self.class.prompts.clone
|
75
|
+
|
76
|
+
while (@current_prompt = current_prompts.shift)
|
77
|
+
__system_prompt = instance_exec(&@current_prompt.system) if @current_prompt.system.present? # rubocop:disable Lint/UnderscorePrefixedVariableName
|
78
|
+
__system_prompt ||= system_prompt if respond_to?(:system_prompt)
|
79
|
+
__system_prompt ||= self.class.system_prompt.presence
|
80
|
+
transcript << { system: __system_prompt } if __system_prompt
|
81
|
+
transcript << { user: instance_exec(&@current_prompt.text) } # text is required
|
82
|
+
|
83
|
+
params = @current_prompt.params.merge(params)
|
84
|
+
|
85
|
+
# set the stream if necessary
|
86
|
+
self.stream = instance_exec(¤t_prompt.stream) if current_prompt.stream.present?
|
87
|
+
|
88
|
+
super(params:, raw:).then do |response|
|
89
|
+
transcript << { assistant: response }
|
90
|
+
@last_response = send(@current_prompt.name, response)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
@last_response
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the model parameter of the current prompt or the default model.
|
98
|
+
#
|
99
|
+
# @return [Object] The model parameter of the current prompt or the default model.
|
100
|
+
def model
|
101
|
+
@current_prompt.params[:model] || super
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the temperature parameter of the current prompt or the default temperature.
|
105
|
+
#
|
106
|
+
# @return [Float] The temperature parameter of the current prompt or the default temperature.
|
107
|
+
def temperature
|
108
|
+
@current_prompt.params[:temperature] || super
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the max_tokens parameter of the current prompt or the default max_tokens.
|
112
|
+
#
|
113
|
+
# @return [Integer] The max_tokens parameter of the current prompt or the default max_tokens.
|
114
|
+
def max_tokens
|
115
|
+
@current_prompt.params[:max_tokens] || super
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/raix/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Obie Fernandez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -47,6 +47,7 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- ".rspec"
|
49
49
|
- ".rubocop.yml"
|
50
|
+
- ".ruby-version"
|
50
51
|
- CHANGELOG.md
|
51
52
|
- CODE_OF_CONDUCT.md
|
52
53
|
- Gemfile
|
@@ -55,6 +56,9 @@ files:
|
|
55
56
|
- README.md
|
56
57
|
- Rakefile
|
57
58
|
- lib/raix.rb
|
59
|
+
- lib/raix/chat_completion.rb
|
60
|
+
- lib/raix/function_dispatch.rb
|
61
|
+
- lib/raix/prompt_declarations.rb
|
58
62
|
- lib/raix/version.rb
|
59
63
|
- raix.gemspec
|
60
64
|
- sig/raix.rbs
|