legion-llm 0.3.22 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/legion/llm/hooks/metering.rb +90 -0
- data/lib/legion/llm/hooks.rb +1 -0
- data/lib/legion/llm/version.rb +1 -1
- data/lib/legion/llm.rb +9 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45a5b0befbd5b6ea879f539a30ecb6675f7481e349c115f52ffc2e167c9e7c8d
|
|
4
|
+
data.tar.gz: 66323d03c6aac956cb0ad78b9bb708cbe7e3c834ede3ab4b34c820e1289f2320
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37ace42f654c110b9e633c53f4999fadd52d447f76145f95bd8ea18a3bcd816ad7ff4b6d3c7270eceaa12ab3b2f4a00f0192066df2a0adc53643d4614f534bb8
|
|
7
|
+
data.tar.gz: 7c6d639f5f45dbc4c3fccb94e8fece4e933da6037758d8eec3590c35fa15c24f55c19cdc9cc534b848a879d5de585d1c2cef070faa0b3bf354417cef25f86ab7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Legion LLM Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.23] - 2026-03-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Auto-metering hook: records token usage after every LLM call via gateway MeteringWriter or AMQP transport
|
|
7
|
+
- `Hooks::Metering.install` registers an `after_chat` hook during `LLM.start`
|
|
8
|
+
- Extracts input/output tokens, provider, model, status from response
|
|
9
|
+
- Opt-out via `llm.metering.auto: false` in settings
|
|
10
|
+
- 11 specs covering hook installation, data extraction, availability checks, and edge cases
|
|
11
|
+
|
|
3
12
|
## [0.3.22] - 2026-03-23
|
|
4
13
|
|
|
5
14
|
### Changed
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module LLM
|
|
5
|
+
module Hooks
|
|
6
|
+
module Metering
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def install
|
|
10
|
+
Legion::LLM::Hooks.after_chat do |response:, model:, **|
|
|
11
|
+
record(response, model)
|
|
12
|
+
nil
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def record(response, model)
|
|
17
|
+
return unless metering_available?
|
|
18
|
+
|
|
19
|
+
payload = extract_metering_data(response, model)
|
|
20
|
+
return if payload[:input_tokens].zero? && payload[:output_tokens].zero?
|
|
21
|
+
|
|
22
|
+
publish_metering(payload)
|
|
23
|
+
rescue StandardError => e
|
|
24
|
+
Legion::Logging.debug("[LLM::Metering] record failed: #{e.message}") if defined?(Legion::Logging)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def extract_metering_data(response, model)
|
|
28
|
+
usage = extract_usage(response)
|
|
29
|
+
{
|
|
30
|
+
provider: extract_provider(response),
|
|
31
|
+
model_id: (extract_model(response) || model).to_s,
|
|
32
|
+
input_tokens: usage[:input_tokens],
|
|
33
|
+
output_tokens: usage[:output_tokens],
|
|
34
|
+
event_type: 'llm_completion',
|
|
35
|
+
status: response.is_a?(Hash) && response[:error] ? 'failure' : 'success'
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def extract_usage(response)
|
|
40
|
+
return { input_tokens: 0, output_tokens: 0 } unless response.is_a?(Hash)
|
|
41
|
+
|
|
42
|
+
usage = response[:usage] || {}
|
|
43
|
+
{
|
|
44
|
+
input_tokens: usage[:input_tokens] || usage[:prompt_tokens] || 0,
|
|
45
|
+
output_tokens: usage[:output_tokens] || usage[:completion_tokens] || 0
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def extract_provider(response)
|
|
50
|
+
return nil unless response.is_a?(Hash)
|
|
51
|
+
|
|
52
|
+
response.dig(:meta, :provider) || response[:provider]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def extract_model(response)
|
|
56
|
+
return nil unless response.is_a?(Hash)
|
|
57
|
+
|
|
58
|
+
response.dig(:meta, :model) || response[:model]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def publish_metering(payload)
|
|
62
|
+
if gateway_metering?
|
|
63
|
+
Legion::Extensions::LLM::Gateway::Runners::MeteringWriter.write_metering_record(payload)
|
|
64
|
+
elsif transport_metering?
|
|
65
|
+
Legion::Transport.publish(
|
|
66
|
+
'lex.metering.record',
|
|
67
|
+
Legion::JSON.dump(payload)
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def gateway_metering?
|
|
73
|
+
defined?(Legion::Extensions::LLM::Gateway::Runners::MeteringWriter)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def transport_metering?
|
|
77
|
+
defined?(Legion::Transport) &&
|
|
78
|
+
Legion::Transport.respond_to?(:connected?) &&
|
|
79
|
+
Legion::Transport.connected?
|
|
80
|
+
rescue StandardError
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def metering_available?
|
|
85
|
+
gateway_metering? || transport_metering?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/legion/llm/hooks.rb
CHANGED
data/lib/legion/llm/version.rb
CHANGED
data/lib/legion/llm.rb
CHANGED
|
@@ -46,6 +46,8 @@ module Legion
|
|
|
46
46
|
run_discovery
|
|
47
47
|
set_defaults
|
|
48
48
|
|
|
49
|
+
install_hooks
|
|
50
|
+
|
|
49
51
|
@started = true
|
|
50
52
|
Legion::Settings[:llm][:connected] = true
|
|
51
53
|
Legion::Logging.info 'Legion::LLM started'
|
|
@@ -494,6 +496,13 @@ module Legion
|
|
|
494
496
|
cloud_providers.include?(resolved&.to_sym)
|
|
495
497
|
end
|
|
496
498
|
|
|
499
|
+
def install_hooks
|
|
500
|
+
metering_enabled = settings.dig(:metering, :auto) != false
|
|
501
|
+
Hooks::Metering.install if metering_enabled
|
|
502
|
+
rescue StandardError => e
|
|
503
|
+
Legion::Logging.debug("LLM hook installation failed: #{e.message}") if defined?(Legion::Logging)
|
|
504
|
+
end
|
|
505
|
+
|
|
497
506
|
def set_defaults
|
|
498
507
|
default_model = settings[:default_model]
|
|
499
508
|
default_provider = settings[:default_provider]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legion-llm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.23
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -145,6 +145,7 @@ files:
|
|
|
145
145
|
- lib/legion/llm/escalation_history.rb
|
|
146
146
|
- lib/legion/llm/helpers/llm.rb
|
|
147
147
|
- lib/legion/llm/hooks.rb
|
|
148
|
+
- lib/legion/llm/hooks/metering.rb
|
|
148
149
|
- lib/legion/llm/hooks/rag_guard.rb
|
|
149
150
|
- lib/legion/llm/hooks/response_guard.rb
|
|
150
151
|
- lib/legion/llm/off_peak.rb
|