boxcars 0.1.8 → 0.2.0

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: 3de375ad403bb62fb6af1045aff6a6115cbb598c3747fe48f882fb40483289e0
4
- data.tar.gz: 343a3077d72ce21a56d8045701a8a3bd681c5fe91fd8ffbca2cc14270b92f3bb
3
+ metadata.gz: 34001190ca60f2b9fe68d603267ffccaaef398cae2f8054e34d6d0926fd8bf9d
4
+ data.tar.gz: 7918d0bad50e6758490a9baa58393e38071e524b0d284c43dd479cf1d091deab
5
5
  SHA512:
6
- metadata.gz: efc72210fb52599b7c6278502a5b4143d995e671c62c7f6c090cbddf2a8926b231b0d7ab0aa28fa1325324ded1ebac5cac4e10e608ae59077a431a20f9d62f23
7
- data.tar.gz: eeb00a993d7bbf64ac5c7461a1e31f241407c58a19a919c0853ade7e4a3bf717ab4f69331c5bc5d8c0049a89c53353d311d41616352131379b7e87b8ec3e491d
6
+ metadata.gz: dacd721802478a783ac9c50c4ebd959764b7601254c3a4b94546f093177cd94bdb4636d9f635154e6419a7d8505152ac7092c491238baab8ac0e47277323a7af
7
+ data.tar.gz: 73c638b8486681e3268ff94e390550f565c011891e9c025556f41df4e0e741ae705fa9fdeb6c3d1996919344abbfff84a8f1454e22a5d108dcae6d65e4718403
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- boxcars (0.1.8)
4
+ boxcars (0.2.0)
5
5
  google_search_results (~> 2.2)
6
6
  ruby-openai (~> 3.0)
7
7
 
@@ -140,7 +140,7 @@ GEM
140
140
  rubocop-rspec (2.18.1)
141
141
  rubocop (~> 1.33)
142
142
  rubocop-capybara (~> 2.17)
143
- ruby-openai (3.3.0)
143
+ ruby-openai (3.5.0)
144
144
  httparty (>= 0.18.1)
145
145
  ruby-progressbar (1.11.0)
146
146
  ruby2_keywords (0.0.5)
@@ -11,7 +11,6 @@ module Boxcars
11
11
  # @param prompt [Boxcars::Prompt] The prompt to use for this boxcar. Defaults to built-in prompt.
12
12
  # @param kwargs [Hash] Any other keyword arguments to pass to the parent class.
13
13
  def initialize(engine: nil, prompt: nil, **kwargs)
14
- # def initialize(engine:, prompt: my_prompt, output_key: :answer, **kwargs)
15
14
  the_prompt = prompt || my_prompt
16
15
  kwargs[:stop] ||= ["```output"]
