active_genie 0.25.2 → 0.26.5
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/VERSION +1 -1
- data/lib/active_genie/clients/providers/anthropic_client.rb +1 -3
- data/lib/active_genie/clients/providers/base_client.rb +10 -10
- data/lib/active_genie/clients/providers/deepseek_client.rb +7 -9
- data/lib/active_genie/clients/providers/google_client.rb +4 -6
- data/lib/active_genie/clients/providers/openai_client.rb +4 -6
- data/lib/active_genie/config/log_config.rb +8 -6
- data/lib/active_genie/data_extractor/from_informal.rb +2 -2
- data/lib/active_genie/logger.rb +3 -1
- data/lib/active_genie/ranking/elo_round.rb +12 -7
- data/lib/active_genie/ranking/free_for_all.rb +1 -1
- data/lib/active_genie/ranking/player.rb +9 -7
- data/lib/active_genie/ranking/players_collection.rb +7 -9
- data/lib/active_genie/ranking/ranking_scoring.rb +1 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad223ae84ac62d9375af07ba18dca9152296cac5e7c432a6fd07118107c4ab6e
|
4
|
+
data.tar.gz: 5faa2d7ad89cf2200296f94892470248a544d86cd37880191777226f121d9cf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a6bd702967d5948e37fed48a9b92d0c2061b4893579e67d526cb3bf9b71b44889b7a5a457d5c78a768f74d6cc650beb17a52c1ce00bf1a5c7d2dc553d88b866
|
7
|
+
data.tar.gz: 845fecdb4f036ce4a97b99ea54d0f5600544d6ce0b052da99e4533e4555d774ce09bff1dc037d3752f30aabe69acc5b9362ab77eaf17c62b8ebb5244e02b5df8
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.26.5
|
@@ -81,16 +81,13 @@ module ActiveGenie
|
|
81
81
|
|
82
82
|
response = http_request(request, uri)
|
83
83
|
|
84
|
-
|
85
|
-
when Net::HTTPSuccess
|
86
|
-
parsed_response = parse_response(response)
|
84
|
+
raise ClientError, "Unexpected response: #{response.code} - #{response.body}" unless response.is_a?(Net::HTTPSuccess)
|
87
85
|
|
88
|
-
|
86
|
+
parsed_response = parse_response(response)
|
89
87
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
88
|
+
log_request_details(uri:, request:, response:, start_time:, parsed_response:)
|
89
|
+
|
90
|
+
parsed_response
|
94
91
|
end
|
95
92
|
|
96
93
|
# Create and configure an HTTP client
|
@@ -103,7 +100,10 @@ module ActiveGenie
|
|
103
100
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
104
101
|
http.read_timeout = @config.llm.read_timeout || DEFAULT_TIMEOUT
|
105
102
|
http.open_timeout = @config.llm.open_timeout || DEFAULT_OPEN_TIMEOUT
|
106
|
-
|
103
|
+
|
104
|
+
retry_with_backoff do
|
105
|
+
http.request(request)
|
106
|
+
end
|
107
107
|
end
|
108
108
|
|
109
109
|
# Apply headers to the request
|
@@ -170,7 +170,7 @@ module ActiveGenie
|
|
170
170
|
|
171
171
|
begin
|
172
172
|
yield
|
173
|
-
rescue Net::
|
173
|
+
rescue Net::OpenTimeout, Net::ReadTimeout, ClientError => e
|
174
174
|
raise if retries > max_retries
|
175
175
|
|
176
176
|
sleep_time = retry_delay * (2**retries)
|
@@ -25,18 +25,16 @@ module ActiveGenie
|
|
25
25
|
model:
|
26
26
|
}
|
27
27
|
|
28
|
-
|
29
|
-
response = request(payload)
|
28
|
+
response = request(payload)
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
if response.nil? || response.keys.empty?
|
31
|
+
raise InvalidResponseError,
|
32
|
+
"Invalid response: #{response}"
|
33
|
+
end
|
35
34
|
|
36
|
-
|
35
|
+
ActiveGenie::Logger.call({ code: :function_calling, fine_tune: true, payload:, response: })
|
37
36
|
|
38
|
-
|
39
|
-
end
|
37
|
+
response
|
40
38
|
end
|
41
39
|
|
42
40
|
private
|
@@ -29,14 +29,12 @@ module ActiveGenie
|
|
29
29
|
}
|
30
30
|
params = { key: provider_config.api_key }
|
31
31
|
|
32
|
-
|
33
|
-
response = request(payload, params)
|
32
|
+
response = request(payload, params)
|
34
33
|
|
35
|
-
|
36
|
-
|
34
|
+
json_string = response&.dig('candidates', 0, 'content', 'parts', 0, 'text')
|
35
|
+
return nil if json_string.nil? || json_string.empty?
|
37
36
|
|
38
|
-
|
39
|
-
end
|
37
|
+
normalize_response(json_string)
|
40
38
|
end
|
41
39
|
|
42
40
|
API_VERSION_PATH = 'v1beta/models'
|
@@ -25,15 +25,13 @@ module ActiveGenie
|
|
25
25
|
model:
|
26
26
|
}
|
27
27
|
|
28
|
-
|
29
|
-
response = request(payload)
|
28
|
+
response = request(payload)
|
30
29
|
|
31
|
-
|
30
|
+
raise InvalidResponseError, "Invalid response: #{response}" if response.nil? || response.keys.empty?
|
32
31
|
|
33
|
-
|
32
|
+
ActiveGenie::Logger.call({ code: :function_calling, fine_tune: true, payload:, response: })
|
34
33
|
|
35
|
-
|
36
|
-
end
|
34
|
+
response
|
37
35
|
end
|
38
36
|
|
39
37
|
private
|
@@ -24,25 +24,27 @@ module ActiveGenie
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def output_call(log)
|
27
|
-
output
|
27
|
+
output&.call(log)
|
28
28
|
|
29
29
|
Array(@observers).each do |obs|
|
30
30
|
next unless obs[:scope].all? { |key, value| log[key.to_sym] == value }
|
31
31
|
|
32
|
-
obs[:observer]
|
32
|
+
obs[:observer]&.call(log)
|
33
33
|
rescue StandardError => e
|
34
34
|
ActiveGenie::Logger.call(code: :observer_error, **obs, error: e.message)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def add_observer(observers: [], scope:
|
38
|
+
def add_observer(observers: [], scope: {}, &block)
|
39
39
|
@observers ||= []
|
40
40
|
|
41
|
-
raise ArgumentError, 'Scope must be a hash'
|
41
|
+
raise ArgumentError, 'Scope must be a hash' if scope && !scope.is_a?(Hash)
|
42
42
|
|
43
|
-
@observers << { observer: block, scope:
|
43
|
+
@observers << { observer: block, scope: } if block_given?
|
44
44
|
Array(observers).each do |observer|
|
45
|
-
|
45
|
+
next unless observer.respond_to?(:call)
|
46
|
+
|
47
|
+
@observers << { observer:, scope: }
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -37,8 +37,8 @@ module ActiveGenie
|
|
37
37
|
def call
|
38
38
|
response = Generalist.call(@text, data_to_extract_with_litote, config: @config)
|
39
39
|
|
40
|
-
if response[
|
41
|
-
response = Generalist.call(response[
|
40
|
+
if response[:message_litote]
|
41
|
+
response = Generalist.call(response[:litote_rephrased], @data_to_extract, config: @config)
|
42
42
|
end
|
43
43
|
|
44
44
|
response
|
data/lib/active_genie/logger.rb
CHANGED
@@ -21,13 +21,15 @@ module ActiveGenie
|
|
21
21
|
log
|
22
22
|
end
|
23
23
|
|
24
|
-
def with_context(context)
|
24
|
+
def with_context(context, observer: nil)
|
25
25
|
@context ||= {}
|
26
26
|
begin
|
27
27
|
@context = @context.merge(context)
|
28
|
+
config.add_observer(observers: [observer])
|
28
29
|
yield if block_given?
|
29
30
|
ensure
|
30
31
|
@context.delete_if { |key, _| context.key?(key) }
|
32
|
+
config.remove_observer([observer])
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -17,11 +17,13 @@ module ActiveGenie
|
|
17
17
|
@config = config
|
18
18
|
@tmp_defenders = []
|
19
19
|
@total_tokens = 0
|
20
|
-
@previous_elo =
|
20
|
+
@previous_elo = {}
|
21
21
|
@previous_highest_elo = @defender_tier.max_by(&:elo).elo
|
22
22
|
end
|
23
23
|
|
24
24
|
def call
|
25
|
+
@previous_elo = @players.to_h { |player| [player.id, player.elo] }
|
26
|
+
|
25
27
|
ActiveGenie::Logger.with_context(log_context) do
|
26
28
|
matches.each do |player_a, player_b|
|
27
29
|
# TODO: battle can take a while, can be parallelized
|
@@ -38,14 +40,17 @@ module ActiveGenie
|
|
38
40
|
|
39
41
|
private
|
40
42
|
|
41
|
-
def save_previous_elo
|
42
|
-
@previous_elo = @players.to_h { |player| [player.id, player.elo] }
|
43
|
-
end
|
44
|
-
|
45
43
|
def matches
|
44
|
+
match_keys = {}
|
45
|
+
|
46
46
|
@relegation_tier.each_with_object([]) do |attack_player, matches|
|
47
47
|
BATTLE_PER_PLAYER.times do
|
48
|
-
|
48
|
+
defense_player = next_defense_player
|
49
|
+
|
50
|
+
next if match_keys["#{attack_player.id}_#{defense_player.id}"]
|
51
|
+
|
52
|
+
match_keys["#{attack_player.id}_#{defense_player.id}"] = true
|
53
|
+
matches << [attack_player, defense_player]
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
@@ -130,7 +135,7 @@ module ActiveGenie
|
|
130
135
|
elo_diffs = players_in_round.map do |player|
|
131
136
|
[player.id, player.elo - @previous_elo[player.id]]
|
132
137
|
end
|
133
|
-
elo_diffs.sort_by { |_, diff| -diff }.to_h
|
138
|
+
elo_diffs.sort_by { |_, diff| -(diff || 0) }.to_h
|
134
139
|
end
|
135
140
|
|
136
141
|
def log_observer(log)
|
@@ -18,7 +18,7 @@ module ActiveGenie
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def call
|
21
|
-
ActiveGenie::Logger.with_context(log_context, observer:
|
21
|
+
ActiveGenie::Logger.with_context(log_context, observer: ->(log) { log_observer(log) }) do
|
22
22
|
matches.each do |player_a, player_b|
|
23
23
|
winner, loser = battle(player_a, player_b)
|
24
24
|
|
@@ -10,8 +10,6 @@ module ActiveGenie
|
|
10
10
|
@params[:content] ||= @params
|
11
11
|
end
|
12
12
|
|
13
|
-
attr_accessor :rank
|
14
|
-
|
15
13
|
def content
|
16
14
|
@content ||= @params[:content]
|
17
15
|
end
|
@@ -29,7 +27,7 @@ module ActiveGenie
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def elo
|
32
|
-
@elo
|
30
|
+
@elo = @elo || @params[:elo] || generate_elo_by_score
|
33
31
|
end
|
34
32
|
|
35
33
|
def ffa_win_count
|
@@ -56,7 +54,7 @@ module ActiveGenie
|
|
56
54
|
|
57
55
|
def elo=(value)
|
58
56
|
ActiveGenie::Logger.call({ code: :new_elo, player_id: id, elo: value }) if value != @elo
|
59
|
-
@elo = value
|
57
|
+
@elo = value || BASE_ELO
|
60
58
|
end
|
61
59
|
|
62
60
|
def eliminated=(value)
|
@@ -80,7 +78,7 @@ module ActiveGenie
|
|
80
78
|
end
|
81
79
|
|
82
80
|
def ffa_score
|
83
|
-
(
|
81
|
+
(ffa_win_count * 3) + ffa_draw_count
|
84
82
|
end
|
85
83
|
|
86
84
|
def sort_value
|
@@ -93,7 +91,9 @@ module ActiveGenie
|
|
93
91
|
|
94
92
|
def to_h
|
95
93
|
{
|
96
|
-
id:, name:, content:,
|
94
|
+
id:, name:, content:,
|
95
|
+
|
96
|
+
score:, elo:,
|
97
97
|
ffa_win_count:, ffa_lose_count:, ffa_draw_count:,
|
98
98
|
eliminated:, ffa_score:, sort_value:
|
99
99
|
}
|
@@ -121,7 +121,9 @@ module ActiveGenie
|
|
121
121
|
private
|
122
122
|
|
123
123
|
def generate_elo_by_score
|
124
|
-
BASE_ELO
|
124
|
+
return BASE_ELO if @score.nil?
|
125
|
+
|
126
|
+
BASE_ELO + (@score - 50)
|
125
127
|
end
|
126
128
|
end
|
127
129
|
end
|
@@ -52,17 +52,11 @@ module ActiveGenie
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def sorted
|
55
|
-
|
56
|
-
sorted_players.each_with_index { |p, i| p.rank = i + 1 }
|
57
|
-
sorted_players
|
55
|
+
@players.sort_by { |p| -p.sort_value }
|
58
56
|
end
|
59
57
|
|
60
58
|
def to_json(*_args)
|
61
|
-
to_h.to_json
|
62
|
-
end
|
63
|
-
|
64
|
-
def to_h
|
65
|
-
sorted.map(&:to_h)
|
59
|
+
@players.map(&:to_h).to_json
|
66
60
|
end
|
67
61
|
|
68
62
|
def method_missing(...)
|
@@ -90,7 +84,11 @@ module ActiveGenie
|
|
90
84
|
def tier_size
|
91
85
|
size = (eligible_size / 3).ceil
|
92
86
|
|
93
|
-
|
87
|
+
if eligible_size < 10
|
88
|
+
(eligible_size / 2).ceil
|
89
|
+
else
|
90
|
+
size.clamp(10, eligible_size - 10)
|
91
|
+
end
|
94
92
|
end
|
95
93
|
end
|
96
94
|
end
|
@@ -20,8 +20,7 @@ module ActiveGenie
|
|
20
20
|
ActiveGenie::Logger.with_context(log_context) do
|
21
21
|
@reviewers = generate_reviewers
|
22
22
|
|
23
|
-
|
24
|
-
players_to_score.each do |player|
|
23
|
+
players_without_score.each do |player|
|
25
24
|
player.score = generate_score(player)
|
26
25
|
end
|
27
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_genie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.26.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radamés Roriz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
The lodash for GenAI, stop reinventing the wheel
|