ruby_bots 0.0.24 → 0.0.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ruby_bots/bot.rb +8 -3
- data/lib/ruby_bots/bots/openai_bot.rb +20 -13
- data/lib/ruby_bots/bots/openai_react_bot.rb +90 -86
- data/lib/ruby_bots/bots/pipeline_bot.rb +11 -6
- data/lib/ruby_bots/bots/router_bot.rb +31 -23
- data/lib/ruby_bots/tool.rb +28 -23
- data/lib/ruby_bots/tools/openai_tool.rb +16 -14
- data/lib/ruby_bots/tools/wolfram_tool.rb +8 -7
- data/lib/ruby_bots/version.rb +2 -2
- data/lib/ruby_bots.rb +25 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7500351293df6637a79657ff218f06faa376a9a35104e11cf8d7f232af2de1d0
|
4
|
+
data.tar.gz: 1fbcb4915525bc159649c098ae66c02cdb41a1ae15941e709d5073327026559a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b76904f26db1b284a6ebc7cd262dcc9d86276afaead350bff6f61964b633d05314f857f3128996b8395fc7cd2df04eab796af9fd81cfef0a43008625d86f89e7
|
7
|
+
data.tar.gz: e685e6fa6df00ceb1c89bceeadf15a2ca06f8ebac02b1b5f7941fbedfbedf98ca5ad0093c300707d25a5fef26203fcc990ccc9339817b9ee260d56bdb80e8790
|
data/lib/ruby_bots/bot.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# Base class for all RubyBots bots
|
2
3
|
class Bot < Tool
|
3
4
|
attr_accessor :tools
|
4
5
|
|
5
|
-
def initialize(
|
6
|
+
def initialize(tools:, name: 'RubyBots Bot', description: 'This is a RubyBots bot')
|
6
7
|
@tools = tools
|
7
|
-
super(name
|
8
|
+
super(name:, description:)
|
8
9
|
end
|
9
10
|
|
10
11
|
private
|
@@ -12,5 +13,9 @@ module RubyBots
|
|
12
13
|
def run(input)
|
13
14
|
raise NotImplementedError
|
14
15
|
end
|
16
|
+
|
17
|
+
def tool_name?(param)
|
18
|
+
errors << 'invalid tool name' unless @tools.map(&:name).include?(param)
|
19
|
+
end
|
15
20
|
end
|
16
|
-
end
|
21
|
+
end
|
@@ -1,38 +1,45 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# Bot class for OpenAI. This will use open AI to determine which tool to use for the response.
|
2
3
|
class OpenAIBot < OpenAITool
|
3
4
|
attr_accessor :tools
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
validate_output :tool_name?
|
7
|
+
|
8
|
+
DEFAULT_DESCRIPTION = 'This bot will use OpenAI to determine the appropriate tool.'.freeze
|
9
|
+
|
10
|
+
def initialize(tools:, name: 'OpenAI bot', description: DEFAULT_DESCRIPTION)
|
8
11
|
@tools = tools
|
9
|
-
super(name
|
12
|
+
super(name:, description:)
|
10
13
|
end
|
11
14
|
|
12
15
|
def system_instructions
|
13
16
|
<<~PROMPT
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
You are an assistant designed to select a tool for a user to use. You are provided with the user's input.
|
18
|
+
Select from the following tools (name - description):
|
19
|
+
#{tools.map { |t| "#{t.name} - #{t.description}" }.join('\n')}
|
17
20
|
|
18
|
-
|
19
|
-
|
21
|
+
Return only the name of the tool that best fits the user's request.
|
22
|
+
If no tools match the user's request respond with "no tool" and nothing more.
|
20
23
|
PROMPT
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
24
|
-
|
27
|
+
|
25
28
|
def run(input)
|
26
29
|
params = {
|
27
30
|
messages: [
|
28
31
|
{ role: :system, content: system_instructions },
|
29
32
|
{ role: :user, content: input }
|
30
33
|
]
|
31
|
-
}.merge(default_params)
|
34
|
+
}.merge(default_params)
|
32
35
|
|
33
36
|
response = client.chat(parameters: params)
|
34
37
|
|
35
|
-
response.dig(
|
38
|
+
response.dig('choices', 0, 'message', 'content')
|
39
|
+
end
|
40
|
+
|
41
|
+
def tool_name?(param)
|
42
|
+
errors << 'invalid tool name' unless @tools.map(&:name).include?(param)
|
36
43
|
end
|
37
44
|
end
|
38
|
-
end
|
45
|
+
end
|
@@ -1,125 +1,129 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# This bot uses the ReAct framework to select from the provide tools and respond to the user.
|
3
|
+
# The input from the tools that are called by the bot are fed back into the messages as observations.
|
2
4
|
class OpenAIReactBot < OpenAIBot
|
3
5
|
attr_accessor :tools
|
4
6
|
|
5
|
-
DEFAULT_DESCRIPTION =
|
6
|
-
|
7
|
-
|
8
|
-
RubyBots::Tool.new(name:"search", description:"Search the web for information. Input should be the string to search for."),
|
9
|
-
RubyBots::Tool.new(name:"calculate", description:"Solve math problems. Input should be a mathematical expression with no additional details or context."),
|
10
|
-
]
|
7
|
+
DEFAULT_DESCRIPTION = <<~DESCRIPTION.strip_heredoc
|
8
|
+
This bot will use the ReAct framework to determine the appropriate response. It is powered by OpenAI and the ReAct framework.
|
9
|
+
DESCRIPTION
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
DEFAULT_TOOLS = [
|
12
|
+
RubyBots::Tool.new(
|
13
|
+
name: 'search',
|
14
|
+
description: 'Search the web for information. Input should be the string to search for.'
|
15
|
+
),
|
16
|
+
RubyBots::Tool.new(
|
17
|
+
name: 'calculate',
|
18
|
+
description: <<~DESC.strip_heredoc
|
19
|
+
Solve math problems. Input should be a mathematical expression with no additional details or context.
|
20
|
+
DESC
|
21
|
+
)
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
def initialize(tools: DEFAULT_TOOLS, name: 'OpenAI ReAct bot', description: DEFAULT_DESCRIPTION)
|
25
|
+
super(tools:, name:, description:)
|
14
26
|
end
|
15
27
|
|
16
28
|
def examples
|
17
|
-
[
|
29
|
+
[EXAMPLE_ONE, EXAMPLE_TWO]
|
18
30
|
end
|
19
31
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Answer: 72 degrees Fahrenheit
|
32
|
+
EXAMPLE_ONE = <<~EXAMPLE.strip_heredoc
|
33
|
+
User: What is the current temperature in the city Julia Roberts was born in?
|
34
|
+
Thought: I need to know where Julia Roberts was born.
|
35
|
+
Action: search[Julia Roberts birthplace]
|
36
|
+
Observation: Smyrna, Georgia
|
37
|
+
Thought: I need to know the current temperature in Smyrna, Georgia.
|
38
|
+
Action: search[current temperature Smyrna, Georgia]
|
39
|
+
Observation: 72 degrees Fahrenheit
|
40
|
+
Thought: I need to tell the user the current temperature in the city Julia Roberts was born in.
|
41
|
+
Answer: 72 degrees Fahrenheit
|
31
42
|
EXAMPLE
|
32
|
-
|
33
|
-
EXAMPLE_TWO = <<~EXAMPLE
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
Observation: 1903
|
50
|
-
Thought: I need to know the current year.
|
51
|
-
Action: search[current year]
|
52
|
-
Observation: 2023
|
53
|
-
Thought: I need to know the amount of years that have passed since 1903.
|
54
|
-
Action: calculate[2023 - 1903]
|
55
|
-
Observation: 120
|
56
|
-
Thought: I need to know half of 120.
|
57
|
-
Action: calculate[120 / 2]
|
58
|
-
Observation: 60
|
59
|
-
Thought: I need to tell the user half of the amount of years that have passed since the year the first airplane flew.
|
60
|
-
Answer: 60
|
43
|
+
|
44
|
+
EXAMPLE_TWO = <<~EXAMPLE.strip_heredoc
|
45
|
+
User: What is half of the amount of years that have passed since the year the first airplane flew?
|
46
|
+
Thought: I need to know the year the first airplane flew.
|
47
|
+
Action: search[first airplane flight year]
|
48
|
+
Observation: 1903
|
49
|
+
Thought: I need to know the current year.
|
50
|
+
Action: search[current year]
|
51
|
+
Observation: 2023
|
52
|
+
Thought: I need to know the amount of years that have passed since 1903.
|
53
|
+
Action: calculate[2023 - 1903]
|
54
|
+
Observation: 120
|
55
|
+
Thought: I need to know half of 120.
|
56
|
+
Action: calculate[120 / 2]
|
57
|
+
Observation: 60
|
58
|
+
Thought: I need to tell the user half of the amount of years that have passed since the year the first airplane flew.
|
59
|
+
Answer: 60
|
61
60
|
EXAMPLE
|
62
61
|
|
62
|
+
def prefix
|
63
|
+
<<~PROMPT.strip_heredoc
|
64
|
+
You are an assistant designed to provide solutions for a user. You are provided with the user's input.
|
65
|
+
PROMPT
|
66
|
+
end
|
67
|
+
|
68
|
+
def suffix
|
69
|
+
''
|
70
|
+
end
|
71
|
+
|
63
72
|
def system_instructions
|
64
73
|
<<~PROMPT
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
74
|
+
#{prefix}
|
75
|
+
|
76
|
+
You run in a loop of thought, action, observation, and reflection until you have a solution for the user.
|
77
|
+
You can utilize the following actions (name - description):
|
78
|
+
#{tools.map { |t| "#{t.name} - #{t.description}" }.join("\n")}
|
79
|
+
|
80
|
+
You should begin by providing a thought and an action with the necessary input for the action. The action will be executed externally, and then you will be called again with the observation returned from the action.
|
81
|
+
|
82
|
+
You should then begin the loop again and provide a thought and action.
|
69
83
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
You should then begin the loop again and provide a thought and action.
|
84
|
+
If you have a solution for the user, return the solution instead of a new action.
|
85
|
+
The final answer should only answer the question without additional information about reasoning or process.
|
74
86
|
|
75
|
-
|
76
|
-
The final answer should only answer the question without additional information about reasoning or process.
|
87
|
+
#{suffix}
|
77
88
|
|
78
|
-
|
79
|
-
|
89
|
+
Examples:
|
90
|
+
#{examples.join("\n\n")}
|
80
91
|
PROMPT
|
81
92
|
end
|
82
93
|
|
83
94
|
private
|
84
|
-
|
85
|
-
def run(input)
|
86
|
-
params = {
|
87
|
-
messages: [
|
88
|
-
{ role: :system, content: system_instructions },
|
89
|
-
{ role: :user, content: input }
|
90
|
-
]
|
91
|
-
}.merge(default_params)
|
92
95
|
|
93
|
-
|
94
|
-
|
96
|
+
def run(input)
|
97
|
+
params = initial_params(input)
|
95
98
|
|
96
|
-
|
99
|
+
until answer?(response = client.chat(parameters: params).dig('choices', 0, 'message', 'content'))
|
97
100
|
params[:messages] << { role: :assistant, content: response }
|
98
|
-
|
99
|
-
observation = get_observation_from_action(response)
|
100
|
-
|
101
|
-
params[:messages] << { role: :assistant, content: "Observation: #{observation}" }
|
102
|
-
|
103
|
-
response = client.chat(parameters: params)
|
104
|
-
|
105
|
-
response = response.dig("choices", 0, "message", "content")
|
101
|
+
params[:messages] << { role: :assistant, content: "Observation: #{get_observation_from_action(response)}" }
|
106
102
|
end
|
107
|
-
|
108
103
|
get_answer_from_response(response)
|
109
104
|
end
|
110
105
|
|
111
|
-
def
|
106
|
+
def initial_params(input)
|
107
|
+
{
|
108
|
+
messages: [
|
109
|
+
{ role: :system, content: system_instructions },
|
110
|
+
{ role: :user, content: input }
|
111
|
+
]
|
112
|
+
}.merge(default_params)
|
113
|
+
end
|
114
|
+
|
115
|
+
def answer?(input)
|
112
116
|
input.match(/Answer: /)
|
113
117
|
end
|
114
118
|
|
115
119
|
def get_observation_from_action(response)
|
116
|
-
|
117
|
-
tool_name =
|
118
|
-
tool_input =
|
120
|
+
tool_string = response.match(/Action: ([\s\S]*)/)[1]
|
121
|
+
tool_name = tool_string.match(/([a-zA-Z_\- ]*)\[([\s\S]*)\]/)[1]
|
122
|
+
tool_input = tool_string.match(/([a-zA-Z_\- ]*)\[([\s\S]*)\]/)[2]
|
119
123
|
|
120
124
|
notify_observers(:action, tool_name, tool_input)
|
121
125
|
|
122
|
-
tool = tools.find{|t| t.name == tool_name}
|
126
|
+
tool = tools.find { |t| t.name == tool_name }
|
123
127
|
|
124
128
|
tool.response(tool_input)
|
125
129
|
end
|
@@ -1,13 +1,18 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# Class to provide a pipeline of tools to solve a problem.
|
3
|
+
# This bot will call the tools provided in order until each tool has responded.
|
4
|
+
# The bot will respond with the last tool's response.
|
2
5
|
class PipelineBot < Bot
|
3
|
-
DEFAULT_DESCRIPTION =
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
DEFAULT_DESCRIPTION = <<~DESCRIPTION.strip_heredoc
|
7
|
+
This bot will utilize all of its tools in a syncronouse pipeline based on the order the tools are provided."
|
8
|
+
DESCRIPTION
|
9
|
+
|
10
|
+
def initialize(tools:, name: 'Pipeline bot', description: DEFAULT_DESCRIPTION)
|
11
|
+
super(tools:, name:, description:)
|
7
12
|
end
|
8
13
|
|
9
14
|
private
|
10
|
-
|
15
|
+
|
11
16
|
def run(input)
|
12
17
|
tools.each do |tool|
|
13
18
|
input = tool.run(input)
|
@@ -16,4 +21,4 @@ module RubyBots
|
|
16
21
|
input
|
17
22
|
end
|
18
23
|
end
|
19
|
-
end
|
24
|
+
end
|
@@ -1,41 +1,49 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# Class to provide a router to different tools.
|
3
|
+
# This bot connects to the OpenAI API and uses gpt-4 by default to choose a proper tool to route the user's input.
|
4
|
+
# The bot will only select and use one tool by default.
|
2
5
|
class RouterBot < OpenAIBot
|
3
|
-
DEFAULT_DESCRIPTION =
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
DEFAULT_DESCRIPTION = <<~DESCRIPTION.strip_heredoc
|
7
|
+
This bot will route the user's input to the appropriate tool. It will only select and use one tool."
|
8
|
+
DESCRIPTION
|
9
|
+
|
10
|
+
def initialize(tools:, name: 'Router bot', description: DEFAULT_DESCRIPTION)
|
11
|
+
super(tools:, name:, description:)
|
7
12
|
end
|
8
13
|
|
9
14
|
def system_instructions
|
10
15
|
<<~PROMPT
|
11
|
-
|
12
|
-
|
13
|
-
|
16
|
+
You are an assistant helping to route a user's input to the correct tool.
|
17
|
+
You can use the following tools (name - description):
|
18
|
+
#{tools.map { |t| "#{t.name} - #{t.description}" }.join('\n')}
|
14
19
|
|
15
|
-
|
16
|
-
If no tools match the user's request respond with "I'm sorry, I am still learning." and nothing more.
|
20
|
+
Return only the name of the tool that best fits the user's request.
|
17
21
|
PROMPT
|
18
22
|
end
|
19
23
|
|
20
24
|
private
|
21
|
-
|
25
|
+
|
22
26
|
def run(input)
|
23
|
-
params =
|
27
|
+
params = initial_params(input)
|
28
|
+
|
29
|
+
response = client.chat(parameters: params)
|
30
|
+
|
31
|
+
response_text = response.dig('choices', 0, 'message', 'content')
|
32
|
+
|
33
|
+
selected_tool = tools.find { |t| t.name == response_text }
|
34
|
+
|
35
|
+
raise RubyBots::InvalidOutputError, 'invalid tool name' unless selected_tool
|
36
|
+
|
37
|
+
selected_tool.response(input)
|
38
|
+
end
|
39
|
+
|
40
|
+
def initial_params(input)
|
41
|
+
{
|
24
42
|
messages: [
|
25
43
|
{ role: :system, content: system_instructions },
|
26
44
|
{ role: :user, content: input }
|
27
45
|
]
|
28
|
-
}.merge(default_params)
|
29
|
-
|
30
|
-
response = client.chat(parameters: params)
|
31
|
-
|
32
|
-
response_text = response.dig("choices", 0, "message", "content")
|
33
|
-
selected_tool = tools.find{|t| t.name == response_text}
|
34
|
-
if selected_tool
|
35
|
-
selected_tool.response(input)
|
36
|
-
else
|
37
|
-
response_text
|
38
|
-
end
|
46
|
+
}.merge(default_params)
|
39
47
|
end
|
40
48
|
end
|
41
|
-
end
|
49
|
+
end
|
data/lib/ruby_bots/tool.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module RubyBots
|
2
|
+
# Base class for all RubyBots tools and bots
|
2
3
|
class Tool
|
3
4
|
attr_accessor :name, :description, :errors
|
4
5
|
|
@@ -23,41 +24,45 @@ module RubyBots
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def response(input)
|
27
|
+
run_input_validations(input)
|
28
|
+
|
29
|
+
raise RubyBots::InvalidInputError, { errors: @errors } if @errors.any?
|
30
|
+
|
31
|
+
output = run(input)
|
32
|
+
|
33
|
+
run_output_validations(output)
|
34
|
+
|
35
|
+
raise RubyBots::InvalidOutputError, { errors: @errors } if @errors.any?
|
36
|
+
|
37
|
+
output
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def run(input)
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
def run_input_validations(input)
|
26
47
|
self.class.input_validators ||= []
|
27
48
|
self.class.input_validators.each do |validator|
|
28
49
|
send(validator, input)
|
29
50
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
else
|
34
|
-
raise RubyBots::InvalidInputError.new(errors: @errors)
|
35
|
-
end
|
36
|
-
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_output_validations(output)
|
37
54
|
self.class.output_validators ||= []
|
38
55
|
self.class.output_validators.each do |validator|
|
39
56
|
send(validator, output)
|
40
57
|
end
|
41
|
-
|
42
|
-
if @errors.any?
|
43
|
-
raise RubyBots::InvalidOutputError.new(errors: @errors)
|
44
|
-
end
|
45
|
-
|
46
|
-
output
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def run(input)
|
52
|
-
raise NotImplementedError
|
53
58
|
end
|
54
59
|
|
55
|
-
def
|
60
|
+
def json?(param)
|
56
61
|
JSON.parse(param)
|
57
62
|
rescue JSON::ParserError
|
58
|
-
errors <<
|
63
|
+
errors << 'invalid JSON'
|
59
64
|
rescue TypeError
|
60
|
-
errors <<
|
65
|
+
errors << 'value is not a String'
|
61
66
|
end
|
62
67
|
end
|
63
|
-
end
|
68
|
+
end
|
@@ -1,41 +1,43 @@
|
|
1
1
|
require 'openai'
|
2
2
|
|
3
3
|
module RubyBots
|
4
|
+
# Tool for connecting to Open AI. Use this tool to connect to Open AI and get a response.
|
5
|
+
# the default model is gpt-4, it can be altered by overriding the default_params method.
|
4
6
|
class OpenAITool < Tool
|
5
|
-
DEFAULT_DESCRIPTION =
|
6
|
-
|
7
|
-
def initialize(name:
|
8
|
-
super(name
|
7
|
+
DEFAULT_DESCRIPTION = 'This tool will use open ai to determine the output.'.freeze
|
8
|
+
|
9
|
+
def initialize(name: 'OpenAI Tool', description: DEFAULT_DESCRIPTION)
|
10
|
+
super(name:, description:)
|
9
11
|
end
|
10
|
-
|
12
|
+
|
11
13
|
def client
|
12
14
|
@client ||= OpenAI::Client.new(access_token: RubyBots.config.openai_api_key)
|
13
15
|
end
|
14
|
-
|
16
|
+
|
15
17
|
def default_params
|
16
18
|
{
|
17
19
|
model: 'gpt-4',
|
18
20
|
temperature: 0
|
19
21
|
}
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
def system_instructions
|
23
|
-
|
25
|
+
'You are a helpful assistant.'
|
24
26
|
end
|
25
27
|
|
26
28
|
private
|
27
|
-
|
29
|
+
|
28
30
|
def run(input)
|
29
31
|
params = {
|
30
32
|
messages: [
|
31
33
|
{ role: :system, content: system_instructions },
|
32
34
|
{ role: :user, content: input }
|
33
35
|
]
|
34
|
-
}.merge(default_params)
|
35
|
-
|
36
|
+
}.merge(default_params)
|
37
|
+
|
36
38
|
response = client.chat(parameters: params)
|
37
|
-
|
38
|
-
response.dig(
|
39
|
+
|
40
|
+
response.dig('choices', 0, 'message', 'content')
|
39
41
|
end
|
40
42
|
end
|
41
|
-
end
|
43
|
+
end
|
@@ -3,14 +3,15 @@ require 'uri'
|
|
3
3
|
require 'net/http'
|
4
4
|
|
5
5
|
module RubyBots
|
6
|
+
# This tool provides an interface to get responses from the Wolfram Alpha API.
|
7
|
+
# This tool requires an App ID key from Wolfram Alpha.
|
8
|
+
# add it to your environment variables as WOLFRAM_APP_ID
|
9
|
+
# it is currently alpha and not fully working or tested.
|
6
10
|
class WolframTool < Tool
|
7
|
-
|
8
|
-
# add it to your environment variables as WOLFRAM_APP_ID
|
11
|
+
DEFAULT_DESCRIPTION = 'This tool will use the Wolfram Alpha API to answer questions.'.freeze
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(name: "Wolfram tool", description: DEFAULT_DESCRIPTION)
|
13
|
-
super(name: name, description: description)
|
13
|
+
def initialize(name: 'Wolfram tool', description: DEFAULT_DESCRIPTION)
|
14
|
+
super(name:, description:)
|
14
15
|
end
|
15
16
|
|
16
17
|
private
|
@@ -21,4 +22,4 @@ module RubyBots
|
|
21
22
|
resp.body
|
22
23
|
end
|
23
24
|
end
|
24
|
-
end
|
25
|
+
end
|
data/lib/ruby_bots/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module RubyBots
|
2
|
-
VERSION =
|
3
|
-
end
|
2
|
+
VERSION = '0.0.25'.freeze
|
3
|
+
end
|
data/lib/ruby_bots.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# Main module for RubyBots
|
1
2
|
module RubyBots
|
2
3
|
class << self
|
3
4
|
def config
|
@@ -9,11 +10,13 @@ module RubyBots
|
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
13
|
+
# Configuration class
|
12
14
|
class Configuration
|
13
15
|
attr_accessor :openai_api_key
|
14
|
-
|
15
|
-
|
16
|
-
@
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@openai_api_key = ENV['OPENAI_ACCESS_TOKEN']
|
19
|
+
@wolfram_app_id = ENV['WOLFRAM_APPID']
|
17
20
|
end
|
18
21
|
end
|
19
22
|
|
@@ -24,16 +27,27 @@ module RubyBots
|
|
24
27
|
def self.tool
|
25
28
|
RubyBots::Tool
|
26
29
|
end
|
27
|
-
|
30
|
+
|
28
31
|
class Error < StandardError; end
|
29
32
|
class InvalidInputError < Error; end
|
30
33
|
class InvalidOutputError < Error; end
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
class String
|
37
|
+
def strip_heredoc
|
38
|
+
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# tools
|
43
|
+
require_relative 'ruby_bots/tool'
|
44
|
+
require_relative 'ruby_bots/tools/openai_tool'
|
45
|
+
|
46
|
+
# bots
|
47
|
+
require_relative 'ruby_bots/bot'
|
48
|
+
require_relative 'ruby_bots/bots/openai_bot'
|
49
|
+
require_relative 'ruby_bots/bots/pipeline_bot'
|
50
|
+
require_relative 'ruby_bots/bots/router_bot'
|
51
|
+
require_relative 'ruby_bots/bots/openai_react_bot'
|
52
|
+
|
53
|
+
require_relative 'ruby_bots/version'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_bots
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.25
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Paulson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: debug
|
@@ -114,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: '3.1'
|
118
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
120
|
- - ">="
|