Skip to content

Commit 7aa3095

Browse files
Merge pull request #16 from SergoHUH/chore/update-ruby-llm
chore(deps): update ruby_llm to 1.16.0
2 parents 3ec8315 + d0ce298 commit 7aa3095

4 files changed

Lines changed: 50 additions & 7 deletions

File tree

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ruby '3.1.3'
55

66
gem 'dotenv', '~> 3.1'
77
gem 'faraday', '~> 2.14'
8-
gem 'ruby_llm', '1.15.0'
8+
gem 'ruby_llm', '1.16.0'
99

1010
group :development, :test do
1111
gem 'rspec', '~> 3.13'

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ GEM
6060
parser (>= 3.3.7.2)
6161
prism (~> 1.7)
6262
ruby-progressbar (1.13.0)
63-
ruby_llm (1.15.0)
63+
ruby_llm (1.16.0)
6464
base64
6565
event_stream_parser (~> 1)
6666
faraday (>= 1.10.0)
@@ -85,7 +85,7 @@ DEPENDENCIES
8585
faraday (~> 2.14)
8686
rspec (~> 3.13)
8787
rubocop (~> 1.75)
88-
ruby_llm (= 1.15.0)
88+
ruby_llm (= 1.16.0)
8989

9090
RUBY VERSION
9191
ruby 3.1.3p185

lib/aireview/reviewer.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,25 @@ def perform_llm_request(context:, stage:, system:, user:, options:)
7777
model = options[:model]
7878
temperature = options[:temperature]
7979
@logger.info("LLM #{stage} request started (model=#{model}, temperature=#{temperature})")
80-
chat = context.chat(model: model, provider: options[:provider].to_sym).with_temperature(temperature.to_f)
80+
chat = build_chat(context: context, stage: stage, model: model, provider: options[:provider])
81+
.with_temperature(temperature.to_f)
8182
chat.with_instructions(system)
8283
response = Timeout.timeout(@config.llm_timeout.to_f) { chat.ask(user) }
8384
@logger.info("LLM #{stage} request completed (model=#{model})")
8485
response
8586
end
8687

88+
def build_chat(context:, stage:, model:, provider:)
89+
context.chat(model: model, provider: provider.to_sym)
90+
rescue RubyLLM::ModelNotFoundError
91+
@logger.warn(
92+
"LLM #{stage}: model not found in RubyLLM registry; " \
93+
"using fallback with incomplete model metadata " \
94+
"(model=#{model}, provider=#{provider})"
95+
)
96+
context.chat(model: model, provider: provider.to_sym, assume_model_exists: true)
97+
end
98+
8799
def request_with_retries(stage:, model:)
88100
attempt = 0
89101

spec/reviewer_spec.rb

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
stub_const('RubyLLM::OverloadedError', Class.new(RubyLLM::Error))
7171
stub_const('RubyLLM::RateLimitError', Class.new(RubyLLM::Error))
7272
stub_const('RubyLLM::ContextLengthExceededError', Class.new(RubyLLM::Error))
73+
stub_const('RubyLLM::ModelNotFoundError', Class.new(StandardError))
7374
RubyLLM.singleton_class.attr_accessor :config
7475
RubyLLM.config = global_ruby_config
7576

@@ -83,6 +84,12 @@
8384
allow(context).to receive(:chat)
8485
.with(model: 'gemini-2.5-flash-lite', provider: anything)
8586
.and_return(critique_chat)
87+
allow(context).to receive(:chat)
88+
.with(model: 'gemini-3.6-flash', provider: anything)
89+
.and_raise(RubyLLM::ModelNotFoundError)
90+
allow(context).to receive(:chat)
91+
.with(model: 'gemini-3.6-flash', provider: anything, assume_model_exists: true)
92+
.and_return(generate_chat)
8693
context_configs << context_config
8794
contexts << context
8895
context
@@ -107,12 +114,14 @@
107114
expect(context_configs.first.gemini_api_base).to eq('https://llm.example.test')
108115
end
109116

110-
it 'uses generate model and temperature for the generate pass' do
117+
it 'uses a known model without bypassing the registry' do
111118
reviewer = described_class.new(config: config, logger: logger)
112119
result = reviewer.generate(system_prompt: 'system prompt', user_prompt: 'user prompt')
113120

114121
expect(result).to eq('generate body')
115-
expect(contexts.first).to have_received(:chat).with(model: 'gemini-2.5-pro', provider: :gemini)
122+
expect(contexts.first)
123+
.to have_received(:chat)
124+
.with(model: 'gemini-2.5-pro', provider: :gemini)
116125
expect(generate_chat).to have_received(:with_temperature).with(0.3)
117126
end
118127

@@ -121,7 +130,9 @@
121130
result = reviewer.critique(system_prompt: 'system prompt', user_prompt: 'user prompt')
122131

123132
expect(result).to eq('critique body')
124-
expect(contexts.first).to have_received(:chat).with(model: 'gemini-2.5-flash-lite', provider: :gemini)
133+
expect(contexts.first)
134+
.to have_received(:chat)
135+
.with(model: 'gemini-2.5-flash-lite', provider: :gemini)
125136
expect(critique_chat).to have_received(:with_temperature).with(0.0)
126137
end
127138

@@ -135,6 +146,26 @@
135146
expect(context_configs.first).not_to equal(context_configs.last)
136147
end
137148

149+
it 'retries an unknown model with an explicit provider' do
150+
allow(config).to receive(:generate_model).and_return('gemini-3.6-flash')
151+
log_output = StringIO.new
152+
reviewer = described_class.new(config: config, logger: Logger.new(log_output))
153+
154+
reviewer.generate(system_prompt: 'system prompt', user_prompt: 'user prompt')
155+
156+
expect(contexts.first)
157+
.to have_received(:chat)
158+
.with(model: 'gemini-3.6-flash', provider: :gemini)
159+
expect(contexts.first)
160+
.to have_received(:chat)
161+
.with(model: 'gemini-3.6-flash', provider: :gemini, assume_model_exists: true)
162+
expect(log_output.string).to include(
163+
'LLM generate: model not found in RubyLLM registry; ' \
164+
'using fallback with incomplete model metadata ' \
165+
'(model=gemini-3.6-flash, provider=gemini)'
166+
)
167+
end
168+
138169
it 'sets the RubyLLM request timeout from LLM_TIMEOUT' do
139170
reviewer = described_class.new(config: config, logger: logger)
140171

0 commit comments

Comments
 (0)