Skip to content

Instantly share code, notes, and snippets.

@swerner
Created February 19, 2024 21:00
Show Gist options
  • Save swerner/12de9a52b687385233e7e3bb0341a40b to your computer and use it in GitHub Desktop.
Save swerner/12de9a52b687385233e7e3bb0341a40b to your computer and use it in GitHub Desktop.
require_relative "synonllm"
class FileHandler
include Synonllm
def open_file(filename)
puts "open_file called with #{filename}"
end
def read_file(filename)
puts "read_file called with #{filename}"
end
end
require_relative "file_handler"
f = FileHandler.new
f.access_file("test_file_with_access_file.rb")
f.load_file("test_file_with_load_file.rb")
f.fetch_contents("test_file_with_fetch_contents.rb")
f.load_contents("test_file_with_load_contents.rb")
f.openFile("test_file_with_camel_case_instead_of_snake_case.rb")
require "openai"
require "pry"
module Synonllm
def method_missing(method_name, *args, &block)
synonym_method_name = find_synonym(method_name, args, self.class.source_file_contents, self.methods - Object.methods - [:method_missing, :respond_to_missing?])
self.send(synonym_method_name.to_sym, *args) if synonym_method_name != 'none'
end
def self.included(base)
base.instance_variable_set(:@source_file, caller_locations.first.path)
base.extend ClassMethods
end
module ClassMethods
def source_file_contents
File.read(@source_file) if @source_file
end
end
def respond_to_missing?(method_name, include_private = false)
true
end
private
def find_synonym(method_name, args, file_contents, available_methods)
client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"])
response = client.chat(
parameters: {
model: "gpt-4-turbo-preview",
messages: [
{
"role": "user",
"content": "You are an expert ruby programmer.
A class whose implementation is: #{file_contents} just has a method called on it of: #{method_name} but that method doesn't exist on the class with args of: #{args}
The available methods on the class are: #{available_methods.join(", ")}
Given what you know about the class, either return the symbol of the method that is likely to be a synonym of the method the user tried to call or 'none' if there isn't a reasonable synonym.
Take a deep breath and think step by step before answering.
"
}
],
function_call: {name: "method_to_call"},
functions: [
{
name: "method_to_call",
description: "The name of the method to call that we will convert into a symbol",
parameters: {
type: "object",
properties: {
method_symbol: {
type: :string,
enum: available_methods.map(&:to_s) << "none",
description: "The name of the method to call for us to turn into a symbol or 'none'"
}
},
required: ["method_symbol"]
}
}
]
}
)
message = response.dig("choices", 0, "message")
if message["role"] == "assistant" && message["function_call"]
function_name = message.dig("function_call", "method_to_call")
args = JSON.parse(
message.dig("function_call", "arguments"), { symbolize_names: true }
)
return args[:method_symbol]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment