raix 0.7.1 → 0.7.3

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: 9a2990e8225edcfbcc5007aae41a0dd69987bff18bd085bb9c486561e5597044
4
- data.tar.gz: 60ef3efa8eb6cbe1b445afd09fc65a4b1d6fc62c872588956baee46b511d79d3
3
+ metadata.gz: 90b0072e3af33e82ccfb040554e9645920e34b4477457ba79335582c9325a7bd
4
+ data.tar.gz: beeb6e0b98b473597d2191b5005fc89cb57fe69633cfe1e8927a6c1c0f61048f
5
5
  SHA512:
6
- metadata.gz: dfa0a7dfed2782d49c95f749c847b024ef41097b4ab318b34f9eabbfd9f754cf49c6eb859c1b14534332efea930d707df457e2d24a4c1f30f043d7dacb3c801c
7
- data.tar.gz: 2e291a98b2ed5e25c2381a30d609e4277cb94458531c03e77b79fc95e70ee92e40c0d9cacb31809a1f7acca860550e4d02698856321869144dc56a4d794ea3d8
6
+ metadata.gz: cbc28460d07263899c0e45be8ccfd3fa522b3162ad2a53d640c1ff0cccb6c7d96f7ab4bef2afa809d47733a98a4a502602b78a6c53918e676955da9d88220f69
7
+ data.tar.gz: d5e4f7dedaeb3ab2de64168f17a9de920a18894d5acfff22c0e00b870bdf96c77478130a61d47f82f7cc01a566b1cbc95f41fb43241cb3ece24c743b80993fed
data/CHANGELOG.md CHANGED
@@ -1,4 +1,14 @@
1
- ## [0.7] - 2024-04-02
1
+ ## [0.7.3] - 2025-04-23
2
+
3
+ ## [0.7.2] - 2025-04-19
4
+ - adds support for `messages` parameter in `chat_completion` to override the transcript
5
+ - fixes potential race conditions in parallel chat completion calls by duplicating transcript
6
+
7
+ ## [0.7.1] - 2025-04-10
8
+ - adds support for JSON response format with automatic parsing
9
+ - improves error handling for JSON parsing failures
10
+
11
+ ## [0.7] - 2025-04-02
2
12
  - adds support for `until` condition in `PromptDeclarations` to control prompt looping
3
13
  - adds support for `if` and `unless` conditions in `PromptDeclarations` to control prompt execution
4
14
  - adds support for `success` callback in `PromptDeclarations` to handle prompt responses
@@ -22,39 +32,38 @@
22
32
  - adds `save_response` option to `chat_completion` to control transcript updates
23
33
  - fixes potential race conditions in transcript handling
24
34
 
25
- ## [0.1.0] - 2024-04-03
35
+ ## [0.4.8] - 2024-11-12
36
+ - adds documentation for `Predicate` maybe handler
37
+ - logs to stdout when a response is unhandled by `Predicate`
26
38
 
27
- - Initial release, placeholder gem
39
+ ## [0.4.7] - 2024-11-12
40
+ - adds missing requires `raix/predicate` so that it can be used in a Rails app automatically
41
+ - adds missing openai support for `Predicate`
28
42
 
29
- ## [0.2.0] - tbd
30
- - adds `ChatCompletion` module
31
- - adds `PromptDeclarations` module
32
- - adds `FunctionDispatch` module
43
+ ## [0.4.5] - 2024-11-11
44
+ - adds support for `ResponseFormat`
45
+ - added some missing requires to support String#squish
33
46
 
34
- ## [0.3.2] - 2024-06-29
35
- - adds support for streaming
47
+ ## [0.4.4] - 2024-11-11
48
+ - adds support for multiple tool calls in a single response
36
49
 
37
- ## [0.4.0] - 2024-10-18
38
- - adds support for Anthropic-style prompt caching
39
- - defaults to `max_completion_tokens` when using OpenAI directly
50
+ ## [0.4.3] - 2024-11-11
51
+ - adds support for `Predicate` module
40
52
 
41
53
  ## [0.4.2] - 2024-11-05
