From b8f46b0192b4c90fba76430ff0ffec6100806fdd Mon Sep 17 00:00:00 2001 From: Ryan Voots Date: Sat, 30 Dec 2023 16:36:31 -0500 Subject: [PATCH] More apis in the new format --- .vstags | 4 +- lib/OpenAIAsync/Server.pm | 5 +-- .../API/v1/{Completion.pm => Completions.pm} | 8 ++-- lib/OpenAIAsync/Server/API/v1/Embeddings.pm | 41 +++++++++++++++++++ lib/OpenAIAsync/Server/API/v1/Models.pm | 40 ++++++++++++++++++ lib/OpenAIAsync/Types/Results.pm | 14 ++++++- 6 files changed, 103 insertions(+), 9 deletions(-) rename lib/OpenAIAsync/Server/API/v1/{Completion.pm => Completions.pm} (74%) create mode 100644 lib/OpenAIAsync/Server/API/v1/Embeddings.pm create mode 100644 lib/OpenAIAsync/Server/API/v1/Models.pm diff --git a/.vstags b/.vstags index ff1ebb3..a4a5892 100644 --- a/.vstags +++ b/.vstags @@ -9896,9 +9896,11 @@ OpenAIAsync::Client .build/t7Cb8f47yj/lib/OpenAIAsync/Client.pm 1;" p OpenAIAsync::Client OpenAIAsync-0.01/lib/OpenAIAsync/Client.pm 1;" p OpenAIAsync::Client lib/OpenAIAsync/Client.pm 1;" p OpenAIAsync::Server lib/OpenAIAsync/Server.pm 1;" p +OpenAIAsync::Server::API::v1::Completions lib/OpenAIAsync/Server/API/v1/Completions.pm 1;" p +OpenAIAsync::Server::API::v1::Embeddings lib/OpenAIAsync/Server/API/v1/Embeddings.pm 1;" p OpenAIAsync::Server::API::v1::File lib/OpenAIAsync/Server/API/v1/Chat.pm 1;" p -OpenAIAsync::Server::API::v1::File lib/OpenAIAsync/Server/API/v1/Completion.pm 1;" p OpenAIAsync::Server::API::v1::File lib/OpenAIAsync/Server/API/v1/File.pm 1;" p +OpenAIAsync::Server::API::v1::ModelList lib/OpenAIAsync/Server/API/v1/Models.pm 1;" p OpenAIAsync::Types .build/0T4wbFlmwf/blib/lib/OpenAIAsync/Types.pm 1;" p OpenAIAsync::Types .build/0T4wbFlmwf/lib/OpenAIAsync/Types.pm 1;" p OpenAIAsync::Types .build/2oNz8Mp68u/blib/lib/OpenAIAsync/Types.pm 1;" p diff --git a/lib/OpenAIAsync/Server.pm b/lib/OpenAIAsync/Server.pm index 71c80aa..06cb7aa 100644 --- a/lib/OpenAIAsync/Server.pm +++ b/lib/OpenAIAsync/Server.pm @@ -233,6 +233,7 @@ class OpenAIAsync::Server :repr(HASH) :isa(IO::Async::Notifier) :strict(params) method __make_http_server($port, $listen, $ctx, %args) { # TODO args? + # TODO make this work during a reload my $server_id = sprintf("%d\0%d", $listen, $port); $ctx->{server_id} = $server_id; @@ -272,9 +273,7 @@ class OpenAIAsync::Server :repr(HASH) :isa(IO::Async::Notifier) :strict(params) push $routes->@*, \%opts; } - async method _route_request($httpserver, $req, $ctx) { - my $routers = $self->_get_routers($httpserver, $req, $ctx); - + async method _route_request($req, $ctx) { my $method = $req->method(); my $uri = URI->new($req->uri); my $path = $uri->path; diff --git a/lib/OpenAIAsync/Server/API/v1/Completion.pm b/lib/OpenAIAsync/Server/API/v1/Completions.pm similarity index 74% rename from lib/OpenAIAsync/Server/API/v1/Completion.pm rename to lib/OpenAIAsync/Server/API/v1/Completions.pm index 53ef5c9..f8eab7c 100644 --- a/lib/OpenAIAsync/Server/API/v1/Completion.pm +++ b/lib/OpenAIAsync/Server/API/v1/Completions.pm @@ -1,4 +1,4 @@ -package OpenAIAsync::Server::API::v1::File; +package OpenAIAsync::Server::API::v1::Completions; use v5.36.0; use Object::Pad; @@ -17,7 +17,7 @@ our $VERSION = '0.02'; =head1 NAME -OpenAIAsync::Server::API::Completion - Basic completion api role, consumed to implement the OpenAI chat completion api. Does not provide an implementation, you are expected to override them in your class +OpenAIAsync::Server::API::Completions - Basic completion api role, consumed to implement the OpenAI chat completion api. Does not provide an implementation, you are expected to override them in your class =head1 SYNOPSIS @@ -25,7 +25,7 @@ OpenAIAsync::Server::API::Completion - Basic completion api role, consumed to im =cut -role OpenAIAsync::Server::API::v1::Completion :strict(params) { +role OpenAIAsync::Server::API::v1::Completions :strict(params) { ADJUST { $self->register_url( method => 'POST', @@ -36,6 +36,6 @@ role OpenAIAsync::Server::API::v1::Completion :strict(params) { decoder => 'www-form-urlencoded', # default is json, we need this for this api ); } - + async method completion($obj, $http_req, $ctx) {...} } \ No newline at end of file diff --git a/lib/OpenAIAsync/Server/API/v1/Embeddings.pm b/lib/OpenAIAsync/Server/API/v1/Embeddings.pm new file mode 100644 index 0000000..c32a535 --- /dev/null +++ b/lib/OpenAIAsync/Server/API/v1/Embeddings.pm @@ -0,0 +1,41 @@ +package OpenAIAsync::Server::API::v1::Embeddings; + +use v5.36.0; +use Object::Pad; +use IO::Async::SSL; # We're not directly using it but I want to enforce that we pull it in when detecting dependencies, since openai itself is always https +use Future::AsyncAwait; +use IO::Async; + +use OpenAIAsync::Types::Results; +use OpenAIAsync::Types::Requests; + +our $VERSION = '0.02'; + +# ABSTRACT: Async server for OpenAI style REST API for various AI systems (LLMs, Images, Video, etc.) + +=pod + +=head1 NAME + +OpenAIAsync::Server::API::Embeddings - Basic embeddings api role, consumed to implement the OpenAI embeddings api. Does not provide an implementation, you are expected to override them in your class + +=head1 SYNOPSIS + +... + +=cut + +role OpenAIAsync::Server::API::v1::Embeddings :strict(params) { + ADJUST { + $self->register_url( + method => 'POST', + url => qr{^/v1/embeddings$}, + handle => async sub($req, $ctx, $obj, $params) {await $self->embeddings($obj, $req, $ctx)}, + request_class => "OpenAIAsync::Type::Request::Embeddings", + result_class => "OpenAIAsync::Type::Result::Embeddings", + decoder => 'www-form-urlencoded', # default is json, we need this for this api + ); + } + + async method embeddings($obj, $http_req, $ctx) {...} +} \ No newline at end of file diff --git a/lib/OpenAIAsync/Server/API/v1/Models.pm b/lib/OpenAIAsync/Server/API/v1/Models.pm new file mode 100644 index 0000000..26f4d75 --- /dev/null +++ b/lib/OpenAIAsync/Server/API/v1/Models.pm @@ -0,0 +1,40 @@ +package OpenAIAsync::Server::API::v1::ModelList; + +use v5.36.0; +use Object::Pad; +use IO::Async::SSL; # We're not directly using it but I want to enforce that we pull it in when detecting dependencies, since openai itself is always https +use Future::AsyncAwait; +use IO::Async; + +use OpenAIAsync::Types::Results; +use OpenAIAsync::Types::Requests; + +our $VERSION = '0.02'; + +# ABSTRACT: Async server for OpenAI style REST API for various AI systems (LLMs, Images, Video, etc.) + +=pod + +=head1 NAME + +OpenAIAsync::Server::API::ModelList - Basic model list api role, consumed to implement the OpenAI model list api. Does not provide an implementation, you are expected to override them in your class + +=head1 SYNOPSIS + +... + +=cut + +role OpenAIAsync::Server::API::v1::ModelList :strict(params) { + ADJUST { + $self->register_url( + method => 'POST', + url => qr{^/v1/models$}, + handle => async sub($req, $ctx, $obj, $params) {await $self->embeddings($obj, $req, $ctx)}, + request_class => "", + result_class => "OpenAIAsync::Type::Result::ModelList", + ); + } + + async method model_list($obj, $http_req, $ctx) {...} +} \ No newline at end of file diff --git a/lib/OpenAIAsync/Types/Results.pm b/lib/OpenAIAsync/Types/Results.pm index ad30346..ac2cc2d 100644 --- a/lib/OpenAIAsync/Types/Results.pm +++ b/lib/OpenAIAsync/Types/Results.pm @@ -107,4 +107,16 @@ class OpenAIAsync::Types::Results::EmbeddingData :does(OpenAIAsync::Types::Base) field $index :JSONNum; field $embedding :JSONList(JSONNum); field $object :JSONStr; -} \ No newline at end of file +} + +class OpenAIAsync::Types::Results::ModelList :does(OpenAIAsync::Types::Base) :Struct { + field $object :JSONStr = 'list'; + field $data :MarshalTo(OpenAIAsync::Types::Results::ModelInfo); +} + +class OpenAIAsync::Types::Results::ModelInfo :does(OpenAIAsync::Types::Base) :Struct { + field $created :JSONNum; + field $id :JSONStr; + field $object :JSONStr = "model"; + field $owned_by :JSONStr; +}