rubric_llm 0.5.0 → 0.6.0.rc1

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: e4b3be22ad7ef0d4af66ddba820a505c75c29f3bf47e1259bdee1ed28cf87ae4
4
- data.tar.gz: 2250b2b15b76203042befc1a86805827161c0df49efaf8dc240c5c594d5166b3
3
+ metadata.gz: 6d32ed4cba47a2fac15973d05bbf531317fa8d80f4c42b277dae5c302884ae57
4
+ data.tar.gz: a4bfbbc318593df77c33d36d41eda2e3d2f1b0cd4d0485fe9b8a61e72ee1519b
5
5
  SHA512:
6
- metadata.gz: 9e7e813f4bf58b17b70b6da5b42f0e77e962cc2862a1b5a62e59c5152ebc8de0c25058842c1c92344704e5fd249846a8662bd9937ad40ef068464c3520c3fee0
7
- data.tar.gz: aa9f1156c49f63cef0f00a7c649b14a6b11d9bec8904962e5a25af88bafd70447c797d7bb1f69ddffd5b17f13dda2e5e702fed5aede15c4cd9ef59c871c1be52
6
+ metadata.gz: a63b324d6f721297415feb55f6232b2771d58a7ca86a4a2ff0903abffec3c5fc5ad638c3d32632ed27bbf6cafea666a8247dcfa418d3454df61e3856c6c83b0a
7
+ data.tar.gz: 424912623b5f7f8157c91c10310c4e8ebe34e7406fcc146a3c146bd4e9de0cbe9b0100acc4b7a9a98174153f53178961f9c8233b120b3d3d23c11a5bf29bb360
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.6.0.rc1] - 2026-09-08
9
+
10
+ This prerelease targets RubyLLM `2.0.0.rc1` and supports RubyLLM 2 only. Applications that use RubyLLM 1.x should stay on RubricLLM `0.5.x`. Stable `0.6.0` waits for the final RubyLLM 2.0 release and the complete Ruby 3.4 and 4.0 test matrix.
11
+
12
+ ### Changed
13
+
14
+ - Require the exact RubyLLM `2.0.0.rc1` prerelease while the compatibility release is under review; Ruby >= 3.4 remains supported
15
+ - Keep `max_tokens` and `RUBRIC_MAX_TOKENS` as the public RubricLLM setting while RubyLLM maps the limit to the selected provider and protocol
16
+ - Treat explicit `temperature: nil` as an instruction to omit temperature from the provider request. Before 0.6.0.rc1, it selected `RUBRIC_TEMPERATURE` or `0.0`; an omitted temperature still reads `RUBRIC_TEMPERATURE` and defaults to `0.0`
17
+ - Use OpenAI Responses by default through RubyLLM 2. OpenAI-compatible gateways that only accept Chat Completions can set `config.openai_protocol = :chat_completions`
18
+ - Keep RubyLLM transport retries and RubricLLM judge retries separate. With RubyLLM's default `config.max_retries = 3` and RubricLLM's default `max_retries: 2`, a retryable metric failure can produce up to `(3 + 1) * (2 + 1) = 12` HTTP attempts
19
+ - Keep Rails persistence migrations separate. Applications that use RubyLLM's Rails records must follow RubyLLM's upstream 2.0 migration guide
20
+
8
21
  ## [0.5.0] - 2026-08-23
9
22
 
10
23
  ### Fixed
