From f58fa7264ea93a5d27c7c55121862fe3be80e767 Mon Sep 17 00:00:00 2001 From: Ryan Voots Date: Wed, 22 Nov 2023 18:11:52 -0500 Subject: [PATCH] Starting embeddings --- lib/OpenAIAsync/Client.pm | 23 +++++++++------ lib/OpenAIAsync/Types/Requests.pm | 4 +-- lib/OpenAIAsync/Types/Results.pm | 14 ++++----- xt/02-chat-completion.t | 49 ------------------------------- xtest.sh | 2 +- 5 files changed, 24 insertions(+), 68 deletions(-) delete mode 100644 xt/02-chat-completion.t diff --git a/lib/OpenAIAsync/Client.pm b/lib/OpenAIAsync/Client.pm index 180caeb..524703a 100644 --- a/lib/OpenAIAsync/Client.pm +++ b/lib/OpenAIAsync/Client.pm @@ -75,9 +75,6 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) :strict(params) async method _make_request($endpoint, $data) { my $json = $_json->encode($data); - use Data::Dumper; - print Dumper($json); - my $url = URI->new($api_base . $endpoint ); my $result = await $http->do_request( @@ -117,9 +114,7 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) :strict(params) die "Unsupported input type [".ref($input)."]"; } - print "Making request\n"; - - my $data = await $self->_make_request("/completions", $input); + my $data = await $self->_make_request($input->_endpoint(), $input); my $type_result = OpenAIAsync::Types::Results::Completion->new($data->%*); @@ -135,9 +130,7 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) :strict(params) die "Unsupported input type [".ref($input)."]"; } - print "Making request\n"; - - my $data = await $self->_make_request("/completions", $input); + my $data = await $self->_make_request($input->_endpoint(), $input); my $type_result = OpenAIAsync::Types::Results::ChatCompletion->new($data->%*); @@ -146,7 +139,19 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) :strict(params) } async method embedding($input) { + if (ref($input) eq 'HASH') { + $input = OpenAIAsync::Types::Requests::Embedding->new($input->%*); + } elsif (ref($input) eq 'OpenAIAsync::Types::Requests::Embedding') { + # dummy, nothing to do + } else { + die "Unsupported input type [".ref($input)."]"; + } + my $data = await $self->_make_request($input->_endpoint(), $input); + + my $type_result = OpenAIAsync::Types::Results::Embedding->new($data->%*); + + return $type_result; } async method image_generate($input) { diff --git a/lib/OpenAIAsync/Types/Requests.pm b/lib/OpenAIAsync/Types/Requests.pm index 09cdb5f..157060c 100644 --- a/lib/OpenAIAsync/Types/Requests.pm +++ b/lib/OpenAIAsync/Types/Requests.pm @@ -14,7 +14,7 @@ role OpenAIAsync::Types::Requests::Base :does(OpenAIAsync::Types::Base) :Struct #### Base Request Types class OpenAIAsync::Types::Requests::ChatCompletion :does(OpenAIAsync::Types::Requests::Base) :Struct { - method _endpoint() {"/chat/completion"} + method _endpoint() {"/chat/completions"} field $messages :MarshalTo([OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union]); field $model :JSONStr = "gpt-3.5-turbo"; field $frequency_penalty :JSONNum = undef; @@ -36,7 +36,7 @@ class OpenAIAsync::Types::Requests::ChatCompletion :does(OpenAIAsync::Types::Req } class OpenAIAsync::Types::Requests::Completion :does(OpenAIAsync::Types::Requests::Base) :Struct { - method _endpoint() {"/completion"} + method _endpoint() {"/completions"} field $model :JSONStr = "gpt-3.5-turbo"; # This is how 99% of everyone else seems to default this field $prompt :JSONStr; diff --git a/lib/OpenAIAsync/Types/Results.pm b/lib/OpenAIAsync/Types/Results.pm index 075feb3..9d45e57 100644 --- a/lib/OpenAIAsync/Types/Results.pm +++ b/lib/OpenAIAsync/Types/Results.pm @@ -8,14 +8,14 @@ use Object::PadX::Role::AutoJSON; use Object::Pad::ClassAttr::Struct; class OpenAIAsync::Types::Results::ToolCall :does(OpenAIAsync::Types::Base) :Struct { - field $id :JSONStr; - field $type :JSONStr; # always "function" right now, may get expanded in the future - field $function :MarshalTo(OpenAIAsync::Types::Results::FunctionCall); + field $id :JSONStr = undef; + field $type :JSONStr = undef; # always "function" right now, may get expanded in the future + field $function :MarshalTo(OpenAIAsync::Types::Results::FunctionCall) = undef; } class OpenAIAsync::Types::Results::FunctionCall :does(OpenAIAsync::Types::Base) :Struct { - field $arguments :JSONStr; # TODO decode the json from this directly? - field $name :JSONStr; + field $arguments :JSONStr = undef; # TODO decode the json from this directly? + field $name :JSONStr = undef; } class OpenAIAsync::Types::Results::ChatMessage :does(OpenAIAsync::Types::Base) :Struct { @@ -43,8 +43,8 @@ class OpenAIAsync::Types::Results::ChatCompletion :does(OpenAIAsync::Types::Base class OpenAIAsync::Types::Results::ChunkDelta :does(OpenAIAsync::Types::Base) :Struct { field $content :JSONStr; - field $function_call :MarshalTo(OpenAIAsync::Types::Results::FunctionCall); - field $tool_cass :MarshalTo([OpenAIAsync::Types::Results::ToolCall]); + field $function_call :MarshalTo(OpenAIAsync::Types::Results::FunctionCall) = undef; + field $tool_cass :MarshalTo([OpenAIAsync::Types::Results::ToolCall]) = undef; field $role :JSONStr; } diff --git a/xt/02-chat-completion.t b/xt/02-chat-completion.t deleted file mode 100644 index 53a97c6..0000000 --- a/xt/02-chat-completion.t +++ /dev/null @@ -1,49 +0,0 @@ -use strict; -use warnings; - -use Test2::V0; - -use OpenAIAsync::Client; - -skip_all("Needs disclaimer to run") unless $ENV{I_PROMISE_NOT_TO_SUE_FOR_EXCESSIVE_COSTS} eq "Signed, ".getlogin(); - -skip_all("No api base defined") unless $ENV{OPENAI_API_BASE}; -skip_all("No API key defined") unless $ENV{OPENAI_API_KEY}; - -exit() unless ($ENV{OPENAI_API_KEY} and $ENV{OPENAI_API_BASE} and $ENV{I_PROMISE_NOT_TO_SUE_FOR_EXCESSIVE_COSTS} eq "Signed, ".getlogin()); - -use IO::Async::Loop; - -my $loop = IO::Async::Loop->new(); - -my $client; -ok(lives { - $client = OpenAIAsync::Client->new(); - - isa_ok($client, "OpenAIAsync::Client"); -}, "basic client creation"); - -ok(lives {$loop->add($client);}, "Adding to loop"); - -my $output_future = $client->chat({ - model => "gpt-3.5-turbo", - messages => [ - { - role => "system", - content => "You are a helpful assistant that tells fanciful stories" - }, - { - role => "user", - content => "Hello!" - } - ], - - - - max_tokens => 1024, -}); - -use Data::Dumper; -print Dumper($output_future->get()); - -done_testing(); \ No newline at end of file diff --git a/xtest.sh b/xtest.sh index 58cf5f1..fbf6d9f 100755 --- a/xtest.sh +++ b/xtest.sh @@ -8,4 +8,4 @@ export I_PROMISE_NOT_TO_SUE_FOR_EXCESSIVE_COSTS="Signed, ryan" #dzil xtest -perl -Ilib xt/02-chat-completion.t +perl -Ilib xt/03-embeddings.t