AI-Ollama-Client

 view release on metacpan or  search on metacpan

Makefile.PL  view on Meta::CPAN

    dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
    clean               => { FILES => "$distbase-*" },

    test            => { TESTS => join( ' ', @tests ) },
);

# This is so that we can do
#     require 'Makefile.PL'
# and then call get_module_info

sub get_module_info { %module }

if( ! caller ) {
    require File::ShareDir::Install;
    File::ShareDir::Install::install_share( module => "$module\::Impl" => 'ollama');

    {
        package MY;
        require File::ShareDir::Install;
        File::ShareDir::Install->import( qw( postamble ));
    }

    # I should maybe use something like Shipwright...
    my $mm = WriteMakefile1(get_module_info);
    my $version = $mm->parse_version($main_file);
    regen_README($main_file, $version);
    regen_EXAMPLES() if -d 'examples';
};

1;

sub WriteMakefile1 {  #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade.
    my %params=@_;
    my $eumm_version=$ExtUtils::MakeMaker::VERSION;
    $eumm_version=eval $eumm_version;
    die "EXTRA_META is deprecated" if exists $params{EXTRA_META};
    die "License not specified" if not exists $params{LICENSE};
    if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) {
        #EUMM 6.5502 has problems with BUILD_REQUIRES
        $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} };
        delete $params{BUILD_REQUIRES};
    }

Makefile.PL  view on Meta::CPAN

    delete $params{META_MERGE} if $eumm_version < 6.46;
    delete $params{META_ADD} if $eumm_version < 6.46;
    delete $params{LICENSE} if $eumm_version < 6.31;
    delete $params{AUTHOR} if $] < 5.005;
    delete $params{ABSTRACT_FROM} if $] < 5.005;
    delete $params{BINARY_LOCATION} if $] < 5.005;

    WriteMakefile(%params);
}

