1
This commit is contained in:
174
api/services/ai_call_recorder.js
Normal file
174
api/services/ai_call_recorder.js
Normal 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;
|
||||
Reference in New Issue
Block a user