Class: ImageMetadataSuggester

Inherits:
Object
  • Object
show all
Defined in:
app/services/image_metadata_suggester.rb

Overview

Generates AI-powered metadata suggestions for an existing library image.

Uses the image's existing fields (title, tags, meta_title, meta_description,
notes) AND — when available — its vision analysis description to produce
SEO-conscious improvements.

Examples:

result = ImageMetadataSuggester.call(image)
if result.success?
  result.title          # => "Radiant Heated Marble Spa Bathroom Floor"
  result.tags           # => ["bathroom", "marble", "spa", "radiant-heat"]
  result.meta_title     # => "Heated marble tile floor in spa bathroom"
  result.meta_description # => "..."
end

Defined Under Namespace

Classes: Result

Constant Summary collapse

PREFERRED_MODELS =
%w[
  gemini-2.0-flash
  gemini-1.5-flash
  gpt-4o-mini
  claude-3-5-haiku-20241022
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(image) ⇒ ImageMetadataSuggester

Returns a new instance of ImageMetadataSuggester.



45
46
47
# File 'app/services/image_metadata_suggester.rb', line 45

def initialize(image)
  @image = image
end

Class Method Details

.call(image) ⇒ Object



41
42
43
# File 'app/services/image_metadata_suggester.rb', line 41

def self.call(image)
  new(image).call
end

Instance Method Details

#callObject



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
# File 'app/services/image_metadata_suggester.rb', line 49

def call
  model = select_model
  return Result.new(error: 'No LLM model available for metadata suggestions') unless model

  message = generate_suggestions(model)
  parsed  = parse_response(message.content.to_s)

  Result.new(
    title:            parsed[:title],
    meta_title:       parsed[:meta_title],
    meta_description: parsed[:meta_description],
    tags:             parsed[:tags] || [],
    notes:            parsed[:notes],
    input_tokens:     message.input_tokens,
    output_tokens:    message.output_tokens,
    model_id:         model
  )
rescue RubyLLM::RateLimitError => e
  Rails.logger.warn "[ImageMetadataSuggester] Rate limited for Image #{@image.id}: #{e.message}"
  Result.new(error: "Rate limited — please retry shortly")
rescue RubyLLM::Error => e
  Rails.logger.warn "[ImageMetadataSuggester] RubyLLM error for Image #{@image.id}: #{e.message}"
  Result.new(error: e.message)
rescue StandardError => e
  Rails.logger.warn "[ImageMetadataSuggester] Failed for Image #{@image.id}: #{e.message}"
  Result.new(error: e.message)
end