data/README.md CHANGED
@@ -8,18 +8,29 @@ Lightweight LLM evaluation framework for Ruby, inspired by [DeepEval](https://gi
8
8
 
9
9
  Provider-agnostic evaluation with pluggable metrics, statistical A/B comparison, and test framework integration: no Rails, no ActiveRecord, no UI. Works anywhere Ruby runs.
10
10
 
11
+ `0.6.0.rc1` is a prerelease for RubyLLM `2.0.0.rc1`. It supports RubyLLM 2 only. Applications that use RubyLLM 1.x should stay on RubricLLM `0.5.x`. Stable `0.6.0` waits for the final RubyLLM 2.0 release and the complete Ruby 3.4 and 4.0 test matrix.
12
+
11
13
  ## Installation
12
14
 
13
- Add to your Gemfile:
15
+ Install the release candidate with both exact prerelease constraints in the same Gemfile change:
14
16
 
15
17
  ```ruby
16
- gem "rubric_llm"
18
+ gem "rubric_llm", "0.6.0.rc1"
19
+ gem "ruby_llm", "2.0.0.rc1"
20
+ ```
21
+
22
+ Then resolve both gems together:
23
+
24
+ ```bash
25
+ bundle update rubric_llm ruby_llm
17
26
  ```
18
27
 
28
+ RubyLLM's upstream prerelease pin command is `bundle add ruby_llm --version 2.0.0.rc1`. If the application still has a RubyLLM 1.x constraint, update both constraints before running Bundler.
29
+
19
30
  Or install directly:
20
31
 
21
32
  ```bash
22
- gem install rubric_llm
33
+ gem install rubric_llm --version 0.6.0.rc1 --pre
23
34
  ```
24
35
 
25
36
  ## Quick Start
@@ -62,6 +73,25 @@ RubricLLM.configure do |c|
62
73
  end
63
74
  ```
64
75
 
76
+ `max_tokens` remains RubricLLM's public setting, and `RUBRIC_MAX_TOKENS` remains its environment variable. RubyLLM 2 maps this shared limit to the selected provider and protocol.
77
+
78
+ When `temperature` is omitted, RubricLLM reads `RUBRIC_TEMPERATURE` and uses `0.0` when the variable is not set. Before 0.6.0.rc1, an explicit `temperature: nil` selected that environment value or `0.0`; it now means that RubricLLM omits temperature from the provider request, so the provider chooses its default:
79
+
80
+ ```ruby
81
+ RubricLLM::Config.new # RUBRIC_TEMPERATURE, otherwise 0.0
82
+ RubricLLM::Config.new(temperature: nil) # omit temperature from the request
83
+ ```
84
+
85
+ RubyLLM 2 uses the OpenAI Responses protocol by default when the selected model supports it. For an OpenAI-compatible gateway that only accepts Chat Completions, configure RubyLLM before evaluating:
86
+
87
+ ```ruby
88
+ RubyLLM.configure do |config|
89
+ config.openai_protocol = :chat_completions
90
+ end
91
+ ```
92
+
93
+ Structured output support depends on the selected provider and model. RubricLLM sends its schema when RubyLLM reports structured output support. Otherwise it requests JSON text and validates the response object and score locally. Check the target provider's support before relying on a schema or a specific protocol. See RubyLLM's [2.0 upgrade guide](https://rubyllm.com/next/upgrading/), [request control guide](https://rubyllm.com/next/chat-request-control/), and [structured output support](https://rubyllm.com/next/structured-output/).
94
+
65
95
  ### Environment Variables
66
96
 
67
97
  All config fields can be set via environment variables:
@@ -100,6 +130,14 @@ RubricLLM.configure do |c|
100
130
  end
101
131
  ```
102
132
 
133
+ RubricLLM has no Rails models or database migrations. If the application also uses RubyLLM's Rails persistence, follow RubyLLM's 2.0 upgrade guide and run its phased migrations separately.
134
+
135
+ ### Retries
136
+
137
+ RubyLLM transport retries and RubricLLM judge retries remain separate. With RubyLLM's default `config.max_retries = 3` and RubricLLM's default `max_retries: 2`, one retryable metric failure can produce up to `(3 + 1) * (2 + 1) = 12` HTTP attempts. Set `RUBRIC_MAX_RETRIES` and `RUBRIC_RETRY_BASE_DELAY` for RubricLLM's layer, and set RubyLLM's `config.max_retries` and related transport settings for its layer. RubricLLM 0.6 does not combine or redesign these retry layers.
138
+
139
+ RubyLLM classifies OpenAI's HTTP 429 `insufficient_quota` response as a rate-limit error, so an exhausted account uses both retry budgets and their delays before the error is returned.
140
+
103
141
  ## Metrics
104
142
 
105
143
  ### LLM-as-Judge Metrics
@@ -323,7 +361,7 @@ result.overall # => mean of non-nil scores only
323
361
 
324
362
  ```bash
325
363
  bundle install
326
- bundle exec rake test
364
+ bundle exec rake test test_contract
327
365
  bundle exec rubocop
328
366
  ```
329
367
 
@@ -365,7 +403,7 @@ Deep dives live in the [project wiki](https://github.com/dpaluy/rubric_llm/wiki)
365
403
  ## Requirements
366
404
 
367
405
  - Ruby >= 3.4
368
- - [ruby_llm](https://github.com/crmne/ruby_llm) ~> 1.0
406
+ - [ruby_llm](https://github.com/crmne/ruby_llm) = 2.0.0.rc1 for RubricLLM 0.6.0.rc1
369
407
  - An API key for your chosen LLM provider (set via RubyLLM configuration)
370
408
 
371
409
  ## Contributing
@@ -5,11 +5,12 @@ module RubricLLM
5
5
  attr_accessor :judge_model, :judge_provider, :temperature, :max_tokens, :custom_prompt,
6
6
  :max_retries, :retry_base_delay, :concurrency
7
7
 
8
- def initialize(judge_model: nil, judge_provider: nil, temperature: nil, max_tokens: nil, # rubocop:disable Metrics/ParameterLists
8
+ def initialize(judge_model: nil, judge_provider: nil, # rubocop:disable Metrics/ParameterLists
9
+ temperature: Float(ENV.fetch("RUBRIC_TEMPERATURE", "0.0")), max_tokens: nil,
9
10
  custom_prompt: nil, max_retries: nil, retry_base_delay: nil, concurrency: nil, validate: false)
10
11
  @judge_model = judge_model || ENV.fetch("RUBRIC_JUDGE_MODEL", "gpt-4o")
11
12
  @judge_provider = (judge_provider || ENV.fetch("RUBRIC_JUDGE_PROVIDER", "openai")).to_sym
12
- @temperature = temperature || Float(ENV.fetch("RUBRIC_TEMPERATURE", "0.0"))
13
+ @temperature = temperature
13
14
  @max_tokens = max_tokens || Integer(ENV.fetch("RUBRIC_MAX_TOKENS", "4096"))
14
15
  @custom_prompt = custom_prompt
15
16
  @max_retries = max_retries || Integer(ENV.fetch("RUBRIC_MAX_RETRIES", "2"))
@@ -61,9 +62,9 @@ module RubricLLM
61
62
  end
62
63
 
63
64
  def validate_temperature
64
- return if temperature.is_a?(Numeric) && temperature.between?(0.0, 2.0)
65
+ return if temperature.nil? || (temperature.is_a?(Numeric) && temperature.between?(0.0, 2.0))
65
66
 
66
- raise ConfigurationError, "temperature must be between 0.0 and 2.0"
67
+ raise ConfigurationError, "temperature must be nil or between 0.0 and 2.0"
67
68
  end
68
69
 
69
70
  def validate_max_tokens
@@ -51,14 +51,13 @@ module RubricLLM
51
51
  attempts += 1
52
52
  chat = RubyLLM.chat(model: config.judge_model, provider: config.judge_provider)
53
53
  chat.with_temperature(config.temperature)
54
- chat.with_params(max_tokens: config.max_tokens)
54
+ chat.with_max_output_tokens(config.max_tokens)
55
55
  apply_response_schema(chat)
56
56
 
57
57
  full_system_prompt = build_system_prompt(system_prompt)
58
58
  chat.with_instructions(full_system_prompt)
59
59
  response = chat.ask(user_prompt)
60
- content = response.content
61
- validate_response!(content.is_a?(Hash) ? content : parse_json(content))
60
+ validate_response!(parse_json(response.content))
62
61
  rescue StandardError => e
63
62
  raise wrap_error(e) unless transient?(e) && attempts <= config.max_retries
64
63
 
@@ -100,17 +99,13 @@ module RubricLLM
100
99
  end
101
100
 
102
101
  def apply_response_schema(chat)
103
- return chat unless chat.respond_to?(:with_schema)
104
102
  return chat unless structured_output_supported?(chat)
105
103
 
106
104
  chat.with_schema(METRIC_RESPONSE_SCHEMA)
107
105
  end
108
106
 
109
107
  def structured_output_supported?(chat)
110
- return true unless chat.respond_to?(:model)
111
- return true unless chat.model.respond_to?(:structured_output?)
112
-
113
- chat.model.structured_output?
108
+ chat.model.supports?(:structured_output)
114
109
  end
115
110
 
116
111
  def validate_response!(response)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubricLLM
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0.rc1"
5
5
  end
data/lib/rubric_llm.rb CHANGED
@@ -143,7 +143,7 @@ module RubricLLM
143
143
  def apply_custom_prompt(config, custom_prompt)
144
144
  return config unless custom_prompt
145
145
 
146
- Config.new(**config.to_h.compact, custom_prompt:)
146
+ Config.new(**config.to_h, custom_prompt:)
147
147
  end
148
148
 
149
149
  def normalize_sample(sample)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubric_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Paluy
@@ -27,16 +27,16 @@ dependencies:
27
27
  name: ruby_llm
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - "~>"
30
+ - - '='
31
31
  - !ruby/object:Gem::Version
32
- version: '1.16'
32
+ version: 2.0.0.rc1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "~>"
37
+ - - '='
38
38
  - !ruby/object:Gem::Version
39
- version: '1.16'
39
+ version: 2.0.0.rc1
40
40
  description: Provider-agnostic LLM evaluation with pluggable metrics, statistical
41
41
  A/B comparison, and test framework integration. Ragas for Ruby, powered by RubyLLM.
42
42
  email: