/** * 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} 记录结果 */ 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} 统计结果 */ 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} 统计结果 */ 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;