=$len)break; $s+=($size-$ov);} return $r; } if ($DOC === '') { logln('ERRORE: doc non trovato'); exit(1); } logln("doc: $DOC"); $text = preg_replace('/\n{3,}/',"\n\n", trim(preg_replace('/[ \t]+/',' ', (string)file_get_contents($DOC)))); if (strlen($text) < 150) { logln('ERRORE: testo troppo breve'); exit(1); } $chunks = chunkText("DOCUMENTO: Come funziona la pagina Rischi di NIS2 Agile (rischi=requisiti, framing corretto).\n\n".$text); logln(strlen($text).' char -> '.count($chunks).' chunk'); $embed = new EmbedService(); $vector = new VectorService(); $vector->ensureCollection($embed->dims); try { $vector->deleteByFilter(['must'=>[['key'=>'scope','match'=>['value'=>'SYSTEM']],['key'=>'source','match'=>['value'=>$SOURCE]]]]); logln('rimossi chunk precedenti di questa fonte'); } catch (Exception $e) { logln('(warn) delete: '.$e->getMessage()); } $docUuid = uuid(); $points = []; foreach ($chunks as $i=>$ch) { $vec=null; for($try=1;$try<=5;$try++){ try{ $vec=$embed->embed($ch); break; }catch(Throwable $e){ if($try===5) throw $e; sleep($try);} } $points[]=['id'=>uuid(),'vector'=>$vec,'payload'=>['doc_uuid'=>$docUuid,'title'=>$TITLE.($i>0?' (parte '.($i+1).')':''),'chunk'=>$ch,'entity_type'=>'guida_prodotto','source'=>$SOURCE,'lang'=>'it','scope'=>'SYSTEM','consulting_firm_id'=>null,'organization_id'=>null,'shared_with_orgs'=>[],'uploaded_by'=>0]]; } foreach (array_chunk($points,64) as $b) { $vector->upsertBatch($b); } try { $stmt = Database::getInstance()->prepare("INSERT INTO kb_uploaded_documents (qdrant_doc_uuid, scope, consulting_firm_id, organization_id, uploaded_by, title, entity_type, source, lang, chunk_count, shared_with_orgs, status) VALUES (?, 'SYSTEM', NULL, NULL, 0, ?, 'guida_prodotto', ?, 'it', ?, '[]', 'ready')"); $stmt->execute([$docUuid, $TITLE, $SOURCE, count($chunks)]); } catch (Exception $e) { logln('(warn) tracking: '.$e->getMessage()); } logln("OK indicizzato: $docUuid, ".count($chunks).' chunk');