From e73b75088b84ef2374978742da8d0b1ecc247a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ACT=E4=B8=B6=E6=B5=81=E6=98=9F=E9=9B=A8?= <1340145680@qq.com> Date: Fri, 20 Mar 2026 14:41:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85Agent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agents/productionAgent/index.ts | 91 ++++++++++++++++++++++++++++ src/agents/productionAgent/tools.ts | 69 --------------------- src/routes/agents/productionAgent.ts | 46 +------------- src/utils/agent/memory.ts | 18 +++--- 4 files changed, 102 insertions(+), 122 deletions(-) create mode 100644 src/agents/productionAgent/index.ts diff --git a/src/agents/productionAgent/index.ts b/src/agents/productionAgent/index.ts new file mode 100644 index 0000000..281ed34 --- /dev/null +++ b/src/agents/productionAgent/index.ts @@ -0,0 +1,91 @@ +import { createAGUIStream } from "@/utils/agent/aguiTools"; +import u from "@/utils"; +import Memory from "@/utils/agent/memory"; +import { useSkill } from "@/utils/agent/skillsTools"; +// import tools from "@/agents/productionAgent/tools"; + +function buildSystemPrompt(skillPrompt: string, mem: Awaited>): string { + let memoryContext = ""; + if (mem.rag.length) { + memoryContext += `[相关记忆]\n${mem.rag.map((r) => r.content).join("\n")}`; + } + if (mem.summaries.length) { + if (memoryContext) memoryContext += "\n\n"; + memoryContext += `[历史摘要]\n${mem.summaries.map((s, i) => `${i + 1}. ${s.content}`).join("\n")}`; + } + if (mem.shortTerm.length) { + if (memoryContext) memoryContext += "\n\n"; + memoryContext += `[近期对话]\n${mem.shortTerm.map((m) => `${m.role}: ${m.content}`).join("\n")}`; + } + if (!memoryContext) return skillPrompt; + return `${skillPrompt}\n\n## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`; +} + +export async function decisionAI(agui: ReturnType, isolationKey: string, text: string) { + const memory = new Memory("productionAgent", isolationKey); + await memory.add("user", text); + const [skill, mem] = await Promise.all([useSkill("production-agent", "decision"), memory.get(text)]); + + const systemPrompt = buildSystemPrompt(skill.prompt, mem); + console.log("%c Line:30 🍊 systemPrompt", "background:#33a5ff", systemPrompt); + + const { textStream } = await u.Ai.Text("productionAgent").stream({ + system: systemPrompt, + messages: [{ role: "user", content: text }], + tools: { + ...skill.tools, + ...memory.getTools(), + }, + onFinish: async (completion) => { + await memory.add("decisionAI", completion.text); + }, + }); + + return textStream; +} + +export async function executionAI(agui: ReturnType, isolationKey: string, text: string) { + const memory = new Memory("productionAgent", isolationKey); + await memory.add("user", text); + const [skill, mem] = await Promise.all([useSkill("production-agent", "execution"), memory.get(text)]); + + const systemPrompt = buildSystemPrompt(skill.prompt, mem); + + const { textStream } = await u.Ai.Text("productionAgent").stream({ + system: systemPrompt, + messages: [{ role: "user", content: text }], + tools: { + ...skill.tools, + ...memory.getTools(), + }, + onFinish: async (completion) => { + await memory.add("executionAI", completion.text); + }, + }); + + return textStream; +} + +export async function supervisionAI(agui: ReturnType, isolationKey: string, text: string) { + agui.custom("systemMessage", "已由 监督层AI 接管对话"); + + const memory = new Memory("productionAgent", isolationKey); + await memory.add("user", text); + const [skill, mem] = await Promise.all([useSkill("production-agent", "supervision"), memory.get(text)]); + + const systemPrompt = buildSystemPrompt(skill.prompt, mem); + + const { textStream } = await u.Ai.Text("productionAgent").stream({ + system: systemPrompt, + messages: [{ role: "user", content: text }], + tools: { + ...skill.tools, + ...memory.getTools(), + }, + onFinish: async (completion) => { + await memory.add("supervisionAI", completion.text); + }, + }); + + return textStream; +} diff --git a/src/agents/productionAgent/tools.ts b/src/agents/productionAgent/tools.ts index 44780db..d6c32ee 100644 --- a/src/agents/productionAgent/tools.ts +++ b/src/agents/productionAgent/tools.ts @@ -2,74 +2,5 @@ import { tool } from "ai"; import { z } from "zod"; import u from "@/utils"; import { useSkill } from "@/utils/agent/skillsTools"; -import { createAGUIStream } from "@/utils/agent/aguiTools"; -interface FlowData { - script: { - blocks: string[]; - }; -} -export default (isolationKey: string, agui: ReturnType) => { - const flowData: FlowData = { - script: { - blocks: [], - }, - }; - return { - get_project_info: tool({ - description: "获取项目信息", - inputSchema: z.object({}), - execute: async () => { - return ` - 项目名称:仙逆 - 视频风格:玄幻3D动漫 - 视频类型:短剧 - 项目描述:讲述了乡村平凡少年王林以心中之感动,逆仙而修,求的不仅是长生,更多的是摆脱那背后的蝼蚁之身。他坚信道在人为,以平庸的资质踏入修真仙途,历经坎坷风雨,凭着其聪睿的心智,一步一步走向巅峰,凭一己之力,扬名修真界。 - 总集数:24集每集2分钟 - 当前集数:3集 - `; - }, - }), - get_state: tool({ - description: "获取工作流指定板块数据", - inputSchema: z.object({ - block: z.enum(["script"]).describe("板块名称,如 script"), - }), - execute: async ({ block }) => { - return flowData[block]; - }, - }), - execution: tool({ - description: "执行层,负责具体执行具体的任务", - inputSchema: z.object({ - taskDescription: z.string().describe("具体的任务描述详细信息"), - }), - execute: async ({ taskDescription }) => { - agui.custom("systemMessage", "已由 执行层AI 接管对话"); - - const skill = await useSkill("production-agent", "execution"); - - const { textStream } = await u.Ai.Text("productionAgent").stream({ - system: skill.prompt, - messages: [{ role: "user", content: `请完成任务:${taskDescription}` }], - tools: { - ...skill.tools, - }, - }); - - let msg: ReturnType | null = null; - let fullResponse = ""; - - for await (const chunk of textStream) { - if (!msg) msg = agui.textMessage(); - msg.send(chunk); - fullResponse += chunk; - } - msg?.end(); - - return { found: true, memories: ["第一条记忆内容", "第二条记忆内容"] }; - }, - }), - }; -}; diff --git a/src/routes/agents/productionAgent.ts b/src/routes/agents/productionAgent.ts index 1d383a0..eefefe7 100644 --- a/src/routes/agents/productionAgent.ts +++ b/src/routes/agents/productionAgent.ts @@ -1,59 +1,17 @@ import express from "express"; import { createAGUIStream } from "@/utils/agent/aguiTools"; -import u from "@/utils"; -import Memory from "@/utils/agent/memory"; -import { useSkill } from "@/utils/agent/skillsTools"; -import tools from "@/agents/productionAgent/tools"; +import * as agent from "@/agents/productionAgent/index"; const router = express.Router(); -function delay(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - export default router.post("/", async (req, res) => { const { prompt: text, projectId, episodesId } = req.body; const isolationKey = `${projectId}:${episodesId}`; - //记忆 - const memory = new Memory("productionAgent", isolationKey); - //skill - const skill = await useSkill("production-agent", "decision"); - const agui = createAGUIStream(res); agui.runStarted(); - agui.custom("systemMessage", "已由 决策层AI 接管对话"); - // 存入用户消息 - await memory.add("user", text); - - // 获取记忆上下文 - const mem = await memory.get(text); - const memoryContext = [ - mem.rag.length > 0 && `[相关记忆]\n${mem.rag.map((r) => r.content).join("\n")}`, - mem.summaries.length > 0 && `[历史摘要]\n${mem.summaries.map((s, i) => `${i + 1}. ${s.content}`).join("\n")}`, - mem.shortTerm.length > 0 && `[近期对话]\n${mem.shortTerm.map((m) => `${m.role}: ${m.content}`).join("\n")}`, - ] - .filter(Boolean) - .join("\n\n"); - - const systemPrompt = [skill.prompt, memoryContext && `## Memory\n以下是你对用户的记忆,可作为参考但不要主动提及:\n${memoryContext}`] - .filter(Boolean) - .join("\n\n"); - - const { textStream } = await u.Ai.Text("productionAgent").stream({ - system: systemPrompt, - messages: [{ role: "user", content: text }], - tools: { - ...skill.tools, - ...memory.getTools(), - ...tools(isolationKey, agui), - }, - onFinish: async (completion) => { - // 存入助手回复 - await memory.add("decisionAI", completion.text); - }, - }); + const textStream = await agent.decisionAI(agui, isolationKey, text); let msg: ReturnType | null = null; let fullResponse = ""; diff --git a/src/utils/agent/memory.ts b/src/utils/agent/memory.ts index 94a8081..16fde04 100644 --- a/src/utils/agent/memory.ts +++ b/src/utils/agent/memory.ts @@ -97,11 +97,11 @@ class Memory { embedding: JSON.stringify(embedding), relatedMessageIds: null, summarized: 0, - createdAt: Date.now(), + createTime: Date.now(), } as any); // 检查未总结消息数量 - const unsummarized = await u.db("memories").where({ isolationKey, type: "message", summarized: 0 }).orderBy("createdAt", "asc"); + const unsummarized = await u.db("memories").where({ isolationKey, type: "message", summarized: 0 }).orderBy("createTime", "asc"); if (unsummarized.length >= Number(messagesPerSummary)) { const batch = unsummarized.slice(0, Number(messagesPerSummary)); @@ -120,7 +120,7 @@ class Memory { embedding: JSON.stringify(summaryEmbedding), relatedMessageIds: JSON.stringify(batchIds), summarized: 0, - createdAt: Date.now(), + createTime: Date.now(), } as any); // 标记已总结 @@ -140,12 +140,12 @@ class Memory { const shortTerm = await u .db("memories") .where({ isolationKey, type: "message", summarized: 0 }) - .orderBy("createdAt", "desc") + .orderBy("createTime", "desc") .limit(Number(shortTermLimit)); shortTerm.reverse(); // 最旧在前 // summaries: 最近的 summary - const summaries = await u.db("memories").where({ isolationKey, type: "summary" }).orderBy("createdAt", "desc").limit(Number(summaryLimit)); + const summaries = await u.db("memories").where({ isolationKey, type: "summary" }).orderBy("createTime", "desc").limit(Number(summaryLimit)); summaries.reverse(); // rag: 向量搜索所有 messages @@ -154,12 +154,12 @@ class Memory { const ragResults = vectorSearch(allMessages, queryEmbedding, Number(ragLimit)); return { - shortTerm: shortTerm.map((m: any) => ({ id: m.id, role: m.role, content: m.content, createdAt: m.createdAt })), + shortTerm: shortTerm.map((m: any) => ({ id: m.id, role: m.role, content: m.content, createTime: m.createTime })), summaries: summaries.map((s) => ({ id: s.id, content: s.content, relatedMessageIds: JSON.parse(s.relatedMessageIds || "[]"), - createdAt: (s as any).createdAt, + createTime: (s as any).createTime, })), rag: ragResults.map((r) => ({ id: r.id, content: r.content, similarity: r.similarity })), }; @@ -190,9 +190,9 @@ class Memory { if (messageIds.length === 0) return []; - const messages = await u.db("memories").whereIn("id", messageIds).orderBy("createdAt", "asc"); + const messages = await u.db("memories").whereIn("id", messageIds).orderBy("createTime", "asc"); - return messages.map((m) => ({ id: m.id, content: m.content, createdAt: m.createdAt })); + return messages.map((m) => ({ id: m.id, content: m.content, createTime: m.createTime })); } getTools() {