PluginProbe
wpForo Forum / 3.1.6
wpForo Forum v3.1.6
3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 All 138 releases
wpforo / admin / pages / tabs / ai-features-tab-ai-tools.php

ai-features-tab-ai-tools.php in wpForo Forum 3.1.6, at admin/pages/tabs/ai-features-tab-ai-tools.php

431 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * AI Features - AI Tools Tab (Custom Knowledge)
4 *
5 * Allows Business+ tenants to upload custom knowledge files (JSON/Markdown/Text)
6 * and configure priority settings for AI features.
7 *
8 * @package wpForo
9 * @subpackage Admin
10 * @since 3.0.0
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Render AI Tools tab content
19 *
20 * @param bool $is_connected Whether tenant is connected to AI service
21 * @param array $status Tenant status data from API
22 */
23 function wpforo_ai_render_ai_tools_tab( $is_connected, $status ) {
24 if ( ! $is_connected ) {
25 ?>
26 <div class="wpforo-ai-box wpforo-ai-not-connected-notice">
27 <div class="wpforo-ai-box-body">
28 <div class="wpforo-ai-status-badge status-warning">
29 <span class="dashicons dashicons-warning"></span>
30 <?php _e( 'Not Connected', 'wpforo' ); ?>
31 </div>
32 <p><?php _e( 'Please connect to wpForo AI API first in the Overview tab to enable AI Tools.', 'wpforo' ); ?></p>
33 <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=overview' ) ); ?>" class="button button-primary">
34 <?php _e( 'Go to Overview', 'wpforo' ); ?>
35 </a>
36 </div>
37 </div>
38 <?php
39 return;
40 }
41
42 // Feature gate check - Business+ plan required
43 $custom_knowledge_available = isset( WPF()->ai_client ) && WPF()->ai_client->is_feature_available( 'custom_knowledge' );
44 if ( ! $custom_knowledge_available ) {
45 ?>
46 <div class="wpforo-ai-box wpforo-ai-upgrade-notice">
47 <div class="wpforo-ai-box-body">
48 <div class="wpforo-ai-status-badge status-warning">
49 <span class="dashicons dashicons-lock"></span>
50 <?php _e( 'Business Plan Required', 'wpforo' ); ?>
51 </div>
52 <p><?php _e( 'Custom Knowledge is available on Business and Enterprise plans. Upgrade to upload your own knowledge files for AI-powered search, chatbot, and bot replies.', 'wpforo' ); ?></p>
53 <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=overview' ) ); ?>" class="button button-primary">
54 <?php _e( 'View Plans', 'wpforo' ); ?>
55 </a>
56 </div>
57 </div>
58 <?php
59 return;
60 }
61
62 // Check storage mode - custom knowledge requires cloud mode
63 $storage_manager = WPF()->vector_storage->for_board( 0 );
64 $storage_mode = $storage_manager->get_storage_mode();
65
66 if ( $storage_mode !== 'cloud' ) {
67 ?>
68 <div class="wpforo-ai-box wpforo-ai-upgrade-notice">
69 <div class="wpforo-ai-box-body">
70 <div class="wpforo-ai-status-badge status-warning">
71 <span class="dashicons dashicons-cloud"></span>
72 <?php _e( 'Cloud Storage Required', 'wpforo' ); ?>
73 </div>
74 <p><?php _e( 'Custom Knowledge requires Cloud storage mode. Please switch to Cloud storage in the Forum Indexing tab to use this feature.', 'wpforo' ); ?></p>
75 <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=rag_indexing' ) ); ?>" class="button button-primary">
76 <?php _e( 'Go to Forum Indexing', 'wpforo' ); ?>
77 </a>
78 </div>
79 </div>
80 <?php
81 return;
82 }
83
84 // Get remaining credits
85 $remaining_credits = 0;
86 if ( isset( $status['subscription']['credits_remaining'] ) ) {
87 $remaining_credits = (int) $status['subscription']['credits_remaining'];
88 }
89
90 // Get all boards for board settings
91 $all_boards = WPF()->board->get_boards( [ 'status' => true ] );
92 $is_multiboard = count( $all_boards ) > 1;
93 ?>
94
95 <div class="wpforo-ai-tools-tab">
96
97 <!-- Add Custom Knowledge Box -->
98 <div class="wpforo-ai-box wpforo-ai-knowledge-upload-box">
99 <div class="wpforo-ai-box-header">
100 <h2>
101 <span class="dashicons dashicons-database-add"></span>
102 <?php _e( 'Add Custom Knowledge', 'wpforo' ); ?>
103 </h2>
104 </div>
105 <div class="wpforo-ai-box-body">
106 <p class="wpforo-ai-section-desc kind-text">
107 <span class="dashicons dashicons-media-text desc-icon"></span>
108 <?php _e( 'Add JSON, Markdown, or Text files to enhance AI search, chatbot, and bot replies with your custom content.', 'wpforo' ); ?>
109 </p>
110
111 <form id="wpforo-ai-knowledge-upload-form" class="wpforo-ai-knowledge-form kind-text">
112 <div class="wpforo-ai-url-input-group">
113 <input type="url"
114 id="knowledge-file-url"
115 name="file_url"
116 placeholder="<?php esc_attr_e( 'Select a TXT, MD, or JSON file from Media Library or paste URL', 'wpforo' ); ?>"
117 required>
118 <button type="button" class="button" id="knowledge-media-btn">
119 <span class="dashicons dashicons-admin-media"></span>
120 <?php _e( 'Media Library', 'wpforo' ); ?>
121 </button>
122 <button type="submit" class="button button-primary" id="knowledge-upload-btn" style="width: 20%; text-align: center; display: inline-block;">
123 <?php _e( 'Index Text File', 'wpforo' ); ?>
124 </button>
125 </div>
126
127 <!-- Hidden fields for auto-detected values -->
128 <input type="hidden" id="knowledge-file-type" name="file_type" value="text">
129 <input type="hidden" id="knowledge-file-name" name="name" value="">
130
131 <div class="wpforo-ai-upload-info">
132 <div class="wpforo-ai-file-detected" id="knowledge-file-detected" style="display: none;">
133 <span class="file-icon"></span>
134 <span class="file-name"></span>
135 <span class="file-type-badge"></span>
136 </div>
137 <div class="wpforo-ai-credits-info">
138 <span class="dashicons dashicons-database"></span>
139 <?php printf(
140 __( 'Credits: %s remaining', 'wpforo' ),
141 '<strong>' . number_format( $remaining_credits ) . '</strong>'
142 ); ?>
143 <span class="wpforo-ai-credit-rate"><?php _e( '(1 credit per 100KB or 1 file with small size, max 20MB)', 'wpforo' ); ?></span>
144 </div>
145 </div>
146
147 <div class="wpforo-ai-upload-progress" id="knowledge-upload-progress" style="display: none;">
148 <div class="wpforo-ai-progress-bar">
149 <div class="wpforo-ai-progress-fill"></div>
150 </div>
151 <div class="wpforo-ai-progress-text"></div>
152 </div>
153 </form>
154
155 <p class="wpforo-ai-section-desc kind-pdf" style="margin-top: 24px;">
156 <span class="dashicons dashicons-media-document desc-icon"></span>
157 <?php _e( 'Add PDF files to enhance AI search, chatbot, and bot replies with your custom content.', 'wpforo' ); ?>
158 </p>
159
160 <form id="wpforo-ai-knowledge-pdf-upload-form" class="wpforo-ai-knowledge-form kind-pdf">
161 <div class="wpforo-ai-url-input-group">
162 <input type="url"
163 id="knowledge-pdf-file-url"
164 name="file_url"
165 placeholder="<?php esc_attr_e( 'Select a PDF from Media Library or paste URL', 'wpforo' ); ?>"
166 required>
167 <button type="button" class="button" id="knowledge-pdf-media-btn">
168 <span class="dashicons dashicons-admin-media"></span>
169 <?php _e( 'Media Library', 'wpforo' ); ?>
170 </button>
171 <button type="submit" class="button button-primary" id="knowledge-pdf-upload-btn" style="width: 20%; text-align: center; display: inline-block;">
172 <?php _e( 'Index PDF File', 'wpforo' ); ?>
173 </button>
174 </div>
175
176 <input type="hidden" id="knowledge-pdf-file-type" name="file_type" value="pdf">
177 <input type="hidden" id="knowledge-pdf-file-name" name="name" value="">
178
179 <div class="wpforo-ai-upload-info">
180 <div class="wpforo-ai-file-detected" id="knowledge-pdf-file-detected" style="display: none;">
181 <span class="file-icon"></span>
182 <span class="file-name"></span>
183 <span class="file-type-badge"></span>
184 </div>
185 <div class="wpforo-ai-credits-info">
186 <span class="dashicons dashicons-database"></span>
187 <?php printf(
188 __( 'Credits: %s remaining', 'wpforo' ),
189 '<strong>' . number_format( $remaining_credits ) . '</strong>'
190 ); ?>
191 <span class="wpforo-ai-credit-rate"><?php _e( '(1 credit per 1 page, max 50MB)', 'wpforo' ); ?></span>
192 </div>
193 </div>
194
195 <div class="wpforo-ai-upload-progress" id="knowledge-pdf-upload-progress" style="display: none;">
196 <div class="wpforo-ai-progress-bar">
197 <div class="wpforo-ai-progress-fill"></div>
198 </div>
199 <div class="wpforo-ai-progress-text"></div>
200 </div>
201 </form>
202
203 <details class="wpforo-ai-file-format-help">
204 <summary><?php _e( 'Supported file formats', 'wpforo' ); ?></summary>
205 <div class="wpforo-ai-format-list">
206 <div class="format-item">
207 <strong>.json</strong> - <?php _e( 'Array of objects with "title" and "content" fields (recommended)', 'wpforo' ); ?>
208 </div>
209 <div class="format-item">
210 <strong>.md</strong> - <?php _e( 'Markdown with ## headings to split into chunks', 'wpforo' ); ?>
211 </div>
212 <div class="format-item">
213 <strong>.txt</strong> - <?php _e( 'Plain text, split by "---" separators or paragraphs', 'wpforo' ); ?>
214 </div>
215 <div class="format-item">
216 <strong>.pdf</strong> - <?php _e( 'PDF documents — each page becomes a section. Scanned/image-only PDFs are auto-OCR\'d when text is too sparse.', 'wpforo' ); ?>
217 </div>
218 </div>
219 </details>
220 </div>
221 </div>
222
223 <!-- Indexed Knowledge Files Box -->
224 <div class="wpforo-ai-box wpforo-ai-knowledge-files-box">
225 <div class="wpforo-ai-box-header">
226 <h2>
227 <span class="dashicons dashicons-media-document"></span>
228 <?php _e( 'Indexed Knowledge Files', 'wpforo' ); ?>
229 <span class="wpforo-ai-file-count" id="knowledge-file-count"></span>
230 </h2>
231 <div class="wpforo-ai-header-actions">
232 <button type="button" class="button button-small" id="knowledge-refresh-files">
233 <span class="dashicons dashicons-update"></span>
234 <?php _e( 'Refresh', 'wpforo' ); ?>
235 </button>
236 </div>
237 </div>
238 <div class="wpforo-ai-box-body">
239 <div id="knowledge-files-loading" class="wpforo-ai-loading">
240 <span class="spinner is-active"></span>
241 <?php _e( 'Loading files...', 'wpforo' ); ?>
242 </div>
243
244 <div id="knowledge-files-empty" class="wpforo-ai-empty-state" style="display: none;">
245 <span class="dashicons dashicons-portfolio"></span>
246 <p><?php _e( 'No knowledge files indexed yet. Upload your first file above.', 'wpforo' ); ?></p>
247 </div>
248
249 <table id="knowledge-files-table" class="wp-list-table widefat fixed striped" style="display: none;">
250 <thead>
251 <tr>
252 <th class="column-name"><?php _e( 'Name', 'wpforo' ); ?></th>
253 <th class="column-type"><?php _e( 'Type', 'wpforo' ); ?></th>
254 <th class="column-size"><?php _e( 'Size', 'wpforo' ); ?></th>
255 <th class="column-chunks"><?php _e( 'Chunks', 'wpforo' ); ?></th>
256 <th class="column-credits"><?php _e( 'Credits', 'wpforo' ); ?></th>
257 <th class="column-status"><?php _e( 'Status', 'wpforo' ); ?></th>
258 <th class="column-actions"><?php _e( 'Actions', 'wpforo' ); ?></th>
259 </tr>
260 </thead>
261 <tbody id="knowledge-files-tbody">
262 </tbody>
263 <tfoot>
264 <tr class="wpforo-ai-files-totals">
265 <td class="column-name"><strong><?php _e( 'Total', 'wpforo' ); ?></strong></td>
266 <td class="column-type"></td>
267 <td class="column-size" id="knowledge-total-size">-</td>
268 <td class="column-chunks" id="knowledge-total-chunks">0</td>
269 <td class="column-credits" id="knowledge-total-credits">0</td>
270 <td class="column-status"></td>
271 <td class="column-actions"></td>
272 </tr>
273 </tfoot>
274 </table>
275 </div>
276 </div>
277
278 <!-- Board Settings Box -->
279 <div class="wpforo-ai-box wpforo-ai-knowledge-settings-box">
280 <div class="wpforo-ai-box-header">
281 <h2>
282 <span class="dashicons dashicons-admin-settings"></span>
283 <?php _e( 'Board Settings', 'wpforo' ); ?>
284 </h2>
285 </div>
286 <div class="wpforo-ai-box-body">
287 <?php if ( $is_multiboard ) : ?>
288 <div class="wpforo-ai-board-selector">
289 <label for="knowledge-board-select"><?php _e( 'Select Board:', 'wpforo' ); ?></label>
290 <select id="knowledge-board-select">
291 <?php foreach ( $all_boards as $board ) : ?>
292 <option value="<?php echo esc_attr( $board['boardid'] ); ?>">
293 <?php echo esc_html( $board['title'] ); ?>
294 </option>
295 <?php endforeach; ?>
296 </select>
297 </div>
298 <?php else : ?>
299 <input type="hidden" id="knowledge-board-select" value="0">
300 <?php endif; ?>
301
302 <form id="wpforo-ai-knowledge-settings-form" class="wpforo-ai-settings-form">
303 <input type="hidden" name="board_id" id="knowledge-settings-board-id" value="0">
304
305 <div id="knowledge-settings-loading" class="wpforo-ai-loading">
306 <span class="spinner is-active"></span>
307 <?php _e( 'Loading settings...', 'wpforo' ); ?>
308 </div>
309
310 <div id="knowledge-settings-content" style="display: none;">
311 <!-- Enable/Disable Toggle -->
312 <div class="wpforo-ai-setting-row wpforo-ai-enable-row">
313 <label class="wpforo-ai-toggle-label">
314 <span class="wpforo-ai-toggle">
315 <input type="checkbox" name="enabled" id="knowledge-enabled" value="1">
316 <span class="wpforo-ai-toggle-slider"></span>
317 </span>
318 <span class="toggle-text"><?php _e( 'Enable Custom Knowledge for this board', 'wpforo' ); ?></span>
319 </label>
320 <p class="description"><?php _e( 'When enabled, AI Search, Chatbot, and Bot Reply will include your custom knowledge files.', 'wpforo' ); ?></p>
321 </div>
322
323 <!-- Priority Settings (hidden by default, shown when enabled) -->
324 <div id="knowledge-priority-section" style="display: none;">
325 <h4><?php _e( 'Source Priority', 'wpforo' ); ?></h4>
326 <p class="description"><?php _e( 'Higher priority sources appear first and influence AI responses more.', 'wpforo' ); ?></p>
327
328 <div class="wpforo-ai-priority-row">
329 <label><?php _e( 'AI Search', 'wpforo' ); ?></label>
330 <div class="wpforo-ai-priority-selects">
331 <select name="search_priority[]" class="priority-select" data-feature="search">
332 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
333 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
334 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
335 </select>
336 <span class="priority-arrow"></span>
337 <select name="search_priority[]" class="priority-select" data-feature="search">
338 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
339 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
340 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
341 </select>
342 <span class="priority-arrow"></span>
343 <select name="search_priority[]" class="priority-select" data-feature="search">
344 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
345 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
346 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
347 </select>
348 </div>
349 </div>
350
351 <div class="wpforo-ai-priority-row">
352 <label><?php _e( 'AI Chatbot', 'wpforo' ); ?></label>
353 <div class="wpforo-ai-priority-selects">
354 <select name="chat_priority[]" class="priority-select" data-feature="chat">
355 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
356 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
357 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
358 </select>
359 <span class="priority-arrow"></span>
360 <select name="chat_priority[]" class="priority-select" data-feature="chat">
361 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
362 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
363 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
364 </select>
365 <span class="priority-arrow"></span>
366 <select name="chat_priority[]" class="priority-select" data-feature="chat">
367 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
368 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
369 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
370 </select>
371 </div>
372 </div>
373
374 <div class="wpforo-ai-priority-row">
375 <label><?php _e( 'Bot Reply', 'wpforo' ); ?></label>
376 <div class="wpforo-ai-priority-selects">
377 <select name="bot_reply_priority[]" class="priority-select" data-feature="bot_reply">
378 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
379 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
380 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
381 </select>
382 <span class="priority-arrow"></span>
383 <select name="bot_reply_priority[]" class="priority-select" data-feature="bot_reply">
384 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
385 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
386 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
387 </select>
388 <span class="priority-arrow"></span>
389 <select name="bot_reply_priority[]" class="priority-select" data-feature="bot_reply">
390 <option value="wordpress"><?php _e( 'WordPress', 'wpforo' ); ?></option>
391 <option value="forum"><?php _e( 'Forum', 'wpforo' ); ?></option>
392 <option value="custom_knowledge"><?php _e( 'Custom Knowledge', 'wpforo' ); ?></option>
393 </select>
394 </div>
395 </div>
396 </div>
397
398 <div class="wpforo-ai-form-actions">
399 <button type="submit" class="button button-primary" id="knowledge-save-settings">
400 <?php _e( 'Save Settings', 'wpforo' ); ?>
401 </button>
402 <span class="wpforo-ai-save-status" id="settings-save-status"></span>
403 </div>
404 </div>
405 </form>
406 </div>
407 </div>
408
409 </div>
410
411 <!-- Delete Confirmation Modal -->
412 <div id="knowledge-delete-modal" class="wpforo-ai-modal" style="display: none;">
413 <div class="wpforo-ai-modal-content">
414 <div class="wpforo-ai-modal-header">
415 <h3><?php _e( 'Delete Knowledge File', 'wpforo' ); ?></h3>
416 <button type="button" class="wpforo-ai-modal-close">&times;</button>
417 </div>
418 <div class="wpforo-ai-modal-body">
419 <p><?php _e( 'Are you sure you want to delete this knowledge file? This will remove all indexed vectors and cannot be undone.', 'wpforo' ); ?></p>
420 <p class="wpforo-ai-delete-file-name"></p>
421 </div>
422 <div class="wpforo-ai-modal-footer">
423 <button type="button" class="button" id="knowledge-delete-cancel"><?php _e( 'Cancel', 'wpforo' ); ?></button>
424 <button type="button" class="button button-danger" id="knowledge-delete-confirm"><?php _e( 'Delete', 'wpforo' ); ?></button>
425 </div>
426 </div>
427 </div>
428
429 <?php
430 }
431