This commit is contained in:
张成
2025-12-27 20:14:40 +08:00
parent 43382668a3
commit 43f7884e52
14 changed files with 1818 additions and 21 deletions

View File

@@ -0,0 +1,174 @@
/**
* AI调用记录工具类
* 用于记录每次AI API调用的详细信息
*/
const Framework = require("../../framework/node-core-framework.js");
class AiCallRecorder {
/**
* 记录AI调用
* @param {Object} params - 调用参数
* @param {Number} params.user_id - 用户ID
* @param {String} params.sn_code - 设备序列号
* @param {String} params.service_type - 服务类型
* @param {String} params.model_name - 模型名称
* @param {Number} params.prompt_tokens - 输入token数
* @param {Number} params.completion_tokens - 输出token数
* @param {Number} params.total_tokens - 总token数
* @param {String} params.request_content - 请求内容
* @param {String} params.response_content - 响应内容
* @param {Number} params.cost_amount - 费用
* @param {String} params.status - 状态
* @param {String} params.error_message - 错误信息
* @param {Number} params.response_time - 响应时间(毫秒)
* @param {String} params.api_provider - API提供商
* @param {String} params.business_type - 业务类型
* @param {Number} params.reference_id - 关联业务ID
* @returns {Promise<Object>} 记录结果
*/
static async record(params) {
try {
const models = Framework.getModels();
const { ai_call_records } = models;
if (!ai_call_records) {
console.error('AI调用记录模型未找到');
return null;
}
const record = await ai_call_records.create({
user_id: params.user_id || null,
sn_code: params.sn_code || null,
service_type: params.service_type || '',
model_name: params.model_name || '',
prompt_tokens: params.prompt_tokens || 0,
completion_tokens: params.completion_tokens || 0,
total_tokens: params.total_tokens || 0,
request_content: params.request_content || null,
response_content: params.response_content || null,
cost_amount: params.cost_amount || null,
status: params.status || 'success',
error_message: params.error_message || null,
response_time: params.response_time || null,
api_provider: params.api_provider || 'openai',
business_type: params.business_type || null,
reference_id: params.reference_id || null,
is_delete: 0,
create_time: new Date()
});
console.log(`AI调用已记录 - ID: ${record.id}, Model: ${params.model_name}, Tokens: ${params.total_tokens}`);
return record;
} catch (error) {
console.error('记录AI调用失败:', error);
return null;
}
}
/**
* 统计用户Token使用量
* @param {Number} user_id - 用户ID
* @param {String} startDate - 开始日期 (可选)
* @param {String} endDate - 结束日期 (可选)
* @returns {Promise<Object>} 统计结果
*/
static async getUserTokenStats(user_id, startDate = null, endDate = null) {
try {
const models = Framework.getModels();
const { ai_call_records, op } = models;
const where = {
user_id,
is_delete: 0,
status: 'success'
};
if (startDate && endDate) {
where.create_time = {
[op.between]: [new Date(startDate), new Date(endDate)]
};
} else if (startDate) {
where.create_time = {
[op.gte]: new Date(startDate)
};
} else if (endDate) {
where.create_time = {
[op.lte]: new Date(endDate)
};
}
const records = await ai_call_records.findAll({ where });
const stats = {
total_calls: records.length,
total_prompt_tokens: 0,
total_completion_tokens: 0,
total_tokens: 0,
total_cost: 0
};
records.forEach(record => {
stats.total_prompt_tokens += record.prompt_tokens || 0;
stats.total_completion_tokens += record.completion_tokens || 0;
stats.total_tokens += record.total_tokens || 0;
stats.total_cost += parseFloat(record.cost_amount || 0);
});
return stats;
} catch (error) {
console.error('统计Token使用量失败:', error);
return null;
}
}
/**
* 统计设备Token使用量
* @param {String} sn_code - 设备序列号
* @param {String} startDate - 开始日期 (可选)
* @param {String} endDate - 结束日期 (可选)
* @returns {Promise<Object>} 统计结果
*/
static async getDeviceTokenStats(sn_code, startDate = null, endDate = null) {
try {
const models = Framework.getModels();
const { ai_call_records, op } = models;
const where = {
sn_code,
is_delete: 0,
status: 'success'
};
if (startDate && endDate) {
where.create_time = {
[op.between]: [new Date(startDate), new Date(endDate)]
};
}
const records = await ai_call_records.findAll({ where });
const stats = {
total_calls: records.length,
total_prompt_tokens: 0,
total_completion_tokens: 0,
total_tokens: 0,
total_cost: 0
};
records.forEach(record => {
stats.total_prompt_tokens += record.prompt_tokens || 0;
stats.total_completion_tokens += record.completion_tokens || 0;
stats.total_tokens += record.total_tokens || 0;
stats.total_cost += parseFloat(record.cost_amount || 0);
});
return stats;
} catch (error) {
console.error('统计设备Token使用量失败:', error);
return null;
}
}
}
module.exports = AiCallRecorder;