mirror of
https://github.com/signerless/llm-checker.git
synced 2026-10-19 09:54:45 +00:00
fix(ai-check): use canonical GPU detection
This commit is contained in:
parent
7ff6aa0d19
commit
6fb813af65
3 changed files with 150 additions and 6 deletions
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
const DeterministicModelSelector = require('./deterministic-selector');
|
||||
const HardwareDetector = require('../hardware/detector');
|
||||
const { OllamaNativeScraper } = require('../ollama/native-scraper');
|
||||
const OllamaClient = require('../ollama/client');
|
||||
const crypto = require('crypto');
|
||||
|
|
@ -14,10 +15,11 @@ const path = require('path');
|
|||
const { evaluateFineTuningSupport } = require('./fine-tuning-support');
|
||||
|
||||
class AICheckSelector {
|
||||
constructor() {
|
||||
this.deterministicSelector = new DeterministicModelSelector();
|
||||
this.ollamaClient = new OllamaClient();
|
||||
this.ollamaScraper = new OllamaNativeScraper();
|
||||
constructor(options = {}) {
|
||||
this.deterministicSelector = options.deterministicSelector || new DeterministicModelSelector();
|
||||
this.hardwareDetector = options.hardwareDetector || new HardwareDetector();
|
||||
this.ollamaClient = options.ollamaClient || new OllamaClient();
|
||||
this.ollamaScraper = options.ollamaScraper || new OllamaNativeScraper();
|
||||
this.cachePath = path.join(require('os').homedir(), '.llm-checker', 'ai-check-cache.json');
|
||||
|
||||
// Priority models for evaluation (prefer these if installed)
|
||||
|
|
@ -81,6 +83,40 @@ Respond with JSON only, no additional text.`;
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the same hardware detector as `check` and `hw-detect`, then translate
|
||||
* its richer result into the deterministic selector's input shape.
|
||||
*
|
||||
* Previously AI Check called DeterministicModelSelector#getHardware(), whose
|
||||
* intentionally minimal non-macOS fallback always returned `cpu_only`. That
|
||||
* discarded GPUs which the unified detector had already found (notably the
|
||||
* Windows RX 7900 XTX reported in issue #106).
|
||||
*/
|
||||
async getDetectedHardwareProfile() {
|
||||
const detected = await this.hardwareDetector.getSystemInfo();
|
||||
const summary = detected?.summary || {};
|
||||
const bestBackend = String(summary.bestBackend || '').toLowerCase();
|
||||
const runtimeBackend = String(summary.runtimeBackend || '').toLowerCase();
|
||||
|
||||
const normalized = this.deterministicSelector.normalizeHardwareProfile({
|
||||
...detected,
|
||||
acceleration: {
|
||||
supports_metal: bestBackend === 'metal' || runtimeBackend === 'metal',
|
||||
supports_cuda: bestBackend === 'cuda' || runtimeBackend === 'cuda',
|
||||
supports_rocm: bestBackend === 'rocm' || runtimeBackend === 'rocm',
|
||||
supports_vulkan: runtimeBackend === 'vulkan'
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...normalized,
|
||||
acceleration: {
|
||||
...normalized.acceleration,
|
||||
supports_vulkan: runtimeBackend === 'vulkan'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async aiCheck(options = {}) {
|
||||
const {
|
||||
category = 'general',
|
||||
|
|
@ -93,8 +129,9 @@ Respond with JSON only, no additional text.`;
|
|||
|
||||
const chalk = require('chalk');
|
||||
|
||||
// Phase 1: Get ALL available models from the 177-model Ollama database
|
||||
const hardware = await this.deterministicSelector.getHardware();
|
||||
// Phase 1: Detect hardware through the canonical detector used by the
|
||||
// rest of the CLI, then load all available models.
|
||||
const hardware = await this.getDetectedHardwareProfile();
|
||||
|
||||
// Use the same synced database that recommend/check use.
|
||||
const ollamaData = await this.loadModelDatabase();
|
||||
|
|
|
|||
106
tests/ai-check-hardware-detection.test.js
Normal file
106
tests/ai-check-hardware-detection.test.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
const assert = require('assert');
|
||||
|
||||
const AICheckSelector = require('../src/models/ai-check-selector');
|
||||
|
||||
async function testAiCheckUsesCanonicalDiscreteGpuDetection() {
|
||||
const detectedHardware = {
|
||||
cpu: {
|
||||
brand: 'AMD Ryzen 7 9800X3D 8-Core Processor',
|
||||
architecture: 'x86_64',
|
||||
cores: 16,
|
||||
physicalCores: 8
|
||||
},
|
||||
memory: { total: 32 },
|
||||
gpu: {
|
||||
model: 'AMD Radeon RX 7900 XTX',
|
||||
vendor: 'AMD',
|
||||
vram: 24,
|
||||
vramPerGPU: 24,
|
||||
gpuCount: 1,
|
||||
dedicated: true,
|
||||
all: [
|
||||
{
|
||||
model: 'AMD Radeon RX 7900 XTX',
|
||||
vendor: 'AMD',
|
||||
vram: 24
|
||||
}
|
||||
]
|
||||
},
|
||||
summary: {
|
||||
bestBackend: 'cpu',
|
||||
runtimeBackend: 'cpu',
|
||||
totalVRAM: 24,
|
||||
hasDedicatedGPU: true,
|
||||
hasIntegratedGPU: false
|
||||
},
|
||||
os: { platform: 'win32' }
|
||||
};
|
||||
|
||||
let detectorCalls = 0;
|
||||
const selector = new AICheckSelector({
|
||||
hardwareDetector: {
|
||||
async getSystemInfo() {
|
||||
detectorCalls += 1;
|
||||
return detectedHardware;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const hardware = await selector.getDetectedHardwareProfile();
|
||||
|
||||
assert.strictEqual(detectorCalls, 1, 'AI Check should call the canonical hardware detector');
|
||||
assert.strictEqual(hardware.gpu.type, 'amd', 'the detected Radeon must not collapse to cpu_only');
|
||||
assert.strictEqual(hardware.gpu.vramGB, 24, 'the detected 24GB VRAM budget must be preserved');
|
||||
assert.strictEqual(hardware.gpu.gpuCount, 1, 'virtual adapters must not reappear as extra GPUs');
|
||||
assert.strictEqual(hardware.acceleration.supports_rocm, false, 'inventory detection must not claim an unconfirmed ROCm runtime');
|
||||
}
|
||||
|
||||
async function testAiCheckPreservesConfirmedVulkanAssist() {
|
||||
const selector = new AICheckSelector({
|
||||
hardwareDetector: {
|
||||
async getSystemInfo() {
|
||||
return {
|
||||
cpu: { brand: 'AMD Ryzen AI 9', architecture: 'x86_64', cores: 24 },
|
||||
memory: { total: 64 },
|
||||
gpu: {
|
||||
model: 'AMD Radeon 890M Graphics',
|
||||
vendor: 'AMD',
|
||||
vram: 32,
|
||||
sharedMemory: 32,
|
||||
dedicated: false,
|
||||
gpuCount: 1
|
||||
},
|
||||
summary: {
|
||||
bestBackend: 'cpu',
|
||||
runtimeBackend: 'vulkan',
|
||||
hasIntegratedGPU: true,
|
||||
hasDedicatedGPU: false
|
||||
},
|
||||
os: { platform: 'win32' }
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const hardware = await selector.getDetectedHardwareProfile();
|
||||
|
||||
assert.strictEqual(hardware.gpu.type, 'amd');
|
||||
assert.strictEqual(hardware.acceleration.supports_vulkan, true);
|
||||
assert.strictEqual(hardware.acceleration.supports_rocm, false);
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await testAiCheckUsesCanonicalDiscreteGpuDetection();
|
||||
await testAiCheckPreservesConfirmedVulkanAssist();
|
||||
console.log('ai-check-hardware-detection.test.js: OK');
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
run().catch((error) => {
|
||||
console.error('ai-check-hardware-detection.test.js: FAILED');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
|
|
@ -16,6 +16,7 @@ const TESTS = [
|
|||
{ name: 'High-end / multi-GPU VRAM detection', file: 'hardware-vram-highend.test.js', category: 'Hardware' },
|
||||
{ name: 'CPU detector Windows fallback', file: 'cpu-detector-windows-fallback.test.js', category: 'Hardware' },
|
||||
{ name: 'Virtual-monitor GPU detection', file: 'virtual-monitor-gpu-detection.test.js', category: 'Hardware' },
|
||||
{ name: 'AI Check hardware detection', file: 'ai-check-hardware-detection.test.js', category: 'Hardware' },
|
||||
{ name: 'Termux platform support', file: 'termux-platform-support.test.js', category: 'Hardware' },
|
||||
{ name: 'Token speed estimation', file: 'token-speed-estimation.test.js', category: 'Performance' },
|
||||
{ name: 'Deterministic model pool', file: 'deterministic-model-pool-check.js', category: 'Recommendations' },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue