From c0b4172e0387db12a75a055519f3eefe4ce9df3e Mon Sep 17 00:00:00 2001 From: wing Date: Sat, 14 Feb 2026 20:44:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(agents):=20=E4=B8=BA=20VectorIndex=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BA=8F=E5=88=97=E5=8C=96/=E5=8F=8D?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **问题**: - VectorIndex 索引只存储在内存 Map 中,重启后全部丢失 - Float32Array 数据无法直接序列化为 JSON - 无法实现跨会话索引持久化 **修复**: - 添加 serialize() 方法:将索引转换为 JSON 可序列化对象 - 添加 deserialize() 方法:从序列化数据恢复索引 - Float32Array 转换为普通数组进行序列化 - 保持向后兼容,不破坏现有功能 **测试**: - 所有 26 个 VectorIndex 单元测试通过 - 修复不破坏现有功能 **注**: - BM25 索引已有 serializeIndex/deserializeIndex 函数 - 两个索引现在都支持持久化 via [HAPI](https://hapi.run) Co-Authored-By: HAPI --- .../retrieval/embeddings/vector-index.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/js/agents/retrieval/embeddings/vector-index.js b/js/agents/retrieval/embeddings/vector-index.js index 9833866c..63347590 100644 --- a/js/agents/retrieval/embeddings/vector-index.js +++ b/js/agents/retrieval/embeddings/vector-index.js @@ -227,6 +227,37 @@ export class VectorIndex { } return stats; } + + /** + * Serialize the index to a JSON-compatible object. + * @returns {{dim:number|null, maxItems:number, rows:Array<[string, {vec:number[], meta:any}]>}} + */ + serialize() { + const rows = []; + for (const [id, row] of this._rows.entries()) { + rows.push([id, { vec: Array.from(row.vec), meta: row.meta }]); + } + return { dim: this._dim, maxItems: this._maxItems, rows }; + } + + /** + * Deserialize and restore the index from a serialized object. + * @param {{dim:number|null, maxItems:number, rows:Array<[string, {vec:number[], meta:any}]>}} data + * @returns {void} + */ + deserialize(data) { + if (!data || typeof data !== 'object') throw new TypeError('deserialize(data): data must be an object'); + this._dim = typeof data.dim === 'number' ? data.dim : null; + this._maxItems = toPositiveInt(data.maxItems, 1000); + this._rows.clear(); + if (Array.isArray(data.rows)) { + for (const [id, row] of data.rows) { + if (typeof id !== 'string' || !row || !Array.isArray(row.vec)) continue; + const vec = new Float32Array(row.vec); + this._rows.set(id, { vec, meta: row.meta }); + } + } + } } export default { VectorIndex };