This commit is contained in:
小帅 2026-03-31 16:23:01 +08:00
commit 57ca496e97
8 changed files with 155 additions and 294 deletions

View File

@ -138,6 +138,7 @@ function createSubAgent(parentCtx: AgentContext) {
"你必须使用如下XML格式写入工作区\n```", "你必须使用如下XML格式写入工作区\n```",
"拍摄计划:<scriptPlan>内容</scriptPlan>", "拍摄计划:<scriptPlan>内容</scriptPlan>",
"分镜表:<storyboardTable>内容</storyboardTable>", "分镜表:<storyboardTable>内容</storyboardTable>",
"分镜面板:<storyboard> <items prompt=提示词内容 group=分组 duration=视频推荐时间 associateAssetsIds=[资产ID列表] /></storyboard>",
"```", "```",
].join("\n"); ].join("\n");
// "剧本:<script>内容</script>", // "剧本:<script>内容</script>",
@ -190,7 +191,7 @@ async function createArtSkills(artName: string) {
} }
const res = { const res = {
prompt: buildSkillPrompt(mainSkills), prompt: buildSkillPrompt(mainSkills),
tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] },workerPath), tools: createSkillTools(mainSkills, { mainSkill: mainSkills, secondarySkills: [], tertiarySkills: [] }, workerPath),
}; };
return res return res;
} }

View File

@ -175,7 +175,7 @@ export default (toolCpnfig: ToolConfig) => {
generate_storyboard: tool({ generate_storyboard: tool({
description: "生成分镜图片", description: "生成分镜图片",
inputSchema: z.object({ inputSchema: z.object({
ids: z.array(z.number()).describe("分镜面板中需要更新的分镜 ID 列表,传入id仅作对应分镜更新用不传入则全部生成"), ids: z.array(z.number()).describe("必须获取真实的分镜ID支持批量生成"),
}), }),
execute: async ({ ids }) => { execute: async ({ ids }) => {
console.log("%c Line:176 🍒 ids", "background:#ea7e5c", ids); console.log("%c Line:176 🍒 ids", "background:#ea7e5c", ids);

View File

@ -1,4 +1,4 @@
// @routes-hash 01a3e214a845cf74065af521bc0794cc // @routes-hash 8b0a09b55cd1b98ff83ad988d077fee3
import { Express } from "express"; import { Express } from "express";
import route1 from "./routes/agents/clearMemory"; import route1 from "./routes/agents/clearMemory";
@ -65,65 +65,64 @@ import route61 from "./routes/production/storyboard/getStoryboardData";
import route62 from "./routes/production/storyboard/pollingImage"; import route62 from "./routes/production/storyboard/pollingImage";
import route63 from "./routes/production/storyboard/previewImage"; import route63 from "./routes/production/storyboard/previewImage";
import route64 from "./routes/production/storyboard/removeFrame"; import route64 from "./routes/production/storyboard/removeFrame";
import route65 from "./routes/production/storyboard/updateStoryboardInfo"; import route65 from "./routes/production/workbench/confirmSelection";
import route66 from "./routes/production/workbench/confirmSelection"; import route66 from "./routes/production/workbench/delVideo";
import route67 from "./routes/production/workbench/delVideo"; import route67 from "./routes/production/workbench/generateVideo";
import route68 from "./routes/production/workbench/generateVideo"; import route68 from "./routes/production/workbench/generateVideoPrompt";
import route69 from "./routes/production/workbench/generateVideoPrompt"; import route69 from "./routes/production/workbench/getChatLines";
import route70 from "./routes/production/workbench/getChatLines"; import route70 from "./routes/production/workbench/getVideoModelDetail";
import route71 from "./routes/production/workbench/getVideoModelDetail"; import route71 from "./routes/production/workbench/videoPolling";
import route72 from "./routes/production/workbench/videoPolling"; import route72 from "./routes/project/addProject";
import route73 from "./routes/project/addProject"; import route73 from "./routes/project/addVisual";
import route74 from "./routes/project/addVisual"; import route74 from "./routes/project/addVisualManual";
import route75 from "./routes/project/addVisualManual"; import route75 from "./routes/project/deleteVisualManual";
import route76 from "./routes/project/deleteVisualManual"; import route76 from "./routes/project/delProject";
import route77 from "./routes/project/delProject"; import route77 from "./routes/project/editProject";
import route78 from "./routes/project/editProject"; import route78 from "./routes/project/editVisualManual";
import route79 from "./routes/project/editVisualManual"; import route79 from "./routes/project/getProject";
import route80 from "./routes/project/getProject"; import route80 from "./routes/project/getVisualManual";
import route81 from "./routes/project/getVisualManual"; import route81 from "./routes/project/visualManual";
import route82 from "./routes/project/visualManual"; import route82 from "./routes/script/addScript";
import route83 from "./routes/script/addScript"; import route83 from "./routes/script/delScript";
import route84 from "./routes/script/delScript"; import route84 from "./routes/script/exportScript";
import route85 from "./routes/script/exportScript"; import route85 from "./routes/script/extractAssets";
import route86 from "./routes/script/extractAssets"; import route86 from "./routes/script/getScrptApi";
import route87 from "./routes/script/getScrptApi"; import route87 from "./routes/script/pollScriptAssets";
import route88 from "./routes/script/pollScriptAssets"; import route88 from "./routes/script/updateScript";
import route89 from "./routes/script/updateScript"; import route89 from "./routes/scriptAgent/getPlanData";
import route90 from "./routes/scriptAgent/getPlanData"; import route90 from "./routes/scriptAgent/setPlanData";
import route91 from "./routes/scriptAgent/setPlanData"; import route91 from "./routes/scriptAgent/updateData";
import route92 from "./routes/scriptAgent/updateData"; import route92 from "./routes/setting/about/checkUpdate";
import route93 from "./routes/setting/about/checkUpdate"; import route93 from "./routes/setting/about/downloadApp";
import route94 from "./routes/setting/about/downloadApp"; import route94 from "./routes/setting/agentDeploy/agentSetKey";
import route95 from "./routes/setting/agentDeploy/agentSetKey"; import route95 from "./routes/setting/agentDeploy/deployAgentModel";
import route96 from "./routes/setting/agentDeploy/deployAgentModel"; import route96 from "./routes/setting/agentDeploy/getAgentDeploy";
import route97 from "./routes/setting/agentDeploy/getAgentDeploy"; import route97 from "./routes/setting/dbConfig/clearData";
import route98 from "./routes/setting/dbConfig/clearData"; import route98 from "./routes/setting/dev/getSwitchAiDevTool";
import route99 from "./routes/setting/dev/getSwitchAiDevTool"; import route99 from "./routes/setting/dev/updateSwitchAiDevTool";
import route100 from "./routes/setting/dev/updateSwitchAiDevTool"; import route100 from "./routes/setting/fileManagement/openFolder";
import route101 from "./routes/setting/fileManagement/openFolder"; import route101 from "./routes/setting/getTextModel";
import route102 from "./routes/setting/getTextModel"; import route102 from "./routes/setting/loginConfig/getUser";
import route103 from "./routes/setting/loginConfig/getUser"; import route103 from "./routes/setting/loginConfig/updateUserPwd";
import route104 from "./routes/setting/loginConfig/updateUserPwd"; import route104 from "./routes/setting/memoryConfig/delAllMemory";
import route105 from "./routes/setting/memoryConfig/delAllMemory"; import route105 from "./routes/setting/memoryConfig/getMemory";
import route106 from "./routes/setting/memoryConfig/getMemory"; import route106 from "./routes/setting/memoryConfig/sureMemory";
import route107 from "./routes/setting/memoryConfig/sureMemory"; import route107 from "./routes/setting/promptManage/getPrompt";
import route108 from "./routes/setting/promptManage/getPrompt"; import route108 from "./routes/setting/promptManage/updatePrompt";
import route109 from "./routes/setting/promptManage/updatePrompt"; import route109 from "./routes/setting/skillManagement/getSkillContent";
import route110 from "./routes/setting/skillManagement/getSkillContent"; import route110 from "./routes/setting/skillManagement/getSkillList";
import route111 from "./routes/setting/skillManagement/getSkillList"; import route111 from "./routes/setting/skillManagement/saveSkillContent";
import route112 from "./routes/setting/skillManagement/saveSkillContent"; import route112 from "./routes/setting/vendorConfig/addVendor";
import route113 from "./routes/setting/vendorConfig/addVendor"; import route113 from "./routes/setting/vendorConfig/deleteVendor";
import route114 from "./routes/setting/vendorConfig/deleteVendor"; import route114 from "./routes/setting/vendorConfig/getVendorList";
import route115 from "./routes/setting/vendorConfig/getVendorList"; import route115 from "./routes/setting/vendorConfig/modelTest";
import route116 from "./routes/setting/vendorConfig/modelTest"; import route116 from "./routes/setting/vendorConfig/updateCode";
import route117 from "./routes/setting/vendorConfig/updateCode"; import route117 from "./routes/setting/vendorConfig/updateVendor";
import route118 from "./routes/setting/vendorConfig/updateVendor"; import route118 from "./routes/task/getProject";
import route119 from "./routes/task/getProject"; import route119 from "./routes/task/getTaskApi";
import route120 from "./routes/task/getTaskApi"; import route120 from "./routes/task/getTaskCategories";
import route121 from "./routes/task/getTaskCategories"; import route121 from "./routes/task/taskDetails";
import route122 from "./routes/task/taskDetails"; import route122 from "./routes/test/test";
import route123 from "./routes/test/test";
export default async (app: Express) => { export default async (app: Express) => {
app.use("/api/agents/clearMemory", route1); app.use("/api/agents/clearMemory", route1);
@ -190,63 +189,62 @@ export default async (app: Express) => {
app.use("/api/production/storyboard/pollingImage", route62); app.use("/api/production/storyboard/pollingImage", route62);
app.use("/api/production/storyboard/previewImage", route63); app.use("/api/production/storyboard/previewImage", route63);
app.use("/api/production/storyboard/removeFrame", route64); app.use("/api/production/storyboard/removeFrame", route64);
app.use("/api/production/storyboard/updateStoryboardInfo", route65); app.use("/api/production/workbench/confirmSelection", route65);
app.use("/api/production/workbench/confirmSelection", route66); app.use("/api/production/workbench/delVideo", route66);
app.use("/api/production/workbench/delVideo", route67); app.use("/api/production/workbench/generateVideo", route67);
app.use("/api/production/workbench/generateVideo", route68); app.use("/api/production/workbench/generateVideoPrompt", route68);
app.use("/api/production/workbench/generateVideoPrompt", route69); app.use("/api/production/workbench/getChatLines", route69);
app.use("/api/production/workbench/getChatLines", route70); app.use("/api/production/workbench/getVideoModelDetail", route70);
app.use("/api/production/workbench/getVideoModelDetail", route71); app.use("/api/production/workbench/videoPolling", route71);
app.use("/api/production/workbench/videoPolling", route72); app.use("/api/project/addProject", route72);
app.use("/api/project/addProject", route73); app.use("/api/project/addVisual", route73);
app.use("/api/project/addVisual", route74); app.use("/api/project/addVisualManual", route74);
app.use("/api/project/addVisualManual", route75); app.use("/api/project/deleteVisualManual", route75);
app.use("/api/project/deleteVisualManual", route76); app.use("/api/project/delProject", route76);
app.use("/api/project/delProject", route77); app.use("/api/project/editProject", route77);
app.use("/api/project/editProject", route78); app.use("/api/project/editVisualManual", route78);
app.use("/api/project/editVisualManual", route79); app.use("/api/project/getProject", route79);
app.use("/api/project/getProject", route80); app.use("/api/project/getVisualManual", route80);
app.use("/api/project/getVisualManual", route81); app.use("/api/project/visualManual", route81);
app.use("/api/project/visualManual", route82); app.use("/api/script/addScript", route82);
app.use("/api/script/addScript", route83); app.use("/api/script/delScript", route83);
app.use("/api/script/delScript", route84); app.use("/api/script/exportScript", route84);
app.use("/api/script/exportScript", route85); app.use("/api/script/extractAssets", route85);
app.use("/api/script/extractAssets", route86); app.use("/api/script/getScrptApi", route86);
app.use("/api/script/getScrptApi", route87); app.use("/api/script/pollScriptAssets", route87);
app.use("/api/script/pollScriptAssets", route88); app.use("/api/script/updateScript", route88);
app.use("/api/script/updateScript", route89); app.use("/api/scriptAgent/getPlanData", route89);
app.use("/api/scriptAgent/getPlanData", route90); app.use("/api/scriptAgent/setPlanData", route90);
app.use("/api/scriptAgent/setPlanData", route91); app.use("/api/scriptAgent/updateData", route91);
app.use("/api/scriptAgent/updateData", route92); app.use("/api/setting/about/checkUpdate", route92);
app.use("/api/setting/about/checkUpdate", route93); app.use("/api/setting/about/downloadApp", route93);
app.use("/api/setting/about/downloadApp", route94); app.use("/api/setting/agentDeploy/agentSetKey", route94);
app.use("/api/setting/agentDeploy/agentSetKey", route95); app.use("/api/setting/agentDeploy/deployAgentModel", route95);
app.use("/api/setting/agentDeploy/deployAgentModel", route96); app.use("/api/setting/agentDeploy/getAgentDeploy", route96);
app.use("/api/setting/agentDeploy/getAgentDeploy", route97); app.use("/api/setting/dbConfig/clearData", route97);
app.use("/api/setting/dbConfig/clearData", route98); app.use("/api/setting/dev/getSwitchAiDevTool", route98);
app.use("/api/setting/dev/getSwitchAiDevTool", route99); app.use("/api/setting/dev/updateSwitchAiDevTool", route99);
app.use("/api/setting/dev/updateSwitchAiDevTool", route100); app.use("/api/setting/fileManagement/openFolder", route100);
app.use("/api/setting/fileManagement/openFolder", route101); app.use("/api/setting/getTextModel", route101);
app.use("/api/setting/getTextModel", route102); app.use("/api/setting/loginConfig/getUser", route102);
app.use("/api/setting/loginConfig/getUser", route103); app.use("/api/setting/loginConfig/updateUserPwd", route103);
app.use("/api/setting/loginConfig/updateUserPwd", route104); app.use("/api/setting/memoryConfig/delAllMemory", route104);
app.use("/api/setting/memoryConfig/delAllMemory", route105); app.use("/api/setting/memoryConfig/getMemory", route105);
app.use("/api/setting/memoryConfig/getMemory", route106); app.use("/api/setting/memoryConfig/sureMemory", route106);
app.use("/api/setting/memoryConfig/sureMemory", route107); app.use("/api/setting/promptManage/getPrompt", route107);
app.use("/api/setting/promptManage/getPrompt", route108); app.use("/api/setting/promptManage/updatePrompt", route108);
app.use("/api/setting/promptManage/updatePrompt", route109); app.use("/api/setting/skillManagement/getSkillContent", route109);
app.use("/api/setting/skillManagement/getSkillContent", route110); app.use("/api/setting/skillManagement/getSkillList", route110);
app.use("/api/setting/skillManagement/getSkillList", route111); app.use("/api/setting/skillManagement/saveSkillContent", route111);
app.use("/api/setting/skillManagement/saveSkillContent", route112); app.use("/api/setting/vendorConfig/addVendor", route112);
app.use("/api/setting/vendorConfig/addVendor", route113); app.use("/api/setting/vendorConfig/deleteVendor", route113);
app.use("/api/setting/vendorConfig/deleteVendor", route114); app.use("/api/setting/vendorConfig/getVendorList", route114);
app.use("/api/setting/vendorConfig/getVendorList", route115); app.use("/api/setting/vendorConfig/modelTest", route115);
app.use("/api/setting/vendorConfig/modelTest", route116); app.use("/api/setting/vendorConfig/updateCode", route116);
app.use("/api/setting/vendorConfig/updateCode", route117); app.use("/api/setting/vendorConfig/updateVendor", route117);
app.use("/api/setting/vendorConfig/updateVendor", route118); app.use("/api/task/getProject", route118);
app.use("/api/task/getProject", route119); app.use("/api/task/getTaskApi", route119);
app.use("/api/task/getTaskApi", route120); app.use("/api/task/getTaskCategories", route120);
app.use("/api/task/getTaskCategories", route121); app.use("/api/task/taskDetails", route121);
app.use("/api/task/taskDetails", route122); app.use("/api/test/test", route122);
app.use("/api/test/test", route123);
} }

View File

@ -42,47 +42,27 @@ export default router.post(
const rolePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_character_derivative"); const rolePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_character_derivative");
const toolPrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_prop_derivative"); const toolPrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_prop_derivative");
const scenePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_scene_derivative"); const scenePrompt = u.getArtPrompt(projectSettingData!.artStyle!, "art_scene_derivative");
const promptRecord: Record<string, { prompt: string; label: string; focus: string }> = { const promptRecord: Record<string, { prompt: string }> = {
role: { role: {
prompt: rolePrompt, prompt: rolePrompt,
label: "角色衍生资产",
focus: "注重人物的姿态、表情、服饰细节、体态特征与情绪表达,保持与原始角色设计的一致性(如发型、瞳色、服装风格),同时体现衍生场景下的变化。",
}, },
tool: { tool: {
prompt: toolPrompt, prompt: toolPrompt,
label: "道具衍生资产",
focus:
"注重道具的材质质感、光影效果、结构细节与功能特征,保持与原始道具设计的一致性(如形状、配色、标志性元素),清晰展示道具在不同状态或角度下的视觉表现。",
}, },
scene: { scene: {
prompt: scenePrompt, prompt: scenePrompt,
label: "场景衍生资产",
focus:
"注重场景的空间层次、光影氛围、环境细节与情绪渲染,保持与原始场景设计的一致性(如建筑风格、色调、标志性地标),体现不同时间段或天气条件下的视觉变化。",
}, },
}; };
const imageData = []; const imageData = [];
for (const item of assetsDataArr) { for (const item of assetsDataArr) {
const typeConfig = promptRecord[item.type!] || promptRecord["role"]; const typeConfig = promptRecord[item.type!] || promptRecord["role"];
const hasRefImage = !!imageUrlRecord[item.assetsId!];
const { text } = await u.Ai.Text("universalAi").invoke({ const { text } = await u.Ai.Text("universalAi").invoke({
system: `你是一位专业的 AI 绘画提示词工程师,擅长将资产描述转化为高质量的图片生成提示词。 system: `${typeConfig.prompt}`,
##
${typeConfig.label}Prompt
##
-
- ${typeConfig.focus}
${hasRefImage ? "- 当前资产有参考图作为风格锚点,提示词应侧重描述衍生变化部分,避免重复参考图已有的基础特征" : "- 当前资产无参考图,提示词需要完整描述视觉特征"}
##
${typeConfig.prompt || "(未指定特定美术风格,请根据资产描述选择合适的画面风格)"}`,
messages: [ messages: [
{ {
role: "user", role: "user",
content: `资产名称: ${item.name}\n资产描述: ${item.describe || "无详细描述"}`, content: `资产描述: ${item.describe || "无详细描述"}`,
}, },
], ],
}); });

View File

@ -11,6 +11,11 @@ export default router.post(
data: z.array( data: z.array(
z.object({ z.object({
prompt: z.string(), prompt: z.string(),
duration: z.number(),
group: z.number(),
state: z.string(),
src: z.string().nullable(),
associateAssetsIds: z.array(z.number()),
}), }),
), ),
scriptId: z.number(), scriptId: z.number(),
@ -18,14 +23,25 @@ export default router.post(
async (req, res) => { async (req, res) => {
const { data, scriptId } = req.body; const { data, scriptId } = req.body;
if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" }); if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" });
await u.db("o_storyboard").insert( for (const item of data) {
data.map((i: { prompt: string }) => ({ const [id] = await u.db("o_storyboard").insert({
...i, prompt: item.prompt,
duration: String(item.duration),
group: String(item.group),
state: item.state,
scriptId, scriptId,
createTime: Date.now(), createTime: Date.now(),
state: "未生成", });
})), if (item.associateAssetsIds?.length) {
); await u.db("o_assets2Storyboard").insert(
return res.status(200).send(success()); item.associateAssetsIds.map((assetId: number) => ({
assetId,
storyboardId: id,
})),
);
}
}
const lastStoryboard = await u.db("o_storyboard").where("scriptId", scriptId);
return res.status(200).send(success(lastStoryboard));
}, },
); );

View File

@ -2,7 +2,7 @@ import express from "express";
import u from "@/utils"; import u from "@/utils";
import { z } from "zod"; import { z } from "zod";
import sharp from "sharp"; import sharp from "sharp";
import { success } from "@/lib/responseFormat"; import { error, success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware"; import { validateFields } from "@/middleware/middleware";
import { Output, tool } from "ai"; import { Output, tool } from "ai";
import { urlToBase64 } from "@/utils/vm"; import { urlToBase64 } from "@/utils/vm";
@ -13,115 +13,27 @@ export type AssetData = z.infer<typeof assetItemSchema>;
export default router.post( export default router.post(
"/", "/",
validateFields({ validateFields({
storyboardIds: z.array(z.number()).optional(), storyboardIds: z.array(z.number()),
projectId: z.number(), projectId: z.number(),
scriptId: z.number(), scriptId: z.number(),
script: z.string(),
scriptPlan: z.string(),
storyboardTable: z.string(),
assets: z.array(assetItemSchema),
}), }),
async (req, res) => { async (req, res) => {
const { const {
storyboardIds, storyboardIds,
projectId, projectId,
scriptId, scriptId,
script,
scriptPlan,
storyboardTable,
assets,
}: { }: {
storyboardIds: number[]; storyboardIds: number[];
projectId: number; projectId: number;
scriptId: number; scriptId: number;
script: string;
scriptPlan: string;
storyboardTable: string;
assets: AssetData[];
} = req.body; } = req.body;
if (!storyboardIds || storyboardIds.length === 0) return res.status(400).send(error("storyboardIds不能为空"));
// 当没有 storyboardIds 时,通过 AI 生成新的分镜面板数据 // 当没有 storyboardIds 时,通过 AI 生成新的分镜面板数据
let finalStoryboardIds: number[] = storyboardIds || []; let finalStoryboardIds: number[] = storyboardIds || [];
if (!storyboardIds || storyboardIds.length === 0) {
await u.db("o_storyboard").where("scriptId", scriptId).delete();
const createdIds: number[] = [];
const resultTools = tool({
description: "结果输出工具(必须调用)",
inputSchema: z.object({
items: z.array(
z.object({
title: z.string().describe("分镜名称"),
description: z.string().describe("分镜详细描述"),
relatedAssets: z.array(z.number()).describe("关联衍生资产id数组"),
duration: z.number().describe("用于生成的视频时长(秒)"),
}),
),
}),
execute: async (resData) => {
console.log("%c Line:46 🌰 resData", "background:#93c0a4", resData.items);
for (const item of resData.items) {
const [id] = await u.db("o_storyboard").insert({
title: item.title,
description: item.description,
scriptId: scriptId,
duration: String(item.duration),
});
createdIds.push(id);
if (item.relatedAssets.length === 0) continue;
await u.db("o_assets2Storyboard").insert(item.relatedAssets.map((i) => ({ storyboardId: id, assetId: i })));
console.log("%c Line:68 🍷 createdIds", "background:#33a5ff", createdIds);
}
return true;
},
});
const { text } = await u.Ai.Text("universalAi").invoke({
system: `你是一位专业的动画分镜师。你的任务是根据剧本内容、分镜表、拍摄计划和可用资产,拆分并生成完整的分镜面板数据。
##
1.
2.
3.
4.
5. 2~8
##
- **** resultTools
- items
- title"开场远景""角色对话特写"
- description 50
- relatedAssets ID
- duration`,
messages: [
{
role: "user",
content: `## 剧本
${script}
##
${storyboardTable}
##
${scriptPlan}
##
${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类型: ${t.type} | 资产ID: ${t.assetsId}`).join("\n")).join("\n")}`,
},
],
tools: { resultTools },
});
console.log("%c Line:52 🍢 text", "background:#93c0a4", text);
finalStoryboardIds = createdIds;
}
await u.db("o_storyboard").whereIn("id", finalStoryboardIds).where("scriptId", scriptId).update({ state: "生成中" }); await u.db("o_storyboard").whereIn("id", finalStoryboardIds).where("scriptId", scriptId).update({ state: "生成中" });
console.log("%c Line:98 🍯 finalStoryboardIds", "background:#3f7cff", finalStoryboardIds);
if (finalStoryboardIds.length === 0) {
res.status(200).send(success());
return;
}
const projectSettingData = await u.db("o_project").where("id", projectId).select("imageModel", "imageQuality", "artStyle").first(); const projectSettingData = await u.db("o_project").where("id", projectId).select("imageModel", "imageQuality", "artStyle").first();
const sceneArkPrompt = u.getArtPrompt(projectSettingData?.artStyle || "", "art_storyboard");
const storyboardData = await u.db("o_storyboard").where("scriptId", scriptId).whereIn("id", finalStoryboardIds); const storyboardData = await u.db("o_storyboard").where("scriptId", scriptId).whereIn("id", finalStoryboardIds);
const assetData = await u const assetData = await u
.db("o_assets") .db("o_assets")
@ -139,9 +51,7 @@ ${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类
success( success(
storyboardData.map((i) => ({ storyboardData.map((i) => ({
id: i.id, id: i.id,
title: i.title, prompt: i.prompt,
description: i.description,
prompt: "",
associateAssetsIds: assetRecord[i.id!], associateAssetsIds: assetRecord[i.id!],
src: null, src: null,
state: i.state, state: i.state,
@ -149,30 +59,12 @@ ${assets.map((i) => i.derive.map((t) => `- 衍生资产名称: ${t.name} | 类
), ),
); );
for (const item of storyboardData) { for (const item of storyboardData) {
const { text } = await u.Ai.Text("universalAi").invoke({
system: `你是一位专业的 AI 绘画提示词工程师,擅长将分镜描述转化为高质量的图片生成提示词。
##
Prompt
##
${sceneArkPrompt || "(未指定特定美术风格,请根据分镜内容选择合适的画面风格)"}`,
messages: [
{
role: "user",
content: `分镜标题: ${item.title}\n分镜描述: ${item.description}`,
},
],
});
console.log("%c Line:27 🍫 text", "background:#ffdd4d", text);
const repeloadObj = { const repeloadObj = {
prompt: text, prompt: item.prompt!,
size: projectSettingData?.imageQuality as "1K" | "2K" | "4K", size: projectSettingData?.imageQuality as "1K" | "2K" | "4K",
aspectRatio: "16:9" as `${number}:${number}`, aspectRatio: "16:9" as `${number}:${number}`,
}; };
await u.db("o_storyboard").where("id", item.id).update({ await u.db("o_storyboard").where("id", item.id).update({
prompt: text,
state: "生成中", state: "生成中",
}); });
u.Ai.Image(projectSettingData?.imageModel as `${string}:${string}`) u.Ai.Image(projectSettingData?.imageModel as `${string}:${string}`)

View File

@ -1,22 +0,0 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
import { id } from "zod/locales";
const router = express.Router();
export default router.post(
"/",
validateFields({
id: z.number(),
prompt: z.string(),
}),
async (req, res) => {
const { id, prompt } = req.body;
await u.db("o_storyboard").where({ id }).update({
prompt,
});
res.status(200).send(success({ message: "更新提示词成功" }));
},
);

View File

@ -11,7 +11,6 @@ const router = express.Router();
/** 新资产AI 首次识别到的资产,需要完整信息 */ /** 新资产AI 首次识别到的资产,需要完整信息 */
const NewAssetSchema = z.object({ const NewAssetSchema = z.object({
prompt: z.string().describe("生成提示词"),
name: z.string().describe("资产名称,仅为名称不做其他任何表述"), name: z.string().describe("资产名称,仅为名称不做其他任何表述"),
desc: z.string().describe("资产描述"), desc: z.string().describe("资产描述"),
type: z.enum(["role", "tool", "scene"]).describe("资产类型"), type: z.enum(["role", "tool", "scene"]).describe("资产类型"),
@ -25,7 +24,6 @@ const ExistingAssetRefSchema = z.object({
}); });
export const AssetSchema = z.object({ export const AssetSchema = z.object({
prompt: z.string().describe("生成提示词"),
name: z.string().describe("资产名称,仅为名称不做其他任何表述"), name: z.string().describe("资产名称,仅为名称不做其他任何表述"),
desc: z.string().describe("资产描述"), desc: z.string().describe("资产描述"),
type: z.enum(["role", "tool", "scene"]).describe("资产类型"), type: z.enum(["role", "tool", "scene"]).describe("资产类型"),
@ -108,7 +106,6 @@ export default router.post(
await u.db("o_assets").insert( await u.db("o_assets").insert(
toInsert.map((asset) => ({ toInsert.map((asset) => ({
name: asset.name, name: asset.name,
prompt: asset.prompt,
type: asset.type, type: asset.type,
describe: asset.desc, describe: asset.desc,
projectId: projectId, projectId: projectId,
@ -218,12 +215,11 @@ export default router.post(
content: content:
data?.data + data?.data +
"\n\n提取剧本中涉及的资产角色、场景、道具参考技能 script_assets_extract 规范,结果必须通过 resultTool 工具返回。" + "\n\n提取剧本中涉及的资产角色、场景、道具参考技能 script_assets_extract 规范,结果必须通过 resultTool 工具返回。" +
"\n\n注意本次会同时提供多集剧本每集剧本以 ===== 【剧本ID: xxx】 ===== 分隔。你需要分析每集剧本使用了哪些资产,并在输出中用 scriptIds 数组标明每个资产在哪些剧本中出现。" + "\n\n注意本次会同时提供多集剧本每集剧本以 ===== 【剧本ID: xxx】 ===== 分隔。你需要分析每集剧本使用了哪些资产,并在输出中用 scriptIds 数组标明每个资产在哪些剧本中出现。",
existingHint,
}, },
{ {
role: "user", role: "user",
content: `请根据以下${validScripts.length}集剧本提取对应的剧本资产(角色、场景、道具):\n\n${scriptsContent}`, content: `当前已有资产列表:${existingHint}\n\n请根据以下${validScripts.length}集剧本提取对应的剧本资产(角色、场景、道具):\n\n${scriptsContent}`,
}, },
], ],
tools: { resultTool }, tools: { resultTool },