17
16
  super(name: kwargs[:name] || "Calculator",
@@ -45,7 +44,7 @@ module Boxcars
45
44
  TEMPLATE = <<~'IPT'
46
45
  You are GPT-3, and you can't do math.
47
46
  You can do basic math, and your memorization abilities are impressive, but you can't do any complex calculations that a human could not do in their head. You also have an annoying tendency to just make up highly specific, but wrong, answers.
48
- So we hooked you up to a Ruby 3 kernel, and now you can execute ruby code. If anyone gives you a hard math problem, just use this format and we’ll take care of the rest:
47
+ So we hooked you up to a Ruby 3 kernel, and now you can execute code written in the Ruby programming language. If anyone gives you a hard math problem, just use this format and we’ll take care of the rest:
49
48
 
50
49
  Question: ${{Question with hard calculation.}}
51
50
  ```ruby
@@ -52,8 +52,11 @@ module Boxcars
52
52
  def get_embedded_sql_answer(text)
53
53
  code = text[/^SQLQuery: (.*)/, 1]
54
54
  Boxcars.debug code, :yellow
55
- output = connection.exec_query(code).to_a
56
- "Answer: #{output}"
55
+ output = connection.exec_query(code)
56
+ output = 0 if output.is_a?(Array) && output.empty?
57
+ output = output.first if output.is_a?(Array) && output.length == 1
58
+ output = output[output.keys.first] if output.is_a?(Hash) && output.length == 1
59
+ "Answer: #{output.to_json}"
57
60
  end
58
61
 
59
62
  def get_answer(text)
@@ -111,6 +111,11 @@ module Boxcars
111
111
  end
112
112
  validate_inputs(inputs: inputs)
113
113
  end
114
+
115
+ # the default answer is the text passed in
116
+ def get_answer(text)
117
+ text
118
+ end
114
119
  end
115
120
  end
116
121
 
@@ -9,9 +9,9 @@ module Boxcars
9
9
 
10
10
  # The default parameters to use when asking the engine.
11
11
  DEFAULT_PARAMS = {
12
- model: "text-davinci-003",
12
+ model: "gpt-3.5-turbo",
13
13
  temperature: 0.7,
14
- max_tokens: 256
14
+ max_tokens: 512
15
15
  }.freeze
16
16
 
17
17
  # the default name of the engine
@@ -43,7 +43,13 @@ module Boxcars
43
43
  organization_id = Boxcars.configuration.organization_id
44
44
  clnt = ::OpenAI::Client.new(access_token: access_token, organization_id: organization_id)
45
45
  the_params = { prompt: prompt }.merge(open_ai_params).merge(kwargs)
46
- clnt.completions(parameters: the_params)
46
+ if the_params[:model] == "gpt-3.5-turbo"
47
+ prompt = prompt.first if prompt.is_a?(Array)
48
+ the_params = { messages: [{ role: "user", content: prompt }] }.merge(open_ai_params).merge(kwargs)
49
+ clnt.chat(parameters: the_params)
50
+ else
51
+ clnt.completions(parameters: the_params)
52
+ end
47
53
  end
48
54
 
49
55
  # get an answer from the engine for a question.
@@ -51,7 +57,7 @@ module Boxcars
51
57
  # @param kwargs [Hash] Additional parameters to pass to the engine if wanted.
52
58
  def run(question, **kwargs)
53
59
  response = client(prompt: question, **kwargs)
54
- answer = response["choices"].map { |c| c["text"] }.join("\n").strip
60
+ answer = response["choices"].map { |c| c.dig("message", "content") || c["text"] }.join("\n").strip
55
61
  puts answer
56
62
  answer
57
63
  end
@@ -74,7 +80,7 @@ module Boxcars
74
80
  def generation_info(sub_choices)
75
81
  sub_choices.map do |choice|
76
82
  Generation.new(
77
- text: choice["text"],
83
+ text: choice.dig("message", "content") || choice["text"],
78
84
  generation_info: {
79
85
  finish_reason: choice.fetch("finish_reason", nil),
80
86
  logprobs: choice.fetch("logprobs", nil)
@@ -160,7 +166,8 @@ module Boxcars
160
166
  'text-babbage-001': 2048,
161
167
  'text-ada-001': 2048,
162
168
  'code-davinci-002': 8000,
163
- 'code-cushman-001': 2048
169
+ 'code-cushman-001': 2048,
170
+ 'gpt-3.5-turbo-1': 4096
164
171
  }.freeze
165
172
  model_lookup[modelname] || 4097
166
173
  end
@@ -7,12 +7,19 @@ module Boxcars
7
7
  # @param code [String] The code to run
8
8
  def call(code:)
9
9
  Boxcars.debug "RubyREPL: #{code}", :yellow
10
+
11
+ # wrap the code in an excption block so we can catch errors
12
+ code = "begin\n#{code}\nrescue Exception => e\n puts 'Error: ' + e.message\nend"
10
13
  output = ""
11
14
  IO.popen("ruby", "r+") do |io|
12
15
  io.puts code
13
16
  io.close_write
14
17
  output = io.read
15
18
  end
19
+ if output =~ /^Error: /
20
+ Boxcars.error output
21
+ output
22
+ end
16
23
  Boxcars.debug "Answer: #{output}", :yellow, style: :bold
17
24
  output
18
25
  end
@@ -19,7 +19,7 @@ module Boxcars
19
19
  ... (this Thought/Action/Action Input/Observation sequence can repeat N times)
20
20
  Thought: I now know the final answer
21
21
  Final Answer: the final answer to the original input question
22
- Next Actions: up to three suggested actions for the user to take next
22
+ Next Actions: If you have them, up to three suggested actions for the user to take after getting this answer.
23
23
  FINPUT
24
24
 
25
25
  # default prompt suffix
@@ -71,13 +71,15 @@ module Boxcars
71
71
  answer = engine_output.split(FINAL_ANSWER_ACTION).last.strip
72
72
  ['Final Answer', answer]
73
73
  else
74
+ # the thought should be the frist line here if it doesn't start with "Action:"
75
+ thought = engine_output.split(/\n+/).reject(&:empty?).first
76
+ Boxcars.debug("Though: #{thought}", :cyan)
74
77
  regex = /Action: (?<action>.*)\nAction Input: (?<action_input>.*)/
75
78
  match = regex.match(engine_output)
76
79
  raise ValueError, "Could not parse engine output: #{engine_output}" unless match
77
80
 
78
81
  action = match[:action].strip
79
- action_input = match[:action_input].strip
80
- # [action, action_input.strip(" ").strip('"')]
82
+ action_input = match[:action_input].strip.delete_prefix('"').delete_suffix('"')
81
83
  [action, action_input]
82
84
  end
83
85
  end
data/lib/boxcars/train.rb CHANGED
@@ -38,7 +38,7 @@ module Boxcars
38
38
  def construct_scratchpad(intermediate_steps)
39
39
  thoughts = ""
40
40
  intermediate_steps.each do |action, observation|
41
- thoughts += action.is_a?(String) ? action : action.log
41
+ thoughts += action.is_a?(String) ? action : " #{action.log}"
42
42
  thoughts += "\n#{observation_prefix}#{observation}\n#{engine_prefix}"
43
43
  end
44
44
  thoughts
@@ -196,7 +196,7 @@ module Boxcars
196
196
  observation = boxcar.run(output.boxcar_input)
197
197
  return_direct = boxcar.return_direct
198
198
  rescue StandardError => e
199
- error "Error in #{boxcar.name} boxcar#call: #{e}", :red
199
+ Boxcars.error "Error in #{boxcar.name} boxcar#call: #{e}", :red
200
200
  observation = "Error - #{e}, correct and try again."
201
201
  end
202
202
  else
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Boxcars
4
4
  # The current version of the gem.
5
- VERSION = "0.1.8"
5
+ VERSION = "0.2.0"
6
6
  end
data/lib/boxcars.rb CHANGED
@@ -30,7 +30,7 @@ module Boxcars
30
30
  def initialize
31
31
  @organization_id = nil
32
32
  @logger = Rails.logger if defined?(Rails)
33
- @log_prompts = false
33
+ @log_prompts = ENV.fetch("LOG_PROMPTS", false)
34
34
  end
35
35
 
36
36
  # @return [String] The OpenAI Access Token either from arg or env.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boxcars
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francis Sullivan
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-03-02 00:00:00.000000000 Z
12
+ date: 2023-03-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debug