nano-bots 3.2.0 → 3.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6ee7d534a42c2e11bc5a66d81b4a3c6baad7bb9e72ceb8ac4ad4735ac2f9d78
4
- data.tar.gz: 8cfaf1303ad1f65b4b50f99c860252c93d2817d6e0a5b3d3ee978d08397ebaa8
3
+ metadata.gz: 12888eb352fa3d3a744e0d4be79073bde3325bc795e13f0bbe60d6b6d0143105
4
+ data.tar.gz: 644af12193710d8484e3802d8ff5f976fb37d88c29bdcb25bbfc0f59df153a90
5
5
  SHA512:
6
- metadata.gz: 114798cb6c752de8d01297c5a6359b25c7d80d6b63b07a5c47f5ed4d677c0454ee0848ba412251f6ef81db02efd3ce285d6aaa08908ff3143d27d80d84315d16
7
- data.tar.gz: 6fcbd9a54554b23aff0767fe002e6435d2f09007bf7190c98179b6998512fa003898403a59f025e4c97204e6128877dde52dd48e17b986ab9b8cd1a568dc988f
6
+ metadata.gz: 0cbda4335fcd2508e0735bd1a1034aea1588f0b944d145ffb0a2c63211c227aa0c855790bc45813c4dcabc97f062fbd26c3c211f405a0bc52b7048ad8ce113fb
7
+ data.tar.gz: e08dabe3aae2bd9501bd9087ebaaf3b243afb3580ca09ce08be2a42b58e9bb3187d2a27df3d4db9e992294ec841e301192af0196fc4daebc8aa5b7dca56eaa3b
data/Gemfile.lock CHANGED
@@ -1,14 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nano-bots (3.2.0)
4
+ nano-bots (3.4.0)
5
+ anthropic (~> 0.3.0)
5
6
  babosa (~> 2.0)
6
7
  cohere-ai (~> 1.1)
7
8
  concurrent-ruby (~> 1.3, >= 1.3.3)
8
9
  dotenv (~> 3.1, >= 3.1.2)
9
10
  faraday (~> 2.9, >= 2.9.2)
10
11
  faraday-typhoeus (~> 1.1)
11
- gemini-ai (~> 4.0)
12
+ gemini-ai (~> 4.1)
12
13
  maritaca-ai (~> 1.2)
13
14
  mistral-ai (~> 1.2)
14
15
  ollama-ai (~> 1.2, >= 1.2.1)
@@ -25,6 +26,10 @@ GEM
25
26
  specs:
26
27
  addressable (2.8.7)
27
28
  public_suffix (>= 2.0.2, < 7.0)
29
+ anthropic (0.3.0)
30
+ event_stream_parser (>= 0.3.0, < 2.0.0)
31
+ faraday (>= 1)
32
+ faraday-multipart (>= 1)
28
33
  ast (2.4.2)
29
34
  babosa (2.0.0)
30
35
  base64 (0.2.0)
@@ -49,9 +54,9 @@ GEM
49
54
  faraday (~> 2.0)
50
55
  typhoeus (~> 1.4)
51
56
  ffi (1.17.0)
52
- gemini-ai (4.0.0)
57
+ gemini-ai (4.1.0)
53
58
  event_stream_parser (~> 1.0)
54
- faraday (~> 2.9)
59
+ faraday (~> 2.9, >= 2.9.2)
55
60
  faraday-typhoeus (~> 1.1)
56
61
  googleauth (~> 1.8)
57
62
  typhoeus (~> 1.4, >= 1.4.1)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Nano Bots 💎 🤖
2
2
 
