diff options
-rw-r--r-- | Gemfile.lock | 6 | ||||
-rw-r--r-- | README.md | 110 | ||||
-rw-r--r-- | components/providers/google.rb | 62 | ||||
-rw-r--r-- | nano-bots.gemspec | 2 | ||||
-rw-r--r-- | ports/dsl/nano-bots.rb | 4 | ||||
-rw-r--r-- | static/gem.rb | 1 |
6 files changed, 137 insertions, 48 deletions
diff --git a/Gemfile.lock b/Gemfile.lock index 92d16fa..bcbb07b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,7 +5,7 @@ PATH babosa (~> 2.0) concurrent-ruby (~> 1.2, >= 1.2.2) dotenv (~> 2.8, >= 2.8.1) - gemini-ai (~> 2.0) + gemini-ai (~> 2.1) pry (~> 0.14.2) rainbow (~> 3.1, >= 3.1.1) rbnacl (~> 7.1, >= 7.1.1) @@ -34,7 +34,7 @@ GEM multipart-post (~> 2) faraday-net_http (3.0.2) ffi (1.16.3) - gemini-ai (2.0.0) + gemini-ai (2.1.0) event_stream_parser (~> 1.0) faraday (~> 2.7, >= 2.7.12) googleauth (~> 1.9, >= 1.9.1) @@ -54,7 +54,7 @@ GEM multi_json (1.15.0) multipart-post (2.3.0) os (1.1.4) - parallel (1.23.0) + parallel (1.24.0) parser (3.2.2.4) ast (~> 2.4.1) racc @@ -105,11 +105,10 @@ NANO_BOTS_END_USER=your-user # NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges ``` -#### Option 2: Service Account (Vertex AI API) +#### Option 2: Service Account Credentials File (Vertex AI API) ```sh export GOOGLE_CREDENTIALS_FILE_PATH=google-credentials.json -export GOOGLE_PROJECT_ID=your-project-id export GOOGLE_REGION=us-east4 export NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE @@ -123,7 +122,6 @@ Alternatively, if your current directory has a `.env` file with the environment ```sh GOOGLE_CREDENTIALS_FILE_PATH=google-credentials.json -GOOGLE_PROJECT_ID=your-project-id GOOGLE_REGION=us-east4 NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE @@ -133,6 +131,44 @@ NANO_BOTS_END_USER=your-user # NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges ``` +#### Option 3: Application Default Credentials (Vertex AI API) + +```sh +export GOOGLE_REGION=us-east4 + +export NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE +export NANO_BOTS_END_USER=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 +``` + +Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded: + +```sh +GOOGLE_REGION=us-east4 + +NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE +NANO_BOTS_END_USER=your-user + +# NANO_BOTS_STATE_DIRECTORY=/home/user/.local/state/nano-bots +# NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges +``` + +#### Custom Project ID + +If you need to manually set a Google Project ID: + +```sh +export GOOGLE_PROJECT_ID=your-project-id +``` + +Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded: + +```sh +GOOGLE_PROJECT_ID=your-project-id +``` + ## Docker Clone the repository and copy the Docker Compose template: @@ -182,7 +218,7 @@ services: - ./your-state-path:/root/.local/state/nano-bots ``` -#### Option 2: Service Account (Vertex AI API) +#### Option 2: Service Account Credentials File (Vertex AI API) ```yaml --- @@ -192,7 +228,6 @@ services: 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 2.0.0 && bash" environment: GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json - GOOGLE_PROJECT_ID: your-project-id GOOGLE_REGION: us-east4 NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE NANO_BOTS_END_USER: your-user @@ -202,6 +237,31 @@ services: - ./your-state-path:/root/.local/state/nano-bots ``` +#### Option 3: Application Default Credentials (Vertex AI API) + +```yaml +--- +services: + nano-bots: + image: ruby:3.2.2-slim-bookworm + 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 2.0.0 && bash" + environment: + GOOGLE_REGION: us-east4 + NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE + NANO_BOTS_END_USER: your-user + volumes: + - ./your-cartridges:/root/.local/share/nano-bots/cartridges + - ./your-state-path:/root/.local/state/nano-bots +``` + +#### Custom Project ID +If you need to manually set a Google Project ID: + +```yaml +environment: + GOOGLE_PROJECT_ID=your-project-id +``` + ### Container Enter the container: @@ -416,7 +476,7 @@ provider: model: gemini-pro ``` -#### Option 2: Service Account (Vertex AI API) +#### Option 2: Service Account Credentials File (Vertex AI API) ```yaml --- @@ -437,12 +497,48 @@ provider: credentials: service: vertex-ai-api file-path: ENV/GOOGLE_CREDENTIALS_FILE_PATH - project-id: ENV/GOOGLE_PROJECT_ID region: ENV/GOOGLE_REGION options: model: gemini-pro ``` +#### Option 3: Application Default Credentials (Vertex AI API) + +```yaml +--- +meta: + symbol: 🤖 + name: Nano Bot Name + author: Your Name + version: 1.0.0 + license: CC0-1.0 + description: A helpful assistant. + +behaviors: + interaction: + directive: You are a helpful assistant. + +provider: + id: google + credentials: + service: vertex-ai-api + region: ENV/GOOGLE_REGION + options: + model: gemini-pro +``` + +#### Custom Project ID + +If you need to manually set a Google Project ID: + +```yaml +--- +provider: + id: google + credentials: + project-id: ENV/GOOGLE_PROJECT_ID +``` + ### Tools (Functions) Nano Bots can also be powered by _Tools_ (Functions): diff --git a/components/providers/google.rb b/components/providers/google.rb index b15dd1b..a522d06 100644 --- a/components/providers/google.rb +++ b/components/providers/google.rb @@ -26,25 +26,9 @@ module NanoBot def initialize(options, settings, credentials, _environment) @settings = settings - gemini_credentials = if credentials[:'api-key'] - { - service: credentials[:service], - api_key: credentials[:'api-key'], - project_id: credentials[:'project-id'], - region: credentials[:region] - } - else - { - service: credentials[:service], - file_path: credentials[:'file-path'], - project_id: credentials[:'project-id'], - region: credentials[:region] - } - end - @client = Gemini.new( - credentials: gemini_credentials, - options: { model: options[:model], stream: options[:stream] } + credentials: credentials.transform_keys { |key| key.to_s.gsub('-', '_').to_sym }, + options: options.transform_keys { |key| key.to_s.gsub('-', '_').to_sym } ) end @@ -70,6 +54,7 @@ module NanoBot end end + # TODO: Does Gemini have system messages? %i[backdrop directive].each do |key| next unless input[:behavior][key] @@ -79,7 +64,6 @@ module NanoBot _meta: { at: Time.now } } ) - # TODO: Does Gemini have system messages? messages.prepend( { role: 'user', parts: { text: input[:behavior][key] }, @@ -140,24 +124,9 @@ module NanoBot end if event.dig('candidates', 0, 'finishReason') - if tools&.size&.positive? - feedback.call( - { should_be_stored: true, - needs_another_round: true, - interaction: { who: 'AI', message: nil, meta: { tool_calls: tools } } } - ) - Tools.apply( - cartridge, input[:tools], tools, feedback, Logic::Google::Tools - ).each do |interaction| - feedback.call({ should_be_stored: true, needs_another_round: true, interaction: }) - end - end - - feedback.call( - { should_be_stored: !(content.nil? || content == ''), - interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content }, - finished: true } - ) + # TODO: This does not have the same behavior as OpenAI, so you should + # not use it as a reference for the end of the streaming. + # Is this a bug from the Google Gemini REST API or expected behavior? end end @@ -166,6 +135,25 @@ module NanoBot Logic::Google::Tokens.apply_policies!(cartridge, payload), stream: true, &stream_call_back ) + + if tools&.size&.positive? + feedback.call( + { should_be_stored: true, + needs_another_round: true, + interaction: { who: 'AI', message: nil, meta: { tool_calls: tools } } } + ) + Tools.apply( + cartridge, input[:tools], tools, feedback, Logic::Google::Tools + ).each do |interaction| + feedback.call({ should_be_stored: true, needs_another_round: true, interaction: }) + end + end + + feedback.call( + { should_be_stored: !(content.nil? || content == ''), + interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content }, + finished: true } + ) rescue StandardError => e raise e.class, e.response[:body] if e.response && e.response[:body] diff --git a/nano-bots.gemspec b/nano-bots.gemspec index ff466aa..074cf50 100644 --- a/nano-bots.gemspec +++ b/nano-bots.gemspec @@ -34,7 +34,7 @@ Gem::Specification.new do |spec| spec.add_dependency 'babosa', '~> 2.0' spec.add_dependency 'concurrent-ruby', '~> 1.2', '>= 1.2.2' spec.add_dependency 'dotenv', '~> 2.8', '>= 2.8.1' - spec.add_dependency 'gemini-ai', '~> 2.0' + spec.add_dependency 'gemini-ai', '~> 2.1' spec.add_dependency 'pry', '~> 0.14.2' spec.add_dependency 'rainbow', '~> 3.1', '>= 3.1.1' spec.add_dependency 'rbnacl', '~> 7.1', '>= 7.1.1' diff --git a/ports/dsl/nano-bots.rb b/ports/dsl/nano-bots.rb index 29cc828..e01b2c4 100644 --- a/ports/dsl/nano-bots.rb +++ b/ports/dsl/nano-bots.rb @@ -40,4 +40,8 @@ module NanoBot def self.version NanoBot::GEM[:version] end + + def self.specification + NanoBot::GEM[:specification] + end end diff --git a/static/gem.rb b/static/gem.rb index 5541189..6b45650 100644 --- a/static/gem.rb +++ b/static/gem.rb @@ -4,6 +4,7 @@ module NanoBot GEM = { name: 'nano-bots', version: '2.0.0', + specification: '2.0.1', author: 'icebaker', summary: 'Ruby Implementation of Nano Bots: small, AI-powered bots for OpenAI ChatGPT and Google Gemini.', description: 'Ruby Implementation of Nano Bots: small, AI-powered bots that can be easily shared as a single file, designed to support multiple providers such as OpenAI ChatGPT and Google Gemini, with support for calling Tools (Functions).', |