Debug module AI

This commit is contained in:
Laurent Destailleur 2024-03-06 00:46:04 +01:00
parent c27551cbb7
commit 5c4c39da2a
6 changed files with 125 additions and 66 deletions

View File

@ -38,11 +38,6 @@ if (empty($action)) {
$action = 'edit';
}
$value = GETPOST('value', 'alpha');
$label = GETPOST('label', 'alpha');
$scandir = GETPOST('scan_dir', 'alpha');
$type = 'myobject';
$error = 0;
$setupnotempty = 0;
@ -71,8 +66,12 @@ $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
// List of AI features
$arrayofaifeatures = array(
'emailing' => 'Emailing',
'imagegeneration' => 'ImageGeneration'
'textgeneration' => array('label' => 'TextGeneration', 'picto'=>'', 'status'=>'development'),
'imagegeneration' => array('label' => 'ImageGeneration', 'picto'=>'', 'status'=>'notused'),
'videogeneration' => array('label' => 'VideoGeneration', 'picto'=>'', 'status'=>'notused'),
'transcription' => array('label' => 'Transcription', 'picto'=>'', 'status'=>'notused'),
'translation' => array('label' => 'Translation', 'picto'=>'', 'status'=>'notused'),
'audiotext' => array('label' => 'AudioText', 'picto'=>'', 'status'=>'notused')
);
@ -80,12 +79,12 @@ $arrayofaifeatures = array(
* Actions
*/
$modulename = GETPOST('module_name');
$functioncode = GETPOST('functioncode', 'alpha');
$pre_prompt = GETPOST('prePrompt', 'alpha');
$post_prompt = GETPOST('postPrompt', 'alpha');
// get all configs in const AI
$currentConfigurationsJson = dolibarr_get_const($db, 'AI_CONFIGURATIONS_PROMPT', $conf->entity);
$currentConfigurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
$currentConfigurations = json_decode($currentConfigurationsJson, true);
if ($action == 'update' && GETPOST('cancel')) {
@ -93,7 +92,7 @@ if ($action == 'update' && GETPOST('cancel')) {
}
if ($action == 'update' && !GETPOST('cancel')) {
$error = 0;
if (empty($modulename)) {
if (empty($functioncode)) {
$error++;
setEventMessages($langs->trans('ErrorInputRequired'), null, 'errors');
}
@ -101,12 +100,12 @@ if ($action == 'update' && !GETPOST('cancel')) {
$currentConfigurations = [];
}
if (empty($modulename) || (empty($pre_prompt) && empty($post_prompt))) {
if (isset($currentConfigurations[$modulename])) {
unset($currentConfigurations[$modulename]);
if (empty($functioncode) || (empty($pre_prompt) && empty($post_prompt))) {
if (isset($currentConfigurations[$functioncode])) {
unset($currentConfigurations[$functioncode]);
}
} else {
$currentConfigurations[$modulename] = [
$currentConfigurations[$functioncode] = [
'prePrompt' => $pre_prompt,
'postPrompt' => $post_prompt,
];
@ -172,10 +171,12 @@ if ($action == 'edit') {
$out .= '</td>';
$out .= '<td>';
// Combo list of AI features
$out .= '<select name="module_name" id="module_select" class="flat minwidth500">';
$out .= '<select name="functioncode" id="functioncode" class="flat minwidth500">';
$out .= '<option>&nbsp;</option>';
foreach ($arrayofaifeatures as $key => $val) {
$out .= '<option value="'.$val.'">'.$langs->trans($arrayofaifeatures[$key]).'</option>';
$labelhtml = $langs->trans($arrayofaifeatures[$key]['label']).($arrayofaifeatures[$key]['status'] == 'notused' ? ' <span class="opacitymedium">('.$langs->trans("NotUsed").')</span>' : "");
$labeltext = $langs->trans($arrayofaifeatures[$key]['label']);
$out .= '<option value="'.$key.'" data-html="'.dol_escape_htmltag($labelhtml).'">'.dol_escape_htmltag($labeltext).'</option>';
}
/*
$sql = "SELECT name FROM llx_const WHERE name LIKE 'MAIN_MODULE_%' AND value = '1'";
@ -191,7 +192,7 @@ if ($action == 'edit') {
}
*/
$out .= '</select>';
$out .= ajax_combobox("module_select");
$out .= ajax_combobox("functioncode");
$out .= '</td>';
$out .= '</tr>';
@ -223,37 +224,42 @@ if ($action == 'edit') {
if ($action == 'edit' || $action == 'create') {
$out = '<table class="noborder centpercent">';
foreach ($currentConfigurations as $key => $config) {
if (!preg_match('/^[a-z]+$/i', $key)) { // Ignore empty saved setup
continue;
$out = '';
if (!empty($currentConfigurations)) {
$out = '<table class="noborder centpercent">';
foreach ($currentConfigurations as $key => $config) {
if (!empty($key) && !preg_match('/^[a-z]+$/i', $key)) { // Ignore empty saved setup
continue;
}
$out .= '<thead>';
$out .= '<tr class="liste_titre">';
$out .= '<td>'.$arrayofaifeatures[$key]['picto'].' '.$langs->trans($arrayofaifeatures[$key]['label']).'</td>';
$out .= '<td></td>';
$out .= '</tr>';
$out .= '</thead>';
$out .= '<tbody>';
$out .= '<tr class="oddeven">';
$out .= '<td class="col-setup-title">';
$out .= '<span id="prePrompt" class="spanforparamtooltip">pre-Prompt</span>';
$out .= '</td>';
$out .= '<td>';
$out .= '<input name="prePrompt" id="prePromptInput" class="flat minwidth500" value="'.$config['prePrompt'].'">';
$out .= '</td>';
$out .= '</tr>';
$out .= '<tr class="oddeven">';
$out .= '<td class="col-setup-title">';
$out .= '<span id="postPrompt" class="spanforparamtooltip">Post-prompt</span>';
$out .= '</td>';
$out .= '<td>';
$out .= '<input name="postPrompt" id="postPromptInput" class="flat minwidth500" value="'.$config['postPrompt'].'">';
$out .= '</td>';
$out .= '</tr>';
}
$out .= '<thead>';
$out .= '<tr class="liste_titre">';
$out .= '<td>'.$langs->trans($arrayofaifeatures[$key]).'</td>';
$out .= '<td></td>';
$out .= '</tr>';
$out .= '</thead>';
$out .= '<tbody>';
$out .= '<tr class="oddeven">';
$out .= '<td class="col-setup-title">';
$out .= '<span id="prePrompt" class="spanforparamtooltip">pre-Prompt</span>';
$out .= '</td>';
$out .= '<td>';
$out .= '<input name="prePrompt" id="prePromptInput" class="flat minwidth500" value="'.$config['prePrompt'].'">';
$out .= '</td>';
$out .= '</tr>';
$out .= '<tr class="oddeven">';
$out .= '<td class="col-setup-title">';
$out .= '<span id="postPrompt" class="spanforparamtooltip">Post-prompt</span>';
$out .= '</td>';
$out .= '<td>';
$out .= '<input name="postPrompt" id="postPromptInput" class="flat minwidth500" value="'.$config['postPrompt'].'">';
$out .= '</td>';
$out .= '</tr>';
$out .= '</tbody>';
$out .= '</table>';
}
$out .= '</tbody>';
$out .= '</table>';
$out .= '</form>';

View File

@ -61,14 +61,19 @@ if (!class_exists('FormSetup')) {
$formSetup = new FormSetup($db);
// List all available IA
$arrayofia = array('chatgpt');
foreach ($arrayofia as $ia) {
// Setup conf AI_PUBLIC_INTERFACE_TOPIC
$item = $formSetup->newItem('AI_KEY_API_'.strtoupper($ia));
/*$item = $formSetup->newItem('AI_API_'.strtoupper($ia).'_ENDPOINT'); // Name of constant must end with _KEY so it is encrypted when saved into database.
$item->defaultFieldValue = '';
}
$item->cssClass = 'minwidth500';*/
$item = $formSetup->newItem('AI_API_'.strtoupper($ia).'_KEY'); // Name of constant must end with _KEY so it is encrypted when saved into database.
$item->defaultFieldValue = '';
$item->cssClass = 'minwidth500';
}
$setupnotempty =+ count($formSetup->items);

View File

@ -45,6 +45,11 @@ require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php';
/*
* View
*/
top_httphead();
//get data from AJAX
@ -54,11 +59,12 @@ $jsonData = json_decode($rawData, true);
if (is_null($jsonData)) {
dol_print_error('data with format JSON valide.');
}
$chatGPT = new Ai($db);
$ai = new Ai($db);
$instructions = dol_string_nohtmltag($jsonData['instructions'], 1, 'UTF-8');
$function = 'textgeneration';
$generatedContent = $chatGPT->generateContent($instructions, 'gpt-3.5-turbo', 'MAILING');
$generatedContent = $ai->generateContent($instructions, 'auto', $function);
if (is_array($generatedContent) && $generatedContent['error']) {
print "Error : " . $generatedContent['message'];

View File

@ -50,38 +50,72 @@ class Ai
public function __construct($db)
{
$this->db = $db;
$this->apiEndpoint = dolibarr_get_const($this->db, 'AI_API_ENDPOINT');
$this->apiKey = dolibarr_get_const($this->db, 'AI_KEY_API_CHATGPT');
$this->apiKey = getDolGlobalString('AI_API_CHATGPT_KEY');
}
/**
* Generate response of instructions
* @param string $instructions instruction for generate content
* @param string $model model name (chat,text,image...)
* @param string $moduleName Name of module
* @return mixed $response
*
* @param string $instructions instruction for generate content
* @param string $model model name ('gpt-3.5-turbo')
* @param string $function code of the feature we want to use ('emailing', 'transcription', 'audiotext', 'imagegeneration', 'translation')
* @return mixed $response
*/
public function generateContent($instructions, $model = 'gpt-3.5-turbo', $moduleName = 'MAILING')
public function generateContent($instructions, $model = 'auto', $function = 'textgeneration')
{
global $conf;
if (empty($this->apiEndpoint)) {
if ($function == 'textgeneration') {
$this->apiEndpoint = 'https://api.openai.com/v1/chat/completions';
if ($model == 'auto') {
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TEXT', 'gpt-3.5-turbo');
}
}
if ($function == 'imagegeneration') {
$this->apiEndpoint = 'https://api.openai.com/v1/images/generations';
if ($model == 'auto') {
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_IMAGE', 'dall-e-3');
}
}
if ($function == 'audiotext') {
$this->apiEndpoint = 'https://api.openai.com/v1/audio/speech';
if ($model == 'auto') {
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_AUDIO', 'tts-1');
}
}
if ($function == 'transcription') {
$this->apiEndpoint = 'https://api.openai.com/v1/audio/transcriptions';
if ($model == 'auto') {
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSCRIPT', 'whisper-1');
}
}
if ($function == 'translation') {
$this->apiEndpoint = 'https://api.openai.com/v1/audio/translations';
if ($model == 'auto') {
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSLATE', 'whisper-1');
}
}
}
try {
$configurationsJson = dolibarr_get_const($this->db, 'AI_CONFIGURATIONS_PROMPT', $conf->entity);
$configurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
$configurations = json_decode($configurationsJson, true);
$prePrompt = '';
$postPrompt = '';
if (isset($configurations[$moduleName])) {
if (isset($configurations[$moduleName]['prePrompt'])) {
$prePrompt = $configurations[$moduleName]['prePrompt'];
if (isset($configurations[$function])) {
if (isset($configurations[$function]['prePrompt'])) {
$prePrompt = $configurations[$function]['prePrompt'];
}
if (isset($configurations[$moduleName]['postPrompt'])) {
$postPrompt = $configurations[$moduleName]['postPrompt'];
if (isset($configurations[$function]['postPrompt'])) {
$postPrompt = $configurations[$function]['postPrompt'];
}
}
$fullInstructions = $prePrompt.' '.$instructions.' .'.$postPrompt;
// TODO Replace this with a simple call of getDolURLContent();
$ch = curl_init($this->apiEndpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([

View File

@ -573,6 +573,7 @@ class FormSetup
}
}
/**
* This class help to create item for class formSetup
*/
@ -646,6 +647,9 @@ class FormSetupItem
public $enabled = 1;
/**
* @var string The css to use on the input field of item
*/
public $cssClass = '';
/**

View File

@ -2437,11 +2437,15 @@ ExportUseForce=Use the parameter -f
ExportUseForceHelp=Force to continue the export even when an error is found (Backup may not be reliable)
CustomPrompt=Custom prompts
AiDescription=AI (Artificial Intelligence) features
AiDescriptionLong=Provides AI (Artificial Intelligence) features in different parts of the application. Need external AI API.
AI_KEY_API_CHATGPT= Key for ChatGPT AI api
AiDescriptionLong=Provides AI (Artificial Intelligence) features in different parts of the application. Need external AI API.
AI_API_CHATGPT_ENDPOINT=Endpoint for ChatGPT AI api
AI_API_CHATGPT_KEY=Key for ChatGPT AI api
AiSetup=AI module setup
AiCustomPrompt=AI custom prompt
AI_CONFIGURATIONS_PROMPT=Custom prompt
TextGeneration=Text generation
ImageGeneration=Image generation
VideoGeneration=Video generation
AudioText=Audio - Text
AIPromptForFeatures=AI custom prompts for features
EnterAnIP=Enter an IP address