ruby_bots 0.0.21 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76d6f4b77a8ef6bc0f8124475142c2fb90460e9c9f602381eca42488aea99ea3
4
- data.tar.gz: bf11eed995aec29f80a3f97f86fc1856f6c4733cdbe7d716cf705af0f9733ad4
3
+ metadata.gz: 9cb9f98a4334909eaa93b2c4f0ed5dcb3c92c85b32ecaeafcf17c2f1e8219a70
4
+ data.tar.gz: 978d6e24d899760d5c79c585ebbf6ee4bb93086c8e809a2d6befa145a74ddf03
5
5
  SHA512:
6
- metadata.gz: 7c052e9aad0d5de43e0ab7644b15ded54a84b1c87429a7780c455d80e93239e15a878a4d015eb9dde9383e300132d661e6e72218dff79b2ac8855117ab2aade3
7
- data.tar.gz: 7fd242669b9332dec10d886ece3145ea3b76420459b5fb532e502f3050803d90cb839e6bb5e65711e6d79dc221a6dc6e5d9b5c115e019ead934bc8a877d8fd2d
6
+ metadata.gz: 44a634ac21766cabd85022c83c96d0672b1cbea6fea831932cf954b891cd310741e618b23cd4a0837e053bf4fb1c706fdc28a414ba7af2ccea451c57ad699d47
7
+ data.tar.gz: 8bbfe05922e5dd8e3016427e60aee9f10e443c811d6dfc1a57fb555d8b134eedd2f41bde6fe2b446315b0b4cfddd65e76d4b408932445190c042da4e4810a5db
data/lib/ruby_bots/bot.rb CHANGED
@@ -9,7 +9,7 @@ module RubyBots
9
9
 
10
10
  private
11
11
 
12
- def run(inputs)
12
+ def run(input)
13
13
  raise NotImplementedError
14
14
  end
15
15
  end
@@ -9,13 +9,24 @@ module RubyBots
9
9
  super(name: name, description: description)
10
10
  end
11
11
 
12
+ def system_instructions
13
+ <<~PROMPT
14
+ You are an assistant designed to select a tool for a user to use. You are provided with the user's input.
15
+ Select from the following tools (name - description):
16
+ #{tools.map{|t| t.name + " - " + t.description}.join("\n")}
17
+
18
+ Return only the name of the tool that best fits the user's request.
19
+ If no tools match the user's request respond with "no tool" and nothing more.
20
+ PROMPT
21
+ end
22
+
12
23
  private
13
24
 
14
- def run(inputs)
25
+ def run(input)
15
26
  params = {
16
27
  messages: [
17
28
  { role: :system, content: system_instructions },
18
- { role: :user, content: inputs }
29
+ { role: :user, content: input }
19
30
  ]
20
31
  }.merge(default_params)
21
32
 
