PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.3.64
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.3.64
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 / core.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 api.php 3 years ago core.php 3 years ago init.php 3 years ago openai.php 3 years ago query.php 3 years ago queryembed.php 3 years ago queryimage.php 3 years ago querytext.php 3 years ago querytranscribe.php 3 years ago rest.php 3 years ago ui.php 3 years ago
core.php
542 lines
1 <?php
2
3 require_once( MWAI_PATH . '/vendor/autoload.php' );
4 require_once( MWAI_PATH . '/constants/init.php' );
5
6 use Rahul900day\Gpt3Encoder\Encoder;
7
8 class Meow_MWAI_Core
9 {
10 public $admin = null;
11 public $is_rest = false;
12 public $is_cli = false;
13 public $site_url = null;
14 public $ai = null;
15 private $option_name = 'mwai_options';
16 public $defaultChatbotParams = MWAI_CHATBOT_PARAMS;
17
18 public function __construct() {
19 $this->site_url = get_site_url();
20 $this->is_rest = MeowCommon_Helpers::is_rest();
21 $this->is_cli = defined( 'WP_CLI' ) && WP_CLI;
22 $this->ai = new Meow_MWAI_AI( $this );
23 add_action( 'plugins_loaded', array( $this, 'init' ) );
24 }
25
26 function init() {
27 global $mwai;
28 $mwai = new Meow_MWAI_API();
29 if ( $this->is_rest ) {
30 new Meow_MWAI_Rest( $this );
31 }
32 if ( is_admin() ) {
33 new Meow_MWAI_Admin( $this );
34 new Meow_MWAI_Modules_Assistants( $this );
35 }
36 else {
37 //new Meow_MWAI_UI( $this );
38 if ( $this->get_option( 'shortcode_chat' ) ) {
39 new Meow_MWAI_Modules_Chatbot();
40 }
41 }
42
43 // Advanced core
44 if ( class_exists( 'MeowPro_MWAI_Core' ) ) {
45 new MeowPro_MWAI_Core( $this );
46 }
47
48 // Dynamic max tokens
49 if ( $this->get_option( 'dynamic_max_tokens' ) ) {
50 add_filter( 'mwai_estimate_tokens', array( $this, 'dynamic_max_tokens' ), 10, 2 );
51 }
52 }
53
54 #region Roles & Capabilities
55
56 function can_access_settings() {
57 return apply_filters( 'mwai_allow_setup', current_user_can( 'manage_options' ) );
58 }
59
60 function can_access_features() {
61 $editor_or_admin = current_user_can( 'editor' ) || current_user_can( 'administrator' );
62 return apply_filters( 'mwai_allow_usage', $editor_or_admin );
63 }
64
65 #endregion
66
67 #region Text-Related Helpers
68
69 // Clean the text perfectly, resolve shortcodes, etc, etc.
70 function clean_text( $rawText = "" ) {
71 $text = strip_tags( $rawText );
72 $text = strip_shortcodes( $text );
73 $text = html_entity_decode( $text );
74 $text = str_replace( array( "\r", "\n" ), "", $text );
75 $sentences = preg_split( '/(?<=[.?!])(?=[a-zA-Z ])/', $text );
76 foreach ( $sentences as $key => $sentence ) {
77 $sentences[$key] = trim( $sentence );
78 }
79 $text = implode( " ", $sentences );
80 $text = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $text );
81 return $text . " ";
82 }
83
84 // Make sure there are no duplicate sentences, and keep the length under a maximum length.
85 function clean_sentences( $text, $maxLength = 1024 ) {
86 $sentences = preg_split( '/(?<=[.?!])(?=[a-zA-Z ])/', $text );
87 $hashes = array();
88 $uniqueSentences = array();
89 $length = 0;
90 foreach ( $sentences as $sentence ) {
91 $sentence = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $sentence );
92 $hash = md5( $sentence );
93 if ( !in_array( $hash, $hashes ) ) {
94 if ( $length + strlen( $sentence ) > $maxLength ) {
95 continue;
96 }
97 $hashes[] = $hash;
98 $uniqueSentences[] = $sentence;
99 $length += strlen( $sentence );
100 }
101 }
102 $text = implode( " ", $uniqueSentences );
103 $text = preg_replace( '/^[\pZ\pC]+|[\pZ\pC]+$/u', '', $text );
104 return $text;
105 }
106
107 function get_text_from_postId( $postId ) {
108 $post = get_post( $postId );
109 if ( !$post ) {
110 return false;
111 }
112 $post->post_content = apply_filters( 'the_content', $post->post_content );
113 $text = $this->clean_text( $post->post_content );
114 $text = $this->clean_sentences( $text );
115 return $text;
116 }
117
118 function markdown_to_html( $content ) {
119 $Parsedown = new Parsedown();
120 $content = $Parsedown->text( $content );
121 return $content;
122 }
123
124 function get_post_language( $postId ) {
125 $locale = get_locale();
126 $code = strtolower( substr( $locale, 0, 2 ) );
127 $lang_codes = array(
128 'aa' => 'Afar',
129 'ab' => 'Abkhazian',
130 'af' => 'Afrikaans',
131 'ak' => 'Akan',
132 'sq' => 'Albanian',
133 'am' => 'Amharic',
134 'ar' => 'Arabic',
135 'an' => 'Aragonese',
136 'hy' => 'Armenian',
137 'as' => 'Assamese',
138 'av' => 'Avaric',
139 'ae' => 'Avestan',
140 'ay' => 'Aymara',
141 'az' => 'Azerbaijani',
142 'ba' => 'Bashkir',
143 'bm' => 'Bambara',
144 'eu' => 'Basque',
145 'be' => 'Belarusian',
146 'bn' => 'Bengali',
147 'bh' => 'Bihari',
148 'bi' => 'Bislama',
149 'bs' => 'Bosnian',
150 'br' => 'Breton',
151 'bg' => 'Bulgarian',
152 'my' => 'Burmese',
153 'ca' => 'Catalan; Valencian',
154 'ch' => 'Chamorro',
155 'ce' => 'Chechen',
156 'zh' => 'Chinese',
157 'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
158 'cv' => 'Chuvash',
159 'kw' => 'Cornish',
160 'co' => 'Corsican',
161 'cr' => 'Cree',
162 'cs' => 'Czech',
163 'da' => 'Danish',
164 'dv' => 'Divehi; Dhivehi; Maldivian',
165 'nl' => 'Dutch; Flemish',
166 'dz' => 'Dzongkha',
167 'en' => 'English',
168 'eo' => 'Esperanto',
169 'et' => 'Estonian',
170 'ee' => 'Ewe',
171 'fo' => 'Faroese',
172 'fj' => 'Fijjian',
173 'fi' => 'Finnish',
174 'fr' => 'French',
175 'fy' => 'Western Frisian',
176 'ff' => 'Fulah',
177 'ka' => 'Georgian',
178 'de' => 'German',
179 'gd' => 'Gaelic; Scottish Gaelic',
180 'ga' => 'Irish',
181 'gl' => 'Galician',
182 'gv' => 'Manx',
183 'el' => 'Greek, Modern',
184 'gn' => 'Guarani',
185 'gu' => 'Gujarati',
186 'ht' => 'Haitian; Haitian Creole',
187 'ha' => 'Hausa',
188 'he' => 'Hebrew',
189 'hz' => 'Herero',
190 'hi' => 'Hindi',
191 'ho' => 'Hiri Motu',
192 'hu' => 'Hungarian',
193 'ig' => 'Igbo',
194 'is' => 'Icelandic',
195 'io' => 'Ido',
196 'ii' => 'Sichuan Yi',
197 'iu' => 'Inuktitut',
198 'ie' => 'Interlingue',
199 'ia' => 'Interlingua (International Auxiliary Language Association)',
200 'id' => 'Indonesian',
201 'ik' => 'Inupiaq',
202 'it' => 'Italian',
203 'jv' => 'Javanese',
204 'ja' => 'Japanese',
205 'kl' => 'Kalaallisut; Greenlandic',
206 'kn' => 'Kannada',
207 'ks' => 'Kashmiri',
208 'kr' => 'Kanuri',
209 'kk' => 'Kazakh',
210 'km' => 'Central Khmer',
211 'ki' => 'Kikuyu; Gikuyu',
212 'rw' => 'Kinyarwanda',
213 'ky' => 'Kirghiz; Kyrgyz',
214 'kv' => 'Komi',
215 'kg' => 'Kongo',
216 'ko' => 'Korean',
217 'kj' => 'Kuanyama; Kwanyama',
218 'ku' => 'Kurdish',
219 'lo' => 'Lao',
220 'la' => 'Latin',
221 'lv' => 'Latvian',
222 'li' => 'Limburgan; Limburger; Limburgish',
223 'ln' => 'Lingala',
224 'lt' => 'Lithuanian',
225 'lb' => 'Luxembourgish; Letzeburgesch',
226 'lu' => 'Luba-Katanga',
227 'lg' => 'Ganda',
228 'mk' => 'Macedonian',
229 'mh' => 'Marshallese',
230 'ml' => 'Malayalam',
231 'mi' => 'Maori',
232 'mr' => 'Marathi',
233 'ms' => 'Malay',
234 'mg' => 'Malagasy',
235 'mt' => 'Maltese',
236 'mo' => 'Moldavian',
237 'mn' => 'Mongolian',
238 'na' => 'Nauru',
239 'nv' => 'Navajo; Navaho',
240 'nr' => 'Ndebele, South; South Ndebele',
241 'nd' => 'Ndebele, North; North Ndebele',
242 'ng' => 'Ndonga',
243 'ne' => 'Nepali',
244 'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian',
245 'nb' => 'Bokmål, Norwegian, Norwegian Bokmål',
246 'no' => 'Norwegian',
247 'ny' => 'Chichewa; Chewa; Nyanja',
248 'oc' => 'Occitan, Provençal',
249 'oj' => 'Ojibwa',
250 'or' => 'Oriya',
251 'om' => 'Oromo',
252 'os' => 'Ossetian; Ossetic',
253 'pa' => 'Panjabi; Punjabi',
254 'fa' => 'Persian',
255 'pi' => 'Pali',
256 'pl' => 'Polish',
257 'pt' => 'Portuguese',
258 'ps' => 'Pushto',
259 'qu' => 'Quechua',
260 'rm' => 'Romansh',
261 'ro' => 'Romanian',
262 'rn' => 'Rundi',
263 'ru' => 'Russian',
264 'sg' => 'Sango',
265 'sa' => 'Sanskrit',
266 'sr' => 'Serbian',
267 'hr' => 'Croatian',
268 'si' => 'Sinhala; Sinhalese',
269 'sk' => 'Slovak',
270 'sl' => 'Slovenian',
271 'se' => 'Northern Sami',
272 'sm' => 'Samoan',
273 'sn' => 'Shona',
274 'sd' => 'Sindhi',
275 'so' => 'Somali',
276 'st' => 'Sotho, Southern',
277 'es' => 'Spanish; Castilian',
278 'sc' => 'Sardinian',
279 'ss' => 'Swati',
280 'su' => 'Sundanese',
281 'sw' => 'Swahili',
282 'sv' => 'Swedish',
283 'ty' => 'Tahitian',
284 'ta' => 'Tamil',
285 'tt' => 'Tatar',
286 'te' => 'Telugu',
287 'tg' => 'Tajik',
288 'tl' => 'Tagalog',
289 'th' => 'Thai',
290 'bo' => 'Tibetan',
291 'ti' => 'Tigrinya',
292 'to' => 'Tonga (Tonga Islands)',
293 'tn' => 'Tswana',
294 'ts' => 'Tsonga',
295 'tk' => 'Turkmen',
296 'tr' => 'Turkish',
297 'tw' => 'Twi',
298 'ug' => 'Uighur; Uyghur',
299 'uk' => 'Ukrainian',
300 'ur' => 'Urdu',
301 'uz' => 'Uzbek',
302 've' => 'Venda',
303 'vi' => 'Vietnamese',
304 'vo' => 'Volapük',
305 'cy' => 'Welsh',
306 'wa' => 'Walloon',
307 'wo' => 'Wolof',
308 'xh' => 'Xhosa',
309 'yi' => 'Yiddish',
310 'yo' => 'Yoruba',
311 'za' => 'Zhuang; Chuang',
312 'zu' => 'Zulu',
313 );
314 $language = strtr( $code, $lang_codes );
315 $lang = apply_filters( 'wpml_post_language_details', null, $postId );
316 if ( !empty( $lang ) ) {
317 $language = $lang['display_name'];
318 }
319 return strtolower( $language );
320 }
321 #endregion
322
323 #region Users/Sessions Helpers
324
325 function get_session_id() {
326 if ( isset( $_COOKIE['mwai_session_id'] ) ) {
327 return $_COOKIE['mwai_session_id'];
328 }
329 return "N/A";
330 }
331
332 // Get the UserID from the data, or from the current user
333 function get_user_id( $data = null ) {
334 if ( isset( $data ) && isset( $data['userId'] ) ) {
335 return (int)$data['userId'];
336 }
337 if ( is_user_logged_in() ) {
338 $current_user = wp_get_current_user();
339 if ( $current_user->ID > 0 ) {
340 return $current_user->ID;
341 }
342 }
343 return null;
344 }
345
346 function get_ip_address( $data = null ) {
347 if ( isset( $data ) && isset( $data['ip'] ) ) {
348 $data['ip'] = (string)$data['ip'];
349 }
350 else {
351 if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
352 $data['ip'] = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
353 }
354 else if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
355 $data['ip'] = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] );
356 }
357 else if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
358 $data['ip'] = sanitize_text_field( $_SERVER['HTTP_X_FORWARDED_FOR'] );
359 }
360 }
361 return $data['ip'];
362 }
363
364 #endregion
365
366 #region Other Helpers
367
368 function isUrl( $url ) {
369 return strpos( $url, 'http' ) === 0 ? true : false;
370 }
371
372 function getPostTypes() {
373 $excluded = array( 'attachment', 'revision', 'nav_menu_item' );
374 $post_types = array();
375 $types = get_post_types( array( 'public' => true ), 'objects' );
376 foreach ( $types as $type ) {
377 if ( in_array( $type->name, $excluded ) ) {
378 continue;
379 }
380 $post_types[] = array(
381 'name' => $type->labels->name,
382 'type' => $type->name,
383 );
384 }
385 return $post_types;
386 }
387
388 #endregion
389
390 #region Usage & Costs
391
392 public function dynamic_max_tokens( $tokens, $text ) {
393 // Approximation (fast, no lib)
394 $asciiCount = 0;
395 $nonAsciiCount = 0;
396 for ( $i = 0; $i < mb_strlen( $text ); $i++ ) {
397 $char = mb_substr( $text, $i, 1 );
398 if ( ord( $char ) < 128 ) {
399 $asciiCount++;
400 }
401 else {
402 $nonAsciiCount++;
403 }
404 }
405 $asciiTokens = $asciiCount / 3.5;
406 $nonAsciiTokens = $nonAsciiCount * 2.5;
407 $tokens = $asciiTokens + $nonAsciiTokens;
408
409 // More exact (slower, and lib)
410 if ( PHP_VERSION_ID >= 70400 ) {
411 try {
412 $token_array = Encoder::encode( $text );
413 if ( !empty( $token_array ) ) {
414 $tokens = count( $token_array );
415 }
416 }
417 catch ( Exception $e ) {
418 error_log( $e->getMessage() );
419 }
420 }
421
422 $tokens = $tokens;
423 return (int)$tokens;
424 }
425
426 public function record_tokens_usage( $model, $prompt_tokens, $completion_tokens = 0 ) {
427 if ( !is_numeric( $prompt_tokens ) ) {
428 throw new Exception( 'Record usage: prompt_tokens is not a number.' );
429 }
430 if ( !is_numeric( $completion_tokens ) ) {
431 $completion_tokens = 0;
432 }
433 if ( !$model ) {
434 throw new Exception( 'Record usage: model is missing.' );
435 }
436 $usage = $this->get_option( 'openai_usage' );
437 $month = date( 'Y-m' );
438 if ( !isset( $usage[$month] ) ) {
439 $usage[$month] = array();
440 }
441 if ( !isset( $usage[$month][$model] ) ) {
442 $usage[$month][$model] = array(
443 'prompt_tokens' => 0,
444 'completion_tokens' => 0,
445 'total_tokens' => 0
446 );
447 }
448 $usage[$month][$model]['prompt_tokens'] += $prompt_tokens;
449 $usage[$month][$model]['completion_tokens'] += $completion_tokens;
450 $usage[$month][$model]['total_tokens'] += $prompt_tokens + $completion_tokens;
451 $this->update_option( 'openai_usage', $usage );
452 return [
453 'prompt_tokens' => $prompt_tokens,
454 'completion_tokens' => $completion_tokens,
455 'total_tokens' => $prompt_tokens + $completion_tokens
456 ];
457 }
458
459 public function record_images_usage( $model, $resolution, $images ) {
460 if ( !$model || !$resolution || !$images ) {
461 throw new Exception( 'Missing parameters for record_image_usage.' );
462 }
463 $usage = $this->get_option( 'openai_usage' );
464 $month = date( 'Y-m' );
465 if ( !isset( $usage[$month] ) ) {
466 $usage[$month] = array();
467 }
468 if ( !isset( $usage[$month][$model] ) ) {
469 $usage[$month][$model] = array(
470 'resolution' => array(),
471 'images' => 0
472 );
473 }
474 if ( !isset( $usage[$month][$model]['resolution'][$resolution] ) ) {
475 $usage[$month][$model]['resolution'][$resolution] = 0;
476 }
477 $usage[$month][$model]['resolution'][$resolution] += $images;
478 $usage[$month][$model]['images'] += $images;
479 $this->update_option( 'openai_usage', $usage );
480 return [
481 'resolution' => $resolution,
482 'images' => $images
483 ];
484 }
485
486 #endregion
487
488 #region Options
489 function get_all_options() {
490 $options = get_option( $this->option_name, null );
491 foreach ( MWAI_OPTIONS as $key => $value ) {
492 if ( !isset( $options[$key] ) ) {
493 $options[$key] = $value;
494 }
495 if ( $key === 'languages' ) {
496 // TODO: If we decide to make a set of options for languages, we can keep it in the settings
497 $options[$key] = MWAI_LANGUAGES;
498 $options[$key] = apply_filters( 'mwai_languages', $options[$key] );
499 }
500 }
501 $options['shortcode_chat_default_params'] = MWAI_CHATBOT_PARAMS;
502 $options['default_limits'] = MWAI_LIMITS;
503 $options['openai_models'] = MWAI_OPENAI_MODELS;
504 return $options;
505 }
506
507 // Validate and keep the options clean and logical.
508 function sanitize_options() {
509 $options = $this->get_all_options();
510 $needs_update = false;
511
512 // We can sanitize our future options here, let's always remember it.
513 // Now, it is empty...
514
515 if ( $needs_update ) {
516 update_option( $this->option_name, $options, false );
517 }
518 return $options;
519 }
520
521 function update_options( $options ) {
522 if ( !update_option( $this->option_name, $options, false ) ) {
523 return false;
524 }
525 $options = $this->sanitize_options();
526 return $options;
527 }
528
529 function update_option( $option, $value ) {
530 $options = $this->get_all_options();
531 $options[$option] = $value;
532 return $this->update_options( $options );
533 }
534
535 function get_option( $option, $default = null ) {
536 $options = $this->get_all_options();
537 return $options[$option] ?? $default;
538 }
539 #endregion
540 }
541
542 ?>