| 329 | } |
| 330 | |
| 331 | async function getAiUsage(teamId, startDate, endDate) { |
| 332 | try { |
| 333 | const whereClause = { team_id: parseInt(teamId, 10) }; |
| 334 | |
| 335 | // Add date filtering if provided |
| 336 | if (startDate || endDate) { |
| 337 | whereClause.createdAt = {}; |
| 338 | if (startDate) whereClause.createdAt[Op.gte] = new Date(startDate); |
| 339 | if (endDate) whereClause.createdAt[Op.lte] = new Date(endDate); |
| 340 | } |
| 341 | |
| 342 | // Get total usage |
| 343 | const totalUsage = await db.AiUsage.findAll({ |
| 344 | where: whereClause, |
| 345 | attributes: [ |
| 346 | [fn("SUM", col("total_tokens")), "total_tokens"], |
| 347 | [fn("SUM", col("prompt_tokens")), "prompt_tokens"], |
| 348 | [fn("SUM", col("completion_tokens")), "completion_tokens"], |
| 349 | [fn("SUM", col("cost_micros")), "total_cost_micros"], |
| 350 | [fn("COUNT", col("id")), "api_calls"], |
| 351 | ], |
| 352 | raw: true, |
| 353 | }); |
| 354 | |
| 355 | const formattedTotalUsage = { |
| 356 | total_tokens: parseInt(totalUsage[0]?.total_tokens, 10) || 0, |
| 357 | prompt_tokens: parseInt(totalUsage[0]?.prompt_tokens, 10) || 0, |
| 358 | completion_tokens: parseInt(totalUsage[0]?.completion_tokens, 10) || 0, |
| 359 | total_cost_micros: parseInt(totalUsage[0]?.total_cost_micros, 10) || 0, |
| 360 | api_calls: parseInt(totalUsage[0]?.api_calls, 10) || 0, |
| 361 | }; |
| 362 | |
| 363 | // Get usage by model |
| 364 | const usageByModel = await db.AiUsage.findAll({ |
| 365 | where: whereClause, |
| 366 | attributes: [ |
| 367 | "model", |
| 368 | [fn("SUM", col("total_tokens")), "total_tokens"], |
| 369 | [fn("COUNT", col("id")), "api_calls"], |
| 370 | ], |
| 371 | group: ["model"], |
| 372 | raw: true, |
| 373 | }); |
| 374 | |
| 375 | const formattedUsageByModel = usageByModel.map((model) => { |
| 376 | return { |
| 377 | model: model.model, |
| 378 | total_tokens: parseInt(model.total_tokens, 10) || 0, |
| 379 | api_calls: parseInt(model.api_calls, 10) || 0, |
| 380 | }; |
| 381 | }); |
| 382 | |
| 383 | return { |
| 384 | total: formattedTotalUsage, |
| 385 | byModel: formattedUsageByModel, |
| 386 | }; |
| 387 | } catch (error) { |
| 388 | throw new Error(error.message); |