Module: RubyLLM::Protocols::Interactions::Transcription

Includes:
Gemini::FileTranscription
Defined in:
lib/ruby_llm/protocols/interactions/transcription.rb

Overview

:nodoc: all

Instance Method Summary collapse

Methods included from Gemini::FileTranscription

#transcribe, #validate_transcription_request

Instance Method Details

#parse_transcription_response(response, model:) ⇒ Object



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

def parse_transcription_response(response, model:)
  data = response.body
  message = parse_completion_body(data, raw: response)
  annotations = Array(data['steps']).flat_map { |step| Array(step['content']) }
                                    .flat_map { |part| Array(part['annotations']) }
  words = annotations.filter_map { |item| parse_transcription_word(item) if item['type'] == 'word_info' }
  RubyLLM::Transcription.new(text: message.content, model:, words: words.empty? ? nil : words,
                             **parse_interaction_usage(data['usage'] || {}))
end

#parse_transcription_word(word) ⇒ Object



50
51
52
53
54
# File 'lib/ruby_llm/protocols/interactions/transcription.rb', line 50

def parse_transcription_word(word)
  { 'word' => word['text'], 'speaker' => word['speaker'],
    'start' => word['start_offset'] && Float(word['start_offset'].delete_suffix('s')),
    'end' => word['end_offset'] && Float(word['end_offset'].delete_suffix('s')) }.compact
end

#render_transcription_options(timestamps:) ⇒ Object

Raises:

  • (ArgumentError)


7
8
9
10
11
12
13
# File 'lib/ruby_llm/protocols/interactions/transcription.rb', line 7

def render_transcription_options(timestamps:, **)
  return {} if timestamps.nil?
  raise ArgumentError, 'Gemini transcription timestamps must be word' unless timestamps == :word

  { generation_config: { transcription_config: { mode: { type: 'verbatim',
                                                         timestamp_granularities: ['word'] } } } }
end

#render_transcription_payload(attachment, model:, language:, speaker_names:, provider_options:, prompt:) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/ruby_llm/protocols/interactions/transcription.rb', line 21

def render_transcription_payload(attachment, model:, language:, speaker_names:, provider_options:, prompt:)
  config = { language_codes: language && Array(language), custom_vocabulary: prompt && Array(prompt) }.compact
  config[:mode] = { type: 'verbatim', diarization_mode: 'speaker' } if speaker_names
  payload = { model:, store: false,
              input: [{ type: 'audio', mime_type: attachment.mime_type, data: attachment.encoded }],
              generation_config: { transcription_config: config } }
  payload = Support::Utils.deep_merge(payload, provider_options)
  validate_transcription_config(payload.dig(:generation_config, :transcription_config))
  payload
end

#transcription_url(_model) ⇒ Object



17
18
19
# File 'lib/ruby_llm/protocols/interactions/transcription.rb', line 17

def transcription_url(_model)
  'interactions'
end

#validate_transcription_config(config) ⇒ Object

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
# File 'lib/ruby_llm/protocols/interactions/transcription.rb', line 32

def validate_transcription_config(config)
  mode = config[:mode]
  return unless config[:custom_vocabulary] && mode.is_a?(Hash)
  return unless mode[:diarization_mode] || mode[:timestamp_granularities]

  raise ArgumentError, 'Gemini custom vocabulary cannot be combined with diarization or word timestamps'
end