PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 0.5.0
AI Engine – The Chatbot, AI Framework & MCP for WordPress v0.5.0
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / openai.php
ai-engine / classes Last commit date
modules 3 years ago admin.php 3 years ago ai.php 3 years ago answer.php 3 years ago core.php 3 years ago init.php 3 years ago openai.php 3 years ago query.php 3 years ago queryimage.php 3 years ago querytext.php 3 years ago rest.php 3 years ago ui.php 3 years ago
openai.php
252 lines
1 <?php
2
3 class Meow_MWAI_OpenAI
4 {
5 private $core = null;
6 private $apiKey = null;
7
8 public function __construct($core)
9 {
10 $this->core = $core;
11 $this->apiKey = $this->core->get_option('openai_apikey');
12 }
13
14 public function listFiles()
15 {
16 return $this->run('GET', '/files');
17 }
18
19 function getSuffixForModel($model)
20 {
21 preg_match("/:([a-zA-Z\-]{1,40})-([0-9]{4})-([0-9]{2})-([0-9]{2})/", $model, $matches);
22 if (count($matches) > 0) {
23 return $matches[1] . ' (' . $matches[2] . '/' . $matches[3] . '/' . $matches[4] . ')';
24 }
25 return 'N/A';
26 }
27
28 function getBaseModel($model)
29 {
30 preg_match("/:([a-zA-Z\-]{1,40})-([0-9]{4})-([0-9]{2})-([0-9]{2})/", $model, $matches);
31 if (count($matches) > 0) {
32 return $matches[1];
33 }
34 return 'N/A';
35 }
36
37 public function listFineTunes()
38 {
39 $finetunes = $this->run('GET', '/fine-tunes');
40 $finetunes['data'] = array_map(function ($finetune) {
41 $finetune['suffix'] = $this->getSuffixForModel($finetune['fine_tuned_model']);
42 return $finetune;
43 }, $finetunes['data']);
44
45 // Get option openai_finetunes_deleted
46 $deleted_finetunes = $this->core->get_option('openai_finetunes_deleted');
47 // Remove all deleted finetunes from the list, make a new array, without using array_filter
48
49 $finetunes['data'] = array_values(array_filter($finetunes['data'], function ($finetune) use ($deleted_finetunes) {
50 return !in_array($finetune['fine_tuned_model'], $deleted_finetunes);
51 }));
52
53 $finetunes_option = $this->core->get_option('openai_finetunes');
54 $fresh_finetunes_options = array_map(function ($finetune) use ($finetunes_option) {
55 $entry = [];
56 $model = $finetune['fine_tuned_model'];
57 $entry['suffix'] = $finetune['suffix'];
58 $entry['model'] = $model;
59 $entry['enabled'] = true;
60 for ($i = 0; $i < count($finetunes_option); $i++) {
61 if ($finetunes_option[$i]['model'] === $model) {
62 $entry['enabled'] = $finetunes_option[$i]['enabled'];
63 break;
64 }
65 }
66 return $entry;
67 }, $finetunes['data']);
68 $this->core->update_option('openai_finetunes', $fresh_finetunes_options);
69 return $finetunes;
70 }
71
72 public function uploadFile($filename, $data)
73 {
74 $result = $this->run('POST', '/files', null, ['data' => $data, 'filename' => $filename]);
75 return $result;
76 }
77
78 public function deleteFile($fileId)
79 {
80 return $this->run('DELETE', '/files/' . $fileId);
81 }
82
83 public function deleteFineTune($modelId)
84 {
85 return $this->run('DELETE', '/models/' . $modelId);
86 }
87
88 public function downloadFile($fileId)
89 {
90 return $this->run('GET', '/files/' . $fileId . '/content', null, null, false);
91 }
92
93 public function fineTuneFile($fileId, $model, $suffix)
94 {
95 $result = $this->run('POST', '/fine-tunes', [
96 'training_file' => $fileId,
97 'model' => $model,
98 'suffix' => $suffix
99 ]);
100 return $result;
101 }
102
103 public function create_body_for_file($file, $boundary)
104 {
105 $fields = array(
106 'purpose' => 'fine-tune',
107 'file' => $file['filename']
108 );
109
110 $body = '';
111 foreach ($fields as $name => $value) {
112 $body .= "--$boundary\r\n";
113 $body .= "Content-Disposition: form-data; name=\"$name\"";
114 if ($name == 'file') {
115 $body .= "; filename=\"{$value}\"\r\n";
116 $body .= "Content-Type: application/json\r\n\r\n";
117 $body .= $file['data'] . "\r\n";
118 } else {
119 $body .= "\r\n\r\n$value\r\n";
120 }
121 }
122 $body .= "--$boundary--\r\n";
123 return $body;
124 }
125
126 public function run($method, $url, $query = null, $file = null, $json = true)
127 {
128 $apiKey = $this->apiKey;
129 $headers = "Content-Type: application/json\r\n" . "Authorization: Bearer " . $apiKey . "\r\n";
130 $body = $query ? json_encode($query) : null;
131 if (!empty($file)) {
132 $boundary = wp_generate_password(24, false);
133 $headers = [
134 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
135 'Authorization' => 'Bearer ' . $this->apiKey,
136 ];
137 $body = $this->create_body_for_file($file, $boundary);
138 }
139
140 $url = 'https://api.openai.com/v1' . $url;
141 $options = [
142 "headers" => $headers,
143 "method" => $method,
144 "timeout" => 60,
145 "body" => $body,
146 "sslverify" => false
147 ];
148
149 try {
150 $response = wp_remote_request($url, $options);
151 if (is_wp_error($response)) {
152 throw new Exception($response->get_error_message());
153 }
154 $response = wp_remote_retrieve_body($response);
155 $data = $json ? json_decode($response, true) : $response;
156
157 // Error handling
158 if (isset($data['error'])) {
159 $message = $data['error']['message'];
160 // If the message contains "Incorrect API key provided: THE_KEY.", replace the key by "----".
161 if (preg_match('/API key provided(: .*)\./', $message, $matches)) {
162 $message = str_replace($matches[1], '', $message);
163 }
164 throw new Exception($message);
165 }
166
167 return $data;
168 } catch (Exception $e) {
169 error_log($e->getMessage());
170 throw new Exception('Error while calling OpenAI: ' . $e->getMessage());
171 }
172 }
173
174 private function calculatePrice( $model, $units, $option = null )
175 {
176 foreach ( MWAI_OPENAI_PRICING as $price ) {
177 if ( $price['model'] == $model ) {
178 if ( $price['type'] == 'image' ) {
179 if ( !$option ) {
180 error_log( "AI Engine: Image models require an option." );
181 return null;
182 }
183 else {
184 foreach ( $price['options'] as $imageType ) {
185 if ( $imageType['option'] == $option ) {
186 return $imageType['price'] * $units;
187 }
188 }
189 }
190 }
191 else {
192 return $price['price'] * $price['unit'] * $units;
193 }
194 }
195 }
196 error_log( "AI Engine: Invalid model ($model)." );
197 return null;
198 }
199
200 public function getPrice( Meow_MWAI_Query $query, Meow_MWAI_Answer $answer )
201 {
202 $model = $query->model;
203 $modelBase = null;
204 $units = 0;
205 $option = null;
206 if ( is_a( $query, 'Meow_MWAI_QueryText' ) ) {
207 // Finetuned models
208 if ( preg_match('/^([a-zA-Z]{0,32}):/', $model, $matches ) ) {
209 $modelBase = "fn-" . $matches[1];
210 }
211 // Standard models
212 else if ( preg_match('/^text-(\w+)-\d+/', $model, $matches ) ) {
213 $modelBase = $matches[1];
214 }
215 if ( empty( $modelBase ) ) {
216 error_log("AI Engine: Cannot find the base model for $model.");
217 return null;
218 }
219 $units = $answer->getTotalTokens();
220 }
221 else if ( is_a( $query, 'Meow_MWAI_QueryImage' ) ) {
222 $modelBase = 'dall-e';
223 $units = $query->maxResults;
224 $option = "1024x1024";
225 }
226 return $this->calculatePrice( $modelBase, $units, $option );
227 }
228
229 public function getIncidents() {
230 $url = 'https://status.openai.com/history.rss';
231 $response = wp_remote_get( $url );
232 if ( is_wp_error( $response ) ) {
233 throw new Exception( $response->get_error_message() );
234 }
235 $response = wp_remote_retrieve_body( $response );
236 $xml = simplexml_load_string( $response );
237 $incidents = array();
238 $oneWeekAgo = time() - 7 * 24 * 60 * 60;
239 foreach ( $xml->channel->item as $item ) {
240 $date = strtotime( $item->pubDate );
241 if ( $date > $oneWeekAgo ) {
242 $incidents[] = array(
243 'title' => (string) $item->title,
244 'description' => (string) $item->description,
245 'date' => $date
246 );
247 }
248 }
249 return $incidents;
250 }
251 }
252