Class: RubyLLM::Attachment
- Inherits:
-
Object
- Object
- RubyLLM::Attachment
- Includes:
- Support::Inspectable
- Defined in:
- lib/ruby_llm/attachment.rb
Overview
An Attachment is a file sent to the model alongside a message. The source
can be a local path, an http(s) URL, an IO-like object, an ActiveStorage
object, or a provider-managed UploadedFile. Chat#ask builds attachments
for you from its with: option:
chat.ask "What's in this image?", with: "ruby_conf.jpg"
Build one explicitly to return a file from a Tool:
RubyLLM::Attachment.new(doc.download_path)
Constant Summary collapse
- DOCUMENT_EXTENSIONS =
File extensions recognized as document attachments when the MIME type alone is inconclusive.
%w[ doc docx dot key numbers odp ods odt pages pot pps ppt pptx rtf xls xlsx ].freeze
- ACTIVE_STORAGE_CLASS_NAMES =
:stopdoc:
%w[ ActiveStorage::Blob ActiveStorage::Attachment ActiveStorage::Attached::One ActiveStorage::Attached::Many ].freeze
Constants included from Support::Inspectable
Support::Inspectable::TRUNCATE_AT
Instance Attribute Summary collapse
-
#filename ⇒ Object
readonly
The filename given at construction or derived from the source.
-
#mime_type ⇒ Object
readonly
The detected MIME type string, such as "image/png".
-
#source ⇒ Object
readonly
The underlying source: a URI, Pathname, IO-like object, ActiveStorage object, or UploadedFile.
Class Method Summary collapse
-
.wrap(sources, config: nil) ⇒ Object
:startdoc:.
Instance Method Summary collapse
-
#active_storage? ⇒ Boolean
:nodoc:.
-
#audio? ⇒ Boolean
Returns whether the attachment is audio.
-
#byte_size ⇒ Object
:nodoc:.
-
#config ⇒ Object
:nodoc:.
-
#content ⇒ Object
Returns the raw bytes of the attachment, fetching or reading the source on the first call.
-
#document? ⇒ Boolean
Returns whether the attachment is a non-PDF, non-text document format such as Word or Excel, judged by MIME type or file extension.
-
#encoded ⇒ Object
:nodoc:.
-
#extension ⇒ Object
:nodoc:.
-
#for_llm ⇒ Object
:nodoc:.
-
#format ⇒ Object
:nodoc:.
-
#image? ⇒ Boolean
Returns whether the attachment is an image.
-
#initialize(source, filename: nil, config: nil) ⇒ Attachment
constructor
Creates an attachment from
source: a file path, URL, IO-like object, ActiveStorage object, or UploadedFile. -
#io_like? ⇒ Boolean
:nodoc:.
-
#path? ⇒ Boolean
:nodoc:.
-
#pdf? ⇒ Boolean
Returns whether the attachment is a PDF.
-
#provider_file? ⇒ Boolean
:nodoc:.
-
#provider_file_id ⇒ Object
:nodoc:.
-
#provider_file_uri ⇒ Object
:nodoc:.
-
#provider_uploads ⇒ Object
Files this attachment has been auto-uploaded to, keyed by provider and credentials.
-
#text? ⇒ Boolean
Returns whether the attachment is textual, like source code or CSV.
-
#to_h ⇒ Object
:nodoc:.
-
#type ⇒ Object
Returns the attachment category as a Symbol:
:image,:video,:audio,:pdf,:text,:document, or:unknown. -
#url? ⇒ Boolean
:nodoc:.
-
#video? ⇒ Boolean
Returns whether the attachment is a video.
Methods included from Support::Inspectable
#full_inspect, #inspect, #pretty_print
Constructor Details
#initialize(source, filename: nil, config: nil) ⇒ Attachment
Creates an attachment from source: a file path, URL, IO-like object,
ActiveStorage object, or UploadedFile. Derives the filename from the
source when filename: is not given, then detects the MIME type.
RubyLLM::Attachment.new("diagram.png")
RubyLLM::Attachment.new(StringIO.new(data), filename: "report.pdf")
config: is the Configuration a URL source is downloaded with, and
defaults to the global one.
Paths and URLs must be trusted and authorized by the application. They can be read or fetched during construction to detect the MIME type. Validate upload parameters before passing them here: an unchecked String can access local files or internal network endpoints.
75 76 77 78 79 80 81 82 |
# File 'lib/ruby_llm/attachment.rb', line 75 def initialize(source, filename: nil, config: nil) @config = config @source = source @source = source_type_cast @filename = filename || source_filename determine_mime_type end |
Instance Attribute Details
#filename ⇒ Object (readonly)
The filename given at construction or derived from the source.
May be nil.
28 29 30 |
# File 'lib/ruby_llm/attachment.rb', line 28 def filename @filename end |
#mime_type ⇒ Object (readonly)
The detected MIME type string, such as "image/png".
31 32 33 |
# File 'lib/ruby_llm/attachment.rb', line 31 def mime_type @mime_type end |
#source ⇒ Object (readonly)
The underlying source: a URI, Pathname, IO-like object, ActiveStorage object, or UploadedFile.
24 25 26 |
# File 'lib/ruby_llm/attachment.rb', line 24 def source @source end |
Class Method Details
.wrap(sources, config: nil) ⇒ Object
:startdoc:
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/ruby_llm/attachment.rb', line 48 def self.wrap(sources, config: nil) # :nodoc: case sources when nil then [] when Hash then sources.values.flat_map { |group| wrap(group, config:) } else Support::Utils.to_safe_array(sources).filter_map do |source| next if source.nil? || (source.is_a?(String) && source.strip.empty?) source.is_a?(Attachment) ? source : new(source, config:) end end end |
Instance Method Details
#active_storage? ⇒ Boolean
:nodoc:
119 120 121 |
# File 'lib/ruby_llm/attachment.rb', line 119 def active_storage? # :nodoc: ACTIVE_STORAGE_CLASS_NAMES.any? { |class_name| source_is_a?(class_name) } end |
#audio? ⇒ Boolean
Returns whether the attachment is audio.
175 176 177 |
# File 'lib/ruby_llm/attachment.rb', line 175 def audio? RubyLLM::Files::MimeType.audio? mime_type end |
#byte_size ⇒ Object
:nodoc:
217 218 219 |
# File 'lib/ruby_llm/attachment.rb', line 217 def byte_size # :nodoc: file_byte_size || loaded_byte_size || content_byte_size end |
#config ⇒ Object
:nodoc:
84 85 86 |
# File 'lib/ruby_llm/attachment.rb', line 84 def config # :nodoc: @config || RubyLLM.config end |
#content ⇒ Object
Returns the raw bytes of the attachment, fetching or reading the source on the first call. Text content is returned as UTF-8.
Raises RubyLLM::Error if the attachment is a provider-managed file, which has no local content.
128 129 130 131 132 133 134 135 136 |
# File 'lib/ruby_llm/attachment.rb', line 128 def content if provider_file? raise Error, "Provider-managed file #{provider_file_id} cannot be read as inline attachment content" end load_content if !defined?(@content) || @content.nil? normalize_text_encoding @content end |
#document? ⇒ Boolean
Returns whether the attachment is a non-PDF, non-text document format such as Word or Excel, judged by MIME type or file extension.
197 198 199 200 201 |
# File 'lib/ruby_llm/attachment.rb', line 197 def document? return false if pdf? || text? RubyLLM::Files::MimeType.document?(mime_type) || DOCUMENT_EXTENSIONS.include?(extension) end |
#encoded ⇒ Object
:nodoc:
138 139 140 |
# File 'lib/ruby_llm/attachment.rb', line 138 def encoded # :nodoc: Base64.strict_encode64(content) end |
#extension ⇒ Object
:nodoc:
203 204 205 206 |
# File 'lib/ruby_llm/attachment.rb', line 203 def extension # :nodoc: extension = File.extname(filename.to_s).delete_prefix('.').downcase extension.empty? ? nil : extension end |
#for_llm ⇒ Object
:nodoc:
142 143 144 145 146 147 148 149 |
# File 'lib/ruby_llm/attachment.rb', line 142 def for_llm # :nodoc: case type when :text "<file name='#{filename}' mime_type='#{mime_type}'>#{content}</file>" else "data:#{mime_type};base64,#{encoded}" end end |
#format ⇒ Object
:nodoc:
179 180 181 182 183 184 185 186 187 188 |
# File 'lib/ruby_llm/attachment.rb', line 179 def format # :nodoc: 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 whether the attachment is an image.
165 166 167 |
# File 'lib/ruby_llm/attachment.rb', line 165 def image? RubyLLM::Files::MimeType.image? mime_type end |
#io_like? ⇒ Boolean
:nodoc:
115 116 117 |
# File 'lib/ruby_llm/attachment.rb', line 115 def io_like? # :nodoc: @source.respond_to?(:read) && !path? && !active_storage? && !provider_file? end |
#path? ⇒ Boolean
:nodoc:
111 112 113 |
# File 'lib/ruby_llm/attachment.rb', line 111 def path? # :nodoc: !provider_file? && (@source.is_a?(Pathname) || (@source.is_a?(String) && !url?)) end |
#pdf? ⇒ Boolean
Returns whether the attachment is a PDF.
191 192 193 |
# File 'lib/ruby_llm/attachment.rb', line 191 def pdf? RubyLLM::Files::MimeType.pdf? mime_type end |
#provider_file? ⇒ Boolean
:nodoc:
92 93 94 |
# File 'lib/ruby_llm/attachment.rb', line 92 def provider_file? # :nodoc: @source.is_a?(UploadedFile) end |
#provider_file_id ⇒ Object
:nodoc:
103 104 105 |
# File 'lib/ruby_llm/attachment.rb', line 103 def provider_file_id # :nodoc: @source.id if provider_file? end |
#provider_file_uri ⇒ Object
:nodoc:
107 108 109 |
# File 'lib/ruby_llm/attachment.rb', line 107 def provider_file_uri # :nodoc: @source.uri if provider_file? end |
#provider_uploads ⇒ Object
Files this attachment has been auto-uploaded to, keyed by provider and credentials. Kept on the attachment so request-time preprocessing uploads once per account while history keeps the original source.
99 100 101 |
# File 'lib/ruby_llm/attachment.rb', line 99 def provider_uploads # :nodoc: @provider_uploads ||= {} end |
#text? ⇒ Boolean
Returns whether the attachment is textual, like source code or CSV.
209 210 211 |
# File 'lib/ruby_llm/attachment.rb', line 209 def text? RubyLLM::Files::MimeType.text? mime_type end |
#to_h ⇒ Object
:nodoc:
213 214 215 |
# File 'lib/ruby_llm/attachment.rb', line 213 def to_h # :nodoc: { type: type, source: @source } end |
#type ⇒ Object
Returns the attachment category as a Symbol: :image, :video,
:audio, :pdf, :text, :document, or :unknown.
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/ruby_llm/attachment.rb', line 153 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
:nodoc:
88 89 90 |
# File 'lib/ruby_llm/attachment.rb', line 88 def url? # :nodoc: @source.is_a?(URI) || (@source.is_a?(String) && @source.match?(%r{\Ahttps?://}i)) end |