Fix two false alarms in the AI health checks
vv_meta uses columns k/v, so the embedder-match check read nothing and reported "unrecorded" — a silent pass on the one mismatch that returns confident nonsense instead of an error. And Ollama reports tags fully qualified while conf carries the bare name, so an installed embedding model was reported missing. A health panel that cries wolf is worse than none.
This commit is contained in:
@@ -236,8 +236,11 @@ function vv_ai_models_loaded(): ?array {
|
||||
function vv_ai_index_meta(): array {
|
||||
$cfg = vv_ai_config();
|
||||
if (!file_exists($cfg['db'])) return [];
|
||||
// Columns are k/v, not key/value. Named wrongly this returns nothing and the embedder-match
|
||||
// check reports "unrecorded" — a silent pass on the one mismatch that returns confident
|
||||
// nonsense rather than an error.
|
||||
$raw = trim((string)@shell_exec(
|
||||
'sqlite3 ' . escapeshellarg($cfg['db']) . ' ' . escapeshellarg('SELECT key, value FROM vv_meta;') . ' 2>/dev/null'
|
||||
'sqlite3 ' . escapeshellarg($cfg['db']) . ' ' . escapeshellarg('SELECT k, v FROM vv_meta;') . ' 2>/dev/null'
|
||||
));
|
||||
$out = [];
|
||||
foreach (explode("\n", $raw) as $line) {
|
||||
@@ -288,14 +291,14 @@ function vv_ai_health(): array {
|
||||
if ($cfg['model'] === '') {
|
||||
$add('gen', 'Generation model', 'bad', 'not configured',
|
||||
'Set ' . strtoupper(vv_detect_host()) . '_OLLAMA_MODEL in the host conf');
|
||||
} elseif (!in_array($cfg['model'], $names, true)) {
|
||||
} elseif (!vv_ai_model_installed($cfg['model'], $names)) {
|
||||
$add('gen', 'Generation model', 'bad', $cfg['model'] . ' is not installed',
|
||||
'Either `ollama pull` it, or point _OLLAMA_MODEL at one of: ' . implode(', ', array_slice($names, 0, 4)));
|
||||
} else {
|
||||
$add('gen', 'Generation model', 'ok', $cfg['model']);
|
||||
}
|
||||
|
||||
if ($cfg['embed_model'] === '' || !in_array($cfg['embed_model'], $names, true)) {
|
||||
if ($cfg['embed_model'] === '' || !vv_ai_model_installed($cfg['embed_model'], $names)) {
|
||||
$add('embed', 'Embedding model', 'bad',
|
||||
($cfg['embed_model'] ?: 'not configured') . ' is not installed',
|
||||
'Retrieval cannot embed a query without it — `ollama pull ' . ($cfg['embed_model'] ?: 'nomic-embed-text') . '`');
|
||||
@@ -315,7 +318,8 @@ function vv_ai_health(): array {
|
||||
// model without reindexing does not error — it silently returns nonsense, scored
|
||||
// confidently, which is the hardest failure here to notice from the answers alone.
|
||||
$builtWith = $meta['embed_model'] ?? '';
|
||||
if ($builtWith !== '' && $cfg['embed_model'] !== '' && $builtWith !== $cfg['embed_model']) {
|
||||
if ($builtWith !== '' && $cfg['embed_model'] !== ''
|
||||
&& vv_ai_model_norm($builtWith) !== vv_ai_model_norm($cfg['embed_model'])) {
|
||||
$add('embedmatch', 'Index / embedder match', 'bad',
|
||||
'index built with ' . $builtWith . ', conf says ' . $cfg['embed_model'],
|
||||
'Vectors from different models are not comparable — rerun AI/ai_index.sh --force');
|
||||
@@ -348,6 +352,25 @@ function vv_ai_health(): array {
|
||||
return $checks;
|
||||
}
|
||||
|
||||
// Ollama reports tags fully qualified — nomic-embed-text:latest — while conf commonly carries
|
||||
// the bare name, and both are valid references. Comparing literally reports an installed model
|
||||
// as missing, which is exactly the false alarm that makes a health panel worth ignoring.
|
||||
function vv_ai_model_norm(string $name): string {
|
||||
$name = trim($name);
|
||||
if ($name === '') return '';
|
||||
// A colon in the final path segment is a tag; anything else is a registry path.
|
||||
$last = substr($name, strrpos($name, '/') === false ? 0 : strrpos($name, '/') + 1);
|
||||
return str_contains($last, ':') ? $name : $name . ':latest';
|
||||
}
|
||||
|
||||
function vv_ai_model_installed(string $name, array $available): bool {
|
||||
$n = vv_ai_model_norm($name);
|
||||
foreach ($available as $m) {
|
||||
if (vv_ai_model_norm($m) === $n) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function command_exists_node(): bool {
|
||||
static $has = null;
|
||||
if ($has !== null) return $has;
|
||||
|
||||
Reference in New Issue
Block a user