AI-Anthropic
view release on metacpan or search on metacpan
"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',
## 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 2.942 seconds using v1.01-cache-2.11-cpan-df04353d9ac )