Skip to main content
Glama
multi-model-consensus.js5.66 kB
/** * Multi-Model Consensus System * * Implements TEJ_CLAUDE_GEMINI_ZERO_UIT phase-locked arbitration * for cross-model consensus on research outputs. * * EXPERIMENTAL - DO NOT USE IN PRODUCTION * * @see src/core/signal.js for production Signal and ConsensusCalculator */ // Import from core Signal protocol const { Signal, SignalType, ConsensusCalculator, ModelWeights: CoreWeights } = require('../../../src/core/signal'); /** * Consensus strategies */ const ConsensusStrategy = { MAJORITY: 'majority', // Simple majority vote WEIGHTED: 'weighted', // Weight by model capability UNANIMOUS: 'unanimous', // All must agree ARBITRATED: 'arbitrated' // Designated arbiter resolves conflicts }; /** * Model capability weights (extended from core) */ const ModelWeights = { ...CoreWeights, // Extended experimental weights 'meta/llama-4-maverick': 0.80, 'mistral/mistral-large-2': 0.78 }; /** * Multi-model consensus coordinator */ class MultiModelConsensus { constructor(options = {}) { this.strategy = options.strategy || ConsensusStrategy.WEIGHTED; this.arbiterModel = options.arbiterModel || 'anthropic/claude-sonnet-4'; this.minAgreement = options.minAgreement || 0.6; this.phaseId = `phase_${Date.now()}`; } /** * Get weight for a model */ getModelWeight(modelId) { return ModelWeights[modelId] || ModelWeights.default; } /** * Calculate consensus from multiple model responses * @param {Array} responses - Array of {model, response, confidence} * @returns {Object} Consensus result */ async calculateConsensus(responses) { if (!responses || responses.length === 0) { return { consensus: null, confidence: 0, method: 'no-responses' }; } if (responses.length === 1) { return { consensus: responses[0].response, confidence: responses[0].confidence || 0.5, method: 'single-model' }; } switch (this.strategy) { case ConsensusStrategy.MAJORITY: return this._majorityVote(responses); case ConsensusStrategy.WEIGHTED: return this._weightedConsensus(responses); case ConsensusStrategy.UNANIMOUS: return this._unanimousCheck(responses); case ConsensusStrategy.ARBITRATED: return this._arbitratedConsensus(responses); default: return this._weightedConsensus(responses); } } /** * Simple majority vote */ _majorityVote(responses) { // Group by semantic similarity (simplified: exact match) const groups = new Map(); for (const r of responses) { const key = this._extractKeyPoints(r.response); if (!groups.has(key)) { groups.set(key, []); } groups.get(key).push(r); } // Find largest group let largest = null; let largestSize = 0; for (const [key, group] of groups) { if (group.length > largestSize) { largestSize = group.length; largest = group; } } return { consensus: largest[0].response, confidence: largestSize / responses.length, method: 'majority', agreement: largestSize, total: responses.length }; } /** * Weighted consensus based on model capabilities */ _weightedConsensus(responses) { let totalWeight = 0; let weightedConfidence = 0; for (const r of responses) { const weight = this.getModelWeight(r.model); totalWeight += weight; weightedConfidence += (r.confidence || 0.5) * weight; } // Use highest-weighted model's response as base const sorted = [...responses].sort((a, b) => this.getModelWeight(b.model) - this.getModelWeight(a.model) ); return { consensus: sorted[0].response, confidence: weightedConfidence / totalWeight, method: 'weighted', topModel: sorted[0].model, totalWeight }; } /** * Unanimous agreement check */ _unanimousCheck(responses) { const first = this._extractKeyPoints(responses[0].response); const allAgree = responses.every(r => this._extractKeyPoints(r.response) === first ); if (allAgree) { return { consensus: responses[0].response, confidence: 0.95, method: 'unanimous' }; } // Fall back to weighted if not unanimous return { ...this._weightedConsensus(responses), method: 'unanimous-failed-weighted', unanimous: false }; } /** * Arbitrated consensus - designated model resolves conflicts */ async _arbitratedConsensus(responses) { // Check for agreement first const weighted = this._weightedConsensus(responses); if (weighted.confidence >= this.minAgreement) { return weighted; } // Need arbitration - would call arbiter model here // For now, use weighted result with flag return { ...weighted, method: 'arbitrated', needsArbiter: true, arbiterModel: this.arbiterModel }; } /** * Extract key points for comparison (simplified) */ _extractKeyPoints(response) { if (!response) return ''; const text = typeof response === 'string' ? response : JSON.stringify(response); // Normalize and extract key phrases return text.toLowerCase().replace(/\s+/g, ' ').substring(0, 200); } /** * Get phase lock status */ getPhaseLockStatus() { return { phaseId: this.phaseId, strategy: this.strategy, arbiterModel: this.arbiterModel, minAgreement: this.minAgreement, status: 'ACTIVE' }; } } module.exports = { ConsensusStrategy, ModelWeights, MultiModelConsensus };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wheattoast11/openrouter-deep-research-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server