[DOCS] KB: modello pagina Rischi (rischi=requisiti, framing) + ingest
Doc SYSTEM per ARIA: pagina Rischi = requisiti del framework (Det. ACN 164179/2025), framing 'rischio di non conformita', codice RSK interno (non ACN), matrice=rappresentazione (art.24), rischi aggiuntivi all-hazard per admin. + scripts/ingest-risks-model.php. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f6d2076684
commit
03796978c5
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* ingest-risks-model.php — Indicizza docs/kb/RISCHI_MODELLO.md nella KB Qdrant nis2_kb
|
||||
* (scope SYSTEM) così ARIA spiega correttamente la pagina Rischi (ticket #500, framing normativo).
|
||||
* Idempotente: cancella i chunk della stessa fonte prima del re-upsert.
|
||||
* Eseguire (host): docker exec nis2-app php /var/www/nis2-agile/application/_ingest-risks.php
|
||||
* (copiare script+doc sotto application/ come per gli altri ingest).
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli') { fwrite(STDERR, "Solo CLI\n"); exit(1); }
|
||||
if (!defined('BASE_PATH')) define('BASE_PATH', dirname(__DIR__));
|
||||
if (!defined('APP_PATH')) define('APP_PATH', BASE_PATH . '/application');
|
||||
require_once APP_PATH . '/config/env.php';
|
||||
require_once APP_PATH . '/config/config.php';
|
||||
require_once APP_PATH . '/config/database.php';
|
||||
require_once APP_PATH . '/services/EmbedService.php';
|
||||
require_once APP_PATH . '/services/VectorService.php';
|
||||
|
||||
$CANDIDATES = [
|
||||
BASE_PATH . '/docs/kb/RISCHI_MODELLO.md',
|
||||
__DIR__ . '/RISCHI_MODELLO.md',
|
||||
__DIR__ . '/_risks_model.md',
|
||||
APP_PATH . '/_risks_model.md',
|
||||
];
|
||||
$DOC = '';
|
||||
foreach ($CANDIDATES as $c) { if (is_file($c)) { $DOC = $c; break; } }
|
||||
$SOURCE = 'NIS2 Agile — Pagina Gestione Rischi (modello rischi=requisiti)';
|
||||
$TITLE = 'Pagina Rischi NIS2 Agile — rischi dai requisiti, codifica RSK, matrice';
|
||||
|
||||
function logln($m){ echo '['.date('Y-m-d H:i:s')."] $m\n"; }
|
||||
function uuid(){ $b=random_bytes(16); $b[6]=chr((ord($b[6])&0x0f)|0x40); $b[8]=chr((ord($b[8])&0x3f)|0x80); return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($b),4)); }
|
||||
function chunkText($t,$size=2000,$ov=200){ $t=mb_convert_encoding($t,'UTF-8','UTF-8'); $r=[]; $len=mb_strlen($t,'UTF-8'); $s=0; while($s<$len){ $take=min($size,$len-$s); $p=mb_substr($t,$s,$take,'UTF-8'); if(trim($p)!=='')$r[]=$p; if($s+$take>=$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');
|
||||
Reference in New Issue
Block a user