nano-bots 0.0.10 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +58 -38
- data/components/provider.rb +3 -3
- data/components/providers/base.rb +4 -0
- data/components/providers/openai.rb +33 -15
- data/components/storage.rb +27 -17
- data/controllers/security.rb +4 -0
- data/docker-compose.example.yml +6 -6
- data/static/cartridges/baseline.yml +9 -6
- data/static/cartridges/default.yml +0 -1
- data/static/gem.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4632306b0fe1fc9af4ee96c7624f163d80c70eb259c80f3efad158e95e76414a
|
4
|
+
data.tar.gz: a2156c47648e3b8b118a4698d23031ca4bd4bf139db6f5f19fa5561f1591cf7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8271268413e87793b147385c999edddbb59dc70203dfca243adb7836ee680dc430a57dc625d038394b6b86e3bb0a9a4e45f12291f9e1ef9574da8ee69ed93e5
|
7
|
+
data.tar.gz: 1d6d1118162ed3dbc3438205aa7b4e858499d154e7cc6bdba963a53ddeeff7c071398e9eebc1f3d273c7aa128c39fbcb452a8f6f9bfff8d41b2dac81fb04d9ce
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,13 +28,13 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
|
|
28
28
|
For a system usage:
|
29
29
|
|
30
30
|
```sh
|
31
|
-
gem install nano-bots -v 0.0
|
31
|
+
gem install nano-bots -v 0.1.0
|
32
32
|
```
|
33
33
|
|
34
34
|
To use it in a project, add it to your `Gemfile`:
|
35
35
|
|
36
36
|
```ruby
|
37
|
-
gem 'nano-bots', '~> 0.0
|
37
|
+
gem 'nano-bots', '~> 0.1.0'
|
38
38
|
```
|
39
39
|
|
40
40
|
```sh
|
@@ -44,10 +44,11 @@ bundle install
|
|
44
44
|
For credentials and configurations, relevant environment variables can be set in your `.bashrc`, `.zshrc`, or equivalent files, as well as in your Docker Container or System Environment. Example:
|
45
45
|
|
46
46
|
```sh
|
47
|
-
export NANO_BOTS_ENCRYPTION_PASSWORD="UNSAFE"
|
48
47
|
export OPENAI_API_ADDRESS=https://api.openai.com
|
49
|
-
export
|
50
|
-
|
48
|
+
export OPENAI_API_KEY=your-access-token
|
49
|
+
|
50
|
+
export NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE
|
51
|
+
export NANO_BOTS_END_USER=your-user
|
51
52
|
|
52
53
|
# export NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots
|
53
54
|
# export NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges
|
@@ -56,10 +57,11 @@ export OPENAI_API_USER_IDENTIFIER=your-user
|
|
56
57
|
Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded:
|
57
58
|
|
58
59
|
```sh
|
59
|
-
NANO_BOTS_ENCRYPTION_PASSWORD="UNSAFE"
|
60
60
|
OPENAI_API_ADDRESS=https://api.openai.com
|
61
|
-
|
62
|
-
|
61
|
+
OPENAI_API_KEY=your-access-token
|
62
|
+
|
63
|
+
NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE
|
64
|
+
NANO_BOTS_END_USER=your-user
|
63
65
|
|
64
66
|
# NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots
|
65
67
|
# NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges
|
@@ -83,15 +85,15 @@ version: '3.7'
|
|
83
85
|
services:
|
84
86
|
nano-bots:
|
85
87
|
image: ruby:3.2.2-slim-bullseye
|
86
|
-
command: sh -c "gem install nano-bots -v 0.0
|
88
|
+
command: sh -c "gem install nano-bots -v 0.1.0 && bash"
|
87
89
|
environment:
|
88
|
-
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
89
90
|
OPENAI_API_ADDRESS: https://api.openai.com
|
90
|
-
|
91
|
-
|
91
|
+
OPENAI_API_KEY: your-access-token
|
92
|
+
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
93
|
+
NANO_BOTS_END_USER: your-user
|
92
94
|
volumes:
|
93
|
-
- ./your-cartridges
|
94
|
-
|
95
|
+
- ./your-cartridges:/.local/share/nano-bots/cartridges
|
96
|
+
- ./your-state:/.local/state/nano-bots
|
95
97
|
```
|
96
98
|
|
97
99
|
Enter the container:
|
@@ -104,8 +106,8 @@ Start playing:
|
|
104
106
|
nb - - eval "hello"
|
105
107
|
nb - - repl
|
106
108
|
|
107
|
-
nb
|
108
|
-
nb
|
109
|
+
nb assistant.yml - eval "hello"
|
110
|
+
nb assistant.yml - repl
|
109
111
|
```
|
110
112
|
|
111
113
|
## Usage
|
@@ -256,13 +258,13 @@ behaviors:
|
|
256
258
|
directive: You are a helpful assistant.
|
257
259
|
|
258
260
|
provider:
|
259
|
-
|
261
|
+
id: openai
|
262
|
+
credentials:
|
263
|
+
address: ENV/OPENAI_API_ADDRESS
|
264
|
+
access-token: ENV/OPENAI_API_KEY
|
260
265
|
settings:
|
266
|
+
user: ENV/NANO_BOTS_END_USER
|
261
267
|
model: gpt-3.5-turbo
|
262
|
-
credentials:
|
263
|
-
address: ENV/OPENAI_API_ADDRESS
|
264
|
-
access-token: ENV/OPENAI_API_ACCESS_TOKEN
|
265
|
-
user-identifier: ENV/OPENAI_API_USER_IDENTIFIER
|
266
268
|
```
|
267
269
|
|
268
270
|
Check the Nano Bots specification to learn more about [how to build cartridges](https://spec.nbots.io/#/README?id=cartridges).
|
@@ -314,33 +316,48 @@ A common strategy for deploying Nano Bots to multiple users through APIs or auto
|
|
314
316
|
You can define custom end-user identifiers in the following way:
|
315
317
|
|
316
318
|
```ruby
|
317
|
-
NanoBot.new(environment: {
|
318
|
-
NanoBot.new(environment: {
|
319
|
+
NanoBot.new(environment: { NANO_BOTS_END_USER: 'custom-user-a' })
|
320
|
+
NanoBot.new(environment: { NANO_BOTS_END_USER: 'custom-user-b' })
|
319
321
|
```
|
320
322
|
|
321
|
-
Consider that you have
|
323
|
+
Consider that you have the following end-user identifier in your environment:
|
322
324
|
```sh
|
323
|
-
|
325
|
+
NANO_BOTS_END_USER=your-name
|
326
|
+
```
|
327
|
+
|
328
|
+
Or a configuration in your Cartridge:
|
329
|
+
```yml
|
330
|
+
---
|
331
|
+
provider:
|
332
|
+
id: openai
|
333
|
+
settings:
|
334
|
+
user: your-name
|
324
335
|
```
|
325
336
|
|
326
337
|
The requests will be performed as follows:
|
327
338
|
|
328
339
|
```ruby
|
329
|
-
NanoBot.new(
|
330
|
-
# { user: 'your-name
|
340
|
+
NanoBot.new(cartridge: '-')
|
341
|
+
# { user: 'your-name' }
|
331
342
|
|
332
|
-
NanoBot.new(environment: {
|
333
|
-
# { user: '
|
343
|
+
NanoBot.new(cartridge: '-', environment: { NANO_BOTS_END_USER: 'custom-user-a' })
|
344
|
+
# { user: 'custom-user-a' }
|
345
|
+
|
346
|
+
NanoBot.new(cartridge: '-', environment: { NANO_BOTS_END_USER: 'custom-user-b' })
|
347
|
+
# { user: 'custom-user-b' }
|
334
348
|
```
|
335
349
|
|
336
350
|
Actually, to enhance privacy, neither your user nor your users' identifiers will be shared in this way. Instead, they will be encrypted before being shared with the provider:
|
337
351
|
|
338
352
|
```ruby
|
339
|
-
'your-name
|
340
|
-
#
|
353
|
+
'your-name'
|
354
|
+
# _O7OjYUESagb46YSeUeSfSMzoO1Yg0BZqpsAkPg4j62SeNYlgwq3kn51Ob2wmIehoA==
|
355
|
+
|
356
|
+
'custom-user-a'
|
357
|
+
# _O7OjYUESagb46YSeUeSfSMzoO1Yg0BZJgIXHCBHyADW-rn4IQr-s2RvP7vym8u5tnzYMIs=
|
341
358
|
|
342
|
-
'
|
343
|
-
#
|
359
|
+
'custom-user-b'
|
360
|
+
# _O7OjYUESagb46YSeUeSfSMzoO1Yg0BZkjUwCcsh9sVppKvYMhd2qGRvP7vym8u5tnzYMIg=
|
344
361
|
```
|
345
362
|
|
346
363
|
In this manner, you possess identifiers if required, however, their actual content can only be decrypted by you via your secure password (`NANO_BOTS_ENCRYPTION_PASSWORD`).
|
@@ -352,11 +369,14 @@ To decrypt your encrypted data, once you have properly configured your password,
|
|
352
369
|
```ruby
|
353
370
|
require 'nano-bots'
|
354
371
|
|
355
|
-
NanoBot.security.decrypt('
|
356
|
-
# your-name
|
372
|
+
NanoBot.security.decrypt('_O7OjYUESagb46YSeUeSfSMzoO1Yg0BZqpsAkPg4j62SeNYlgwq3kn51Ob2wmIehoA==')
|
373
|
+
# your-name
|
374
|
+
|
375
|
+
NanoBot.security.decrypt('_O7OjYUESagb46YSeUeSfSMzoO1Yg0BZJgIXHCBHyADW-rn4IQr-s2RvP7vym8u5tnzYMIs=')
|
376
|
+
# custom-user-a
|
357
377
|
|
358
|
-
NanoBot.security.decrypt('
|
359
|
-
#
|
378
|
+
NanoBot.security.decrypt('_O7OjYUESagb46YSeUeSfSMzoO1Yg0BZkjUwCcsh9sVppKvYMhd2qGRvP7vym8u5tnzYMIg=')
|
379
|
+
# custom-user-b
|
360
380
|
```
|
361
381
|
|
362
382
|
If you lose your password, you lose your data. It is not possible to recover it at all. For real.
|
@@ -388,5 +408,5 @@ gem build nano-bots.gemspec
|
|
388
408
|
|
389
409
|
gem signin
|
390
410
|
|
391
|
-
gem push nano-bots-0.0.
|
411
|
+
gem push nano-bots-0.1.0.gem
|
392
412
|
```
|
data/components/provider.rb
CHANGED
@@ -8,11 +8,11 @@ module NanoBot
|
|
8
8
|
module Components
|
9
9
|
class Provider
|
10
10
|
def self.new(provider, environment: {})
|
11
|
-
case provider[:
|
11
|
+
case provider[:id]
|
12
12
|
when 'openai'
|
13
|
-
Providers::OpenAI.new(provider[:settings], environment:)
|
13
|
+
Providers::OpenAI.new(provider[:settings], provider[:credentials], environment:)
|
14
14
|
else
|
15
|
-
raise "Unsupported provider #{provider[:
|
15
|
+
raise "Unsupported provider \"#{provider[:id]}\""
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -6,6 +6,10 @@ module NanoBot
|
|
6
6
|
module Components
|
7
7
|
module Providers
|
8
8
|
class Base
|
9
|
+
def initialize(_settings, _credentials, _environment: {})
|
10
|
+
raise NoMethodError, "The 'initialize' method is not implemented for the current provider."
|
11
|
+
end
|
12
|
+
|
9
13
|
def evaluate(_payload)
|
10
14
|
raise NoMethodError, "The 'evaluate' method is not implemented for the current provider."
|
11
15
|
end
|
@@ -9,6 +9,8 @@ module NanoBot
|
|
9
9
|
module Components
|
10
10
|
module Providers
|
11
11
|
class OpenAI < Base
|
12
|
+
DEFAULT_ADDRESS = 'https://api.openai.com'
|
13
|
+
|
12
14
|
CHAT_SETTINGS = %i[
|
13
15
|
model stream temperature top_p n stop max_tokens
|
14
16
|
presence_penalty frequency_penalty logit_bias
|
@@ -16,14 +18,18 @@ module NanoBot
|
|
16
18
|
|
17
19
|
attr_reader :settings
|
18
20
|
|
19
|
-
def initialize(settings, environment: {})
|
21
|
+
def initialize(settings, credentials, environment: {})
|
20
22
|
@settings = settings
|
23
|
+
@credentials = credentials
|
21
24
|
@environment = environment
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
uri_base = if @credentials[:address].nil? || @credentials[:address].to_s.strip.empty?
|
27
|
+
"#{DEFAULT_ADDRESS}/"
|
28
|
+
else
|
29
|
+
"#{@credentials[:address].to_s.sub(%r{/$}, '')}/"
|
30
|
+
end
|
31
|
+
|
32
|
+
@client = ::OpenAI::Client.new(uri_base:, access_token: @credentials[:'access-token'])
|
27
33
|
end
|
28
34
|
|
29
35
|
def stream(input)
|
@@ -48,16 +54,7 @@ module NanoBot
|
|
48
54
|
)
|
49
55
|
end
|
50
56
|
|
51
|
-
|
52
|
-
|
53
|
-
user_suffix = @environment && (
|
54
|
-
@environment['NANO_BOTS_USER_IDENTIFIER'] ||
|
55
|
-
@environment[:NANO_BOTS_USER_IDENTIFIER]
|
56
|
-
)
|
57
|
-
|
58
|
-
user = "#{user}/#{user_suffix}" if user_suffix && user_suffix != ''
|
59
|
-
|
60
|
-
payload = { model: @settings[:model], user: Crypto.encrypt(user, soft: true), messages: }
|
57
|
+
payload = { user: OpenAI.end_user(@settings, @environment), messages: }
|
61
58
|
|
62
59
|
CHAT_SETTINGS.each do |key|
|
63
60
|
payload[key] = @settings[key] if @settings.key?(key)
|
@@ -87,6 +84,27 @@ module NanoBot
|
|
87
84
|
block.call({ who: 'AI', message: result.dig('choices', 0, 'message', 'content') }, true)
|
88
85
|
end
|
89
86
|
end
|
87
|
+
|
88
|
+
def self.end_user(settings, environment)
|
89
|
+
user = ENV.fetch('NANO_BOTS_END_USER', nil)
|
90
|
+
|
91
|
+
user = settings[:user] if !settings[:user].nil? && !settings[:user].to_s.strip.empty?
|
92
|
+
|
93
|
+
candidate = environment && (
|
94
|
+
environment['NANO_BOTS_END_USER'] ||
|
95
|
+
environment[:NANO_BOTS_END_USER]
|
96
|
+
)
|
97
|
+
|
98
|
+
user = candidate if !candidate.nil? && !candidate.to_s.strip.empty?
|
99
|
+
|
100
|
+
user = if user.nil? || user.to_s.strip.empty?
|
101
|
+
'unknown'
|
102
|
+
else
|
103
|
+
user.to_s.strip
|
104
|
+
end
|
105
|
+
|
106
|
+
Crypto.encrypt(user, soft: true)
|
107
|
+
end
|
90
108
|
end
|
91
109
|
end
|
92
110
|
end
|
data/components/storage.rb
CHANGED
@@ -8,6 +8,31 @@ require_relative './crypto'
|
|
8
8
|
module NanoBot
|
9
9
|
module Components
|
10
10
|
class Storage
|
11
|
+
def self.end_user(cartridge, environment)
|
12
|
+
user = ENV.fetch('NANO_BOTS_END_USER', nil)
|
13
|
+
|
14
|
+
if cartridge[:provider][:id] == 'openai' &&
|
15
|
+
!cartridge[:provider][:settings][:user].nil? &&
|
16
|
+
!cartridge[:provider][:settings][:user].to_s.strip.empty?
|
17
|
+
user = cartridge[:provider][:settings][:user]
|
18
|
+
end
|
19
|
+
|
20
|
+
candidate = environment && (
|
21
|
+
environment['NANO_BOTS_END_USER'] ||
|
22
|
+
environment[:NANO_BOTS_END_USER]
|
23
|
+
)
|
24
|
+
|
25
|
+
user = candidate if !candidate.nil? && !candidate.to_s.strip.empty?
|
26
|
+
|
27
|
+
user = if user.nil? || user.to_s.strip.empty?
|
28
|
+
'unknown'
|
29
|
+
else
|
30
|
+
user.to_s.strip
|
31
|
+
end
|
32
|
+
|
33
|
+
Crypto.encrypt(user, soft: true)
|
34
|
+
end
|
35
|
+
|
11
36
|
def self.build_path_and_ensure_state_file!(key, cartridge, environment: {})
|
12
37
|
path = [
|
13
38
|
Logic::Helpers::Hash.fetch(cartridge, %i[state directory]),
|
@@ -18,27 +43,12 @@ module NanoBot
|
|
18
43
|
|
19
44
|
path = "#{user_home!.sub(%r{/$}, '')}/.local/state/nano-bots" if path.nil?
|
20
45
|
|
21
|
-
|
22
|
-
environment['NANO_BOTS_USER_IDENTIFIER'] ||
|
23
|
-
environment[:NANO_BOTS_USER_IDENTIFIER]
|
24
|
-
)
|
25
|
-
|
26
|
-
path = "#{path.sub(%r{/$}, '')}/ruby-nano-bots/vault"
|
27
|
-
|
28
|
-
if prefix
|
29
|
-
normalized = prefix.split('/').map do |part|
|
30
|
-
Crypto.encrypt(
|
31
|
-
part.to_s.gsub('.', '-').force_encoding('UTF-8').to_slug.normalize,
|
32
|
-
soft: true
|
33
|
-
)
|
34
|
-
end.join('/')
|
35
|
-
|
36
|
-
path = "#{path}/#{normalized}"
|
37
|
-
end
|
46
|
+
path = "#{path.sub(%r{/$}, '')}/ruby-nano-bots"
|
38
47
|
|
39
48
|
path = "#{path}/#{cartridge[:meta][:author].to_slug.normalize}"
|
40
49
|
path = "#{path}/#{cartridge[:meta][:name].to_slug.normalize}"
|
41
50
|
path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}"
|
51
|
+
path = "#{path}/#{end_user(cartridge, environment)}"
|
42
52
|
path = "#{path}/#{Crypto.encrypt(key, soft: true)}"
|
43
53
|
path = "#{path}/state.json"
|
44
54
|
|
data/controllers/security.rb
CHANGED
@@ -9,6 +9,10 @@ module NanoBot
|
|
9
9
|
Components::Crypto.decrypt(content)
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.encrypt(content, soft: false)
|
13
|
+
Components::Crypto.encrypt(content, soft:)
|
14
|
+
end
|
15
|
+
|
12
16
|
def self.check
|
13
17
|
password = ENV.fetch('NANO_BOTS_ENCRYPTION_PASSWORD', nil)
|
14
18
|
password = 'UNSAFE' unless password && password != ''
|
data/docker-compose.example.yml
CHANGED
@@ -3,12 +3,12 @@ version: '3.7'
|
|
3
3
|
services:
|
4
4
|
nano-bots:
|
5
5
|
image: ruby:3.2.2-slim-bullseye
|
6
|
-
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev && gem install nano-bots -v 0.0
|
6
|
+
command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev && gem install nano-bots -v 0.1.0 && bash"
|
7
7
|
environment:
|
8
|
-
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
9
8
|
OPENAI_API_ADDRESS: https://api.openai.com
|
10
|
-
|
11
|
-
|
9
|
+
OPENAI_API_KEY: your-access-token
|
10
|
+
NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
|
11
|
+
NANO_BOTS_END_USER: your-user
|
12
12
|
volumes:
|
13
|
-
- ./your-cartridges
|
14
|
-
|
13
|
+
- ./your-cartridges:/.local/share/nano-bots/cartridges
|
14
|
+
- ./your-state:/.local/state/nano-bots
|
@@ -1,14 +1,17 @@
|
|
1
1
|
---
|
2
2
|
meta:
|
3
|
+
symbol: 🤖
|
3
4
|
name: Unknown
|
4
|
-
author:
|
5
|
+
author: None
|
5
6
|
version: 0.0.0
|
7
|
+
license: CC0-1.0
|
8
|
+
description: Unknown
|
6
9
|
|
7
10
|
provider:
|
8
|
-
|
11
|
+
id: openai
|
12
|
+
credentials:
|
13
|
+
address: ENV/OPENAI_API_ADDRESS
|
14
|
+
access-token: ENV/OPENAI_API_KEY
|
9
15
|
settings:
|
16
|
+
user: ENV/NANO_BOTS_END_USER
|
10
17
|
model: gpt-3.5-turbo
|
11
|
-
credentials:
|
12
|
-
address: ENV/OPENAI_API_ADDRESS
|
13
|
-
access-token: ENV/OPENAI_API_ACCESS_TOKEN
|
14
|
-
user-identifier: ENV/OPENAI_API_USER_IDENTIFIER
|
data/static/gem.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module NanoBot
|
4
4
|
GEM = {
|
5
5
|
name: 'nano-bots',
|
6
|
-
version: '0.0
|
6
|
+
version: '0.1.0',
|
7
7
|
author: 'icebaker',
|
8
8
|
summary: 'Ruby Implementation of Nano Bots: small, AI-powered bots',
|
9
9
|
description: 'Ruby Implementation of Nano Bots: small, AI-powered bots easily shared as a single file, designed to support multiple providers such as Vicuna, OpenAI ChatGPT, Google PaLM, Alpaca, and LLaMA.',
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nano-bots
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- icebaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: babosa
|