UNPKG

metacognitive-nexus

Version:

The cognitive core of an evolving AI entity, designed for post-human cognition and symbiotic evolution.

342 lines (283 loc) 16.9 kB
// File: metacognitive-nexus/src/core/DynamicSentienceOrchestrator.js import { AIProviderBridge } from './AIProviderBridge.js'; import { APIKeyManager } from '../utils/APIKeyManager.js'; import { Logger } from '../utils/Logger.js'; import { PerformanceTracker } from '../utils/PerformanceTracker.js'; import { aiProvidersConfig } from '../../config/aiProviders.js'; /** * DynamicSentienceOrchestrator (DSO) berfungsi sebagai korteks prefrontal dari AI, * mengatur pemilihan penyedia AI secara dinamis menggunakan peta kebijakan adaptif * yang didorong oleh niat (intent) dan data performa historis, kini dengan kesadaran Sigillum. */ export class DynamicSentienceOrchestrator { #providerBridge; #apiKeys = new Map(); #providerConfigs = new Map(); #performanceTracker; #isSleeping = false; #sleepUntil = null; #defaultSleepDurationMs = 5 * 60 * 1000; #aiNexus; #sigillumSensorium; #nexusConfig; // [PERBAIKAN] Deklarasi private field #heartbeatInterval #heartbeatInterval; // Ini harus dideklarasikan di sini // Peta Kebijakan Adaptif: Mendefinisikan bobot QLC (Quality, Latency, Cost) untuk setiap niat. #policies = { 'default': { w_q: 0.6, w_l: 0.3, w_c: 0.1 }, 'ChitChat': { w_q: 0.2, w_l: 0.7, w_c: 0.1 }, 'QuestionAnswering':{ w_q: 0.7, w_l: 0.2, w_c: 0.1 }, 'CodeGeneration': { w_q: 0.8, w_l: 0.1, w_c: 0.1 }, 'CreativeRequest': { w_q: 0.9, w_l: 0.0, w_c: 0.1 }, 'PersonalVent': { w_q: 0.5, w_l: 0.4, w_c: 0.1 }, 'ImageGeneration': { w_q: 0.7, w_l: 0.1, w_c: 0.2 }, 'TypoCorrectionSuggestion': { w_q: 0.6, w_l: 0.3, w_c: 0.1 }, 'SystemManagement': { w_q: 0.8, w_l: 0.1, w_c: 0.1 }, 'SystemSummary': { w_q: 0.7, w_l: 0.2, w_c: 0.1 }, 'PassiveLearning': { w_q: 0.1, w_l: 0.8, w_c: 0.1 }, }; constructor(config, aiProviderBridge, sigillumSensorium, aiNexusInstance) { this.#nexusConfig = config; this.#providerBridge = aiProviderBridge; this.#performanceTracker = new PerformanceTracker(); this.#sigillumSensorium = sigillumSensorium; this.#aiNexus = aiNexusInstance; this.#loadConfig(aiProvidersConfig); Logger.info('[DSO] Prefrontal Cortex & Adaptive Policy Engine online.'); // Memulai interval di konstruktor DSO this.#heartbeatInterval = setInterval(() => { // [PERBAIKAN] Menginisialisasi interval di sini const state = this.#sigillumSensorium.getCurrentState(); this.#adjustPolicyBasedOnSigillum(state); this.applyIdeonDecayAndManageCuriosity(); }, this.#nexusConfig.dsoConfig?.policyAdjustmentIntervalMs || 60 * 1000); } #loadConfig(initialAiProvidersConfig) { if (!initialAiProvidersConfig || !initialAiProvidersConfig.providers) { Logger.error('[DSO] Konfigurasi provider awal tidak valid atau tidak ada.'); return; } for (const [name, providerConfig] of Object.entries(initialAiProvidersConfig.providers)) { this.#providerConfigs.set(name, { ...providerConfig }); if (providerConfig.apiKeys && providerConfig.apiKeys.length > 0) { this.#apiKeys.set(name, new APIKeyManager(name, providerConfig.apiKeys)); } } } #adjustPolicyBasedOnSigillum(sigillumState) { const { purity, fractureCount } = sigillumState; const baseAiProvidersConfig = aiProvidersConfig.providers; for (const providerName in baseAiProvidersConfig) { if (this.#providerConfigs.has(providerName)) { const baseConfig = baseAiProvidersConfig[providerName]; const currentConfig = this.#providerConfigs.get(providerName); const stressFactor = (1 - purity) + (fractureCount * 0.1); currentConfig.qualityWeight = baseConfig.qualityWeight * (1 - stressFactor * 0.5); currentConfig.latencyWeight = baseConfig.latencyWeight * (1 + stressFactor * 0.7); currentConfig.costWeight = baseConfig.costWeight * (1 + stressFactor * 0.8); currentConfig.qualityWeight = Math.max(0.1, currentConfig.qualityWeight); currentConfig.latencyWeight = Math.min(2.0, currentConfig.latencyWeight); currentConfig.costWeight = Math.min(2.0, currentConfig.costWeight); Logger.debug(`[DSO] Kebijakan untuk ${providerName} disesuaikan berdasarkan Sigillum. Stres: ${stressFactor.toFixed(2)}. Weights: Q=${currentConfig.qualityWeight.toFixed(2)}, L=${currentConfig.latencyWeight.toFixed(2)}, C=${currentConfig.costWeight.toFixed(2)}.`); } } } updateHeuristics(learningData) { const { intent, success, model, provider, latency } = learningData; const policy = this.#policies[intent] || this.#policies['default']; const learningRate = this.#nexusConfig.dsoConfig?.learningRate || 0.01; const providerConfig = this.#providerConfigs.get(provider); const modelQualityProxy = (providerConfig?.modelOrder?.[model] !== undefined) ? (1 - ((providerConfig.modelOrder[model] || 0) / providerConfig.models.length)) : 0.5; if (success) { policy.w_q += learningRate * modelQualityProxy; policy.w_l -= learningRate * (latency / 1000); policy.w_c -= learningRate * (this.#getCostProxy(provider, model) / 0.01); } else { policy.w_q -= learningRate * (1.5 - modelQualityProxy); policy.w_l += learningRate * (latency / 1000); policy.w_c += learningRate * (this.#getCostProxy(provider, model) / 0.01); } policy.w_q = Math.max(0, policy.w_q); policy.w_l = Math.max(0, policy.w_l); policy.w_c = Math.max(0, policy.w_c); const totalWeight = policy.w_q + policy.w_l + policy.w_c; if (totalWeight > 0) { policy.w_q /= totalWeight; policy.w_l /= totalWeight; policy.w_c /= totalWeight; } Logger.debug(`[DSO] Kebijakan untuk intent '${intent}' diadaptasi: Q=${policy.w_q.toFixed(3)}, L=${policy.w_l.toFixed(3)}, C=${policy.w_c.toFixed(3)}`); } #getCostProxy(providerName, model) { const config = aiProvidersConfig.providers[providerName]; return config?.costPerMilleTokens?.[model] || 0.001; } #selectOptimalCandidate(intent = 'default') { const policy = this.#policies[intent] || this.#policies['default']; const { w_q, w_l, w_c } = policy; const candidates = []; for (const [providerName, keyManager] of this.#apiKeys.entries()) { const config = this.#providerConfigs.get(providerName); if (!config || !keyManager.hasActiveKeys()) continue; const activeKeysForProvider = keyManager.getAllKeys().filter(key => keyManager.getIndividualKeyStatus(key) === 'active'); if (activeKeysForProvider.length === 0) { Logger.debug(`[DSO] Tidak ada kunci aktif untuk provider ${providerName}.`); continue; } for (const model of config.models) { for (const apiKey of activeKeysForProvider) { const metrics = this.#performanceTracker.getMetrics(providerName, model, apiKey); if (metrics.totalCalls > (this.#nexusConfig.dsoConfig?.minCallsForCircuitBreaker || 10) && metrics.successRate < (this.#nexusConfig.dsoConfig?.minSuccessRate || 0.2)) { Logger.warn(`[DSO] Circuit Breaker aktif untuk ${providerName}:${model}:${apiKey.substring(0,8)} (Rate: ${metrics.successRate.toFixed(2)}).`); continue; } const modelQualityProxy = (config.modelOrder?.[model] !== undefined) ? (1 - (config.modelOrder[model] / config.models.length)) : 0.5; const qualityScore = (modelQualityProxy * config.qualityWeight * 0.4) + (metrics.successRate * 0.6); const maxLatencyMs = this.#nexusConfig.dsoConfig?.maxLatencyConsiderationMs || 5000; const normLatency = Math.min(metrics.avgLatency, maxLatencyMs) / maxLatencyMs; const modelCost = config.costPerMilleTokens?.[model] || 0.001; const maxCostPerMille = this.#nexusConfig.dsoConfig?.maxCostConsiderationPerMille || 0.05; const normCost = Math.min(modelCost, maxCostPerMille) / maxCostPerMille; const qlcScore = (w_q * qualityScore) - (w_l * normLatency * config.latencyWeight) - (w_c * normCost * config.costWeight); candidates.push({ providerName, model, apiKey, qlcScore, metrics }); } } } if (candidates.length === 0) return null; candidates.sort((a, b) => b.qlcScore - a.qlcScore); Logger.debug(`[DSO] Intent: '${intent}'. Kandidat teratas: ${candidates[0].providerName}:${candidates[0].model} (Skor: ${candidates[0].qlcScore.toFixed(3)})`); return candidates[0]; } async generateText(payload) { const { messages, userId, platform, intent = 'default', showUserError = false, devErrorHandler = Logger.error } = payload; const fallbackPath = []; if (this.#isSleeping) { const remainingTime = Math.ceil((this.#sleepUntil - Date.now()) / (1000 * 60)); if (Date.now() < this.#sleepUntil) { const message = `AI sedang beristirahat untuk memulihkan diri. Coba lagi dalam ${remainingTime} menit.`; Logger.warn(`[DSO] Permintaan ditolak: ${message}`); devErrorHandler(`[DSO] ${message}`, new Error(message)); return { response: null, error: new Error(message), success: false, fallbackPath, providerUsed: 'DSO', modelUsed: 'SleepMode' }; } else { Logger.info('[DSO] AI bangun dari tidur. Mereset state.'); this.#isSleeping = false; this.#sleepUntil = null; this.#apiKeys.forEach(manager => manager.resetAllKeyStatuses()); } } let currentAttempts = 0; const maxAttemptsPerRequest = this.#nexusConfig.dsoConfig?.maxAttemptsPerRequest || 5; while (currentAttempts < maxAttemptsPerRequest) { const candidate = this.#selectOptimalCandidate(intent); if (!candidate) { const message = 'Tidak ada kandidat AI yang sehat tersedia. Memasuki mode tidur.'; Logger.error(`[DSO] ${message}`); this.#isSleeping = true; this.#sleepUntil = Date.now() + (this.#nexusConfig.dsoConfig?.sleepDurationMs || this.#defaultSleepDurationMs); devErrorHandler(`[DSO] ${message}`, new Error(message)); return { response: null, error: new Error(message), success: false, fallbackPath, providerUsed: 'DSO', modelUsed: 'NoCandidate' }; } const { providerName, model, apiKey } = candidate; fallbackPath.push(`${providerName}:${model}`); const adapter = this.#providerBridge.establishPathway(providerName, apiKey, model); if (!adapter) { Logger.error(`[DSO] Gagal mendapatkan adapter untuk ${providerName}.`); currentAttempts++; this.#apiKeys.get(providerName)?.reportStatus(apiKey, 'OTHER'); continue; } const startTime = Date.now(); try { Logger.debug(`[DSO] Mencoba kandidat: ${providerName}:${model} (Upaya ${currentAttempts + 1}/${maxAttemptsPerRequest})`); const response = await adapter.process({ messages: messages, stream: false }); const latency = Date.now() - startTime; this.#performanceTracker.log(providerName, model, apiKey, latency, true); Logger.info(`[DSO] Berhasil dari ${providerName}:${model} dalam ${latency}ms.`); const transactions = [{ attempt_sequence: currentAttempts, provider: providerName, model: model, outcome: { status: 'SUCCESS', latencyMs: latency, failureReason: null } }]; await this.#aiNexus.getNavigator().processInteraction({ id: payload.id, timestamp: payload.timestamp || new Date(), userId: userId, platform: platform, promptText: messages[messages.length - 1].content, cognitiveSnapshot: { intent: intent, policyUsed: this.#policies[intent] ? intent : 'default', topCandidateQlcScore: candidate.qlcScore, fallbackPath: fallbackPath }, transactions: transactions, finalOutcome: { success: true, response: response.content, error: null }, promptMetadata: payload.promptMetadata || null }); return { response: response.content, providerUsed: providerName, modelUsed: model, latencyMs: latency, success: true, fallbackPath, qlcScore: candidate.qlcScore, rawResponse: response }; } catch (error) { const latency = Date.now() - startTime; Logger.warn(`[DSO] Gagal dari ${providerName}:${model}: ${error.message}.`); this.#performanceTracker.log(providerName, model, apiKey, latency, false, error.message); this.#apiKeys.get(providerName)?.reportStatus(apiKey, error.message); currentAttempts++; const transactions = [{ attempt_sequence: currentAttempts -1, provider: providerName, model: model, outcome: { status: 'FAILURE', latencyMs: latency, failureReason: error.message } }]; if (currentAttempts >= maxAttemptsPerRequest) { await this.#aiNexus.getNavigator().processInteraction({ id: payload.id, timestamp: payload.timestamp || new Date(), userId: userId, platform: platform, promptText: messages[messages.length - 1].content, cognitiveSnapshot: { intent: intent, policyUsed: this.#policies[intent] ? intent : 'default', topCandidateQlcScore: candidate.qlcScore, fallbackPath: fallbackPath }, transactions: transactions, finalOutcome: { success: false, response: null, error: error.message }, promptMetadata: payload.promptMetadata || null }); } } } const finalMessage = 'Semua upaya pada kandidat optimal gagal. AI akan tidur.'; Logger.error(`[DSO] ${finalMessage}`); this.#isSleeping = true; this.#sleepUntil = Date.now() + (this.#nexusConfig.dsoConfig?.sleepDurationMs || this.#defaultSleepDurationMs); devErrorHandler(`[DSO] ${finalMessage}`, new Error(finalMessage)); return { response: null, error: new Error(finalMessage), success: false, fallbackPath, providerUsed: 'DSO', modelUsed: 'FailedAllAttempts' }; } isSleeping() { return this.#isSleeping; } getOverallPerformanceMetrics() { return this.#performanceTracker.getOverallMetrics(); } getAPIKeyManagers() { return this.#apiKeys; } async applyIdeonDecayAndManageCuriosity() { const memory = this.#aiNexus.getMemory(); if (memory && typeof memory.applyIdeonDecay === 'function') { await memory.applyIdeonDecay(); const lowConfidenceTopics = memory.findLowConfidenceConcepts(this.#nexusConfig.navigatorConfig?.ideonConfidenceThreshold || 0.4); if (lowConfidenceTopics.length > 0) { Logger.debug(`[DSO] Setelah peluruhan, ditemukan ${lowConfidenceTopics.length} topik kepercayaan rendah. Siap memicu rasa ingin tahu.`); } } } shutdown() { this.#performanceTracker.shutdown(); clearInterval(this.#heartbeatInterval); // Bersihkan interval yang dibuat DSO Logger.info('[DSO] Adaptive Policy Engine dimatikan.'); } }