PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.7.3
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.7.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 / reply.php
ai-engine / classes Last commit date
engines 1 year ago modules 1 year ago queries 1 year ago admin.php 2 years ago api.php 1 year ago core.php 1 year ago discussion.php 1 year ago init.php 2 years ago logging.php 1 year ago reply.php 1 year ago rest.php 1 year ago
reply.php
265 lines
1 <?php
2
3 class Meow_MWAI_Reply implements JsonSerializable {
4 public $id = null;
5 public $result = '';
6 public $results = [];
7 public $usage = [
8 'prompt_tokens' => 0,
9 'completion_tokens' => 0,
10 'total_tokens' => 0,
11 'price' => null,
12 ];
13 public $query = null;
14 public $type = 'text';
15
16 // This is when models return a message that needs to be executed (functions, tools, etc)
17 public $needFeedbacks = [];
18 public $needClientActions = [];
19
20 public function __construct( $query = null ) {
21 $this->query = $query;
22 }
23
24 #[\ReturnTypeWillChange]
25 public function jsonSerialize() {
26 $isEmbedding = false;
27 $embeddingsDimensions = null;
28 $embedddingsMessage = null;
29 if ( is_array( $this->results ) && count( $this->results ) > 0 ) {
30 $isEmbedding = is_array( $this->results[0] );
31 if ( $isEmbedding ) {
32 $embeddingsDimensions = count( $this->results[0] );
33 $embedddingsMessage = "A $embeddingsDimensions-dimensional embedding was returned.";
34 }
35 }
36 $data = [
37 'result' => $isEmbedding ? $embedddingsMessage : $this->result,
38 'results' => $isEmbedding ? [] : $this->results,
39 'usage' => $this->usage,
40 'system' => [
41 'class' => get_class( $this ),
42 ]
43 ];
44 if ( !empty( $this->needFeedbacks ) ) {
45 $data['needFeedbacks'] = $this->needFeedbacks;
46 }
47 if ( !empty( $this->needClientActions ) ) {
48 $data['needClientActions'] = $this->needClientActions;
49 }
50 return $data;
51 }
52
53 public function set_usage( $usage ) {
54 $this->usage = $usage;
55 }
56
57 public function set_id( $id ) {
58 $this->id = $id;
59 }
60
61 public function set_type( $type ) {
62 $this->type = $type;
63 }
64
65 public function get_total_tokens() {
66 return $this->usage['total_tokens'];
67 }
68
69 public function get_in_tokens( $query = null ) {
70 $in_tokens = $this->usage['prompt_tokens'];
71 if ( empty( $in_tokens ) && $query ) {
72 $in_tokens = $query->get_in_tokens();
73 }
74 return $in_tokens;
75 }
76
77 public function get_out_tokens() {
78 $out_tokens = $this->usage['completion_tokens'];
79 if ( empty( $out_tokens ) ) {
80 $out_tokens = Meow_MWAI_Core::estimate_tokens( $this->result );
81 }
82 return $out_tokens;
83 }
84
85 public function get_price() {
86 // If it's not set return null, but it can be 0
87 if ( !isset( $this->usage['price'] ) ) {
88 return null;
89 }
90 return $this->usage['price'];
91 }
92
93 public function get_units() {
94 if ( isset( $this->usage['total_tokens'] ) ) {
95 return $this->usage['total_tokens'];
96 }
97 else if ( isset( $this->usage['images'] ) ) {
98 return $this->usage['images'];
99 }
100 else if ( isset( $this->usage['seconds'] ) ) {
101 return $this->usage['seconds'];
102 }
103 return null;
104 }
105
106 public function get_type() {
107 return $this->type;
108 }
109
110 public function set_reply( $reply ) {
111 $this->result = $reply;
112 $this->results[] = [ $reply ];
113 }
114
115 public function replace( $search, $replace ) {
116 $this->result = str_replace( $search, $replace, $this->result );
117 $this->results = array_map( function( $result ) use ( $search, $replace ) {
118 return str_replace( $search, $replace, $result );
119 }, $this->results );
120 }
121
122 private function extract_arguments( $funcArgs ) {
123 $finalArgs = [];
124 if ( is_string( $funcArgs ) ) {
125 $arguments = trim( str_replace( "\n", "", $funcArgs ) );
126 if ( substr( $arguments, 0, 1 ) == '{' ) {
127 $arguments = json_decode( $arguments, true );
128 $finalArgs = $arguments;
129 }
130 }
131 else if ( is_array( $funcArgs ) ) {
132 $finalArgs = $funcArgs;
133 }
134 return $finalArgs;
135 }
136
137 /**
138 * Set the choices from OpenAI as the results.
139 * The last (or only) result is set as the result.
140 * @param array $choices ID of the model to use.
141 */
142 public function set_choices( $choices, $rawMessage = null) {
143 $this->results = [];
144 if ( is_array( $choices ) ) {
145 foreach ( $choices as $choice ) {
146
147 // It's chat completion
148 if ( isset( $choice['message'] ) ) {
149
150 // It's text content
151 if ( isset( $choice['message']['content'] ) ) {
152 $content = trim( $choice['message']['content'] );
153 $this->results[] = $content;
154 $this->result = $content;
155 }
156
157 // It's a tool call (OpenAI-style and Anthropic-style)
158 $toolCalls = [];
159 if ( isset( $choice['message']['tool_calls'] ) ) {
160 $tools = $choice['message']['tool_calls'];
161 foreach ( $tools as $tool ) {
162 if ( $tool['type'] === 'function' ) {
163 $toolCalls[] = [
164 'toolId' => $tool['id'],
165 //'mode' => 'interactive',
166 'type' => 'tool_call',
167 'name' => trim( $tool['function']['name'] ),
168 'arguments' => $this->extract_arguments( $tool['function']['arguments'] ),
169 // Represent the original message that triggered the function call
170 'rawMessage' => $rawMessage ? $rawMessage : $choice['message'],
171 ];
172 }
173 }
174 }
175
176 // If it's a function call (Open-AI style; usually for a final execution)
177 if ( isset( $choice['message']['function_call'] ) ) {
178 $content = $choice['message']['function_call'];
179 $toolCalls[] = [
180 'toolId' => null,
181 'mode' => 'static',
182 'type' => 'function_call',
183 'name' => trim( $choice['message']['function_call']['name'] ),
184 'arguments' => $this->extract_arguments( $tool['message']['function_call']['arguments'] ),
185 'rawMessage' => $rawMessage ? $rawMessage : $choice['message'],
186 ];
187 }
188
189 // Resolve the original function from the query
190 if ( !empty( $toolCalls ) ) {
191 foreach ( $toolCalls as &$toolCall ) {
192 if ( $toolCall['type'] !== 'function_call' && $toolCall['type'] !== 'tool_call' ) {
193 continue;
194 }
195 foreach ( $this->query->functions as $function ) {
196 if ( $function->name == $toolCall['name'] ) {
197 $toolCall['function'] = $function;
198 break;
199 }
200 }
201 }
202 }
203
204 // NOTE: Anaheim proposed that fix to avoid the error "Duplicate value for 'tool_call_id'"
205 // This happens when the same function is called twice; we need to investigate.
206 $toolCallsDeepCopy = array_map( function( $toolCall ) {
207 return is_array( $toolCall ) ? array_merge( [], $toolCall ) : $toolCall;
208 }, $toolCalls);
209 $toolCalls = $toolCallsDeepCopy;
210
211 // Let's separate the Feedbacks (PHP code) and Client Actions (JS code)
212 $this->needFeedbacks = [];
213 $this->needClientActions = [];
214 foreach ( $toolCalls as $toolCall ) {
215 if ( $toolCall['function']->target !== 'js' ) {
216 $this->needFeedbacks[] = $toolCall;
217 }
218 else if ( $toolCall['function']->target === 'js' ) {
219 $this->needClientActions[] = $toolCall;
220 }
221 }
222 }
223
224 // It's text completion
225 else if ( isset( $choice['text'] ) ) {
226
227 // TODO: Assistants return an array (so actually not really a text completion)
228 // We should probably make this clearer and analyze all the outputs from different endpoints.
229 if ( is_array( $choice['text'] ) ) {
230 $text = trim( $choice['text']['value'] );
231 $this->results[] = $text;
232 $this->result = $text;
233 }
234 else {
235 $text = trim( $choice['text'] );
236 $this->results[] = $text;
237 $this->result = $text;
238 }
239 }
240
241 // It's url/image
242 else if ( isset( $choice['url'] ) ) {
243 $url = trim( $choice['url'] );
244 $this->results[] = $url;
245 $this->result = $url;
246 }
247
248 // It's embedding
249 else if ( isset( $choice['embedding'] ) ) {
250 $content = $choice['embedding'];
251 $this->results[] = $content;
252 $this->result = $content;
253 }
254 }
255 }
256 else {
257 $this->result = $choices;
258 $this->results[] = $choices;
259 }
260 }
261
262 public function toJson() {
263 return json_encode( $this );
264 }
265 }