diff options
author | icebaker <icebaker@proton.me> | 2023-11-18 19:07:10 -0300 |
---|---|---|
committer | icebaker <icebaker@proton.me> | 2023-11-18 19:07:10 -0300 |
commit | 8ae78b954350755a47a13133668dba93bac15f37 (patch) | |
tree | 9cdc3bb770d778bd8d00675fdbc1f27a6e27e37c /logic | |
parent | ab22d1bbe37093912cb7418b3c945153a15f4255 (diff) |
adding support for tools
Diffstat (limited to 'logic')
-rw-r--r-- | logic/cartridge/adapters.rb | 2 | ||||
-rw-r--r-- | logic/cartridge/affixes.rb | 2 | ||||
-rw-r--r-- | logic/cartridge/default.rb | 4 | ||||
-rw-r--r-- | logic/cartridge/fetch.rb | 24 | ||||
-rw-r--r-- | logic/cartridge/interaction.rb | 14 | ||||
-rw-r--r-- | logic/cartridge/tools.rb | 53 | ||||
-rw-r--r-- | logic/providers/openai.rb | 57 | ||||
-rw-r--r-- | logic/providers/openai/tools.rb | 70 |
8 files changed, 215 insertions, 11 deletions
diff --git a/logic/cartridge/adapters.rb b/logic/cartridge/adapters.rb index bc8ddaf..4a3fadf 100644 --- a/logic/cartridge/adapters.rb +++ b/logic/cartridge/adapters.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative '../helpers/hash' -require_relative './default' +require_relative 'default' module NanoBot module Logic diff --git a/logic/cartridge/affixes.rb b/logic/cartridge/affixes.rb index 0b40fa2..bf94d92 100644 --- a/logic/cartridge/affixes.rb +++ b/logic/cartridge/affixes.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require_relative '../helpers/hash' -require_relative './default' +require_relative 'default' module NanoBot module Logic diff --git a/logic/cartridge/default.rb b/logic/cartridge/default.rb index 43d45d4..24a8e7c 100644 --- a/logic/cartridge/default.rb +++ b/logic/cartridge/default.rb @@ -15,7 +15,7 @@ module NanoBot return @values if @values path = File.expand_path('../../static/cartridges/default.yml', __dir__) - cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol]) + cartridge = YAML.safe_load_file(path, permitted_classes: [Symbol]) @values = Logic::Helpers::Hash.symbolize_keys(cartridge) @values end @@ -24,7 +24,7 @@ module NanoBot return @baseline if @baseline path = File.expand_path('../../static/cartridges/baseline.yml', __dir__) - cartridge = YAML.safe_load(File.read(path), permitted_classes: [Symbol]) + cartridge = YAML.safe_load_file(path, permitted_classes: [Symbol]) @baseline = Logic::Helpers::Hash.symbolize_keys(cartridge) @baseline end diff --git a/logic/cartridge/fetch.rb b/logic/cartridge/fetch.rb new file mode 100644 index 0000000..2335358 --- /dev/null +++ b/logic/cartridge/fetch.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require_relative 'default' +require_relative '../helpers/hash' + +module NanoBot + module Logic + module Cartridge + module Fetch + def self.cascate(cartridge, paths) + results = paths.map { |path| Helpers::Hash.fetch(cartridge, path) } + result = results.find { |candidate| !candidate.nil? } + return result unless result.nil? + + results = paths.map { |path| Helpers::Hash.fetch(Default.instance.values, path) } + result = results.find { |candidate| !candidate.nil? } + return result unless result.nil? + + nil + end + end + end + end +end diff --git a/logic/cartridge/interaction.rb b/logic/cartridge/interaction.rb index 160d818..5e8264e 100644 --- a/logic/cartridge/interaction.rb +++ b/logic/cartridge/interaction.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true -require 'sweet-moon' - -require_relative './affixes' -require_relative './adapters' +require_relative 'affixes' +require_relative 'adapters' module NanoBot module Logic @@ -12,23 +10,25 @@ module NanoBot def self.input(cartridge, interface, content) lua = Adapter.expression(cartridge, interface, :input, :lua) fennel = Adapter.expression(cartridge, interface, :input, :fennel) + clojure = Adapter.expression(cartridge, interface, :input, :clojure) prefix = Affixes.get(cartridge, interface, :input, :prefix) suffix = Affixes.get(cartridge, interface, :input, :suffix) - { content:, prefix:, suffix:, lua:, fennel: } + { content:, prefix:, suffix:, lua:, fennel:, clojure: } end def self.output(cartridge, interface, result, streaming, _finished) if streaming - result[:message] = { content: result[:message], lua: nil, fennel: nil } + result[:message] = { content: result[:message], lua: nil, fennel: nil, clojure: nil } return result end lua = Adapter.expression(cartridge, interface, :output, :lua) fennel = Adapter.expression(cartridge, interface, :output, :fennel) + clojure = Adapter.expression(cartridge, interface, :output, :clojure) - result[:message] = { content: result[:message], lua:, fennel: } + result[:message] = { content: result[:message], lua:, fennel:, clojure: } result end diff --git a/logic/cartridge/tools.rb b/logic/cartridge/tools.rb new file mode 100644 index 0000000..6a45bf0 --- /dev/null +++ b/logic/cartridge/tools.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require_relative 'fetch' +require_relative 'affixes' +require_relative 'adapters' + +module NanoBot + module Logic + module Cartridge + module Tools + def self.fetch_from_interface(cartridge, interface, action, path) + Fetch.cascate(cartridge, [ + [:interfaces, interface, :tools, action].concat(path), + [:interfaces, :tools, action].concat(path), + %i[interfaces tools].concat(path) + ]) + end + + def self.feedback?(cartridge, interface, action) + Fetch.cascate(cartridge, [ + [:interfaces, interface, :tools, action, :feedback], + [:interfaces, :tools, action, :feedback], + %i[interfaces tools feedback] + ]) + end + + def self.input(cartridge, interface, content) + lua = Adapter.expression(cartridge, interface, :input, :lua) + fennel = Adapter.expression(cartridge, interface, :input, :fennel) + + prefix = Affixes.get(cartridge, interface, :input, :prefix) + suffix = Affixes.get(cartridge, interface, :input, :suffix) + + { content:, prefix:, suffix:, lua:, fennel: } + end + + def self.output(cartridge, interface, result, streaming, _finished) + if streaming + result[:message] = { content: result[:message], lua: nil, fennel: nil } + return result + end + + lua = Adapter.expression(cartridge, interface, :output, :lua) + fennel = Adapter.expression(cartridge, interface, :output, :fennel) + + result[:message] = { content: result[:message], lua:, fennel: } + + result + end + end + end + end +end diff --git a/logic/providers/openai.rb b/logic/providers/openai.rb new file mode 100644 index 0000000..00e7a43 --- /dev/null +++ b/logic/providers/openai.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'json' + +module NanoBot + module Logic + module OpenAI + def self.prepare_tools(cartridge, tools) + applies = [] + tools.each do |tool| + cartridge.each do |candidate| + next unless candidate[:type] == 'function' && + tool[:type] == candidate[:type] && + tool[:function][:name] == candidate[:name] + + source = {} + + source[:fennel] = candidate[:fennel] if candidate[:fennel] + source[:lua] = candidate[:lua] if candidate[:lua] + + applies << { + name: tool[:function][:name], + type: candidate[:type], + parameters: JSON.parse(tool[:function][:arguments]), + source: + } + end + end + + applies + end + + def self.adapt_tool(cartridge) + raise 'unsupported tool' if cartridge[:type] != 'function' + + adapted = { + type: 'function', + function: { + name: cartridge[:name], description: cartridge[:description], + parameters: { type: 'object', properties: {} } + } + } + + properties = adapted[:function][:parameters][:properties] + + cartridge[:parameters].each do |parameter| + key = parameter[:name].to_sym + properties[key] = {} + properties[key][:type] = parameter[:type] || 'string' + properties[key][:description] = parameter[:description] if parameter[:description] + end + + adapted + end + end + end +end diff --git a/logic/providers/openai/tools.rb b/logic/providers/openai/tools.rb new file mode 100644 index 0000000..080d81e --- /dev/null +++ b/logic/providers/openai/tools.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'json' + +require_relative '../../helpers/hash' + +module NanoBot + module Logic + module OpenAI + module Tools + def self.prepare(cartridge, tools) + applies = [] + tools.each do |tool| + # TODO: Does this mutate the hash? + tool = Helpers::Hash.symbolize_keys(tool) + + cartridge.each do |candidate| + next unless ( + candidate[:type].nil? || + (candidate[:type] == 'function' && tool[:type] == candidate[:type]) + ) && tool[:function][:name] == candidate[:name] + + source = {} + + source[:clojure] = candidate[:clojure] if candidate[:clojure] + source[:fennel] = candidate[:fennel] if candidate[:fennel] + source[:lua] = candidate[:lua] if candidate[:lua] + + applies << { + id: tool[:id], + name: tool[:function][:name], + type: candidate[:type] || 'function', + parameters: JSON.parse(tool[:function][:arguments]), + source: + } + end + end + + applies + end + + def self.adapt(cartridge) + raise 'unsupported tool' if cartridge[:type] != 'function' && !cartridge[:type].nil? + + adapted = { + type: cartridge[:type] || 'function', + function: { + name: cartridge[:name], description: cartridge[:description], + parameters: { type: 'object', properties: {} } + } + } + + properties = adapted[:function][:parameters][:properties] + + adapted[:function][:parameters][:required] = cartridge[:required] if cartridge[:required] + + cartridge[:parameters]&.each do |parameter| + key = parameter[:name].to_sym + properties[key] = {} + properties[key][:type] = parameter[:type] || 'string' + properties[key][:description] = parameter[:description] if parameter[:description] + properties[key][:items] = parameter[:items].slice(:type) if parameter[:items] + end + + adapted + end + end + end + end +end |