Module: Durable::Llm::ResponseHelpers

Defined in:
lib/durable/llm/response_helpers.rb

Overview

Helper methods for working with LLM responses

This module provides convenience methods for extracting content, messages, and metadata from LLM response objects. It handles the common patterns of response processing across different providers.

Examples:

Using response helpers

response = client.chat(messages: [...])
content = ResponseHelpers.extract_content(response)
tokens = ResponseHelpers.token_usage(response)

Class Method Summary collapse

Class Method Details

.all_contents(response) ⇒ Array<String>

Extracts all choice contents from a response

Examples:

Get all alternatives

response = client.completion(messages: [...], n: 3)
alternatives = ResponseHelpers.all_contents(response)

Parameters:

  • response (Object)

    The API response object

Returns:

  • (Array<String>)

    Array of content strings from all choices



51
52
53
54
55
56
57
58
59
60
# File 'lib/durable/llm/response_helpers.rb', line 51

def all_contents(response)
  return [] unless response&.respond_to?(:choices)

  response.choices.map do |choice|
    next unless choice.respond_to?(:message)

    message = choice.message
    message.content if message.respond_to?(:content)
  end.compact
end

.estimate_cost(response, model = nil) ⇒ Float?

Calculates the cost of a response (approximate)

This is a rough estimate based on common pricing. For accurate costs, consult your provider's pricing page.

Examples:

Estimate cost

response = client.completion(messages: [...])
cost = ResponseHelpers.estimate_cost(response)
puts "Estimated cost: $#{cost}"

Parameters:

  • response (Object)

    The API response object

  • model (String, nil) (defaults to: nil)

    Optional model name for pricing lookup

Returns:

  • (Float, nil)

    Estimated cost in USD



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/durable/llm/response_helpers.rb', line 155

def estimate_cost(response, model = nil)
  usage = token_usage(response)
  return nil unless usage

  model ||= model_used(response)
  return nil unless model

  # Rough pricing estimates (as of 2025)
  pricing = case model
            when /gpt-4-turbo/
              { prompt: 0.01 / 1000, completion: 0.03 / 1000 }
            when /gpt-4/
              { prompt: 0.03 / 1000, completion: 0.06 / 1000 }
            when /gpt-3.5-turbo/
              { prompt: 0.0015 / 1000, completion: 0.002 / 1000 }
            when /claude-3-opus/
              { prompt: 0.015 / 1000, completion: 0.075 / 1000 }
            when /claude-3-sonnet/
              { prompt: 0.003 / 1000, completion: 0.015 / 1000 }
            else
              return nil # Unknown model
            end

  (usage[:prompt_tokens] * pricing[:prompt]) +
    (usage[:completion_tokens] * pricing[:completion])
end

.extract_content(response) ⇒ String?

Extracts the text content from a completion response

Examples:

Extract content from response

response = client.completion(messages: [...])
text = ResponseHelpers.extract_content(response)
puts text

Parameters:

  • response (Object)

    The API response object

Returns:

  • (String, nil)

    The extracted content or nil if not found



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/durable/llm/response_helpers.rb', line 30

def extract_content(response)
  return nil unless response
  return nil unless response.respond_to?(:choices)
  return nil if response.choices.empty?

  choice = response.choices.first
  return nil unless choice.respond_to?(:message)

  message = choice.message
  return nil unless message.respond_to?(:content)

  message.content
end

.finish_reason(response) ⇒ String?

Extracts the finish reason from a response

Examples:

Check why completion finished

response = client.completion(messages: [...])
reason = ResponseHelpers.finish_reason(response)
puts "Finished because: #{reason}"

Parameters:

  • response (Object)

    The API response object

Returns:

  • (String, nil)

    The finish reason (e.g., 'stop', 'length', 'content_filter')



91
92
93
94
95
96
97
# File 'lib/durable/llm/response_helpers.rb', line 91

def finish_reason(response)
  return nil unless response&.respond_to?(:choices)
  return nil if response.choices.empty?

  choice = response.choices.first
  choice.finish_reason if choice.respond_to?(:finish_reason)
end

.model_used(response) ⇒ String?

Extracts model information from response

Examples:

Get model name

response = client.completion(messages: [...])
model = ResponseHelpers.model_used(response)
puts "Model: #{model}"

Parameters:

  • response (Object)

    The API response object

Returns:

  • (String, nil)

    The model used for the completion



137
138
139
140
141
# File 'lib/durable/llm/response_helpers.rb', line 137

def model_used(response)
  return nil unless response&.respond_to?(:model)

  response.model
end

.to_hash(response) ⇒ Hash

Formats a response as a simple hash with common fields

Examples:

Format response

response = client.completion(messages: [...])
simple = ResponseHelpers.to_hash(response)
# => { content: "...", tokens: {...}, finish_reason: "stop" }

Parameters:

  • response (Object)

    The API response object

Returns:

  • (Hash)

    Simplified response hash



120
121
122
123
124
125
126
127
# File 'lib/durable/llm/response_helpers.rb', line 120

def to_hash(response)
  {
    content: extract_content(response),
    tokens: token_usage(response),
    finish_reason: finish_reason(response),
    all_contents: all_contents(response)
  }
end

.token_usage(response) ⇒ Hash?

Extracts token usage information from a response

Examples:

Get token usage

response = client.completion(messages: [...])
usage = ResponseHelpers.token_usage(response)
puts "Used #{usage[:total_tokens]} tokens"

Parameters:

  • response (Object)

    The API response object

Returns:

  • (Hash, nil)

    Hash with :prompt_tokens, :completion_tokens, :total_tokens



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/durable/llm/response_helpers.rb', line 70

def token_usage(response)
  return nil unless response&.respond_to?(:usage)

  usage = response.usage
  return nil unless usage

  {
    prompt_tokens: usage.prompt_tokens,
    completion_tokens: usage.completion_tokens,
    total_tokens: usage.total_tokens
  }
end

.truncated?(response) ⇒ Boolean

Checks if a response was truncated due to length

Examples:

Check if truncated

response = client.completion(messages: [...])
if ResponseHelpers.truncated?(response)
  puts "Response was cut off. Consider increasing max_tokens."
end

Parameters:

  • response (Object)

    The API response object

Returns:

  • (Boolean)

    True if response was truncated



108
109
110
# File 'lib/durable/llm/response_helpers.rb', line 108

def truncated?(response)
  finish_reason(response) == 'length'
end