alwas-ml-models / integration /alwas-ml-client.js
muthuk1's picture
Upload integration/alwas-ml-client.js
3b60e51 verified
/**
* ALWAS ML Client — Drop-in integration for Express.js backend
* Replaces Groq API with local ML models for complexity estimation,
* bottleneck detection, and completion time prediction.
*
* Usage:
* const ml = require('./alwas-ml-client');
* const estimate = await ml.estimateBlock({ block_type: 'PLL', tech_node: '7nm', ... });
*/
const ML_API_URL = process.env.ML_API_URL || 'http://localhost:7860';
class ALWASMLClient {
constructor(baseUrl = ML_API_URL) {
this.baseUrl = baseUrl;
}
async _post(endpoint, data) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`ML API error: ${response.status} ${await response.text()}`);
}
return response.json();
}
async _get(endpoint) {
const response = await fetch(`${this.baseUrl}${endpoint}`);
if (!response.ok) {
throw new Error(`ML API error: ${response.status}`);
}
return response.json();
}
/**
* Estimate complexity and hours for a new block.
* DIRECT REPLACEMENT for Groq AI estimation endpoint.
*
* @param {Object} block - Block metadata
* @param {string} block.block_type - e.g., 'ADC', 'PLL', 'LDO'
* @param {string} block.tech_node - e.g., '7nm', '28nm'
* @param {string} [block.priority='P3-Medium'] - Priority level
* @param {number} [block.transistor_count] - Estimated transistor count
* @param {boolean} [block.has_dependencies=false]
* @param {number} [block.num_dependencies=0]
* @param {number} [block.constraint_complexity=1.0] - 0-3 scale
* @param {number} [block.drc_iterations=2]
* @param {number} [block.engineer_skill_factor=1.0] - 0.5-1.5
* @returns {Object} { complexity, estimated_hours, confidence, reasoning, ... }
*/
async estimateBlock(block) {
return this._post('/predict/estimate', block);
}
/**
* Predict bottleneck risk for an in-progress block.
* Use in the hourly cron bottleneck scanner.
*
* @param {Object} block - Current block state
* @returns {Object} { risk_level, confidence, recommendations, should_alert }
*/
async predictBottleneck(block) {
return this._post('/predict/bottleneck', block);
}
/**
* Predict remaining time to completion.
* Use in Block Detail page for "Est. Completion" row.
*
* @param {Object} block - Block with progress info
* @returns {Object} { remaining_hours, remaining_days, estimated_completion_date, progress_percent }
*/
async predictCompletion(block) {
return this._post('/predict/completion', block);
}
/**
* Bulk estimate multiple blocks at once.
* Use with CSV bulk import feature.
*
* @param {Array<Object>} blocks - Array of block metadata
* @returns {Object} { count, estimates, total_estimated_hours }
*/
async bulkEstimate(blocks) {
return this._post('/predict/bulk-estimate', { blocks });
}
/**
* Get model performance metrics.
* @returns {Object} metrics for all 4 models
*/
async getMetrics() {
return this._get('/model/metrics');
}
/**
* Get supported block types, tech nodes, priorities.
* @returns {Object} { tech_nodes, block_types, priorities, stages }
*/
async getSupportedValues() {
return this._get('/model/supported-values');
}
/**
* Health check
* @returns {Object} { status, models_loaded, timestamp }
*/
async healthCheck() {
return this._get('/health');
}
/**
* Convert a Mongoose block document to ML API format for estimation.
* @param {Object} mongoBlock - Mongoose Block document
* @returns {Object} formatted for /predict/estimate
*/
static formatForEstimate(mongoBlock) {
return {
block_type: mongoBlock.type || mongoBlock.blockType,
tech_node: mongoBlock.techNode || mongoBlock.tech_node,
priority: mongoBlock.priority || 'P3-Medium',
transistor_count: mongoBlock.transistorCount || mongoBlock.transistor_count,
has_dependencies: (mongoBlock.dependencies?.length || 0) > 0,
num_dependencies: mongoBlock.dependencies?.length || 0,
constraint_complexity: mongoBlock.constraintComplexity || 1.0,
drc_iterations: mongoBlock.drcIterations || 2,
engineer_skill_factor: 1.0, // default; update from engineer profile
};
}
/**
* Convert a Mongoose block document to ML API format for bottleneck prediction.
* @param {Object} mongoBlock - Mongoose Block document
* @param {number} daysSinceLastTransition - Days in current stage
* @returns {Object} formatted for /predict/bottleneck
*/
static formatForBottleneck(mongoBlock, daysSinceLastTransition) {
return {
block_type: mongoBlock.type || mongoBlock.blockType,
tech_node: mongoBlock.techNode || mongoBlock.tech_node,
priority: mongoBlock.priority || 'P3-Medium',
estimated_hours: mongoBlock.estimatedHours || 20,
hours_logged: mongoBlock.hoursLogged || 0,
drc_iterations: mongoBlock.drcIterations || 2,
drc_violations_total: mongoBlock.drcViolations || 0,
lvs_mismatches_total: mongoBlock.lvsMismatches || 0,
current_stage: mongoBlock.status,
days_in_current_stage: daysSinceLastTransition,
engineer_skill_factor: 1.0,
is_overdue: mongoBlock.dueDate ? new Date() > new Date(mongoBlock.dueDate) : false,
};
}
/**
* Convert a Mongoose block document to ML API format for completion prediction.
* @param {Object} mongoBlock - Mongoose Block document
* @returns {Object} formatted for /predict/completion
*/
static formatForCompletion(mongoBlock) {
const startDate = new Date(mongoBlock.createdAt || mongoBlock.startDate);
const now = new Date();
const daysSinceStart = (now - startDate) / (1000 * 60 * 60 * 24);
return {
block_type: mongoBlock.type || mongoBlock.blockType,
tech_node: mongoBlock.techNode || mongoBlock.tech_node,
priority: mongoBlock.priority || 'P3-Medium',
estimated_hours: mongoBlock.estimatedHours || 20,
engineer_skill_factor: 1.0,
drc_iterations: mongoBlock.drcIterations || 2,
current_stage: mongoBlock.status,
cumulative_hours: mongoBlock.hoursLogged || 0,
cumulative_days: daysSinceStart,
cumulative_drc_violations: mongoBlock.drcViolations || 0,
cumulative_lvs_mismatches: mongoBlock.lvsMismatches || 0,
};
}
}
module.exports = new ALWASMLClient();
module.exports.ALWASMLClient = ALWASMLClient;