diff --git a/.vstags b/.vstags new file mode 100644 index 0000000..47de308 --- /dev/null +++ b/.vstags @@ -0,0 +1,103 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +OpenAIAsync::Types lib/OpenAIAsync/Types.pm 1;" p +OpenAIAsync::Types::Requests .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/latest/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests .build/previous/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests:: .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 1;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 170;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/latest/lib/OpenAIAsync/Types/Requests.pm 170;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 170;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 170;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union .build/previous/lib/OpenAIAsync/Types/Requests.pm 169;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union lib/OpenAIAsync/Types/Requests.pm 170;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 94;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/latest/lib/OpenAIAsync/Types/Requests.pm 94;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 94;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 94;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion .build/previous/lib/OpenAIAsync/Types/Requests.pm 93;" p +OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion lib/OpenAIAsync/Types/Requests.pm 94;" p +OpenAIAsync::Types::Results .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/4DgDOdekNW/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/_pSCu227xy/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/latest/blib/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/latest/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/nb3podVIwj/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/previous/blib/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results .build/previous/lib/OpenAIAsync/Types/Results.pm 1;" p +OpenAIAsync::Types::Results lib/OpenAIAsync/Types/Results.pm 1;" p +new .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 173;" s +new .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 97;" s +new .build/latest/lib/OpenAIAsync/Types/Requests.pm 173;" s +new .build/latest/lib/OpenAIAsync/Types/Requests.pm 97;" s +new .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 173;" s +new .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 97;" s +new .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 173;" s +new .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 97;" s +new .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +new .build/previous/lib/OpenAIAsync/Types/Requests.pm 172;" s +new .build/previous/lib/OpenAIAsync/Types/Requests.pm 96;" s +new lib/OpenAIAsync/Types/Requests.pm 173;" s +new lib/OpenAIAsync/Types/Requests.pm 97;" s +ontent::new .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 173;" s +ontent::new .build/latest/lib/OpenAIAsync/Types/Requests.pm 173;" s +ontent::new .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 173;" s +ontent::new .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 173;" s +ontent::new .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new .build/previous/lib/OpenAIAsync/Types/Requests.pm 172;" s +ontent::new lib/OpenAIAsync/Types/Requests.pm 173;" s +y::new .build/4DgDOdekNW/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/4DgDOdekNW/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/NfFNPyy4iR/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/_pSCu227xy/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/_pSCu227xy/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/latest/blib/lib/OpenAIAsync/Types/Requests.pm 97;" s +y::new .build/latest/lib/OpenAIAsync/Types/Requests.pm 97;" s +y::new .build/nb3podVIwj/blib/lib/OpenAIAsync/Types/Requests.pm 97;" s +y::new .build/nb3podVIwj/lib/OpenAIAsync/Types/Requests.pm 97;" s +y::new .build/previous/blib/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new .build/previous/lib/OpenAIAsync/Types/Requests.pm 96;" s +y::new lib/OpenAIAsync/Types/Requests.pm 97;" s diff --git a/lib/OpenAIAsync.pm b/lib/OpenAIAsync.pm new file mode 100644 index 0000000..b701d2f --- /dev/null +++ b/lib/OpenAIAsync.pm @@ -0,0 +1,7 @@ +package OpenAIAsync; + +our $VERSION="0.01"; + +# ABSTRACT: OpenAI style Client and Server for processing various AI tasks + +1; \ No newline at end of file diff --git a/lib/OpenAIAsync/Client.pm b/lib/OpenAIAsync/Client.pm index b1a9d07..da6acee 100644 --- a/lib/OpenAIAsync/Client.pm +++ b/lib/OpenAIAsync/Client.pm @@ -6,6 +6,10 @@ use Future::AsyncAwait; use OpenAIAsync::Types::Results; use OpenAIAsync::Types::Requests; +our $VERSION="v0.1.0"; + +# ABSTRACT: Async client for OpenAI style REST API for various AI systems (LLMs, Images, Video, etc.) + class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) { use JSON::MaybeXS qw//; use Net::Async::HTTP; @@ -13,17 +17,16 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) { use URI; field $_json = JSON::MaybeXS->new(utf8 => 1, convert_blessed => 1); + field $http; + # TODO document these directly, other options gets mixed in BEFORE all of these field $_http_max_in_flight :param(http_max_in_flight) = 2; field $_http_max_redirects :param(http_max_redirects) = 3; field $_http_max_connections_per_host :param(http_max_connections_per_host) = 2; field $_http_timeout :param(http_timeout) = 120; # My personal server is kinda slow, use a generous default field $_http_stall_timeout :param(http_stall_timeout) = 600; # generous for my slow personal server - field $_http_proxy_host :param(http_proxy_host) = undef; - field $_http_proxy_port :param(http_proxy_port) = undef; - field $_http_proxy_path :param(http_proxy_path) = undef; - - field $http; + field $_http_other :param(http_other_options) = {}; + field $_http_user_agent = __PACKAGE__." Perl/$VERSION (Net::Async::HTTP/".$Net::Async::HTTP::VERSION." IO::Async/".$IO::Async::VERSION." Perl/$])"; field $api_base :param(api_base) = $ENV{OPENAI_API_BASE} // "https://api.openai.com/v1"; field $api_key :param(api_key) = $ENV{OPENAI_API_KEY}; @@ -31,15 +34,17 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) { field $api_org_name :param(api_org_name) = undef; method configure(%params) { - # We require them to go this way + # We require them to go this way, so that there is no conflicts + # TODO document this my %io_async_params = ($params{io_async_notifier_params} // {})->%*; - IO::Async::Notifier::configure($self, ); + IO::Async::Notifier::configure($self, %io_async_params); } method __make_http() { die "Missing API Key for OpenAI" unless $api_key; return Net::Async::HTTP->new( + $_http_other->%*, user_agent => "SNN OpenAI Client 1.0", +headers => { "Authorization" => "Bearer $api_key", @@ -53,7 +58,6 @@ class OpenAIAsync::Client :repr(HASH) :isa(IO::Async::Notifier) { max_in_flight => $_http_max_in_flight, timeout => $_http_timeout, stall_timeout => $_http_stall_timeout, - # TODO proxy stuff ) } diff --git a/lib/OpenAIAsync/Types.pm b/lib/OpenAIAsync/Types.pm new file mode 100644 index 0000000..7f9a359 --- /dev/null +++ b/lib/OpenAIAsync/Types.pm @@ -0,0 +1,11 @@ +package OpenAIAsync::Types; +use v5.38.0; +use Object::Pad; + +use Object::PadX::Role::AutoMarshal; +use Object::PadX::Role::AutoJSON; +use Object::Pad::ClassAttr::Struct; + +# Base role for all the types to simplify things later +role OpenAIAsync::Types::Base :does(Object::PadX::Role::AutoJSON) :does(Object::PadX::Role::AutoMarshal) :Struct { +} diff --git a/lib/OpenAIAsync/Types/Requests.pm b/lib/OpenAIAsync/Types/Requests.pm index 112f09b..8dbf565 100644 --- a/lib/OpenAIAsync/Types/Requests.pm +++ b/lib/OpenAIAsync/Types/Requests.pm @@ -1,38 +1,95 @@ -package OpenAIAsync::Types::Requests::; +package OpenAIAsync::Types::Requests; use v5.38.0; use Object::Pad; use Object::PadX::Role::AutoMarshal; use Object::PadX::Role::AutoJSON; use Object::Pad::ClassAttr::Struct; +use OpenAIAsync::Types; -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::ToolCall :does(AutoMarshal) :does(AutoJSON) :Struct { +role OpenAIAsync::Types::Requests::Base :does(OpenAIAsync::Types::Base) :Struct { + requires _endpoint; # How the client finds where to send the request +} + +#### Base Request Types + +class OpenAIAsync::Types::Requests::ChatCompletion :does(OpenAIAsync::Types::Requests::Base) { + method _endpoint() {...} + field $messages :MarshalTo([OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union]); +} + +class OpenAIAsync::Types::Requests::Completion :does(OpenAIAsync::Types::Requests::Base) { + method _endpoint() {...} + use JSON::MaybeXS; # TODO make a role that does this better? + + field $model :JSONStr = "gpt-3.5-turbo"; # This is how 99% of everyone else seems to default this + field $prompt :JSONStr; + + field $max_tokens :JSONNum = undef; # use the platform default usually + field $temperature :JSONNum = undef; + field $top_p :JSONNum = undef; + field $seed :JSONNum = undef; + field $echo :JSONBool = undef; # true or false only + field $suffix :JSONStr = undef; + field $stop :JSONStr = undef; # array of stop tokens + field $user :JSONStr = undef; # used for tracking purposes later + + field $frequency_penalty :JSONNum = undef; + field $presence_penalty :JSONNum = undef; + + field $logit_bias = undef; # TODO make this work + field $log_probs = undef; # TODO + + field $n :JSONNum = undef; # Danger will robinson! easy to cause $$$$$$$ costs + field $best_of :JSONNum = undef; + + field $stream :JSONBool = undef; # TODO FALSE ALWAYS RIGHT NOW + + ADJUST { + # Type assertions here + die "Streaming unsupported" if $self->stream; + } +} + +class OpenAIAsync::Types::Requests::Embedding :does(OpenAIAsync::Types::Requests::Base) { + method _endpoint() {...} + field $input :JSONStr; + field $model :JSONStr; + field $encoding_format :JSONStr = undef; + field $user :JSONStr = undef; +} + +### Request Subtypes + +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::ToolCall :does(OpenAIAsync::Types::Base) { field $id :JSONStr; field $arguments :JSONStr; field $type :JSONStr; field $function :MarshalTo(OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::FunctionCall); } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::FunctionCall :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::FunctionCall :does(OpenAIAsync::Types::Base) { field $arguments :JSONStr; field $name :JSONStr; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::Text :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::Text :does(OpenAIAsync::Types::Base) { field $type :JSONStr; field $text :JSONStr; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ImageUrl :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ImageUrl :does(OpenAIAsync::Types::Base) { field $url :JSONStr; field $detail :JSONStr = undef; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::Image :does(AutoJSON) :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::Image :does(OpenAIAsync::Types::Base) { field $type :JSONStr; field $image_url :MarshalTo(OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ImageUrl); } +# TODO, why have two of these? just shove it into the big one below + package OpenAIAsync::Types::Requests::ChatCompletion::Messages::User::ContentUnion { # This guy does some additional checks to give us the right type here @@ -53,7 +110,7 @@ package } }; -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User :does(OpenAIAsync::Types::Base) { # This particular type is more complicated than AutoMarshal can handle, so we need to # do this in a custom manner. field $role; @@ -82,7 +139,7 @@ class OpenAIAsync::Types::Requests::ChatCompletion::Messages::User :does(AutoJSO } } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant :does(AutoMarshal) :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant :does(OpenAIAsync::Types::Base) { field $role :JSONStr; field $content :JSONStr; field $name = undef; @@ -90,19 +147,19 @@ class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant :does(Au field $function_call :MarshalTo(OpenAIAsync::Types::Requests::ChatCompletion::Messages::Assistant::FunctionCall) = undef; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Function :does(AutoMarshal) :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Function :does(OpenAIAsync::Types::Base) { field $role :JSONStr; field $content :JSONStr; field $name :JSONStr; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Tool :does(AutoMarshal) :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::Tool :does(OpenAIAsync::Types::Base) { field $role :JSONStr; field $content :JSONStr; field $tool_call_id :JSONStr; } -class OpenAIAsync::Types::Requests::ChatCompletion::Messages::System :does(AutoMarshal) :does(AutoJSON) :Struct { +class OpenAIAsync::Types::Requests::ChatCompletion::Messages::System :does(OpenAIAsync::Types::Base) { field $role :JSONStr; field $name :JSONStr = undef; field $content :JSONStr; @@ -133,46 +190,3 @@ package } }; -class OpenAIAsync::Types::Requests::ChatCompletion :does(AutoMarshal) :does(AutoJSON) :Struct { - field $messages :MarshalTo([OpenAIAsync::Types::Requests::ChatCompletion::Messages::Union]); -} - -class OpenAIAsync::Types::Requests::Completion :does(AutoJSON) :Struct { - use JSON::MaybeXS; # TODO make a role that does this better? - - field $model :JSONStr = "gpt-3.5-turbo"; # This is how 99% of everyone else seems to default this - field $prompt :JSONStr; - - field $max_tokens :JSONNum = undef; # use the platform default usually - field $temperature :JSONNum = undef; - field $top_p :JSONNum = undef; - field $seed :JSONNum = undef; - field $echo :JSONBool = undef; # true or false only - field $suffix :JSONStr = undef; - field $stop :JSONStr = undef; # array of stop tokens - field $user :JSONStr = undef; # used for tracking purposes later - - field $frequency_penalty :JSONNum = undef; - field $presence_penalty :JSONNum = undef; - - field $logit_bias = undef; # TODO make this work - field $log_probs = undef; # TODO - - field $n :JSONNum = undef; # Danger will robinson! easy to cause $$$$$$$ costs - field $best_of :JSONNum = undef; - - field $stream :JSONBool = undef; # TODO FALSE ALWAYS RIGHT NOW - - ADJUST { - # Type assertions here - die "Streaming unsupported" if $self->stream; - - } -} - -class OpenAIAsync::Types::Requests::Embedding :does(AutoJSON) :Struct { - field $input :JSONStr; - field $model :JSONStr; - field $encoding_format :JSONStr = undef; - field $user :JSONStr = undef; -} \ No newline at end of file diff --git a/lib/OpenAIAsync/Types/Results.pm b/lib/OpenAIAsync/Types/Results.pm index ef1e4c3..18d6957 100644 --- a/lib/OpenAIAsync/Types/Results.pm +++ b/lib/OpenAIAsync/Types/Results.pm @@ -2,34 +2,36 @@ package OpenAIAsync::Types::Results; use v5.38.0; use Object::Pad; +use OpenAIAsync::Types; use Object::PadX::Role::AutoMarshal; +use Object::PadX::Role::AutoJSON; use Object::Pad::ClassAttr::Struct; -class OpenAIAsync::Types::Results::ToolCall :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ToolCall :does(OpenAIAsync::Types::Base) { field $id; field $type; # always "function" right now, may get expanded in the future field $function :MarshalTo(OpenAIAsync::Types::Results::FunctionCall); } -class OpenAIAsync::Types::Results::FunctionCall :Struct { +class OpenAIAsync::Types::Results::FunctionCall :does(OpenAIAsync::Types::Base) { field $arguments; # TODO decode the json from this directly? field $name; } -class OpenAIAsync::Types::Results::ChatMessage :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChatMessage :does(OpenAIAsync::Types::Base) { field $content; field $tool_calls :MarshalTo([OpenAIAsync::Types::Results::ToolCall]) = undef; # don't think my local server provides this field $role; field $function_call :MarshalTo(OpenAIAsync::Types::Results::FunctionCall) = undef; # Depcrecated, might still happen } -class OpenAIAsync::Types::Results::ChatCompletionChoices :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChatCompletionChoices :does(OpenAIAsync::Types::Base) { field $finish_reason; field $index; field $message :MarshalTo(OpenAIAsync::Types::Results::ChatMessage); } -class OpenAIAsync::Types::Results::ChatCompletion :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChatCompletion :does(OpenAIAsync::Types::Base) { field $id; field $choices :MarshalTo([OpenAIAsync::Types::Results::ChatCompletionChoices]); field $created; @@ -39,21 +41,21 @@ class OpenAIAsync::Types::Results::ChatCompletion :does(AutoMarshal) :Struct { field $object; } -class OpenAIAsync::Types::Results::ChunkDelta :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChunkDelta :does(OpenAIAsync::Types::Base) { field $content; field $function_call :MarshalTo(OpenAIAsync::Types::Results::FunctionCall); field $tool_cass :MarshalTo([OpenAIAsync::Types::Results::ToolCall]); field $role; } -class OpenAIAsync::Types::Results::ChatCompletionChunkChoices :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChatCompletionChunkChoices :does(OpenAIAsync::Types::Base) { field $delta :MarshalTo(OpenAIAsync::Types::Results::ChunkDelta); field $finish_reason; field $index; } # This is part of the streaming API -class OpenAIAsync::Types::Results::ChatCompletionChunk :does(AutoMarshal) :Struct { +class OpenAIAsync::Types::Results::ChatCompletionChunk :does(OpenAIAsync::Types::Base) { field $id; field $choices :MarshalTo(OpenAIAsync::Types::Results::ChatCompletionChunkChoices); field $created; @@ -62,13 +64,13 @@ class OpenAIAsync::Types::Results::ChatCompletionChunk :does(AutoMarshal) :Struc field $object; } -class OpenAIAsync::Types::Results::Usage :Struct { +class OpenAIAsync::Types::Results::Usage :does(OpenAIAsync::Types::Base) { field $total_tokens; field $prompt_tokens; field $completion_tokens; # look at chat completions, is this the same } -class OpenAIAsync::Types::Results::LogProbs :Struct { +class OpenAIAsync::Types::Results::LogProbs :does(OpenAIAsync::Types::Base) { field $text_offset = undef; field $token_logprobs = undef; field $tokens = undef; diff --git a/t/01-use-ok.t b/t/01-use-ok.t new file mode 100644 index 0000000..687dc52 --- /dev/null +++ b/t/01-use-ok.t @@ -0,0 +1,11 @@ +use strict; +use warnings; + +use Test::More; + +require_ok('OpenAIAsync::Client'); +require_ok('OpenAIAsync::Types'); +require_ok('OpenAIAsync::Types::Requests'); +require_ok('OpenAIAsync::Types::Results'); + +done_testing(); \ No newline at end of file