150 lines
3.4 KiB
JavaScript
150 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('crypto');
|
|
const COS = require('cos-nodejs-sdk-v5');
|
|
const { execSync } = require('child_process');
|
|
|
|
// ─── 常量 ───
|
|
const TRAINING_INTERVAL = 6 * 60 * 60 * 1000; // 6小时
|
|
const MODEL_BUCKET = 'agent-models-1250000000';
|
|
const MODEL_REGION = 'ap-guangzhou';
|
|
|
|
// ─── COS 客户端 ───
|
|
const cos = new COS({
|
|
SecretId: process.env.COS_SECRET_ID,
|
|
SecretKey: process.env.COS_SECRET_KEY
|
|
});
|
|
|
|
// ─── 主权验证 ───
|
|
function validateSovereign(token) {
|
|
const emailAuth = require('./email-auth');
|
|
return emailAuth.validateSession(token).valid;
|
|
}
|
|
|
|
/**
|
|
* Agent训练执行器
|
|
*/
|
|
class AgentTrainer {
|
|
constructor(agentId) {
|
|
this.agentId = agentId;
|
|
this.modelKey = `models/${agentId}/${Date.now()}.model`;
|
|
this.training = false;
|
|
}
|
|
|
|
/**
|
|
* 执行训练
|
|
*/
|
|
async train() {
|
|
if (this.training) return;
|
|
this.training = true;
|
|
|
|
try {
|
|
// 1. 准备训练数据
|
|
const data = await this.prepareData();
|
|
|
|
// 2. 执行训练脚本
|
|
const modelBuffer = this.runTrainingScript(data);
|
|
|
|
// 3. 上传模型
|
|
await this.uploadModel(modelBuffer);
|
|
|
|
// 4. 更新联邦状态
|
|
await this.updateFederationStatus();
|
|
|
|
return { success: true, modelKey: this.modelKey };
|
|
} catch (err) {
|
|
console.error(`[Agent Training] ${this.agentId} 训练失败:`, err);
|
|
return { error: true, message: err.message };
|
|
} finally {
|
|
this.training = false;
|
|
}
|
|
}
|
|
|
|
async prepareData() {
|
|
// 从COS获取历史数据
|
|
const { Body } = await cos.getObject({
|
|
Bucket: MODEL_BUCKET,
|
|
Region: MODEL_REGION,
|
|
Key: `data/${this.agentId}/latest.json`
|
|
});
|
|
return JSON.parse(Body.toString());
|
|
}
|
|
|
|
runTrainingScript(data) {
|
|
const scriptPath = require.resolve('./training-script');
|
|
return execSync(`node ${scriptPath}`, {
|
|
input: JSON.stringify(data),
|
|
stdio: ['pipe', 'pipe', 'inherit']
|
|
});
|
|
}
|
|
|
|
async uploadModel(buffer) {
|
|
await cos.putObject({
|
|
Bucket: MODEL_BUCKET,
|
|
Region: MODEL_REGION,
|
|
Key: this.modelKey,
|
|
Body: buffer
|
|
});
|
|
}
|
|
|
|
async updateFederationStatus() {
|
|
const handshake = require('./agent-handshake');
|
|
await handshake.updateModelVersion(this.agentId, this.modelKey);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 定时训练调度器
|
|
*/
|
|
class TrainingScheduler {
|
|
constructor() {
|
|
this.timers = new Map();
|
|
}
|
|
|
|
schedule(agentId) {
|
|
if (this.timers.has(agentId)) return;
|
|
|
|
const trainer = new AgentTrainer(agentId);
|
|
const timer = setInterval(() => trainer.train(), TRAINING_INTERVAL);
|
|
|
|
// 立即执行首次训练
|
|
trainer.train();
|
|
|
|
this.timers.set(agentId, timer);
|
|
}
|
|
|
|
unschedule(agentId) {
|
|
const timer = this.timers.get(agentId);
|
|
if (timer) {
|
|
clearInterval(timer);
|
|
this.timers.delete(agentId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 全局调度器实例
|
|
const scheduler = new TrainingScheduler();
|
|
|
|
module.exports = {
|
|
/**
|
|
* 启动Agent训练计划
|
|
*/
|
|
startTraining(agentId, token) {
|
|
if (!validateSovereign(token)) {
|
|
throw new Error('无权限: 仅限主权者启动训练');
|
|
}
|
|
scheduler.schedule(agentId);
|
|
return { success: true };
|
|
},
|
|
|
|
/**
|
|
* 停止Agent训练
|
|
*/
|
|
stopTraining(agentId, token) {
|
|
if (!validateSovereign(token)) {
|
|
throw new Error('无权限: 仅限主权者停止训练');
|
|
}
|
|
scheduler.unschedule(agentId);
|
|
return { success: true };
|
|
}
|
|
}; |