Class: ActiveCanvas::AiModel

Inherits:
ApplicationRecord show all
Defined in:
app/models/active_canvas/ai_model.rb

Constant Summary collapse

MODALITY_MAP =
{
  "chat"      => { input: %w[text],  output: %w[text] },
  "image"     => { input: %w[text],  output: %w[image] },
  "embedding" => { input: %w[text],  output: %w[embedding] },
  "audio"     => { input: %w[text],  output: %w[audio] }
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.image_models_for_providers(providers) ⇒ Object



82
83
84
# File 'app/models/active_canvas/ai_model.rb', line 82

def image_models_for_providers(providers)
  active.image_models.where(provider: providers).order(:name)
end

.refresh_from_ruby_llm!Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/models/active_canvas/ai_model.rb', line 38

def refresh_from_ruby_llm!
  raise_if_ruby_llm_not_available!

  RubyLLM.models.refresh!

  models_data = RubyLLM.models.all

  imported_count = 0
  models_data.each do |model|
    record = find_or_initialize_by(model_id: model.id)
    is_new_record = record.new_record?

    modalities = derive_modalities(model.type, model.supports_vision?)

    record.assign_attributes(
      provider: model.provider,
      model_type: model.type,
      name: model.name || model.id,
      family: model.family,
      context_window: model.context_window,
      max_tokens: model.max_tokens,
      input_modalities: modalities[:input],
      output_modalities: modalities[:output],
      supports_functions: model.supports_functions? || false,
      input_price_per_million: model.input_price_per_million,
      output_price_per_million: model.output_price_per_million
    )

    record.active = true if is_new_record

    if record.save
      imported_count += 1
    else
      Rails.logger.warn "Failed to save AI model #{model.id}: #{record.errors.full_messages.join(', ')}"
    end
  end

  imported_count
end

.text_models_for_providers(providers) ⇒ Object



78
79
80
# File 'app/models/active_canvas/ai_model.rb', line 78

def text_models_for_providers(providers)
  active.text_models.where(provider: providers).order(:name)
end

.vision_models_for_providers(providers) ⇒ Object



86
87
88
# File 'app/models/active_canvas/ai_model.rb', line 86

def vision_models_for_providers(providers)
  active.vision_models.where(provider: providers).order(:name)
end

Instance Method Details

#as_json_for_editorObject



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/active_canvas/ai_model.rb', line 122

def as_json_for_editor
  {
    id: model_id,
    name: display_name,
    provider: provider,
    type: model_type,
    input_modalities: input_modalities,
    output_modalities: output_modalities,
    supports_functions: supports_functions,
    context_window: context_window,
    max_tokens: max_tokens
  }
end

#display_nameObject



105
106
107
# File 'app/models/active_canvas/ai_model.rb', line 105

def display_name
  name.presence || model_id
end

#price_infoObject



113
114
115
116
117
118
119
120
# File 'app/models/active_canvas/ai_model.rb', line 113

def price_info
  return nil if input_price_per_million.nil? && output_price_per_million.nil?

  parts = []
  parts << "$#{input_price_per_million}/M in" if input_price_per_million
  parts << "$#{output_price_per_million}/M out" if output_price_per_million
  parts.join(" / ")
end

#supports_vision?Boolean

Returns:

  • (Boolean)


109
110
111
# File 'app/models/active_canvas/ai_model.rb', line 109

def supports_vision?
  input_modalities&.include?("image")
end