active_genie 0.30.1 → 0.30.8
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/README.md +7 -5
- data/VERSION +1 -1
- data/lib/active_genie/comparator/debate.rb +13 -31
- data/lib/active_genie/comparator/fight.rb +3 -3
- data/lib/active_genie/comparator.rb +0 -2
- data/lib/active_genie/configs/base_config.rb +25 -0
- data/lib/active_genie/configs/extractor_config.rb +6 -14
- data/lib/active_genie/configs/lister_config.rb +6 -10
- data/lib/active_genie/configs/llm_config.rb +12 -25
- data/lib/active_genie/configs/log_config.rb +19 -16
- data/lib/active_genie/configs/providers/anthropic_config.rb +10 -16
- data/lib/active_genie/configs/providers/deepseek_config.rb +4 -19
- data/lib/active_genie/configs/providers/google_config.rb +4 -19
- data/lib/active_genie/configs/providers/openai_config.rb +4 -19
- data/lib/active_genie/configs/providers/provider_base.rb +21 -67
- data/lib/active_genie/configs/providers_config.rb +39 -20
- data/lib/active_genie/configs/ranker_config.rb +6 -12
- data/lib/active_genie/configuration.rb +23 -60
- data/lib/active_genie/{ranker/entities → entities}/player.rb +4 -0
- data/lib/active_genie/{ranker/entities → entities}/players.rb +1 -1
- data/lib/active_genie/entities/result.rb +29 -0
- data/lib/active_genie/errors/invalid_model_error.rb +42 -0
- data/lib/active_genie/errors/invalid_provider_error.rb +1 -1
- data/lib/active_genie/errors/provider_server_error.rb +26 -0
- data/lib/active_genie/errors/without_available_provider_error.rb +39 -0
- data/lib/active_genie/extractor/data.json +9 -0
- data/lib/active_genie/extractor/data.prompt.md +12 -0
- data/lib/active_genie/extractor/data.rb +71 -0
- data/lib/active_genie/extractor/explanation.rb +22 -41
- data/lib/active_genie/extractor/litote.rb +10 -9
- data/lib/active_genie/extractor.rb +5 -0
- data/lib/active_genie/lister/feud.json +5 -1
- data/lib/active_genie/lister/feud.rb +12 -17
- data/lib/active_genie/lister/juries.rb +18 -16
- data/lib/active_genie/logger.rb +16 -28
- data/lib/active_genie/providers/anthropic_provider.rb +12 -6
- data/lib/active_genie/providers/base_provider.rb +15 -18
- data/lib/active_genie/providers/deepseek_provider.rb +18 -10
- data/lib/active_genie/providers/google_provider.rb +11 -5
- data/lib/active_genie/providers/openai_provider.rb +8 -6
- data/lib/active_genie/providers/unified_provider.rb +58 -3
- data/lib/active_genie/ranker/elo.rb +41 -36
- data/lib/active_genie/ranker/free_for_all.rb +45 -28
- data/lib/active_genie/ranker/scoring.rb +20 -11
- data/lib/active_genie/ranker/tournament.rb +23 -35
- data/lib/active_genie/scorer/jury_bench.rb +18 -23
- data/lib/active_genie/utils/base_module.rb +34 -0
- data/lib/active_genie/utils/call_wrapper.rb +20 -0
- data/lib/active_genie/utils/deep_merge.rb +12 -0
- data/lib/active_genie/utils/fiber_by_batch.rb +2 -2
- data/lib/active_genie/utils/text_case.rb +18 -0
- data/lib/active_genie.rb +16 -18
- data/lib/tasks/benchmark.rake +1 -3
- data/lib/tasks/templates/active_genie.rb +0 -3
- data/lib/tasks/test.rake +62 -1
- metadata +25 -15
- data/lib/active_genie/configs/comparator_config.rb +0 -10
- data/lib/active_genie/configs/scorer_config.rb +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 02e46bc41ee34451323202588e8018cca0f7497529f9c7f6ce64c0e00e009f7e
|
|
4
|
+
data.tar.gz: 4a78b8402fee546b0fd6fef3352cd85d476399167edf051798ec71709c46bb7b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e606f1827f1b88e67dea196d56173a5dd4c5ff51861a77942faebef38fdd6f252e3077c9ca2bc8585769ab4f873344dea0abebb88d19af1f40493aac9e7374d
|
|
7
|
+
data.tar.gz: 4beac5e264438b7c9eb692669ff16940e140251cc8e87b35e61fbef8eb3fdf604acc2966ed021705bca63a9ff90cd63312abe25143b68364a67d92becd113d58
|
data/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# ActiveGenie 🧞♂️
|
|
2
|
-
> The Lodash for GenAI:
|
|
2
|
+
> The Lodash for GenAI: Consistent + Model-Agnostic
|
|
3
3
|
|
|
4
4
|
[](https://badge.fury.io/rb/active_genie)
|
|
5
5
|
[](https://github.com/roriz/active_genie/actions/workflows/benchmark.yml)
|
|
6
6
|
|
|
7
|
-
ActiveGenie is
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
**ActiveGenie** is an **enabler for creating reliable GenAI features**, offering powerful, **model-agnostic tools** across any provider. It allows you to settle subjective comparisons with a `ActibeGenie::Comparator` module that stages a political debate, get accurate scores from an **AI jury** using `ActiveGenie::Scorer`, and **rank large datasets** using `ActiveGenie::Ranker`'s tournament-style system.
|
|
8
|
+
This reliability is built on three core pillars:
|
|
9
|
+
* **Custom Benchmarking:** Testing for consistency with every new version and model update.
|
|
10
|
+
* **Reasoning Prompting:** Utilizing human reasoning techniques (like debate and jury review) to control a model's reasoning.
|
|
11
|
+
* **Overfitting Prompts:** Highly specialized, and potentially model-specific, prompt for each module's purpose.
|
|
10
12
|
|
|
11
13
|
For full documentation, visit [activegenie.ai](https://activegenie.ai).
|
|
12
14
|
|
|
@@ -57,7 +59,7 @@ schema = {
|
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
result = ActiveGenie::
|
|
62
|
+
result = ActiveGenie::Extractor.call(
|
|
61
63
|
text,
|
|
62
64
|
schema,
|
|
63
65
|
config: { provider_name: :openai, model: 'gpt-4.1-mini' } # optional
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.30.
|
|
1
|
+
0.30.8
|
|
@@ -14,11 +14,7 @@ module ActiveGenie
|
|
|
14
14
|
# @example Debate usage with two players and criteria
|
|
15
15
|
# Debate.call("Player A content", "Player B content", "Evaluate keyword usage and pattern matching")
|
|
16
16
|
#
|
|
17
|
-
class Debate
|
|
18
|
-
def self.call(...)
|
|
19
|
-
new(...).call
|
|
20
|
-
end
|
|
21
|
-
|
|
17
|
+
class Debate < ActiveGenie::BaseModule
|
|
22
18
|
# @param player_a [String] The content or submission from the first player
|
|
23
19
|
# @param player_b [String] The content or submission from the second player
|
|
24
20
|
# @param criteria [String] The evaluation criteria or rules to assess against
|
|
@@ -31,7 +27,7 @@ module ActiveGenie
|
|
|
31
27
|
@player_a = player_a
|
|
32
28
|
@player_b = player_b
|
|
33
29
|
@criteria = criteria
|
|
34
|
-
|
|
30
|
+
super(config:)
|
|
35
31
|
end
|
|
36
32
|
|
|
37
33
|
# @return [ComparatorResponse] The evaluation result containing the winner and reasoning
|
|
@@ -43,13 +39,9 @@ module ActiveGenie
|
|
|
43
39
|
{ role: 'user', content: "criteria: #{@criteria}" }
|
|
44
40
|
]
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
messages,
|
|
48
|
-
FUNCTION,
|
|
49
|
-
config: @config
|
|
50
|
-
)
|
|
42
|
+
provider_response = ::ActiveGenie::Providers::UnifiedProvider.function_calling(messages, FUNCTION, config:)
|
|
51
43
|
|
|
52
|
-
response_formatted(
|
|
44
|
+
response_formatted(provider_response)
|
|
53
45
|
end
|
|
54
46
|
|
|
55
47
|
PROMPT = File.read(File.join(__dir__, 'debate.prompt.md'))
|
|
@@ -57,28 +49,18 @@ module ActiveGenie
|
|
|
57
49
|
|
|
58
50
|
private
|
|
59
51
|
|
|
60
|
-
def response_formatted(
|
|
61
|
-
winner,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
reasoning =
|
|
66
|
-
|
|
67
|
-
comparator_response = ActiveGenie::Comparator::ComparatorResponse.new(winner:, loser:, reasoning:,
|
|
68
|
-
raw: response)
|
|
69
|
-
log_comparator(comparator_response)
|
|
52
|
+
def response_formatted(provider_response)
|
|
53
|
+
winner, = case provider_response['impartial_judge_winner']
|
|
54
|
+
when 'player_a' then [@player_a, @player_b]
|
|
55
|
+
when 'player_b' then [@player_b, @player_a]
|
|
56
|
+
end
|
|
57
|
+
reasoning = provider_response['impartial_judge_winner_reasoning']
|
|
70
58
|
|
|
71
|
-
|
|
59
|
+
ActiveGenie::Result.new(data: winner, reasoning:, metadata: provider_response)
|
|
72
60
|
end
|
|
73
61
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
code: :comparator,
|
|
77
|
-
player_a: @player_a[0..30],
|
|
78
|
-
player_b: @player_b[0..30],
|
|
79
|
-
criteria: @criteria[0..30],
|
|
80
|
-
**comparator_response.to_h
|
|
81
|
-
)
|
|
62
|
+
def module_config
|
|
63
|
+
{ llm: { recommended_model: 'claude-haiku-4-5' } }
|
|
82
64
|
end
|
|
83
65
|
end
|
|
84
66
|
end
|
|
@@ -21,13 +21,13 @@ module ActiveGenie
|
|
|
21
21
|
{ role: 'user', content: "criteria: #{@criteria}" }
|
|
22
22
|
]
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
provider_response = ::ActiveGenie::Providers::UnifiedProvider.function_calling(
|
|
25
25
|
messages,
|
|
26
26
|
FUNCTION,
|
|
27
|
-
config:
|
|
27
|
+
config:
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
-
response_formatted(
|
|
30
|
+
response_formatted(provider_response)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
PROMPT = File.read(File.join(__dir__, 'fight.prompt.md'))
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveGenie
|
|
4
|
+
module Config
|
|
5
|
+
class BaseConfig
|
|
6
|
+
def initialize(**args)
|
|
7
|
+
attributes.each do |var|
|
|
8
|
+
send("#{var}=", args[var] || args[var.to_s])
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def attributes
|
|
13
|
+
public_methods(false).grep(/=$/).map { |m| m.to_s.delete('=').to_sym }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
attributes.each do |var|
|
|
19
|
+
h[var.to_sym] = send(var)
|
|
20
|
+
end
|
|
21
|
+
h
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'base_config'
|
|
4
|
+
|
|
3
5
|
module ActiveGenie
|
|
4
6
|
module Config
|
|
5
|
-
class ExtractorConfig
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def initialize
|
|
9
|
-
@with_explanation = true
|
|
10
|
-
@min_accuracy = 70
|
|
11
|
-
@verbose = false
|
|
12
|
-
end
|
|
7
|
+
class ExtractorConfig < BaseConfig
|
|
8
|
+
attr_writer :min_accuracy
|
|
13
9
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
config.with_explanation = config_params[:with_explanation] if config_params.key?(:with_explanation)
|
|
17
|
-
config.min_accuracy = config_params[:min_accuracy] if config_params.key?(:min_accuracy)
|
|
18
|
-
config.verbose = config_params[:verbose] if config_params.key?(:verbose)
|
|
19
|
-
end
|
|
10
|
+
def min_accuracy
|
|
11
|
+
@min_accuracy ||= 70
|
|
20
12
|
end
|
|
21
13
|
end
|
|
22
14
|
end
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'base_config'
|
|
4
|
+
|
|
3
5
|
module ActiveGenie
|
|
4
6
|
module Config
|
|
5
|
-
class ListerConfig
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def initialize
|
|
9
|
-
@number_of_items = 5
|
|
10
|
-
end
|
|
7
|
+
class ListerConfig < BaseConfig
|
|
8
|
+
attr_writer :number_of_items
|
|
11
9
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
config.number_of_items = config_params[:number_of_items] if config_params.key?(:number_of_items)
|
|
15
|
-
end
|
|
10
|
+
def number_of_items
|
|
11
|
+
@number_of_items ||= 5
|
|
16
12
|
end
|
|
17
13
|
end
|
|
18
14
|
end
|
|
@@ -1,38 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'base_config'
|
|
4
|
+
|
|
3
5
|
module ActiveGenie
|
|
4
6
|
module Config
|
|
5
|
-
class LlmConfig
|
|
6
|
-
attr_accessor :model, :
|
|
7
|
-
:
|
|
7
|
+
class LlmConfig < BaseConfig
|
|
8
|
+
attr_accessor :model, :recommended_model, :max_retries, :retry_delay,
|
|
9
|
+
:read_timeout, :open_timeout
|
|
10
|
+
attr_writer :temperature, :max_fibers, :max_tokens
|
|
8
11
|
attr_reader :provider_name
|
|
9
12
|
|
|
10
|
-
def
|
|
11
|
-
@
|
|
12
|
-
@provider_name = nil
|
|
13
|
-
@provider = nil
|
|
14
|
-
@temperature = 0
|
|
15
|
-
@max_tokens = 4096
|
|
16
|
-
@max_retries = nil
|
|
17
|
-
@retry_delay = nil
|
|
18
|
-
@model_tier = 'lower_tier'
|
|
19
|
-
@read_timeout = nil
|
|
20
|
-
@open_timeout = nil
|
|
21
|
-
@max_fibers = 10
|
|
13
|
+
def temperature
|
|
14
|
+
@temperature ||= 0
|
|
22
15
|
end
|
|
23
16
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@provider_name = provider_name.to_s.downcase.strip.to_sym
|
|
17
|
+
def max_fibers
|
|
18
|
+
@max_fibers ||= 10
|
|
28
19
|
end
|
|
29
20
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
config_params.each do |key, value|
|
|
33
|
-
config.send("#{key}=", value) if config.respond_to?("#{key}=")
|
|
34
|
-
end
|
|
35
|
-
end
|
|
21
|
+
def max_tokens
|
|
22
|
+
@max_tokens ||= 4096
|
|
36
23
|
end
|
|
37
24
|
end
|
|
38
25
|
end
|
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'base_config'
|
|
4
|
+
|
|
3
5
|
module ActiveGenie
|
|
4
6
|
module Config
|
|
5
|
-
class LogConfig
|
|
7
|
+
class LogConfig < BaseConfig
|
|
8
|
+
attr_reader :output
|
|
6
9
|
attr_writer :file_path, :fine_tune_file_path
|
|
7
|
-
attr_reader :output, :observers
|
|
8
10
|
|
|
9
11
|
def file_path
|
|
10
|
-
@file_path
|
|
12
|
+
@file_path ||= 'log/active_genie.log'
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def fine_tune_file_path
|
|
14
|
-
@fine_tune_file_path
|
|
16
|
+
@fine_tune_file_path ||= 'log/active_genie_fine_tune.log'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def observers=(observers)
|
|
20
|
+
Array(observers).each do |observer|
|
|
21
|
+
add_observer(observers: [observer[:observer]], scope: observer[:scope] || {})
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def observers
|
|
26
|
+
@observers ||= []
|
|
15
27
|
end
|
|
16
28
|
|
|
17
29
|
def additional_context
|
|
18
|
-
@additional_context
|
|
30
|
+
@additional_context ||= {}
|
|
19
31
|
end
|
|
20
32
|
|
|
21
33
|
def additional_context=(context)
|
|
22
|
-
@additional_context = additional_context.merge(context).compact
|
|
34
|
+
@additional_context = additional_context.merge(context || {}).compact
|
|
23
35
|
end
|
|
24
36
|
|
|
25
37
|
def output=(output)
|
|
38
|
+
return if output.nil?
|
|
26
39
|
raise InvalidLogOutputError, output unless output.respond_to?(:call)
|
|
27
40
|
|
|
28
41
|
@output = output
|
|
@@ -50,16 +63,6 @@ module ActiveGenie
|
|
|
50
63
|
def clear_observers
|
|
51
64
|
@observers = []
|
|
52
65
|
end
|
|
53
|
-
|
|
54
|
-
def merge(config_params = {})
|
|
55
|
-
dup.tap do |config|
|
|
56
|
-
config_params.compact.each do |key, value|
|
|
57
|
-
config.send("#{key}=", value) if config.respond_to?("#{key}=")
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
config.add_observer(config_params[:observers]) if config_params[:observers]
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
66
|
end
|
|
64
67
|
end
|
|
65
68
|
end
|
|
@@ -8,7 +8,10 @@ module ActiveGenie
|
|
|
8
8
|
# Configuration class for the Anthropic API client.
|
|
9
9
|
# Manages API keys, URLs, model selections, and client instantiation.
|
|
10
10
|
class AnthropicConfig < ProviderBase
|
|
11
|
-
|
|
11
|
+
def initialize(anthropic_version: nil, **args)
|
|
12
|
+
@anthropic_version = anthropic_version
|
|
13
|
+
super(**args)
|
|
14
|
+
end
|
|
12
15
|
|
|
13
16
|
# Retrieves the API key.
|
|
14
17
|
# Falls back to the ANTHROPIC_API_KEY environment variable if not set.
|
|
@@ -31,25 +34,16 @@ module ActiveGenie
|
|
|
31
34
|
@anthropic_version || '2023-06-01'
|
|
32
35
|
end
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# @return [String] The lower tier model name.
|
|
37
|
-
def lower_tier_model
|
|
38
|
-
@lower_tier_model || 'claude-3-5-haiku-20241022'
|
|
37
|
+
def default_model
|
|
38
|
+
@default_model || 'claude-3-5-haiku-20241022'
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# @return [String] The middle tier model name.
|
|
44
|
-
def middle_tier_model
|
|
45
|
-
@middle_tier_model || 'claude-3-7-sonnet-20250219'
|
|
41
|
+
def valid_model?(model)
|
|
42
|
+
model.include?('claude')
|
|
46
43
|
end
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# @return [String] The upper tier model name.
|
|
51
|
-
def higher_tier_model
|
|
52
|
-
@higher_tier_model || 'claude-3-opus-20240229'
|
|
45
|
+
def to_h
|
|
46
|
+
super.merge({ anthropic_version: })
|
|
53
47
|
end
|
|
54
48
|
end
|
|
55
49
|
end
|
|
@@ -8,8 +8,6 @@ module ActiveGenie
|
|
|
8
8
|
# Configuration class for the DeepSeek API client.
|
|
9
9
|
# Manages API keys, organization IDs, URLs, model selections, and client instantiation.
|
|
10
10
|
class DeepseekConfig < ProviderBase
|
|
11
|
-
NAME = :deepseek
|
|
12
|
-
|
|
13
11
|
# Retrieves the API key.
|
|
14
12
|
# Falls back to the DEEPSEEK_API_KEY environment variable if not set.
|
|
15
13
|
# @return [String, nil] The API key.
|
|
@@ -24,25 +22,12 @@ module ActiveGenie
|
|
|
24
22
|
@api_url || 'https://api.deepseek.com/v1'
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# @return [String] The lower tier model name.
|
|
30
|
-
def lower_tier_model
|
|
31
|
-
@lower_tier_model || 'deepseek-chat'
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Retrieves the model name designated for the middle tier (e.g., balanced performance).
|
|
35
|
-
# Defaults to 'deepseek-chat'.
|
|
36
|
-
# @return [String] The middle tier model name.
|
|
37
|
-
def middle_tier_model
|
|
38
|
-
@middle_tier_model || 'deepseek-chat'
|
|
25
|
+
def default_model
|
|
26
|
+
@default_model || 'deepseek-chat'
|
|
39
27
|
end
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# @return [String] The upper tier model name.
|
|
44
|
-
def higher_tier_model
|
|
45
|
-
@higher_tier_model || 'deepseek-reasoner'
|
|
29
|
+
def valid_model?(model)
|
|
30
|
+
model.include?('deepseek')
|
|
46
31
|
end
|
|
47
32
|
end
|
|
48
33
|
end
|
|
@@ -8,8 +8,6 @@ module ActiveGenie
|
|
|
8
8
|
# Configuration class for the Google Generative Language API client.
|
|
9
9
|
# Manages API keys, URLs, model selections, and client instantiation.
|
|
10
10
|
class GoogleConfig < ProviderBase
|
|
11
|
-
NAME = :google
|
|
12
|
-
|
|
13
11
|
# Retrieves the API key.
|
|
14
12
|
# Falls back to the GENERATIVE_LANGUAGE_GOOGLE_API_KEY environment variable if not set.
|
|
15
13
|
# @return [String, nil] The API key.
|
|
@@ -26,25 +24,12 @@ module ActiveGenie
|
|
|
26
24
|
@api_url || 'https://generativelanguage.googleapis.com'
|
|
27
25
|
end
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# @return [String] The lower tier model name.
|
|
32
|
-
def lower_tier_model
|
|
33
|
-
@lower_tier_model || 'gemini-2.0-flash-lite'
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Retrieves the model name designated for the middle tier (e.g., balanced performance).
|
|
37
|
-
# Defaults to 'gemini-2.0-flash'.
|
|
38
|
-
# @return [String] The middle tier model name.
|
|
39
|
-
def middle_tier_model
|
|
40
|
-
@middle_tier_model || 'gemini-2.0-flash'
|
|
27
|
+
def default_model
|
|
28
|
+
@default_model || 'gemini-2.5-flash'
|
|
41
29
|
end
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# @return [String] The upper tier model name.
|
|
46
|
-
def higher_tier_model
|
|
47
|
-
@higher_tier_model || 'gemini-2.5-pro-experimental'
|
|
31
|
+
def valid_model?(model)
|
|
32
|
+
model.include?('gemini')
|
|
48
33
|
end
|
|
49
34
|
end
|
|
50
35
|
end
|
|
@@ -8,8 +8,6 @@ module ActiveGenie
|
|
|
8
8
|
# Configuration class for the OpenAI API client.
|
|
9
9
|
# Manages API keys, organization IDs, URLs, model selections, and client instantiation.
|
|
10
10
|
class OpenaiConfig < ProviderBase
|
|
11
|
-
NAME = :openai
|
|
12
|
-
|
|
13
11
|
# Retrieves the API key.
|
|
14
12
|
# Falls back to the OPENAI_API_KEY environment variable if not set.
|
|
15
13
|
# @return [String, nil] The API key.
|
|
@@ -24,25 +22,12 @@ module ActiveGenie
|
|
|
24
22
|
@api_url || 'https://api.openai.com/v1'
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# @return [String] The lower tier model name.
|
|
30
|
-
def lower_tier_model
|
|
31
|
-
@lower_tier_model || 'gpt-4.1-mini'
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Retrieves the model name designated for the middle tier (e.g., balanced performance).
|
|
35
|
-
# Defaults to 'gpt-4o'.
|
|
36
|
-
# @return [String] The middle tier model name.
|
|
37
|
-
def middle_tier_model
|
|
38
|
-
@middle_tier_model || 'gpt-4.1'
|
|
25
|
+
def default_model
|
|
26
|
+
@default_model || 'gpt-5-mini'
|
|
39
27
|
end
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# @return [String] The upper tier model name.
|
|
44
|
-
def higher_tier_model
|
|
45
|
-
@higher_tier_model || 'o3-mini'
|
|
29
|
+
def valid_model?(model)
|
|
30
|
+
model.include?('gpt')
|
|
46
31
|
end
|
|
47
32
|
end
|
|
48
33
|
end
|
|
@@ -4,37 +4,14 @@ module ActiveGenie
|
|
|
4
4
|
module Config
|
|
5
5
|
module Providers
|
|
6
6
|
class ProviderBase
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Maps a symbolic tier (:lower_tier, :middle_tier, :upper_tier) to a specific model name.
|
|
13
|
-
# Falls back to the lower_tier_model if the tier is nil or unrecognized.
|
|
14
|
-
# @param tier [Symbol, String, nil] The symbolic tier name.
|
|
15
|
-
# @return [String] The corresponding model name.
|
|
16
|
-
def tier_to_model(tier)
|
|
17
|
-
{
|
|
18
|
-
lower_tier: lower_tier_model,
|
|
19
|
-
middle_tier: middle_tier_model,
|
|
20
|
-
upper_tier: higher_tier_model
|
|
21
|
-
}[tier&.to_sym] || lower_tier_model
|
|
7
|
+
def initialize(api_key: nil, organization: nil, api_url: nil, default_model: nil)
|
|
8
|
+
@api_key = api_key
|
|
9
|
+
@organization = organization
|
|
10
|
+
@api_url = api_url
|
|
11
|
+
@default_model = default_model
|
|
22
12
|
end
|
|
23
13
|
|
|
24
|
-
|
|
25
|
-
# @param config [Hash] Additional key-value pairs to merge into the hash.
|
|
26
|
-
# @return [Hash] The configuration settings as a hash.
|
|
27
|
-
def to_h(config = {})
|
|
28
|
-
{
|
|
29
|
-
name: NAME,
|
|
30
|
-
api_key:,
|
|
31
|
-
api_url:,
|
|
32
|
-
lower_tier_model:,
|
|
33
|
-
middle_tier_model:,
|
|
34
|
-
higher_tier_model:,
|
|
35
|
-
**config
|
|
36
|
-
}
|
|
37
|
-
end
|
|
14
|
+
attr_writer :api_key, :organization, :api_url, :default_model
|
|
38
15
|
|
|
39
16
|
# Validates the configuration.
|
|
40
17
|
# @return [Boolean] True if the configuration is valid, false otherwise.
|
|
@@ -42,46 +19,23 @@ module ActiveGenie
|
|
|
42
19
|
api_key && api_url
|
|
43
20
|
end
|
|
44
21
|
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
# @return [
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Retrieves the base API URL for OpenAI API.
|
|
53
|
-
# Defaults to 'https://api.openai.com/v1'.
|
|
54
|
-
# @return [String] The API base URL.
|
|
55
|
-
def api_url
|
|
56
|
-
raise NotImplementedError, 'Subclasses must implement this method'
|
|
22
|
+
# Checks if the given model is valid for this provider. Example provider.valid_model?('gpt-4') => true
|
|
23
|
+
# @param model [String, nil] The model name to validate.
|
|
24
|
+
# @return [Boolean] True if the model is valid, false otherwise.
|
|
25
|
+
def valid_model?(_model)
|
|
26
|
+
false
|
|
57
27
|
end
|
|
58
28
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
# @return [
|
|
62
|
-
def
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def lower_tier_model
|
|
70
|
-
raise NotImplementedError, 'Subclasses must implement this method'
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Retrieves the model name designated for the middle tier (e.g., balanced performance).
|
|
74
|
-
# Defaults to 'gpt-4o'.
|
|
75
|
-
# @return [String] The middle tier model name.
|
|
76
|
-
def middle_tier_model
|
|
77
|
-
raise NotImplementedError, 'Subclasses must implement this method'
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Retrieves the model name designated for the upper tier (e.g., most capable).
|
|
81
|
-
# Defaults to 'o1-preview'.
|
|
82
|
-
# @return [String] The upper tier model name.
|
|
83
|
-
def higher_tier_model
|
|
84
|
-
raise NotImplementedError, 'Subclasses must implement this method'
|
|
29
|
+
# Returns a hash representation of the configuration.
|
|
30
|
+
# @param config [Hash] Additional key-value pairs to merge into the hash.
|
|
31
|
+
# @return [Hash] The configuration settings as a hash.
|
|
32
|
+
def to_h
|
|
33
|
+
{
|
|
34
|
+
api_key: @api_key,
|
|
35
|
+
api_url: @api_url,
|
|
36
|
+
organization: @organization,
|
|
37
|
+
default_model: @default_model
|
|
38
|
+
}
|
|
85
39
|
end
|
|
86
40
|
end
|
|
87
41
|
end
|