PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.5
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.5
8.0.5 8.0.4 8.0.3 8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 All 47 releases
gamipress / modules / ai-assistant / includes / ajax-functions.php

ajax-functions.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 8.0.5, at modules/ai-assistant/includes/ajax-functions.php

189 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Ajax Functions
4 *
5 * @package GamiPress\AI_Assistant\Ajax_Functions
6 * @since 1.0.0
7 * @version 1.0.0
8 */
9 // Exit if accessed directly
10 if ( ! defined( 'ABSPATH' ) ) exit;
11
12 /**
13 * Process an AI prompt
14 *
15 * @since 1.0.0
16 */
17 function gamipress_ai_assistant_ajax_process_prompt() {
18 // Security check, forces to die if not security passed
19 check_ajax_referer( 'gamipress_admin', 'nonce' );
20
21 // Permissions check
22 if( ! current_user_can( gamipress_get_manager_capability() ) )
23 wp_send_json_error( __( 'You\'re not allowed to perform this action.', 'gamipress' ) );
24
25 // Check prompt
26 $prompt = isset( $_POST['prompt'] ) ? sanitize_text_field( $_POST['prompt'] ) : '';
27
28 if( empty( $prompt ) )
29 wp_send_json_error( __( 'Please, type something.', 'gamipress' ) );
30
31 // Check if supports AI
32 $supports_ai = function_exists('wp_supports_ai') && (bool) call_user_func('wp_supports_ai');
33
34 if( ! $supports_ai )
35 wp_send_json_error( __( 'This assistant requires an AI connector in order to work, please configure at least one.', 'gamipress' ) );
36
37 // Check model
38 $model = isset( $_POST['model'] ) ? sanitize_text_field( $_POST['model'] ) : '';
39
40 if( ! empty( $model ) ) {
41 $models = gamipress_ai_assistant_get_models_ids();
42
43 if( ! in_array( $model, $models ) )
44 $model = '';
45 }
46
47 try {
48 $user_message = \WordPress\AiClient\Messages\DTO\Message::fromArray( array(
49 'role' => 'user',
50 'parts' => array(
51 array(
52 'channel' => 'content',
53 'type' => 'text',
54 'text' => $prompt,
55 ),
56 ),
57 ) );
58 } catch ( \Exception $e ) {
59 wp_send_json_error( __( 'Could not process your prompt.', 'gamipress' ) );
60 }
61
62 // Sanitize history
63 $history = isset( $_POST['history'] ) && is_array( $_POST['history'] ) ? $_POST['history'] : array();
64 $history_messages = array();
65
66 foreach( $history as $prev ) {
67 // Skip invalid entries
68 if( ! isset( $prev['text'] ) || ! isset( $prev['author'] ) ) continue;
69
70 $prev_role = sanitize_text_field( $prev['author'] );
71 $prev_text = sanitize_text_field( $prev['text'] );
72
73 if( empty( $prev_text ) ) continue;
74
75 try {
76 $history_messages[] = \WordPress\AiClient\Messages\DTO\Message::fromArray( array(
77 'role' => $prev_role === 'user' ? 'user' : 'model',
78 'parts' => array(
79 array(
80 'channel' => 'content',
81 'type' => 'text',
82 'text' => $prev_text,
83 ),
84 ),
85 ) );
86 } catch ( \Exception $e ) {
87 // Do not report this error
88 // wp_send_json_error( __( 'Could not process history messages.', 'gamipress' ) );
89 }
90 }
91
92 $history_messages[] = $user_message;
93
94 $abilities = gamipress_ai_assistant_get_abilities();
95
96 $prompt = wp_ai_client_prompt()
97 ->using_system_instruction( gamipress_ai_assistant_get_system_instructions() )
98 ->with_history( ...$history_messages )
99 ->using_abilities( ...$abilities );
100
101 if( ! empty( $model ) )
102 $prompt->using_model_preference( $model );
103
104 $resolver = new WP_AI_Client_Ability_Function_Resolver( ...$abilities );
105
106 // Bail if no models found
107 if ( ! $prompt->is_supported_for_text_generation() )
108 wp_send_json_error( sprintf( __( 'No models found that support %s for this prompt.', 'gamipress' ), __( 'text generation', 'gamipress' ) ) );
109
110 $call = 0;
111 /**
112 * Filter available to modify the maximum ability calls
113 *
114 * @since 1.0.0
115 *
116 * @param integer $max_calls
117 *
118 * @return integer
119 */
120 $max_calls = apply_filters( 'gamipress_ai_assistant_max_ability_calls', 5 );
121 $response = '';
122
123 while ( $call < $max_calls ) {
124
125 $result = $prompt->generate_result();
126
127 // Bail if is a WP_Error
128 if( is_wp_error( $result ) ) {
129
130 // If not is the first call, and we have previous success, send previous messages
131 if( $response !== '' )
132 wp_send_json_success( $response );
133
134 wp_send_json_error( $result->get_error_message() );
135
136 }
137
138 $message = $result->toMessage();
139
140 if( $response !== '' )
141 $response .= "\n";
142
143 try {
144 $response .= $result->toText();
145 } catch ( \Exception $e ) {
146 // Do not report this error
147 // wp_send_json_error( array( 'message' => __( 'Could not process AI result.', 'gamipress' ) ) );
148 }
149
150 // Check if there are abilities to execute
151 if ( $resolver->has_ability_calls( $message ) ) {
152 $response_message = $resolver->execute_abilities( $message );
153
154 $function_responses = gamipress_ai_assistant_get_all_function_responses( $response_message );
155
156 $glue = count( $function_responses ) > 1 ? "\n" : ' ';
157
158 foreach( $function_responses as $i => $function_response ) {
159
160 $g = ( $i === 0 && strlen( $response ) === 0 ? '' : $glue );
161
162 // Function response needs to match our output_schema ( array( 'success' => bool, 'message' => '' )
163 if( isset( $function_response['message'] ) )
164 $response .= $g . $function_response['message'];
165 }
166
167 // For ability calls, after process the call rebuild the prompt
168 $history_messages[] = $response_message;
169
170 // Rebuild the prompt to call it again
171 $prompt = wp_ai_client_prompt()
172 ->using_system_instruction( gamipress_ai_assistant_get_system_instructions() )
173 ->with_history( ...$history_messages )
174 ->using_abilities( ...$abilities );
175
176 if( ! empty( $model ) )
177 $prompt->using_model_preference( $model );
178
179 $call++;
180 continue;
181 }
182
183 // Send back a successful response
184 wp_send_json_success( $response );
185
186 }
187
188 }
189 add_action( 'wp_ajax_gamipress_ai_assistant_process_prompt', 'gamipress_ai_assistant_ajax_process_prompt' );