const Framework = require('../../framework/node-core-framework'); /** * AI调用记录服务 * 负责记录所有AI API调用的详细信息 */ class AiCallRecorder { /** * 记录AI调用 * @param {Object} params - 调用参数 * @param {Number} params.user_id - 用户ID * @param {String} params.sn_code - 设备SN码 * @param {String} params.service_type - 服务类型(chat/completion/embedding) * @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 - 状态(success/failed) * @param {String} params.error_message - 错误信息 * @param {Number} params.response_time - 响应时间(毫秒) * @param {String} params.api_provider - API提供商 * @param {String} params.business_type - 业务类型 * @param {String} 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.warn('[AI记录] ai_call_records 模型未加载'); return null; } const now = new Date(); 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 || 'qwen', business_type: params.business_type || null, reference_id: params.reference_id || null, create_time: now, last_modify_time: now, is_delete: 0 }); return record; } catch (error) { console.error('[AI记录] 记录失败:', error.message); throw error; } } /** * 获取用户Token使用统计 * @param {Number} userId - 用户ID * @param {Object} options - 查询选项 * @param {Date} options.startDate - 开始日期 * @param {Date} options.endDate - 结束日期 * @returns {Promise} 统计数据 */ static async getUserTokenStats(userId, options = {}) { try { const models = Framework.getModels(); const { ai_call_records } = models; const { Op } = Framework.getSequelize(); if (!ai_call_records) { return null; } const where = { user_id: userId, is_delete: 0 }; if (options.startDate && options.endDate) { where.create_time = { [Op.between]: [options.startDate, options.endDate] }; } const stats = await ai_call_records.findOne({ where, attributes: [ [Framework.getSequelize().fn('COUNT', Framework.getSequelize().col('id')), 'total_calls'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('prompt_tokens')), 'total_prompt_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('completion_tokens')), 'total_completion_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('total_tokens')), 'total_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('cost_amount')), 'total_cost'], [Framework.getSequelize().fn('AVG', Framework.getSequelize().col('response_time')), 'avg_response_time'] ], raw: true }); return stats; } catch (error) { console.error('[AI记录] 获取用户统计失败:', error.message); throw error; } } /** * 获取设备Token使用统计 * @param {String} snCode - 设备SN码 * @param {Object} options - 查询选项 * @param {Date} options.startDate - 开始日期 * @param {Date} options.endDate - 结束日期 * @returns {Promise} 统计数据 */ static async getDeviceTokenStats(snCode, options = {}) { try { const models = Framework.getModels(); const { ai_call_records } = models; const { Op } = Framework.getSequelize(); if (!ai_call_records) { return null; } const where = { sn_code: snCode, is_delete: 0 }; if (options.startDate && options.endDate) { where.create_time = { [Op.between]: [options.startDate, options.endDate] }; } const stats = await ai_call_records.findOne({ where, attributes: [ [Framework.getSequelize().fn('COUNT', Framework.getSequelize().col('id')), 'total_calls'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('prompt_tokens')), 'total_prompt_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('completion_tokens')), 'total_completion_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('total_tokens')), 'total_tokens'], [Framework.getSequelize().fn('SUM', Framework.getSequelize().col('cost_amount')), 'total_cost'], [Framework.getSequelize().fn('AVG', Framework.getSequelize().col('response_time')), 'avg_response_time'] ], raw: true }); return stats; } catch (error) { console.error('[AI记录] 获取设备统计失败:', error.message); throw error; } } } module.exports = AiCallRecorder;