diff options
author | icebaker <113217272+icebaker@users.noreply.github.com> | 2023-12-28 21:01:33 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-28 21:01:33 -0300 |
commit | 8b7b90c9601eb3d73ae443142aab2c9d8168cb62 (patch) | |
tree | 540270080c6cc6d61b6c2f81e9b70c81f0e60f28 | |
parent | 347ac029c922fbb3843ec22324527f2c6b3ba9a9 (diff) | |
parent | 94d7aa2b726a09abfac85f472eef8921d14c16a9 (diff) |
Merge pull request #12 from icebaker/ib-mistral-ai
Adding support for Mistral AI and upgrading gemini-ai
-rw-r--r-- | Gemfile.lock | 14 | ||||
-rw-r--r-- | README.md | 327 | ||||
-rw-r--r-- | components/provider.rb | 5 | ||||
-rw-r--r-- | components/providers/google.rb | 21 | ||||
-rw-r--r-- | components/providers/mistral.rb | 115 | ||||
-rw-r--r-- | controllers/session.rb | 1 | ||||
-rw-r--r-- | logic/cartridge/streaming.rb | 2 | ||||
-rw-r--r-- | logic/providers/google/tokens.rb | 2 | ||||
-rw-r--r-- | logic/providers/mistral/tokens.rb | 14 | ||||
-rw-r--r-- | logic/providers/openai/tokens.rb | 2 | ||||
-rw-r--r-- | nano-bots.gemspec | 3 | ||||
-rw-r--r-- | spec/logic/cartridge/interaction_spec.rb | 2 | ||||
-rw-r--r-- | static/gem.rb | 8 |
13 files changed, 367 insertions, 149 deletions
diff --git a/Gemfile.lock b/Gemfile.lock index be466f6..3355970 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,11 +1,12 @@ PATH remote: . specs: - nano-bots (2.2.0) + nano-bots (2.3.0) babosa (~> 2.0) concurrent-ruby (~> 1.2, >= 1.2.2) dotenv (~> 2.8, >= 2.8.1) - gemini-ai (~> 2.2) + gemini-ai (~> 3.1) + mistral-ai (~> 1.0) pry (~> 0.14.2) rainbow (~> 3.1, >= 3.1.1) rbnacl (~> 7.1, >= 7.1.1) @@ -26,7 +27,7 @@ GEM diff-lcs (1.5.0) dotenv (2.8.1) event_stream_parser (1.0.0) - faraday (2.7.12) + faraday (2.8.1) base64 faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) @@ -34,9 +35,9 @@ GEM multipart-post (~> 2) faraday-net_http (3.0.2) ffi (1.16.3) - gemini-ai (2.2.0) + gemini-ai (3.1.0) event_stream_parser (~> 1.0) - faraday (~> 2.7, >= 2.7.12) + faraday (~> 2.8, >= 2.8.1) googleauth (~> 1.9, >= 1.9.1) google-cloud-env (2.1.0) faraday (>= 1.0, < 3.a) @@ -51,6 +52,9 @@ GEM jwt (2.7.1) language_server-protocol (3.17.0.3) method_source (1.0.0) + mistral-ai (1.0.0) + event_stream_parser (~> 1.0) + faraday (~> 2.8, >= 2.8.1) multi_json (1.15.0) multipart-post (2.3.0) os (1.1.4) @@ -1,27 +1,29 @@ # Nano Bots 💎 🤖 -A Ruby implementation of the [Nano Bots](https://github.com/icebaker/nano-bots) specification. +A Ruby implementation of the [Nano Bots](https://github.com/icebaker/nano-bots) specification with support for [OpenAI ChatGPT](https://openai.com/chatgpt), [Mistral AI](https://mistral.ai), and [Google Gemini](https://deepmind.google/technologies/gemini). -![Ruby Nano Bots](https://user-images.githubusercontent.com/113217272/237839690-7880915a-b287-4484-a75e-0b96284b8a32.png) -_Image artificially created by Midjourney through a prompt generated by a Nano Bot specialized in Midjourney._ +![Ruby Nano Bots](https://raw.githubusercontent.com/icebaker/assets/main/nano-bots/ruby-nano-bots-canvas.png) https://user-images.githubusercontent.com/113217272/238141567-c58a240c-7b67-4b3b-864a-0f49bbf6e22f.mp4 - [Setup](#setup) - [OpenAI ChatGPT](#openai-chatgpt) + - [Mistral AI](#mistral-ai) - [Google Gemini](#google-gemini) - - [Docker](#docker) - - [OpenAI ChatGPT](#openai-chatgpt-1) - - [Google Gemini](#google-gemini-1) - [Usage](#usage) - [Command Line](#command-line) - [Library](#library) - [Cartridges](#cartridges) - - [OpenAI ChatGPT](#openai-chatgpt-2) - - [Google Gemini](#google-gemini-2) + - [OpenAI ChatGPT](#openai-chatgpt-1) + - [Mistral AI](#mistral-ai-1) + - [Google Gemini](#google-gemini-1) - [Tools (Functions)](#tools-functions) - [Experimental Clojure Support](#experimental-clojure-support) - [Marketplace](#marketplace) +- [Docker](#docker) + - [OpenAI ChatGPT](#openai-chatgpt-1) + - [Mistral AI](#mistral-ai-1) + - [Google Gemini](#google-gemini-1) - [Security and Privacy](#security-and-privacy) - [Cryptography](#cryptography) - [End-user IDs](#end-user-ids) @@ -51,12 +53,7 @@ bundle install 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: -### OpenAI ChatGPT - ```sh -export OPENAI_API_ADDRESS=https://api.openai.com -export OPENAI_API_KEY=your-access-token - export NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE export NANO_BOTS_END_USER=your-user @@ -67,9 +64,6 @@ export NANO_BOTS_END_USER=your-user 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_KEY=your-access-token - NANO_BOTS_ENCRYPTION_PASSWORD=UNSAFE NANO_BOTS_END_USER=your-user @@ -77,6 +71,38 @@ NANO_BOTS_END_USER=your-user # NANO_BOTS_CARTRIDGES_DIRECTORY=/home/user/.local/share/nano-bots/cartridges ``` +### OpenAI ChatGPT + +You can obtain your credentials on the [OpenAI Platform](https://platform.openai.com). + +```sh +export OPENAI_API_ADDRESS=https://api.openai.com +export OPENAI_API_KEY=your-access-token +``` + +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_KEY=your-access-token +``` + +### Mistral AI + +You can obtain your credentials on the [Mistral Platform](https://console.mistral.ai). + +```sh +export MISTRAL_API_ADDRESS=https://api.mistral.ai +export MISTRAL_API_KEY=your-api-key +``` + +Alternatively, if your current directory has a `.env` file with the environment variables, they will be automatically loaded: + +```sh +MISTRAL_API_ADDRESS=https://api.mistral.ai +MISTRAL_API_KEY=your-api-key +``` + ### Google Gemini Click [here](https://github.com/gbaptista/gemini-ai#credentials) to learn how to obtain your credentials. @@ -169,117 +195,6 @@ Alternatively, if your current directory has a `.env` file with the environment GOOGLE_PROJECT_ID=your-project-id ``` -## Docker - -Clone the repository and copy the Docker Compose template: - -``` -git clone https://github.com/icebaker/ruby-nano-bots.git -cd ruby-nano-bots -cp docker-compose.example.yml docker-compose.yml -``` - -Set your provider credentials and choose your desired directory for the cartridges files: - -### OpenAI ChatGPT - -```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.2.0 && bash" - environment: - OPENAI_API_ADDRESS: https://api.openai.com - OPENAI_API_KEY: your-access-token - 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 -``` - -### Google Gemini - -#### Option 1: API Key (Generative Language 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.2.0 && bash" - environment: - GOOGLE_API_KEY: your-api-key - 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 -``` - -#### Option 2: Service Account Credentials File (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.2.0 && bash" - environment: - GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json - GOOGLE_REGION: us-east4 - NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE - NANO_BOTS_END_USER: your-user - volumes: - - ./google-credentials.json:/root/.config/google-credentials.json - - ./your-cartridges:/root/.local/share/nano-bots/cartridges - - ./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.2.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: -```sh -docker compose run nano-bots -``` - -Start playing: -```sh -nb - - eval "hello" -nb - - repl - -nb assistant.yml - eval "hello" -nb assistant.yml - repl -``` - -You can exit the REPL by typing `exit`. - ## Usage ### Command Line @@ -447,6 +362,32 @@ provider: model: gpt-4-1106-preview ``` +### Mistral AI + +Read the [full specification](https://spec.nbots.io/#/README?id=mistral-ai) for Mistral AI. + +```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: mistral + credentials: + api-key: ENV/MISTRAL_API_KEY + settings: + model: mistral-medium +``` + ### Google Gemini Read the [full specification](https://spec.nbots.io/#/README?id=google-gemini) for Google Gemini. @@ -564,7 +505,7 @@ The randomly generated number is 59. 🤖> | ``` -To successfully use Tools (Functions), you need to specify a provider and a model that supports them. As of the writing of this README, the provider that supports them is [OpenAI](https://platform.openai.com/docs/models), with models `gpt-3.5-turbo-1106` and `gpt-4-1106-preview`, and [Google](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling#supported_models), with the `vertex-ai-api` service and the model `gemini-pro`. +To successfully use Tools (Functions), you need to specify a provider and a model that supports them. As of the writing of this README, the provider that supports them is [OpenAI](https://platform.openai.com/docs/models), with models `gpt-3.5-turbo-1106` and `gpt-4-1106-preview`, and [Google](https://cloud.google.com/vertex-ai/docs/generative-ai/multimodal/function-calling#supported_models), with the `vertex-ai-api` service and the model `gemini-pro`. Mistral AI does not support tools. Check the [Nano Bots specification](https://spec.nbots.io/#/README?id=tools-functions-2) to learn more about Tools (Functions). @@ -609,6 +550,135 @@ safety: You can explore the Nano Bots [Marketplace](https://nbots.io) to discover new Cartridges that can help you. +## Docker + +Clone the repository and copy the Docker Compose template: + +``` +git clone https://github.com/icebaker/ruby-nano-bots.git +cd ruby-nano-bots +cp docker-compose.example.yml docker-compose.yml +``` + +Set your provider credentials and choose your desired directory for the cartridges files: + +### OpenAI ChatGPT + +```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.2.0 && bash" + environment: + OPENAI_API_ADDRESS: https://api.openai.com + OPENAI_API_KEY: your-access-token + 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 +``` + +### Mistral AI + +```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.2.0 && bash" + environment: + MISTRAL_API_ADDRESS: https://api.mistral.ai + MISTRAL_API_KEY: your-api-key + 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 +``` + +### Google Gemini + +#### Option 1: API Key (Generative Language 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.2.0 && bash" + environment: + GOOGLE_API_KEY: your-api-key + 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 +``` + +#### Option 2: Service Account Credentials File (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.2.0 && bash" + environment: + GOOGLE_CREDENTIALS_FILE_PATH: /root/.config/google-credentials.json + GOOGLE_REGION: us-east4 + NANO_BOTS_ENCRYPTION_PASSWORD: UNSAFE + NANO_BOTS_END_USER: your-user + volumes: + - ./google-credentials.json:/root/.config/google-credentials.json + - ./your-cartridges:/root/.local/share/nano-bots/cartridges + - ./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.2.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: +```sh +docker compose run nano-bots +``` + +Start playing: +```sh +nb - - eval "hello" +nb - - repl + +nb assistant.yml - eval "hello" +nb assistant.yml - repl +``` + +You can exit the REPL by typing `exit`. + ## Security and Privacy Each provider will have its own security and privacy policies (e.g. [OpenAI Policy](https://openai.com/policies/api-data-usage-policies)), so you must consult them to understand their implications. @@ -720,6 +790,7 @@ If you lose your password, you lose your data. It is not possible to recover it Currently supported providers: - [x] [Open AI ChatGPT](https://platform.openai.com/docs/api-reference) +- [x] [Mistral AI](https://docs.mistral.ai/api/) - [x] [Google Gemini](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini) - [ ] [Anthropic Claude](https://www.anthropic.com) - [ ] [Cohere Command](https://cohere.com) diff --git a/components/provider.rb b/components/provider.rb index 57f1cca..bdf3639 100644 --- a/components/provider.rb +++ b/components/provider.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true -require_relative 'providers/openai' require_relative 'providers/google' +require_relative 'providers/mistral' +require_relative 'providers/openai' module NanoBot module Components @@ -12,6 +13,8 @@ module NanoBot Providers::OpenAI.new(nil, provider[:settings], provider[:credentials], environment:) when 'google' Providers::Google.new(provider[:options], provider[:settings], provider[:credentials], environment:) + when 'mistral' + Providers::Mistral.new(provider[:options], provider[:settings], provider[:credentials], environment:) else raise "Unsupported provider \"#{provider[:id]}\"" end diff --git a/components/providers/google.rb b/components/providers/google.rb index 25ffbde..3976e2c 100644 --- a/components/providers/google.rb +++ b/components/providers/google.rb @@ -6,6 +6,8 @@ require_relative 'base' require_relative '../../logic/providers/google/tools' require_relative '../../logic/providers/google/tokens' +require_relative '../../logic/helpers/hash' +require_relative '../../logic/cartridge/default' require_relative 'tools' @@ -26,9 +28,19 @@ module NanoBot def initialize(options, settings, credentials, _environment) @settings = settings + gemini_options = options.transform_keys { |key| key.to_s.gsub('-', '_').to_sym } + + unless gemini_options.key?(:stream) + gemini_options[:stream] = Logic::Helpers::Hash.fetch( + Logic::Cartridge::Default.instance.values, %i[provider settings stream] + ) + end + + gemini_options[:server_sent_events] = gemini_options.delete(:stream) + @client = Gemini.new( credentials: credentials.transform_keys { |key| key.to_s.gsub('-', '_').to_sym }, - options: options.transform_keys { |key| key.to_s.gsub('-', '_').to_sym } + options: gemini_options ) end @@ -105,6 +117,9 @@ module NanoBot tools = [] stream_call_back = proc do |event, _parsed, _raw| + # TODO: How to better handle finishReason == 'OTHER'? + return if event.dig('candidates', 0, 'finishReason') == 'OTHER' + partial_content = event.dig('candidates', 0, 'content', 'parts').filter do |part| part.key?('text') end.map { |part| part['text'] }.join @@ -132,7 +147,7 @@ module NanoBot @client.stream_generate_content( Logic::Google::Tokens.apply_policies!(cartridge, payload), - stream: true, &stream_call_back + server_sent_events: true, &stream_call_back ) if tools&.size&.positive? @@ -156,7 +171,7 @@ module NanoBot else result = @client.stream_generate_content( Logic::Google::Tokens.apply_policies!(cartridge, payload), - stream: false + server_sent_events: false ) tools = result.dig(0, 'candidates', 0, 'content', 'parts').filter do |part| diff --git a/components/providers/mistral.rb b/components/providers/mistral.rb new file mode 100644 index 0000000..9b5c6c4 --- /dev/null +++ b/components/providers/mistral.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require 'mistral-ai' + +require_relative 'base' + +require_relative '../../logic/providers/mistral/tokens' +require_relative '../../logic/helpers/hash' +require_relative '../../logic/cartridge/default' + +module NanoBot + module Components + module Providers + class Mistral < Base + attr_reader :settings + + CHAT_SETTINGS = %i[ + model temperature top_p max_tokens stream safe_mode random_seed + ].freeze + + def initialize(options, settings, credentials, _environment) + @settings = settings + + mistral_options = if options + options.transform_keys { |key| key.to_s.gsub('-', '_').to_sym } + else + {} + end + + unless @settings.key?(:stream) + @settings = Marshal.load(Marshal.dump(@settings)) + @settings[:stream] = Logic::Helpers::Hash.fetch( + Logic::Cartridge::Default.instance.values, %i[provider settings stream] + ) + end + + mistral_options[:server_sent_events] = @settings[:stream] + + @client = ::Mistral.new( + credentials: credentials.transform_keys { |key| key.to_s.gsub('-', '_').to_sym }, + options: mistral_options + ) + end + + def evaluate(input, streaming, cartridge, &feedback) + messages = input[:history].map do |event| + { role: event[:who] == 'user' ? 'user' : 'assistant', + content: event[:message], + _meta: { at: event[:at] } } + end + + %i[backdrop directive].each do |key| + next unless input[:behavior][key] + + messages.prepend( + { role: key == :directive ? 'system' : 'user', + content: input[:behavior][key], + _meta: { at: Time.now } } + ) + end + + payload = { messages: } + + CHAT_SETTINGS.each do |key| + payload[key] = @settings[key] unless payload.key?(key) || !@settings.key?(key) + end + + raise 'Mistral does not support tools.' if input[:tools] + + if streaming + content = '' + + stream_call_back = proc do |event, _parsed, _raw| + partial_content = event.dig('choices', 0, 'delta', 'content') + + if partial_content + content += partial_content + feedback.call( + { should_be_stored: false, + interaction: { who: 'AI', message: partial_content } } + ) + end + + if event.dig('choices', 0, 'finish_reason') + feedback.call( + { should_be_stored: !(content.nil? || content == ''), + interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content }, + finished: true } + ) + end + end + + @client.chat_completions( + Logic::Mistral::Tokens.apply_policies!(cartridge, payload), + server_sent_events: true, &stream_call_back + ) + else + result = @client.chat_completions( + Logic::Mistral::Tokens.apply_policies!(cartridge, payload), + server_sent_events: false + ) + + content = result.dig('choices', 0, 'message', 'content') + + feedback.call( + { should_be_stored: !(content.nil? || content.to_s.strip == ''), + interaction: content.nil? || content == '' ? nil : { who: 'AI', message: content }, + finished: true } + ) + end + end + end + end + end +end diff --git a/controllers/session.rb b/controllers/session.rb index e12ab86..dd89d6b 100644 --- a/controllers/session.rb +++ b/controllers/session.rb @@ -138,7 +138,6 @@ module NanoBot feedback[:interaction][:meta][:tool][:action] == 'confirming' Interfaces::Tool.confirming(self, @cartridge, mode, feedback[:interaction][:meta][:tool]) else - if feedback[:interaction] && feedback.dig(:interaction, :meta, :tool, :action) Interfaces::Tool.dispatch_feedback( self, @cartridge, mode, feedback[:interaction][:meta][:tool] diff --git a/logic/cartridge/streaming.rb b/logic/cartridge/streaming.rb index 6949b3a..0b9b19f 100644 --- a/logic/cartridge/streaming.rb +++ b/logic/cartridge/streaming.rb @@ -8,7 +8,7 @@ module NanoBot module Streaming def self.enabled?(cartridge, interface) provider_stream = case Helpers::Hash.fetch(cartridge, %i[provider id]) - when 'openai' + when 'openai', 'mistral' Helpers::Hash.fetch(cartridge, %i[provider settings stream]) when 'google' Helpers::Hash.fetch(cartridge, %i[provider options stream]) diff --git a/logic/providers/google/tokens.rb b/logic/providers/google/tokens.rb index 3d5492f..0d74928 100644 --- a/logic/providers/google/tokens.rb +++ b/logic/providers/google/tokens.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'openai' - module NanoBot module Logic module Google diff --git a/logic/providers/mistral/tokens.rb b/logic/providers/mistral/tokens.rb new file mode 100644 index 0000000..7aa64b7 --- /dev/null +++ b/logic/providers/mistral/tokens.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module NanoBot + module Logic + module Mistral + module Tokens + def self.apply_policies!(_cartridge, payload) + payload[:messages] = payload[:messages].map { |message| message.except(:_meta) } + payload + end + end + end + end +end diff --git a/logic/providers/openai/tokens.rb b/logic/providers/openai/tokens.rb index 60efa60..828b774 100644 --- a/logic/providers/openai/tokens.rb +++ b/logic/providers/openai/tokens.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'openai' - module NanoBot module Logic module OpenAI diff --git a/nano-bots.gemspec b/nano-bots.gemspec index 15fc8cf..2ff38cb 100644 --- a/nano-bots.gemspec +++ b/nano-bots.gemspec @@ -34,7 +34,8 @@ 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.2' + spec.add_dependency 'gemini-ai', '~> 3.1' + spec.add_dependency 'mistral-ai', '~> 1.0' 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/spec/logic/cartridge/interaction_spec.rb b/spec/logic/cartridge/interaction_spec.rb index f3ba46e..54fd956 100644 --- a/spec/logic/cartridge/interaction_spec.rb +++ b/spec/logic/cartridge/interaction_spec.rb @@ -26,7 +26,7 @@ RSpec.describe NanoBot::Logic::Cartridge::Interaction do ) end - it 'prepares the non-streamming output' do + it 'prepares the non-streaming output' do expect(described_class.output(cartridge, :repl, { message: 'hello' }, false, true)).to eq( { message: { content: 'hello', fennel: nil, lua: nil, clojure: nil } } ) diff --git a/static/gem.rb b/static/gem.rb index e9e5754..b6ce260 100644 --- a/static/gem.rb +++ b/static/gem.rb @@ -3,11 +3,11 @@ module NanoBot GEM = { name: 'nano-bots', - version: '2.2.0', - specification: '2.0.1', + version: '2.3.0', + specification: '2.1.0', 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).', + summary: 'Ruby Implementation of Nano Bots: small, AI-powered bots for OpenAI ChatGPT, Mistral AI, 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, Mistral AI, and Google Gemini, with support for calling Tools (Functions).', github: 'https://github.com/icebaker/ruby-nano-bots', gem_server: 'https://rubygems.org', license: 'MIT', |