From f7bfc05a53390786e4a0bea279774a08a1b3fc5b Mon Sep 17 00:00:00 2001 From: zhishi <1951671751@qq.com> Date: Thu, 19 Mar 2026 20:04:49 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=B0=E5=BF=86=E9=85=8D=E7=BD=AE=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/initDB.ts | 47 +++++++++++++------ src/routes/setting/memoryConfig/getMemory.ts | 23 +++++++-- src/routes/setting/memoryConfig/sureMemory.ts | 42 ++++++++++++----- src/utils/agent/embedding.ts | 14 ++++-- 4 files changed, 92 insertions(+), 34 deletions(-) diff --git a/src/lib/initDB.ts b/src/lib/initDB.ts index b5b6df6..1df3ecc 100644 --- a/src/lib/initDB.ts +++ b/src/lib/initDB.ts @@ -48,8 +48,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { - }, + initData: async (knex) => {}, }, //技能表 { @@ -61,7 +60,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //Agent配置表 { @@ -153,16 +152,36 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => value: uuid().slice(0, 8), }, { - key: "shortTermMemoryLength", - value: 10, - }, - { - key: "searchTopK", + key: "messagesPerSummary", value: 3, }, { - key: "similarityThreshold", - value: 0.3, + key: "shortTermLimit", + value: 5, + }, + { + key: "summaryMaxLength", + value: 500, + }, + { + key: "summaryLimit", + value: 10, + }, + { + key: "ragLimit", + value: 3, + }, + { + key: "deepRetrieveSummaryLimit", + value: 5, + }, + { + key: "modelOnnxFile", + value: '["all-MiniLM-L6-v2", "onnx", "model_fp16.onnx"]', + }, + { + key: "modelDtype", + value: "fp16", }, ]); }, @@ -183,7 +202,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //提示词表 { @@ -200,7 +219,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.unique(["id"]); table.unique(["code"]); // 代号唯一 }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //资产表 { @@ -220,7 +239,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //任务中心表 { @@ -238,7 +257,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //小说原文表 { diff --git a/src/routes/setting/memoryConfig/getMemory.ts b/src/routes/setting/memoryConfig/getMemory.ts index 1870cd4..e6687b0 100644 --- a/src/routes/setting/memoryConfig/getMemory.ts +++ b/src/routes/setting/memoryConfig/getMemory.ts @@ -4,14 +4,31 @@ import u from "@/utils"; const router = express.Router(); export default router.get("/", async (req, res) => { - const settingData = await u.db("o_setting").whereIn("key", ["shortTermMemoryLength", "searchTopK", "similarityThreshold"]); + const settingData = await u + .db("o_setting") + .whereIn("key", [ + "messagesPerSummary", + "shortTermLimit", + "summaryMaxLength", + "summaryLimit", + "ragLimit", + "deepRetrieveSummaryLimit", + "modelOnnxFile", + "modelDtype", + ]); if (!settingData) return res.status(400).send(error(`获取记忆配置失败`)); - const memoryObj: Record = {}; + const memoryObj: Record = {}; settingData.forEach((i) => { if (i.key && i.value) { - memoryObj[i.key] = Number(i.value); + let value: number | string | string[] = i.value; + if (i.key == "modelOnnxFile") { + value = JSON.parse(i.value); + } else if (i.key != "modelDtype") { + value = Number(value); + } + memoryObj[i.key] = value; } }); diff --git a/src/routes/setting/memoryConfig/sureMemory.ts b/src/routes/setting/memoryConfig/sureMemory.ts index b0d298b..bed990e 100644 --- a/src/routes/setting/memoryConfig/sureMemory.ts +++ b/src/routes/setting/memoryConfig/sureMemory.ts @@ -9,21 +9,37 @@ const router = express.Router(); export default router.post( "/", validateFields({ - shortTermMemoryLength: z.number(), //短期记忆长度 - searchTopK: z.number(), //搜索记忆条数 - similarityThreshold: z.number(), //记忆相似度阈值 + messagesPerSummary: z.number(), + shortTermLimit: z.number(), + summaryMaxLength: z.number(), + summaryLimit: z.number(), + ragLimit: z.number(), + deepRetrieveSummaryLimit: z.number(), + modelOnnxFile: z.array(z.string()), + modelDtype: z.string(), }), async (req, res) => { - const { shortTermMemoryLength, searchTopK, similarityThreshold } = req.body; - await u.db("o_setting").where("key", "shortTermMemoryLength").update({ - value: shortTermMemoryLength, - }); - await u.db("o_setting").where("key", "searchTopK").update({ - value: searchTopK, - }); - await u.db("o_setting").where("key", "similarityThreshold").update({ - value: similarityThreshold, - }); + const { messagesPerSummary, shortTermLimit, summaryMaxLength, summaryLimit, ragLimit, deepRetrieveSummaryLimit, modelOnnxFile, modelDtype } = + req.body; + + const upsert = async (key: string, value: string) => { + const exists = await u.db("o_setting").where("key", key).first(); + if (exists) { + await u.db("o_setting").where("key", key).update({ value }); + } else { + await u.db("o_setting").insert({ key, value }); + } + }; + + await upsert("messagesPerSummary", messagesPerSummary); + await upsert("shortTermLimit", shortTermLimit); + await upsert("summaryMaxLength", summaryMaxLength); + await upsert("summaryLimit", summaryLimit); + await upsert("ragLimit", ragLimit); + await upsert("deepRetrieveSummaryLimit", deepRetrieveSummaryLimit); + await upsert("modelOnnxFile", JSON.stringify(modelOnnxFile)); + await upsert("modelDtype", modelDtype); + res.status(200).send(success("保存设置成功")); }, ); diff --git a/src/utils/agent/embedding.ts b/src/utils/agent/embedding.ts index 679b66e..f195e23 100644 --- a/src/utils/agent/embedding.ts +++ b/src/utils/agent/embedding.ts @@ -2,18 +2,24 @@ import { pipeline, env as transformersEnv, FeatureExtractionPipeline } from "@hu import path from "path"; import fs from "fs"; import getPath from "@/utils/getPath"; +import db from "@/utils/db"; // ── 模型配置 ── -const modelOnnxFile = ["all-MiniLM-L6-v2", "onnx", "model_fp16.onnx"]; // 模型文件路径 -const modelDtype = "fp16" as const; // 量化类型:fp32 - +// const modelOnnxFile = ["all-MiniLM-L6-v2", "onnx", "model_fp16.onnx"]; // 模型文件路径 +// const modelDtype = "fp16" as const; // 量化类型:fp32 let extractor: FeatureExtractionPipeline | null = null; export async function initEmbedding(): Promise { if (extractor) return; //todo 模型配置放到这里 - + const modelConfigData = await db("o_setting").whereIn("key", ["modelOnnxFile", "modelDtype"]); + const modelObj: Record = {}; + Object.entries(modelConfigData).forEach(([key, value]) => { + modelObj[key] = value as string; + }); + let modelOnnxFile = modelObj?.modelOnnxFile ? JSON.parse(modelObj.modelOnnxFile) : ["all-MiniLM-L6-v2", "onnx", "model_fp16.onnx"]; // 模型文件路径 + let modelDtype = modelObj?.modelDtype ?? ("fp16" as const); // 量化类型:fp32 const onnxPath = path.join(getPath("models"), ...modelOnnxFile); if (!fs.existsSync(onnxPath)) { throw new Error(`Embedding 模型文件不存在: ${onnxPath}`);