Class: Rubino::LLM::ContentBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/llm/content_builder.rb

Overview

Image-path helpers shared by the vision tool, run executor, and the interaction lifecycle: extension matching, in-text image extraction, and the model-family vision heuristic.

Constant Summary collapse

SUPPORTED_IMAGE_TYPES =
%w[.png .jpg .jpeg .gif .webp .bmp].freeze

Class Method Summary collapse

Class Method Details

.extract_images(text) ⇒ Object

Detects image references in text (file paths or URLs) Extracts them and returns [cleaned_text, image_list]



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rubino/llm/content_builder.rb', line 21

def self.extract_images(text)
  images = []
  cleaned = text.dup

  # Match file paths to images: /path/to/image.png or ./image.jpg
  cleaned.gsub!(%r{(?:^|\s)((?:/|\./|~/)[^\s]+\.(?:png|jpg|jpeg|gif|webp|bmp))}i) do
    path = ::Regexp.last_match(1).strip
    if File.exist?(File.expand_path(path))
      images << { type: :file, path: File.expand_path(path) }
      "" # Remove from text
    else
      ::Regexp.last_match(0)
    end
  end

  # Match image URLs
  cleaned.gsub!(%r{(https?://[^\s]+\.(?:png|jpg|jpeg|gif|webp|bmp)(?:\?[^\s]*)?)}i) do
    url = ::Regexp.last_match(1)
    images << { type: :url, url: url }
    "" # Remove from text
  end

  [cleaned.strip, images]
end

.image_file?(path) ⇒ Boolean

True when the path has a recognised image extension. Centralised here so Executor and tools share one definition.

Returns:

  • (Boolean)


13
14
15
16
17
# File 'lib/rubino/llm/content_builder.rb', line 13

def self.image_file?(path)
  return false if path.nil? || path.to_s.empty?

  SUPPORTED_IMAGE_TYPES.include?(File.extname(path.to_s).downcase)
end

.supports_vision?(model_id) ⇒ Boolean

Returns true if the model_id matches a known vision-capable family. Heuristic only — Configuration#model_supports_vision? lets callers override per-tenant (e.g. behind a proxy where model_id is the literal “auto” and the real upstream is decided server-side).

Returns:

  • (Boolean)


50
51
52
# File 'lib/rubino/llm/content_builder.rb', line 50

def self.supports_vision?(model_id)
  model_id.match?(/gpt-4|claude|gemini|minimax-m3|mimo-v|qwen.*-vl|llava/i)
end