PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.3
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.3
6.0.3 6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 All 34 releases
automatorwp / modules / ai-assistant / includes / ajax-functions.php

ajax-functions.php in AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI 6.0.3, at modules/ai-assistant/includes/ajax-functions.php

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