Skip to content

Commit

Permalink
Merge pull request #19 from sergiobayona/custom_function_naming
Browse files Browse the repository at this point in the history
make the function name and description easier to customize
  • Loading branch information
sergiobayona authored May 15, 2024
2 parents 59455d7 + 93e43b6 commit 1902ca9
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
14 changes: 12 additions & 2 deletions lib/instructor/openai/patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,29 @@ def build_function(model)
{
type: 'function',
function: {
name: model.name.humanize.titleize,
name: generate_function_name(model),
description: generate_description(model),
parameters: model.json_schema
}
}
end

def generate_function_name(model)
model.schema.fetch(:title, model.name)
end

# Generates the description for the function.
#
# @param model [Class] The response model class.
# @return [String] The generated description.
def generate_description(model)
"Correctly extracted `#{model.name}` with all the required parameters with correct types"
if model.respond_to?(:instructions)
raise Instructor::Error, 'The instructions must be a string' unless model.instructions.is_a?(String)

model.instructions
else
"Correctly extracted `#{model.name}` with all the required parameters with correct types"
end
end

# Checks if the response is iterable.
Expand Down
51 changes: 49 additions & 2 deletions spec/openai/patch_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ def self.name
'User'
end

def self.instructions
"Extract the user's name and age."
end

define_schema do
title 'SomeUser'
property :name, String
property :age, Integer
end
Expand All @@ -24,19 +29,39 @@ def self.name
expect(patched_client).to eq(OpenAI::Client)
end

context 'when generating description' do
let(:client) { patched_client.new }

it "returns the model's instructions" do
expect(client.generate_description(user_model)).to eq("Extract the user's name and age.")
end

it 'returns the default description when the model does not have instructions' do
model = Class.new do
include EasyTalk::Model

def self.name
'User'
end

define_schema {}
end

expect(client.generate_description(model)).to eq('Correctly extracted `User` with all the required parameters with correct types')
end
end

context 'with a new instance of the patched client' do
it 'returns an instance of the patched client' do
expect(patched_client.new).to be_an_instance_of(OpenAI::Client)
end

pending 'receives the chat method with the expected arguments' do
client = patched_client.new
client.chat(parameters: {}, response_model: nil)
expect(client).to have_received(:chat).with(parameters: {}, response_model: nil)
end

it 'does not require the response model argument' do
client = patched_client.new
expect { client.chat(parameters: {}) }.not_to raise_error(ArgumentError)
end

Expand All @@ -45,6 +70,28 @@ def self.name
expect { client.chat }.to raise_error(ArgumentError, 'missing keyword: :parameters')
end

describe 'when setting the function_name' do
it 'returns the function_name based on the schema title' do
client = patched_client.new
expect(client.generate_function_name(user_model)).to eq('SomeUser')
end

it 'returns the class name when the schema title is not defined' do
model = Class.new do
include EasyTalk::Model

def self.name
'User'
end

define_schema {}
end

client = patched_client.new
expect(client.generate_function_name(model)).to eq('User')
end
end

it 'returns an object with the expected valid attribute values', vcr: 'patching_spec/valid_response' do
client = patched_client.new

Expand Down

0 comments on commit 1902ca9

Please sign in to comment.