haixunMaster/lib/services/matrix.ts

84 lines
2.5 KiB
TypeScript

import { prisma, resolvePersona } from "@/lib/db";
import { getOrCreateSettings } from "@/lib/user-settings";
import { getActiveAccountProfile } from "@/lib/account-context";
import { generateContentMatrix } from "@/lib/ai/generate-matrix";
import { parseProviderApiKeys } from "@/lib/ai/keys";
import { parseResearchMap } from "@/lib/types/research";
export async function generateMatrixForScan(scanId: string, count?: number) {
const scan = await prisma.scan.findUnique({
where: { id: scanId },
include: {
topic: true,
items: {
where: { OR: [{ qualityTier: null }, { qualityTier: { not: "EXCLUDE" } }] },
orderBy: [{ combinedScore: "desc" }, { score: "desc" }],
take: 24,
include: {
replies: { orderBy: { likeCount: "desc" }, take: 5 },
},
},
},
});
if (!scan) throw new Error("找不到海巡紀錄");
if (scan.items.length === 0) {
throw new Error("此海巡沒有素材,請重新海巡");
}
const settings = await getOrCreateSettings();
const account = await getActiveAccountProfile();
const apiKeys = parseProviderApiKeys(settings.providerApiKeys);
const researchMap = parseResearchMap(scan.topic.researchMap);
const rowCount = count ?? settings.matrixRows ?? 7;
const rows = await generateContentMatrix({
topicLabel: scan.topic.label,
query: scan.topic.query,
brief: scan.topic.brief,
persona: resolvePersona(settings, account),
researchMap,
aiProvider: settings.aiProvider,
aiModel: settings.aiModel,
apiKeys,
count: rowCount,
posts: scan.items.map((item) => ({
text: item.text,
authorName: item.authorName,
permalink: item.permalink,
searchTag: item.searchTag,
likeCount: item.likeCount,
replyCount: item.replyCount,
qualityReason: item.qualityReason,
replies: item.replies.map((r) => ({
text: r.text,
authorName: r.authorName,
likeCount: r.likeCount,
})),
})),
});
const created = [];
for (const row of rows) {
const record = await prisma.draft.create({
data: {
accountId: scan.topic.accountId,
topicId: scan.topicId,
text: row.text,
angle: row.angle,
hook: row.hook,
referenceNotes: row.referenceNotes,
searchTag: row.searchTag,
sortOrder: row.sortOrder,
rationale: row.rationale,
sources: JSON.stringify(row.sourcePermalinks),
status: "PENDING",
},
});
created.push(record);
}
return created;
}