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

99 lines
3.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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());