Module: RubyLLM::Protocols::Interactions::Content

Defined in:
lib/ruby_llm/protocols/interactions/content.rb

Overview

:nodoc:

Constant Summary collapse

CITATION_TYPES =
%w[url_citation file_citation place_citation].freeze

Class Method Summary collapse

Class Method Details

.interaction_attachment_type(attachment) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 34

def interaction_attachment_type(attachment)
  return 'image' if attachment.image?
  return 'audio' if attachment.audio?
  return 'video' if attachment.video?

  'document' if attachment.pdf?
end

.interaction_citation_index(text, bytes) ⇒ Object



84
85
86
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 84

def interaction_citation_index(text, bytes)
  text.byteslice(0, bytes)&.length unless bytes.nil?
end

.interaction_citation_source(annotation) ⇒ Object



70
71
72
73
74
75
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 70

def interaction_citation_source(annotation)
  { url: annotation['url'] || annotation['document_uri'],
    title: annotation['title'] || annotation['file_name'] || annotation['name'],
    source_id: annotation['media_id'] || annotation['place_id'], cited_text: annotation['source'],
    start_page: annotation['page_number'], end_page: annotation['page_number'] }
end

.interaction_citation_span(text, annotation, offset) ⇒ Object



77
78
79
80
81
82
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 77

def interaction_citation_span(text, annotation, offset)
  start_index = interaction_citation_index(text, annotation['start_index'])
  end_index = interaction_citation_index(text, annotation['end_index'])
  { start_index: start_index && (offset + start_index), end_index: end_index && (offset + end_index),
    text: start_index && end_index && text[start_index...end_index] }
end

.parse_interaction_citations(part, offset) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 61

def parse_interaction_citations(part, offset)
  Array(part['annotations']).filter_map do |annotation|
    next unless CITATION_TYPES.include?(annotation['type'])

    Citation.new(**interaction_citation_source(annotation),
                 **interaction_citation_span(part['text'].to_s, annotation, offset))
  end
end

.parse_interaction_content(steps) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 42

def parse_interaction_content(steps)
  result = { text: +'', attachments: [], citations: [] }
  steps.select { |step| step['type'] == 'model_output' }.each do |step|
    Array(step['content']).each { |part| parse_interaction_part(part, result) }
  end
  result
end

.parse_interaction_part(part, result) ⇒ Object



50
51
52
53
54
55
56
57
58
59
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 50

def parse_interaction_part(part, result)
  if part['type'] == 'text'
    text = part['text'].to_s
    result[:citations].concat(parse_interaction_citations(part, result[:text].length))
    result[:text] << text
  elsif part['data'] || part['uri']
    source = part['uri'] || StringIO.new(Base64.decode64(part['data']))
    result[:attachments] << Attachment.new(source, config: @config)
  end
end

.render_interaction_attachment(attachment) ⇒ Object

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 18

def render_interaction_attachment(attachment)
  return { type: 'text', text: attachment.content } if attachment.text?

  type = interaction_attachment_type(attachment)
  raise ArgumentError, "Gemini Interactions does not support #{attachment.mime_type} input" unless type

  part = { type: type, mime_type: attachment.mime_type }
  if attachment.provider_file?
    part.merge(uri: attachment.provider_file_uri)
  elsif attachment.url?
    part.merge(uri: attachment.source.to_s)
  else
    part.merge(data: attachment.encoded)
  end
end

.render_interaction_content(text, attachments) ⇒ Object



13
14
15
16
# File 'lib/ruby_llm/protocols/interactions/content.rb', line 13

def render_interaction_content(text, attachments)
  parts = text.nil? ? [] : [{ type: 'text', text: text.to_s }]
  parts + attachments.map { |attachment| render_interaction_attachment(attachment) }
end