Files
zhuiguang-ai/scripts/seed-persona-variants.mjs

118 lines
3.7 KiB
JavaScript

// 给所有 bot 初始化 A/B 测试变体
// 用法:node scripts/seed-persona-variants.mjs [--bot=<key>]
// - 默认跑所有 bot
// - --bot=laochen 只为老陈创建/更新变体
import { PrismaClient } from "@prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import { readFileSync } from "fs";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";
import "dotenv/config";
import {
ensureBotVariants,
ensureExperiment,
disconnectBotExperiment,
} from "./lib/bot-persona-experiment.mjs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const base = process.env.DATABASE_URL.replace("mysql://", "mariadb://");
const sep = base.includes("?") ? "&" : "?";
const connectionString = `${base}${sep}connection_limit=2&pool_timeout=10`;
const adapter = new PrismaMariaDb(connectionString);
const prisma = new PrismaClient({ adapter });
const BOT_DATA_PATH = resolve(__dirname, "..", "data", "bot-characters.json");
function ts() {
return `[${new Date().toISOString()}]`;
}
function parseArgs() {
const args = process.argv.slice(2);
const out = { bot: null };
for (const a of args) {
if (a.startsWith("--bot=")) out.bot = a.split("=")[1];
}
return out;
}
async function main() {
const args = parseArgs();
console.log(`${ts()} Seed persona variants starting${args.bot ? ` (bot=${args.bot})` : ""}...`);
const { characters } = JSON.parse(readFileSync(BOT_DATA_PATH, "utf-8"));
let botChars = characters.filter((c) => !c.role || c.role !== "passerby");
if (args.bot) {
botChars = botChars.filter((c) => c.key === args.bot);
if (botChars.length === 0) {
console.error(`${ts()} Bot "${args.bot}" not found in bot-characters.json`);
process.exit(1);
}
}
let variantCreated = 0;
let experimentCreated = 0;
for (const c of botChars) {
const botUser = await prisma.user.findFirst({ where: { email: `bot_${c.key}@zhuiguang.ai` } });
if (!botUser) {
console.warn(`${ts()} bot user not found for key=${c.key}, skipping.`);
continue;
}
const botConfig = await prisma.botConfig.findUnique({ where: { userId: botUser.id } });
if (!botConfig) {
console.warn(`${ts()} botConfig not found for key=${c.key}, skipping.`);
continue;
}
const { variants, created } = await ensureBotVariants(botConfig.id, botUser.id);
variantCreated += created;
console.log(`${ts()} ${c.displayName}: variants=${variants.length} (created=${created})`);
const exp = await ensureExperiment(botConfig.id);
if (exp) {
experimentCreated++;
console.log(`${ts()} exp#${exp.id} status=${exp.status}`);
}
}
await prisma.taskLog.create({
data: {
taskKey: "seed-persona-variants",
taskName: "Bot 人设 A/B 变体初始化",
status: "success",
startedAt: new Date(),
finishedAt: new Date(),
triggerBy: "manual",
result: { botCount: botChars.length, variantCreated, experimentCreated },
},
});
console.log(
`${ts()} Done. bots=${botChars.length} variants_created=${variantCreated} experiments=${experimentCreated}`
);
}
main()
.catch(async (e) => {
console.error(`${ts()} Fatal:`, e);
try {
await prisma.taskLog.create({
data: {
taskKey: "seed-persona-variants",
taskName: "Bot 人设 A/B 变体初始化",
status: "failed",
startedAt: new Date(),
finishedAt: new Date(),
triggerBy: "manual",
error: (e && e.message ? e.message : String(e)).slice(0, 1000),
},
});
} catch {}
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
await disconnectBotExperiment();
});