Module: RubyLLM::Providers::OpenAI::Images

Included in:
RubyLLM::Providers::OpenAI
Defined in:
lib/ruby_llm/providers/openai/images.rb

Overview

Image generation methods for the OpenAI API integration

Class Method Summary collapse

Class Method Details

.attachments?(value) ⇒ Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/ruby_llm/providers/openai/images.rb', line 80

def attachments?(value)
  Array(value).any? { |item| !blank_attachment?(item) }
end

.blank_attachment?(value) ⇒ Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/ruby_llm/providers/openai/images.rb', line 84

def blank_attachment?(value)
  value.nil? || (value.is_a?(String) && value.strip.empty?)
end

.build_upload_part(source, label:) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/ruby_llm/providers/openai/images.rb', line 66

def build_upload_part(source, label:)
  attachment = Attachment.new(source)
  unless attachment.image?
    raise UnsupportedAttachmentError,
          "OpenAI image editing only supports image attachments for #{label}"
  end

  Faraday::UploadIO.new(StringIO.new(attachment.content), attachment.mime_type, attachment.filename)
end

.build_upload_parts(sources, label:) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/ruby_llm/providers/openai/images.rb', line 58

def build_upload_parts(sources, label:)
  Array(sources).filter_map do |source|
    next if blank_attachment?(source)

    build_upload_part(source, label:)
  end
end

.editing?(with, mask) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/ruby_llm/providers/openai/images.rb', line 76

def editing?(with, mask)
  attachments?(with) || !mask.nil?
end

.images_url(with: nil, mask: nil) ⇒ Object



10
11
12
# File 'lib/ruby_llm/providers/openai/images.rb', line 10

def images_url(with: nil, mask: nil)
  editing?(with, mask) ? 'images/edits' : 'images/generations'
end

.parse_image_response(response, model:) ⇒ Object

Raises:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ruby_llm/providers/openai/images.rb', line 25

def parse_image_response(response, model:)
  data = response.body
  image_data = Array(data['data']).first

  raise Error.new(nil, 'Unexpected response format from OpenAI image API') unless image_data

  Image.new(
    url: image_data['url'],
    mime_type: 'image/png', # DALL-E typically returns PNGs
    revised_prompt: image_data['revised_prompt'],
    model_id: model,
    data: image_data['b64_json'],
    usage: data['usage'] || {}
  )
end

.render_edit_payload(prompt, model:, with:, mask:, params:) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/ruby_llm/providers/openai/images.rb', line 47

def render_edit_payload(prompt, model:, with:, mask:, params:)
  payload = params.merge(
    model: model,
    prompt: prompt,
    image: build_upload_parts(with, label: 'images'),
    n: 1
  )
  payload[:mask] = build_upload_part(mask, label: 'mask') if mask
  payload
end

.render_image_payload(prompt, model:, size:, with: nil, mask: nil, params: {}) ⇒ Object

rubocop:disable Metrics/ParameterLists



14
15
16
17
18
19
20
21
22
23
# File 'lib/ruby_llm/providers/openai/images.rb', line 14

def render_image_payload(prompt, model:, size:, with: nil, mask: nil, params: {}) # rubocop:disable Metrics/ParameterLists
  return render_edit_payload(prompt, model:, with:, mask:, params:) if editing?(with, mask)

  {
    model: model,
    prompt: prompt,
    n: 1,
    size: size
  }.merge(params)
end

.validate_paint_inputs!(with:, mask:) ⇒ Object

Raises:

  • (ArgumentError)


41
42
43
44
45
# File 'lib/ruby_llm/providers/openai/images.rb', line 41

def validate_paint_inputs!(with:, mask:)
  return unless editing?(with, mask)

  raise ArgumentError, 'with: is required when mask: is provided' if mask && !attachments?(with)
end