Module: LlmCostTracker::Providers::Openai::UsageExtractor

Defined in:
lib/llm_cost_tracker/providers/openai/usage_extractor.rb

Constant Summary collapse

INPUT_DETAIL_KEYS =
%i[input_tokens_details input_token_details prompt_tokens_details].freeze
OUTPUT_DETAIL_KEYS =
%i[output_tokens_details output_token_details completion_tokens_details].freeze

Class Method Summary collapse

Class Method Details

.audio_input_tokens(usage) ⇒ Object



56
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 56

def self.audio_input_tokens(usage)      = detail(usage, INPUT_DETAIL_KEYS, :audio_tokens)

.audio_output_tokens(usage) ⇒ Object



57
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 57

def self.audio_output_tokens(usage)     = detail(usage, OUTPUT_DETAIL_KEYS, :audio_tokens)

.cache_read_input_tokens(usage) ⇒ Object



54
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 54

def self.cache_read_input_tokens(usage) = detail(usage, INPUT_DETAIL_KEYS, :cached_tokens)

.detail(usage, containers, key) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 62

def self.detail(usage, containers, key)
  containers.each do |container|
    value = usage.dig(container, key)
    return value.to_i if value
  end
  0
end

.hidden_output_tokens(usage) ⇒ Object



55
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 55

def self.hidden_output_tokens(usage)    = detail(usage, OUTPUT_DETAIL_KEYS, :reasoning_tokens)

.image_input_tokens(usage) ⇒ Object



58
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 58

def self.image_input_tokens(usage)      = detail(usage, INPUT_DETAIL_KEYS, :image_tokens)

.image_output_tokens(usage) ⇒ Object



59
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 59

def self.image_output_tokens(usage)     = detail(usage, OUTPUT_DETAIL_KEYS, :image_tokens)

.split_output(output_tokens:, image_output_details:, text_output_details:, audio_output:, default_to_image: false) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 39

def self.split_output(output_tokens:,
                      image_output_details:,
                      text_output_details:,
                      audio_output:,
                      default_to_image: false)
  if image_output_details.zero? && text_output_details.zero?
    remainder = [output_tokens - audio_output, 0].max
    return default_to_image ? [remainder, 0] : [0, remainder]
  end

  text_output = text_output_details
  text_output = [output_tokens - image_output_details - audio_output, 0].max if text_output.zero?
  [image_output_details, text_output]
end

.text_output_tokens(usage) ⇒ Object



60
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 60

def self.text_output_tokens(usage)      = detail(usage, OUTPUT_DETAIL_KEYS, :text_tokens)

.token_usage(usage, model: nil) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/llm_cost_tracker/providers/openai/usage_extractor.rb', line 11

def self.token_usage(usage, model: nil)
  input_tokens = (usage[:input_tokens] || usage[:prompt_tokens]).to_i
  output_tokens = (usage[:output_tokens] || usage[:completion_tokens]).to_i
  cache_read = cache_read_input_tokens(usage)
  audio_input = audio_input_tokens(usage)
  audio_output = audio_output_tokens(usage)
  image_input = image_input_tokens(usage)
  image_output, regular_output = split_output(
    output_tokens: output_tokens,
    image_output_details: image_output_tokens(usage),
    text_output_details: text_output_tokens(usage),
    audio_output: audio_output,
    default_to_image: ModelFamilies.image_output?(model)
  )

  Usage::TokenUsage.build(
    input_tokens: [input_tokens - cache_read - audio_input - image_input, 0].max,
    output_tokens: regular_output,
    total_tokens: usage[:total_tokens],
    cache_read_input_tokens: cache_read,
    audio_input_tokens: audio_input,
    audio_output_tokens: audio_output,
    image_input_tokens: image_input,
    image_output_tokens: image_output,
    hidden_output_tokens: hidden_output_tokens(usage)
  )
end