sub regen_README {
    # README is the short version that just tells people what this is
    # and how to install it
    my( $file, $version ) = @_;
    eval {
        # Get description
        my $readme = join "\n",
            pod_section($file, 'NAME', 'no heading' ),
            pod_section($file, 'DESCRIPTION' ),
            <<VERSION,
This document describes version $version.

Makefile.PL  view on Meta::CPAN


[![Windows](https://github.com/Corion/$distbase/workflows/windows/badge.svg)](https://github.com/Corion/$distbase/actions?query=workflow%3Awindows)
[![MacOS](https://github.com/Corion/$distbase/workflows/macos/badge.svg)](https://github.com/Corion/$distbase/actions?query=workflow%3Amacos)
[![Linux](https://github.com/Corion/$distbase/workflows/linux/badge.svg)](https://github.com/Corion/$distbase/actions?query=workflow%3Alinux)

STATUS
        update_file( 'README.mkdn', $readme_mkdn );
    };
}

sub pod_section {
    my( $filename, $section, $remove_heading ) = @_;
    open my $fh, '<', $filename
        or die "Couldn't read '$filename': $!";

    my @section =
        grep { /^=head1\s+$section/.../^=/ } <$fh>;

    # Trim the section
    if( @section ) {
        pop @section if $section[-1] =~ /^=/;

Makefile.PL  view on Meta::CPAN

        pop @section
            while @section and $section[-1] =~ /^\s*$/;
        shift @section
            while @section and $section[0] =~ /^\s*$/;
    };

    @section = map { $_ =~ s!^=\w+\s+!!; $_ } @section;
    return join "", @section;
}

sub regen_EXAMPLES {
    my $perl = $^X;
    if ($perl =~/\s/) {
        $perl = qq{"$perl"};
    };
    (my $example_file = $main_file) =~ s!\.pm$!/Examples.pm!;
    my $examples = `$perl -w examples/gen_examples_pod.pl`;
    if ($examples) {
        warn "(Re)Creating $example_file\n";
        $examples =~ s/\r\n/\n/g;
        update_file( $example_file, $examples );
    };
};

sub update_file {
    my( $filename, $new_content ) = @_;
    my $content;
    if( -f $filename ) {
        open my $fh, '<:raw:encoding(UTF-8)', $filename
            or die "Couldn't read '$filename': $!";
        local $/;
        $content = <$fh>;
    };

    if( $content ne $new_content ) {

lib/AI/Ollama/Client.pm  view on Meta::CPAN

=head1 METHODS

=head2 C<< checkBlob >>

  my $res = $client->checkBlob()->get;

Check to see if a blob exists on the Ollama server which is useful when creating models.

=cut

around 'checkBlob' => sub ( $super, $self, %options ) {
    $super->( $self, %options )->then( sub( $res ) {
        if( $res->code =~ /^2\d\d$/ ) {
            return Future->done( 1 )
        } else {
            return Future->done( 0 )
        }
    });
};

=head2 C<< createBlob >>

lib/AI/Ollama/Client.pm  view on Meta::CPAN


      Future::Mojo->done( defined $res );
  } until => sub($done) { $done->get };

Generate a response for a given prompt with a provided model.

Returns a L<< AI::Ollama::GenerateCompletionResponse >>.

=cut

around 'generateCompletion' => sub ( $super, $self, %options ) {
    # Encode images as base64, if images exist:
    # (but create a copy so we don't over write the input array)
    if (my $images = $options{images}) {

        # Allow { filename => '/etc/passwd' }
        $options{images} = [
            map {
                my $item = $_;
                if( ref($item) eq 'HASH' ) {
                    $item = Mojo::File->new($item->{filename})->slurp();

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

The L<Mojo::UserAgent> to use

=head2 B<< server >>

The server to access

=cut

has 'schema_file' => (
    is => 'lazy',
    default => sub { require AI::Ollama::Client::Impl; module_file('AI::Ollama::Client::Impl', 'ollama-curated.yaml') },
);

has 'schema' => (
    is => 'lazy',
    default => sub {
        if( my $fn = $_[0]->schema_file ) {
            YAML::PP->new( boolean => 'JSON::PP' )->load_file($fn);
        }
    },
);

has 'validate_requests' => (
    is => 'rw',
    default => 1,
);

has 'validate_responses' => (
    is => 'rw',
    default => 1,
);

has 'openapi' => (
    is => 'lazy',
    default => sub {
        if( my $schema = $_[0]->schema ) {
            OpenAPI::Modern->new( openapi_schema => $schema, openapi_uri => '' )
        }
    },
);

# The HTTP stuff should go into a ::Role I guess
has 'ua' => (
    is => 'lazy',
    default => sub { Mojo::UserAgent->new },
);

has 'server' => (
    is => 'ro',
);

=head1 METHODS

=head2 C<< build_checkBlob_request >>

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item B<< digest >>

the SHA256 digest of the blob

=back



=cut

sub build_checkBlob_request( $self, %options ) {
    croak "Missing required parameter 'digest'"
        unless exists $options{ 'digest' };

    my $method = 'HEAD';
    my $template = URI::Template->new( '/blobs/{digest}' );
    my $path = $template->process(
              'digest' => delete $options{'digest'},
    );
    my $url = Mojo::URL->new( $self->server . $path );

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

        {
        }
    );

    $self->validate_request( $tx );

    return $tx
}


sub checkBlob( $self, %options ) {
    my $tx = $self->build_checkBlob_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item B<< digest >>

the SHA256 digest of the blob

=back



=cut

sub build_createBlob_request( $self, %options ) {
    croak "Missing required parameter 'digest'"
        unless exists $options{ 'digest' };

    my $method = 'POST';
    my $template = URI::Template->new( '/blobs/{digest}' );
    my $path = $template->process(
              'digest' => delete $options{'digest'},
    );
    my $url = Mojo::URL->new( $self->server . $path );

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

        }
        => $body,
    );

    $self->validate_request( $tx );

    return $tx
}


sub createBlob( $self, %options ) {
    my $tx = $self->build_createBlob_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< stream >>

If C<false> the response will be returned as a single response object, otherwise the response will be streamed as a series of objects.

=back

Returns a L<< AI::Ollama::GenerateChatCompletionResponse >> on success.

=cut

sub build_generateChatCompletion_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/chat';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::GenerateChatCompletionRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/x-ndjson',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub generateChatCompletion( $self, %options ) {
    my $tx = $self->build_generateChatCompletion_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    our @store; # we should use ->retain() instead
    push @store, $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN


=item C<< source >>

Name of the model to copy.

=back


=cut

sub build_copyModel_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/copy';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::CopyModelRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub copyModel( $self, %options ) {
    my $tx = $self->build_copyModel_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< stream >>

If C<false> the response will be returned as a single response object, otherwise the response will be streamed as a series of objects.

=back

Returns a L<< AI::Ollama::CreateModelResponse >> on success.

=cut

sub build_createModel_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/create';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::CreateModelRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/x-ndjson',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub createModel( $self, %options ) {
    my $tx = $self->build_createModel_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    our @store; # we should use ->retain() instead
    push @store, $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN


The model name.

Model names follow a C<model:tag> format. Some examples are C<orca-mini:3b-q4_1> and C<llama2:70b>. The tag is optional and, if not provided, will default to C<latest>. The tag is used to identify a specific version.

=back


=cut

sub build_deleteModel_request( $self, %options ) {
    my $method = 'DELETE';
    my $path = '/delete';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::DeleteModelRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub deleteModel( $self, %options ) {
    my $tx = $self->build_deleteModel_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< prompt >>

Text to generate embeddings for.

=back

Returns a L<< AI::Ollama::GenerateEmbeddingResponse >> on success.

=cut

sub build_generateEmbedding_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/embeddings';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::GenerateEmbeddingRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/json',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub generateEmbedding( $self, %options ) {
    my $tx = $self->build_generateEmbedding_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< template >>

The full prompt or prompt template (overrides what is defined in the Modelfile).

=back

Returns a L<< AI::Ollama::GenerateCompletionResponse >> on success.

=cut

sub build_generateCompletion_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/generate';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::GenerateCompletionRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/x-ndjson',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub generateCompletion( $self, %options ) {
    my $tx = $self->build_generateCompletion_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    our @store; # we should use ->retain() instead
    push @store, $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< stream >>

If C<false> the response will be returned as a single response object, otherwise the response will be streamed as a series of objects.

=back

Returns a L<< AI::Ollama::PullModelResponse >> on success.

=cut

sub build_pullModel_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/pull';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::PullModelRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/x-ndjson',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub pullModel( $self, %options ) {
    my $tx = $self->build_pullModel_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    our @store; # we should use ->retain() instead
    push @store, $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

=item C<< stream >>

If C<false> the response will be returned as a single response object, otherwise the response will be streamed as a series of objects.

=back

Returns a L<< AI::Ollama::PushModelResponse >> on success.

=cut

sub build_pushModel_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/push';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::PushModelRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/json',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub pushModel( $self, %options ) {
    my $tx = $self->build_pushModel_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

The model name.

Model names follow a C<model:tag> format. Some examples are C<orca-mini:3b-q4_1> and C<llama2:70b>. The tag is optional and, if not provided, will default to C<latest>. The tag is used to identify a specific version.

=back

Returns a L<< AI::Ollama::ModelInfo >> on success.

=cut

sub build_showModelInfo_request( $self, %options ) {
    my $method = 'POST';
    my $path = '/show';
    my $url = Mojo::URL->new( $self->server . $path );

    my $request = AI::Ollama::ModelInfoRequest->new( \%options )->as_hash;
    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/json',
            "Content-Type" => 'application/json',
        }
        => json => $request,
    );

    $self->validate_request( $tx );

    return $tx
}


sub showModelInfo( $self, %options ) {
    my $tx = $self->build_showModelInfo_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN


  my $res = $client->listModels()->get;

List models that are available locally.


Returns a L<< AI::Ollama::ModelsResponse >> on success.

=cut

sub build_listModels_request( $self, %options ) {
    my $method = 'GET';
    my $path = '/tags';
    my $url = Mojo::URL->new( $self->server . $path );

    my $tx = $self->ua->build_tx(
        $method => $url,
        {
            'Accept' => 'application/json',
        }
    );

    $self->validate_request( $tx );

    return $tx
}


sub listModels( $self, %options ) {
    my $tx = $self->build_listModels_request(%options);


    my $res = Future::Mojo->new();

    my $r1 = Future::Mojo->new();
    $r1->then( sub( $tx ) {
        my $resp = $tx->res;
        $self->emit(response => $resp);
        # Should we validate using OpenAPI::Modern here?!

lib/AI/Ollama/Client/Impl.pm  view on Meta::CPAN

    })->catch(sub($err) {
        $self->emit(response => $tx, $err);
        $r1->fail( $err => $tx );
        undef $r1;
    });

    return $res
}


sub validate_response( $self, $payload, $tx ) {
    if(     $self->validate_responses
        and my $openapi = $self->openapi ) {
        my $results = $openapi->validate_response($payload, { request => $tx->req });
        if( $results->{error}) {
            say $results;
            say $tx->res->to_string;
        };
    };
}

sub validate_request( $self, $tx ) {
    if(        $self->validate_requests
        and my $openapi = $self->openapi ) {
        my $results = $openapi->validate_request($tx->req);
        if( $results->{error}) {
            say $results;
            say $tx->req->to_string;
        };
    };
}

lib/AI/Ollama/CopyModelRequest.pm  view on Meta::CPAN


AI::Ollama::CopyModelRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::CopyModelRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< destination >>

Name of the new model.

=cut

lib/AI/Ollama/CreateModelRequest.pm  view on Meta::CPAN


AI::Ollama::CreateModelRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::CreateModelRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< modelfile >>

The contents of the Modelfile.

=cut

lib/AI/Ollama/CreateModelResponse.pm  view on Meta::CPAN


AI::Ollama::CreateModelResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::CreateModelResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< status >>

Status creating the model

=cut

lib/AI/Ollama/DeleteModelRequest.pm  view on Meta::CPAN


AI::Ollama::DeleteModelRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::DeleteModelRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< name >>

The model name.

Model names follow a `model:tag` format. Some examples are `orca-mini:3b-q4_1` and `llama2:70b`. The tag is optional and, if not provided, will default to `latest`. The tag is used to identify a specific version.

lib/AI/Ollama/GenerateChatCompletionRequest.pm  view on Meta::CPAN


AI::Ollama::GenerateChatCompletionRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateChatCompletionRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< format >>

The format to return a response in. Currently the only accepted value is json.

Enable JSON mode by setting the format parameter to json. This will structure the response as valid JSON.

lib/AI/Ollama/GenerateChatCompletionResponse.pm  view on Meta::CPAN


AI::Ollama::GenerateChatCompletionResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateChatCompletionResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< created_at >>

Date on which a model was created.

=cut

lib/AI/Ollama/GenerateCompletionRequest.pm  view on Meta::CPAN


AI::Ollama::GenerateCompletionRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateCompletionRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< context >>

The context parameter returned from a previous request to [generateCompletion], this can be used to keep a short conversational memory.

=cut

lib/AI/Ollama/GenerateCompletionResponse.pm  view on Meta::CPAN


AI::Ollama::GenerateCompletionResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateCompletionResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< context >>

An encoding of the conversation used in this response, this can be sent in the next request to keep a conversational memory.

=cut

lib/AI/Ollama/GenerateEmbeddingRequest.pm  view on Meta::CPAN


AI::Ollama::GenerateEmbeddingRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateEmbeddingRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< model >>

The model name.

Model names follow a `model:tag` format. Some examples are `orca-mini:3b-q4_1` and `llama2:70b`. The tag is optional and, if not provided, will default to `latest`. The tag is used to identify a specific version.

lib/AI/Ollama/GenerateEmbeddingResponse.pm  view on Meta::CPAN


AI::Ollama::GenerateEmbeddingResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::GenerateEmbeddingResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< embedding >>

The embedding for the prompt.

=cut

lib/AI/Ollama/Message.pm  view on Meta::CPAN


AI::Ollama::Message -

=head1 SYNOPSIS

  my $obj = AI::Ollama::Message->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< content >>

The content of the message

=cut

lib/AI/Ollama/Model.pm  view on Meta::CPAN


AI::Ollama::Model -

=head1 SYNOPSIS

  my $obj = AI::Ollama::Model->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< modified_at >>

Model modification date.

=cut

lib/AI/Ollama/ModelInfo.pm  view on Meta::CPAN


AI::Ollama::ModelInfo -

=head1 SYNOPSIS

  my $obj = AI::Ollama::ModelInfo->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< license >>

The model's license.

=cut

lib/AI/Ollama/ModelInfoRequest.pm  view on Meta::CPAN


AI::Ollama::ModelInfoRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::ModelInfoRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< name >>

The model name.

Model names follow a `model:tag` format. Some examples are `orca-mini:3b-q4_1` and `llama2:70b`. The tag is optional and, if not provided, will default to `latest`. The tag is used to identify a specific version.

lib/AI/Ollama/ModelsResponse.pm  view on Meta::CPAN


AI::Ollama::ModelsResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::ModelsResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< models >>

List of models available locally.

=cut

lib/AI/Ollama/PullModelRequest.pm  view on Meta::CPAN


AI::Ollama::PullModelRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::PullModelRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< insecure >>

Allow insecure connections to the library.

Only use this if you are pulling from your own library during development.

lib/AI/Ollama/PullModelResponse.pm  view on Meta::CPAN


AI::Ollama::PullModelResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::PullModelResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< completed >>

Total bytes transferred.

=cut

lib/AI/Ollama/PushModelRequest.pm  view on Meta::CPAN


AI::Ollama::PushModelRequest -

=head1 SYNOPSIS

  my $obj = AI::Ollama::PushModelRequest->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< insecure >>

Allow insecure connections to the library.

Only use this if you are pushing to your library during development.

lib/AI/Ollama/PushModelResponse.pm  view on Meta::CPAN


AI::Ollama::PushModelResponse -

=head1 SYNOPSIS

  my $obj = AI::Ollama::PushModelResponse->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< digest >>

the model's digest

=cut

lib/AI/Ollama/RequestOptions.pm  view on Meta::CPAN


AI::Ollama::RequestOptions -

=head1 SYNOPSIS

  my $obj = AI::Ollama::RequestOptions->new();
  ...

=cut

sub as_hash( $self ) {
    return { $self->%* }
}

=head1 PROPERTIES

=head2 C<< embedding_only >>

Enable embedding only. (Default: false)

=cut

scripts/code-completion.pl  view on Meta::CPAN


my $ol = AI::Ollama::Client->new(
    server => 'http://192.168.1.97:11434/api',
);

my $model = 'codellama:13b-code';
my $tx = $ol->pullModel(
    name => $model,
)->get;

my @prompts = @ARGV ? @ARGV : (qq{fetch an url and print its content with Mojolicious; write concise code <PRE> sub fetch {\n <SUF> } <MID>});

for my $prompt (@prompts) {
    my $response = $ol->generateCompletion(
        model => $model,
        prompt => $prompt,
        system => 'You are a helpful concise coding assistant',
    );

    my $code;
    my $responses = $response->get;

scripts/describe-image.pl  view on Meta::CPAN

    if( $err ) {
        warn $err if $err;
    } else {
        #use Data::Dumper;
        warn $tx->code;
    }
});

my $tx = $ol->pullModel(
    name => 'llava:latest',
)->catch(sub {
    use Data::Dumper; warn Dumper \@_;
})->get;

my @images = @ARGV ? @ARGV : ('t/testdata/objectdetection.jpg');

for my $image (@images) {
    my $response = $ol->generateCompletion(
        model => 'llava:latest',
        prompt => 'You are tagging images. Please list all the objects in this image as tags. Also list the location where it was taken.',
        images => [

scripts/music-genre-json.pl  view on Meta::CPAN

        model => $model,
        prompt => $prompt,
        temperature => '0.0',
        messages => [
            {role => 'system',
             content => join "\n",
                       'You are a music expert.',
                       'You are given an artist name and song title.',
                       'Please suggest three musical genres of that title and performer.',
                       'Only list the musical genres.',
                       #'Answer in JSON only with an array containing objects { "genre": "the genre", "sub-genre": "the sub genre" }.',
            },
            { role => 'user', content => $prompt },
        ],
    );

    my $chat;
    my $responses = $response->get;
    repeat {
        my $check = eval {
        my ($res) = $responses->shift;

xt/99-compile.t  view on Meta::CPAN

};

plan 'no_plan';

require './Makefile.PL';
# Loaded from Makefile.PL
our %module = get_module_info();

my $last_version = undef;

sub check {
    #return if (! m{(\.pm|\.pl) \z}xmsi);

    my ($stdout, $stderr, $exit) = capture(sub {
        system( $^X, '-Mblib', '-c', $_ );
    });

    s!\s*\z!!
        for ($stdout, $stderr);

    if( $exit ) {
        diag $stderr;
        diag "Exit code: ", $exit;
        fail($_);

xt/99-compile.t  view on Meta::CPAN

    );

if( my $exe = $module{EXE_FILES}) {
    push @files, @$exe;
};

for (@files) {
    check($_)
}

sub wanted {
  push @files, $File::Find::name if /\.p(l|m|od)$/;
}

xt/99-pod.t  view on Meta::CPAN

  if( my $exe = $module{EXE_FILES}) {
    push @files, @$exe;
  };

  plan tests => scalar @files;
  foreach my $file (@files) {
    pod_file_ok($file);
  }
}

sub wanted {
  push @files, $File::Find::name if /\.p(l|m|od)$/;
}

xt/99-synopsis.t  view on Meta::CPAN


#if( my $exe = $module{EXE_FILES}) {
#    push @files, @$exe;
#};

plan tests => scalar @files;
foreach my $file (@files) {
    synopsis_file_ok($file);
}

sub wanted {
    push @files, $File::Find::name if /\.p(l|m|od)$/
        and $_ !~ /\bDSL\.pm$/; # we skip that one as it initializes immediately
}

sub synopsis_file_ok {
    my( $file ) = @_;
    my $name = "SYNOPSIS in $file compiles";
    open my $fh, '<', $file
        or die "Couldn't read '$file': $!";
    my @synopsis = map  { s!^\s\s!!; $_ } # outdent all code for here-docs
                   grep { /^\s\s/ } # extract all verbatim (=code) stuff
                   grep { /^=head1\s+SYNOPSIS$/.../^=/ } # extract Pod synopsis
                   <$fh>;
    if( @synopsis ) {
        my($tmpfh,$tempname) = tempfile();

xt/99-test-prerequisites.t  view on Meta::CPAN

    @tests = grep { -f $_ } grep { m!^(t/.*\.t|scripts/.*\.pl)$! } map { s!\s*$!!; $_ } <$manifest>
}
plan tests => 0+@tests;

my $meta = Parse::CPAN::Meta->load_file('META.json');

# Find what META.* declares
my $explicit_test_prereqs = CPAN::Meta::Prereqs->new( $meta->{prereqs} )->merged_requirements->as_string_hash;
my $minimum_perl = $meta->{prereqs}->{runtime}->{requires}->{perl} || 5.006;

sub distributed_packages {
    my @modules;
    for( @_ ) {
        dir($_)->recurse( callback => sub {
            my( $child ) = @_;
            if( !$child->is_dir and $child =~ /\.pm$/) {
                push @modules, ((scalar $child->slurp()) =~ m/^\s*package\s+(?:#.*?\n\s+)*(\w+(?:::\w+)*)\b/msg);
            }
        });
    };
    map { $_ => $_ } @modules;
}

# Find what we distribute:



( run in 0.401 second using v1.01-cache-2.11-cpan-a5abf4f5562 )