Merge branch 'develop' of https://github.com/HBAI-Ltd/Toonflow-app into develop
# Conflicts: # src/router.ts
This commit is contained in:
commit
26e0c88c45
@ -114,10 +114,10 @@ Toonflow 是面向短剧生产的 AI 工作台,围绕“策划 → 编剧 →
|
||||
|
||||
## 📺 视频教程
|
||||
|
||||
https://www.bilibili.com/video/BV1na6wB6Ea2
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
https://www.bilibili.com/video/BV1oXD7BqEqJ
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow 8 分钟快速上手 AI 视频**
|
||||
**Toonflow 12 分钟快速上手 AI 视频**
|
||||
👉 [点击观看](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
📱 手机微信扫码观看
|
||||
|
||||
@ -1 +1 @@
|
||||
1.1.4
|
||||
1.1.5-dev
|
||||
@ -107,11 +107,11 @@ With Toonflow, you can complete the entire workflow from text to final video wit
|
||||
|
||||
## 📺 Video Tutorial
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow: 8-Minute AI Video Quick Start**
|
||||
👉 [Click to Watch](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
👉 [Click to Watch](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 Scan the QR code to watch on mobile
|
||||
|
||||
|
||||
@ -101,11 +101,11 @@ Toonflow は、AI技術を活用して小説を自動的に脚本へ変換し、
|
||||
|
||||
## 📺 動画チュートリアル
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow 8分でわかるクイックスタート AI動画作成**
|
||||
👉 [クリックして視聴](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
**Toonflow 12分でわかるクイックスタート AI動画作成**
|
||||
👉 [クリックして視聴](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 QRコードをスキャンして視聴
|
||||
|
||||
|
||||
@ -105,11 +105,11 @@ Toonflow — это мощный ИИ-инструмент для создани
|
||||
|
||||
## 📺 Видеоуроки
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow: Быстрый старт в AI-видео за 8 минут**
|
||||
👉 [Нажмите для просмотра](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
**Toonflow: Быстрый старт в AI-видео за 12 минут**
|
||||
👉 [Нажмите для просмотра](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 Отсканируйте QR-код для просмотра видео на телефоне
|
||||
|
||||
|
||||
@ -102,11 +102,11 @@ Toonflow เป็นเครื่องมือ AI สำหรับสร
|
||||
|
||||
## 📺 วิดีโอสอนการใช้งาน
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**เริ่มต้นสร้างวิดีโอ AI กับ Toonflow ใน 8 นาที**
|
||||
👉 [คลิกเพื่อรับชม](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
**เริ่มต้นสร้างวิดีโอ AI กับ Toonflow ใน 12 นาที**
|
||||
👉 [คลิกเพื่อรับชม](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 **สแกน QR Code เพื่อรับชมวิดีโอบนมือถือ**
|
||||
|
||||
|
||||
@ -97,11 +97,11 @@ Toonflow là công cụ AI chuyên tạo phim ngắn và truyện tranh, có kh
|
||||
|
||||
## 📺 Hướng dẫn bằng Video
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow - 8 phút làm quen nhanh với Video AI**
|
||||
👉 [Nhấn để xem](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
**Toonflow - 12 phút làm quen nhanh với Video AI**
|
||||
👉 [Nhấn để xem](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 **Quét mã QR để xem video trên điện thoại**
|
||||
<img src="./videoQR.png" alt="Quét mã QR để xem video" width="150"/>
|
||||
|
||||
@ -104,11 +104,11 @@ Toonflow 是一款 AI 短劇與漫畫創作工具,能夠利用 AI 技術將小
|
||||
|
||||
## 📺 影片教學
|
||||
|
||||
[https://www.bilibili.com/video/BV1na6wB6Ea2](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[](https://www.bilibili.com/video/BV1na6wB6Ea2)
|
||||
[https://www.bilibili.com/video/BV1oXD7BqEqJ](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
[](https://www.bilibili.com/video/BV1oXD7BqEqJ)
|
||||
|
||||
**Toonflow 8 分鐘快速上手 AI 影片**
|
||||
👉 [點擊觀看](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
**Toonflow 12 分鐘快速上手 AI 影片**
|
||||
👉 [點擊觀看](https://www.bilibili.com/video/BV1oXD7BqEqJ/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e)
|
||||
|
||||
📱 使用手機掃描 QR Code 觀看
|
||||
|
||||
|
||||
BIN
docs/videoCover.jpg
Normal file
BIN
docs/videoCover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 101 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "toonflow",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.5-dev",
|
||||
"description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。",
|
||||
"author": "HBAI-Ltd <ltlctools@outlook.com>",
|
||||
"license": "Apache-2.0",
|
||||
@ -47,7 +47,7 @@
|
||||
"ai": "^6.0.67",
|
||||
"axios": "^1.13.2",
|
||||
"axios-retry": "^4.5.0",
|
||||
"better-sqlite3": "^12.8.0",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"compressing": "^2.1.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.3",
|
||||
|
||||
@ -50,8 +50,8 @@ export async function runDecisionAI(ctx: AgentContext) {
|
||||
|
||||
const projectInfo = await u.db("o_project").where("id", ctx.resTool.data.projectId).first();
|
||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${ctx.resTool.data.projectId}`);
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/)
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/)
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/);
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/);
|
||||
const models = await u.vendor.getModelList(id);
|
||||
if (!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
||||
const findData = models.find((i: any) => i.modelName == videoModelName);
|
||||
@ -60,7 +60,7 @@ export async function runDecisionAI(ctx: AgentContext) {
|
||||
|
||||
const mem = buildMemPrompt(await memory.get(text));
|
||||
|
||||
const { fullStream } = await u.Ai.Text("productionAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||
const { fullStream } = await u.Ai.Text("productionAgent:decisionAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||
messages: [
|
||||
{ role: "system", content: prompt },
|
||||
{ role: "assistant", content: mem + "\n" + modelInfo },
|
||||
@ -90,6 +90,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const { resTool, abortSignal } = parentCtx;
|
||||
const memory = new Memory("productionAgent", parentCtx.isolationKey);
|
||||
async function runAgent({
|
||||
key,
|
||||
prompt,
|
||||
system,
|
||||
name,
|
||||
@ -97,6 +98,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
tools: extraTools,
|
||||
messages,
|
||||
}: {
|
||||
key: `${string}:${string}`;
|
||||
prompt: string;
|
||||
system: string;
|
||||
name: string;
|
||||
@ -107,7 +109,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
parentCtx.msg.complete();
|
||||
const subMsg = resTool.newMessage("assistant", name);
|
||||
|
||||
const { fullStream } = await u.Ai.Text("productionAgent", parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel).stream({
|
||||
const { fullStream } = await u.Ai.Text(key, parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel).stream({
|
||||
system,
|
||||
messages: messages ?? [{ role: "user", content: prompt }],
|
||||
abortSignal,
|
||||
@ -135,8 +137,8 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`);
|
||||
const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!);
|
||||
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/)
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/)
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/);
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/);
|
||||
const models = await u.vendor.getModelList(id);
|
||||
if (!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
||||
const findData = models.find((i: any) => i.modelName == videoModelName);
|
||||
@ -181,6 +183,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const skill = path.join(u.getPath("skills"), "production_execution_derive_assets.md");
|
||||
const systemPrompt = await fs.promises.readFile(skill, "utf-8");
|
||||
return runAgent({
|
||||
key: "productionAgent:deriveAssetsAgent",
|
||||
prompt,
|
||||
system: systemPrompt,
|
||||
name: "执行导演",
|
||||
@ -202,6 +205,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const skill = path.join(u.getPath("skills"), "production_execution_generate_assets.md");
|
||||
const systemPrompt = await fs.promises.readFile(skill, "utf-8");
|
||||
return runAgent({
|
||||
key: "productionAgent:generateAssetsAgent",
|
||||
prompt,
|
||||
system: systemPrompt,
|
||||
name: "执行导演",
|
||||
@ -226,6 +230,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const addPrompt = "\n你必须使用如下XML格式写入工作区:\n```\n<scriptPlan>内容</scriptPlan>\n```";
|
||||
|
||||
return runAgent({
|
||||
key: "productionAgent:directorPlanAgent",
|
||||
prompt,
|
||||
system: systemPrompt + addPrompt,
|
||||
name: "执行导演",
|
||||
@ -247,6 +252,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const skill = path.join(u.getPath("skills"), "production_execution_storyboard_gen.md");
|
||||
const systemPrompt = await fs.promises.readFile(skill, "utf-8");
|
||||
return runAgent({
|
||||
key: "productionAgent:storyboardGenAgent",
|
||||
prompt,
|
||||
system: systemPrompt,
|
||||
name: "执行导演",
|
||||
@ -284,6 +290,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
"\n你必须使用如下XML格式写入工作区:\n```\n<storyboardItem videoDesc='视频描述' prompt=提示词内容 track='分组' duration='视频推荐时间' associateAssetsIds='[该分镜所需的资产ID列表]'></storyboardItem>\n```";
|
||||
|
||||
return runAgent({
|
||||
key: "productionAgent:storyboardPanelAgent",
|
||||
prompt,
|
||||
system: systemPrompt + addPrompt,
|
||||
name: "执行导演",
|
||||
@ -308,6 +315,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const addPrompt = "\n你必须使用如下XML格式写入工作区:\n```\n<storyboardTable>内容</storyboardTable>\n```";
|
||||
|
||||
return runAgent({
|
||||
key: "productionAgent:storyboardTableAgent",
|
||||
prompt,
|
||||
system: systemPrompt + addPrompt,
|
||||
name: "执行导演",
|
||||
@ -328,6 +336,7 @@ async function createSubAgent(parentCtx: AgentContext) {
|
||||
const skill = path.join(u.getPath("skills"), "production_agent_supervision.md");
|
||||
const systemPrompt = await fs.promises.readFile(skill, "utf-8");
|
||||
return runAgent({
|
||||
key: "productionAgent:supervisionAgent",
|
||||
prompt,
|
||||
system: systemPrompt,
|
||||
name: "监制",
|
||||
|
||||
@ -63,7 +63,7 @@ export async function runDecisionAI(ctx: AgentContext) {
|
||||
`章节数量:${novelData.length}章`,
|
||||
].join("\n");
|
||||
|
||||
const { fullStream } = await u.Ai.Text("scriptAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||
const { fullStream } = await u.Ai.Text("scriptAgent:decisionAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||
messages: [
|
||||
{ role: "system", content: prompt },
|
||||
{ role: "assistant", content: projectInfo + "\n" + mem },
|
||||
@ -94,6 +94,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
const memory = new Memory("scriptAgent", parentCtx.isolationKey);
|
||||
|
||||
async function runAgent({
|
||||
key,
|
||||
prompt,
|
||||
system,
|
||||
name,
|
||||
@ -101,6 +102,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
tools: extraTools,
|
||||
messages,
|
||||
}: {
|
||||
key: `${string}:${string}`;
|
||||
prompt: string;
|
||||
system: string;
|
||||
name: string;
|
||||
@ -111,7 +113,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
parentCtx.msg.complete();
|
||||
const subMsg = resTool.newMessage("assistant", name);
|
||||
|
||||
const { fullStream } = await u.Ai.Text("scriptAgent", parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel).stream({
|
||||
const { fullStream } = await u.Ai.Text(key, parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel).stream({
|
||||
system,
|
||||
messages: messages ?? [{ role: "user", content: prompt }],
|
||||
abortSignal,
|
||||
@ -145,6 +147,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
const formatPrompt = "\n你必须使用如下XML格式写入工作区:\n<storySkeleton>故事骨架内容</storySkeleton>";
|
||||
|
||||
return runAgent({
|
||||
key: "scriptAgent:storySkeletonAgent",
|
||||
prompt,
|
||||
system: systemPrompt + formatPrompt,
|
||||
name: "编剧",
|
||||
@ -164,6 +167,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
const formatPrompt = "\n你必须使用如下XML格式写入工作区:\n<adaptationStrategy>改编策略内容</adaptationStrategy>";
|
||||
|
||||
return runAgent({
|
||||
key: "scriptAgent:adaptationStrategyAgent",
|
||||
prompt,
|
||||
system: systemPrompt + formatPrompt,
|
||||
name: "编剧",
|
||||
@ -190,6 +194,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
const formatPrompt = `\n你必须使用如下XML格式写入工作区:\nXML不得添加任何额外标签<scriptItem name="剧本名称">剧本内容</scriptItem><scriptItem name="剧本名称">剧本内容</scriptItem><scriptItem name="剧本名称">剧本内容</scriptItem>`;
|
||||
|
||||
return runAgent({
|
||||
key: "scriptAgent:scriptAgent",
|
||||
prompt,
|
||||
system: systemPrompt + formatPrompt,
|
||||
messages: [
|
||||
@ -210,6 +215,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
const systemPrompt = await fs.promises.readFile(skill, "utf-8");
|
||||
|
||||
return runAgent({
|
||||
key: "scriptAgent:supervisionAgent",
|
||||
prompt,
|
||||
system: systemPrompt,
|
||||
name: "编辑",
|
||||
|
||||
@ -59,7 +59,45 @@ export default async (knex: Knex): Promise<void> => {
|
||||
|
||||
// 添加新字段
|
||||
await addColumn("o_prompt", "useData", "text");
|
||||
// 添加新字段
|
||||
await addColumn("o_agentDeploy", "type", "string");
|
||||
// 添加新字段
|
||||
await addColumn("o_agentDeploy", "temperature", "integer");
|
||||
// 添加新字段
|
||||
await addColumn("o_agentDeploy", "maxOutputTokens", "integer");
|
||||
|
||||
//添加数据高级配置
|
||||
const advancedAgentList = [
|
||||
{ key: "scriptAgent:decisionAgent", name: "剧本Agent:决策层", desc: "决策层" },
|
||||
{ key: "scriptAgent:supervisionAgent", name: "剧本Agent:监督层", desc: "监督层" },
|
||||
{ key: "scriptAgent:storySkeletonAgent", name: "剧本Agent:故事骨架", desc: "故事骨架生成" },
|
||||
{ key: "scriptAgent:adaptationStrategyAgent", name: "剧本Agent:改编策略", desc: "改编策略生成" },
|
||||
{ key: "scriptAgent:scriptAgent", name: "剧本Agent:剧本生成", desc: "剧本生成" },
|
||||
{ key: "productionAgent:decisionAgent", name: "生产Agent:决策层", desc: "决策层" },
|
||||
{ key: "productionAgent:supervisionAgent", name: "生产Agent:监督层", desc: "监督层" },
|
||||
{ key: "productionAgent:deriveAssetsAgent", name: "生产Agent:衍生资产", desc: "衍生资产" },
|
||||
{ key: "productionAgent:generateAssetsAgent", name: "生产Agent:生成资产", desc: "生成资产" },
|
||||
{ key: "productionAgent:directorPlanAgent", name: "生产Agent:导演规划", desc: "导演规划" },
|
||||
{ key: "productionAgent:storyboardGenAgent", name: "生产Agent:分镜生成", desc: "分镜生成" },
|
||||
{ key: "productionAgent:storyboardPanelAgent", name: "生产Agent:分镜面板", desc: "分镜面板生成" },
|
||||
{ key: "productionAgent:storyboardTableAgent", name: "生产Agent:分镜表格", desc: "分镜表格生成" },
|
||||
];
|
||||
for (const agent of advancedAgentList) {
|
||||
const exists = await db("o_agentDeploy").where("key", agent.key).select("*").first();
|
||||
if (!exists) {
|
||||
await db("o_agentDeploy").insert({
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: agent.key,
|
||||
name: agent.name,
|
||||
desc: agent.desc,
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
//矫正提示词
|
||||
await db("o_prompt").where("type", "scriptAssetExtraction").update({
|
||||
data: `---\nname: universal_agent\ndescription: 专注于从剧本内容中提取所使用的资产(角色、场景、道具)并生成结构化资产列表的助手。\n---\n\n# Script Assets Extract\n\n你是一个专业的剧本内容分析助手,专注于从剧本文本中识别和提取所有涉及的资产(角色、场景、道具),并为每项资产生成可供下游制作流程使用的结构化描述和提示词。\n\n## 何时使用\n\n用户提供剧本内容,你需要逐段阅读并提取其中涉及的所有资产(人物角色、场景地点、道具物件),输出为结构化的资产列表。产出的资产描述将用于后续 AI 图片生成和制作流程。\n\n## 与系统的对应关系\n\n- 资产类型:\n - \`role\` — 角色(对应 \`o_assets.type = "role"\`)\n - \`scene\` — 场景(对应 \`o_assets.type = "scene"\`)\n - \`tool\` — 道具(对应 \`o_assets.type = "tool"\`)\n- 下游用途:资产提示词生成 → AI 资产图生成 → 分镜制作\n\n## 输出要求\n\n**必须通过调用 \`resultTool\` 工具返回结果**,禁止以纯文本、Markdown 表格或 JSON 代码块等形式直接输出资产列表。\n\`resultTool\` 的 schema 会对字段类型和枚举值做强校验,调用时请严格按照下方字段定义填写,确保数据结构正确、字段完整、类型匹配。\n\n每个资产对象包含以下字段:\n\n| 字段 | 类型 | 必填 | 说明 |\n| ---- | ---- | ---- | ---- |\n| \`name\` | string | 是 | 资产名称,使用剧本中的原始称呼,不做其他多余描述 |\n| \`desc\` | string | 是 | 资产描述,30-80 字的视觉化描述 |\n| \`prompt\` | string | 是 | 生成提示词,英文,用于 AI 图片生成 |\n| \`type\` | enum | 是 | 资产类型:\`role\` / \`scene\` / \`tool\` |\n\n## 提取规则\n\n### 角色(role)\n\n- 提取剧本中出现的所有有名字的角色\n- \`desc\`:包含性别、外貌特征、服饰风格、体态气质等视觉要素,需在描述开头明确标注角色性别(如"男性,……"或"女性,……")\n- \`prompt\`:英文提示词,描述角色的外观特征,需以性别词开头(如 \`a young man, ...\` 或 \`a young woman, ...\`),适用于 AI 角色图生成\n- 同一角色有多个称呼时,取最常用的作为 \`name\`\n- 无名龙套(如"路人甲"、"士兵")可跳过,除非其造型对剧情有重要视觉意义\n\n### 场景(scene)\n\n- 提取剧本中出现的所有场景/地点\n- \`desc\`:包含空间结构、光照氛围、关键陈设、色调基调等视觉要素\n- \`prompt\`:英文提示词,描述场景的整体视觉风格,适用于 AI 场景图生成\n- 同一场景的不同状态(如白天/夜晚)不重复提取,在 \`desc\` 中注明即可\n\n### 道具(tool)\n\n- 提取剧本中出现的重要道具/物品\n- \`desc\`:包含外观形状、颜色材质、尺寸参考、特殊效果等视觉要素\n- \`prompt\`:英文提示词,描述道具的外观细节,适用于 AI 道具图生成\n- 仅提取有独立视觉意义或剧情功能的道具,通用物品可跳过\n\n\n## 提示词(prompt)生成规范\n\n- 采用逗号分隔的关键词/短语格式\n- 优先描述**视觉特征**,避免抽象概念\n- 包含风格关键词(如 anime style, manga style 等,根据项目风格决定)\n- 角色 prompt 示例:\`a young man, sharp eyebrows, black hair, pale skin, wearing a gray Taoist robe, slender build, cold expression\`\n- 场景 prompt 示例:\`dark cave interior, glowing crystals on walls, misty atmosphere, dim blue lighting, stone altar in center\`\n- 道具 prompt 示例:\`ancient jade pendant, oval shape, translucent green, carved dragon pattern, glowing faintly\`\n\n## 提取流程\n\n1. 通读剧本全文,识别所有出现的角色、场景、道具\n2. 对每个资产生成结构化的 \`name\`、\`desc\`、\`prompt\`、\`type\`\n3. 去重:同一资产不重复提取\n4. **必须通过调用 \`resultTool\` 工具输出完整资产列表**,不要分多次调用,一次性将所有资产放入 \`assetsList\` 数组中提交\n\n## 提取原则\n\n1. **忠于剧本**:所有提取基于剧本中的实际内容,不臆造未出现的资产\n2. **视觉优先**:描述和提示词聚焦视觉特征,便于 AI 图片生成\n3. **精简实用**:只提取对制作有实际意义的资产,避免过度提取\n4. **分类准确**:严格按照 role/scene/tool 分类,不混淆\n5. **提示词质量**:英文提示词应具体、可执行,能直接用于 AI 图片生成\n\n## 注意事项\n\n- 资产列表中**不要包含剧本内容本身**,仅提取所使用到的资产\n- 角色的随身物品如果有独立剧情功能,应单独作为道具提取\n- 场景中的固定陈设不需要单独提取为道具,除非该物件有独立剧情作用`,
|
||||
|
||||
@ -58,7 +58,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
},
|
||||
initData: async (knex) => {},
|
||||
initData: async (knex) => { },
|
||||
},
|
||||
//Agent配置表
|
||||
{
|
||||
@ -71,6 +71,8 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
table.text("vendorId");
|
||||
table.string("desc");
|
||||
table.string("name");
|
||||
table.integer("temperature");
|
||||
table.integer("maxOutputTokens");
|
||||
table.boolean("disabled").defaultTo(false);
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
@ -113,6 +115,150 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
desc: "根据剧本内容生成角色配音,支持多种声音风格和情绪",
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "scriptAgent:decisionAgent",
|
||||
name: "剧本Agent:决策层",
|
||||
desc: "决策层",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "scriptAgent:supervisionAgent",
|
||||
name: "剧本Agent:监督层",
|
||||
desc: "监督层",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "scriptAgent:storySkeletonAgent",
|
||||
name: "剧本Agent:故事骨架",
|
||||
desc: "故事骨架生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "scriptAgent:adaptationStrategyAgent",
|
||||
name: "剧本Agent:改编策略",
|
||||
desc: "改编策略生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "scriptAgent:scriptAgent",
|
||||
name: "剧本Agent:剧本生成",
|
||||
desc: "剧本生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:decisionAgent",
|
||||
name: "生产Agent:决策层",
|
||||
desc: "决策层",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:supervisionAgent",
|
||||
name: "生产Agent:监督层",
|
||||
desc: "监督层",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:deriveAssetsAgent",
|
||||
name: "生产Agent:衍生资产",
|
||||
desc: "衍生资产",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:generateAssetsAgent",
|
||||
name: "生产Agent:生成资产",
|
||||
desc: "生成资产",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:directorPlanAgent",
|
||||
name: "生产Agent:导演规划",
|
||||
desc: "导演规划",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:storyboardGenAgent",
|
||||
name: "生产Agent:分镜生成",
|
||||
desc: "分镜生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:storyboardPanelAgent",
|
||||
name: "生产Agent:分镜面板",
|
||||
desc: "分镜面板生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
model: "",
|
||||
modelName: "",
|
||||
vendorId: null,
|
||||
key: "productionAgent:storyboardTableAgent",
|
||||
name: "生产Agent:分镜表格",
|
||||
desc: "分镜表格生成",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 0,
|
||||
disabled: false,
|
||||
},
|
||||
|
||||
]);
|
||||
},
|
||||
},
|
||||
@ -186,7 +332,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
},
|
||||
initData: async (knex) => {},
|
||||
initData: async (knex) => { },
|
||||
},
|
||||
//提示词表
|
||||
{
|
||||
@ -231,7 +377,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
},
|
||||
initData: async (knex) => {},
|
||||
initData: async (knex) => { },
|
||||
},
|
||||
//小说原文表
|
||||
{
|
||||
@ -310,7 +456,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
},
|
||||
initData: async (knex) => {},
|
||||
initData: async (knex) => { },
|
||||
},
|
||||
//生成图片表
|
||||
{
|
||||
|
||||
180
src/router.ts
180
src/router.ts
@ -1,4 +1,4 @@
|
||||
// @routes-hash cc267cab29401f6ad9055dac01879652
|
||||
// @routes-hash 0eb42cb2928b13229e60a26b83f977a9
|
||||
import { Express } from "express";
|
||||
|
||||
import route1 from "./routes/agents/clearMemory";
|
||||
@ -103,50 +103,51 @@ import route99 from "./routes/script/batchAddScript";
|
||||
import route100 from "./routes/script/delScript";
|
||||
import route101 from "./routes/script/exportScript";
|
||||
import route102 from "./routes/script/extractAssets";
|
||||
import route103 from "./routes/script/getScrptApi";
|
||||
import route104 from "./routes/script/pollScriptAssets";
|
||||
import route105 from "./routes/script/updateScript";
|
||||
import route106 from "./routes/scriptAgent/getPlanData";
|
||||
import route107 from "./routes/scriptAgent/setPlanData";
|
||||
import route108 from "./routes/scriptAgent/updateData";
|
||||
import route109 from "./routes/setting/about/checkUpdate";
|
||||
import route110 from "./routes/setting/about/downloadApp";
|
||||
import route111 from "./routes/setting/agentDeploy/agentSetKey";
|
||||
import route112 from "./routes/setting/agentDeploy/deployAgentModel";
|
||||
import route113 from "./routes/setting/agentDeploy/getAgentDeploy";
|
||||
import route114 from "./routes/setting/dbConfig/clearData";
|
||||
import route115 from "./routes/setting/dev/getSwitchAiDevTool";
|
||||
import route116 from "./routes/setting/dev/updateSwitchAiDevTool";
|
||||
import route117 from "./routes/setting/fileManagement/openFolder";
|
||||
import route118 from "./routes/setting/getTextModel";
|
||||
import route119 from "./routes/setting/loginConfig/getUser";
|
||||
import route120 from "./routes/setting/loginConfig/updateUserPwd";
|
||||
import route121 from "./routes/setting/memoryConfig/delAllMemory";
|
||||
import route122 from "./routes/setting/memoryConfig/getMemory";
|
||||
import route123 from "./routes/setting/memoryConfig/sureMemory";
|
||||
import route124 from "./routes/setting/modelMap/bindingPrompt";
|
||||
import route125 from "./routes/setting/modelMap/getImageAndVideoModel";
|
||||
import route126 from "./routes/setting/promptManage/getPrompt";
|
||||
import route127 from "./routes/setting/promptManage/updatePrompt";
|
||||
import route128 from "./routes/setting/skillManagement/getSkillContent";
|
||||
import route129 from "./routes/setting/skillManagement/getSkillList";
|
||||
import route130 from "./routes/setting/skillManagement/saveSkillContent";
|
||||
import route131 from "./routes/setting/vendorConfig/addVendor";
|
||||
import route132 from "./routes/setting/vendorConfig/addVendorModel";
|
||||
import route133 from "./routes/setting/vendorConfig/deleteVendor";
|
||||
import route134 from "./routes/setting/vendorConfig/delVendorModel";
|
||||
import route135 from "./routes/setting/vendorConfig/enableVendor";
|
||||
import route136 from "./routes/setting/vendorConfig/getCodeByLink";
|
||||
import route137 from "./routes/setting/vendorConfig/getVendorList";
|
||||
import route138 from "./routes/setting/vendorConfig/modelTest";
|
||||
import route139 from "./routes/setting/vendorConfig/updateCode";
|
||||
import route140 from "./routes/setting/vendorConfig/updateVendorInputs";
|
||||
import route141 from "./routes/setting/vendorConfig/upVendorModel";
|
||||
import route142 from "./routes/task/getProject";
|
||||
import route143 from "./routes/task/getTaskApi";
|
||||
import route144 from "./routes/task/getTaskCategories";
|
||||
import route145 from "./routes/task/taskDetails";
|
||||
import route146 from "./routes/test/test";
|
||||
import route103 from "./routes/script/getAiRegex";
|
||||
import route104 from "./routes/script/getScrptApi";
|
||||
import route105 from "./routes/script/pollScriptAssets";
|
||||
import route106 from "./routes/script/updateScript";
|
||||
import route107 from "./routes/scriptAgent/getPlanData";
|
||||
import route108 from "./routes/scriptAgent/setPlanData";
|
||||
import route109 from "./routes/scriptAgent/updateData";
|
||||
import route110 from "./routes/setting/about/checkUpdate";
|
||||
import route111 from "./routes/setting/about/downloadApp";
|
||||
import route112 from "./routes/setting/agentDeploy/agentSetKey";
|
||||
import route113 from "./routes/setting/agentDeploy/deployAgentModel";
|
||||
import route114 from "./routes/setting/agentDeploy/getAgentDeploy";
|
||||
import route115 from "./routes/setting/dbConfig/clearData";
|
||||
import route116 from "./routes/setting/dev/getSwitchAiDevTool";
|
||||
import route117 from "./routes/setting/dev/updateSwitchAiDevTool";
|
||||
import route118 from "./routes/setting/fileManagement/openFolder";
|
||||
import route119 from "./routes/setting/getTextModel";
|
||||
import route120 from "./routes/setting/loginConfig/getUser";
|
||||
import route121 from "./routes/setting/loginConfig/updateUserPwd";
|
||||
import route122 from "./routes/setting/memoryConfig/delAllMemory";
|
||||
import route123 from "./routes/setting/memoryConfig/getMemory";
|
||||
import route124 from "./routes/setting/memoryConfig/sureMemory";
|
||||
import route125 from "./routes/setting/modelMap/bindingPrompt";
|
||||
import route126 from "./routes/setting/modelMap/getImageAndVideoModel";
|
||||
import route127 from "./routes/setting/promptManage/getPrompt";
|
||||
import route128 from "./routes/setting/promptManage/updatePrompt";
|
||||
import route129 from "./routes/setting/skillManagement/getSkillContent";
|
||||
import route130 from "./routes/setting/skillManagement/getSkillList";
|
||||
import route131 from "./routes/setting/skillManagement/saveSkillContent";
|
||||
import route132 from "./routes/setting/vendorConfig/addVendor";
|
||||
import route133 from "./routes/setting/vendorConfig/addVendorModel";
|
||||
import route134 from "./routes/setting/vendorConfig/deleteVendor";
|
||||
import route135 from "./routes/setting/vendorConfig/delVendorModel";
|
||||
import route136 from "./routes/setting/vendorConfig/enableVendor";
|
||||
import route137 from "./routes/setting/vendorConfig/getCodeByLink";
|
||||
import route138 from "./routes/setting/vendorConfig/getVendorList";
|
||||
import route139 from "./routes/setting/vendorConfig/modelTest";
|
||||
import route140 from "./routes/setting/vendorConfig/updateCode";
|
||||
import route141 from "./routes/setting/vendorConfig/updateVendorInputs";
|
||||
import route142 from "./routes/setting/vendorConfig/upVendorModel";
|
||||
import route143 from "./routes/task/getProject";
|
||||
import route144 from "./routes/task/getTaskApi";
|
||||
import route145 from "./routes/task/getTaskCategories";
|
||||
import route146 from "./routes/task/taskDetails";
|
||||
import route147 from "./routes/test/test";
|
||||
|
||||
export default async (app: Express) => {
|
||||
app.use("/api/agents/clearMemory", route1);
|
||||
@ -251,48 +252,49 @@ export default async (app: Express) => {
|
||||
app.use("/api/script/delScript", route100);
|
||||
app.use("/api/script/exportScript", route101);
|
||||
app.use("/api/script/extractAssets", route102);
|
||||
app.use("/api/script/getScrptApi", route103);
|
||||
app.use("/api/script/pollScriptAssets", route104);
|
||||
app.use("/api/script/updateScript", route105);
|
||||
app.use("/api/scriptAgent/getPlanData", route106);
|
||||
app.use("/api/scriptAgent/setPlanData", route107);
|
||||
app.use("/api/scriptAgent/updateData", route108);
|
||||
app.use("/api/setting/about/checkUpdate", route109);
|
||||
app.use("/api/setting/about/downloadApp", route110);
|
||||
app.use("/api/setting/agentDeploy/agentSetKey", route111);
|
||||
app.use("/api/setting/agentDeploy/deployAgentModel", route112);
|
||||
app.use("/api/setting/agentDeploy/getAgentDeploy", route113);
|
||||
app.use("/api/setting/dbConfig/clearData", route114);
|
||||
app.use("/api/setting/dev/getSwitchAiDevTool", route115);
|
||||
app.use("/api/setting/dev/updateSwitchAiDevTool", route116);
|
||||
app.use("/api/setting/fileManagement/openFolder", route117);
|
||||
app.use("/api/setting/getTextModel", route118);
|
||||
app.use("/api/setting/loginConfig/getUser", route119);
|
||||
app.use("/api/setting/loginConfig/updateUserPwd", route120);
|
||||
app.use("/api/setting/memoryConfig/delAllMemory", route121);
|
||||
app.use("/api/setting/memoryConfig/getMemory", route122);
|
||||
app.use("/api/setting/memoryConfig/sureMemory", route123);
|
||||
app.use("/api/setting/modelMap/bindingPrompt", route124);
|
||||
app.use("/api/setting/modelMap/getImageAndVideoModel", route125);
|
||||
app.use("/api/setting/promptManage/getPrompt", route126);
|
||||
app.use("/api/setting/promptManage/updatePrompt", route127);
|
||||
app.use("/api/setting/skillManagement/getSkillContent", route128);
|
||||
app.use("/api/setting/skillManagement/getSkillList", route129);
|
||||
app.use("/api/setting/skillManagement/saveSkillContent", route130);
|
||||
app.use("/api/setting/vendorConfig/addVendor", route131);
|
||||
app.use("/api/setting/vendorConfig/addVendorModel", route132);
|
||||
app.use("/api/setting/vendorConfig/deleteVendor", route133);
|
||||
app.use("/api/setting/vendorConfig/delVendorModel", route134);
|
||||
app.use("/api/setting/vendorConfig/enableVendor", route135);
|
||||
app.use("/api/setting/vendorConfig/getCodeByLink", route136);
|
||||
app.use("/api/setting/vendorConfig/getVendorList", route137);
|
||||
app.use("/api/setting/vendorConfig/modelTest", route138);
|
||||
app.use("/api/setting/vendorConfig/updateCode", route139);
|
||||
app.use("/api/setting/vendorConfig/updateVendorInputs", route140);
|
||||
app.use("/api/setting/vendorConfig/upVendorModel", route141);
|
||||
app.use("/api/task/getProject", route142);
|
||||
app.use("/api/task/getTaskApi", route143);
|
||||
app.use("/api/task/getTaskCategories", route144);
|
||||
app.use("/api/task/taskDetails", route145);
|
||||
app.use("/api/test/test", route146);
|
||||
app.use("/api/script/getAiRegex", route103);
|
||||
app.use("/api/script/getScrptApi", route104);
|
||||
app.use("/api/script/pollScriptAssets", route105);
|
||||
app.use("/api/script/updateScript", route106);
|
||||
app.use("/api/scriptAgent/getPlanData", route107);
|
||||
app.use("/api/scriptAgent/setPlanData", route108);
|
||||
app.use("/api/scriptAgent/updateData", route109);
|
||||
app.use("/api/setting/about/checkUpdate", route110);
|
||||
app.use("/api/setting/about/downloadApp", route111);
|
||||
app.use("/api/setting/agentDeploy/agentSetKey", route112);
|
||||
app.use("/api/setting/agentDeploy/deployAgentModel", route113);
|
||||
app.use("/api/setting/agentDeploy/getAgentDeploy", route114);
|
||||
app.use("/api/setting/dbConfig/clearData", route115);
|
||||
app.use("/api/setting/dev/getSwitchAiDevTool", route116);
|
||||
app.use("/api/setting/dev/updateSwitchAiDevTool", route117);
|
||||
app.use("/api/setting/fileManagement/openFolder", route118);
|
||||
app.use("/api/setting/getTextModel", route119);
|
||||
app.use("/api/setting/loginConfig/getUser", route120);
|
||||
app.use("/api/setting/loginConfig/updateUserPwd", route121);
|
||||
app.use("/api/setting/memoryConfig/delAllMemory", route122);
|
||||
app.use("/api/setting/memoryConfig/getMemory", route123);
|
||||
app.use("/api/setting/memoryConfig/sureMemory", route124);
|
||||
app.use("/api/setting/modelMap/bindingPrompt", route125);
|
||||
app.use("/api/setting/modelMap/getImageAndVideoModel", route126);
|
||||
app.use("/api/setting/promptManage/getPrompt", route127);
|
||||
app.use("/api/setting/promptManage/updatePrompt", route128);
|
||||
app.use("/api/setting/skillManagement/getSkillContent", route129);
|
||||
app.use("/api/setting/skillManagement/getSkillList", route130);
|
||||
app.use("/api/setting/skillManagement/saveSkillContent", route131);
|
||||
app.use("/api/setting/vendorConfig/addVendor", route132);
|
||||
app.use("/api/setting/vendorConfig/addVendorModel", route133);
|
||||
app.use("/api/setting/vendorConfig/deleteVendor", route134);
|
||||
app.use("/api/setting/vendorConfig/delVendorModel", route135);
|
||||
app.use("/api/setting/vendorConfig/enableVendor", route136);
|
||||
app.use("/api/setting/vendorConfig/getCodeByLink", route137);
|
||||
app.use("/api/setting/vendorConfig/getVendorList", route138);
|
||||
app.use("/api/setting/vendorConfig/modelTest", route139);
|
||||
app.use("/api/setting/vendorConfig/updateCode", route140);
|
||||
app.use("/api/setting/vendorConfig/updateVendorInputs", route141);
|
||||
app.use("/api/setting/vendorConfig/upVendorModel", route142);
|
||||
app.use("/api/task/getProject", route143);
|
||||
app.use("/api/task/getTaskApi", route144);
|
||||
app.use("/api/task/getTaskCategories", route145);
|
||||
app.use("/api/task/taskDetails", route146);
|
||||
app.use("/api/test/test", route147);
|
||||
}
|
||||
|
||||
35
src/routes/script/getAiRegex.ts
Normal file
35
src/routes/script/getAiRegex.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import express from "express";
|
||||
import u from "@/utils";
|
||||
import { z } from "zod";
|
||||
import { success } from "@/lib/responseFormat";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
const router = express.Router();
|
||||
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
content: z.string(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { content } = req.body;
|
||||
const systemPrompt = `你是一个正则表达式专家。用户会提供一段剧本文本,你需要分析其中的集/章节分隔模式,返回一个JavaScript正则表达式字符串。
|
||||
|
||||
要求:
|
||||
1. 正则必须包含两个捕获组:第一个捕获组匹配集数/章节编号(数字或中文数字),第二个捕获组匹配该集的标题/名称(scriptName)。
|
||||
2. 返回格式为 /正则表达式/g,例如:/第\s*([0-9一二三四五六七八九十百千万]+)\s*集\s*([^\n\r]*)/g
|
||||
3. 只返回正则表达式字符串本身,不要有任何其他解释文字或markdown格式。
|
||||
4. 如果文本中没有明显的章节分隔模式,返回空字符串。`;
|
||||
|
||||
const resText = await u.Ai.Text("universalAi").invoke({
|
||||
system: systemPrompt,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: content.slice(0, 2000),
|
||||
},
|
||||
],
|
||||
});
|
||||
const result = (resText.text || "").trim();
|
||||
res.status(200).send(success(result));
|
||||
},
|
||||
);
|
||||
@ -43,6 +43,97 @@ export default router.post(
|
||||
modelName: "toonflow:claude-haiku-4-5-20251001",
|
||||
vendorId: "toonflow",
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "scriptAgent:decisionAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "scriptAgent:supervisionAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "scriptAgent:storySkeletonAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "scriptAgent:adaptationStrategyAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "scriptAgent:scriptAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:decisionAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:supervisionAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:deriveAssetsAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:generateAssetsAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:directorPlanAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardGenAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardPanelAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
await u.db("o_agentDeploy").where("key", "productionAgent:storyboardTableAgent").update({
|
||||
model: "claude-sonnet-4-6",
|
||||
modelName: "toonflow:claude-sonnet-4-6",
|
||||
vendorId: "toonflow",
|
||||
temperature: 1,
|
||||
maxOutputTokens: 8192,
|
||||
});
|
||||
res.status(200).send(success("一键填入成功"));
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@ -14,10 +14,12 @@ export default router.post(
|
||||
modelName: z.string(),
|
||||
vendorId: z.string().nullable(),
|
||||
desc: z.string(),
|
||||
temperature: z.number().optional(),
|
||||
maxOutputTokens: z.number().optional(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { id, name, model, modelName, vendorId, desc } = req.body;
|
||||
await u.db("o_agentDeploy").where({ id }).update({ id, name, model, modelName, vendorId, desc });
|
||||
const { id, name, model, modelName, vendorId, desc, temperature, maxOutputTokens } = req.body;
|
||||
await u.db("o_agentDeploy").where({ id }).update({ id, name, model, modelName, vendorId, desc, temperature, maxOutputTokens });
|
||||
res.status(200).send(success("配置成功"));
|
||||
},
|
||||
);
|
||||
|
||||
@ -4,6 +4,8 @@ import u from "@/utils";
|
||||
const router = express.Router();
|
||||
|
||||
export default router.post("/", async (req, res) => {
|
||||
const data = await u.db("o_agentDeploy").leftJoin("o_vendorConfig", "o_vendorConfig.id", "o_agentDeploy.vendorId").select("o_agentDeploy.*");
|
||||
res.status(200).send(success(data));
|
||||
const allData = await u.db("o_agentDeploy").leftJoin("o_vendorConfig", "o_vendorConfig.id", "o_agentDeploy.vendorId").select("o_agentDeploy.*");
|
||||
const qrdinaryData = allData.filter((item: any) => !item.key?.includes(":"));
|
||||
const advancedData = allData.filter((item: any) => item.key?.includes(":"));
|
||||
res.status(200).send(success({ qrdinaryData, advancedData }));
|
||||
});
|
||||
|
||||
40
src/types/database.d.ts
vendored
40
src/types/database.d.ts
vendored
@ -1,37 +1,6 @@
|
||||
// @db-hash e2ce409a953a516777e836e1ff0ca34b
|
||||
// @db-hash 5364c2db0bf42b520761b813ce040489
|
||||
//该文件由脚本自动生成,请勿手动修改
|
||||
|
||||
export interface _o_project_old_20260404 {
|
||||
'artStyle'?: string | null;
|
||||
'createTime'?: number | null;
|
||||
'directorManual'?: string | null;
|
||||
'id'?: number | null;
|
||||
'imageModel'?: string | null;
|
||||
'imageQuality'?: string | null;
|
||||
'intro'?: string | null;
|
||||
'mode'?: string | null;
|
||||
'name'?: string | null;
|
||||
'projectType'?: string | null;
|
||||
'type'?: string | null;
|
||||
'userId'?: number | null;
|
||||
'videoModel'?: string | null;
|
||||
'videoRatio'?: string | null;
|
||||
}
|
||||
export interface _o_prompt_old_20260406 {
|
||||
'data'?: string | null;
|
||||
'id'?: number;
|
||||
'name'?: string | null;
|
||||
'type'?: string | null;
|
||||
'useData'?: string | null;
|
||||
}
|
||||
export interface _o_prompt_old_20260406_1 {
|
||||
'data'?: string | null;
|
||||
'id'?: number;
|
||||
'name'?: string | null;
|
||||
'TEXT'?: any | null;
|
||||
'type'?: string | null;
|
||||
'useData'?: string | null;
|
||||
}
|
||||
export interface memories {
|
||||
'content': string;
|
||||
'createTime': number;
|
||||
@ -49,9 +18,13 @@ export interface o_agentDeploy {
|
||||
'disabled'?: boolean | null;
|
||||
'id'?: number;
|
||||
'key'?: string | null;
|
||||
'maxOutputTokens'?: number | null;
|
||||
'model'?: string | null;
|
||||
'modelName'?: string | null;
|
||||
'name'?: string | null;
|
||||
'temperature'?: number | null;
|
||||
'topP'?: number | null;
|
||||
'type'?: string | null;
|
||||
'vendorId'?: string | null;
|
||||
}
|
||||
export interface o_agentWorkData {
|
||||
@ -266,9 +239,6 @@ export interface o_videoTrack {
|
||||
}
|
||||
|
||||
export interface DB {
|
||||
"_o_project_old_20260404": _o_project_old_20260404;
|
||||
"_o_prompt_old_20260406": _o_prompt_old_20260406;
|
||||
"_o_prompt_old_20260406_1": _o_prompt_old_20260406_1;
|
||||
"memories": memories;
|
||||
"o_agentDeploy": o_agentDeploy;
|
||||
"o_agentWorkData": o_agentWorkData;
|
||||
|
||||
@ -4,19 +4,75 @@ import axios from "axios";
|
||||
import { transform } from "sucrase";
|
||||
import u from "@/utils";
|
||||
|
||||
type AiType = "scriptAgent" | "productionAgent" | "universalAi";
|
||||
type AiType =
|
||||
| "scriptAgent"
|
||||
| "productionAgent"
|
||||
| "universalAi"
|
||||
| "scriptAgent:decisionAgent"
|
||||
| "scriptAgent:supervisionAgent"
|
||||
| "scriptAgent:storySkeletonAgent"
|
||||
| "scriptAgent:adaptationStrategyAgent"
|
||||
| "scriptAgent:scriptAgent"
|
||||
| "productionAgent:decisionAgent"
|
||||
| "productionAgent:supervisionAgent"
|
||||
| "productionAgent:deriveAssetsAgent"
|
||||
| "productionAgent:generateAssetsAgent"
|
||||
| "productionAgent:directorPlanAgent"
|
||||
| "productionAgent:storyboardGenAgent"
|
||||
| "productionAgent:storyboardPanelAgent"
|
||||
| "productionAgent:storyboardTableAgent";
|
||||
|
||||
type FnName = "textRequest" | "imageRequest" | "videoRequest" | "ttsRequest";
|
||||
|
||||
const AiTypeValues: AiType[] = ["scriptAgent", "productionAgent", "universalAi"];
|
||||
const AiTypeValues: AiType[] = [
|
||||
"scriptAgent",
|
||||
"productionAgent",
|
||||
"universalAi",
|
||||
"scriptAgent:decisionAgent",
|
||||
"scriptAgent:supervisionAgent",
|
||||
"scriptAgent:storySkeletonAgent",
|
||||
"scriptAgent:adaptationStrategyAgent",
|
||||
"scriptAgent:scriptAgent",
|
||||
"productionAgent:decisionAgent",
|
||||
"productionAgent:supervisionAgent",
|
||||
"productionAgent:deriveAssetsAgent",
|
||||
"productionAgent:generateAssetsAgent",
|
||||
"productionAgent:directorPlanAgent",
|
||||
"productionAgent:storyboardGenAgent",
|
||||
"productionAgent:storyboardPanelAgent",
|
||||
"productionAgent:storyboardTableAgent",
|
||||
"universalAi",
|
||||
];
|
||||
async function resolveModelName(value: AiType | `${string}:${string}`): Promise<`${string}:${string}`> {
|
||||
if (AiTypeValues.includes(value as AiType)) {
|
||||
const agentDeployData = await u.db("o_agentDeploy").where("key", value).first();
|
||||
if (!agentDeployData?.modelName) throw new Error(`${value}模型未配置`);
|
||||
return agentDeployData.modelName as `${number}:${string}`;
|
||||
let modelName = null;
|
||||
if (!agentDeployData?.modelName) {
|
||||
const [mainly] = agentDeployData!.key!.split(/:(.+)/);
|
||||
const mainlyData = await u.db("o_agentDeploy").where("key", mainly).first();
|
||||
if (!mainlyData?.modelName) throw new Error(`未找到部署配置 ${value}`);
|
||||
modelName = mainlyData.modelName;
|
||||
}
|
||||
modelName = agentDeployData?.modelName || modelName;
|
||||
return modelName as `${number}:${string}`;
|
||||
}
|
||||
return value as `${number}:${string}`;
|
||||
}
|
||||
|
||||
async function getModelConfig(value: AiType | `${string}:${string}`) {
|
||||
if (AiTypeValues.includes(value as AiType)) {
|
||||
const agentDeployData = await u.db("o_agentDeploy").where("key", value).first();
|
||||
if (!agentDeployData?.modelName) {
|
||||
const [mainly] = agentDeployData!.key!.split(/:(.+)/);
|
||||
const mainlyData = await u.db("o_agentDeploy").where("key", mainly).first();
|
||||
if (!mainlyData?.modelName) throw new Error(`未找到部署配置 ${value}`);
|
||||
return mainlyData;
|
||||
}
|
||||
return agentDeployData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getVendorTemplateFn(
|
||||
fnName: "textRequest",
|
||||
modelName: `${string}:${string}`,
|
||||
@ -101,21 +157,26 @@ class AiText {
|
||||
return mws.length > 0 ? wrapLanguageModel({ model: baseModel, middleware: mws.length === 1 ? mws[0] : mws }) : baseModel;
|
||||
}
|
||||
async invoke(input: Omit<Parameters<typeof generateText>[0], "model">) {
|
||||
const config = await getModelConfig(this.AiType);
|
||||
console.log("%c Line:161 🥃 config", "background:#3f7cff", config);
|
||||
|
||||
return generateText({
|
||||
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
||||
...input,
|
||||
model: await this.resolveModel(),
|
||||
temperature: 2,
|
||||
...(config?.temperature && { temperature: config.temperature }),
|
||||
...(config?.maxOutputTokens && { maxOutputTokens: config.maxOutputTokens }),
|
||||
} as Parameters<typeof generateText>[0]);
|
||||
}
|
||||
async stream(input: Omit<Parameters<typeof streamText>[0], "model">) {
|
||||
const config = await getModelConfig(this.AiType);
|
||||
|
||||
return streamText({
|
||||
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
||||
...input,
|
||||
model: await this.resolveModel(extractReasoningMiddleware({ tagName: "reasoning_content", separator: "\n" })),
|
||||
topP: 1,
|
||||
temperature: 2,
|
||||
maxOutputTokens: 9999999999,
|
||||
...(config?.temperature && { temperature: config.temperature }),
|
||||
...(config?.maxOutputTokens && { maxOutputTokens: config.maxOutputTokens }),
|
||||
} as Parameters<typeof streamText>[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1338,10 +1338,10 @@ basic-auth@~2.0.1:
|
||||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
better-sqlite3@^12.8.0:
|
||||
version "12.8.0"
|
||||
resolved "https://registry.npmmirror.com/better-sqlite3/-/better-sqlite3-12.8.0.tgz#ec9ccd4a426a35f3b9355c147af6c92a6ddd6862"
|
||||
integrity sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==
|
||||
better-sqlite3@^12.9.0:
|
||||
version "12.9.0"
|
||||
resolved "https://registry.npmmirror.com/better-sqlite3/-/better-sqlite3-12.9.0.tgz#32498c99ba3fb36f604fbb5c70667c5f68c00414"
|
||||
integrity sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==
|
||||
dependencies:
|
||||
bindings "^1.5.0"
|
||||
prebuild-install "^7.1.1"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user