diff --git a/lib/ruby_llm/active_record/chat_methods.rb b/lib/ruby_llm/active_record/chat_methods.rb index 114d7ff7d..a324c77fa 100644 --- a/lib/ruby_llm/active_record/chat_methods.rb +++ b/lib/ruby_llm/active_record/chat_methods.rb @@ -65,8 +65,8 @@ def resolve_model_from_strings # rubocop:disable Metrics/PerceivedComplexity m.context_window = model_info.context_window m.max_output_tokens = model_info.max_output_tokens m.capabilities = model_info.capabilities || [] - m.modalities = model_info.modalities || {} - m.pricing = model_info.pricing || {} + m.modalities = model_info.modalities.to_h + m.pricing = model_info.pricing.to_h m.metadata = model_info.metadata || {} end diff --git a/spec/ruby_llm/active_record/acts_as_model_spec.rb b/spec/ruby_llm/active_record/acts_as_model_spec.rb index c9d6e2029..5ef461501 100644 --- a/spec/ruby_llm/active_record/acts_as_model_spec.rb +++ b/spec/ruby_llm/active_record/acts_as_model_spec.rb @@ -305,6 +305,41 @@ def messages chat.to_llm end + it 'persists created model attributes using JSON-serializable hashes' do + model_info = RubyLLM::Model::Info.new( + id: 'priced-registry-model', + name: 'Priced Registry Model', + provider: 'openai', + modalities: { input: %w[text image], output: %w[text] }, + capabilities: ['streaming'], + pricing: { + text_tokens: { + standard: { + input_per_million: 1.25, + output_per_million: 5.0 + } + } + } + ) + allow(RubyLLM::Models).to receive(:resolve).and_return([model_info, nil]) + + chat = chat_class.create!(model_id: 'priced-registry-model') + created_model = chat.model.reload + + expect(created_model.modalities).to eq( + 'input' => %w[text image], + 'output' => %w[text] + ) + expect(created_model.pricing).to eq( + 'text_tokens' => { + 'standard' => { + 'input_per_million' => 1.25, + 'output_per_million' => 5.0 + } + } + ) + end + it 'fails when model does not exist' do expect { chat_class.create!(model_id: 'non-existent') }.to raise_error(RubyLLM::ModelNotFoundError) end