PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.6.72
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.6.72
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 / querytext.php
ai-engine / classes Last commit date
engines 3 years ago modules 3 years ago admin.php 3 years ago api.php 3 years ago core.php 3 years ago init.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 reply.php 3 years ago rest.php 3 years ago
querytext.php
380 lines
1 <?php
2
3 class Meow_MWAI_QueryText extends Meow_MWAI_Query implements JsonSerializable {
4 public int $maxTokens = 1024;
5 public float $temperature = 0.8;
6 public int $maxSentences = 15;
7 public bool $isChat = false;
8 public ?string $stop = null;
9 public array $messages = [];
10 public ?string $context = null;
11 public ?string $newMessage = null;
12 public ?string $promptEnding = null;
13 public bool $casuallyFineTuned = false;
14
15 public function __construct( ?string $prompt = '', int $maxTokens = 1024, string $model = 'gpt-3.5-turbo' ) {
16 parent::__construct( $prompt );
17 $this->setModel( $model );
18 $this->setMaxTokens( $maxTokens );
19 }
20
21 public function jsonSerialize() {
22 return [
23 'class' => get_class( $this ),
24 'prompt' => $this->prompt,
25 'messages' => $this->messages,
26 'maxTokens' => $this->maxTokens,
27 'temperature' => $this->temperature,
28 'maxSentences' => $this->maxSentences,
29 'isChat' => $this->isChat,
30 'stop' => $this->stop,
31 'context' => $this->context,
32 'newMessage' => $this->newMessage,
33 'promptEnding' => $this->promptEnding,
34 'casuallyFineTuned' => $this->casuallyFineTuned,
35 'model' => $this->model,
36 'mode' => $this->mode,
37 'session' => $this->session,
38 'env' => $this->env,
39 'service' => $this->service,
40 ];
41 }
42
43 public function getLastPrompt(): string {
44 if ( empty( $this->messages ) ) {
45 return $this->prompt;
46 }
47 $lastMessage = end( $this->messages );
48 return $lastMessage['content'];
49 }
50
51 // Quick and dirty token estimation
52 // Let's keep this synchronized with Helpers in JS
53 function estimateTokens( $content ): int
54 {
55 $text = "";
56 // https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
57 if ( is_array( $content ) ) {
58 foreach ( $content as $message ) {
59 $role = $message['role'];
60 $content = $message['content'];
61 $text .= "=#=$role\n$content=#=\n";
62 }
63 }
64 else {
65 $text = $content;
66 }
67 $tokens = 0;
68 return apply_filters( 'mwai_estimate_tokens', (int)$tokens, $text, $this->model );
69 }
70
71 /**
72 * Make sure the maxTokens is not greater than the model's context length.
73 */
74 public function finalChecks() {
75 if ( empty( $this->model ) ) { return; }
76
77 // Make sure the number of messages is not too great
78 if ( !empty( $this->maxSentences ) ) {
79 $context = array_shift( $this->messages );
80 if ( !empty( $this->messages ) ) {
81 $this->messages = array_slice( $this->messages, -$this->maxSentences * 2 );
82 }
83 else {
84 $this->messages = [];
85 }
86 if ( !empty( $context ) ) {
87 array_unshift( $this->messages, $context );
88 }
89 }
90
91 // Make sure the max tokens are respected.
92 $realMax = 4096;
93 $finetuneFamily = preg_match('/^([a-zA-Z]{0,32}):/', $this->model, $matches );
94 $finetuneFamily = ( isset( $matches ) && count( $matches ) > 0 ) ? $matches[1] : 'N/A';
95 $foundModel = null;
96 foreach ( MWAI_OPENAI_MODELS as $currentModel ) {
97 if ( $currentModel['model'] === $this->model || $currentModel['family'] === $finetuneFamily ) {
98 $foundModel = $currentModel['name'];
99 $realMax = $currentModel['maxTokens'];
100 break;
101 }
102 }
103 $estimatedTokens = $this->estimateTokens( $this->messages );
104 if ( !empty( $realMax ) && $estimatedTokens > $realMax ) {
105 throw new Exception( "AI Engine: The prompt is too long! It contains about $estimatedTokens tokens (estimation). The $foundModel model only accepts a maximum of $realMax tokens. " );
106 }
107 $realMax = (int)($realMax - $estimatedTokens) - 16;
108 if ( $this->maxTokens > $realMax ) {
109 $this->maxTokens = $realMax;
110 }
111 }
112
113 /**
114 * ID of the model to use.
115 * @param string $model ID of the model to use.
116 */
117 public function setModel( string $model ) {
118 $this->model = $model;
119 $this->mode = 'completion';
120 foreach ( MWAI_OPENAI_MODELS as $currentModel ) {
121 if ( $currentModel['model'] === $this->model ) {
122 if ( $currentModel['mode'] ) {
123 $this->mode = $currentModel['mode'];
124 }
125 break;
126 }
127 }
128 }
129
130 /**
131 * Given a prompt, the model will return one or more predicted completions.
132 * It can also return the probabilities of alternative tokens at each position.
133 * @param string $prompt The prompt to generate completions.
134 */
135 public function setPrompt( $prompt ) {
136 parent::setPrompt( $prompt );
137 $this->validateMessages();
138 }
139
140 /**
141 * The prompt is used by models who uses Text Completion (and not Chat Completion).
142 * This returns the prompt if it's not a chat, otherwise it will build a prompt with
143 * all the messages nicely formatted.
144 */
145 public function getPrompt(): ?string {
146 if ( !$this->isChat ) {
147 return $this->prompt;
148 }
149
150 $first = reset( $this->messages );
151 $prompt = "";
152 if ( $first && $first['role'] === 'system' ) {
153 $prompt = $first['content'] . "\n\n";
154 }
155
156 // Casually Fine-Tuned or Prompt-Ending
157 if ( !empty( $this->promptEnding ) ) {
158 $last = end( $this->messages );
159 if ( $last && $last['role'] === 'user' ) {
160 $prompt = $last['content'] . $this->promptEnding;
161 }
162 return $prompt;
163 }
164
165 // Standard Completion
166 while ( $message = next( $this->messages ) ) {
167 $role = $message['role'];
168 $content = $message['content'];
169 if ( $role === 'system' ) {
170 $prompt .= "$content\n\n";
171 }
172 if ( $role === 'user' ) {
173 $prompt .= "User: $content\n";
174 }
175 if ( $role === 'assistant' ) {
176 $prompt .= "AI: $content\n";
177 }
178 }
179 $prompt .= "AI: ";
180 return $prompt;
181 }
182
183 /**
184 * Similar to the prompt, but focus on the new/last message.
185 * Only used when the model has a chat mode (and only used in messages).
186 * @param string $prompt The messages to generate completions.
187 */
188 public function setNewMessage( string $newMessage ): void {
189 $this->newMessage = $newMessage;
190 $this->validateMessages();
191 }
192
193 public function replace( $search, $replace ) {
194 $this->prompt = str_replace( $search, $replace, $this->prompt );
195 $this->validateMessages();
196 }
197
198 public function setIsChat( $isChat ) {
199 $this->isChat = $isChat;
200 }
201
202 /**
203 * Similar to the prompt, but use an array of messages instead.
204 * @param string $prompt The messages to generate completions.
205 */
206 public function setMessages( array $messages ) {
207 $messages = array_map( function( $message ) {
208 return [ 'role' => $message['role'], 'content' => $message['content'] ];
209 }, $messages );
210 $this->messages = $messages;
211 $this->validateMessages();
212 }
213
214 public function getLastMessage(): ?string {
215 if ( !empty( $this->messages ) ) {
216 $lastMessageIndex = count( $this->messages ) - 1;
217 $lastMessage = $this->messages[$lastMessageIndex];
218 return $lastMessage['content'];
219 }
220 return null;
221 }
222
223 // Function that adds a message just before the last message
224 public function injectContext( string $content ): void {
225 if ( !empty( $this->messages ) ) {
226 $lastMessageIndex = count( $this->messages ) - 1;
227 $lastMessage = $this->messages[$lastMessageIndex];
228 $this->messages[$lastMessageIndex] = [ 'role' => 'system', 'content' => $content ];
229 array_push( $this->messages, $lastMessage );
230 }
231 $this->validateMessages();
232 }
233
234 /**
235 * The context that is used for the chat completion (mode === 'chat').
236 * @param string $context The context to use.
237 */
238 public function setContext( string $context ): void {
239 $this->context = apply_filters( 'mwai_ai_context', $context, $this );
240 $this->validateMessages();
241 }
242
243 private function validateMessages(): void {
244 // Messages should end with either the prompt or, if exists, the newMessage.
245 $message = empty( $this->newMessage ) ? $this->prompt : $this->newMessage;
246 if ( empty( $this->messages ) ) {
247 $this->messages = [ [ 'role' => 'user', 'content' => $message ] ];
248 }
249 else {
250 $last = &$this->messages[ count( $this->messages ) - 1 ];
251 if ( $last['role'] === 'user' ) {
252 $last['content'] = $message;
253 }
254 else {
255 array_push( $this->messages, [ 'role' => 'user', 'content' => $message ] );
256 }
257 }
258
259 // The main context must be first.
260 if ( !empty( $this->context ) ) {
261 if ( is_array( $this->messages ) && count( $this->messages ) > 0 ) {
262 if ( $this->messages[0]['role'] !== 'system' ) {
263 array_unshift( $this->messages, [ 'role' => 'system', 'content' => $this->context ] );
264 }
265 else {
266 $this->messages[0]['content'] = $this->context;
267 }
268 }
269 }
270 }
271
272 /**
273 * The maximum number of tokens to generate in the completion.
274 * The token count of your prompt plus max_tokens cannot exceed the model's context length.
275 * Most models have a context length of 2048 tokens (except for the newest models, which support 4096).
276 * @param float $prompt The maximum number of tokens.
277 */
278 public function setMaxTokens( int $maxTokens ): void {
279 $this->maxTokens = $maxTokens;
280 }
281
282 /**
283 * Set the sampling temperature to use. Higher values means the model will take more risks.
284 * Try 0.9 for more creative applications, and 0 for ones with a well-defined reply.
285 * @param float $temperature The temperature.
286 */
287 public function setTemperature( float $temperature ): void {
288 $temperature = floatval( $temperature );
289 if ( $temperature > 1 ) {
290 $temperature = 1;
291 }
292 if ( $temperature < 0 ) {
293 $temperature = 0;
294 }
295 $this->temperature = round( $temperature, 2 );
296 }
297
298 public function setMaxSentences( int $maxSentences ): void {
299 if ( !empty( $maxSentences ) ) {
300 $this->maxSentences = intval( $maxSentences );
301 $this->validateMessages();
302 }
303 }
304
305 public function setStop( string $stop ): void {
306 $this->stop = $stop;
307 }
308
309 // Based on the params of the query, update the attributes
310 public function injectParams( array $params ): void {
311 if ( isset( $params['model'] ) ) {
312 $this->setModel( $params['model'] );
313 }
314 if ( isset( $params['casually_fine_tuned'] ) && $params['casually_fine_tuned'] === true ) {
315 $this->promptEnding = "\\n\\n###\\n\\n";
316 $this->stop = "\\n\\n";
317 $this->casuallyFineTuned = true;
318 }
319 if ( isset( $params['casuallyFineTuned'] ) && $params['casuallyFineTuned'] === true ) {
320 $this->promptEnding = "\\n\\n###\\n\\n";
321 $this->stop = "\\n\\n";
322 $this->casuallyFineTuned = true;
323 }
324 if ( isset( $params['prompt'] ) ) {
325 $this->setPrompt( $params['prompt'] );
326 }
327 if ( isset( $params['context'] ) ) {
328 $this->setContext( $params['context'] );
329 }
330 if ( isset( $params['messages'] ) ) {
331 $this->setMessages( $params['messages'] );
332 }
333 if ( isset( $params['new_message'] ) ) {
334 $this->setNewMessage( $params['newMessage'] );
335 }
336 if ( isset( $params['newMessage'] ) ) {
337 $this->setNewMessage( $params['newMessage'] );
338 }
339 if ( isset( $params['max_tokens'] ) && intval( $params['max_tokens'] ) > 0 ) {
340 $this->setMaxTokens( intval( $params['max_tokens'] ) );
341 }
342 if ( isset( $params['maxTokens'] ) && intval( $params['maxTokens'] ) > 0 ) {
343 $this->setMaxTokens( intval( $params['maxTokens'] ) );
344 }
345 if ( isset( $params['max_messages'] ) && intval( $params['max_messages'] ) > 0 ) {
346 $this->setMaxSentences( intval( $params['max_messages'] ) );
347 }
348 if ( isset( $params['maxSentences'] ) && intval( $params['maxSentences'] ) > 0 ) {
349 $this->setMaxSentences( intval( $params['maxSentences'] ) );
350 }
351 if ( isset( $params['temperature'] ) ) {
352 $this->setTemperature( $params['temperature'] );
353 }
354 if ( isset( $params['stop'] ) ) {
355 $this->setStop( $params['stop'] );
356 }
357 if ( isset( $params['max_results'] ) ) {
358 $this->setMaxResults( $params['max_results'] );
359 }
360 if ( isset( $params['maxResults'] ) ) {
361 $this->setMaxResults( $params['maxResults'] );
362 }
363 if ( isset( $params['env'] ) ) {
364 $this->setEnv( $params['env'] );
365 }
366 if ( isset( $params['session'] ) ) {
367 $this->setSession( $params['session'] );
368 }
369 // Should add the params related to Open AI and Azure
370 if ( isset( $params['service'] ) ) {
371 $this->setService( $params['service'] );
372 }
373 if ( isset( $params['api_key'] ) ) {
374 $this->setApiKey( $params['apiKey'] );
375 }
376 if ( isset( $params['apiKey'] ) ) {
377 $this->setApiKey( $params['apiKey'] );
378 }
379 }
380 }