PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 0.8.3
AI Engine – The Chatbot, AI Framework & MCP for WordPress v0.8.3
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
253 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];
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" => 120,
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 }
169 catch (Exception $e) {
170 error_log($e->getMessage());
171 throw new Exception('Error while calling OpenAI: ' . $e->getMessage());
172 }
173 }
174
175 private function calculatePrice( $model, $units, $option = null )
176 {
177 foreach ( MWAI_OPENAI_PRICING as $price ) {
178 if ( $price['model'] == $model ) {
179 if ( $price['type'] == 'image' ) {
180 if ( !$option ) {
181 error_log( "AI Engine: Image models require an option." );
182 return null;
183 }
184 else {
185 foreach ( $price['options'] as $imageType ) {
186 if ( $imageType['option'] == $option ) {
187 return $imageType['price'] * $units;
188 }
189 }
190 }
191 }
192 else {
193 return $price['price'] * $price['unit'] * $units;
194 }
195 }
196 }
197 error_log( "AI Engine: Invalid model ($model)." );
198 return null;
199 }
200
201 public function getPrice( Meow_MWAI_Query $query, Meow_MWAI_Answer $answer )
202 {
203 $model = $query->model;
204 $modelBase = null;
205 $units = 0;
206 $option = null;
207 if ( is_a( $query, 'Meow_MWAI_QueryText' ) ) {
208 // Finetuned models
209 if ( preg_match('/^([a-zA-Z]{0,32}):/', $model, $matches ) ) {
210 $modelBase = "fn-" . $matches[1];
211 }
212 // Standard models
213 else if ( preg_match('/^text-(\w+)-\d+/', $model, $matches ) ) {
214 $modelBase = $matches[1];
215 }
216 if ( empty( $modelBase ) ) {
217 error_log("AI Engine: Cannot find the base model for $model.");
218 return null;
219 }
220 $units = $answer->getTotalTokens();
221 }
222 else if ( is_a( $query, 'Meow_MWAI_QueryImage' ) ) {
223 $modelBase = 'dall-e';
224 $units = $query->maxResults;
225 $option = "1024x1024";
226 }
227 return $this->calculatePrice( $modelBase, $units, $option );
228 }
229
230 public function getIncidents() {
231 $url = 'https://status.openai.com/history.rss';
232 $response = wp_remote_get( $url );
233 if ( is_wp_error( $response ) ) {
234 throw new Exception( $response->get_error_message() );
235 }
236 $response = wp_remote_retrieve_body( $response );
237 $xml = simplexml_load_string( $response );
238 $incidents = array();
239 $oneWeekAgo = time() - 7 * 24 * 60 * 60;
240 foreach ( $xml->channel->item as $item ) {
241 $date = strtotime( $item->pubDate );
242 if ( $date > $oneWeekAgo ) {
243 $incidents[] = array(
244 'title' => (string) $item->title,
245 'description' => (string) $item->description,
246 'date' => $date
247 );
248 }
249 }
250 return $incidents;
251 }
252 }
253