diff options
-rw-r--r-- | README.md | 47 | ||||
-rw-r--r-- | components/storage.rb | 2 | ||||
-rw-r--r-- | controllers/instance.rb | 49 | ||||
-rw-r--r-- | controllers/interfaces/cli.rb | 34 | ||||
-rw-r--r-- | controllers/session.rb | 17 | ||||
-rw-r--r-- | docker-compose.example.yml | 1 | ||||
-rw-r--r-- | ports/dsl/nano-bots.rb | 8 | ||||
-rw-r--r-- | static/cartridges/default.yml | 14 |
8 files changed, 139 insertions, 33 deletions
@@ -13,6 +13,8 @@ https://user-images.githubusercontent.com/113217272/237840989-1e29a5cc-6644-48d0 - [Command Line](#command-line) - [Library](#library) - [Cartridges](#cartridges) +- [Providers](#providers) +- [Debugging](#debugging) - [Development](#development) - [Publish to RubyGems](#publish-to-rubygems) @@ -41,11 +43,20 @@ export OPENAI_API_ADDRESS=https://api.openai.com export OPENAI_API_ACCESS_TOKEN=your-token export OPENAI_API_USER_IDENTIFIER=your-user -export NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots -export NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges +# export NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots +# export NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges ``` -Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded. +Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded: + +```sh +OPENAI_API_ADDRESS=https://api.openai.com +OPENAI_API_ACCESS_TOKEN=your-token +OPENAI_API_USER_IDENTIFIER=your-user + +# NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots +# NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges +``` ## Docker @@ -72,6 +83,7 @@ services: OPENAI_API_USER_IDENTIFIER: your-user volumes: - ./your-cartridges:/cartridges + # - ./your-data:/data ``` Enter the container: @@ -81,6 +93,10 @@ docker compose run nano-bots Start playing: ```sh +nb - - eval "hello" +nb - - repl + +nb cartridges/assistant.yml - eval "hello" nb cartridges/assistant.yml - repl ``` @@ -93,6 +109,9 @@ After installing the gem, the `nb` binary command will be available for your pro Examples of usage: ```bash +nb - - eval "hello" +# => Hello! How may I assist you today? + nb to-en-us-translator.yml - eval "Salut, comment ça va?" # => Hello, how are you doing? @@ -115,6 +134,8 @@ cat article.txt | ``` ```bash +nb - - repl + nb assistant.yml - repl ``` @@ -145,6 +166,16 @@ require 'securerandom' SecureRandom.hex # => 6ea6c43c42a1c076b1e3c36fa349ac2c ``` +### Debugging + +```sh +nb - - cartridge +nb cartridge.yml - cartridge + +nb - STATE-KEY state +nb cartridge.yml STATE-KEY state +``` + ### Library To use it as a library: @@ -198,6 +229,16 @@ provider: Check the Nano Bots specification to learn more about [how to build cartridges](https://icebaker.github.io/nano-bots/#/README?id=cartridges). +## Providers + +Currently supported providers: + +- [ ] [Vicuna](https://github.com/lm-sys/FastChat) +- [x] [Open AI](https://platform.openai.com/docs/api-reference) +- [ ] [Google PaLM](https://developers.generativeai.google/) +- [ ] [Alpaca](https://github.com/tatsu-lab/stanford_alpaca) +- [ ] [LLaMA](https://github.com/facebookresearch/llama) + ## Development ```bash diff --git a/components/storage.rb b/components/storage.rb index 3d3f58d..d46455f 100644 --- a/components/storage.rb +++ b/components/storage.rb @@ -19,7 +19,7 @@ module NanoBot path = "#{path.sub(%r{/$}, '')}/ruby-nano-bots/#{cartridge[:meta][:author].to_slug.normalize}" path = "#{path}/#{cartridge[:meta][:name].to_slug.normalize}" - path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}/#{key.to_slug.normalize}" + path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}/#{key}" path = "#{path}/state.json" FileUtils.mkdir_p(File.dirname(path)) diff --git a/controllers/instance.rb b/controllers/instance.rb index f3cbd74..b22a785 100644 --- a/controllers/instance.rb +++ b/controllers/instance.rb @@ -12,35 +12,64 @@ require_relative './session' module NanoBot module Controllers class Instance - def initialize(cartridge_path:, state: nil) + def initialize(cartridge_path:, stream:, state: nil) + @stream = stream + load_cartridge!(cartridge_path) provider = Components::Provider.new(@cartridge[:provider]) - @session = Session.new(provider:, cartridge: @cartridge, state:) + @session = Session.new(provider:, cartridge: @cartridge, state:, stream: @stream) + end + + def cartridge + puts YAML.dump(@safe_cartridge) end - def debug - @session.debug + def state + @session.state end def eval(input) Interfaces::Eval.evaluate(input, @cartridge, @session) + + return unless @stream.is_a?(StringIO) + + @stream.flush + result = @stream.string.clone + @stream.truncate(0) + @stream.rewind + result end def repl + if @stream.is_a?(StringIO) + @stream.flush + @stream = $stdout + @session.stream = @stream + end Interfaces::REPL.start(@cartridge, @session) end private def load_cartridge!(path) - @cartridge = Logic::Helpers::Hash.symbolize_keys( - YAML.safe_load( - File.read(Components::Storage.cartridge_path(path)), - permitted_classes: [Symbol] - ) - ) + elected_path = if path.strip == '-' + File.expand_path('../static/cartridges/default.yml', __dir__) + else + Components::Storage.cartridge_path(path) + end + + if elected_path.nil? + @stream.write("Cartridge file not found: \"#{path}\"\n") + raise StandardError, "Cartridge file not found: \"#{path}\"" + end + + @cartridge = YAML.safe_load(File.read(elected_path), permitted_classes: [Symbol]) + + @safe_cartridge = Marshal.load(Marshal.dump(@cartridge)) + + @cartridge = Logic::Helpers::Hash.symbolize_keys(@cartridge) inject_environment_variables!(@cartridge) end diff --git a/controllers/interfaces/cli.rb b/controllers/interfaces/cli.rb index 3574a80..2a93044 100644 --- a/controllers/interfaces/cli.rb +++ b/controllers/interfaces/cli.rb @@ -13,20 +13,38 @@ module NanoBot puts NanoBot::GEM[:version] exit when 'help', '', nil + puts '' puts "Nano Bots #{NanoBot::GEM[:version]}" - puts ' nb cartridge.yml - eval "Hello"' + puts '' + puts ' nb - - eval "hello"' + puts ' nb - - repl' + puts '' + puts ' nb cartridge.yml - eval "hello"' puts ' nb cartridge.yml - repl' - puts ' nb cartridge.yml - debug' - puts ' nb cartridge.yml STATE-KEY eval "Hello"' + puts '' + puts ' nb - STATE-KEY eval "hello"' + puts ' nb - STATE-KEY repl' + puts '' + puts ' nb cartridge.yml STATE-KEY eval "hello"' puts ' nb cartridge.yml STATE-KEY repl' - puts ' nb cartridge.yml STATE-KEY debug' + puts '' + puts ' nb - - cartridge' + puts ' nb cartridge.yml - cartridge' + puts '' + puts ' nb - STATE-KEY state' + puts ' nb cartridge.yml STATE-KEY state' + puts '' puts ' nb version' + puts ' nb help' + puts '' exit end params = { cartridge_path: ARGV[0], state: ARGV[1], command: ARGV[2] } - bot = Instance.new(cartridge_path: params[:cartridge_path], state: params[:state]) + bot = Instance.new( + cartridge_path: params[:cartridge_path], state: params[:state], stream: $stdout + ) case params[:command] when 'eval' @@ -35,8 +53,10 @@ module NanoBot bot.eval(params[:input]) when 'repl' bot.repl - when 'debug' - bot.debug + when 'state' + bot.state + when 'cartridge' + bot.cartridge else raise "TODO: [#{params[:command]}]" end diff --git a/controllers/session.rb b/controllers/session.rb index ff3b8ad..afaca18 100644 --- a/controllers/session.rb +++ b/controllers/session.rb @@ -12,12 +12,13 @@ module NanoBot STREAM_TIMEOUT_IN_SECONDS = 5 class Session - def initialize(provider:, cartridge:, state: nil) + attr_accessor :stream + + def initialize(provider:, cartridge:, state: nil, stream: $stdout) + @stream = stream @provider = provider @cartridge = cartridge - @output = $stdout - @stateless = state.nil? || state.strip == '-' || state.strip.empty? if @stateless @@ -30,7 +31,7 @@ module NanoBot end end - def debug + def state pp({ state: { path: @state_path, @@ -67,7 +68,7 @@ module NanoBot process(input, mode:) end - def stream(interface) + def streaming(interface) provider = @provider.settings.key?(:stream) ? @provider.settings[:stream] : true interface = interface.key?(:stream) ? interface[:stream] : true @@ -77,7 +78,7 @@ module NanoBot def process(input, mode:) interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {} - streaming = stream(interface) + streaming = streaming(interface) input[:interface] = interface @@ -105,11 +106,11 @@ module NanoBot end def flush - @output.flush + @stream.flush end def print(content) - @output.write(content) + @stream.write(content) end end end diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 1ec49c1..f3af38f 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -10,3 +10,4 @@ services: OPENAI_API_USER_IDENTIFIER: your-user volumes: - ./your-cartridges:/cartridges + # - ./your-data:/data diff --git a/ports/dsl/nano-bots.rb b/ports/dsl/nano-bots.rb index bce169c..40bed1d 100644 --- a/ports/dsl/nano-bots.rb +++ b/ports/dsl/nano-bots.rb @@ -7,16 +7,16 @@ require_relative '../../controllers/instance' require_relative '../../controllers/interfaces/cli' module NanoBot - def self.new(cartridge:, state: '-') - Controllers::Instance.new(cartridge_path: cartridge, state:) + def self.new(cartridge: '-', state: '-') + Controllers::Instance.new(cartridge_path: cartridge, state:, stream: StringIO.new) end def self.cli Controllers::Interfaces::CLI.handle! end - def self.repl(cartridge:, state: '-') - Controllers::Instance.new(cartridge_path: cartridge, state:).repl + def self.repl(cartridge: '-', state: '-') + Controllers::Instance.new(cartridge_path: cartridge, state:, stream: $stdout).repl end def self.version diff --git a/static/cartridges/default.yml b/static/cartridges/default.yml new file mode 100644 index 0000000..b5eed62 --- /dev/null +++ b/static/cartridges/default.yml @@ -0,0 +1,14 @@ +--- +meta: + name: Unknown + author: Nobody + version: 0.0.0 + +provider: + name: openai + settings: + model: gpt-3.5-turbo + credentials: + address: ENV/OPENAI_API_ADDRESS + access-token: ENV/OPENAI_API_ACCESS_TOKEN + user-identifier: ENV/OPENAI_API_USER_IDENTIFIER |