3
- An implementation of the [Nano Bots](https://spec.nbots.io) specification with support for [Cohere Command](https://cohere.com), [Google Gemini](https://deepmind.google/technologies/gemini), [Maritaca AI MariTalk](https://www.maritaca.ai), [Mistral AI](https://mistral.ai), [Ollama](https://ollama.ai), [OpenAI ChatGPT](https://openai.com/chatgpt), and others, with support for calling tools (functions).
3
+ An implementation of the [Nano Bots](https://spec.nbots.io) specification with support for [Anthropic Claude](https://www.anthropic.com/claude), [Cohere Command](https://cohere.com), [Google Gemini](https://deepmind.google/technologies/gemini), [Maritaca AI Sabiá](https://www.maritaca.ai), [Mistral AI](https://mistral.ai), [Ollama](https://ollama.ai), [OpenAI ChatGPT](https://openai.com/chatgpt), and others, with support for calling tools (functions).
4
4
 
5
5
  ![Ruby Nano Bots](https://raw.githubusercontent.com/icebaker/assets/main/nano-bots/ruby-nano-bots-canvas.png)
6
6
 
@@ -9,7 +9,7 @@ https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b
9
9
  ## TL;DR and Quick Start
10
10
 
11
11
  ```sh
12
- gem install nano-bots -v 3.2.0
12
+ gem install nano-bots -v 3.4.0
13
13
  ```
14
14
 
15
15
  ```bash
@@ -59,7 +59,7 @@ nb gpt.yml - eval "hi"
59
59
  ```
60
60
 
61
61
  ```ruby
62
- gem 'nano-bots', '~> 3.2.0'
62
+ gem 'nano-bots', '~> 3.4.0'
63
63
  ```
64
64
 
65
65
  ```ruby
@@ -80,6 +80,7 @@ end
80
80
  - [Debugging](#debugging)
81
81
  - [Library](#library)
82
82
  - [Setup](#setup)
83
+ - [Anthropic Claude](#anthropic-claude)
83
84
  - [Cohere Command](#cohere-command)
84
85
  - [Maritaca AI MariTalk](#maritaca-ai-maritalk)
85
86
  - [Mistral AI](#mistral-ai)
@@ -100,6 +101,7 @@ end
100
101
  - [Decrypting](#decrypting)
101
102
  - [Supported Providers](#supported-providers)
102
103
  - [Docker](#docker)
104
+ - [Anthropic Claude Container](#anthropic-claude-container)
103
105
  - [Cohere Command Container](#cohere-command-container)
104
106
  - [Maritaca AI MariTalk Container](#maritaca-ai-maritalk-container)
105
107
  - [Mistral AI Container](#mistral-ai-container)
@@ -250,13 +252,13 @@ end
250
252
  To install the CLI on your system:
251
253
 
252
254
  ```sh
253
- gem install nano-bots -v 3.2.0
255
+ gem install nano-bots -v 3.4.0
254
256
  ```
255
257
 
256
258
  To use it in a Ruby project as a library, add to your `Gemfile`:
257
259
 
258
260
  ```ruby
259
- gem 'nano-bots', '~> 3.2.0'
261
+ gem 'nano-bots', '~> 3.4.0'
260
262
  ```
261
263
 
262
264
  ```sh
@@ -283,6 +285,59 @@ NANO_BOTS_END_USER=your-user
283
285
  # NANO_BOTS_CARTRIDGES_PATH=/home/user/.local/share/nano-bots/cartridges
284
286
  ```
285
287
 
288
+ ### Anthropic Claude
289
+
290
+ You can obtain your credentials on the [Anthropic Console](https://console.anthropic.com).
291
+
292
+ ```sh
293
+ export ANTHROPIC_API_KEY=your-api-key
294
+ ```
295
+
296
+ Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded:
297
+
298
+ ```sh
299
+ ANTHROPIC_API_KEY=your-api-key
300
+ ```
301
+
302
+ Create a `cartridge.yml` file:
303
+
304
+ ```yaml
305
+ ---
306
+ meta:
307
+ symbol: 🤖
308
+ name: Nano Bot Name
309
+ author: Your Name
310
+ version: 1.0.0
311
+ license: CC0-1.0
312
+ description: A helpful assistant.
313
+
314
+ behaviors:
315
+ interaction:
316
+ directive: You are a helpful assistant.
317
+
318
+ provider:
319
+ id: anthropic
320
+ credentials:
321
+ api-key: ENV/ANTHROPIC_API_KEY
322
+ settings:
323
+ model: claude-3-5-sonnet-20240620
324
+ max_tokens: 4096
325
+ ```
326
+
327
+ Read the [full specification](https://spec.nbots.io/#/README?id=anthropic-claude) for Anthropic Claude.
328
+
329
+ ```bash
330
+ nb cartridge.yml - eval "Hello"
331
+
332
+ nb cartridge.yml - repl
333
+ ```
334
+
335
+ ```ruby
336
+ bot = NanoBot.new(cartridge: 'cartridge.yml')
337
+
338
+ puts bot.eval('Hello')
339
+ ```
340
+
286
341
  ### Cohere Command
287
342
 
288
343
  You can obtain your credentials on the [Cohere Platform](https://dashboard.cohere.com).
@@ -939,7 +994,7 @@ If you lose your password, you lose your data. It is not possible to recover it
939
994
 
940
995
  ## Supported Providers
941
996
 
942
- - [ ] [Anthropic Claude](https://www.anthropic.com)
997
+ - [x] [Anthropic Claude](https://www.anthropic.com)
943
998
  - [x] [Cohere Command](https://cohere.com)
944
999
  - [x] [Google Gemini](https://deepmind.google/technologies/gemini)
945
1000
  - [x] [Maritaca AI MariTalk](https://www.maritaca.ai)
@@ -965,6 +1020,23 @@ cp docker-compose.example.yml docker-compose.yml
965
1020
 
966
1021
  Set your provider credentials and choose your desired path for the cartridges files:
967
1022
 
1023
+ ### Anthropic Claude Container
1024
+
1025
+ ```yaml
1026
+ ---
1027
+ services:
1028
+ nano-bots:
1029
+ image: ruby:3.3.3-slim-bookworm
1030
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1031
+ environment:
1032
+ ANTHROPIC_API_KEY: your-api-key
1033
+ NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
1034
+ NANO_BOTS_END_USER: your-user
1035
+ volumes:
1036
+ - ./your-cartridges:/root/.local/share/nano-bots/cartridges
1037
+ - ./your-state-path:/root/.local/state/nano-bots
1038
+ ```
1039
+
968
1040
  ### Cohere Command Container
969
1041
 
970
1042
  ```yaml
@@ -972,7 +1044,7 @@ Set your provider credentials and choose your desired path for the cartridges fi
972
1044
  services:
973
1045
  nano-bots:
974
1046
  image: ruby:3.3.3-slim-bookworm
975
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1047
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
976
1048
  environment:
977
1049
  COHERE_API_KEY: your-api-key
978
1050
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -989,7 +1061,7 @@ services:
989
1061
  services:
990
1062
  nano-bots:
991
1063
  image: ruby:3.3.3-slim-bookworm
992
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1064
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
993
1065
  environment:
994
1066
  MARITACA_API_KEY: your-api-key
995
1067
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1006,7 +1078,7 @@ services:
1006
1078
  services:
1007
1079
  nano-bots:
1008
1080
  image: ruby:3.3.3-slim-bookworm
1009
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1081
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1010
1082
  environment:
1011
1083
  MISTRAL_API_KEY: your-api-key
1012
1084
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1025,7 +1097,7 @@ Remember that your `localhost` is by default inaccessible from inside Docker. Yo
1025
1097
  services:
1026
1098
  nano-bots:
1027
1099
  image: ruby:3.3.3-slim-bookworm
1028
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1100
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1029
1101
  environment:
1030
1102
  OLLAMA_API_ADDRESS: http://localhost:11434
1031
1103
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1044,7 +1116,7 @@ services:
1044
1116
  services:
1045
1117
  nano-bots:
1046
1118
  image: ruby:3.3.3-slim-bookworm
1047
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1119
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1048
1120
  environment:
1049
1121
  OPENAI_API_KEY: your-access-token
1050
1122
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1063,7 +1135,7 @@ services:
1063
1135
  services:
1064
1136
  nano-bots:
1065
1137
  image: ruby:3.3.3-slim-bookworm
1066
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1138
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1067
1139
  environment:
1068
1140
  GOOGLE_API_KEY: your-api-key
1069
1141
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1080,7 +1152,7 @@ services:
1080
1152
  services:
1081
1153
  nano-bots:
1082
1154
  image: ruby:3.3.3-slim-bookworm
1083
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1155
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1084
1156
  environment:
1085
1157
  GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json
1086
1158
  GOOGLE_REGION: us-east4
@@ -1099,7 +1171,7 @@ services:
1099
1171
  services:
1100
1172
  nano-bots:
1101
1173
  image: ruby:3.3.3-slim-bookworm
1102
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
1174
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
1103
1175
  environment:
1104
1176
  GOOGLE_REGION: us-east4
1105
1177
  NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE
@@ -1161,5 +1233,5 @@ gem build nano-bots.gemspec
1161
1233
 
1162
1234
  gem signin
1163
1235
 
1164
- gem push nano-bots-3.2.0.gem
1236
+ gem push nano-bots-3.4.0.gem
1165
1237
  ```
@@ -24,7 +24,11 @@ module NanoBot
24
24
 
25
25
  state.eval(code)
26
26
  embedded = state.get(:embedded)
27
- embedded.call(values)
27
+ begin
28
+ embedded.call(values)
29
+ rescue StandardError => e
30
+ e.message
31
+ end
28
32
  end
29
33
 
30
34
  def self.fennel(source:, parameters:, values:, safety:)
@@ -39,7 +43,11 @@ module NanoBot
39
43
  safety[:sandboxed] ? { allowedGlobals: %w[math string table] } : nil
40
44
  )
41
45
  embedded = state.get(:embedded)
42
- embedded.call(values)
46
+ begin
47
+ embedded.call(values)
48
+ rescue StandardError => e
49
+ e.message
50
+ end
43
51
  end
44
52
 
45
53
  def self.clojure(source:, parameters:, values:, safety:)
@@ -4,6 +4,7 @@ require_relative 'providers/openai'
4
4
  require_relative 'providers/ollama'
5
5
  require_relative 'providers/mistral'
6
6
  require_relative 'providers/google'
7
+ require_relative 'providers/anthropic'
7
8
  require_relative 'providers/cohere'
8
9
  require_relative 'providers/maritaca'
9
10
 
@@ -20,6 +21,8 @@ module NanoBot
20
21
  Providers::Mistral.new(provider[:options], provider[:settings], provider[:credentials], environment:)
21
22
  when 'google'
22
23
  Providers::Google.new(provider[:options], provider[:settings], provider[:credentials], environment:)
24
+ when 'anthropic'
25
+ Providers::Anthropic.new(nil, provider[:settings], provider[:credentials], environment:)
23
26
  when 'cohere'
24
27
  Providers::Cohere.new(provider[:options], provider[:settings], provider[:credentials], environment:)
25
28
  when 'maritaca'
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'anthropic'
4
+
5
+ require_relative 'base'
6
+
7
+ require_relative '../../logic/providers/anthropic/tokens'
8
+ require_relative '../../logic/helpers/hash'
9
+ require_relative '../../logic/cartridge/default'
10
+
11
+ module NanoBot
12
+ module Components
13
+ module Providers
14
+ class Anthropic < Base
15
+ attr_reader :settings
16
+
17
+ CHAT_SETTINGS = %i[
18
+ model stream max_tokens temperature top_k top_p tool_choice
19
+ metadata stop_sequences
20
+ ].freeze
21
+
22
+ def initialize(_options, settings, credentials, _environment)
23
+ @settings = settings
24
+
25
+ unless @settings.key?(:stream)
26
+ @settings = Marshal.load(Marshal.dump(@settings))
27
+ @settings[:stream] = Logic::Helpers::Hash.fetch(
28
+ Logic::Cartridge::Default.instance.values, %i[provider settings stream]
29
+ )
30
+ end
31
+
32
+ @client = ::Anthropic::Client.new(
33
+ access_token: credentials[:'api-key'],
34
+ anthropic_version: credentials[:'anthropic-version']
35
+ )
36
+ end
37
+
38
+ def evaluate(input, streaming, cartridge, &feedback)
39
+ messages = input[:history].map do |event|
40
+ { role: event[:who] == 'user' ? 'user' : 'assistant',
41
+ content: event[:message],
42
+ _meta: { at: event[:at] } }
43
+ end
44
+
45
+ if input[:behavior][:backdrop]
46
+ messages.prepend(
47
+ { role: 'assistant',
48
+ content: 'Ok.',
49
+ _meta: { at: Time.now } }
50
+ )
51
+
52
+ messages.prepend(
53
+ { role: 'user',
54
+ content: input[:behavior][:backdrop],
55
+ _meta: { at: Time.now } }
56
+ )
57
+ end
58
+
59
+ payload = { messages: }
60
+
61
+ payload[:system] = input[:behavior][:directive] if input[:behavior][:directive]
62
+
63
+ CHAT_SETTINGS.each do |key|
64
+ payload[key] = @settings[key] unless payload.key?(key) || !@settings.key?(key)
65
+ end
66
+
67
+ raise 'Anthropic does not support tools.' if input[:tools]
68
+
69
+ if streaming
70
+ content = ''
71
+
72
+ stream_call_back = proc do |event|
73
+ partial_content = event.dig('delta', 'text')
74
+
75
+ if partial_content && event['type'] == 'content_block_delta'
76
+ content += partial_content
77
+ feedback.call(
78
+ { should_be_stored: false,
79
+ interaction: { who: 'AI', message: partial_content } }
80
+ )
81
+ end
82
+
83
+ if event['type'] == 'content_block_stop'
84
+ feedback.call(
85
+ { should_be_stored: !(content.nil? || content == ''),
86
+ interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content },
87
+ finished: true }
88
+ )
89
+ end
90
+ end
91
+
92
+ @client.messages(
93
+ parameters: Logic::Anthropic::Tokens.apply_policies!(
94
+ cartridge, payload
95
+ ).merge({ stream: stream_call_back })
96
+ )
97
+ else
98
+ result = @client.messages(
99
+ parameters: Logic::Anthropic::Tokens.apply_policies!(cartridge, payload)
100
+ )
101
+
102
+ content = result['content'].map { |content| content['text'] }.join
103
+
104
+ feedback.call(
105
+ { should_be_stored: !(content.nil? || content.to_s.strip == ''),
106
+ interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content },
107
+ finished: true }
108
+ )
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -15,9 +15,10 @@ module NanoBot
15
15
  attr_reader :settings
16
16
 
17
17
  CHAT_SETTINGS = %i[
18
- model stream prompt_truncation connectors
19
- search_queries_only documents citation_quality
20
- temperature
18
+ model stream prompt_truncation connectors search_queries_only
19
+ documents citation_quality temperature max_tokens max_input_tokens
20
+ k p seed stop_sequences frequency_penalty presence_penalty
21
+ force_single_step
21
22
  ].freeze
22
23
 
23
24
  def initialize(options, settings, credentials, _environment)
@@ -19,7 +19,9 @@ module NanoBot
19
19
 
20
20
  SETTINGS = {
21
21
  generationConfig: %i[
22
- temperature topP topK candidateCount maxOutputTokens stopSequences
22
+ temperature maxOutputTokens candidateCount presencePenalty
23
+ frequencyPenalty topK topP stopSequences
24
+ responseMimeType responseSchema
23
25
  ].freeze
24
26
  }.freeze
25
27
 
@@ -154,6 +156,9 @@ module NanoBot
154
156
  if event.dig('candidates', 0, 'finishReason') == 'SAFETY'
155
157
  reasons = event.dig('candidates', 0, 'safetyRatings')
156
158
  raise StandardError, "Generation stopped for safety reasons: #{reasons}"
159
+ elsif event.dig('candidates', 0, 'finishReason') == 'RECITATION'
160
+ reasons = event.dig('candidates', 0, 'citationMetadata')
161
+ raise StandardError, "Generation stopped for recitation reasons: #{reasons}"
157
162
  end
158
163
  end
159
164
 
@@ -15,7 +15,8 @@ module NanoBot
15
15
  attr_reader :settings
16
16
 
17
17
  CHAT_SETTINGS = %i[
18
- max_tokens model stream do_sample temperature top_p repetition_penalty stopping_tokens
18
+ stream model max_tokens do_sample temperature top_p
19
+ repetition_penalty num_tokens_per_message stopping_tokens
19
20
  ].freeze
20
21
 
21
22
  def initialize(options, settings, credentials, _environment)
@@ -15,7 +15,8 @@ module NanoBot
15
15
  attr_reader :settings
16
16
 
17
17
  CHAT_SETTINGS = %i[
18
- model temperature top_p max_tokens stream safe_mode random_seed
18
+ model temperature top_p max_tokens stream safe_prompt random_seed
19
+ safe_mode
19
20
  ].freeze
20
21
 
21
22
  def initialize(options, settings, credentials, _environment)
@@ -15,12 +15,15 @@ module NanoBot
15
15
  attr_reader :settings
16
16
 
17
17
  CHAT_SETTINGS = %i[
18
- model template stream
18
+ model template stream format raw
19
19
  ].freeze
20
20
 
21
21
  CHAT_OPTIONS = %i[
22
- mirostat mirostat_eta mirostat_tau num_ctx num_gqa num_gpu num_thread repeat_last_n
23
- repeat_penalty temperature seed stop tfs_z num_predict top_k top_p
22
+ num_keep seed num_predict top_k top_p tfs_z typical_p repeat_last_n
23
+ temperature repeat_penalty presence_penalty frequency_penalty
24
+ mirostat mirostat_tau mirostat_eta penalize_newline numa num_ctx
25
+ num_batch num_gpu main_gpu low_vram f16_kv vocab_only use_mmap
26
+ use_mlock num_thread stop
24
27
  ].freeze
25
28
 
26
29
  def initialize(options, settings, credentials, _environment)
@@ -35,7 +35,7 @@ module NanoBot
35
35
  Crypto.encrypt(user, soft: true)
36
36
  end
37
37
 
38
- def self.build_path_and_ensure_state_file!(key, cartridge, environment: {})
38
+ def self.build_path_for_state_file(key, cartridge, environment: {})
39
39
  path = [
40
40
  Logic::Helpers::Hash.fetch(cartridge, %i[state path]),
41
41
  Logic::Helpers::Hash.fetch(cartridge, %i[state directory]),
@@ -54,18 +54,8 @@ module NanoBot
54
54
  path = "#{path}/#{cartridge[:meta][:version].to_s.gsub('.', '-').to_slug.normalize}"
55
55
  path = "#{path}/#{end_user(cartridge, environment)}"
56
56
  path = "#{path}/#{Crypto.encrypt(key, soft: true)}"
57
- path = "#{path}/state.json"
58
57
 
59
- FileUtils.mkdir_p(File.dirname(path))
60
-
61
- unless File.exist?(path)
62
- File.write(
63
- path,
64
- Crypto.encrypt(JSON.generate({ key:, history: [] }))
65
- )
66
- end
67
-
68
- path
58
+ "#{path}/state.json"
69
59
  end
70
60
 
71
61
  def self.cartridges_path(components: {})
@@ -34,7 +34,9 @@ module NanoBot
34
34
  if @stateless
35
35
  @state = { history: [] }
36
36
  else
37
- @state_path = Components::Storage.build_path_and_ensure_state_file!(
37
+ @state_key = state.strip
38
+
39
+ @state_path = Components::Storage.build_path_for_state_file(
38
40
  state.strip, @cartridge, environment:
39
41
  )
40
42
 
@@ -43,16 +45,24 @@ module NanoBot
43
45
  end
44
46
 
45
47
  def state
46
- { state: { path: @state_path, content: @state } }
48
+ if @state[:history].empty?
49
+ nil
50
+ else
51
+ { state: { path: @state_path, content: @state } }
52
+ end
47
53
  end
48
54
 
49
55
  def load_state
56
+ return { key: @state_key, history: [] } unless File.exist?(@state_path)
57
+
50
58
  @state = Logic::Helpers::Hash.symbolize_keys(
51
59
  JSON.parse(Components::Crypto.decrypt(File.read(@state_path)))
52
60
  )
53
61
  end
54
62
 
55
63
  def store_state!
64
+ FileUtils.mkdir_p(File.dirname(@state_path)) unless File.exist?(@state_path)
65
+
56
66
  File.write(@state_path, Components::Crypto.encrypt(JSON.generate(@state)))
57
67
  end
58
68
 
@@ -2,13 +2,16 @@
2
2
  services:
3
3
  nano-bots:
4
4
  image: ruby:3.3.3-slim-bookworm
5
- command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.2.0 && bash"
5
+ command: sh -c "apt-get update && apt-get install -y --no-install-recommends build-essential libffi-dev libsodium-dev lua5.4-dev curl && curl -s https://raw.githubusercontent.com/babashka/babashka/master/install | bash && gem install nano-bots -v 3.4.0 && bash"
6
6
  environment:
7
+ ANTHROPIC_API_KEY: your-api-key
8
+
7
9
  COHERE_API_KEY: your-api-key
8
10
 
9
11
  # GOOGLE_API_KEY: your-api-key
10
12
 
11
13
  # GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json
14
+ # GOOGLE_CREDENTIALS_FILE_CONTENTS: "contents"
12
15
  # GOOGLE_PROJECT_ID: your-project-id
13
16
  GOOGLE_REGION: us-east4
14
17
 
@@ -8,7 +8,7 @@ module NanoBot
8
8
  module Streaming
9
9
  def self.enabled?(cartridge, interface)
10
10
  provider_stream = case Helpers::Hash.fetch(cartridge, %i[provider id])
11
- when 'openai', 'mistral', 'cohere', 'ollama'
11
+ when 'openai', 'mistral', 'anthropic', 'cohere', 'ollama'
12
12
  Helpers::Hash.fetch(cartridge, %i[provider settings stream])
13
13
  when 'google', 'maritaca'
14
14
  Helpers::Hash.fetch(cartridge, %i[provider options stream])
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NanoBot
4
+ module Logic
5
+ module Anthropic
6
+ module Tokens
7
+ def self.apply_policies!(_cartridge, payload)
8
+ payload[:messages] = payload[:messages].map { |message| message.except(:_meta) }
9
+ payload
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
data/nano-bots.gemspec CHANGED
@@ -40,8 +40,9 @@ Gem::Specification.new do |spec|
40
40
  spec.add_dependency 'redcarpet', '~> 3.6'
41
41
  spec.add_dependency 'sweet-moon', '~> 1.0'
42
42
 
43
+ spec.add_dependency 'anthropic', '~> 0.3.0'
43
44
  spec.add_dependency 'cohere-ai', '~> 1.1'
44
- spec.add_dependency 'gemini-ai', '~> 4.0'
45
+ spec.add_dependency 'gemini-ai', '~> 4.1'
45
46
  spec.add_dependency 'maritaca-ai', '~> 1.2'
46
47
  spec.add_dependency 'mistral-ai', '~> 1.2'
47
48
  spec.add_dependency 'ollama-ai', '~> 1.2', '>= 1.2.1'