@@ -0,0 +1,131 @@
1
+ module RubyBots
2
+ class OpenAIReactBot < OpenAIBot
3
+ attr_accessor :tools
4
+
5
+ DEFAULT_DESCRIPTION = "This bot will use the ReAct framework to determine the appropriate response. It is powered by OpenAI and the ReAct framework."
6
+
7
+ DEFAULT_TOOLS = [
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
+ ]
11
+
12
+ def initialize(name: "OpenAI ReAct bot", description: DEFAULT_DESCRIPTION, tools: DEFAULT_TOOLS)
13
+ @tools = tools
14
+ super(name: name, description: description)
15
+ end
16
+
17
+ def examples
18
+ [
19
+ <<~EXAMPLE
20
+ User: What is the current temperature in the city Julia Roberts was born in?
21
+ Thought: I need to know where Julia Roberts was born.
22
+ Action: search[Julia Roberts birthplace]
23
+ Observation: Smyrna, Georgia
24
+ Thought: I need to know the current temperature in Smyrna, Georgia.
25
+ Action: search[current temperature Smyrna, Georgia]
26
+ Observation: 72 degrees Fahrenheit
27
+ Thought: I need to tell the user the current temperature in the city Julia Roberts was born in.
28
+ Answer: 72 degrees Fahrenheit
29
+ EXAMPLE
30
+ ,
31
+ <<~EXAMPLE
32
+ User: What is the square of the age of Albert Einstein at his death?
33
+ Thought: I need to know the age of Albert Einstein at his death.
34
+ Action: search[Albert Einstein age at death]
35
+ Observation: 76 years old
36
+ Thought: I need to know the square of 76.
37
+ Action: calculate[76^2]
38
+ Observation: 5776
39
+ Thought: I need to tell the user the square of the age of Albert Einstein at his death.
40
+ Answer: 5776
41
+ EXAMPLE
42
+ ,
43
+ <<~EXAMPLE
44
+ User: What is half of the amount of years that have passed since the year the first airplane flew?
45
+ Thought: I need to know the year the first airplane flew.
46
+ Action: search[first airplane flight year]
47
+ Observation: 1903
48
+ Thought: I need to know the current year.
49
+ Action: search[current year]
50
+ Observation: 2023
51
+ Thought: I need to know the amount of years that have passed since 1903.
52
+ Action: calculate[2023 - 1903]
53
+ Observation: 120
54
+ Thought: I need to know half of 120.
55
+ Action: calculate[120 / 2]
56
+ Observation: 60
57
+ Thought: I need to tell the user half of the amount of years that have passed since the year the first airplane flew.
58
+ Answer: 60
59
+ EXAMPLE
60
+ ]
61
+ end
62
+
63
+ def system_instructions
64
+ <<~PROMPT
65
+ You are an assistant designed to provide solutions for a user. You are provided with the user's input.
66
+ You run in a loop of thought, action, observation, and reflection until you have a solution for the user.
67
+ You can utilize the following actions to gather more information (name - description):
68
+ #{ tools.map{ |t| t.name + " - " + t.description }.join("\n") }
69
+
70
+ You should begin by providing a thought and an action with the necessary input for the action. The action will be
71
+ executed externally, and then you will be called again with the observation returned from the action.
72
+
73
+ You should then begin the loop again and provide a thought and action.
74
+
75
+ If you have a solution for the user, return the solution instead of a new action.
76
+ The final answer should only answer the question without additional information about reasoning or process.
77
+
78
+ Examples:
79
+ #{ examples.join("\n\n") }
80
+ PROMPT
81
+ end
82
+
83
+ 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
+
93
+ response = client.chat(parameters: params)
94
+ response = response.dig("choices", 0, "message", "content")
95
+
96
+ while !is_answer?(response)
97
+ 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")
106
+ end
107
+
108
+ get_answer_from_response(response)
109
+ end
110
+
111
+ def is_answer?(input)
112
+ input.match(/Answer: /)
113
+ end
114
+
115
+ def get_observation_from_action(response)
116
+ t = response.match(/Action: ([\s\S]*)/)[1]
117
+ tool_name = t.match(/([a-zA-Z\-\_]*)\[([\s\S]*)\]/)[1]
118
+ tool_input = t.match(/([a-zA-Z\-\_]*)\[([\s\S]*)\]/)[2]
119
+
120
+ notify_observers(:action, tool_name, tool_input)
121
+
122
+ tool = tools.find{|t| t.name == tool_name}
123
+
124
+ tool.response(tool_input)
125
+ end
126
+
127
+ def get_answer_from_response(response)
128
+ response.match(/Answer: ([\s\S]*)/)[1]
129
+ end
130
+ end
131
+ end
@@ -8,12 +8,12 @@ module RubyBots
8
8
 
9
9
  private
10
10
 
11
- def run(inputs)
11
+ def run(input)
12
12
  tools.each do |tool|
13
- inputs = tool.run(inputs)
13
+ input = tool.run(input)
14
14
  end
15
15
 
16
- inputs
16
+ input
17
17
  end
18
18
  end
19
19
  end
@@ -19,11 +19,11 @@ module RubyBots
19
19
 
20
20
  private
21
21
 
