mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-02-20 13:46:52 +01:00
NEW Add a test mode into the setup of AI prompts
This commit is contained in:
parent
c4f29dca59
commit
3a9931c0bb
|
|
@ -1113,7 +1113,7 @@ if ($action == 'edit') {
|
|||
|
||||
print dol_get_fiche_head(array(), '', '', -1);
|
||||
|
||||
// Cree l'objet formulaire mail
|
||||
// Create form object
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$formmail = new FormMail($db);
|
||||
$formmail->trackid = (($action == 'testhtml') ? "testhtml" : "test");
|
||||
|
|
@ -1132,7 +1132,7 @@ if ($action == 'edit') {
|
|||
$formmail->withtopic = (GETPOSTISSET('subject') ? GETPOST('subject') : $langs->trans("Test"));
|
||||
$formmail->withtopicreadonly = 0;
|
||||
$formmail->withfile = 2;
|
||||
$formmail->withlayout = 1;
|
||||
$formmail->withlayout = 1; // Not MAIN_EMAIL_USE_LAYOUT must be set
|
||||
$formmail->withaiprompt = ($action == 'testhtml' ? 'html' : 'text');
|
||||
$formmail->withbody = (GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : ($action == 'testhtml' ? $langs->transnoentities("PredefinedMailTestHtml") : $langs->transnoentities("PredefinedMailTest")));
|
||||
$formmail->withbodyreadonly = 0;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,15 @@ $langs->loadLangs(array("admin", "website", "other"));
|
|||
// Parameters
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$backtopage = GETPOST('backtopage', 'alpha');
|
||||
$cancel = GETPOST('cancel');
|
||||
$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
|
||||
|
||||
$functioncode = GETPOST('functioncode', 'alpha');
|
||||
$pre_prompt = GETPOST('prePrompt');
|
||||
$post_prompt = GETPOST('postPrompt');
|
||||
$blacklists = GETPOST('blacklists');
|
||||
$test = GETPOST('test');
|
||||
|
||||
if (empty($action)) {
|
||||
$action = 'edit';
|
||||
}
|
||||
|
|
@ -83,20 +90,16 @@ $arrayofaifeatures = array(
|
|||
* Actions
|
||||
*/
|
||||
|
||||
$functioncode = GETPOST('functioncode', 'alpha');
|
||||
$pre_prompt = GETPOST('prePrompt');
|
||||
$post_prompt = GETPOST('postPrompt');
|
||||
$blacklists = GETPOST('blacklists');
|
||||
// get all configs in const AI
|
||||
|
||||
$currentConfigurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
|
||||
$currentConfigurations = json_decode($currentConfigurationsJson, true);
|
||||
|
||||
if ($action == 'update' && GETPOST('cancel')) {
|
||||
if ($action == 'update' && $cancel) {
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
if ($action == 'update' && !GETPOST('cancel')) {
|
||||
if ($action == 'update' && !$cancel && !$test) {
|
||||
$error = 0;
|
||||
if (empty($functioncode)) {
|
||||
$error++;
|
||||
|
|
@ -135,7 +138,8 @@ if ($action == 'update' && !GETPOST('cancel')) {
|
|||
$action = 'edit';
|
||||
}
|
||||
|
||||
if ($action == 'updatePrompts') {
|
||||
// Update entry
|
||||
if ($action == 'updatePrompts' && !$test) {
|
||||
$key = GETPOST('key', 'alpha');
|
||||
|
||||
$blacklistArray = array_filter(array_map('trim', explode(',', $blacklists)));
|
||||
|
|
@ -149,17 +153,21 @@ if ($action == 'updatePrompts') {
|
|||
$newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
|
||||
$result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
|
||||
if (!$error) {
|
||||
$action = '';
|
||||
$action = 'edit';
|
||||
if ($result) {
|
||||
header("Location: ".$_SERVER['PHP_SELF']);
|
||||
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
|
||||
exit;
|
||||
} else {
|
||||
setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test entry
|
||||
if ($action == 'updatePrompts' && $test) {
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
// Delete entry
|
||||
if ($action == 'confirm_deleteproperty' && GETPOST('confirm') == 'yes') {
|
||||
$key = GETPOST('key', 'alpha');
|
||||
|
||||
|
|
@ -311,12 +319,12 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
|||
$out .= '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
$out .= '<input type="hidden" name="key" value="'.$key.'" />';
|
||||
$out .= '<input type="hidden" name="action" value="updatePrompts">';
|
||||
$out .= '<input type="hidden" name="page_y" value="">';
|
||||
|
||||
$out .= '<table class="noborder centpercent">';
|
||||
$out .= '<thead>';
|
||||
$out .= '<tr class="liste_titre">';
|
||||
$out .= '<td class="titlefield">'.$arrayofaifeatures[$key]['picto'].' '.$langs->trans($arrayofaifeatures[$key]['label']);
|
||||
$out .= '<a class="viewfielda reposition marginleftonly marginrighttonly showInputBtn" href="#" data-index="'.$key.'" data-state="edit" data-icon-edit="'.dol_escape_htmltag(img_edit()).'" data-icon-cancel="'.dol_escape_htmltag(img_view()).'">'.img_edit().'</a>';
|
||||
$out .= '<a class="deletefielda reposition marginleftonly right" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&key='.urlencode($key).'">'.img_delete().'</a>';
|
||||
$out .= '</td>';
|
||||
$out .= '<td></td>';
|
||||
|
|
@ -329,7 +337,7 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
|||
$out .= '<span id="prePrompt" class="spanforparamtooltip">'.$langs->trans("Pre-Prompt").'</span>';
|
||||
$out .= '</td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<textarea class="flat minwidth500" id="prePromptInput_'.$key.'" name="prePrompt" rows="2" disabled>'.$config['prePrompt'].'</textarea>';
|
||||
$out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="prePromptInput_'.$key.'" name="prePrompt" rows="2">'.$config['prePrompt'].'</textarea>';
|
||||
$out .= '</td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
|
|
@ -338,21 +346,34 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
|||
$out .= '<span id="postPrompt" class="spanforparamtooltip">'.$langs->trans("Post-Prompt").'</span>';
|
||||
$out .= '</td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<textarea class="flat minwidth500" id="postPromptInput_'.$key.'" name="postPrompt" rows="2" disabled>'.$config['postPrompt'].'</textarea>';
|
||||
$out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="postPromptInput_'.$key.'" name="postPrompt" rows="2">'.$config['postPrompt'].'</textarea>';
|
||||
$out .= '</td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
$out .= '<tr id="fichetwothirdright-'.$key.'" class="oddeven">';
|
||||
$out .= '<td>'.$langs->trans("BlackListWords").'</td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<textarea class="flat minwidth500" id="blacklist_'.$key.'" name="blacklists" rows="6" disabled>'.(isset($config['blacklists']) ? implode(', ', (array) $config['blacklists']) : '').'</textarea>';
|
||||
$out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="blacklist_'.$key.'" name="blacklists" rows="3">'.(isset($config['blacklists']) ? implode(', ', (array) $config['blacklists']) : '').'</textarea>';
|
||||
$out .= '</td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
$out .= '<tr>';
|
||||
$out .= '<td></td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<input type="submit" class="button small submitBtn" name="modify" data-index="'.$key.'" style="display: none;" value="'.dol_escape_htmltag($langs->trans("Modify")).'"/>';
|
||||
$out .= '<input type="submit" class="button small submitBtn reposition" name="modify" data-index="'.$key.'" value="'.dol_escape_htmltag($langs->trans("Modify")).'"/>';
|
||||
$out .= ' ';
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$showlinktoai = $key; // 'textgeneration', 'imagegeneration', ...
|
||||
$showlinktoailabel = $langs->trans("ToTest");
|
||||
$formmail = new FormMail($db);
|
||||
$htmlname = $key;
|
||||
|
||||
// Fill $out
|
||||
include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
|
||||
|
||||
$out .= '<div id="'.$htmlname.'"></div>';
|
||||
|
||||
$out .= '</td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
|
|
@ -363,51 +384,6 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
$out .= "<script>
|
||||
var configurations = ".$currentConfigurationsJson.";
|
||||
$(document).ready(function() {
|
||||
$('#module_select').change(function() {
|
||||
var selectedModule = $(this).val();
|
||||
var moduleConfig = configurations[selectedModule];
|
||||
|
||||
if (moduleConfig) {
|
||||
$('#prePromptInput').val(moduleConfig.prePrompt || '');
|
||||
$('#postPromptInput').val(moduleConfig.postPrompt || '');
|
||||
$('#blacklistsInput').val(moduleConfig.blacklists ? moduleConfig.blacklists.join(', ') : '');
|
||||
} else {
|
||||
$('#prePromptInput').val('');
|
||||
$('#postPromptInput').val('');
|
||||
$('#blacklistsInput').val('');
|
||||
}
|
||||
});
|
||||
|
||||
$('.showInputBtn').click(function() {
|
||||
event.preventDefault();
|
||||
var index = $(this).data('index');
|
||||
var state = $(this).data('state');
|
||||
|
||||
if(state === 'edit') {
|
||||
$('#prePromptInput_'+index).removeAttr('disabled').focus();
|
||||
$('#postPromptInput_'+index).removeAttr('disabled');
|
||||
$('#blacklist_'+index).removeAttr('disabled');
|
||||
$('.submitBtn[data-index=' + index + ']').show();
|
||||
$(this).html($(this).data('icon-cancel'));
|
||||
$(this).data('state', 'cancel');
|
||||
|
||||
} else {
|
||||
|
||||
$('#prePromptInput_'+index).attr('disabled', 'disabled');
|
||||
$('#postPromptInput_'+index).attr('disabled', 'disabled');
|
||||
$('#blacklist_'+index).attr('disabled', 'disabled');
|
||||
$('.submitBtn[data-index=' + index + ']').hide();
|
||||
$(this).html($(this).data('icon-edit'));
|
||||
$(this).data('state', 'edit');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>";
|
||||
|
||||
print $out;
|
||||
|
||||
print '<br>';
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ require '../../main.inc.php';
|
|||
|
||||
require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php';
|
||||
|
||||
if (!isModEnabled('ai')) {
|
||||
accessforbidden('Module AI not enabled');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* View
|
||||
|
|
@ -63,7 +67,7 @@ if (is_null($jsonData)) {
|
|||
$ai = new Ai($db);
|
||||
|
||||
// Get parameters
|
||||
$function = empty($jsonData['function']) ? 'textgeneration' : $jsonData['function']; // Default value. Can also be 'textgenerationemail', 'textgenerationwebpage', ...
|
||||
$function = empty($jsonData['function']) ? 'textgeneration' : $jsonData['function']; // Default value. Can also be 'textgeneration', 'textgenerationemail', 'textgenerationwebpage', 'imagegeneration', 'videogeneration', ...
|
||||
$instructions = dol_string_nohtmltag($jsonData['instructions'], 1, 'UTF-8');
|
||||
$format = empty($jsonData['format']) ? '' : $jsonData['format'];
|
||||
|
||||
|
|
@ -80,5 +84,16 @@ if (is_array($generatedContent) && $generatedContent['error']) {
|
|||
print "Error returned by API call: " . $generatedContent['message'];
|
||||
}
|
||||
} else {
|
||||
print $generatedContent;
|
||||
if ($function == 'textgenerationemail' || $function == 'textgenerationwebpage') {
|
||||
print dolPrintHTML($generatedContent); // Note that common HTML tags are NOT escaped (but a sanitization is done)
|
||||
} elseif ($function == 'imagegeneration') {
|
||||
// TODO
|
||||
} elseif ($function == 'videogeneration') {
|
||||
// TODO
|
||||
} elseif ($function == 'audiogeneration') {
|
||||
// TODO
|
||||
} else {
|
||||
// Default case 'textgeneration'
|
||||
print dolPrintText($generatedContent); // Note that common HTML tags are NOT escaped (but a sanitization is done)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,11 +71,11 @@ class Ai
|
|||
/**
|
||||
* Generate response of instructions
|
||||
*
|
||||
* @param string $instructions Instruction to generate content
|
||||
* @param string $model Model name ('gpt-3.5-turbo', 'gpt-4-turbo', 'dall-e-3', ...)
|
||||
* @param string $function Code of the feature we want to use ('textgeneration', 'transcription', 'audiogeneration', 'imagegeneration', 'translation')
|
||||
* @param string $format Format for output ('', 'html', ...)
|
||||
* @return mixed $response
|
||||
* @param string $instructions Instruction to generate content
|
||||
* @param string $model Model name ('gpt-3.5-turbo', 'gpt-4-turbo', 'dall-e-3', ...)
|
||||
* @param string $function Code of the feature we want to use ('textgeneration', 'transcription', 'audiogeneration', 'imagegeneration', 'translation')
|
||||
* @param string $format Format for output ('', 'html', ...)
|
||||
* @return string|array $response Text or array if error
|
||||
*/
|
||||
public function generateContent($instructions, $model = 'auto', $function = 'textgeneration', $format = '')
|
||||
{
|
||||
|
|
@ -83,96 +83,100 @@ class Ai
|
|||
return array('error' => true, 'message' => 'API key is not defined for the AI enabled service ('.$this->apiService.')');
|
||||
}
|
||||
|
||||
// $this->apiEndpoint is set here only if forced.
|
||||
// In most cases, it is empty and we must get it from $function and $this->apiService
|
||||
if (empty($this->apiEndpoint)) {
|
||||
if ($function == 'imagegeneration') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/images/generations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_IMAGE', 'dall-e-3');
|
||||
}
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/images/generations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_IMAGE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
}
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/images/generations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_IMAGE', 'dall-e-3');
|
||||
}
|
||||
}
|
||||
} elseif ($function == 'audiogeneration') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/audio/speech';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_AUDIO', 'tts-1');
|
||||
}
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/audio/speech';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_AUDIO', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
}
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/audio/speech';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_AUDIO', 'tts-1');
|
||||
}
|
||||
}
|
||||
} elseif ($function == 'transcription') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/transcriptions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSCRIPT', 'whisper-1');
|
||||
}
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/transcriptions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TRANSCRIPT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
}
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/transcriptions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_TRANSCRIPT', 'whisper-1');
|
||||
}
|
||||
}
|
||||
} elseif ($function == 'translation') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/translations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSLATE', 'whisper-1');
|
||||
}
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/translations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TRANSLATE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
}
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/translations';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_TRANSLATE', 'whisper-1');
|
||||
}
|
||||
}
|
||||
} else { // else textgeneration...
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/chat/completions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TEXT', 'gpt-3.5-turbo');
|
||||
}
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/chat/completions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TEXT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
}
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/chat/completions';
|
||||
if ($model == 'auto') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_TEXT', 'gpt-3.5-turbo');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dol_syslog("Call API for apiEndpoint=".$this->apiEndpoint." apiKey=".substr($this->apiKey, 0, 3).'***********, model='.$model);
|
||||
// $model may be undefined or 'auto'.
|
||||
// If this is the case, we must get it from $function and $this->apiService
|
||||
if (empty($model) || $model == 'auto') {
|
||||
// Return the endpoint and the model from $this->apiService.
|
||||
if ($function == 'imagegeneration') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_IMAGE', 'dall-e-3');
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_IMAGE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_IMAGE', 'dall-e-3');
|
||||
}
|
||||
} elseif ($function == 'audiogeneration') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_AUDIO', 'tts-1');
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_AUDIO', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_AUDIO', 'tts-1');
|
||||
}
|
||||
} elseif ($function == 'transcription') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSCRIPT', 'whisper-1');
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TRANSCRIPT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_TRANSCRIPT', 'whisper-1');
|
||||
}
|
||||
} elseif ($function == 'translation') {
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSLATE', 'whisper-1');
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TRANSLATE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_TRANSLATE', 'whisper-1');
|
||||
}
|
||||
} else { // else textgeneration...
|
||||
if ($this->apiService == 'chatgpt') {
|
||||
$model = getDolGlobalString('AI_API_CHATGPT_MODEL_TEXT', 'gpt-3.5-turbo');
|
||||
} elseif ($this->apiService == 'groq') {
|
||||
$model = getDolGlobalString('AI_API_GROK_MODEL_TEXT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
|
||||
} elseif ($this->apiService == 'custom') {
|
||||
$model = getDolGlobalString('AI_API_CUSTOM_MODEL_TEXT', 'tinyllama-1.1b'); // with JAN: 'tinyllama-1.1b', 'mistral-ins-7b-q4'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dol_syslog("Call API for apiKey=".substr($this->apiKey, 0, 3).'***********, apiEndpoint='.$this->apiEndpoint.", model=".$model);
|
||||
|
||||
try {
|
||||
if (empty($this->apiEndpoint)) {
|
||||
|
|
@ -187,42 +191,72 @@ class Ai
|
|||
|
||||
if (isset($configurations[$function])) {
|
||||
if (isset($configurations[$function]['prePrompt'])) {
|
||||
$prePrompt = $configurations[$function]['prePrompt'];
|
||||
$prePrompt = $configurations[$function]['prePrompt']; // TODO We can send prePrompt into a separated message with role system.
|
||||
}
|
||||
|
||||
if (isset($configurations[$function]['postPrompt'])) {
|
||||
$postPrompt = $configurations[$function]['postPrompt'];
|
||||
}
|
||||
}
|
||||
$fullInstructions = $prePrompt.' '.$instructions.' .'.$postPrompt;
|
||||
|
||||
$fullInstructions = ($prePrompt ? $prePrompt.' ' : '').$instructions.($postPrompt ? '. '.$postPrompt : '');
|
||||
|
||||
// Set payload string
|
||||
/*{
|
||||
"messages": [
|
||||
{
|
||||
"content": "You are a helpful assistant.",
|
||||
"role": "system"
|
||||
},
|
||||
{
|
||||
"content": "Hello!",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
"model": "tinyllama-1.1b",
|
||||
"stream": true,
|
||||
"max_tokens": 2048,
|
||||
"stop": [
|
||||
"hello"
|
||||
],
|
||||
"frequency_penalty": 0,
|
||||
"presence_penalty": 0,
|
||||
"temperature": 0.7,
|
||||
"top_p": 0.95
|
||||
}*/
|
||||
$payload = json_encode([
|
||||
'messages' => [
|
||||
['role' => 'user', 'content' => $fullInstructions]
|
||||
],
|
||||
'model' => $model
|
||||
'model' => $model,
|
||||
//'stream' => false
|
||||
]);
|
||||
|
||||
$headers = ([
|
||||
'Authorization: Bearer ' . $this->apiKey,
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
$response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers);
|
||||
|
||||
$localurl = 2; // Accept both local and external endpoints
|
||||
$response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers, array('http', 'https'), $localurl);
|
||||
|
||||
if (empty($response['http_code'])) {
|
||||
throw new Exception('API request failed. No http received');
|
||||
}
|
||||
if (!empty($response['http_code']) && $response['http_code'] != 200) {
|
||||
throw new Exception('API request on endpoint '.$this->apiEndpoint.' failed with status code ' . $response['http_code']);
|
||||
throw new Exception('API request on AI endpoint '.$this->apiEndpoint.' failed with status code '.$response['http_code'].(empty($response['content']) ? '' : ' - '.$response['content']));
|
||||
}
|
||||
|
||||
if (getDolGlobalString("AI_DEBUG")) {
|
||||
dol_syslog("response content = ".var_export($response['content'], true));
|
||||
}
|
||||
|
||||
// Decode JSON response
|
||||
$decodedResponse = json_decode($response['content'], true);
|
||||
|
||||
// Extraction content
|
||||
$generatedContent = $decodedResponse['choices'][0]['message']['content'];
|
||||
|
||||
dol_syslog("generatedContent=".$generatedContent);
|
||||
dol_syslog("generatedContent=".dol_trunc($generatedContent, 50));
|
||||
|
||||
// If content is not HTML, we convert it into HTML
|
||||
if ($format == 'html') {
|
||||
|
|
|
|||
|
|
@ -63,17 +63,17 @@ class FormMail extends Form
|
|||
public $frommail;
|
||||
|
||||
/**
|
||||
* @var string user, company, robot
|
||||
* @var string user, company, robot
|
||||
*/
|
||||
public $fromtype;
|
||||
|
||||
/**
|
||||
* @var int from ID
|
||||
* @var int from ID
|
||||
*/
|
||||
public $fromid;
|
||||
|
||||
/**
|
||||
* @var int also from robot
|
||||
* @var int Add also the robot email as possible senders
|
||||
*/
|
||||
public $fromalsorobot;
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ class FormMail extends Form
|
|||
public $replytoname;
|
||||
|
||||
/**
|
||||
* @var string replyto email
|
||||
* @var string Reply-to email
|
||||
*/
|
||||
public $replytomail;
|
||||
|
||||
|
|
@ -1419,42 +1419,38 @@ class FormMail extends Form
|
|||
|
||||
$htmlContent = preg_replace('/[^a-z0-9_]/', '', $htmlContent);
|
||||
|
||||
$out = '<tr id="ai_input" class="hidden">';
|
||||
$out .= '<td>';
|
||||
//$out .= $form->textwithpicto($langs->trans('HelpWithAI'), $langs->trans("YouCanMakeSomeInstructionForEmail"));
|
||||
$out .= '</td>';
|
||||
|
||||
$out .= '<td>';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions" name="instruction" placeholder="'.$langs->trans("EnterYourAIPromptHere").'..." />';
|
||||
$out .= '<input id="generate_button" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
|
||||
$out .= '<div id="ai_status_message" class="fieldrequired hideobject marginrightonly margintoponly">';
|
||||
$out = '<div id="ai_input'.$htmlContent.'" class="hidden">';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions'.$htmlContent.'" name="instruction" placeholder="'.$langs->trans("EnterYourAIPromptHere").'..." />';
|
||||
$out .= '<input id="generate_button'.$htmlContent.'" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
|
||||
$out .= '<div id="ai_status_message'.$htmlContent.'" class="fieldrequired hideobject marginrightonly margintoponly">';
|
||||
$out .= '<i class="fa fa-spinner fa-spin fa-2x fa-fw valignmiddle marginrightonly"></i>'.$langs->trans("AIProcessingPleaseWait", getDolGlobalString('AI_API_SERVICE', 'chatgpt'));
|
||||
$out .= '</div>';
|
||||
$out .= "</td></tr>\n";
|
||||
|
||||
$out .= "</div>\n";
|
||||
|
||||
$out .= "<script type='text/javascript'>
|
||||
$(document).ready(function() {
|
||||
// for keydown
|
||||
$('#ai_instructions').keydown(function(event) {
|
||||
$('#ai_instructions".$htmlContent."').keydown(function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
$('#generate_button').click();
|
||||
$('#generate_button".$htmlContent."').click();
|
||||
}
|
||||
});
|
||||
|
||||
$('#generate_button').click(function() {
|
||||
console.log('We click on generate ai button');
|
||||
$('#generate_button".$htmlContent."').click(function() {
|
||||
console.log('We click on generate_button".$htmlContent." ai button');
|
||||
|
||||
var instructions = $('#ai_instructions').val();
|
||||
var instructions = $('#ai_instructions".$htmlContent."').val();
|
||||
var timeoutfinished = 0;
|
||||
var apicallfinished = 0;
|
||||
|
||||
$('#ai_status_message').show();
|
||||
$('#ai_status_message".$htmlContent."').show();
|
||||
$('.icon-container .loader').show();
|
||||
setTimeout(function() {
|
||||
timeoutfinished = 1;
|
||||
if (apicallfinished) {
|
||||
$('#ai_status_message').hide();
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
|
|
@ -1474,9 +1470,10 @@ class FormMail extends Form
|
|||
'instructions': instructions, /* the prompt string */
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log('Add response into field \'".$htmlContent."\': '+response);
|
||||
console.log('Add response into field \'#".$htmlContent."\': '+response);
|
||||
|
||||
jQuery('#".$htmlContent."').val(response);
|
||||
jQuery('#".$htmlContent."').val(response); // If #htmlcontent is a input name or textarea
|
||||
jQuery('#".$htmlContent."').html(response); // If #htmlContent is a div
|
||||
//jQuery('#".$htmlContent."preview').val(response);
|
||||
|
||||
if (CKEDITOR.instances) {
|
||||
|
|
@ -1492,17 +1489,17 @@ class FormMail extends Form
|
|||
}
|
||||
|
||||
// remove readonly
|
||||
$('#ai_instructions').val('');
|
||||
$('#ai_instructions".$htmlContent."').val('');
|
||||
|
||||
apicallfinished = 1;
|
||||
if (timeoutfinished) {
|
||||
$('#ai_status_message').hide();
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert(error);
|
||||
console.error('error ajax', status, error);
|
||||
$('#ai_status_message').hide();
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1878,8 +1878,8 @@ function dol_escape_xml($stringtoescape)
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a string label (so on 1 line only and that should not contains any HTML) ready to be output on HTML page
|
||||
* To use text that is not HTML content inside an attribute, use can simply only dol_escape_htmltag(). In doubt, use dolPrintHTMLForAttribute().
|
||||
* Return a string label (so on 1 line only and that should not contains any HTML) ready to be output on HTML page.
|
||||
* To use text that is not HTML content inside an attribute, you can simply use only dol_escape_htmltag(). In doubt, use dolPrintHTMLForAttribute().
|
||||
*
|
||||
* @param string $s String to print
|
||||
* @return string String ready for HTML output
|
||||
|
|
@ -1889,6 +1889,18 @@ function dolPrintLabel($s)
|
|||
return dol_escape_htmltag(dol_string_nohtmltag($s, 1, 'UTF-8', 0, 0), 0, 0, '', 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string label (possible on several lines and that should not contains any HTML) ready to be output on HTML page.
|
||||
* To use text that is not HTML content inside an attribute, you can simply use only dol_escape_htmltag(). In doubt, use dolPrintHTMLForAttribute().
|
||||
*
|
||||
* @param string $s String to print
|
||||
* @return string String ready for HTML output
|
||||
*/
|
||||
function dolPrintText($s)
|
||||
{
|
||||
return dol_escape_htmltag(dol_string_nohtmltag($s, 2, 'UTF-8', 0, 0), 0, 1, '', 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string (that can be on several lines) ready to be output on a HTML page.
|
||||
* To output a text inside an attribute, you can use dolPrintHTMLForAttribute() or dolPrintHTMLForTextArea() inside a textarea
|
||||
|
|
@ -1918,7 +1930,8 @@ function dolPrintHTMLForAttribute($s)
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a string ready to be output on input textarea
|
||||
* Return a string ready to be output on input textarea.
|
||||
* Differs from dolPrintHTML because all tags are escape. With dolPrintHTML, all tags except common one are escaped.
|
||||
*
|
||||
* @param string $s String to print
|
||||
* @param int $allowiframe Allow iframe tags
|
||||
|
|
@ -1951,7 +1964,7 @@ function dolPrintPassword($s)
|
|||
* @param string $stringtoescape String to escape
|
||||
* @param int $keepb 1=Replace b tags with escaped value (except if in $noescapetags), 0=Remove them completely
|
||||
* @param int $keepn 1=Preserve \r\n strings, 0=Replace them with escaped value, -1=Remove them. Set to 1 when escaping for a <textarea>.
|
||||
* @param string $noescapetags '' or 'common' or list of tags to not escape.
|
||||
* @param string $noescapetags ''= or 'common' or list of tags to not escape.
|
||||
* @param int $escapeonlyhtmltags 1=Escape only html tags, not the special chars like accents.
|
||||
* @param int $cleanalsojavascript Clean also javascript. @TODO switch this option to 1 by default.
|
||||
* @return string Escaped string
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@
|
|||
* $conf
|
||||
* $formmail
|
||||
* $formwebsite (optional)
|
||||
* $showlinktolayout
|
||||
* $showlinktolayoutlabel
|
||||
* $showlinktolayout=0|1
|
||||
* $showlinktolayoutlabel='...'
|
||||
* $showlinktoai ('' or 'textgeneration', 'textgenerationemail', 'textgenerationwebpage', ...)
|
||||
* $showlinktoailabel
|
||||
* $showlinktoailabel='...'
|
||||
* $htmlname
|
||||
*/
|
||||
|
||||
|
|
@ -31,6 +31,11 @@ if (empty($conf) || !is_object($conf)) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (empty($htmlname)) {
|
||||
print 'Parameter htmlname not defined.';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
?>
|
||||
<!-- BEGIN PHP TEMPLATE formlayoutai.tpl.php -->
|
||||
<?php
|
||||
|
|
@ -57,19 +62,19 @@ if ($showlinktolayout) {
|
|||
}
|
||||
// Add link to add AI content
|
||||
if ($showlinktoai) {
|
||||
$out .= '<a href="#" id="linkforaiprompt" class="reposition notasortlink inline-block alink marginrightonly">';
|
||||
$out .= '<a href="#" id="linkforaiprompt'.$showlinktoai.'" class="reposition notasortlink inline-block alink marginrightonly">';
|
||||
$out .= img_picto($showlinktoailabel, 'ai', 'class="paddingrightonly"');
|
||||
$out .= $showlinktoailabel.'...';
|
||||
$out .= '</a>';
|
||||
|
||||
$out .= '<script>
|
||||
$(document).ready(function() {
|
||||
$("#linkforaiprompt").click(function() {
|
||||
console.log("We click on linkforaiprompt");
|
||||
$("#linkforaiprompt'.$showlinktoai.'").click(function() {
|
||||
console.log("formlayoutai.tpl: We click on linkforaiprompt'.$showlinktoai.', we toggle #ai_input'.$showlinktoai.'");
|
||||
event.preventDefault();
|
||||
jQuery("#ai_input").toggle();
|
||||
jQuery("#ai_input'.$htmlname.'").toggle();
|
||||
jQuery("#template-selector").hide();
|
||||
if (!jQuery("ai_input").is(":hidden")) {
|
||||
if (!jQuery("#ai_input'.$htmlname.'").is(":hidden")) {
|
||||
console.log("Set focus on input field");
|
||||
jQuery("#ai_instructions").focus();
|
||||
if (!jQuery("pageContent").is(":hidden")) { // May exists for website page only
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user