Class: RubyLLM::Protocols::Bedrock::AsyncVideos

Inherits:
RubyLLM::Protocol show all
Defined in:
lib/ruby_llm/protocols/bedrock/async_videos.rb

Overview

Luma Ray 2 video generation through Bedrock asynchronous invocation.

Constant Summary collapse

IMAGE_TYPES =
%w[image/png image/jpeg].freeze

Instance Attribute Summary

Attributes inherited from RubyLLM::Protocol

#config, #connection, #model, #provider

Instance Method Summary collapse

Methods inherited from RubyLLM::Protocol

abstract, #animate_later, #apply_compaction, #apply_compaction_headers, #apply_end_user, #cache_content, #compact, #complete, #count_tokens, #delete_cache, #embed, #extend_cache, #find_cache, #initialize, #list_models, #moderate, #ocr, #paint, #parse_error, #parse_image_responses, #post_image, #preprocess_message, #raise_transcription_streaming_unsupported, #render, #render_embedding, #render_transcription_options, #render_video_extension_payload, #rerank, #server_tool_aliases, #speak, #stream_speech, #stream_speech_response, #stream_transcription, #supports_embedding_media?, #tokenize, #tool_approval_response, #transcribe, #video_extension_attachment, #video_extension_url, #video_request_url

Methods included from RubyLLM::Protocol::BinaryStreaming

#stream_binary

Methods included from RubyLLM::Protocol::Streaming

build_on_data_handler, build_stream_error_response, error_chunk?, failed_http_status, faraday_1?, handle_data, handle_error_chunk, handle_error_event, handle_failed_response, handle_json_error_chunk, handle_sse, handle_stream, json_error_payload?, parse_error_from_json, parse_streaming_error, process_stream_chunk, raise_stream_error, stream_events, stream_response, stream_state

Constructor Details

This class inherits a constructor from RubyLLM::Protocol

Instance Method Details

#download_video(job) ⇒ Object

Raises:



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 63

def download_video(job)
  prefix = job.raw.dig('outputDataConfig', 's3OutputDataConfig', 's3Uri')
  raise Error, 'Bedrock video job has no output S3 URI' unless prefix

  prefix_length = (prefix.rindex(%r{[^/]}) || -1) + 1
  uris = @provider.list_file_uris("#{prefix[0, prefix_length]}/")
  videos = uris.select { |uri| uri.downcase.end_with?('.mp4') }
  raise Error, 'Expected exactly one MP4 in the Bedrock video output' unless videos.one?

  Video.new(data: @provider.download_file(videos.first), mime_type: 'video/mp4', model: job.model, raw: job.raw)
end

#parse_video_job(response, model:) ⇒ Object

Raises:



33
34
35
36
37
38
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 33

def parse_video_job(response, model:)
  id = response.body['invocationArn']
  raise Error.new('Bedrock did not return a video invocation ARN', response:) unless id

  VideoJob.new(id: id, protocol: self, model: model, raw: response.body)
end

#parse_video_job_status(response) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 52

def parse_video_job_status(response, **)
  body = response.body
  status = case body['status']
           when 'InProgress' then :pending
           when 'Completed' then :completed
           when 'Failed' then :failed
           else raise Error.new("Unknown Bedrock video status: #{body['status'].inspect}", response:)
           end
  { status: status, raw: body, error: body['failureMessage'] }
end

#post_video(url, payload) ⇒ Object



27
28
29
30
31
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 27

def post_video(url, payload)
  @connection.post(url, payload, idempotent: false) do |request|
    request.headers.merge!(@provider.sign_headers('POST', url, JSON.generate(payload)))
  end
end

#refresh_video_job(job) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 44

def refresh_video_job(job)
  url = video_job_url(job)
  response = @connection.get(url) do |request|
    request.headers.merge!(@provider.sign_headers('GET', url, ''))
  end
  parse_video_job_status(response, job:)
end

#render_video_payload(prompt, model:, with: [], provider_options: {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 14

def render_video_payload(prompt, model:, with: [], provider_options: {})
  output_uri = video_output_uri
  unless prompt.is_a?(String) && (1..5000).cover?(prompt.length)
    raise ArgumentError, 'Luma Ray 2 requires a prompt between 1 and 5000 characters'
  end

  options = Support::Utils.deep_symbolize_keys(provider_options)
  outer = options.slice(:clientRequestToken, :tags)
  input = { prompt: prompt }.merge(render_keyframes(with)).merge(options.except(*outer.keys))
  { modelId: model, modelInput: input, clientRequestToken: SecureRandom.uuid,
    outputDataConfig: { s3OutputDataConfig: { s3Uri: output_uri } } }.merge(outer)
end

#video_job_url(job) ⇒ Object



40
41
42
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 40

def video_job_url(job)
  "/async-invoke/#{URI.encode_www_form_component(job.id)}"
end

#video_urlObject



10
11
12
# File 'lib/ruby_llm/protocols/bedrock/async_videos.rb', line 10

def video_url
  '/async-invoke'
end