Class: RubyLLM::Attachment

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_llm/attachment.rb

Overview

A class representing a file attachment.

Constant Summary collapse

DOCUMENT_EXTENSIONS =
%w[
  doc docx dot key numbers odp ods odt pages pot pps ppt pptx rtf xls xlsx
].freeze
ACTIVE_STORAGE_CLASS_NAMES =
%w[
  ActiveStorage::Blob
  ActiveStorage::Attachment
  ActiveStorage::Attached::One
  ActiveStorage::Attached::Many
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, filename: nil) ⇒ Attachment

Returns a new instance of Attachment.



22
23
24
25
26
27
28
# File 'lib/ruby_llm/attachment.rb', line 22

def initialize(source, filename: nil)
  @source = source
  @source = source_type_cast
  @filename = filename || source_filename

  determine_mime_type
end

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



10
11
12
# File 'lib/ruby_llm/attachment.rb', line 10

def filename
  @filename
end

#mime_typeObject (readonly)

Returns the value of attribute mime_type.



10
11
12
# File 'lib/ruby_llm/attachment.rb', line 10

def mime_type
  @mime_type
end

#sourceObject (readonly)

Returns the value of attribute source.



10
11
12
# File 'lib/ruby_llm/attachment.rb', line 10

def source
  @source
end

Instance Method Details

#active_storage?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/ruby_llm/attachment.rb', line 42

def active_storage?
  ACTIVE_STORAGE_CLASS_NAMES.any? { |class_name| source_is_a?(class_name) }
end

#audio?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/ruby_llm/attachment.rb', line 105

def audio?
  RubyLLM::MimeType.audio? mime_type
end

#contentObject



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/ruby_llm/attachment.rb', line 46

def content
  return @content if defined?(@content) && !@content.nil?

  if url?
    fetch_content
  elsif path?
    load_content_from_path
  elsif active_storage?
    load_content_from_active_storage
  elsif io_like?
    load_content_from_io
  else
    RubyLLM.logger.warn "Source is neither a URL, path, ActiveStorage, nor IO-like: #{@source.class}"
    nil
  end

  @content
end

#document?Boolean

Returns:

  • (Boolean)


124
125
126
127
128
# File 'lib/ruby_llm/attachment.rb', line 124

def document?
  return false if pdf? || text?

  RubyLLM::MimeType.document?(mime_type) || DOCUMENT_EXTENSIONS.include?(extension)
end

#encodedObject



65
66
67
# File 'lib/ruby_llm/attachment.rb', line 65

def encoded
  Base64.strict_encode64(content)
end

#extensionObject



130
131
132
133
# File 'lib/ruby_llm/attachment.rb', line 130

def extension
  extension = File.extname(filename.to_s).delete_prefix('.').downcase
  extension.empty? ? nil : extension
end

#for_llmObject



77
78
79
80
81
82
83
84
# File 'lib/ruby_llm/attachment.rb', line 77

def for_llm
  case type
  when :text
    "<file name='#{filename}' mime_type='#{mime_type}'>#{content}</file>"
  else
    "data:#{mime_type};base64,#{encoded}"
  end
end

#formatObject



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

def format
  case mime_type
  when 'audio/mpeg'
    'mp3'
  when 'audio/wav', 'audio/wave', 'audio/x-wav'
    'wav'
  else
    mime_type.split('/').last
  end
end

#image?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/ruby_llm/attachment.rb', line 97

def image?
  RubyLLM::MimeType.image? mime_type
end

#io_like?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/ruby_llm/attachment.rb', line 38

def io_like?
  @source.respond_to?(:read) && !path? && !active_storage?
end

#path?Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/ruby_llm/attachment.rb', line 34

def path?
  @source.is_a?(Pathname) || (@source.is_a?(String) && !url?)
end

#pdf?Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/ruby_llm/attachment.rb', line 120

def pdf?
  RubyLLM::MimeType.pdf? mime_type
end

#save(path) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/ruby_llm/attachment.rb', line 69

def save(path)
  return unless io_like?

  File.open(path, 'w') do |f|
    f.puts(@source.read)
  end
end

#text?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/ruby_llm/attachment.rb', line 135

def text?
  RubyLLM::MimeType.text? mime_type
end

#to_hObject



139
140
141
# File 'lib/ruby_llm/attachment.rb', line 139

def to_h
  { type: type, source: @source }
end

#typeObject



86
87
88
89
90
91
92
93
94
95
# File 'lib/ruby_llm/attachment.rb', line 86

def type
  return :image if image?
  return :video if video?
  return :audio if audio?
  return :pdf if pdf?
  return :text if text?
  return :document if document?

  :unknown
end

#url?Boolean

Returns:

  • (Boolean)


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

def url?
  @source.is_a?(URI) || (@source.is_a?(String) && @source.match?(%r{^https?://}))
end

#video?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/ruby_llm/attachment.rb', line 101

def video?
  RubyLLM::MimeType.video? mime_type
end