118 lines
3.7 KiB
JavaScript
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();
|
|
});
|