Class: LlmModel
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- LlmModel
- Defined in:
- app/models/llm_model.rb
Overview
== Schema Information
Table name: ruby_llm_models
Database name: primary
id :bigint not null, primary key
capabilities :jsonb
context_window :integer
family :string
knowledge_cutoff :date
max_output_tokens :integer
metadata :jsonb
modalities :jsonb
model_created_at :datetime
name :string not null
pricing :jsonb
provider :string not null
created_at :datetime not null
updated_at :datetime not null
model_id :string not null
Indexes
index_ruby_llm_models_on_capabilities (capabilities) USING gin
index_ruby_llm_models_on_family (family)
index_ruby_llm_models_on_modalities (modalities) USING gin
index_ruby_llm_models_on_provider_and_model_id (provider,model_id) UNIQUE
RubyLLM 2.0 owns the model registry outright: acts_as_model and
config.model_registry_class are gone, and the rows moved to
ruby_llm_models, read and written by RubyLLM::ActiveRecord::Model — which
the gem marks :nodoc: private API.
This class stays as the application's read model over that table, for the
same reason AssistantToolCall does: it keeps the gem-private constant and the
gem-chosen table name in one file instead of scattered across workers.
Writes go through the gem (RubyLLM.models.refresh! and the acts_as_chat
find_or_create path). The one exception is #apply_reasoning_options! below.
Constant Summary
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Class Method Summary collapse
-
.apply_reasoning_options! ⇒ Integer
Advertise adaptive thinking to RubyLLM.
-
.refresh! ⇒ Object
Pull the live provider registry into ruby_llm_models.
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Class Method Details
.apply_reasoning_options! ⇒ Integer
Advertise adaptive thinking to RubyLLM.
RubyLLM builds the Anthropic thinking: {type: 'adaptive'} +
output_config.effort payload itself, but gates it on
model.reasoning_option('effort') and raises "Anthropic thinking effort
is not supported for " when it is missing. The gem's bundled
models.json carries no reasoning_options for our Claude ids, so nothing
would advertise it.
RubyLLM::Model reads reasoning_options out of metadata (model.rb:186),
so seeding it there is enough to make the native path fire. Deriving from
AiModelConstants — the single source of truth for model generations —
covers records created by a later registry refresh with no seed data to
maintain.
MUST be re-run after every RubyLLM.models.refresh!: refresh rebuilds each
row's metadata from models.json, which drops the key again. That's why
this is a class method rather than the 1.x #to_llm override — there is
no gem-side read hook left to hang it on.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'app/models/llm_model.rb', line 80 def adaptive = where(provider: 'anthropic').select do |model| AiModelConstants.adaptive_thinking?(model.model_id) && model.['reasoning_options'].blank? end adaptive.each do |model| model.update_column( :metadata, model..merge( 'reasoning_options' => [{ 'type' => 'effort', 'values' => AiModelConstants::ADAPTIVE_EFFORT_LEVELS }] ) ) end.size end |
.refresh! ⇒ Object
Pull the live provider registry into ruby_llm_models.
1.x got this free from acts_as_model. In 2.0 the refresh and the
persistence are two separate gem calls, and neither knows about our
adaptive-thinking metadata — so all three steps belong together, behind
the name both callers (WeeklyLlmModelSyncWorker, rails llm:sync)
already use.
53 54 55 56 57 |
# File 'app/models/llm_model.rb', line 53 def refresh! RubyLLM.models.refresh! RubyLLM::ActiveRecord::Model.save_to_database end |