AI-Anthropic

 view release on metacpan or  search on metacpan

META.json  view on Meta::CPAN

            "Test::More" : "0.88"
         }
      }
   },
   "release_status" : "stable",
   "resources" : {
      "bugtracker" : {
         "web" : "https://github.com/yourusername/AI-Anthropic/issues"
      },
      "repository" : {
         "type" : "git",
         "url" : "https://github.com/yourusername/AI-Anthropic.git",
         "web" : "https://github.com/yourusername/AI-Anthropic"
      }
   },
   "version" : "0.01",
   "x_serialization_backend" : "JSON::PP version 4.16"
}

Makefile.PL  view on Meta::CPAN

    },
    
    TEST_REQUIRES => {
        'Test::More' => '0.88',
    },
    
    META_MERGE => {
        'meta-spec' => { version => 2 },
        resources => {
            repository => {
                type => 'git',
                url  => 'https://github.com/yourusername/AI-Anthropic.git',
                web  => 'https://github.com/yourusername/AI-Anthropic',
            },
            bugtracker => {
                web => 'https://github.com/yourusername/AI-Anthropic/issues',
            },
        },
        keywords => [
            'anthropic', 'claude', 'ai', 'llm', 'api', 
            'chatbot', 'gpt', 'language-model',

README.md  view on Meta::CPAN


## Vision (Images)

```perl
# From file
my $response = $claude->chat(
    messages => [
        {
            role    => 'user',
            content => [
                { type => 'text', text => 'What is in this image?' },
                { type => 'image', path => '/path/to/image.jpg' },
            ],
        },
    ],
);

# From URL
my $response = $claude->chat(
    messages => [
        {
            role    => 'user',
            content => [
                { type => 'text', text => 'Describe this image' },
                { type => 'image', url => 'https://example.com/image.png' },
            ],
        },
    ],
);
```

## Tool Use (Function Calling)

```perl
my $response = $claude->chat(
    messages => [
        { role => 'user', content => 'What is the weather in Baku?' },
    ],
    tools => [
        {
            name        => 'get_weather',
            description => 'Get current weather for a location',
            input_schema => {
                type       => 'object',
                properties => {
                    location => {
                        type        => 'string',
                        description => 'City name',
                    },
                },
                required => ['location'],
            },
        },
    ],
);
```

lib/AI/Anthropic.pm  view on Meta::CPAN

    my ($self, $messages) = @_;
    
    my @normalized;
    for my $msg (@$messages) {
        my $content = $msg->{content};
        
        # Handle image content
        if (ref $content eq 'ARRAY') {
            my @parts;
            for my $part (@$content) {
                if ($part->{type} eq 'image' && $part->{path}) {
                    # Load image from file
                    push @parts, $self->_image_from_file($part->{path});
                } elsif ($part->{type} eq 'image' && $part->{url}) {
                    # Load image from URL
                    push @parts, $self->_image_from_url($part->{url});
                } elsif ($part->{type} eq 'image' && $part->{base64}) {
                    push @parts, {
                        type   => 'image',
                        source => {
                            type         => 'base64',
                            media_type   => $part->{media_type} // 'image/png',
                            data         => $part->{base64},
                        },
                    };
                } else {
                    push @parts, $part;
                }
            }
            push @normalized, { role => $msg->{role}, content => \@parts };
        } else {
            push @normalized, $msg;

lib/AI/Anthropic.pm  view on Meta::CPAN


sub _image_from_file {
    my ($self, $path) = @_;
    
    open my $fh, '<:raw', $path
        or croak "Cannot open image file '$path': $!";
    local $/;
    my $data = <$fh>;
    close $fh;
    
    # Detect media type
    my $media_type = 'image/png';
    if ($path =~ /\.jpe?g$/i) {
        $media_type = 'image/jpeg';
    } elsif ($path =~ /\.gif$/i) {
        $media_type = 'image/gif';
    } elsif ($path =~ /\.webp$/i) {
        $media_type = 'image/webp';
    }
    
    return {
        type   => 'image',
        source => {
            type       => 'base64',
            media_type => $media_type,
            data       => encode_base64($data, ''),
        },
    };
}

sub _image_from_url {
    my ($self, $url) = @_;
    
    return {
        type   => 'image',
        source => {
            type => 'url',
            url  => $url,
        },
    };
}

sub _request {
    my ($self, $body) = @_;
    
    my $response = $self->{_http}->post(
        $self->{api_base} . '/v1/messages',

lib/AI/Anthropic.pm  view on Meta::CPAN

                
                # Parse SSE events
                for my $line (split /\n/, $chunk) {
                    next unless $line =~ /^data: (.+)/;
                    my $data = $1;
                    next if $data eq '[DONE]';
                    
                    eval {
                        my $event = $self->{_json}->decode($data);
                        
                        if ($event->{type} eq 'content_block_delta') {
                            my $text = $event->{delta}{text} // '';
                            $full_text .= $text;
                            $callback->($text) if $callback;
                        } elsif ($event->{type} eq 'message_stop') {
                            $response_data = $event;
                        }
                    };
                }
            },
        }
    );
    
    unless ($response->{success}) {
        return $self->_handle_response($response);

lib/AI/Anthropic.pm  view on Meta::CPAN

    my $claude = AI::Anthropic->new;
    print $claude->message("Hello, Claude!");

=head2 With image (vision)

    my $response = $claude->chat(
        messages => [
            {
                role    => 'user',
                content => [
                    { type => 'text', text => 'What is in this image?' },
                    { type => 'image', path => '/path/to/image.jpg' },
                ],
            },
        ],
    );

=head2 Tool use (function calling)

    my $response = $claude->chat(
        messages => [
            { role => 'user', content => 'What is the weather in London?' },
        ],
        tools => [
            {
                name        => 'get_weather',
                description => 'Get current weather for a location',
                input_schema => {
                    type       => 'object',
                    properties => {
                        location => {
                            type        => 'string',
                            description => 'City name',
                        },
                    },
                    required => ['location'],
                },
            },
        ],
    );

=head2 Streaming



( run in 0.658 second using v1.01-cache-2.11-cpan-df04353d9ac )