line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package OpenAIGPT4; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
672
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
4
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.18'; # Incremented version number |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
690
|
use LWP::UserAgent; |
|
1
|
|
|
|
|
54261
|
|
|
1
|
|
|
|
|
39
|
|
9
|
1
|
|
|
1
|
|
467
|
use LWP::Protocol::https; |
|
1
|
|
|
|
|
98177
|
|
|
1
|
|
|
|
|
53
|
|
10
|
1
|
|
|
1
|
|
514
|
use HTTP::Request::Common qw(POST); |
|
1
|
|
|
|
|
2396
|
|
|
1
|
|
|
|
|
64
|
|
11
|
1
|
|
|
1
|
|
692
|
use JSON; |
|
1
|
|
|
|
|
8459
|
|
|
1
|
|
|
|
|
4
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
OpenAIGPT4 - Interact with the OpenAI GPT-3,4 API |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 VERSION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Version 0.18 |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use OpenAIGPT4; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $gpt = OpenAIGPT4->new(''); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
print "ChatGPT: Hello! Let's start a conversation.\n"; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
while (1) { |
30
|
|
|
|
|
|
|
print "User: "; |
31
|
|
|
|
|
|
|
my $user_input = ; |
32
|
|
|
|
|
|
|
chomp $user_input; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Send the user's input to the API and receive a response |
35
|
|
|
|
|
|
|
my $response = $gpt->generate_text($user_input); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# Display the response |
38
|
|
|
|
|
|
|
print "ChatGPT: $response\n"; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# Check for exit condition (e.g., input of the keyword "exit") |
41
|
|
|
|
|
|
|
if ($user_input eq 'exit') { |
42
|
|
|
|
|
|
|
last; # Exit the loop to end the conversation |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 DESCRIPTION |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
OpenAIGPT4 is a Perl module that enables developers to interface with the OpenAI GPT-3,4 API. With this module, you can easily generate natural language text. It also supports a debug flag to log HTTP request and response details. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head1 METHODS |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head2 new |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $gpt = OpenAIGPT4->new('', 'http://open_ai_host_url', 1); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
This constructor returns a new OpenAIGPT4 object. You must pass your OpenAI API key as the argument. The open ai host url is optional, and can be used for running against a LocalAI API server. The last parameter is the debug flag. If set to 1, the module will print HTTP request and response details to STDOUT. |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 generate_text |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
my $response = $gpt->generate_text('Hello, how are you?', 'gpt-4'); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
This method generates text given a prompt. The first argument should be a string containing the prompt. The second argument is optional and can be used to specify the model to be used for the generation. If no model is specified, it defaults to 'gpt-3.5-turbo-0613'. It returns the generated text. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 AUTHOR |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Kawamura Shingo, |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Copyright 2023 Kawamura Shingo. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub new { |
77
|
1
|
|
|
1
|
1
|
622
|
my ($class, $api_key, $api_host, $debug) = @_; |
78
|
|
|
|
|
|
|
|
79
|
1
|
|
50
|
|
|
9
|
my $self = { |
|
|
|
50
|
|
|
|
|
80
|
|
|
|
|
|
|
api_key => $api_key, |
81
|
|
|
|
|
|
|
ua => LWP::UserAgent->new, |
82
|
|
|
|
|
|
|
api_host => $api_host // 'https://api.openai.com', |
83
|
|
|
|
|
|
|
history => [], # Keep track of conversation history |
84
|
|
|
|
|
|
|
debug => $debug // 0, # Add debug flag |
85
|
|
|
|
|
|
|
}; |
86
|
|
|
|
|
|
|
|
87
|
1
|
|
|
|
|
2729
|
return bless $self, $class; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub generate_text { |
91
|
0
|
|
|
0
|
1
|
|
my ($self, $prompt, $model, $temperature) = @_; |
92
|
|
|
|
|
|
|
|
93
|
0
|
|
0
|
|
|
|
$model //= 'gpt-3.5-turbo-0613'; |
94
|
0
|
|
0
|
|
|
|
$temperature //= 0.7; |
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
push @{$self->{history}}, {role => 'user', content => $prompt}; |
|
0
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
my $req = POST $self->{api_host}.'/v1/chat/completions', |
99
|
|
|
|
|
|
|
Content_Type => 'application/json', |
100
|
|
|
|
|
|
|
Content => to_json({ |
101
|
|
|
|
|
|
|
model => $model, |
102
|
|
|
|
|
|
|
messages => $self->{history}, |
103
|
|
|
|
|
|
|
temperature => $temperature, |
104
|
|
|
|
|
|
|
}), |
105
|
0
|
|
|
|
|
|
Authorization => 'Bearer ' . $self->{api_key}; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# Log request if debug flag is set |
108
|
0
|
0
|
|
|
|
|
if($self->{debug}){ |
109
|
0
|
|
|
|
|
|
print "Request: ", $req->as_string, "\n"; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
my $res = $self->{ua}->request($req); |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Log response if debug flag is set |
115
|
0
|
0
|
|
|
|
|
if($self->{debug}){ |
116
|
0
|
|
|
|
|
|
print "Response: ", $res->as_string, "\n"; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
0
|
0
|
|
|
|
|
if ($res->is_success) { |
120
|
0
|
|
|
|
|
|
my $data = from_json($res->decoded_content); |
121
|
0
|
|
|
|
|
|
my $reply = $data->{choices}[0]{message}{content}; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Add the model's reply to the conversation history |
124
|
0
|
|
|
|
|
|
push @{$self->{history}}, {role => 'system', content => $reply}; |
|
0
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
return $reply; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
else { |
129
|
0
|
|
|
|
|
|
my $error_message = $res->status_line; |
130
|
0
|
0
|
|
|
|
|
if ($res->content) { |
131
|
0
|
|
|
|
|
|
my $error_data = eval { from_json($res->content) }; |
|
0
|
|
|
|
|
|
|
132
|
0
|
0
|
|
|
|
|
if ($@) { |
133
|
0
|
|
|
|
|
|
$error_message .= " Error decoding response body: $@"; |
134
|
|
|
|
|
|
|
} else { |
135
|
0
|
|
|
|
|
|
$error_message .= " Response body: " . to_json($error_data); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
} |
138
|
0
|
|
|
|
|
|
die $error_message; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
1; |