active_genie 0.28.2 → 0.29.0
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/battle/fight.prompt.md +6 -3
- data/lib/active_genie/battle/fight.rb +2 -2
- data/lib/active_genie/battle/generalist.rb +2 -2
- data/lib/active_genie/battle.rb +4 -0
- data/lib/active_genie/config/factory_config.rb +19 -0
- data/lib/active_genie/configuration.rb +7 -2
- data/lib/active_genie/factory/feud.json +21 -0
- data/lib/active_genie/factory/feud.prompt.md +20 -0
- data/lib/active_genie/factory/feud.rb +61 -0
- data/lib/active_genie/factory.rb +21 -0
- data/lib/active_genie/scoring/generalist.rb +1 -1
- data/lib/active_genie.rb +1 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d304f581f4ebf42ba3fe4095d319c7d450b554b7af7c9a86ff4c34af1d6b771
|
4
|
+
data.tar.gz: 749952b6fcf70903b247987d739ab8d2a55e40fd70873ed65f9eedf64fde9abd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb9fccff5748c42bdf51dbd4b57041bd6de75f69cafa10cf77246eb6e3e67c4204436187fb595afd70af610b841b103bfd79f5040019e58a779a6eae8b17802e
|
7
|
+
data.tar.gz: 1a958882621ce6a9f5d20b2383e8be76bee47e776d30a8f007f7d20516aefb01c936dd56f315cc3e1d1c0255d4eafc7ad9d80e477edf308b2acd5392489198db
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.29.0
|
@@ -1,4 +1,5 @@
|
|
1
|
-
Create a dynamic, back-and-forth verbal match between two fighters, given their names and preferred fighting styles.
|
1
|
+
Create a dynamic, back-and-forth verbal match between two fighters, given their names and preferred fighting styles. Criteria are vital as they provide a clear metric to compare the players. Follow these criteria strictly.
|
2
|
+
In this match, fighters do not physically battle, instead, they engage in a spoken confrontation, each describing and boasting about their fighting style, how their techniques would outmaneuver, counter, or overwhelm the other's approach. Each moviment must be focused in how it will help the fighter to reach the criteria as fully as possible. Ensure that each verbal exchange details:
|
2
3
|
- The technique or strategy the speaker would use.
|
3
4
|
- How that move is superior to the opponent’s last stated tactic.
|
4
5
|
- How the opponent might respond, and what reply the speaker would have.
|
@@ -10,7 +11,8 @@ Explicit steps:
|
|
10
11
|
- Alternate dialogue, with each fighter explaining their tactical move, then the intended counter or rebuttal, going at least two cycles each.
|
11
12
|
- Ensure reasoning (the logic or explanation behind each technique and counter) always precedes the conclusion or actual "move" or taunt.
|
12
13
|
- Close with a final statement or taunt from each fighter, maintaining the competitive tone.
|
13
|
-
- Make the dialogue lively and imaginative
|
14
|
+
- Make the dialogue lively and imaginative.
|
15
|
+
- Make sure follow these criteria strictly.
|
14
16
|
|
15
17
|
Output Format:
|
16
18
|
- Structure as a script, with each turn labeled by the fighter’s name.
|
@@ -23,6 +25,7 @@ Example:
|
|
23
25
|
Example Input:
|
24
26
|
Fighter One: Master Crane, Style: Crane Kung Fu
|
25
27
|
Fighter Two: Iron Ox, Style: Ox Bull Charge
|
28
|
+
Criteria: Fair fight 1v1 using only techniques from their style.
|
26
29
|
|
27
30
|
Example Output:
|
28
31
|
Master Crane: My Crane Kung Fu relies on lightness and precision, striking where your heavy blows simply can't reach. Your Ox Bull Charge is powerful, but too direct, I'd dance aside and tap your pressure points before you even turn.
|
@@ -38,4 +41,4 @@ Important Considerations:
|
|
38
41
|
- Always have the reasoning/strategy before the actual attack or boast in each utterance.
|
39
42
|
- Maintain the turn order and competitive dialogue style.
|
40
43
|
|
41
|
-
*Reminder: The main objective is to script an imaginative, turn-based verbal contest between two
|
44
|
+
*Reminder: The main objective is to script an imaginative, turn-based verbal contest between two fighters, with detailed reasoning and taunts about their style advantages until reach the criteria, as instructed above.*
|
@@ -16,9 +16,9 @@ module ActiveGenie
|
|
16
16
|
def call
|
17
17
|
messages = [
|
18
18
|
{ role: 'system', content: PROMPT },
|
19
|
-
{ role: 'user', content: "criteria: #{@criteria}" },
|
20
19
|
{ role: 'user', content: "player_a: #{@player_a}" },
|
21
|
-
{ role: 'user', content: "player_b: #{@player_b}" }
|
20
|
+
{ role: 'user', content: "player_b: #{@player_b}" },
|
21
|
+
{ role: 'user', content: "criteria: #{@criteria}" }
|
22
22
|
]
|
23
23
|
|
24
24
|
response = ::ActiveGenie::Clients::UnifiedClient.function_calling(
|
@@ -40,9 +40,9 @@ module ActiveGenie
|
|
40
40
|
def call
|
41
41
|
messages = [
|
42
42
|
{ role: 'system', content: PROMPT },
|
43
|
-
{ role: 'user', content: "criteria: #{@criteria}" },
|
44
43
|
{ role: 'user', content: "player_a: #{@player_a}" },
|
45
|
-
{ role: 'user', content: "player_b: #{@player_b}" }
|
44
|
+
{ role: 'user', content: "player_b: #{@player_b}" },
|
45
|
+
{ role: 'user', content: "criteria: #{@criteria}" }
|
46
46
|
]
|
47
47
|
|
48
48
|
response = ::ActiveGenie::Clients::UnifiedClient.function_calling(
|
data/lib/active_genie/battle.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveGenie
|
4
|
+
module Config
|
5
|
+
class FactoryConfig
|
6
|
+
attr_accessor :number_of_items
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@number_of_items = 5
|
10
|
+
end
|
11
|
+
|
12
|
+
def merge(config_params = {})
|
13
|
+
dup.tap do |config|
|
14
|
+
config.number_of_items = config_params[:number_of_items] if config_params.key?(:number_of_items)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -7,6 +7,7 @@ require_relative 'config/scoring_config'
|
|
7
7
|
require_relative 'config/data_extractor_config'
|
8
8
|
require_relative 'config/battle_config'
|
9
9
|
require_relative 'config/llm_config'
|
10
|
+
require_relative 'config/factory_config'
|
10
11
|
|
11
12
|
module ActiveGenie
|
12
13
|
class Configuration
|
@@ -34,6 +35,10 @@ module ActiveGenie
|
|
34
35
|
@battle ||= Config::BattleConfig.new
|
35
36
|
end
|
36
37
|
|
38
|
+
def factory
|
39
|
+
@factory ||= Config::FactoryConfig.new
|
40
|
+
end
|
41
|
+
|
37
42
|
def llm
|
38
43
|
@llm ||= Config::LlmConfig.new
|
39
44
|
end
|
@@ -42,7 +47,7 @@ module ActiveGenie
|
|
42
47
|
@logger ||= ActiveGenie::Logger.new(log_config: log)
|
43
48
|
end
|
44
49
|
|
45
|
-
SUB_CONFIGS = %w[log providers llm ranking scoring data_extractor battle].freeze
|
50
|
+
SUB_CONFIGS = %w[log providers llm ranking scoring data_extractor battle factory].freeze
|
46
51
|
|
47
52
|
def merge(config_params = {})
|
48
53
|
return config_params if config_params.is_a?(Configuration)
|
@@ -80,6 +85,6 @@ module ActiveGenie
|
|
80
85
|
end
|
81
86
|
end
|
82
87
|
|
83
|
-
attr_writer
|
88
|
+
attr_writer(*SUB_CONFIGS, :logger)
|
84
89
|
end
|
85
90
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"name": "feud_items_generator",
|
3
|
+
"description": "Generate a list of items for a given theme.",
|
4
|
+
"parameters": {
|
5
|
+
"type": "object",
|
6
|
+
"properties": {
|
7
|
+
"theme": {
|
8
|
+
"type": "string",
|
9
|
+
"description": "The theme for the feud."
|
10
|
+
},
|
11
|
+
"items": {
|
12
|
+
"type": "array",
|
13
|
+
"description": "The list of items for the feud.",
|
14
|
+
"items": {
|
15
|
+
"type": "string"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"required": ["theme", "items"]
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Emulate the game "Family Feud": For a given theme, reason about the general public's most common answers impersonating a survey of average people's opinions and generate an ordered, survey-style answer list.
|
2
|
+
|
3
|
+
- Before producing the answer list, internally consider: If a group of average people were surveyed on this theme, which answers would be mentioned most frequently?.
|
4
|
+
|
5
|
+
# Output Format
|
6
|
+
|
7
|
+
A numbered list in plain text
|
8
|
+
|
9
|
+
# Example
|
10
|
+
|
11
|
+
Example for the theme "Favorite Fast Foods":
|
12
|
+
1. Pizza
|
13
|
+
2. Hamburgers
|
14
|
+
3. Hot Dogs
|
15
|
+
4. French Fries
|
16
|
+
|
17
|
+
# Notes
|
18
|
+
|
19
|
+
- Always impersonate a "Family Feud" survey: order is critical most likely answers should come first.
|
20
|
+
- Judge each item by their general public reputation and cultural impact.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../clients/unified_client'
|
4
|
+
|
5
|
+
module ActiveGenie
|
6
|
+
module Factory
|
7
|
+
# The Factory::Feud class provides a foundation for generating a list of items for a given theme
|
8
|
+
#
|
9
|
+
# @example Feud usage with two players and criteria
|
10
|
+
# Feud.call("Industries that are most likely to be affected by climate change")
|
11
|
+
#
|
12
|
+
class Feud
|
13
|
+
def self.call(...)
|
14
|
+
new(...).call
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param theme [String] The theme for the feud
|
18
|
+
# @param config [Hash] Additional configuration options that modify the battle evaluation behavior
|
19
|
+
# @return [Array of strings] List of items
|
20
|
+
def initialize(theme, config: {})
|
21
|
+
@theme = theme
|
22
|
+
@config = ActiveGenie.configuration.merge(config)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Array] The list of items
|
26
|
+
def call
|
27
|
+
messages = [
|
28
|
+
{ role: 'system', content: PROMPT },
|
29
|
+
{ role: 'system', content: "List #{number_of_items} top items." },
|
30
|
+
{ role: 'user', content: "theme: #{@theme}" }
|
31
|
+
]
|
32
|
+
|
33
|
+
response = ::ActiveGenie::Clients::UnifiedClient.function_calling(
|
34
|
+
messages,
|
35
|
+
FUNCTION,
|
36
|
+
config: @config
|
37
|
+
)
|
38
|
+
|
39
|
+
log_feud(response)
|
40
|
+
response['items']
|
41
|
+
end
|
42
|
+
|
43
|
+
PROMPT = File.read(File.join(__dir__, 'feud.prompt.md'))
|
44
|
+
FUNCTION = JSON.parse(File.read(File.join(__dir__, 'feud.json')), symbolize_names: true)
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def number_of_items
|
49
|
+
@config.factory.number_of_items
|
50
|
+
end
|
51
|
+
|
52
|
+
def log_feud(response)
|
53
|
+
@config.logger.call(
|
54
|
+
code: :feud,
|
55
|
+
theme: @theme[0..30],
|
56
|
+
items: response['items'].map { |item| item[0..30] }
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'factory/feud'
|
4
|
+
|
5
|
+
module ActiveGenie
|
6
|
+
module Factory
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def feud(...)
|
10
|
+
Feud.call(...)
|
11
|
+
end
|
12
|
+
|
13
|
+
def list(...)
|
14
|
+
Feud.call(...)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(...)
|
18
|
+
Feud.call(...)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/active_genie.rb
CHANGED
@@ -13,6 +13,7 @@ module ActiveGenie
|
|
13
13
|
autoload :Battle, File.join(__dir__, 'active_genie/battle')
|
14
14
|
autoload :Scoring, File.join(__dir__, 'active_genie/scoring')
|
15
15
|
autoload :Ranking, File.join(__dir__, 'active_genie/ranking')
|
16
|
+
autoload :Factory, File.join(__dir__, 'active_genie/factory')
|
16
17
|
|
17
18
|
VERSION = File.read(File.expand_path('../VERSION', __dir__)).strip
|
18
19
|
|
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.29.0
|
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-07-
|
11
|
+
date: 2025-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
ActiveGenie is a Ruby gem that helps developers build reliable, future-proof GenAI features without worrying about changing models, prompts, or providers. Like Lodash for GenAI, it offers simple, reusable modules for tasks like data extraction, scoring, and ranking, so you can focus on your app’s logic, not the shifting AI landscape.
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/active_genie/clients/unified_client.rb
|
39
39
|
- lib/active_genie/config/battle_config.rb
|
40
40
|
- lib/active_genie/config/data_extractor_config.rb
|
41
|
+
- lib/active_genie/config/factory_config.rb
|
41
42
|
- lib/active_genie/config/llm_config.rb
|
42
43
|
- lib/active_genie/config/log_config.rb
|
43
44
|
- lib/active_genie/config/providers/anthropic_config.rb
|
@@ -57,6 +58,10 @@ files:
|
|
57
58
|
- lib/active_genie/data_extractor/generalist.rb
|
58
59
|
- lib/active_genie/errors/invalid_log_output_error.rb
|
59
60
|
- lib/active_genie/errors/invalid_provider_error.rb
|
61
|
+
- lib/active_genie/factory.rb
|
62
|
+
- lib/active_genie/factory/feud.json
|
63
|
+
- lib/active_genie/factory/feud.prompt.md
|
64
|
+
- lib/active_genie/factory/feud.rb
|
60
65
|
- lib/active_genie/logger.rb
|
61
66
|
- lib/active_genie/ranking.rb
|
62
67
|
- lib/active_genie/ranking/elo_round.rb
|