ruby_bots 0.0.21 → 0.0.22

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 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: