修正供应商,修正多余代码
This commit is contained in:
parent
493e9c2ef0
commit
4a5ac8732f
8
data/vendor/volcengine.ts
vendored
8
data/vendor/volcengine.ts
vendored
@ -133,7 +133,7 @@ declare const exports: {
|
|||||||
|
|
||||||
const vendor: VendorConfig = {
|
const vendor: VendorConfig = {
|
||||||
id: "volcengine",
|
id: "volcengine",
|
||||||
version: "2.1",
|
version: "2.2",
|
||||||
author: "leeqi",
|
author: "leeqi",
|
||||||
name: "火山引擎(豆包)",
|
name: "火山引擎(豆包)",
|
||||||
description:
|
description:
|
||||||
@ -301,10 +301,10 @@ const textRequest = (model: TextModel, think: boolean, thinkLevel: 0 | 1 | 2 | 3
|
|||||||
3: "high",
|
3: "high",
|
||||||
};
|
};
|
||||||
|
|
||||||
return createOpenAI({
|
return createOpenAICompatible({
|
||||||
|
name: "volcengine",
|
||||||
baseURL: getBaseUrl(),
|
baseURL: getBaseUrl(),
|
||||||
apiKey,
|
apiKey,
|
||||||
compatibility: "compatible",
|
|
||||||
fetch: async (url: string, options?: RequestInit) => {
|
fetch: async (url: string, options?: RequestInit) => {
|
||||||
const rawBody = JSON.parse((options?.body as string) ?? "{}");
|
const rawBody = JSON.parse((options?.body as string) ?? "{}");
|
||||||
const modifiedBody = {
|
const modifiedBody = {
|
||||||
@ -319,7 +319,7 @@ const textRequest = (model: TextModel, think: boolean, thinkLevel: 0 | 1 | 2 | 3
|
|||||||
body: JSON.stringify(modifiedBody),
|
body: JSON.stringify(modifiedBody),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}).chat(model.modelName);
|
}).chatModel(model.modelName);
|
||||||
};
|
};
|
||||||
|
|
||||||
const imageRequest = async (config: ImageConfig, model: ImageModel): Promise<string> => {
|
const imageRequest = async (config: ImageConfig, model: ImageModel): Promise<string> => {
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
1.1.3
|
1.1.4
|
||||||
@ -99,4 +99,4 @@
|
|||||||
"better-sqlite3": "^12.8.0"
|
"better-sqlite3": "^12.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,11 @@ export interface AgentContext {
|
|||||||
abortSignal?: AbortSignal;
|
abortSignal?: AbortSignal;
|
||||||
resTool: ResTool;
|
resTool: ResTool;
|
||||||
msg: ReturnType<ResTool["newMessage"]>;
|
msg: ReturnType<ResTool["newMessage"]>;
|
||||||
|
messages?: { role: "user" | "assistant" | "system"; content: string }[];
|
||||||
|
thinkConfig: {
|
||||||
|
think: boolean;
|
||||||
|
thinlLevel: 0 | 1 | 2 | 3;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
||||||
@ -35,7 +40,7 @@ function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
|||||||
return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`;
|
return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function decisionAI(ctx: AgentContext) {
|
export async function runDecisionAI(ctx: AgentContext) {
|
||||||
const { isolationKey, text, abortSignal } = ctx;
|
const { isolationKey, text, abortSignal } = ctx;
|
||||||
const memory = new Memory("productionAgent", isolationKey);
|
const memory = new Memory("productionAgent", isolationKey);
|
||||||
await memory.add("user", text);
|
await memory.add("user", text);
|
||||||
@ -45,17 +50,17 @@ export async function decisionAI(ctx: AgentContext) {
|
|||||||
|
|
||||||
const projectInfo = await u.db("o_project").where("id", ctx.resTool.data.projectId).first();
|
const projectInfo = await u.db("o_project").where("id", ctx.resTool.data.projectId).first();
|
||||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${ctx.resTool.data.projectId}`);
|
if (!projectInfo) throw new Error(`项目不存在,ID: ${ctx.resTool.data.projectId}`);
|
||||||
const [_, imageModelName] = projectInfo.imageModel!.split(":");
|
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/)
|
||||||
const [id, videoModelName] = projectInfo.videoModel!.split(":");
|
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/)
|
||||||
const models = await u.vendor.getModelList(id);
|
const models = await u.vendor.getModelList(id);
|
||||||
if(!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
if (!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
||||||
const findData = models.find((i: any) => i.modelName == videoModelName);
|
const findData = models.find((i: any) => i.modelName == videoModelName);
|
||||||
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
||||||
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
||||||
|
|
||||||
const mem = buildMemPrompt(await memory.get(text));
|
const mem = buildMemPrompt(await memory.get(text));
|
||||||
|
|
||||||
const { textStream } = await u.Ai.Text("productionAgent").stream({
|
const { fullStream } = await u.Ai.Text("productionAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: prompt },
|
{ role: "system", content: prompt },
|
||||||
{ role: "assistant", content: mem + "\n" + modelInfo },
|
{ role: "assistant", content: mem + "\n" + modelInfo },
|
||||||
@ -72,7 +77,13 @@ export async function decisionAI(ctx: AgentContext) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return textStream;
|
let currentMsg = ctx.msg;
|
||||||
|
await consumeFullStream(fullStream, currentMsg, () => {
|
||||||
|
if (ctx.msg === currentMsg) return currentMsg;
|
||||||
|
currentMsg.complete();
|
||||||
|
currentMsg = ctx.msg;
|
||||||
|
return currentMsg;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createSubAgent(parentCtx: AgentContext) {
|
async function createSubAgent(parentCtx: AgentContext) {
|
||||||
@ -95,29 +106,15 @@ async function createSubAgent(parentCtx: AgentContext) {
|
|||||||
}) {
|
}) {
|
||||||
parentCtx.msg.complete();
|
parentCtx.msg.complete();
|
||||||
const subMsg = resTool.newMessage("assistant", name);
|
const subMsg = resTool.newMessage("assistant", name);
|
||||||
const text = subMsg.text();
|
|
||||||
let fullResponse = "";
|
|
||||||
|
|
||||||
const { textStream } = await u.Ai.Text("productionAgent").stream({
|
const { fullStream } = await u.Ai.Text("productionAgent", parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel).stream({
|
||||||
system,
|
system,
|
||||||
messages: messages ?? [{ role: "user", content: prompt }],
|
messages: messages ?? [{ role: "user", content: prompt }],
|
||||||
abortSignal,
|
abortSignal,
|
||||||
tools: { ...extraTools, ...useTools({ resTool, msg: subMsg }) },
|
tools: { ...extraTools, ...useTools({ resTool, msg: subMsg }) },
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
const fullResponse = await consumeFullStream(fullStream, subMsg);
|
||||||
for await (const chunk of textStream) {
|
|
||||||
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
|
||||||
text.append(chunk);
|
|
||||||
fullResponse += chunk;
|
|
||||||
}
|
|
||||||
text.complete();
|
|
||||||
subMsg.complete();
|
|
||||||
} catch (err: any) {
|
|
||||||
text.complete();
|
|
||||||
subMsg.stop();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullResponse.trim()) {
|
if (fullResponse.trim()) {
|
||||||
await memory.add(memoryKey, removeAllXmlTags(fullResponse), {
|
await memory.add(memoryKey, removeAllXmlTags(fullResponse), {
|
||||||
@ -138,10 +135,10 @@ async function createSubAgent(parentCtx: AgentContext) {
|
|||||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`);
|
if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`);
|
||||||
const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!);
|
const artSkills = await createArtSkills(projectInfo?.artStyle!, projectInfo?.directorManual!);
|
||||||
|
|
||||||
const [_, imageModelName] = projectInfo.imageModel!.split(":");
|
const [_, imageModelName] = projectInfo.imageModel!.split(/:(.+)/)
|
||||||
const [id, videoModelName] = projectInfo.videoModel!.split(":");
|
const [id, videoModelName] = projectInfo.videoModel!.split(/:(.+)/)
|
||||||
const models = await u.vendor.getModelList(id);
|
const models = await u.vendor.getModelList(id);
|
||||||
if(!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
if (!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`);
|
||||||
const findData = models.find((i: any) => i.modelName == videoModelName);
|
const findData = models.find((i: any) => i.modelName == videoModelName);
|
||||||
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
||||||
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
||||||
@ -370,7 +367,53 @@ ${buildSkillPrompt(mainSkills)}`,
|
|||||||
};
|
};
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
async function consumeFullStream(
|
||||||
|
fullStream: AsyncIterable<any>,
|
||||||
|
initialMsg: ReturnType<ResTool["newMessage"]>,
|
||||||
|
syncMsg?: () => ReturnType<ResTool["newMessage"]>,
|
||||||
|
): Promise<string> {
|
||||||
|
let msg = initialMsg;
|
||||||
|
let text = msg.text();
|
||||||
|
let thinking: ReturnType<typeof msg.thinking> | null = null;
|
||||||
|
let thinkTime = 0;
|
||||||
|
let fullResponse = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
for await (const chunk of fullStream) {
|
||||||
|
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
||||||
|
if (syncMsg) {
|
||||||
|
const newMsg = syncMsg();
|
||||||
|
if (newMsg !== msg) {
|
||||||
|
msg = newMsg;
|
||||||
|
text = msg.text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunk.type === "reasoning-start") {
|
||||||
|
thinkTime = Date.now();
|
||||||
|
thinking = msg.thinking("思考中...");
|
||||||
|
} else if (chunk.type === "reasoning-delta") {
|
||||||
|
thinking?.append(chunk.text);
|
||||||
|
} else if (chunk.type === "reasoning-end") {
|
||||||
|
thinkTime = Date.now() - thinkTime;
|
||||||
|
thinking?.updateTitle(`思考完毕(${(thinkTime / 1000).toFixed(1)} 秒)`);
|
||||||
|
thinking?.complete();
|
||||||
|
thinking = null;
|
||||||
|
} else if (chunk.type === "text-delta") {
|
||||||
|
text.append(chunk.text);
|
||||||
|
fullResponse += chunk.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text.complete();
|
||||||
|
msg.complete();
|
||||||
|
} catch (err: any) {
|
||||||
|
thinking?.complete();
|
||||||
|
text.complete();
|
||||||
|
msg.stop();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullResponse;
|
||||||
|
}
|
||||||
function removeAllXmlTags(text: string): string {
|
function removeAllXmlTags(text: string): string {
|
||||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, "");
|
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, "");
|
||||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, "");
|
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, "");
|
||||||
|
|||||||
@ -16,6 +16,10 @@ export interface AgentContext {
|
|||||||
abortSignal?: AbortSignal;
|
abortSignal?: AbortSignal;
|
||||||
resTool: ResTool;
|
resTool: ResTool;
|
||||||
msg: ReturnType<ResTool["newMessage"]>;
|
msg: ReturnType<ResTool["newMessage"]>;
|
||||||
|
thinkConfig: {
|
||||||
|
think: boolean;
|
||||||
|
thinlLevel: 0 | 1 | 2 | 3;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
||||||
@ -34,7 +38,7 @@ function buildMemPrompt(mem: Awaited<ReturnType<Memory["get"]>>): string {
|
|||||||
return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`;
|
return `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function decisionAI(ctx: AgentContext) {
|
export async function runDecisionAI(ctx: AgentContext) {
|
||||||
const { isolationKey, text, userMessageTime, abortSignal, resTool } = ctx;
|
const { isolationKey, text, userMessageTime, abortSignal, resTool } = ctx;
|
||||||
|
|
||||||
const memory = new Memory("scriptAgent", isolationKey);
|
const memory = new Memory("scriptAgent", isolationKey);
|
||||||
@ -59,7 +63,7 @@ export async function decisionAI(ctx: AgentContext) {
|
|||||||
`章节数量:${novelData.length}章`,
|
`章节数量:${novelData.length}章`,
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
const { textStream } = await u.Ai.Text("scriptAgent").stream({
|
const { fullStream } = await u.Ai.Text("scriptAgent", ctx.thinkConfig.think, ctx.thinkConfig.thinlLevel).stream({
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: prompt },
|
{ role: "system", content: prompt },
|
||||||
{ role: "assistant", content: projectInfo + "\n" + mem },
|
{ role: "assistant", content: projectInfo + "\n" + mem },
|
||||||
@ -76,7 +80,13 @@ export async function decisionAI(ctx: AgentContext) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return textStream;
|
let currentMsg = ctx.msg;
|
||||||
|
await consumeFullStream(fullStream, currentMsg, () => {
|
||||||
|
if (ctx.msg === currentMsg) return currentMsg;
|
||||||
|
currentMsg.complete();
|
||||||
|
currentMsg = ctx.msg;
|
||||||
|
return currentMsg;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSubAgent(parentCtx: AgentContext) {
|
function createSubAgent(parentCtx: AgentContext) {
|
||||||
@ -100,29 +110,15 @@ function createSubAgent(parentCtx: AgentContext) {
|
|||||||
}) {
|
}) {
|
||||||
parentCtx.msg.complete();
|
parentCtx.msg.complete();
|
||||||
const subMsg = resTool.newMessage("assistant", name);
|
const subMsg = resTool.newMessage("assistant", name);
|
||||||
const text = subMsg.text();
|
|
||||||
let fullResponse = "";
|
|
||||||
|
|
||||||
const { textStream } = await u.Ai.Text("scriptAgent").stream({
|
const { fullStream } = await u.Ai.Text("scriptAgent", parentCtx.thinkConfig.think, parentCtx.thinkConfig.thinlLevel ).stream({
|
||||||
system,
|
system,
|
||||||
messages: messages ?? [{ role: "user", content: prompt }],
|
messages: messages ?? [{ role: "user", content: prompt }],
|
||||||
abortSignal,
|
abortSignal,
|
||||||
tools: { ...extraTools, ...useTools({ resTool, msg: subMsg }) },
|
tools: { ...extraTools, ...useTools({ resTool, msg: subMsg }) },
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
const fullResponse = await consumeFullStream(fullStream, subMsg);
|
||||||
for await (const chunk of textStream) {
|
|
||||||
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
|
||||||
text.append(chunk);
|
|
||||||
fullResponse += chunk;
|
|
||||||
}
|
|
||||||
text.complete();
|
|
||||||
subMsg.complete();
|
|
||||||
} catch (err: any) {
|
|
||||||
text.complete();
|
|
||||||
subMsg.stop();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullResponse.trim()) {
|
if (fullResponse.trim()) {
|
||||||
await memory.add(memoryKey, removeAllXmlTags(fullResponse), {
|
await memory.add(memoryKey, removeAllXmlTags(fullResponse), {
|
||||||
@ -230,6 +226,54 @@ function createSubAgent(parentCtx: AgentContext) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function consumeFullStream(
|
||||||
|
fullStream: AsyncIterable<any>,
|
||||||
|
initialMsg: ReturnType<ResTool["newMessage"]>,
|
||||||
|
syncMsg?: () => ReturnType<ResTool["newMessage"]>,
|
||||||
|
): Promise<string> {
|
||||||
|
let msg = initialMsg;
|
||||||
|
let text = msg.text();
|
||||||
|
let thinking: ReturnType<typeof msg.thinking> | null = null;
|
||||||
|
let thinkTime = 0;
|
||||||
|
let fullResponse = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
for await (const chunk of fullStream) {
|
||||||
|
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
||||||
|
if (syncMsg) {
|
||||||
|
const newMsg = syncMsg();
|
||||||
|
if (newMsg !== msg) {
|
||||||
|
msg = newMsg;
|
||||||
|
text = msg.text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunk.type === "reasoning-start") {
|
||||||
|
thinkTime = Date.now();
|
||||||
|
thinking = msg.thinking("思考中...");
|
||||||
|
} else if (chunk.type === "reasoning-delta") {
|
||||||
|
thinking?.append(chunk.text);
|
||||||
|
} else if (chunk.type === "reasoning-end") {
|
||||||
|
thinkTime = Date.now() - thinkTime;
|
||||||
|
thinking?.updateTitle(`思考完毕(${(thinkTime / 1000).toFixed(1)} 秒)`);
|
||||||
|
thinking?.complete();
|
||||||
|
thinking = null;
|
||||||
|
} else if (chunk.type === "text-delta") {
|
||||||
|
text.append(chunk.text);
|
||||||
|
fullResponse += chunk.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text.complete();
|
||||||
|
msg.complete();
|
||||||
|
} catch (err: any) {
|
||||||
|
thinking?.complete();
|
||||||
|
text.complete();
|
||||||
|
msg.stop();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullResponse;
|
||||||
|
}
|
||||||
|
|
||||||
function removeAllXmlTags(text: string): string {
|
function removeAllXmlTags(text: string): string {
|
||||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, "");
|
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, "");
|
||||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, "");
|
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, "");
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -261,29 +261,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
|||||||
table.unique(["id"]);
|
table.unique(["id"]);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
//大纲表
|
|
||||||
{
|
|
||||||
name: "o_outline",
|
|
||||||
builder: (table) => {
|
|
||||||
table.integer("id").notNullable();
|
|
||||||
table.integer("episode");
|
|
||||||
table.text("data");
|
|
||||||
table.integer("projectId");
|
|
||||||
table.primary(["id"]);
|
|
||||||
table.unique(["id"]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//大纲-原文表
|
|
||||||
{
|
|
||||||
name: "o_outlineNovel",
|
|
||||||
builder: (table) => {
|
|
||||||
table.integer("id").notNullable();
|
|
||||||
table.integer("outlineId").unsigned().references("id").inTable("o_outline");
|
|
||||||
table.integer("novelId").unsigned().references("id").inTable("o_novel");
|
|
||||||
table.primary(["id"]);
|
|
||||||
table.unique(["id"]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//剧本
|
//剧本
|
||||||
{
|
{
|
||||||
name: "o_script",
|
name: "o_script",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// @routes-hash 62534cff632db5d31442f1bca1932925
|
// @routes-hash 4d6cbfaad479bdfafe13bc61e7550f55
|
||||||
import { Express } from "express";
|
import { Express } from "express";
|
||||||
|
|
||||||
import route1 from "./routes/agents/clearMemory";
|
import route1 from "./routes/agents/clearMemory";
|
||||||
@ -34,22 +34,22 @@ import route30 from "./routes/general/generalStatistics";
|
|||||||
import route31 from "./routes/general/getSingleProject";
|
import route31 from "./routes/general/getSingleProject";
|
||||||
import route32 from "./routes/general/updateProject";
|
import route32 from "./routes/general/updateProject";
|
||||||
import route33 from "./routes/login/login";
|
import route33 from "./routes/login/login";
|
||||||
import route34 from "./routes/migrate/migrateData";
|
import route34 from "./routes/modelSelect/getModelDetail";
|
||||||
import route35 from "./routes/modelSelect/getModelDetail";
|
import route35 from "./routes/modelSelect/getModelList";
|
||||||
import route36 from "./routes/modelSelect/getModelList";
|
import route36 from "./routes/novel/addNovel";
|
||||||
import route37 from "./routes/novel/addNovel";
|
import route37 from "./routes/novel/batchDeleteNovel";
|
||||||
import route38 from "./routes/novel/batchDeleteNovel";
|
import route38 from "./routes/novel/delNovel";
|
||||||
import route39 from "./routes/novel/delNovel";
|
import route39 from "./routes/novel/event/batchDeleteEvent";
|
||||||
import route40 from "./routes/novel/event/batchDeleteEvent";
|
import route40 from "./routes/novel/event/deletEvent";
|
||||||
import route41 from "./routes/novel/event/deletEvent";
|
import route41 from "./routes/novel/event/generateEvents";
|
||||||
import route42 from "./routes/novel/event/generateEvents";
|
import route42 from "./routes/novel/event/getEvent";
|
||||||
import route43 from "./routes/novel/event/getEvent";
|
import route43 from "./routes/novel/getNovel";
|
||||||
import route44 from "./routes/novel/getNovel";
|
import route44 from "./routes/novel/getNovelData";
|
||||||
import route45 from "./routes/novel/getNovelData";
|
import route45 from "./routes/novel/getNovelEventState";
|
||||||
import route46 from "./routes/novel/getNovelEventState";
|
import route46 from "./routes/novel/getNovelIndex";
|
||||||
import route47 from "./routes/novel/getNovelIndex";
|
import route47 from "./routes/novel/updateNovel";
|
||||||
import route48 from "./routes/novel/updateNovel";
|
import route48 from "./routes/other/deleteAllData";
|
||||||
import route49 from "./routes/other/deleteAllData";
|
import route49 from "./routes/other/getModelDetails";
|
||||||
import route50 from "./routes/other/getVersion";
|
import route50 from "./routes/other/getVersion";
|
||||||
import route51 from "./routes/production/assets/batchGenerateAssetsImage";
|
import route51 from "./routes/production/assets/batchGenerateAssetsImage";
|
||||||
import route52 from "./routes/production/assets/deleteAssetsDireve";
|
import route52 from "./routes/production/assets/deleteAssetsDireve";
|
||||||
@ -179,22 +179,22 @@ export default async (app: Express) => {
|
|||||||
app.use("/api/general/getSingleProject", route31);
|
app.use("/api/general/getSingleProject", route31);
|
||||||
app.use("/api/general/updateProject", route32);
|
app.use("/api/general/updateProject", route32);
|
||||||
app.use("/api/login/login", route33);
|
app.use("/api/login/login", route33);
|
||||||
app.use("/api/migrate/migrateData", route34);
|
app.use("/api/modelSelect/getModelDetail", route34);
|
||||||
app.use("/api/modelSelect/getModelDetail", route35);
|
app.use("/api/modelSelect/getModelList", route35);
|
||||||
app.use("/api/modelSelect/getModelList", route36);
|
app.use("/api/novel/addNovel", route36);
|
||||||
app.use("/api/novel/addNovel", route37);
|
app.use("/api/novel/batchDeleteNovel", route37);
|
||||||
app.use("/api/novel/batchDeleteNovel", route38);
|
app.use("/api/novel/delNovel", route38);
|
||||||
app.use("/api/novel/delNovel", route39);
|
app.use("/api/novel/event/batchDeleteEvent", route39);
|
||||||
app.use("/api/novel/event/batchDeleteEvent", route40);
|
app.use("/api/novel/event/deletEvent", route40);
|
||||||
app.use("/api/novel/event/deletEvent", route41);
|
app.use("/api/novel/event/generateEvents", route41);
|
||||||
app.use("/api/novel/event/generateEvents", route42);
|
app.use("/api/novel/event/getEvent", route42);
|
||||||
app.use("/api/novel/event/getEvent", route43);
|
app.use("/api/novel/getNovel", route43);
|
||||||
app.use("/api/novel/getNovel", route44);
|
app.use("/api/novel/getNovelData", route44);
|
||||||
app.use("/api/novel/getNovelData", route45);
|
app.use("/api/novel/getNovelEventState", route45);
|
||||||
app.use("/api/novel/getNovelEventState", route46);
|
app.use("/api/novel/getNovelIndex", route46);
|
||||||
app.use("/api/novel/getNovelIndex", route47);
|
app.use("/api/novel/updateNovel", route47);
|
||||||
app.use("/api/novel/updateNovel", route48);
|
app.use("/api/other/deleteAllData", route48);
|
||||||
app.use("/api/other/deleteAllData", route49);
|
app.use("/api/other/getModelDetails", route49);
|
||||||
app.use("/api/other/getVersion", route50);
|
app.use("/api/other/getVersion", route50);
|
||||||
app.use("/api/production/assets/batchGenerateAssetsImage", route51);
|
app.use("/api/production/assets/batchGenerateAssetsImage", route51);
|
||||||
app.use("/api/production/assets/deleteAssetsDireve", route52);
|
app.use("/api/production/assets/deleteAssetsDireve", route52);
|
||||||
|
|||||||
@ -27,22 +27,6 @@ interface NovelChapter {
|
|||||||
|
|
||||||
type ItemType = "characters" | "props" | "scenes";
|
type ItemType = "characters" | "props" | "scenes";
|
||||||
|
|
||||||
interface ResultItem {
|
|
||||||
type: ItemType;
|
|
||||||
name: string;
|
|
||||||
chapterRange: number[];
|
|
||||||
}
|
|
||||||
function findItemByName(items: ResultItem[], name: string, type?: ItemType): ResultItem | undefined {
|
|
||||||
return items.find((item) => (!type || item.type === type) && item.name === name);
|
|
||||||
}
|
|
||||||
function mergeNovelText(novelData: NovelChapter[]): string {
|
|
||||||
if (!Array.isArray(novelData)) return "";
|
|
||||||
return novelData
|
|
||||||
.map((chap) => {
|
|
||||||
return `${chap.chapter.trim()}\n\n${chap.chapterData.trim().replace(/\r?\n/g, "\n")}\n`;
|
|
||||||
})
|
|
||||||
.join("\n");
|
|
||||||
}
|
|
||||||
//润色提示词
|
//润色提示词
|
||||||
export default router.post(
|
export default router.post(
|
||||||
"/",
|
"/",
|
||||||
@ -66,23 +50,6 @@ export default router.post(
|
|||||||
if (!project) return res.status(500).send(success({ message: "项目为空" }));
|
if (!project) return res.status(500).send(success({ message: "项目为空" }));
|
||||||
|
|
||||||
// 预加载公共数据
|
// 预加载公共数据
|
||||||
const allOutlineDataList: { data: string }[] = await u.db("o_outline").where("projectId", projectId).select("data");
|
|
||||||
const itemMap: Record<string, ResultItem> = {};
|
|
||||||
if (allOutlineDataList.length > 0)
|
|
||||||
allOutlineDataList.forEach((row) => {
|
|
||||||
const data: OutlineData = JSON.parse(row?.data || "{}");
|
|
||||||
(["characters", "props", "scenes"] as ItemType[]).forEach((type) => {
|
|
||||||
(data[type] || []).forEach((item) => {
|
|
||||||
const key = `${type}-${item.name}`;
|
|
||||||
if (!itemMap[key]) {
|
|
||||||
itemMap[key] = { type, name: item.name, chapterRange: [...(data.chapterRange || [])] };
|
|
||||||
} else {
|
|
||||||
itemMap[key].chapterRange = Array.from(new Set([...itemMap[key].chapterRange, ...(data.chapterRange || [])]));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const result: ResultItem[] = Object.values(itemMap);
|
|
||||||
const assetsIds = items.map((item: { assetsId: number }) => item.assetsId);
|
const assetsIds = items.map((item: { assetsId: number }) => item.assetsId);
|
||||||
//查询所有资产,用于判断每个资产是否是衍生资产
|
//查询所有资产,用于判断每个资产是否是衍生资产
|
||||||
const assetsDataList = await u.db("o_assets").whereIn("id", assetsIds).select("id", "assetsId");
|
const assetsDataList = await u.db("o_assets").whereIn("id", assetsIds).select("id", "assetsId");
|
||||||
@ -132,7 +99,6 @@ export default router.post(
|
|||||||
await u.db("o_assets").where("id", item.assetsId).update({ promptState: "生成失败", promptErrorReason: "视觉手册未定义" });
|
await u.db("o_assets").where("id", item.assetsId).update({ promptState: "生成失败", promptErrorReason: "视觉手册未定义" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
findItemByName(result, item.name, config.itemType);
|
|
||||||
const systemPrompt = visualManual;
|
const systemPrompt = visualManual;
|
||||||
try {
|
try {
|
||||||
const { _output } = (await u.Ai.Text("universalAi").invoke({
|
const { _output } = (await u.Ai.Text("universalAi").invoke({
|
||||||
|
|||||||
@ -4,36 +4,10 @@ import * as zod from "zod";
|
|||||||
import { error, success } from "@/lib/responseFormat";
|
import { error, success } from "@/lib/responseFormat";
|
||||||
import { validateFields } from "@/middleware/middleware";
|
import { validateFields } from "@/middleware/middleware";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
interface OutlineItem {
|
|
||||||
description: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OutlineData {
|
|
||||||
chapterRange: number[];
|
|
||||||
characters?: OutlineItem[];
|
|
||||||
props?: OutlineItem[];
|
|
||||||
scenes?: OutlineItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NovelChapter {
|
|
||||||
id: number;
|
|
||||||
reel: string;
|
|
||||||
chapter: string;
|
|
||||||
chapterData: string;
|
|
||||||
projectId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ItemType = "characters" | "props" | "scenes";
|
type ItemType = "characters" | "props" | "scenes";
|
||||||
|
|
||||||
interface ResultItem {
|
|
||||||
type: ItemType;
|
|
||||||
name: string;
|
|
||||||
chapterRange: number[];
|
|
||||||
}
|
|
||||||
function findItemByName(items: ResultItem[], name: string, type?: ItemType): ResultItem | undefined {
|
|
||||||
return items.find((item) => (!type || item.type === type) && item.name === name);
|
|
||||||
}
|
|
||||||
//润色提示词
|
//润色提示词
|
||||||
export default router.post(
|
export default router.post(
|
||||||
"/",
|
"/",
|
||||||
@ -51,31 +25,8 @@ export default router.post(
|
|||||||
//如果没有找到对应的项目,返回错误
|
//如果没有找到对应的项目,返回错误
|
||||||
if (!project) return res.status(500).send(success({ message: "项目为空" }));
|
if (!project) return res.status(500).send(success({ message: "项目为空" }));
|
||||||
|
|
||||||
const allOutlineDataList: { data: string }[] = await u.db("o_outline").where("projectId", projectId).select("data");
|
|
||||||
await u.db("o_assets").where("id", assetsId).update({ promptState: "生成中" });
|
await u.db("o_assets").where("id", assetsId).update({ promptState: "生成中" });
|
||||||
|
|
||||||
const itemMap: Record<string, ResultItem> = {};
|
|
||||||
|
|
||||||
if (allOutlineDataList.length > 0)
|
|
||||||
allOutlineDataList.forEach((row) => {
|
|
||||||
const data: OutlineData = JSON.parse(row?.data || "{}");
|
|
||||||
(["characters", "props", "scenes"] as ItemType[]).forEach((type) => {
|
|
||||||
(data[type] || []).forEach((item) => {
|
|
||||||
const key = `${type}-${item.name}`;
|
|
||||||
if (!itemMap[key]) {
|
|
||||||
itemMap[key] = {
|
|
||||||
type,
|
|
||||||
name: item.name,
|
|
||||||
chapterRange: [...(data.chapterRange || [])],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
itemMap[key].chapterRange = Array.from(new Set([...itemMap[key].chapterRange, ...(data.chapterRange || [])]));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const result: ResultItem[] = Object.values(itemMap);
|
|
||||||
//查询资产是否是衍生资产
|
//查询资产是否是衍生资产
|
||||||
const assetsData = await u.db("o_assets").where("id", assetsId).select("assetsId").first();
|
const assetsData = await u.db("o_assets").where("id", assetsId).select("assetsId").first();
|
||||||
if (!assetsData) return { code: 500, message: "资产不存在" };
|
if (!assetsData) return { code: 500, message: "资产不存在" };
|
||||||
@ -109,7 +60,6 @@ export default router.post(
|
|||||||
//获取到视觉手册
|
//获取到视觉手册
|
||||||
const visualManual = await u.getArtPrompt(project.artStyle as string, "art_skills", config.visualManual);
|
const visualManual = await u.getArtPrompt(project.artStyle as string, "art_skills", config.visualManual);
|
||||||
if (!visualManual) return res.status(500).send(error("视觉手册未定义"));
|
if (!visualManual) return res.status(500).send(error("视觉手册未定义"));
|
||||||
findItemByName(result, name, config.itemType);
|
|
||||||
const systemPrompt = visualManual;
|
const systemPrompt = visualManual;
|
||||||
try {
|
try {
|
||||||
const { _output } = (await u.Ai.Text("universalAi").invoke({
|
const { _output } = (await u.Ai.Text("universalAi").invoke({
|
||||||
|
|||||||
@ -1,133 +0,0 @@
|
|||||||
import express from "express";
|
|
||||||
import { success } from "@/lib/responseFormat";
|
|
||||||
import db from "@/utils/db";
|
|
||||||
import type { DB } from "@/types/database";
|
|
||||||
import knex from "knex";
|
|
||||||
import path from "path";
|
|
||||||
import fs from "fs";
|
|
||||||
import { tr } from "zod/locales";
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
// 迁移数据
|
|
||||||
export default router.post(
|
|
||||||
"/",
|
|
||||||
async (req, res) => {
|
|
||||||
// return res.status(200).send({
|
|
||||||
// success: true,
|
|
||||||
// message: '数据迁移功能已关闭,建议手动迁移数据后删除旧数据库文件'
|
|
||||||
// });
|
|
||||||
//连接旧数据库,读取数据
|
|
||||||
try {
|
|
||||||
let db2: knex.Knex | null = null;
|
|
||||||
//读取旧数据库路径
|
|
||||||
let db2Path: string;
|
|
||||||
if (typeof process.versions?.electron !== "undefined") {
|
|
||||||
const { app } = require("electron");
|
|
||||||
const userDataDir: string = app.getPath("userData");
|
|
||||||
db2Path = path.join(userDataDir, "db2.sqlite");
|
|
||||||
} else {
|
|
||||||
db2Path = path.join(process.cwd(), "db2.sqlite");
|
|
||||||
}
|
|
||||||
const dbDir = path.dirname(db2Path);
|
|
||||||
// 确保数据库目录存在
|
|
||||||
if (!fs.existsSync(dbDir)) {
|
|
||||||
fs.mkdirSync(dbDir, { recursive: true });
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(db2Path)) {
|
|
||||||
return res.status(404).send({
|
|
||||||
success: false,
|
|
||||||
message: `源数据库文件不存在: ${db2Path}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//连接旧数据库
|
|
||||||
db2 = knex({
|
|
||||||
client: "better-sqlite3",
|
|
||||||
connection: {
|
|
||||||
filename: db2Path,
|
|
||||||
},
|
|
||||||
useNullAsDefault: true,
|
|
||||||
});
|
|
||||||
//需要迁移的旧数据表
|
|
||||||
const db2TableNames = [
|
|
||||||
't_project',
|
|
||||||
't_assets',
|
|
||||||
't_event',
|
|
||||||
't_image',
|
|
||||||
't_novel',
|
|
||||||
't_outline',
|
|
||||||
't_script',
|
|
||||||
't_storyboard',
|
|
||||||
't_video',
|
|
||||||
]
|
|
||||||
//新数据库的表
|
|
||||||
const dbTableNames = [
|
|
||||||
'o_project',
|
|
||||||
'o_assets',
|
|
||||||
'o_event',
|
|
||||||
'o_eventChapter',
|
|
||||||
'o_image',
|
|
||||||
'o_novel',
|
|
||||||
'o_outline',
|
|
||||||
'o_outlineNovel',
|
|
||||||
'o_script',
|
|
||||||
'o_scriptAssets',
|
|
||||||
'o_scriptOutline',
|
|
||||||
'o_storyboard',
|
|
||||||
'o_storyboardScript',
|
|
||||||
'o_video',
|
|
||||||
]
|
|
||||||
|
|
||||||
for (const tableName of db2TableNames) {
|
|
||||||
try {
|
|
||||||
// 从 db2 读取数据
|
|
||||||
const sourceData = await db2(tableName).select('*');
|
|
||||||
for (const item of sourceData) {
|
|
||||||
//迁移项目表
|
|
||||||
if (tableName === 't_project') {
|
|
||||||
// await db("o_project").insert({
|
|
||||||
// name: item.name,
|
|
||||||
// intro: item.intro,
|
|
||||||
// type: item.type,
|
|
||||||
// artStyle: item.artStyle,
|
|
||||||
// videoRatio: item.videoRatio,
|
|
||||||
// createTime: item.createTime,
|
|
||||||
// userId: item.userId,
|
|
||||||
// projectType: "基于小说原文"
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
//迁移资产表
|
|
||||||
if (tableName === 't_assets') {
|
|
||||||
}
|
|
||||||
//迁移事件表
|
|
||||||
if (tableName === 't_event') { }
|
|
||||||
//迁移图片表
|
|
||||||
if (tableName === 't_image') { }
|
|
||||||
//迁移小说表
|
|
||||||
if (tableName === 't_novel') { }
|
|
||||||
//迁移大纲表
|
|
||||||
if (tableName === 't_outline') { }
|
|
||||||
//迁移脚本表
|
|
||||||
if (tableName === 't_script') { }
|
|
||||||
//迁移分镜面板
|
|
||||||
if (tableName === 't_storyboard') { }
|
|
||||||
//迁移视频表
|
|
||||||
if (tableName === 't_video') { }
|
|
||||||
}
|
|
||||||
// // 将数据插入到 db 中
|
|
||||||
// const targetTableName = dbTableNames[db2TableNames.indexOf(tableName)];
|
|
||||||
// await db(targetTableName).insert(sourceData);
|
|
||||||
// console.log(`成功迁移表 ${tableName} 的数据到 ${targetTableName}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`连接旧数据库失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('连接旧数据库失败:', error);
|
|
||||||
}
|
|
||||||
return res.status(200).send({
|
|
||||||
success: true,
|
|
||||||
message: '数据迁移功能已关闭,建议手动迁移数据后删除旧数据库文件'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@ -12,7 +12,7 @@ export default router.post(
|
|||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { modelId } = req.body;
|
const { modelId } = req.body;
|
||||||
const [id, name] = modelId.split(":");
|
const [id, name] = modelId.split(/:(.+)/);
|
||||||
const models = await u.vendor.getModelList(id);
|
const models = await u.vendor.getModelList(id);
|
||||||
const findData = models.find((i: any) => i.modelName == name);
|
const findData = models.find((i: any) => i.modelName == name);
|
||||||
res.status(200).send(success(findData));
|
res.status(200).send(success(findData));
|
||||||
|
|||||||
21
src/routes/other/getModelDetails.ts
Normal file
21
src/routes/other/getModelDetails.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import express from "express";
|
||||||
|
import { success, error } from "@/lib/responseFormat";
|
||||||
|
import u from "@/utils";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { validateFields } from "@/middleware/middleware";
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
export default router.post(
|
||||||
|
"/",
|
||||||
|
validateFields({
|
||||||
|
key: z.string().optional(),
|
||||||
|
}),
|
||||||
|
async (req, res) => {
|
||||||
|
const { key } = req.body;
|
||||||
|
const [id, modelName] = key ? key.split(":") : [];
|
||||||
|
const models = await u.vendor.getModelList(id);
|
||||||
|
const model = models.find((m) => m.modelName === modelName);
|
||||||
|
if (!model) return res.status(400).send(error("未找到模型"));
|
||||||
|
res.status(200).send(success(model));
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -73,7 +73,7 @@ export default router.post(
|
|||||||
shouldGenerateImage: item.shouldGenerateImage,
|
shouldGenerateImage: item.shouldGenerateImage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const [id, modelData] = model.split(":");
|
const [id, modelData] = model.split(/:(.+)/);
|
||||||
const projectData = await u.db("o_project").select("*").where({ id: projectId }).first();
|
const projectData = await u.db("o_project").select("*").where({ id: projectId }).first();
|
||||||
const videoPrompt = await u.db("o_prompt").where("type", "videoPromptGeneration").first();
|
const videoPrompt = await u.db("o_prompt").where("type", "videoPromptGeneration").first();
|
||||||
let videoPromptGeneration = "" as string | undefined;
|
let videoPromptGeneration = "" as string | undefined;
|
||||||
|
|||||||
@ -18,9 +18,6 @@ export default router.post(
|
|||||||
await u.db("o_agentWorkData").where("projectId", id).delete();
|
await u.db("o_agentWorkData").where("projectId", id).delete();
|
||||||
const novelData = await u.db("o_novel").where("projectId", id).select("id");
|
const novelData = await u.db("o_novel").where("projectId", id).select("id");
|
||||||
const novelId = novelData.map((item: any) => item.id);
|
const novelId = novelData.map((item: any) => item.id);
|
||||||
if (novelId.length > 0) {
|
|
||||||
await u.db("o_outlineNovel").whereIn("novelId", novelId).delete();
|
|
||||||
}
|
|
||||||
//删除项目下的原文
|
//删除项目下的原文
|
||||||
await u.db("o_novel").where("projectId", id).delete();
|
await u.db("o_novel").where("projectId", id).delete();
|
||||||
// 删除项目下的剧本信息
|
// 删除项目下的剧本信息
|
||||||
|
|||||||
@ -41,6 +41,11 @@ export default (nsp: Namespace) => {
|
|||||||
});
|
});
|
||||||
let abortController: AbortController | null = null;
|
let abortController: AbortController | null = null;
|
||||||
|
|
||||||
|
const thinkConfig: agent.AgentContext["thinkConfig"] = {
|
||||||
|
think: false,
|
||||||
|
thinlLevel: 0,
|
||||||
|
};
|
||||||
|
|
||||||
socket.on("updateContext", (data: { isolationKey: string; projectId: number; scriptId: number }, callback) => {
|
socket.on("updateContext", (data: { isolationKey: string; projectId: number; scriptId: number }, callback) => {
|
||||||
isolationKey = data.isolationKey;
|
isolationKey = data.isolationKey;
|
||||||
resTool = new ResTool(socket, {
|
resTool = new ResTool(socket, {
|
||||||
@ -66,46 +71,11 @@ export default (nsp: Namespace) => {
|
|||||||
abortSignal: currentController.signal,
|
abortSignal: currentController.signal,
|
||||||
resTool,
|
resTool,
|
||||||
msg,
|
msg,
|
||||||
|
thinkConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const textStream = await agent.decisionAI(ctx);
|
await agent.runDecisionAI(ctx);
|
||||||
|
|
||||||
let currentMsg = ctx.msg;
|
|
||||||
let text = currentMsg.text();
|
|
||||||
|
|
||||||
const syncCurrentMessage = () => {
|
|
||||||
if (ctx.msg === currentMsg) return;
|
|
||||||
text.complete();
|
|
||||||
currentMsg.complete();
|
|
||||||
currentMsg = ctx.msg;
|
|
||||||
text = currentMsg.text();
|
|
||||||
};
|
|
||||||
|
|
||||||
let aborted = false;
|
|
||||||
try {
|
|
||||||
for await (const chunk of textStream) {
|
|
||||||
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
|
||||||
syncCurrentMessage();
|
|
||||||
text.append(chunk);
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
if (err.name === "AbortError" || currentController.signal.aborted) {
|
|
||||||
aborted = true;
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
syncCurrentMessage();
|
|
||||||
if (aborted) {
|
|
||||||
text.append("[已停止]");
|
|
||||||
text.complete();
|
|
||||||
currentMsg.stop();
|
|
||||||
} else {
|
|
||||||
text.complete();
|
|
||||||
currentMsg.complete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.name !== "AbortError" && !currentController.signal.aborted) {
|
if (err.name !== "AbortError" && !currentController.signal.aborted) {
|
||||||
const errorMsg = u.error(err).message;
|
const errorMsg = u.error(err).message;
|
||||||
@ -120,6 +90,12 @@ export default (nsp: Namespace) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on("updateThinkConfig", (data: { think: boolean; thinlLevel: 0 | 1 | 2 | 3 }) => {
|
||||||
|
thinkConfig.think = data.think;
|
||||||
|
thinkConfig.thinlLevel = data.thinlLevel;
|
||||||
|
console.log("[productionAgent] 更新思考配置:", thinkConfig);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("stop", () => {
|
socket.on("stop", () => {
|
||||||
abortController?.abort();
|
abortController?.abort();
|
||||||
abortController = null;
|
abortController = null;
|
||||||
|
|||||||
@ -40,6 +40,11 @@ export default (nsp: Namespace) => {
|
|||||||
});
|
});
|
||||||
let abortController: AbortController | null = null;
|
let abortController: AbortController | null = null;
|
||||||
|
|
||||||
|
const thinkConfig: agent.AgentContext["thinkConfig"] = {
|
||||||
|
think:false,
|
||||||
|
thinlLevel: 0,
|
||||||
|
}
|
||||||
|
|
||||||
socket.on("chat", async (data: { content: string }) => {
|
socket.on("chat", async (data: { content: string }) => {
|
||||||
const { content } = data;
|
const { content } = data;
|
||||||
abortController?.abort();
|
abortController?.abort();
|
||||||
@ -55,45 +60,11 @@ export default (nsp: Namespace) => {
|
|||||||
abortSignal: currentController.signal,
|
abortSignal: currentController.signal,
|
||||||
resTool,
|
resTool,
|
||||||
msg,
|
msg,
|
||||||
|
thinkConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const textStream = await agent.decisionAI(ctx);
|
await agent.runDecisionAI(ctx);
|
||||||
|
|
||||||
let currentMsg = ctx.msg;
|
|
||||||
let text = currentMsg.text();
|
|
||||||
|
|
||||||
const syncCurrentMessage = () => {
|
|
||||||
if (ctx.msg === currentMsg) return;
|
|
||||||
text.complete();
|
|
||||||
currentMsg.complete();
|
|
||||||
currentMsg = ctx.msg;
|
|
||||||
text = currentMsg.text();
|
|
||||||
};
|
|
||||||
|
|
||||||
let aborted = false;
|
|
||||||
try {
|
|
||||||
for await (const chunk of textStream) {
|
|
||||||
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1));
|
|
||||||
syncCurrentMessage();
|
|
||||||
text.append(chunk);
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
if (err.name === "AbortError" || currentController.signal.aborted) {
|
|
||||||
aborted = true;
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
syncCurrentMessage();
|
|
||||||
if (aborted) {
|
|
||||||
text.complete();
|
|
||||||
currentMsg.stop();
|
|
||||||
} else {
|
|
||||||
text.complete();
|
|
||||||
currentMsg.complete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.name !== "AbortError" && !currentController.signal.aborted) {
|
if (err.name !== "AbortError" && !currentController.signal.aborted) {
|
||||||
const errorMsg = u.error(err).message;
|
const errorMsg = u.error(err).message;
|
||||||
@ -108,6 +79,12 @@ export default (nsp: Namespace) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on("updateThinkConfig", (data: { think: boolean; thinlLevel: 0 | 1 | 2 | 3 }) => {
|
||||||
|
thinkConfig.think = data.think;
|
||||||
|
thinkConfig.thinlLevel = data.thinlLevel;
|
||||||
|
console.log("[scriptAgent] 更新思考配置:", thinkConfig);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("stop", () => {
|
socket.on("stop", () => {
|
||||||
abortController?.abort();
|
abortController?.abort();
|
||||||
abortController = null;
|
abortController = null;
|
||||||
|
|||||||
2
src/types/database.d.ts
vendored
2
src/types/database.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
// @db-hash 3296433eb24314b094ac5d3839c049c5
|
// @db-hash 9248d7bcfe0a1bc57e5b9bc33d8c7d83
|
||||||
//该文件由脚本自动生成,请勿手动修改
|
//该文件由脚本自动生成,请勿手动修改
|
||||||
|
|
||||||
export interface memories {
|
export interface memories {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ async function getVendorTemplateFn(
|
|||||||
): Promise<(think?: boolean, thinkLevel?: 0 | 1 | 2 | 3) => any>;
|
): Promise<(think?: boolean, thinkLevel?: 0 | 1 | 2 | 3) => any>;
|
||||||
async function getVendorTemplateFn(fnName: Exclude<FnName, "textRequest">, modelName: `${string}:${string}`): Promise<(input: any) => any>;
|
async function getVendorTemplateFn(fnName: Exclude<FnName, "textRequest">, modelName: `${string}:${string}`): Promise<(input: any) => any>;
|
||||||
async function getVendorTemplateFn(fnName: FnName, modelName: `${string}:${string}`): Promise<any> {
|
async function getVendorTemplateFn(fnName: FnName, modelName: `${string}:${string}`): Promise<any> {
|
||||||
const [id, name] = modelName.split(":");
|
const [id, name] = modelName.split(/:(.+)/);
|
||||||
const vendorConfigData = await u.db("o_vendorConfig").where("id", id).first();
|
const vendorConfigData = await u.db("o_vendorConfig").where("id", id).first();
|
||||||
if (!vendorConfigData) throw new Error(`未找到供应商配置 id=${id}`);
|
if (!vendorConfigData) throw new Error(`未找到供应商配置 id=${id}`);
|
||||||
const modelList = await u.vendor.getModelList(id);
|
const modelList = await u.vendor.getModelList(id);
|
||||||
@ -55,7 +55,7 @@ async function withTaskRecord<T>(
|
|||||||
fn: (modelName: `${string}:${string}`, think: Boolean, thinkLevel: 0 | 1 | 2 | 3) => Promise<T>,
|
fn: (modelName: `${string}:${string}`, think: Boolean, thinkLevel: 0 | 1 | 2 | 3) => Promise<T>,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const modelName = await resolveModelName(modelKey);
|
const modelName = await resolveModelName(modelKey);
|
||||||
const [id, model] = modelName.split(":");
|
const [_, model] = modelName.split(/:(.+)/);
|
||||||
const taskRecord = await u.task(projectId, taskClass, model, { describe: describe, content: relatedObjects });
|
const taskRecord = await u.task(projectId, taskClass, model, { describe: describe, content: relatedObjects });
|
||||||
try {
|
try {
|
||||||
const result = await fn(modelName, false, 0);
|
const result = await fn(modelName, false, 0);
|
||||||
@ -89,46 +89,29 @@ class AiText {
|
|||||||
this.think = think;
|
this.think = think;
|
||||||
this.thinkLevel = thinkLevel;
|
this.thinkLevel = thinkLevel;
|
||||||
}
|
}
|
||||||
async invoke(input: Omit<Parameters<typeof generateText>[0], "model">) {
|
private async resolveModel(middleware?: any | any[]) {
|
||||||
const switchAiDevTool = await u.db("o_setting").where("key", "switchAiDevTool").first();
|
const switchAiDevTool = await u.db("o_setting").where("key", "switchAiDevTool").first();
|
||||||
const modelName = await resolveModelName(this.AiType);
|
const modelName = await resolveModelName(this.AiType);
|
||||||
const sdkFn = await getVendorTemplateFn("textRequest", modelName);
|
const sdkFn = await getVendorTemplateFn("textRequest", modelName);
|
||||||
|
const baseModel = await sdkFn(this.think, this.thinkLevel);
|
||||||
|
const mws = [
|
||||||
|
...(switchAiDevTool?.value === "1" ? [devToolsMiddleware()] : []),
|
||||||
|
...(middleware ? (Array.isArray(middleware) ? middleware : [middleware]) : []),
|
||||||
|
];
|
||||||
|
return mws.length > 0 ? wrapLanguageModel({ model: baseModel, middleware: mws.length === 1 ? mws[0] : mws }) : baseModel;
|
||||||
|
}
|
||||||
|
async invoke(input: Omit<Parameters<typeof generateText>[0], "model">) {
|
||||||
return generateText({
|
return generateText({
|
||||||
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
||||||
...input,
|
...input,
|
||||||
model:
|
model: await this.resolveModel(),
|
||||||
switchAiDevTool?.value === "1"
|
|
||||||
? wrapLanguageModel({
|
|
||||||
model: await sdkFn(this.think, this.thinkLevel),
|
|
||||||
middleware: devToolsMiddleware(),
|
|
||||||
})
|
|
||||||
: await sdkFn(this.think, this.thinkLevel),
|
|
||||||
} as Parameters<typeof generateText>[0]);
|
} as Parameters<typeof generateText>[0]);
|
||||||
}
|
}
|
||||||
async stream(input: Omit<Parameters<typeof streamText>[0], "model">) {
|
async stream(input: Omit<Parameters<typeof streamText>[0], "model">) {
|
||||||
const switchAiDevTool = await u.db("o_setting").where("key", "switchAiDevTool").first();
|
|
||||||
const modelName = await resolveModelName(this.AiType);
|
|
||||||
const sdkFn = await getVendorTemplateFn("textRequest", modelName);
|
|
||||||
return streamText({
|
return streamText({
|
||||||
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
...(input.tools && { stopWhen: stepCountIs(Object.keys(input.tools).length * 50) }),
|
||||||
...input,
|
...input,
|
||||||
model:
|
model: await this.resolveModel(extractReasoningMiddleware({ tagName: "reasoning_content", separator: "\n" })),
|
||||||
switchAiDevTool?.value == "1"
|
|
||||||
? wrapLanguageModel({
|
|
||||||
model: sdkFn(this.think, this.thinkLevel),
|
|
||||||
middleware: [
|
|
||||||
devToolsMiddleware(),
|
|
||||||
extractReasoningMiddleware({
|
|
||||||
tagName: "reasoning_content",
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
})
|
|
||||||
: wrapLanguageModel({
|
|
||||||
model: sdkFn(this.think, this.thinkLevel),
|
|
||||||
middleware: extractReasoningMiddleware({
|
|
||||||
tagName: "reasoning_content",
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
} as Parameters<typeof streamText>[0]);
|
} as Parameters<typeof streamText>[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user