Module: RubyLLM::Providers::OpenAIResponses::Batches

Defined in:
lib/ruby_llm/providers/openai_responses/batches.rb

Overview

Stateless helpers for the Batch API. Provides URL builders, JSONL serialization, status constants, and result parsing.

Constant Summary collapse

VALIDATING =

Status constants

'validating'
IN_PROGRESS =
'in_progress'
COMPLETED =
'completed'
FAILED =
'failed'
CANCELLED =
'cancelled'
CANCELLING =
'cancelling'
EXPIRED =
'expired'
TERMINAL_STATUSES =
[COMPLETED, FAILED, CANCELLED, EXPIRED].freeze
PENDING_STATUSES =
[VALIDATING, IN_PROGRESS, CANCELLING].freeze

Class Method Summary collapse

Class Method Details

.batch_url(batch_id) ⇒ Object



35
36
37
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 35

def batch_url(batch_id)
  "batches/#{batch_id}"
end

.batches_urlObject



31
32
33
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 31

def batches_url
  'batches'
end

.build_jsonl(requests) ⇒ Object

Build a JSONL string from an array of request hashes. Each request has: custom_id, body (the Responses API payload)



61
62
63
64
65
66
67
68
69
70
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 61

def build_jsonl(requests)
  requests.map do |req|
    JSON.generate({
                    custom_id: req[:custom_id],
                    method: 'POST',
                    url: '/v1/responses',
                    body: req[:body]
                  })
  end.join("\n")
end

.cancel_batch_url(batch_id) ⇒ Object



39
40
41
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 39

def cancel_batch_url(batch_id)
  "batches/#{batch_id}/cancel"
end

.file_content_url(file_id) ⇒ Object



43
44
45
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 43

def file_content_url(file_id)
  "files/#{file_id}/content"
end

.files_urlObject

— URL helpers —



27
28
29
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 27

def files_url
  'files'
end

.normalize_input(input) ⇒ Object

Wraps a plain string into the Responses API input format.



75
76
77
78
79
80
81
82
83
84
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 75

def normalize_input(input)
  case input
  when String
    [{ type: 'message', role: 'user', content: input }]
  when Array
    input
  else
    input
  end
end

.parse_errors(jsonl_string) ⇒ Object

Parse JSONL error file into an array of error hashes.



124
125
126
127
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 124

def parse_errors(jsonl_string)
  results = parse_results(jsonl_string)
  results.select { |r| r.dig('response', 'status_code')&.>= 400 }
end

.parse_results(jsonl_string) ⇒ Object

Parse JSONL output into an array of raw result hashes.



89
90
91
92
93
94
95
96
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 89

def parse_results(jsonl_string)
  jsonl_string.each_line.filter_map do |line|
    line = line.strip
    next if line.empty?

    JSON.parse(line)
  end
end

.parse_results_to_messages(jsonl_string) ⇒ Object

Parse JSONL output into a Hash of { custom_id => Message }. Reuses Chat.extract_output_text and Chat.extract_tool_calls to avoid duplication.



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 100

def parse_results_to_messages(jsonl_string)
  results = parse_results(jsonl_string)
  results.each_with_object({}) do |result, hash|
    custom_id = result['custom_id']
    response_body = result.dig('response', 'body')
    next unless response_body

    output = response_body['output'] || []
    content = Chat.extract_output_text(output)
    tool_calls = Chat.extract_tool_calls(output)
    usage = response_body['usage'] || {}

    hash[custom_id] = Message.new(
      role: :assistant,
      content: content,
      tool_calls: tool_calls,
      input_tokens: usage['input_tokens'],
      output_tokens: usage['output_tokens'],
      model_id: response_body['model']
    )
  end
end

.pending?(status) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 53

def pending?(status)
  PENDING_STATUSES.include?(status)
end

.terminal?(status) ⇒ Boolean

— Status helpers —

Returns:

  • (Boolean)


49
50
51
# File 'lib/ruby_llm/providers/openai_responses/batches.rb', line 49

def terminal?(status)
  TERMINAL_STATUSES.include?(status)
end