diff --git a/htdocs/ai/admin/custom_prompt.php b/htdocs/ai/admin/custom_prompt.php index 56c29fa0e5e..c784e9ae3b8 100644 --- a/htdocs/ai/admin/custom_prompt.php +++ b/htdocs/ai/admin/custom_prompt.php @@ -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 .= ''; $out .= ''; // Combo list of AI features - $out .= ''; $out .= ''; foreach ($arrayofaifeatures as $key => $val) { - $out .= ''; + $labelhtml = $langs->trans($arrayofaifeatures[$key]['label']).($arrayofaifeatures[$key]['status'] == 'notused' ? ' ('.$langs->trans("NotUsed").')' : ""); + $labeltext = $langs->trans($arrayofaifeatures[$key]['label']); + $out .= ''; } /* $sql = "SELECT name FROM llx_const WHERE name LIKE 'MAIN_MODULE_%' AND value = '1'"; @@ -191,7 +192,7 @@ if ($action == 'edit') { } */ $out .= ''; - $out .= ajax_combobox("module_select"); + $out .= ajax_combobox("functioncode"); $out .= ''; $out .= ''; @@ -223,37 +224,42 @@ if ($action == 'edit') { if ($action == 'edit' || $action == 'create') { - $out = ''; - foreach ($currentConfigurations as $key => $config) { - if (!preg_match('/^[a-z]+$/i', $key)) { // Ignore empty saved setup - continue; + $out = ''; + + if (!empty($currentConfigurations)) { + $out = '
'; + foreach ($currentConfigurations as $key => $config) { + if (!empty($key) && !preg_match('/^[a-z]+$/i', $key)) { // Ignore empty saved setup + continue; + } + + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; + $out .= ''; } - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; + $out .= ''; + $out .= '
'.$arrayofaifeatures[$key]['picto'].' '.$langs->trans($arrayofaifeatures[$key]['label']).'
'; + $out .= 'pre-Prompt'; + $out .= ''; + $out .= ''; + $out .= '
'; + $out .= 'Post-prompt'; + $out .= ''; + $out .= ''; + $out .= '
'.$langs->trans($arrayofaifeatures[$key]).'
'; - $out .= 'pre-Prompt'; - $out .= ''; - $out .= ''; - $out .= '
'; - $out .= 'Post-prompt'; - $out .= ''; - $out .= ''; - $out .= '
'; } - $out .= ''; - $out .= ''; $out .= ''; diff --git a/htdocs/ai/admin/setup.php b/htdocs/ai/admin/setup.php index 4fdb1f02435..73e4765d7a4 100644 --- a/htdocs/ai/admin/setup.php +++ b/htdocs/ai/admin/setup.php @@ -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); diff --git a/htdocs/ai/ajax/generate_content.php b/htdocs/ai/ajax/generate_content.php index 34d7f196753..9b1adf13b84 100644 --- a/htdocs/ai/ajax/generate_content.php +++ b/htdocs/ai/ajax/generate_content.php @@ -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']; diff --git a/htdocs/ai/class/ai.class.php b/htdocs/ai/class/ai.class.php index 2771c1b0e06..399b3adb1ee 100644 --- a/htdocs/ai/class/ai.class.php +++ b/htdocs/ai/class/ai.class.php @@ -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([ diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 32215871529..e5199267d31 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -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 = ''; /** diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 6182aa8f97b..b7dd42c84e2 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -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