class RubyLLM::Content
handle their own formatting needs.
Stores data in a standard internal format, letting providers
Represents the content sent to or received from an LLM.
def attach_audio(source)
def attach_audio(source) source = File.expand_path(source) unless source.start_with?('http') data = encode_file(source) format = File.extname(source).delete('.') || 'wav' { type: 'input_audio', input_audio: { data: data, format: format } } end
def attach_image(source) # rubocop:disable Metrics/MethodLength
def attach_image(source) # rubocop:disable Metrics/MethodLength source = File.expand_path(source) unless source.start_with?('http') return { type: 'image', source: { url: source } } if source.start_with?('http') data = Base64.strict_encode64(File.read(source)) mime_type = mime_type_for(source) { type: 'image', source: { type: 'base64', media_type: mime_type, data: data } } end
def attach_pdf(source)
def attach_pdf(source) source = File.expand_path(source) unless source.start_with?('http') pdf_data = { type: 'pdf', source: source } # For local files, validate they exist unless source.start_with?('http') raise Error, "PDF file not found: #{source}" unless File.exist?(source) # Preload file content for providers that need it pdf_data[:content] = File.read(source) end pdf_data end
def encode_file(source)
def encode_file(source) if source.start_with?('http') response = Faraday.get(source) Base64.strict_encode64(response.body) else Base64.strict_encode64(File.read(source)) end end
def format
def format return @parts.first[:text] if @parts.size == 1 && @parts.first[:type] == 'text' to_a end
def initialize(text = nil, attachments = {}) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
def initialize(text = nil, attachments = {}) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength @parts = [] @parts << { type: 'text', text: text } unless text.nil? || text.empty? Array(attachments[:image]).each do |source| @parts << attach_image(source) end Array(attachments[:audio]).each do |source| @parts << attach_audio(source) end Array(attachments[:pdf]).each do |source| @parts << attach_pdf(source) end end
def mime_type_for(path)
def mime_type_for(path) ext = File.extname(path).delete('.') "image/#{ext}" end
def to_a
def to_a return if @parts.empty? @parts end