28if (!defined(
'NOTOKENRENEWAL')) {
29 define(
'NOTOKENRENEWAL', 1);
31if (!defined(
'NOREQUIREMENU')) {
32 define(
'NOREQUIREMENU',
'1');
34if (!defined(
'NOREQUIREHTML')) {
35 define(
'NOREQUIREHTML',
'1');
37if (!defined(
'NOREQUIREAJAX')) {
38 define(
'NOREQUIREAJAX',
'1');
40if (!defined(
'NOHEADERNOFOOTER')) {
41 define(
'NOHEADERNOFOOTER',
'1');
44require_once
'../../main.inc.php';
52require_once DOL_DOCUMENT_ROOT.
'/core/class/html.form.class.php';
53require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
54require_once DOL_DOCUMENT_ROOT.
'/ai/class/ai.class.php';
58 $langs->setDefaultLang(
GETPOST(
'lang',
'aZ09'));
61$langs->loadLangs(array(
"main",
"other",
"exports"));
63$action =
GETPOST(
'action',
'aZ09');
64$modulepart =
GETPOST(
'modulepart',
'aZ09');
66$upload_dir =
$conf->user->dir_temp.
'/import';
74if (preg_match(
'/^upload_page-([a-z_]+)-uid(\d+)-/', $file, $reg)) {
75 $modulepart = $reg[1];
77 if ($reg[2] != $user->id) {
78 accessforbidden(
'User id found in filename to process does not match current user id');
104$originalfilename = $file;
105$uid = $thiid = $pid = $erid = $salid = 0;
106if (preg_match(
'/-uid([\d+])/', $file, $reg)) {
108 $originalfilename = preg_replace(
'/-uid\d+/',
'', $originalfilename);
110if (preg_match(
'/-thiid([\d+])/', $file, $reg)) {
112 $originalfilename = preg_replace(
'/-thiid\d+/',
'', $originalfilename);
114if (preg_match(
'/-pid([\d+])/', $file, $reg)) {
116 $originalfilename = preg_replace(
'/-pid\d+/',
'', $originalfilename);
118if (preg_match(
'/-erid([\d+])/', $file, $reg)) {
120 $originalfilename = preg_replace(
'/-erid\d+/',
'', $originalfilename);
122if (preg_match(
'/-salid([\d+])/', $file, $reg)) {
124 $originalfilename = preg_replace(
'/-salid\d+/',
'', $originalfilename);
126$originalfilename = preg_replace(
'/^upload_page-[a-z_]+-/',
'', $originalfilename);
132$METHOD =
'converttotext';
135$docformat = $doctypelabel = $prompt =
'';
136$fullpathoffile = $upload_dir.
'/'.$file;
141if ($modulepart ==
'invoice_supplier') {
143 $doctypelabel =
'invoice';
146 $prompt =
'Analyze the contents of this '.$docformat.
' document of an '.$doctypelabel.
' and convert all readable text and numerical information into a structured JSON format. Follow these guidelines:
148 1. **Hierarchical Structure:** Group related information into logical categories like "document_info", "vendor or issuer", "recipient", "items", "payment_info" and "other" depending on the content.
149 2. **Flexible Field Identification:** Identify and organize common fields that are found such as:
150 - "invoice number", "invoice reference"
151 - "date", "issue date", "due date", "transaction or invoice date"
152 - "vendor name", "vendor vat number", "vendor professional id (siret, siren, ...), "vendor address", "vendor phone", "vendor email",
153 - "items", "products", "services", "product or service label", "product or service ref", "product or service ref"
154 - "totals", "summary", "amounts", "balance"
155 - "notes," "comments," "messages," "terms"
156 3. **Handle Tables and Lists:** If the document contains tables, represent each row as an object in a list with fields like "no", "ref", "description", "quantity", "vat rate", "unit price", "total excluding tax", "total including tax".
157 4. **Normalize Dates:** If dates are present, format them in ISO format (YYYY-MM-DD) whenever possible.
158 5. **Ignore Background Noise:** Exclude background noise, decorative elements, and irrelevant symbols that do not contribute to the data content.
159 6. **Preserve Context:** If the image contains sections, headings, or grouping indicators, use them to create logical hierarchies in the JSON structure.
160 7. **General Usability:** Format the text to be suitable for further processing, analysis, or database import.
162 **Example JSON Structure:**
166 "document_ref": "<document ref or number>",
169 "currency_code": "<currency_code>"
173 "address": "<address>",
174 "phone": "<phone number>",
176 "vatnumber": "<vat number>",
177 "profid": "<professional id>"
181 "address": "<address>",
182 "phone": "<phone number>",
184 "vatnumber": "<vat number>",
185 "profid": "<professional id>"
192 "description": "<description>",
193 "quantity": "<quantity>",
194 "vatrate": "<vat rate>",
195 "totalinctax": "<total including tax>"
196 "totalexcltax": "<total excluding tax>"
200 "subtotal": "<subtotal>",
201 "tax": "<amount of tax>",
202 "total": "<total to pay>"
206 "method": "<check or cash or card or direct_debit or credit_transfer or other>",
207 "details": "Detail of the payment mode"
212 "method": "<check or cash or card or direct_debit or credit_transfer or other>",
213 "amount": "<detail of the payment>",
214 "note":"<other information on payment done>"
217 "notes": "<optional text>"
225if ($METHOD ==
'converttotext') {
226 $result =
dolDocToText($fullpathoffile,
'',
'fulltext');
227 if (empty($result[
'error'])) {
228 $fileContent = $result[
'content'];
232 $prompt =
'This is the content of the document:'.
"\n\n".substr($fileContent, 0, 12000).
"\n\nQuestion: ".$prompt;
234 $result = $ai->generateContent($prompt,
'auto',
'docparsing',
'');
236 if (is_array($result)) {
237 if ($result[
'error']) {
239 $errors[] = $result[
'error'];
241 if ($result[
'curl_error_no']) {
243 $errors[] = $result[
'curl_error_no'];
246 $answer = (
string) $result;
248 $answer = preg_replace(
'/^```json/',
'', $answer);
249 $answer = preg_replace(
'/```$/',
'', $answer);
252 $errors[] =
'Failed to convert document into TXT';
257if ($METHOD ==
'thread') {
268 "purpose" =>
"assistants",
269 "file" =>
new CURLFile($fullpathoffile)
272 $result = $ai->generateContent($payload,
'auto',
'file',
'');
274 if (is_array($result)) {
275 if ($result[
'error']) {
277 $errors[] = $result[
'error'];
279 if ($result[
'curl_error_no']) {
281 $errors[] = $result[
'curl_error_no'];
284 $fileId = json_decode($result,
true)[
'id'];
291 "name" =>
"PDF Analyzer",
292 "instructions" =>
"Analyze PDF and answer precisely",
294 [
"type" =>
"file_search"]
298 $result = $ai->generateContent($payload,
'auto',
'assistant',
'', array(
'OpenAI-Beta',
'assistants=v2'));
300 if (is_array($result)) {
301 if ($result[
'error']) {
303 $errors[] = $result[
'error'];
305 if ($result[
'curl_error_no']) {
307 $errors[] = $result[
'curl_error_no'];
310 $assistantId = json_decode($result,
true)[
'id'];
319 $result = $ai->generateContent($payload,
'auto',
'thread',
'', array(
'OpenAI-Beta',
'assistants=v2'));
321 if (is_array($result)) {
322 if ($result[
'error']) {
324 $errors[] = $result[
'error'];
326 if ($result[
'curl_error_no']) {
328 $errors[] = $result[
'curl_error_no'];
331 $threadId = json_decode($result,
true)[
'id'];
342 "type" =>
"input_text",
348 "file_id" => $fileId,
349 "tools" => [[
"type" =>
"file_search"]]
353 $moreendpoint = $threadId.
'/messages';
355 $result = $ai->generateContent($payload,
'auto',
'thread',
'', array(
'OpenAI-Beta',
'assistants=v2'), $moreendpoint);
357 if (is_array($result)) {
358 if ($result[
'error']) {
360 $errors[] = $result[
'error'];
362 if ($result[
'curl_error_no']) {
364 $errors[] = $result[
'curl_error_no'];
373 [
"assistant_id" => $assistantId]
375 $moreendpoint = $threadId.
'/runs';
377 $result = $ai->generateContent($payload,
'auto',
'thread',
'', array(
'OpenAI-Beta',
'assistants=v2'), $moreendpoint);
379 if (is_array($result)) {
380 if ($result[
'error']) {
382 $errors[] = $result[
'error'];
384 if ($result[
'curl_error_no']) {
386 $errors[] = $result[
'curl_error_no'];
389 $runId = json_decode($result,
true)[
'id'];
400 $moreendpoint = $threadId.
'/runs/'.$runId;
402 $result = $ai->generateContent($payload,
'auto',
'thread',
'', array(
'OpenAI-Beta',
'assistants=v2'), $moreendpoint);
404 if (is_array($result)) {
405 if ($result[
'error']) {
407 $errors[] = $result[
'error'];
409 if ($result[
'curl_error_no']) {
411 $errors[] = $result[
'curl_error_no'];
414 $status =
'completed';
416 $status = json_decode($result,
true)[
'status'];
418 }
while ($status !==
"completed");
425 $moreendpoint = $threadId.
'/messages';
427 $result = $ai->generateContent($prompt,
'auto',
'thread',
'', array(
'OpenAI-Beta',
'assistants=v2'));
429 if (is_array($result)) {
430 if ($result[
'error']) {
432 $errors[] = $result[
'error'];
434 if ($result[
'curl_error_no']) {
436 $errors[] = $result[
'curl_error_no'];
450if (!empty($errors)) {
451 http_response_code(500);
453 print json_encode(array(
'errors' => $errors));
455 $data = json_decode((
string) $answer,
true);
458 http_response_code(500);
461 $errors[] =
'Failed to decode answer';
462 print
'Failed to decode answer';
dolDocToText($filetoprocess, $useFullTextIndexation='pdftotext', $options='html')
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.