001project_wildgrowth/backend/scripts/stats-models-100.js

99 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

2026-02-11 15:26:03 +08:00
#!/usr/bin/env node
/**
* 拉取最近 100 条已完成课程按模型对比生成时间字数
* 用法node scripts/stats-models-100.js
*/
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
function countOutlineChars(outline) {
if (!outline || !outline.chapters || !Array.isArray(outline.chapters)) return 0;
let total = 0;
for (const ch of outline.chapters) {
if (ch.nodes && Array.isArray(ch.nodes)) {
for (const node of ch.nodes) {
const s = node.suggestedContent;
if (s && typeof s === 'string') total += s.length;
}
}
}
return total;
}
function modelLabel(modelId) {
if (!modelId) return '未知';
if (modelId.includes('lite')) return 'lite';
if (modelId.includes('flash')) return 'flash';
return modelId;
}
async function main() {
const tasks = await prisma.courseGenerationTask.findMany({
where: { status: 'completed' },
orderBy: { createdAt: 'desc' },
take: 100,
include: { course: { select: { id: true, title: true } } },
});
if (tasks.length === 0) {
console.log('没有已完成的课程');
return;
}
const rows = tasks.map((t) => {
const durationSec = t.updatedAt && t.createdAt
? Math.round((new Date(t.updatedAt) - new Date(t.createdAt)) / 1000)
: null;
const chars = countOutlineChars(t.outline);
return {
courseId: t.courseId,
title: (t.course?.title || '课程创建中').slice(0, 28),
modelId: t.modelId || null,
model: modelLabel(t.modelId),
createdAt: t.createdAt.toISOString().replace('T', ' ').slice(0, 19),
durationSec,
chars,
};
});
const byModel = {};
for (const r of rows) {
const k = r.model;
if (!byModel[k]) byModel[k] = { count: 0, totalDuration: 0, totalChars: 0, durations: [], chars: [] };
byModel[k].count++;
if (r.durationSec != null) {
byModel[k].totalDuration += r.durationSec;
byModel[k].durations.push(r.durationSec);
}
byModel[k].totalChars += r.chars;
byModel[k].chars.push(r.chars);
}
console.log('=== 最近 100 条已完成课程:按模型对比 ===\n');
console.log('--- 按模型汇总 ---');
console.log('模型\t\t条数\t平均生成时间(秒)\t总字数\t平均字数');
for (const [model, s] of Object.entries(byModel)) {
const avgDur = s.count > 0 && s.totalDuration > 0 ? Math.round(s.totalDuration / s.count) : '-';
const avgChars = s.count > 0 ? Math.round(s.totalChars / s.count) : 0;
console.log(`${model}\t\t${s.count}\t${avgDur}\t\t\t${s.totalChars}\t${avgChars}`);
}
console.log('\n--- 明细表(最近 100 条:课程标题、模型、创建时间、生成时间(秒)、字数)---');
console.log('序号\t课程标题\t\t\t模型\t创建时间\t\t生成(秒)\t字数');
rows.forEach((r, i) => {
const title = (r.title + '\t').slice(0, 20);
const model = (r.model || '未知').padEnd(6);
const dur = r.durationSec != null ? String(r.durationSec) : '-';
console.log(`${i + 1}\t${title}\t${model}\t${r.createdAt}\t${dur}\t\t${r.chars}`);
});
}
main()
.then(() => process.exit(0))
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());