mirror of
https://github.com/signerless/llm-checker.git
synced 2026-10-19 09:54:45 +00:00
This commit adds a comprehensive AI-powered model selection system using machine learning: 🧠 **AI Model Selector Framework** - TabTransformer model architecture for hardware-aware model selection - Lightweight quantized ONNX model (<150KB) for fast inference - Comprehensive Python training pipeline with data collection and preprocessing - JavaScript runtime with ONNX integration for real-time model selection 🔬 **Machine Learning Pipeline** - benchmark_collector.py: Automated performance data collection across different hardware - dataset_aggregator.py: Data preprocessing and training label generation - train_model.py: TabTransformer training with quantization and ONNX export - Hardware feature engineering with categorical and numerical features 🎯 **Smart Selection Logic** - AI-powered predictions based on hardware specifications - Robust fallback heuristics when AI model unavailable - Confidence scoring and multi-model ranking - Hardware tier classification (CPU, RAM, VRAM) ⚡ **New CLI Command: ai-check** - `ai-check --status`: Check AI model training status - `ai-check --benchmark`: Collect performance benchmarks - `ai-check --train`: Train the AI model - `ai-check --models <list>`: Select from specific models - `ai-check --prompt <text>`: Run with selected model 🔧 **Technical Features** - Optional ONNX Runtime dependency with graceful fallback - System information detection with multiple fallback methods - Cross-platform compatibility (macOS, Linux, Windows) - Integration with existing Ollama client and hardware detection 📊 **Model Architecture** - 2-layer TabTransformer with 32-dim embeddings - Binary classification for optimal model selection - Features: model size, CPU cores/freq, RAM/VRAM, GPU model, platform - Target: >90% AUC, <150KB model size, <100ms inference This enables intelligent, hardware-optimized model selection that learns from real performance data across diverse system configurations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
194 lines
No EOL
7 KiB
JavaScript
Executable file
194 lines
No EOL
7 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
const AIModelSelector = require('./index');
|
|
const { spawn } = require('child_process');
|
|
|
|
class OllamaAISelector {
|
|
constructor() {
|
|
this.selector = new AIModelSelector();
|
|
}
|
|
|
|
async getAvailableModels() {
|
|
return new Promise((resolve, reject) => {
|
|
const ollama = spawn('ollama', ['list']);
|
|
let output = '';
|
|
let error = '';
|
|
|
|
ollama.stdout.on('data', (data) => {
|
|
output += data.toString();
|
|
});
|
|
|
|
ollama.stderr.on('data', (data) => {
|
|
error += data.toString();
|
|
});
|
|
|
|
ollama.on('close', (code) => {
|
|
if (code !== 0) {
|
|
reject(new Error(`Ollama list failed: ${error}`));
|
|
return;
|
|
}
|
|
|
|
// Parse ollama list output
|
|
const lines = output.trim().split('\n').slice(1); // Skip header
|
|
const models = lines
|
|
.filter(line => line.trim())
|
|
.map(line => line.split(/\s+/)[0])
|
|
.filter(model => model && !model.includes('NAME'));
|
|
|
|
resolve(models);
|
|
});
|
|
});
|
|
}
|
|
|
|
async runOllamaModel(modelName, prompt) {
|
|
console.log(`🚀 Running Ollama with ${modelName}...`);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const args = ['run', modelName];
|
|
if (prompt) {
|
|
args.push(prompt);
|
|
}
|
|
|
|
const ollama = spawn('ollama', args, {
|
|
stdio: 'inherit' // Stream output directly to terminal
|
|
});
|
|
|
|
ollama.on('close', (code) => {
|
|
if (code === 0) {
|
|
resolve();
|
|
} else {
|
|
reject(new Error(`Ollama exited with code ${code}`));
|
|
}
|
|
});
|
|
|
|
ollama.on('error', (error) => {
|
|
reject(new Error(`Failed to start Ollama: ${error.message}`));
|
|
});
|
|
});
|
|
}
|
|
|
|
async selectAndRun(candidateModels = null, prompt = null) {
|
|
try {
|
|
console.log('🧠 AI-Powered Ollama Model Selector');
|
|
console.log('=' * 40);
|
|
|
|
// Get available models if not provided
|
|
if (!candidateModels) {
|
|
console.log('📋 Getting available models...');
|
|
candidateModels = await this.getAvailableModels();
|
|
|
|
if (candidateModels.length === 0) {
|
|
console.log('❌ No Ollama models found. Install some models first:');
|
|
console.log(' ollama pull llama2:7b');
|
|
console.log(' ollama pull mistral:7b');
|
|
console.log(' ollama pull phi3:mini');
|
|
return;
|
|
}
|
|
|
|
console.log(`✅ Found ${candidateModels.length} models: ${candidateModels.join(', ')}`);
|
|
}
|
|
|
|
// Use AI to select best model
|
|
let result;
|
|
try {
|
|
console.log('🔍 Analyzing your hardware...');
|
|
result = await this.selector.predictBestModel(candidateModels);
|
|
console.log('✅ AI selection completed');
|
|
} catch (error) {
|
|
console.log(`⚠️ AI selection failed: ${error.message}`);
|
|
console.log('🔄 Falling back to heuristic selection...');
|
|
|
|
const specs = await this.selector.getSystemSpecs();
|
|
result = this.selector.selectModelHeuristic(candidateModels, specs);
|
|
}
|
|
|
|
// Display results
|
|
console.log('\n📊 Selection Results:');
|
|
console.log(`🏆 Best Model: ${result.bestModel}`);
|
|
|
|
if (result.systemSpecs) {
|
|
const specs = result.systemSpecs;
|
|
console.log(`💻 System: ${specs.cpu_cores} cores, ${specs.total_ram_gb.toFixed(1)}GB RAM`);
|
|
console.log(`🎮 GPU: ${specs.gpu_model_normalized} (${specs.gpu_vram_gb.toFixed(1)}GB VRAM)`);
|
|
}
|
|
|
|
if (result.allPredictions) {
|
|
console.log('\n📈 All Model Scores:');
|
|
result.allPredictions.slice(0, 5).forEach((pred, i) => {
|
|
const score = (pred.score * 100).toFixed(1);
|
|
const icon = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : ' ';
|
|
console.log(`${icon} ${pred.model}: ${score}% (${pred.size}B params)`);
|
|
});
|
|
}
|
|
|
|
// Run the selected model
|
|
console.log(`\n🚀 Launching ${result.bestModel}...`);
|
|
await this.runOllamaModel(result.bestModel, prompt);
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error:', error.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// CLI interface
|
|
async function main() {
|
|
const args = process.argv.slice(2);
|
|
|
|
if (args.includes('--help') || args.includes('-h')) {
|
|
console.log('AI-Powered Ollama Model Selector');
|
|
console.log('');
|
|
console.log('Automatically selects the best Ollama model for your hardware using AI.');
|
|
console.log('');
|
|
console.log('Usage:');
|
|
console.log(' ollama-select # Select from all available models');
|
|
console.log(' ollama-select model1 model2 # Select from specific models');
|
|
console.log(' ollama-select --test # Test the selector');
|
|
console.log('');
|
|
console.log('Examples:');
|
|
console.log(' ollama-select llama2:7b mistral:7b phi3:mini');
|
|
console.log(' ollama-select');
|
|
console.log('');
|
|
return;
|
|
}
|
|
|
|
if (args.includes('--test')) {
|
|
console.log('🧪 Testing AI Model Selector...');
|
|
|
|
const selector = new AIModelSelector();
|
|
try {
|
|
await selector.initialize();
|
|
|
|
const testModels = ['llama2:7b', 'mistral:7b', 'phi3:mini'];
|
|
const result = await selector.predictBestModel(testModels);
|
|
|
|
console.log('✅ Test successful!');
|
|
console.log(`Best model: ${result.bestModel}`);
|
|
console.log('Scores:', result.allPredictions.map(p => `${p.model}: ${(p.score * 100).toFixed(1)}%`));
|
|
|
|
} catch (error) {
|
|
console.log('❌ Test failed:', error.message);
|
|
|
|
// Test fallback
|
|
console.log('🔄 Testing fallback heuristic...');
|
|
const result = selector.selectModelHeuristic(testModels);
|
|
console.log(`Fallback result: ${result.bestModel} (${result.reason})`);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Extract model candidates and prompt
|
|
const candidateModels = args.filter(arg => !arg.startsWith('--'));
|
|
const prompt = null; // Could be extended to accept prompts
|
|
|
|
const cli = new OllamaAISelector();
|
|
await cli.selectAndRun(candidateModels.length > 0 ? candidateModels : null, prompt);
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main().catch(console.error);
|
|
}
|
|
|
|
module.exports = OllamaAISelector; |