134 lines
3.6 KiB
JavaScript
134 lines
3.6 KiB
JavaScript
|
|
// exe-engine/src/adapters/base-adapter.js
|
|||
|
|
// EXE-Engine · 模型适配器基类
|
|||
|
|
// 统一抽象 EXEModelAdapter 接口
|
|||
|
|
// PRJ-EXE-001 · Phase 0
|
|||
|
|
// 版权:国作登字-2026-A-00037559
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* EXEModelAdapter 基类
|
|||
|
|
*
|
|||
|
|
* 所有模型适配器(DeepSeek、Qwen 等)均继承此基类,
|
|||
|
|
* 统一暴露 execute() 和 healthCheck() 接口。
|
|||
|
|
*
|
|||
|
|
* 本体论锚定:适配器 = 墨水瓶的接口。
|
|||
|
|
* 不同品牌的墨水瓶,瓶口规格不同,但笔尖只认一种接口。
|
|||
|
|
*/
|
|||
|
|
class BaseAdapter {
|
|||
|
|
/**
|
|||
|
|
* @param {object} config
|
|||
|
|
* @param {string} config.name 模型标识
|
|||
|
|
* @param {string} config.provider 供应商标识
|
|||
|
|
* @param {string} config.endpoint API 端点
|
|||
|
|
* @param {string} config.apiKey API 密钥
|
|||
|
|
* @param {string[]} config.capabilities 能力标签
|
|||
|
|
* @param {object} config.costPerToken 成本 { input, output, currency, unit }
|
|||
|
|
* @param {number} config.maxContext 最大上下文窗口
|
|||
|
|
* @param {number} config.defaultTemperature 默认温度
|
|||
|
|
* @param {number} config.defaultMaxTokens 默认最大 token
|
|||
|
|
*/
|
|||
|
|
constructor(config) {
|
|||
|
|
if (new.target === BaseAdapter) {
|
|||
|
|
throw new Error('BaseAdapter 不可直接实例化,请使用具体子类');
|
|||
|
|
}
|
|||
|
|
this.name = config.name;
|
|||
|
|
this.provider = config.provider;
|
|||
|
|
this.endpoint = config.endpoint;
|
|||
|
|
this.apiKey = config.apiKey;
|
|||
|
|
this.capabilities = config.capabilities || [];
|
|||
|
|
this.costPerToken = config.costPerToken || { input: 0, output: 0 };
|
|||
|
|
this.maxContext = config.maxContext || 32000;
|
|||
|
|
this.defaultTemperature = config.defaultTemperature || 0.7;
|
|||
|
|
this.defaultMaxTokens = config.defaultMaxTokens || 4096;
|
|||
|
|
|
|||
|
|
// 运行时状态
|
|||
|
|
this._healthy = true;
|
|||
|
|
this._lastHealthCheck = null;
|
|||
|
|
this._failureCount = 0;
|
|||
|
|
this._cooldownUntil = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 执行推理请求(子类必须实现)
|
|||
|
|
* @param {object} request EXE 标准请求
|
|||
|
|
* @returns {Promise<object>} EXE 标准响应
|
|||
|
|
*/
|
|||
|
|
async execute(request) {
|
|||
|
|
throw new Error('子类必须实现 execute() 方法');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 健康检查(子类可覆写)
|
|||
|
|
* @returns {Promise<boolean>}
|
|||
|
|
*/
|
|||
|
|
async healthCheck() {
|
|||
|
|
this._lastHealthCheck = new Date().toISOString();
|
|||
|
|
return this._healthy;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检测该适配器是否支持指定能力
|
|||
|
|
* @param {string} capability
|
|||
|
|
* @returns {boolean}
|
|||
|
|
*/
|
|||
|
|
supports(capability) {
|
|||
|
|
return this.capabilities.includes(capability);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 记录失败并判断是否进入冷却期
|
|||
|
|
* @param {string} reason
|
|||
|
|
*/
|
|||
|
|
recordFailure(reason) {
|
|||
|
|
this._failureCount++;
|
|||
|
|
if (this._failureCount >= 3) {
|
|||
|
|
// 连续 3 次失败,冷却 5 分钟
|
|||
|
|
this._cooldownUntil = Date.now() + 5 * 60 * 1000;
|
|||
|
|
this._healthy = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 重置失败计数
|
|||
|
|
*/
|
|||
|
|
resetFailures() {
|
|||
|
|
this._failureCount = 0;
|
|||
|
|
this._cooldownUntil = null;
|
|||
|
|
this._healthy = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 是否处于冷却期
|
|||
|
|
* @returns {boolean}
|
|||
|
|
*/
|
|||
|
|
isInCooldown() {
|
|||
|
|
if (!this._cooldownUntil) return false;
|
|||
|
|
if (Date.now() >= this._cooldownUntil) {
|
|||
|
|
this.resetFailures();
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取适配器状态摘要
|
|||
|
|
* @returns {object}
|
|||
|
|
*/
|
|||
|
|
getStatus() {
|
|||
|
|
return {
|
|||
|
|
name: this.name,
|
|||
|
|
provider: this.provider,
|
|||
|
|
healthy: this._healthy,
|
|||
|
|
inCooldown: this.isInCooldown(),
|
|||
|
|
failureCount: this._failureCount,
|
|||
|
|
lastHealthCheck: this._lastHealthCheck,
|
|||
|
|
capabilities: this.capabilities,
|
|||
|
|
costPerToken: this.costPerToken,
|
|||
|
|
maxContext: this.maxContext
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = BaseAdapter;
|