Module: Legion::LLM::Metering
- Extended by:
- Legion::Logging::Helper
- Defined in:
- lib/legion/llm/metering.rb,
lib/legion/llm/metering/tokens.rb,
lib/legion/llm/metering/tracker.rb,
lib/legion/llm/metering/estimator.rb
Defined Under Namespace
Modules: Pricing, Recorder, Tokens
Class Method Summary
collapse
Class Method Details
.const_missing(name) ⇒ Object
Backward-compat: resolve old Legion::LLM::Metering::Exchange, ::Event
139
140
141
142
143
144
145
146
147
148
149
150
|
# File 'lib/legion/llm/metering.rb', line 139
def self.const_missing(name)
case name
when :Exchange
require_relative 'transport/exchanges/metering'
Transport::Exchanges::Metering
when :Event
require_relative 'transport/messages/metering_event'
Transport::Messages::MeteringEvent
else
super
end
end
|
.emit(event) ⇒ Object
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/legion/llm/metering.rb', line 23
def emit(event)
event_class = metering_event_class if transport_connected?
if event_class
event_class.new(**event).publish
log.info("[llm][metering] published provider=#{event[:provider]} model=#{event[:model_id]}")
:published
elsif spool_available?
spool_event(event)
log.info("[llm][metering] spooled provider=#{event[:provider]} model=#{event[:model_id]}")
:spooled
else
log.warn("[llm][metering] dropped provider=#{event[:provider]} model=#{event[:model_id]}")
:dropped
end
rescue StandardError => e
handle_exception(e, level: :warn, operation: 'llm.metering.emit')
:dropped
end
|
123
124
125
126
127
|
# File 'lib/legion/llm/metering.rb', line 123
def (response)
return nil unless response.is_a?(Hash)
settings_value(settings_value(response, :meta), :model) || settings_value(response, :model)
end
|
117
118
119
120
121
|
# File 'lib/legion/llm/metering.rb', line 117
def (response)
return nil unless response.is_a?(Hash)
settings_value(settings_value(response, :meta), :provider) || settings_value(response, :provider)
end
|
107
108
109
110
111
112
113
114
115
|
# File 'lib/legion/llm/metering.rb', line 107
def (response)
return { input_tokens: 0, output_tokens: 0 } unless response.is_a?(Hash)
usage = settings_value(response, :usage) || {}
{
input_tokens: settings_value(usage, :input_tokens) || settings_value(usage, :prompt_tokens) || 0,
output_tokens: settings_value(usage, :output_tokens) || settings_value(usage, :completion_tokens) || 0
}
end
|
.flush_spool ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/legion/llm/metering.rb', line 43
def flush_spool
return 0 unless spool_available? && transport_connected?
spool = Legion::Data::Spool.for(Legion::LLM)
flushed = spool.flush(:metering) { |event| emit(event) }
log.info("[llm][metering] spool_flushed count=#{flushed}")
flushed
rescue StandardError => e
handle_exception(e, level: :warn, operation: 'llm.metering.flush_spool')
0
end
|
.install_hook ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/legion/llm/metering.rb', line 55
def install_hook
Legion::LLM::Hooks.after_chat do |response:, model:, **|
usage = (response)
next if usage[:input_tokens].zero? && usage[:output_tokens].zero?
resolved_model = ((response) || model).to_s
resolved_provider = (response)
Metering::Recorder.record(
model: resolved_model,
input_tokens: usage[:input_tokens],
output_tokens: usage[:output_tokens],
provider: resolved_provider
)
emit(
provider: resolved_provider,
model_id: resolved_model,
input_tokens: usage[:input_tokens],
output_tokens: usage[:output_tokens],
event_type: 'llm_completion',
status: response.is_a?(Hash) && response[:error] ? 'failure' : 'success'
)
nil
end
end
|
.load_transport ⇒ Object
14
15
16
17
18
19
|
# File 'lib/legion/llm/metering.rb', line 14
def self.load_transport
return unless defined?(Legion::Transport::Message)
require_relative 'transport/exchanges/metering'
require_relative 'transport/messages/metering_event'
end
|
.metering_event_class ⇒ Object
.settings_value(hash, key) ⇒ Object
129
130
131
132
133
134
135
136
|
# File 'lib/legion/llm/metering.rb', line 129
def settings_value(hash, key)
return nil unless hash.respond_to?(:key?)
string_key = key.to_s
return hash[string_key] if hash.key?(string_key)
hash[key] if hash.key?(key)
end
|
.spool_available? ⇒ Boolean
98
99
100
|
# File 'lib/legion/llm/metering.rb', line 98
def spool_available?
!!defined?(Legion::Data::Spool)
end
|
.spool_event(event) ⇒ Object
102
103
104
105
|
# File 'lib/legion/llm/metering.rb', line 102
def spool_event(event)
spool = Legion::Data::Spool.for(Legion::LLM)
spool.write(:metering, event)
end
|
.transport_connected? ⇒ Boolean