22
- def run(inputs)
22
+ def run(input)
23
23
  params = {
24
24
  messages: [
25
25
  { role: :system, content: system_instructions },
26
- { role: :user, content: inputs }
26
+ { role: :user, content: input }
27
27
  ]
28
28
  }.merge(default_params)
29
29
 
@@ -32,7 +32,7 @@ module RubyBots
32
32
  response_text = response.dig("choices", 0, "message", "content")
33
33
  selected_tool = tools.find{|t| t.name == response_text}
34
34
  if selected_tool
35
- selected_tool.response(inputs)
35
+ selected_tool.response(input)
36
36
  else
37
37
  response_text
38
38
  end
@@ -48,7 +48,7 @@ module RubyBots
48
48
 
49
49
  private
50
50
 
51
- def run(inputs)
51
+ def run(input)
52
52
  raise NotImplementedError
53
53
  end
54
54
 
@@ -25,11 +25,11 @@ module RubyBots
25
25
 
26
26
  private
27
27
 
28
- def run(inputs)
28
+ def run(input)
29
29
  params = {
30
30
  messages: [
31
31
  { role: :system, content: system_instructions },
32
- { role: :user, content: inputs }
32
+ { role: :user, content: input }
33
33
  ]
34
34
  }.merge(default_params)
35
35
 
@@ -0,0 +1,24 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ module RubyBots
6
+ class WolframTool < Tool
7
+ # This tool requires an App ID key from Wolfram Alpha.
8
+ # add it to your environment variables as WOLFRAM_APP_ID
9
+
10
+ DEFAULT_DESCRIPTION = "This tool will use the Wolfram Alpha API to answer questions."
11
+
12
+ def initialize(name: "Wolfram tool", description: DEFAULT_DESCRIPTION)
13
+ super(name: name, description: description)
14
+ end
15
+
16
+ private
17
+
18
+ def run(input)
19
+ uri = URI("http://api.wolframalpha.com/v1/simple?appid=#{ENV['WOLFRAM_APPID']}&i=#{CGI.escape(input)}")
20
+ resp = Net::HTTP.get_response(uri)
21
+ resp.body
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module RubyBots
2
- VERSION = "0.0.21".freeze
2
+ VERSION = "0.0.22".freeze
3
3
  end
data/lib/ruby_bots.rb CHANGED
@@ -13,6 +13,7 @@ module RubyBots
13
13
  attr_accessor :openai_api_key
14
14
  def initialize()
15
15
  @openai_api_key = ENV["OPENAI_ACCESS_TOKEN"]
16
+ @wolfram_app_id = ENV["WOLFRAM_APPID"]
16
17
  end
17
18
  end
18
19
 
@@ -34,4 +35,5 @@ require "ruby_bots/bot"
34
35
  require "ruby_bots/tools/openai_tool.rb"
35
36
  require "ruby_bots/bots/openai_bot.rb"
36
37
  require "ruby_bots/bots/pipeline_bot.rb"
37
- require "ruby_bots/bots/router_bot.rb"
38
+ require "ruby_bots/bots/router_bot.rb"
39
+ require "ruby_bots/bots/openai_react_bot.rb"
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.21
4
+ version: 0.0.22
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-03 00:00:00.000000000 Z
11
+ date: 2023-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: debug
@@ -91,10 +91,12 @@ files:
91
91
  - lib/ruby_bots.rb
92
92
  - lib/ruby_bots/bot.rb
93
93
  - lib/ruby_bots/bots/openai_bot.rb
94
+ - lib/ruby_bots/bots/openai_react_bot.rb
94
95
  - lib/ruby_bots/bots/pipeline_bot.rb
95
96
  - lib/ruby_bots/bots/router_bot.rb
96
97
  - lib/ruby_bots/tool.rb
97
98
  - lib/ruby_bots/tools/openai_tool.rb
99
+ - lib/ruby_bots/tools/wolfram_tool.rb
98
100
  - lib/ruby_bots/version.rb
99
101
  homepage: https://github.com/aha-app/ruby_bots
100
102
  licenses: