Module: Boxcars

Defined in:
lib/boxcars.rb,
lib/boxcars/train.rb,
lib/boxcars/boxcar.rb,
lib/boxcars/engine.rb,
lib/boxcars/prompt.rb,
lib/boxcars/result.rb,
lib/boxcars/x_node.rb,
lib/boxcars/version.rb,
lib/boxcars/ruby_repl.rb,
lib/boxcars/generation.rb,
lib/boxcars/engine/groq.rb,
lib/boxcars/observation.rb,
lib/boxcars/conversation.rb,
lib/boxcars/vector_store.rb,
lib/boxcars/engine/cohere.rb,
lib/boxcars/engine/ollama.rb,
lib/boxcars/engine/openai.rb,
lib/boxcars/vector_search.rb,
lib/boxcars/boxcar/swagger.rb,
lib/boxcars/boxcar/sql_base.rb,
lib/boxcars/boxcar/url_text.rb,
lib/boxcars/train/xml_train.rb,
lib/boxcars/train/zero_shot.rb,
lib/boxcars/engine/anthropic.rb,
lib/boxcars/boxcar/calculator.rb,
lib/boxcars/boxcar/sql_sequel.rb,
lib/boxcars/engine/gpt4all_eng.rb,
lib/boxcars/train/train_action.rb,
lib/boxcars/train/train_finish.rb,
lib/boxcars/conversation_prompt.rb,
lib/boxcars/engine/perplexityai.rb,
lib/boxcars/train/xml_zero_shot.rb,
lib/boxcars/boxcar/active_record.rb,
lib/boxcars/boxcar/engine_boxcar.rb,
lib/boxcars/boxcar/google_search.rb,
lib/boxcars/boxcar/vector_answer.rb,
lib/boxcars/engine/engine_result.rb,
lib/boxcars/vector_store/document.rb,
lib/boxcars/boxcar/ruby_calculator.rb,
lib/boxcars/boxcar/wikipedia_search.rb,
lib/boxcars/vector_store/split_text.rb,
lib/boxcars/boxcar/sql_active_record.rb,
lib/boxcars/boxcar/xml_engine_boxcar.rb,
lib/boxcars/boxcar/json_engine_boxcar.rb,
lib/boxcars/vector_store/hnswlib/search.rb,
lib/boxcars/vector_store/pgvector/search.rb,
lib/boxcars/vector_store/in_memory/search.rb,
lib/boxcars/vector_store/embed_via_open_ai.rb,
lib/boxcars/vector_store/embed_via_tensorflow.rb,
lib/boxcars/vector_store/hnswlib/load_from_disk.rb,
lib/boxcars/vector_store/hnswlib/save_to_hnswlib.rb,
lib/boxcars/vector_store/hnswlib/build_from_files.rb,
lib/boxcars/vector_store/pgvector/build_from_array.rb,
lib/boxcars/vector_store/pgvector/build_from_files.rb,
lib/boxcars/vector_store/pgvector/save_to_database.rb,
lib/boxcars/vector_store/in_memory/build_from_array.rb,
lib/boxcars/vector_store/in_memory/build_from_files.rb

Overview

Boxcars is a framework for running a series of tools to get an answer to a question.

Defined Under Namespace

Modules: VectorStore Classes: ActiveRecord, Anthropic, ArgumentError, Boxcar, Calculator, Cohere, Configuration, ConfigurationError, Conversation, ConversationPrompt, Engine, EngineBoxcar, EngineResult, Error, Generation, GoogleSearch, Gpt4allEng, Groq, JSONEngineBoxcar, KeyError, Observation, Ollama, Openai, Perplexityai, Prompt, Result, RubyCalculator, RubyREPL, SQLActiveRecord, SQLBase, SQLSequel, SecurityError, Swagger, Train, TrainAction, TrainFinish, URLText, ValueError, VectorAnswer, VectorSearch, WikipediaSearch, XMLEngineBoxcar, XMLTrain, XMLZeroShot, XNode, XmlError, ZeroShot

Constant Summary collapse

VERSION =

The current version of the gem.

"0.6.5"

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.configurationObject



95
96
97
# File 'lib/boxcars.rb', line 95

def self.configuration
  @configuration ||= Boxcars::Configuration.new
end

Class Method Details

.ask_userObject

return a proc that will ask the user for input



115
116
117
118
119
120
121
# File 'lib/boxcars.rb', line 115

def self.ask_user
  proc do |changes, _code|
    puts "This request will make #{changes} changes. Are you sure you want to run it? (y/[n])"
    answer = gets.chomp
    answer.downcase == 'y'
  end
end

.colorize(str, color, **options) ⇒ Object

simple colorization



187
188
189
190
191
192
193
194
195
196
# File 'lib/boxcars.rb', line 187

def self.colorize(str, color, **options)
  background = options[:background] || options[:bg] || false
  style = options[:style]
  offsets = %i[gray red green yellow blue magenta cyan white]
  styles = %i[normal bold dark italic underline xx xx underline xx strikethrough]
  start = background ? 40 : 30
  color_code = start + (offsets.index(color) || 8)
  style_code = styles.index(style) || 0
  "\e[#{style_code};#{color_code}m#{str}\e[0m"
end

.configure {|configuration| ... } ⇒ Object

Configure the gem.

Yields:



100
101
102
# File 'lib/boxcars.rb', line 100

def self.configure
  yield(configuration)
end

.debug(msg, color = nil, **options) ⇒ Object

Logging system debug log



143
144
145
146
147
148
149
150
151
# File 'lib/boxcars.rb', line 143

def self.debug(msg, color = nil, **options)
  msg = colorize(msg.to_s, color, **options) if color
  log << msg
  if logger
    logger.debug(msg)
  else
    puts msg
  end
end

.engineObject

Return the default Engine class.



110
111
112
# File 'lib/boxcars.rb', line 110

def self.engine
  configuration.default_engine || Boxcars::Openai
end

.error(msg, color = nil, **options) ⇒ Object

error log



176
177
178
179
180
181
182
183
184
# File 'lib/boxcars.rb', line 176

def self.error(msg, color = nil, **options)
  msg = colorize(msg.to_s, color, **options) if color
  log << msg
  if logger
    logger.error(msg)
  else
    puts msg
  end
end

.info(msg, color = nil, **options) ⇒ Object

info log



154
155
156
157
158
159
160
161
162
# File 'lib/boxcars.rb', line 154

def self.info(msg, color = nil, **options)
  msg = colorize(msg.to_s, color, **options) if color
  log << msg
  if logger
    logger.info(msg)
  else
    puts msg
  end
end

.logObject

Keep a running log of log messages



129
130
131
132
# File 'lib/boxcars.rb', line 129

def self.log
  @log ||= []
  @log
end

.loggerObject

Return a logger, possibly if set.



124
125
126
# File 'lib/boxcars.rb', line 124

def self.logger
  Boxcars.configuration.logger
end

.take_logObject

Resets the log and return the old log



135
136
137
138
139
# File 'lib/boxcars.rb', line 135

def self.take_log
  logs = @log
  @log = []
  logs
end

.trainObject

Return the default Train class.



105
106
107
# File 'lib/boxcars.rb', line 105

def self.train
  configuration.default_train || Boxcars::ZeroShot
end

.warn(msg, color = nil, **options) ⇒ Object

warn log



165
166
167
168
169
170
171
172
173
# File 'lib/boxcars.rb', line 165

def self.warn(msg, color = nil, **options)
  msg = colorize(msg.to_s, color, **options) if color
  log << msg
  if logger
    logger.warn(msg)
  else
    puts msg
  end
end

Instance Method Details

#engine_typeObject

the engine type



121
122
123
# File 'lib/boxcars/engine/openai.rb', line 121

def engine_type
  "openai"
end

#generate(prompts:, stop: nil) ⇒ EngineResult

Call out to endpoint with k unique prompts.

Parameters:

  • prompts (Array<String>)

    The prompts to pass into the model.

  • inputs (Array<String>)

    The inputs to subsitite into the prompt.

  • stop (Array<String>) (defaults to: nil)

    Optional list of stop words to use when generating.

Returns:



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/boxcars/engine/perplexityai.rb', line 147

def generate(prompts:, stop: nil)
  params = {}
  params[:stop] = stop if stop
  choices = []
  token_usage = {}
  # Get the token usage from the response.
  # Includes prompt, completion, and total tokens used.
  inkeys = %w[completion_tokens prompt_tokens total_tokens].freeze
  prompts.each_slice(batch_size) do |sub_prompts|
    sub_prompts.each do |sprompts, inputs|
      response = client(prompt: sprompts, inputs: inputs, **params)
      check_response(response)
      choices.concat(response["choices"])
      usage_keys = inkeys & response["usage"].keys
      usage_keys.each { |key| token_usage[key] = token_usage[key].to_i + response["usage"][key] }
    end
  end

  n = params.fetch(:n, 1)
  generations = []
  prompts.each_with_index do |_prompt, i|
    sub_choices = choices[i * n, (i + 1) * n]
    generations.push(generation_info(sub_choices))
  end
  EngineResult.new(generations: generations, engine_output: { token_usage: token_usage })
end

#generation_info(sub_choices) ⇒ Array<Generation>

Get generation informaton

Parameters:

  • sub_choices (Array<Hash>)

    The choices to get generation info for.

Returns:

  • (Array<Generation>)

    The generation information.



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/boxcars/engine/perplexityai.rb', line 130

def generation_info(sub_choices)
  sub_choices.map do |choice|
    Generation.new(
      text: choice.dig("message", "content") || choice["text"],
      generation_info: {
        finish_reason: choice.fetch("finish_reason", nil),
        logprobs: choice.fetch("logprobs", nil)
      }
    )
  end
end

#get_num_tokens(text:) ⇒ Object

calculate the number of tokens used



116
117
118
# File 'lib/boxcars/engine/perplexityai.rb', line 116

def get_num_tokens(text:)
  text.split.length # TODO: hook up to token counting gem
end

#max_tokens_for_prompt(_prompt_text) ⇒ Integer

Calculate the maximum number of tokens possible to generate for a prompt.

Parameters:

  • prompt_text (String)

    The prompt text to use.

Returns:

  • (Integer)

    the number of tokens possible to generate.



143
144
145
146
147
148
149
# File 'lib/boxcars/engine/openai.rb', line 143

def max_tokens_for_prompt(prompt_text)
  num_tokens = get_num_tokens(prompt_text)

  # get max context size for model by name
  max_size = modelname_to_contextsize(model_name)
  max_size - num_tokens
end

#modelname_to_contextsize(modelname) ⇒ Object

lookup the context size for a model by name

Parameters:

  • modelname (String)

    The name of the model to lookup.



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/boxcars/engine/openai.rb', line 127

def modelname_to_contextsize(modelname)
  model_lookup = {
    'text-davinci-003': 4097,
    'text-curie-001': 2048,
    'text-babbage-001': 2048,
    'text-ada-001': 2048,
    'code-davinci-002': 8000,
    'code-cushman-001': 2048,
    'gpt-3.5-turbo-1': 4096
  }.freeze
  model_lookup[modelname] || 4097
end