summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md66
-rwxr-xr-xbin/nb (renamed from bin/rnb)0
-rw-r--r--components/providers/openai.rb9
-rw-r--r--components/storage.rb5
-rw-r--r--controllers/instance.rb3
-rw-r--r--controllers/interfaces/cli.rb16
-rw-r--r--controllers/interfaces/eval.rb37
-rw-r--r--controllers/interfaces/repl.rb63
-rw-r--r--controllers/session.rb16
-rw-r--r--nano-bots.gemspec2
10 files changed, 140 insertions, 77 deletions
diff --git a/README.md b/README.md
index 985f05a..4a3e714 100644
--- a/README.md
+++ b/README.md
@@ -81,32 +81,32 @@ docker compose run nano-bots
Start playing:
```sh
-rnb cartridges/assistant.yml - repl
+nb cartridges/assistant.yml - repl
```
## Usage
### Command Line
-After installing the gem, the `rnb` binary command will be available for your project or system.
+After installing the gem, the `nb` binary command will be available for your project or system.
Examples of usage:
```bash
-rnb to-en-us-translator.yml - eval "Salut, comment ça va?"
+nb to-en-us-translator.yml - eval "Salut, comment ça va?"
# => Hello, how are you doing?
-rnb midjourney.yml - eval "happy and friendly cyberpunk robot"
-# => The robot exploring a bustling city, surrounded by neon lights
-# and high-rise buildings. The prompt should include colorful
-# lighting and a sense of excitement in the facial expression.
+nb midjourney.yml - eval "happy cyberpunk robot"
+# => A cheerful and fun-loving robot is dancing wildly amidst a
+# futuristic and lively cityscape. Holographic advertisements
+# and vibrant neon colors can be seen in the background.
-rnb lisp.yml - eval "(+ 1 2)"
+nb lisp.yml - eval "(+ 1 2)"
# => 3
cat article.txt |
- rnb to-en-us-translator.yml - eval |
- rnb summarizer.yml - eval
+ nb to-en-us-translator.yml - eval |
+ nb summarizer.yml - eval
# -> LLM stands for Large Language Model, which refers to an
# artificial intelligence algorithm capable of processing
# and understanding vast amounts of natural language data,
@@ -115,23 +115,34 @@ cat article.txt |
```
```bash
-rnb assistant.yml - repl
+nb assistant.yml - repl
```
-All of the commands above are stateless. If you want to preserve the history of your interactions, replace the `-` with a state key. You can use a simple key, such as your username, or a randomly generated one:
+```text
+🤖> Hi, how are you doing?
-```ruby
-require 'securerandom'
+As an AI language model, I do not experience emotions but I am functioning
+well. How can I assist you?
-SecureRandom.hex # => 6ea6c43c42a1c076b1e3c36fa349ac2c
+🤖> |
```
+All of the commands above are stateless. If you want to preserve the history of your interactions, replace the `-` with a state key:
+
```bash
-rnb assistant.yml your-user eval "Salut, comment ça va?"
-rnb assistant.yml your-user repl
+nb assistant.yml your-user eval "Salut, comment ça va?"
+nb assistant.yml your-user repl
+
+nb assistant.yml 6ea6c43c42a1c076b1e3c36fa349ac2c eval "Salut, comment ça va?"
+nb assistant.yml 6ea6c43c42a1c076b1e3c36fa349ac2c repl
+```
-rnb assistant.yml 6ea6c43c42a1c076b1e3c36fa349ac2c eval "Salut, comment ça va?"
-rnb assistant.yml 6ea6c43c42a1c076b1e3c36fa349ac2c repl
+You can use a simple key, such as your username, or a randomly generated one:
+
+```ruby
+require 'securerandom'
+
+SecureRandom.hex # => 6ea6c43c42a1c076b1e3c36fa349ac2c
```
### Library
@@ -139,13 +150,13 @@ rnb assistant.yml 6ea6c43c42a1c076b1e3c36fa349ac2c repl
To use it as a library:
```ruby
-require 'nano-bots/cli' # Equivalent to the `rnb` command.
+require 'nano-bots/cli' # Equivalent to the `nb` command.
```
```ruby
require 'nano-bots'
-NanoBot.cli # Equivalent to the `rnb` command.
+NanoBot.cli # Equivalent to the `nb` command.
NanoBot.repl(cartridge: 'cartridge.yml') # Starts a new REPL.
@@ -166,20 +177,15 @@ Here's what a Nano Bot Cartridge looks like:
```yaml
---
-name: Assistant
-version: 0.0.1
+meta:
+ name: Nano Bot Name
+ author: Your Name
+ version: 0.0.1
behaviors:
interaction:
directive: You are a helpful assistant.
-interfaces:
- repl:
- prompt:
- - text: '🤖'
- - text: '> '
- color: blue
-
provider:
name: openai
settings:
diff --git a/bin/rnb b/bin/nb
index b674232..b674232 100755
--- a/bin/rnb
+++ b/bin/nb
diff --git a/components/providers/openai.rb b/components/providers/openai.rb
index e163573..c0a6639 100644
--- a/components/providers/openai.rb
+++ b/components/providers/openai.rb
@@ -24,6 +24,13 @@ module NanoBot
)
end
+ def stream(input)
+ provider = @settings.key?(:stream) ? @settings[:stream] : true
+ interface = input[:interface].key?(:stream) ? input[:interface][:stream] : true
+
+ provider && interface
+ end
+
def evaluate(input, &block)
messages = input[:history].map do |event|
{ role: event[:who] == 'user' ? 'user' : 'assistant',
@@ -51,7 +58,7 @@ module NanoBot
payload.delete(:logit_bias) if payload.key?(:logit_bias) && payload[:logit_bias].nil?
- if @settings[:stream] && input[:interface][:stream]
+ if stream(input)
content = ''
payload[:stream] = proc do |chunk, _bytesize|
diff --git a/components/storage.rb b/components/storage.rb
index 5f51d06..3d3f58d 100644
--- a/components/storage.rb
+++ b/components/storage.rb
@@ -17,8 +17,9 @@ module NanoBot
path = "#{user_home!.sub(%r{/$}, '')}/.local/state/nano-bots" if path.nil?
- path = "#{path.sub(%r{/$}, '')}/nano-bots-rb/#{cartridge[:name].to_slug.normalize}"
- path = "#{path}/#{cartridge[:version].to_slug.normalize}/#{key.to_slug.normalize}"
+ 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}/state.json"
FileUtils.mkdir_p(File.dirname(path))
diff --git a/controllers/instance.rb b/controllers/instance.rb
index e8037e2..f3cbd74 100644
--- a/controllers/instance.rb
+++ b/controllers/instance.rb
@@ -6,6 +6,7 @@ require_relative '../logic/helpers/hash'
require_relative '../components/provider'
require_relative '../components/storage'
require_relative './interfaces/repl'
+require_relative './interfaces/eval'
require_relative './session'
module NanoBot
@@ -24,7 +25,7 @@ module NanoBot
end
def eval(input)
- @session.evaluate_and_print(input, mode: 'eval')
+ Interfaces::Eval.evaluate(input, @cartridge, @session)
end
def repl
diff --git a/controllers/interfaces/cli.rb b/controllers/interfaces/cli.rb
index 550361f..3574a80 100644
--- a/controllers/interfaces/cli.rb
+++ b/controllers/interfaces/cli.rb
@@ -13,14 +13,14 @@ module NanoBot
puts NanoBot::GEM[:version]
exit
when 'help', '', nil
- puts "Ruby Nano Bots #{NanoBot::GEM[:version]}"
- puts ' rnb cartridge.yml - eval "Hello"'
- puts ' rnb cartridge.yml - repl'
- puts ' rnb cartridge.yml - debug'
- puts ' rnb cartridge.yml STATE-KEY eval "Hello"'
- puts ' rnb cartridge.yml STATE-KEY repl'
- puts ' rnb cartridge.yml STATE-KEY debug'
- puts ' rnb version'
+ puts "Nano Bots #{NanoBot::GEM[:version]}"
+ 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 ' nb cartridge.yml STATE-KEY repl'
+ puts ' nb cartridge.yml STATE-KEY debug'
+ puts ' nb version'
exit
end
diff --git a/controllers/interfaces/eval.rb b/controllers/interfaces/eval.rb
new file mode 100644
index 0000000..6cb12b4
--- /dev/null
+++ b/controllers/interfaces/eval.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'pry'
+require 'rainbow'
+
+require_relative '../../logic/helpers/hash'
+
+module NanoBot
+ module Controllers
+ module Interfaces
+ module Eval
+ def self.evaluate(input, cartridge, session)
+ prefix = build_prefix(cartridge)
+ postfix = build_postfix(cartridge)
+
+ session.print(prefix) unless prefix.nil?
+
+ session.evaluate_and_print(input, mode: 'eval')
+
+ session.print(postfix) unless postfix.nil?
+ end
+
+ def self.build_prefix(cartridge)
+ eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
+ return nil if eval_interface.nil?
+ eval_interface[:prefix]
+ end
+
+ def self.build_postfix(cartridge)
+ eval_interface = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces eval])
+ return "\n" if eval_interface.nil? || !eval_interface.key?(:postfix) # default
+ eval_interface[:postfix]
+ end
+ end
+ end
+ end
+end
diff --git a/controllers/interfaces/repl.rb b/controllers/interfaces/repl.rb
index 7b53eb2..5477c33 100644
--- a/controllers/interfaces/repl.rb
+++ b/controllers/interfaces/repl.rb
@@ -10,20 +10,17 @@ module NanoBot
module Interfaces
module REPL
def self.start(cartridge, session)
- if Logic::Helpers::Hash.fetch(
- cartridge, %i[interfaces repl prefix]
- )
- session.print(Logic::Helpers::Hash.fetch(cartridge,
- %i[interfaces repl prefix]))
- end
-
- session.boot(mode: 'repl')
+ prefix = build_prefix(cartridge)
+ postfix = build_postfix(cartridge)
- session.print(Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl postfix]) || "\n")
-
- session.flush
+ if Logic::Helpers::Hash.fetch(cartridge, %i[behaviors boot instruction])
+ session.print(prefix) unless prefix.nil?
+ session.boot(mode: 'repl')
+ session.print(postfix) unless postfix.nil?
+ session.print("\n")
+ end
- prompt = build_prompt(cartridge[:interfaces][:repl][:prompt])
+ prompt = build_prompt(Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl prompt]))
Pry.config.prompt = Pry::Prompt.new(
'REPL',
@@ -32,31 +29,43 @@ module NanoBot
)
Pry.commands.block_command(/(.*)/, 'handler') do |line|
- if Logic::Helpers::Hash.fetch(
- cartridge, %i[interfaces repl prefix]
- )
- session.print(Logic::Helpers::Hash.fetch(
- cartridge, %i[interfaces repl prefix]
- ))
- end
-
+ session.print(postfix) unless postfix.nil?
session.evaluate_and_print(line, mode: 'repl')
- session.print(Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl postfix]) || "\n")
+ session.print(postfix) unless postfix.nil?
+ session.print("\n")
session.flush
end
Pry.start
end
+ def self.build_prefix(cartridge)
+ repl = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl])
+ return "\n" if repl.nil? || !repl.key?(:prefix) # default
+ repl[:prefix]
+ end
+
+ def self.build_postfix(cartridge)
+ repl = Logic::Helpers::Hash.fetch(cartridge, %i[interfaces repl])
+ return "\n" if repl.nil? || !repl.key?(:postfix) # default
+ repl[:postfix]
+ end
+
def self.build_prompt(prompt)
result = ''
- prompt.each do |partial|
- result += if partial[:color]
- Rainbow(partial[:text]).send(partial[:color])
- else
- partial[:text]
- end
+ if prompt.is_a?(Array)
+ prompt.each do |partial|
+ result += if partial[:color]
+ Rainbow(partial[:text]).send(partial[:color])
+ else
+ partial[:text]
+ end
+ end
+ elsif prompt.is_a?(String)
+ result = prompt
+ else
+ result = '🤖' + Rainbow('> ').blue
end
result
diff --git a/controllers/session.rb b/controllers/session.rb
index 9277a84..ff3b8ad 100644
--- a/controllers/session.rb
+++ b/controllers/session.rb
@@ -67,13 +67,18 @@ module NanoBot
process(input, mode:)
end
- def process(input, mode:)
- streaming = @provider.settings[:stream] && Logic::Helpers::Hash.fetch(
- @cartridge, [:interfaces, mode.to_sym, :stream]
- )
+ def stream(interface)
+ provider = @provider.settings.key?(:stream) ? @provider.settings[:stream] : true
+ interface = interface.key?(:stream) ? interface[:stream] : true
+
+ provider && interface
+ end
+ def process(input, mode:)
interface = Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym]) || {}
+ streaming = stream(interface)
+
input[:interface] = interface
updated_at = Time.now
@@ -84,9 +89,6 @@ module NanoBot
if finished
@state[:history] << output
self.print(output[:message]) unless streaming
- unless Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym, :postfix]).nil?
- self.print(Logic::Helpers::Hash.fetch(@cartridge, [:interfaces, mode.to_sym, :postfix]))
- end
ready = true
flush
elsif streaming
diff --git a/nano-bots.gemspec b/nano-bots.gemspec
index 88a1270..0a3d9a6 100644
--- a/nano-bots.gemspec
+++ b/nano-bots.gemspec
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ['ports/dsl']
- spec.executables = ['rnb']
+ spec.executables = ['nb']
spec.add_dependency 'babosa', '~> 2.0'
spec.add_dependency 'dotenv', '~> 2.8', '>= 2.8.1'