Class: RubyLLM::Image

Inherits:
Object
  • Object
show all
Includes:
Accounting::Usage::Result, Support::Inspectable
Defined in:
lib/ruby_llm/image.rb

Overview

An Image is a generated or edited image. Save it to a file with #save or read its bytes with #to_blob. Both handle hosted URLs and inline data.

image = RubyLLM.paint("a sunset over mountains in watercolor style")
image.save("sunset.png")

Constant Summary

Constants included from Support::Inspectable

Support::Inspectable::TRUNCATE_AT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Accounting::Usage::Result

#ruby_llm_usage_entries, #ruby_llm_usage_entries=

Methods included from Support::Inspectable

#full_inspect, #inspect, #pretty_print

Constructor Details

#initialize(url: nil, data: nil, mime_type: nil, revised_prompt: nil, model: nil, usage: {}) ⇒ Image

Returns a new instance of Image.



111
112
113
114
115
116
117
118
# File 'lib/ruby_llm/image.rb', line 111

def initialize(url: nil, data: nil, mime_type: nil, revised_prompt: nil, model: nil, usage: {})
  @url = url
  @data = data
  @mime_type = mime_type
  @revised_prompt = revised_prompt
  @model = model
  @raw_usage = usage
end

Instance Attribute Details

#configObject



107
108
109
# File 'lib/ruby_llm/image.rb', line 107

def config
  @config || RubyLLM.config
end

#dataObject (readonly)

The Base64-encoded image data, for providers that return the image inline, or nil.



21
22
23
# File 'lib/ruby_llm/image.rb', line 21

def data
  @data
end

#mime_typeObject (readonly)

The MIME type of the image data, such as "image/png".



24
25
26
# File 'lib/ruby_llm/image.rb', line 24

def mime_type
  @mime_type
end

#modelObject (readonly)

The id of the model that generated the image.



30
31
32
# File 'lib/ruby_llm/image.rb', line 30

def model
  @model
end

#revised_promptObject (readonly)

The provider's rewritten version of the prompt, when reported.



27
28
29
# File 'lib/ruby_llm/image.rb', line 27

def revised_prompt
  @revised_prompt
end

#urlObject (readonly)

The URL of the hosted image, for providers that return one, or nil.



17
18
19
# File 'lib/ruby_llm/image.rb', line 17

def url
  @url
end

Class Method Details

.paint(prompt, model: nil, provider: nil, assume_model_exists: false, size: nil, count: nil, context: nil, with: nil, mask: nil, provider_options: {}, metadata: nil) ⇒ Object

Generates an image from prompt and returns an Image. Most code calls this through RubyLLM.paint.

model: selects the image model and defaults to the configured default_image_model. provider: forces a specific provider, and assume_model_exists: skips the registry lookup, which is useful for custom endpoints. size: requests dimensions on models that support it. count: asks for several images in one request, returning an Array of Images instead of one. with: passes one or more source images for editing, and mask: constrains which parts of the image may change. provider_options: takes options in the provider's request vocabulary and merges them into the request as-is. context: supplies a Context whose configuration replaces the global one. metadata: is included in the instrumentation payload.

image = RubyLLM.paint("A small watercolor robot", model: "gpt-image-2")

images = RubyLLM.paint("A small watercolor robot", count: 4)
images.each_with_index { |image, i| image.save("robot-#{i}.png") }

RubyLLM.paint(
"Turn the logo green and keep the background transparent",
model: "gpt-image-2",
with: "logo.png"
)

Providers that cannot generate several images in one request ignore count: and return a single Image.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ruby_llm/image.rb', line 60

def self.paint(prompt,
               model: nil,
               provider: nil,
               assume_model_exists: false,
               size: nil,
               count: nil,
               context: nil,
               with: nil,
               mask: nil,
               provider_options: {},
               metadata: nil)
  config = context&.config || RubyLLM.config
  model ||= config.default_image_model
  model, provider_instance = Models.resolve(model, provider: provider, assume_model_exists: assume_model_exists,
                                                   config: config)
  empty_tokens = Tokens.new
  payload = {
    provider: provider_instance.slug,
    provider_class: provider_instance.name,
    model: model.id,
    model_info: model,
    prompt: prompt,
    size: size,
    count: count,
    provider_options: provider_options,
    metadata: ,
    tokens: empty_tokens,
    cost: Cost.new(tokens: empty_tokens, model:, category: :images)
  }

  RubyLLM.instrument('image.ruby_llm', payload, config: config) do |event|
    result = provider_instance.paint(prompt, model:, size:, count:, with:, mask:, provider_options:)
    images = Support::Utils.to_safe_array(result)
    event[:result] = result
    event[:response_model] = images.first&.model
    event[:tokens] = Tokens.aggregate(images.map(&:tokens))
    event[:cost] = Cost.aggregate(images.map(&:cost))
    result
  end
end

Instance Method Details

#base64?Boolean

Returns true if the image holds inline Base64 data, false otherwise.

Returns:

  • (Boolean)


122
123
124
# File 'lib/ruby_llm/image.rb', line 122

def base64?
  !@data.nil?
end

#costObject

Returns a Cost across every provider attempt, using reported prices when available and registry pricing otherwise.

image.cost.total


171
172
173
174
175
# File 'lib/ruby_llm/image.rb', line 171

def cost
  return ruby_llm_usage_cost unless ruby_llm_usage_entries.empty?

  Cost.new(tokens:, model: model_info, category: :images, input_details: input_tokens_details)
end

#model_infoObject

Returns the registry Model for #model, or nil if the model id is missing or not in the registry.



179
180
181
182
183
184
185
# File 'lib/ruby_llm/image.rb', line 179

def model_info
  return unless model

  @model_info ||= RubyLLM.models.find(model)
rescue ModelNotFoundError
  nil
end

#save(path) ⇒ Object

Writes the binary image to path, expanding it first. Returns path as given.

image.save("steampunk_owl.png")


145
146
147
148
# File 'lib/ruby_llm/image.rb', line 145

def save(path)
  File.binwrite(File.expand_path(path), to_blob)
  path
end

#to_blobObject

Returns the raw binary image bytes, decoding #data when present or downloading from #url otherwise.

image_bytes = image.to_blob


131
132
133
134
135
136
137
138
# File 'lib/ruby_llm/image.rb', line 131

def to_blob
  if base64?
    Base64.decode64 @data
  else
    response = Transport::Connection.basic(config).get @url
    response.body
  end
end

#tokensObject

Returns a Tokens with usage across every provider attempt. Its fields are nil when none were reported.

image.tokens.input
image.tokens.output


156
157
158
159
160
161
162
163
164
# File 'lib/ruby_llm/image.rb', line 156

def tokens
  return ruby_llm_usage_tokens unless ruby_llm_usage_entries.empty?

  @tokens ||= Tokens.new(
    input: raw_usage['input_tokens'],
    output: raw_usage['output_tokens'],
    reported_cost: raw_usage['cost']
  )
end