boxcars 0.1.7 → 0.1.8

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: f8cfde09f23575d2b54249bd2b6d2c15697092b7c52db4d5f0546bb0113a3949
4
- data.tar.gz: d557f681bf8a26251608b17038650868563da9d54753789c568331328cfa456b
3
+ metadata.gz: 3de375ad403bb62fb6af1045aff6a6115cbb598c3747fe48f882fb40483289e0
4
+ data.tar.gz: 343a3077d72ce21a56d8045701a8a3bd681c5fe91fd8ffbca2cc14270b92f3bb
5
5
  SHA512:
6
- metadata.gz: db5af829a8a6e600cbb402e53aa7aaf1f9374725c5cf1d61ee908cb58ffda305b03ee00a4664e9f1134dc6887be9dab8c7877ad4c6b981e5a5665bfc1cfec2f3
7
- data.tar.gz: 17930e46fa46b4d1a268367aff6d9b5851fac890f00d5a87e722ed3833552bb851614a5ab606cb9a08afce611a5882c9838094e31c1d34b9d17c05923656fc38
6
+ metadata.gz: efc72210fb52599b7c6278502a5b4143d995e671c62c7f6c090cbddf2a8926b231b0d7ab0aa28fa1325324ded1ebac5cac4e10e608ae59077a431a20f9d62f23
7
+ data.tar.gz: eeb00a993d7bbf64ac5c7461a1e31f241407c58a19a919c0853ade7e4a3bf717ab4f69331c5bc5d8c0049a89c53353d311d41616352131379b7e87b8ec3e491d
data/.env_sample ADDED
@@ -0,0 +1,2 @@
1
+ openai_access_token: ''
2
+ serpapi_api_key: ''
data/CHANGELOG.md CHANGED
@@ -1,8 +1,20 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased](https://github.com/BoxcarsAI/boxcars/tree/HEAD)
3
+ ## [v0.1.7](https://github.com/BoxcarsAI/boxcars/tree/v0.1.7) (2023-02-27)
4
4
 
5
- [Full Changelog](https://github.com/BoxcarsAI/boxcars/compare/v0.1.5...HEAD)
5
+ [Full Changelog](https://github.com/BoxcarsAI/boxcars/compare/v0.1.6...v0.1.7)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - figure out logging [\#10](https://github.com/BoxcarsAI/boxcars/issues/10)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Fix typos in README concepts [\#26](https://github.com/BoxcarsAI/boxcars/pull/26) ([MasterOdin](https://github.com/MasterOdin))
14
+
15
+ ## [v0.1.6](https://github.com/BoxcarsAI/boxcars/tree/v0.1.6) (2023-02-24)
16
+
17
+ [Full Changelog](https://github.com/BoxcarsAI/boxcars/compare/v0.1.5...v0.1.6)
6
18
 
7
19
  **Implemented enhancements:**
8
20
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- boxcars (0.1.7)
4
+ boxcars (0.1.8)
5
5
  google_search_results (~> 2.2)
6
6
  ruby-openai (~> 3.0)
7
7
 
@@ -7,7 +7,7 @@ module Boxcars
7
7
  # the description of this engine boxcar
8
8
  ARDESC = "useful for when you need to query a database for an application named %<name>s."
9
9
  LOCKED_OUT_MODELS = %w[ActiveRecord::SchemaMigration ActiveRecord::InternalMetadata ApplicationRecord].freeze
10
- attr_accessor :connection, :input_key, :requested_models, :read_only, :approval_callback
10
+ attr_accessor :connection, :requested_models, :read_only, :approval_callback
11
11
  attr_reader :except_models
12
12
 
13
13
  # @param engine [Boxcars::Engine] The engine to user for this boxcar. Can be inherited from a train if nil.
@@ -15,43 +15,25 @@ module Boxcars
15
15
  # @param read_only [Boolean] Whether to use read only models. Defaults to true unless you pass an approval function.
16
16
  # @param approval_callback [Proc] A function to call to approve changes. Defaults to nil.
17
17
  # @param kwargs [Hash] Any other keyword arguments. These can include:
18
- # :name, :description, :prompt, :input_key, :output_key and :except_models
18
+ # :name, :description, :prompt, :except_models, :top_k, and :stop
19
19
  def initialize(engine: nil, models: nil, read_only: nil, approval_callback: nil, **kwargs)
20
20
  check_models(models)
21
21
  @except_models = LOCKED_OUT_MODELS + kwargs[:except_models].to_a
22
22
  @approval_callback = approval_callback
23
23
  @read_only = read_only.nil? ? !approval_callback : read_only
24
- @input_key = kwargs[:input_key] || :question
25
- @output_key = kwargs[:output_key] || :answer
26
24
  the_prompt = kwargs[prompt] || my_prompt
27
25
  name = kwargs[:name] || "Data"
26
+ kwargs[:stop] ||= ["Answer:"]
28
27
  super(name: name,
29
28
  description: kwargs[:description] || format(ARDESC, name: name),
30
29
  engine: engine,
31
30
  prompt: the_prompt,
32
- output_key: output_key)
31
+ **kwargs)
33
32
  end
34
33
 
35
- # the input keys for the prompt
36
- # @return [Array<Symbol>] The input keys for the prompt.
37
- def input_keys
38
- [input_key]
39
- end
40
-
41
- # the output keys for the prompt
42
- # @return [Array<Symbol>] The output keys for the prompt.
43
- def output_keys
44
- [output_key]
45
- end
46
-
47
- # call the boxcar
48
- # @param inputs [Hash] The inputs to the boxcar.
49
- # @return [Hash] The outputs from the boxcar.
50
- def call(inputs:)
51
- t = predict(question: inputs[input_key], top_k: 5, model_info: model_info, stop: ["Answer:"]).strip
52
- answer = get_answer(t)
53
- Boxcars.info answer, :magenta
54
- { output_key => answer }
34
+ # @return Hash The additional variables for this boxcar.
35
+ def prediction_additional
36
+ { model_info: model_info }.merge super
55
37
  end
56
38
 
57
39
  private
@@ -83,7 +65,7 @@ module Boxcars
83
65
 
84
66
  def model_info
85
67
  models = wanted_models
86
- models.pretty_inspect
68
+ models.inspect
87
69
  end
88
70
 
89
71
  # to be safe, we wrap the code in a transaction and rollback
@@ -167,13 +149,12 @@ module Boxcars
167
149
  output = 0 if output.is_a?(Array) && output.empty?
168
150
  output = output.first if output.is_a?(Array) && output.length == 1
169
151
  output = output[output.keys.first] if output.is_a?(Hash) && output.length == 1
170
- "Answer: #{output.inspect}"
152
+ "Answer: #{output.to_json}"
171
153
  rescue StandardError => e
172
154
  "Error: #{e.message}"
173
155
  end
174
156
 
175
157
  def get_answer(text)
176
- # debugger
177
158
  case text
178
159
  when /^ARCode:/
179
160
  get_active_record_answer(text)
@@ -209,7 +190,8 @@ module Boxcars
209
190
 
210
191
  # The prompt to use for the engine.
211
192
  def my_prompt
212
- @my_prompt ||= Prompt.new(input_variables: [:question, :top_k, :model_info], template: TEMPLATE)
193
+ @my_prompt ||= Prompt.new(input_variables: [:question], other_inputs: [:top_k], output_variables: [:answer],
194
+ template: TEMPLATE)
213
195
  end
214
196
  end
215
197
  end
@@ -6,42 +6,19 @@ module Boxcars
6
6
  class Calculator < EngineBoxcar
7
7
  # the description of this engine boxcar
8
8
  CALCDESC = "useful for when you need to answer questions about math"
9
- attr_accessor :input_key
10
9
 
11
10
  # @param engine [Boxcars::Engine] The engine to user for this boxcar. Can be inherited from a train if nil.
12
11
  # @param prompt [Boxcars::Prompt] The prompt to use for this boxcar. Defaults to built-in prompt.
13
- # @param input_key [Symbol] The key to use for the input. Defaults to :question.
14
- # @param output_key [Symbol] The key to use for the output. Defaults to :answer.
15
12
  # @param kwargs [Hash] Any other keyword arguments to pass to the parent class.
16
- def initialize(engine: nil, prompt: nil, input_key: :question, output_key: :answer, **kwargs)
17
- # def initialize(engine:, prompt: my_prompt, input_key: :question, output_key: :answer, **kwargs)
18
- @input_key = input_key
13
+ def initialize(engine: nil, prompt: nil, **kwargs)
14
+ # def initialize(engine:, prompt: my_prompt, output_key: :answer, **kwargs)
19
15
  the_prompt = prompt || my_prompt
16
+ kwargs[:stop] ||= ["```output"]
20
17
  super(name: kwargs[:name] || "Calculator",
21
18
  description: kwargs[:description] || CALCDESC,
22
19
  engine: engine,
23
20
  prompt: the_prompt,
24
- output_key: output_key)
25
- end
26
-
27
- # the prompt input keys
28
- def input_keys
29
- [input_key]
30
- end
31
-
32
- # the output keys
33
- def output_keys
34
- [output_key]
35
- end
36
-
37
- # call the calculator
38
- # @param inputs [Hash] The inputs to the boxcar.
39
- # @return [Hash] The outputs from the boxcar.
40
- def call(inputs:)
41
- t = predict(question: inputs[input_key], stop: ["```output"]).strip
42
- answer = get_answer(t)
43
- Boxcars.info answer, :magenta
44
- { output_key => answer }
21
+ **kwargs)
45
22
  end
46
23
 
47
24
  private
@@ -104,7 +81,7 @@ module Boxcars
104
81
 
105
82
  # The prompt to use for the engine.
106
83
  def my_prompt
107
- @my_prompt ||= Prompt.new(input_variables: [:question], template: TEMPLATE)
84
+ @my_prompt ||= Prompt.new(input_variables: [:question], output_variables: [:answer], template: TEMPLATE)
108
85
  end
109
86
  end
110
87
  end
@@ -4,17 +4,18 @@
4
4
  module Boxcars
5
5
  # For Boxcars that use an engine to do their work.
6
6
  class EngineBoxcar < Boxcar
7
- attr_accessor :prompt, :engine, :output_key
7
+ attr_accessor :prompt, :engine, :top_k, :stop
8
8
 
9
9
  # A Boxcar is a container for a single tool to run.
10
10
  # @param prompt [Boxcars::Prompt] The prompt to use for this boxcar with sane defaults.
11
11
  # @param name [String] The name of the boxcar. Defaults to classname.
12
12
  # @param description [String] A description of the boxcar.
13
13
  # @param engine [Boxcars::Engine] The engine to user for this boxcar. Can be inherited from a train if nil.
14
- def initialize(prompt:, engine: nil, output_key: "text", name: nil, description: nil)
14
+ def initialize(prompt:, engine: nil, name: nil, description: nil, **kwargs)
15
15
  @prompt = prompt
16
16
  @engine = engine || Boxcars.engine.new
17
- @output_key = output_key
17
+ @top_k = kwargs[:top_k] || 5
18
+ @stop = kwargs[:stop] || ["Answer:"]
18
19
  super(name: name, description: description)
19
20
  end
20
21
 
@@ -23,9 +24,14 @@ module Boxcars
23
24
  prompt.input_variables
24
25
  end
25
26
 
27
+ # the first input key for the prompt
28
+ def input_key
29
+ input_keys.first
30
+ end
31
+
26
32
  # output keys
27
33
  def output_keys
28
- [output_key]
34
+ prompt.output_variables
29
35
  end
30
36
 
31
37
  # generate a response from the engine
@@ -35,6 +41,7 @@ module Boxcars
35
41
  stop = input_list[0][:stop]
36
42
  prompts = []
37
43
  input_list.each do |inputs|
44
+ # prompt.missing_variables?(inputs)
38
45
  new_prompt = prompt.format(**inputs)
39
46
  Boxcars.debug("Prompt after formatting:\n#{new_prompt}", :cyan) if Boxcars.configuration.log_prompts
40
47
  prompts.push(new_prompt)
@@ -48,7 +55,7 @@ module Boxcars
48
55
  def apply(input_list:)
49
56
  response = generate(input_list: input_list)
50
57
  response.generations.to_h do |generation|
51
- [output_key, generation[0].text]
58
+ [output_keys.first, generation[0].text]
52
59
  end
53
60
  end
54
61
 
@@ -56,7 +63,7 @@ module Boxcars
56
63
  # @param kwargs [Hash] A hash of input values to use for the prompt.
57
64
  # @return [String] The output value.
58
65
  def predict(**kwargs)
59
- apply(input_list: [kwargs])[output_key]
66
+ apply(input_list: [kwargs])[output_keys.first]
60
67
  end
61
68
 
62
69
  # predict a response from the engine and parse it
@@ -77,7 +84,7 @@ module Boxcars
77
84
  def apply_and_parse(input_list:)
78
85
  result = apply(input_list: input_list)
79
86
  if prompt.output_parser
80
- result.map { |r| prompt.output_parser.parse(r[output_key]) }
87
+ result.map { |r| prompt.output_parser.parse(r[output_keys.first]) }
81
88
  else
82
89
  result
83
90
  end
@@ -90,5 +97,32 @@ module Boxcars
90
97
 
91
98
  raise Boxcars::ArgumentError, "run not supported when there is not exactly one output key. Got #{output_keys}."
92
99
  end
100
+
101
+ # call the boxcar
102
+ # @param inputs [Hash] The inputs to the boxcar.
103
+ # @return [Hash] The outputs from the boxcar.
104
+ def call(inputs:)
105
+ t = predict(**prediction_variables(inputs)).strip
106
+ answer = get_answer(t)
107
+ Boxcars.debug answer, :magenta
108
+ { output_keys.first => answer }
109
+ end
110
+
111
+ # @param inputs [Hash] The inputs to the boxcar.
112
+ # @return Hash The input variable for this boxcar.
113
+ def prediction_input(inputs)
114
+ { input_key => inputs[input_key] }
115
+ end
116
+
117
+ # @return Hash The additional variables for this boxcar.
118
+ def prediction_additional
119
+ { stop: stop, top_k: top_k }
120
+ end
121
+
122
+ # @param inputs [Hash] The inputs to the boxcar.
123
+ # @return Hash The variables for this boxcar.
124
+ def prediction_variables(inputs)
125
+ prediction_input(inputs).merge(prediction_additional)
126
+ end
93
127
  end
94
128
  end
@@ -6,46 +6,26 @@ module Boxcars
6
6
  class SQL < EngineBoxcar
7
7
  # the description of this engine boxcar
8
8
  SQLDESC = "useful for when you need to query a database for %<name>s."
9
- attr_accessor :connection, :input_key
9
+ attr_accessor :connection
10
10
 
11
11
  # @param connection [ActiveRecord::Connection] The SQL connection to use for this boxcar.
12
12
  # @param engine [Boxcars::Engine] The engine to user for this boxcar. Can be inherited from a train if nil.
13
- # @param input_key [Symbol] The key to use for the input. Defaults to :question.
14
- # @param output_key [Symbol] The key to use for the output. Defaults to :answer.
15
13
  # @param kwargs [Hash] Any other keyword arguments to pass to the parent class. This can include
16
- # :name, :description and :prompt
17
- def initialize(connection: nil, engine: nil, input_key: :question, output_key: :answer, **kwargs)
14
+ # :name, :description, :prompt and :top_k
15
+ def initialize(connection: nil, engine: nil, **kwargs)
18
16
  @connection = connection || ::ActiveRecord::Base.connection
19
- @input_key = input_key
20
17
  the_prompt = kwargs[prompt] || my_prompt
21
- name = kwargs[:name] || "data"
18
+ kwargs[:stop] ||= ["Answer:"]
19
+ name = kwargs[:name] || "database"
22
20
  super(name: name,
23
21
  description: kwargs[:description] || format(SQLDESC, name: name),
24
22
  engine: engine,
25
- prompt: the_prompt,
26
- output_key: output_key)
23
+ prompt: the_prompt)
27
24
  end
28
25
 
29
- # the input keys for the prompt
30
- # @return [Array<Symbol>] The input keys for the prompt.
31
- def input_keys
32
- [input_key]
33
- end
34
-
35
- # the output keys for the prompt
36
- # @return [Array<Symbol>] The output keys for the prompt.
37
- def output_keys
38
- [output_key]
39
- end
40
-
41
- # call the boxcar
42
- # @param inputs [Hash] The inputs to the boxcar.
43
- # @return [Hash] The outputs from the boxcar.
44
- def call(inputs:)
45
- t = predict(question: inputs[input_key], dialect: dialect, top_k: 5, table_info: schema, stop: ["Answer:"]).strip
46
- answer = get_answer(t)
47
- Boxcars.debug answer, :magenta
48
- { output_key => answer }
26
+ # @return Hash The additional variables for this boxcar.
27
+ def prediction_additional
28
+ { schema: schema, dialect: dialect }.merge super
49
29
  end
50
30
 
51
31
  private
@@ -66,7 +46,6 @@ module Boxcars
66
46
  end
67
47
 
68
48
  def dialect
69
- # connection.instance_variable_get "@config"[:adapter]
70
49
  connection.class.name.split("::").last.sub("Adapter", "")
71
50
  end
72
51
 
@@ -107,14 +86,18 @@ module Boxcars
107
86
  Answer: "Final answer here"
108
87
 
109
88
  Only use the following tables:
110
- %<table_info>s
89
+ %<schema>s
111
90
 
112
91
  Question: %<question>s
113
92
  IPT
114
93
 
115
94
  # The prompt to use for the engine.
116
95
  def my_prompt
117
- @my_prompt ||= Prompt.new(input_variables: [:question, :dialect, :top_k], template: TEMPLATE)
96
+ @my_prompt ||= Prompt.new(
97
+ input_variables: [:question],
98
+ other_inputs: [:top_k, :dialect, :table_info],
99
+ output_variables: [:answer],
100
+ template: TEMPLATE)
118
101
  end
119
102
  end
120
103
  end
@@ -77,7 +77,7 @@ module Boxcars
77
77
  begin
78
78
  output = call(inputs: inputs)
79
79
  rescue StandardError => e
80
- error "Error in #{name} boxcar#call: #{e}", :red
80
+ Boxcars.error "Error in #{name} boxcar#call: #{e}", :red
81
81
  raise e
82
82
  end
83
83
  validate_outputs(outputs: output.keys)
@@ -83,6 +83,25 @@ module Boxcars
83
83
  end
84
84
  end
85
85
 
86
+ # make sure we got a valid response
87
+ # @param response [Hash] The response to check.
88
+ # @param must_haves [Array<String>] The keys that must be in the response. Defaults to %w[choices].
89
+ # @raise [KeyError] if there is an issue with the access token.
90
+ # @raise [ValueError] if the response is not valid.
91
+ def check_response(response, must_haves: %w[choices])
92
+ if response['error']
93
+ code = response.dig('error', 'code')
94
+ msg = response.dig('error', 'message') || 'unknown error'
95
+ raise KeyError, "OPENAI_ACCESS_TOKEN not valid" if code == 'invalid_api_key'
96
+
97
+ raise ValueError, "OpenAI error: #{msg}"
98
+ end
99
+
100
+ must_haves.each do |key|
101
+ raise ValueError, "Expecting key #{key} in response" unless response.key?(key)
102
+ end
103
+ end
104
+
86
105
  # Call out to OpenAI's endpoint with k unique prompts.
87
106
  # @param prompts [Array<String>] The prompts to pass into the model.
88
107
  # @param stop [Array<String>] Optional list of stop words to use when generating.
@@ -98,6 +117,7 @@ module Boxcars
98
117
  sub_prompts = prompts.each_slice(batch_size).to_a
99
118
  sub_prompts.each do |sprompts|
100
119
  response = client(prompt: sprompts, **params)
120
+ check_response(response)
101
121
  choices.concat(response["choices"])
102
122
  keys_to_use = inkeys & response["usage"].keys
103
123
  keys_to_use.each { |key| token_usage[key] = token_usage[key].to_i + response["usage"][key] }
@@ -3,25 +3,44 @@
3
3
  module Boxcars
4
4
  # used by Boxcars that have engine's to create a prompt.
5
5
  class Prompt
6
- attr_reader :template, :input_variables, :output_variables
6
+ attr_reader :template, :input_variables, :other_inputs, :output_variables
7
7
 
8
8
  # @param template [String] The template to use for the prompt.
9
- # @param input_variables [Array<Symbol>] The input vars to use for the prompt.
10
- # @param output_variables [Array<Symbol>] The output vars to use for the prompt. Defaults to [:agent_scratchpad]
11
- def initialize(template:, input_variables:, output_variables: [:agent_scratchpad])
9
+ # @param input_variables [Array<Symbol>] The input vars to use for the prompt. Defaults to [:input]
10
+ # @param other_inputs [Array<Symbol>] The other input vars to use for the prompt. Defaults to []
11
+ # @param output_variables [Array<Symbol>] The output vars to use for the prompt. Defaults to [:output]
12
+ def initialize(template:, input_variables: nil, other_inputs: nil, output_variables: nil)
12
13
  @template = template
13
- @input_variables = input_variables
14
- @output_variables = output_variables
14
+ @input_variables = input_variables || [:input]
15
+ @other_inputs = other_inputs || []
16
+ @output_variables = output_variables || [:output]
15
17
  end
16
18
 
17
19
  # format the prompt with the input variables
20
+ # @param inputs [Hash] The inputs to use for the prompt.
21
+ # @return [String] The formatted prompt.
22
+ # @raise [Boxcars::KeyError] if the template has extra keys.
18
23
  def format(inputs)
19
24
  @template % inputs
25
+ rescue ::KeyError => e
26
+ first_line = e.message.to_s.split("\n").first
27
+ Boxcars.error "Missing prompt input key: #{first_line}"
28
+ raise KeyError, "Prompt format error: #{first_line}"
20
29
  end
21
30
 
22
31
  # check if the template is valid
23
32
  def template_is_valid?
24
- @template.include?("%<input>s") && @template.include?("%<agent_scratchpad>s")
33
+ all_vars = (input_variables + other_inputs + output_variables).sort
34
+ template_vars = @template.scan(/%<(\w+)>s/).flatten.map(&:to_sym).sort
35
+ all_vars == template_vars
36
+ end
37
+
38
+ # missing variables in the template
39
+ def missing_variables?(inputs)
40
+ input_vars = [input_variables, other_inputs].flatten.sort
41
+ return if inputs.keys.sort == input_vars
42
+
43
+ raise ArgumentError, "Missing expected input keys, got: #{inputs.keys}. Expected: #{input_vars}"
25
44
  end
26
45
 
27
46
  # create a prompt template from examples
@@ -29,17 +48,22 @@ module Boxcars
29
48
  # @param input_variables [Array<Symbol>] The input variables to use for the prompt.
30
49
  # @param example_separator [String] The separator to use between the examples. Defaults to "\n\n"
31
50
  # @param prefix [String] The prefix to use for the template. Defaults to ""
32
- def self.from_examples(examples:, suffix:, input_variables:, example_separator: "\n\n", prefix: "")
51
+ def self.from_examples(examples:, suffix:, input_variables:, example_separator: "\n\n", prefix: "", **kwargs)
33
52
  template = [prefix, examples, suffix].join(example_separator)
34
- Prompt.new(template: template, input_variables: input_variables)
53
+ other_inputs = kwargs[:other_inputs] || []
54
+ output_variables = kwargs[:output_variables] || [:output]
55
+ Prompt.new(template: template, input_variables: input_variables, other_inputs: other_inputs,
56
+ output_variables: output_variables)
35
57
  end
36
58
 
37
59
  # create a prompt template from a file
38
60
  # @param path [String] The path to the file to use for the template.
39
- # @param input_variables [Array<Symbol>] The input variables to use for the prompt.
40
- def self.from_file(path:, input_variables:)
61
+ # @param input_variables [Array<Symbol>] The input variables to use for the prompt. Defaults to [:input]
62
+ # @param output_variables [Array<Symbol>] The output variables to use for the prompt. Defaults to [:output]
63
+ def self.from_file(path:, input_variables: nil, other_inputs: nil, output_variables: nil)
41
64
  template = File.read(path)
42
- Prompt.new(template: template, input_variables: input_variables)
65
+ Prompt.new(template: template, input_variables: input_variables, other_inputs: other_inputs,
66
+ output_variables: output_variables)
43
67
  end
44
68
  end
45
69
  end
@@ -19,6 +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
23
  FINPUT
23
24
 
24
25
  # default prompt suffix
data/lib/boxcars/train.rb CHANGED
@@ -16,7 +16,7 @@ module Boxcars
16
16
  @name = name || self.class.name
17
17
  @return_values = [:output]
18
18
  @return_intermediate_steps = kwargs[:return_intermediate_steps] || false
19
- @max_iterations = kwargs[:max_iterations]
19
+ @max_iterations = kwargs[:max_iterations] || 25
20
20
  @early_stopping_method = kwargs[:early_stopping_method] || "force"
21
21
 
22
22
  super(prompt: prompt, engine: engine, name: kwargs[:name], description: kwargs[:description])
@@ -137,8 +137,6 @@ module Boxcars
137
137
  case prompt
138
138
  when Prompt
139
139
  prompt.template += "\n%<agent_scratchpad>s"
140
- # when FewShotPromptTemplate
141
- # prompt.suffix += "\n%<agent_scratchpad>s"
142
140
  else
143
141
  raise ValueError, "Got unexpected prompt type #{type(prompt)}"
144
142
  end
@@ -199,7 +197,7 @@ module Boxcars
199
197
  return_direct = boxcar.return_direct
200
198
  rescue StandardError => e
201
199
  error "Error in #{boxcar.name} boxcar#call: #{e}", :red
202
- raise e
200
+ observation = "Error - #{e}, correct and try again."
203
201
  end
204
202
  else
205
203
  observation = "#{output.boxcar} is not a valid boxcar, try another one."
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Boxcars
4
4
  # The current version of the gem.
5
- VERSION = "0.1.7"
5
+ VERSION = "0.1.8"
6
6
  end
data/lib/boxcars.rb CHANGED
@@ -19,6 +19,9 @@ module Boxcars
19
19
  # Error class for all Boxcars security errors.
20
20
  class SecurityError < Error; end
21
21
 
22
+ # Error class for all Boxcars key errors.
23
+ class KeyError < Error; end
24
+
22
25
  # Configuration contains gem settings
23
26
  class Configuration
24
27
  attr_writer :openai_access_token, :serpapi_api_key
@@ -50,18 +53,18 @@ module Boxcars
50
53
  end
51
54
 
52
55
  def key_lookup(key, kwargs)
53
- rv = if kwargs.key?(key) && !kwargs[key].nil?
54
- # override with kwargs if present
55
- kwargs[key]
56
- elsif (set_val = instance_variable_get("@#{key}"))
57
- # use saved value if present
58
- set_val
59
- else
60
- # otherwise, dig out of the environment
61
- new_key = ENV.fetch(key.to_s.upcase, nil)
62
- new_key
63
- end
64
- check_key(key, rv)
56
+ val = if kwargs.key?(key) && !kwargs[key].nil?
57
+ # override with kwargs if present
58
+ kwargs[key]
59
+ elsif (provided_val = instance_variable_get("@#{key}"))
60
+ # use saved value if present. Set using Boxcars::configuration.the_key = "abcde"
61
+ provided_val
62
+ else
63
+ # otherwise, dig out of the environment
64
+ env_val = ENV.fetch(key.to_s.upcase, nil)
65
+ env_val
66
+ end
67
+ check_key(key, val)
65
68
  end
66
69
  end
67
70
 
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.7
4
+ version: 0.1.8
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-02-27 00:00:00.000000000 Z
12
+ date: 2023-03-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debug
@@ -89,6 +89,7 @@ executables: []
89
89
  extensions: []
90
90
  extra_rdoc_files: []
91
91
  files:
92
+ - ".env_sample"
92
93
  - ".rspec"
93
94
  - ".rubocop.yml"
94
95
  - CHANGELOG.md