42
54
  - adds support for [Predicted Outputs](https://platform.openai.com/docs/guides/latency-optimization#use-predicted-outputs) with the `prediction` option for OpenAI
43
55
 
44
- ## [0.4.3] - 2024-11-11
45
- - adds support for `Predicate` module
46
-
47
- ## [0.4.4] - 2024-11-11
48
- - adds support for multiple tool calls in a single response
56
+ ## [0.4.0] - 2024-10-18
57
+ - adds support for Anthropic-style prompt caching
58
+ - defaults to `max_completion_tokens` when using OpenAI directly
49
59
 
50
- ## [0.4.5] - 2024-11-11
51
- - adds support for `ResponseFormat`
52
- - added some missing requires to support String#squish
60
+ ## [0.3.2] - 2024-06-29
61
+ - adds support for streaming
53
62
 
54
- ## [0.4.7] - 2024-11-12
55
- - adds missing requires `raix/predicate` so that it can be used in a Rails app automatically
56
- - adds missing openai support for `Predicate`
63
+ ## [0.2.0] - tbd
64
+ - adds `ChatCompletion` module
65
+ - adds `PromptDeclarations` module
66
+ - adds `FunctionDispatch` module
57
67
 
58
- ## [0.4.8] - 2024-11-12
59
- - adds documentation for `Predicate` maybe handler
60
- - logs to stdout when a response is unhandled by `Predicate`
68
+ ## [0.1.0] - 2024-04-03
69
+ - Initial release, placeholder gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- raix (0.7.1)
4
+ raix (0.7.3)
5
5
  activesupport (>= 6.0)
6
6
  open_router (~> 0.2)
7
7
  ruby-openai (~> 7.0)
@@ -211,6 +211,7 @@ GEM
211
211
  PLATFORMS
212
212
  arm64-darwin-21
213
213
  arm64-darwin-22
214
+ arm64-darwin-23
214
215
  arm64-darwin-24
215
216
  x86_64-linux
216
217
 
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Raix (pronounced "ray" because the x is silent) is a library that gives you everything you need to add discrete large-language model (LLM) AI components to your Ruby applications. Raix consists of proven code that has been extracted from [Olympia](https://olympia.chat), the world's leading virtual AI team platform, and probably one of the biggest and most successful AI chat projects written completely in Ruby.
6
6
 
7
- Understanding the how to use discrete AI components in otherwise normal code is key to productively leveraging Raix, and the subject of a book written by Raix's author Obie Fernandez, titled [Patterns of Application Development Using AI](https://leanpub.com/patterns-of-application-development-using-ai). You can easily support the ongoing development of this project by buying the book at Leanpub.
7
+ Understanding how to use discrete AI components in otherwise normal code is key to productively leveraging Raix, and the subject of a book written by Raix's author Obie Fernandez, titled [Patterns of Application Development Using AI](https://leanpub.com/patterns-of-application-development-using-ai). You can easily support the ongoing development of this project by buying the book at Leanpub.
8
8
 
9
9
  At the moment, Raix natively supports use of either OpenAI or OpenRouter as its underlying AI provider. Eventually you will be able to specify your AI provider via an adapter, kind of like ActiveRecord maps to databases. Note that you can also use Raix to add AI capabilities to non-Rails applications as long as you include ActiveSupport as a dependency. Extracting the base code to its own standalone library without Rails dependencies is on the roadmap, but not a high priority.
10
10
 
@@ -23,6 +23,7 @@ end
23
23
 
24
24
  => "The question of the meaning of life is one of the most profound and enduring inquiries in philosophy, religion, and science.
25
25
  Different perspectives offer various answers..."
26
+ ```
26
27
 
27
28
  By default, Raix will automatically add the AI's response to the transcript. This behavior can be controlled with the `save_response` parameter, which defaults to `true`. You may want to set it to `false` when making multiple chat completion calls during the lifecycle of a single object (whether sequentially or in parallel) and want to manage the transcript updates yourself:
28
29
 
@@ -32,7 +33,7 @@ By default, Raix will automatically add the AI's response to the transcript. Thi
32
33
 
33
34
  #### Transcript Format
34
35
 
35
- The transcript accepts both abbreviated and standard OpenAI message hash formats. The abbreviated format, suitable for system, assistant, and user messages is simply a mapping of `role => content`, as show in the example above.
36
+ The transcript accepts both abbreviated and standard OpenAI message hash formats. The abbreviated format, suitable for system, assistant, and user messages is simply a mapping of `role => content`, as shown in the example above.
36
37
 
37
38
  ```ruby
38
39
  transcript << { user: "What is the meaning of life?" }
@@ -46,6 +47,12 @@ transcript << { role: "user", content: "What is the meaning of life?" }
46
47
 
47
48
  One of the advantages of OpenRouter and the reason that it is used by default by this library is that it handles mapping message formats from the OpenAI standard to whatever other model you're wanting to use (Anthropic, Cohere, etc.)
48
49
 
50
+ Note that it's possible to override the current object's transcript by passing a `messages` array to `chat_completion`. This allows for multiple threads to share a single conversation context in parallel, by deferring when they write their responses back to the transcript.
51
+
52
+ ```
53
+ chat_completion(openai: "gpt-4.1-nano", messages: [{ user: "What is the meaning of life?" }])
54
+ ```
55
+
49
56
  ### Predicted Outputs
50
57
 
51
58
  Raix supports [Predicted Outputs](https://platform.openai.com/docs/guides/latency-optimization#use-predicted-outputs) with the `prediction` parameter for OpenAI.
@@ -56,7 +63,7 @@ Raix supports [Predicted Outputs](https://platform.openai.com/docs/guides/latenc
56
63
 
57
64
  ### Prompt Caching
58
65
 
59
- Raix supports [Anthropic-style prompt caching](https://openrouter.ai/docs/prompt-caching#anthropic-claude) when using Anthropic's Claud family of models. You can specify a `cache_at` parameter when doing a chat completion. If the character count for the content of a particular message is longer than the cache_at parameter, it will be sent to Anthropic as a multipart message with a cache control "breakpoint" set to "ephemeral".
66
+ Raix supports [Anthropic-style prompt caching](https://openrouter.ai/docs/prompt-caching#anthropic-claude) when using Anthropic's Claude family of models. You can specify a `cache_at` parameter when doing a chat completion. If the character count for the content of a particular message is longer than the cache_at parameter, it will be sent to Anthropic as a multipart message with a cache control "breakpoint" set to "ephemeral".
60
67
 
61
68
  Note that there is a limit of four breakpoints, and the cache will expire within five minutes. Therefore, it is recommended to reserve the cache breakpoints for large bodies of text, such as character cards, CSV data, RAG data, book chapters, etc. Raix does not enforce a limit on the number of breakpoints, which means that you might get an error if you try to cache too many messages.
62
69
 
@@ -239,7 +246,7 @@ class PromptSubscriber
239
246
 
240
247
  attr_accessor :conversation, :bot_message, :user_message
241
248
 
242
- # many other declarations ommitted...
249
+ # many other declarations omitted...
243
250
 
244
251
  prompt call: FetchUrlCheck
245
252
 
@@ -563,13 +570,13 @@ You will also need to configure the OpenRouter API access token as per the instr
563
570
 
564
571
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
565
572
 
566
- Specs require `OR_ACCESS_TOKEN` and `OAI_ACCESS_TOKEN` environment variables, for access to OpenRouter and OpenAI, respectively. You can add those keys to a local unversionsed `.env` file and they will be picked up by the `dotenv` gem.
573
+ Specs require `OR_ACCESS_TOKEN` and `OAI_ACCESS_TOKEN` environment variables, for access to OpenRouter and OpenAI, respectively. You can add those keys to a local unversioned `.env` file and they will be picked up by the `dotenv` gem.
567
574
 
568
575
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
569
576
 
570
577
  ## Contributing
571
578
 
572
- Bug reports and pull requests are welcome on GitHub at https://github.com/[OlympiaAI]/raix. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[OlympiaAI]/raix/blob/main/CODE_OF_CONDUCT.md).
579
+ Bug reports and pull requests are welcome on GitHub at https://github.com/OlympiaAI/raix. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/OlympiaAI/raix/blob/main/CODE_OF_CONDUCT.md).
573
580
 
574
581
  ## License
575
582
 
@@ -577,4 +584,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
577
584
 
578
585
  ## Code of Conduct
579
586
 
580
- 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).
587
+ 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).
@@ -43,8 +43,9 @@ module Raix
43
43
  # @option params [Boolean] :json (false) Whether to return the parse the response as a JSON object. Will search for <json> tags in the response first, then fall back to the default JSON parsing of the entire response.
44
44
  # @option params [Boolean] :openai (false) Whether to use OpenAI's API instead of OpenRouter's.
45
45
  # @option params [Boolean] :raw (false) Whether to return the raw response or dig the text content.
46
+ # @option params [Array] :messages (nil) An array of messages to use instead of the transcript.
46
47
  # @return [String|Hash] The completed chat response.
47
- def chat_completion(params: {}, loop: false, json: false, raw: false, openai: false, save_response: true)
48
+ def chat_completion(params: {}, loop: false, json: false, raw: false, openai: false, save_response: true, messages: nil)
48
49
  # set params to default values if not provided
49
50
  params[:cache_at] ||= cache_at.presence
50
51
  params[:frequency_penalty] ||= frequency_penalty.presence
@@ -68,13 +69,17 @@ module Raix
68
69
  params[:top_logprobs] ||= top_logprobs.presence
69
70
  params[:top_p] ||= top_p.presence
70
71
 
72
+ json = true if params[:response_format].is_a?(Raix::ResponseFormat)
73
+
71
74
  if json
72
75
  unless openai
73
76
  params[:provider] ||= {}
74
77
  params[:provider][:require_parameters] = true
75
78
  end
76
- params[:response_format] ||= {}
77
- params[:response_format][:type] = "json_object"
79
+ if params[:response_format].blank?
80
+ params[:response_format] ||= {}
81
+ params[:response_format][:type] = "json_object"
82
+ end
78
83
  end
79
84
 
80
85
  # used by FunctionDispatch
@@ -87,7 +92,9 @@ module Raix
87
92
 
88
93
  # duplicate the transcript to avoid race conditions in situations where
89
94
  # chat_completion is called multiple times in parallel
90
- messages = transcript.flatten.compact.map { |msg| adapter.transform(msg) }.dup
95
+ # TODO: Defensive programming, ensure messages is an array
96
+ messages ||= transcript.flatten.compact
97
+ messages = messages.map { |msg| adapter.transform(msg) }.dup
91
98
  raise "Can't complete an empty transcript" if messages.blank?
92
99
 
93
100
  begin
@@ -56,27 +56,31 @@ module Raix
56
56
 
57
57
  define_method(name) do |arguments|
58
58
  id = SecureRandom.uuid[0, 23]
59
- transcript << {
60
- role: "assistant",
61
- content: nil,
62
- tool_calls: [
59
+ instance_exec(arguments, &block).tap do |content|
60
+ # add in one operation to prevent race condition and potential wrong
61
+ # interleaving of tool calls in multi-threaded environments
62
+ transcript << [
63
+ {
64
+ role: "assistant",
65
+ content: nil,
66
+ tool_calls: [
67
+ {
68
+ id:,
69
+ type: "function",
70
+ function: {
71
+ name:,
72
+ arguments: arguments.to_json
73
+ }
74
+ }
75
+ ]
76
+ },
63
77
  {
64
- id:,
65
- type: "function",
66
- function: {
67
- name:,
68
- arguments: arguments.to_json
69
- }
78
+ role: "tool",
79
+ tool_call_id: id,
80
+ name:,
81
+ content: content.to_s
70
82
  }
71
83
  ]
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
84
  # TODO: add on_error handler as optional parameter to function
81
85
  end
82
86
 
@@ -50,16 +50,20 @@ module Raix
50
50
  {}.tap do |response|
51
51
  case input
52
52
  when Array
53
- properties = {}
54
- input.each { |item| properties.merge!(decode(item)) }
55
-
56
53
  response[:type] = "array"
57
- response[:items] = {
58
- type: "object",
59
- properties:,
60
- required: properties.keys.select { |key| properties[key].delete(:required) },
61
- additionalProperties: false
62
- }
54
+
55
+ if input.size == 1 && input.first.is_a?(String)
56
+ response[:items] = { type: input.first }
57
+ else
58
+ properties = {}
59
+ input.each { |item| properties.merge!(decode(item)) }
60
+ response[:items] = {
61
+ type: "object",
62
+ properties:,
63
+ required: properties.keys.select { |key| properties[key].delete(:required) },
64
+ additionalProperties: false
65
+ }
66
+ end
63
67
  when Hash
64
68
  input.each do |key, value|
65
69
  response[key] = if value.is_a?(Hash) && value.key?(:type)
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.7.1"
4
+ VERSION = "0.7.3"
5
5
  end
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.7.1
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Obie Fernandez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-14 00:00:00.000000000 Z
11
+ date: 2025-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport