Node.js + LangChain +React:搭建个人知识库(四)- 把向量和文件切块存入mysql中

前面已经完成BGE模型本地加载和文档切片的大坑,成功拿到了文档的向量化数据。

今天这篇不聊虚的,直接进入数据持久化 阶段------把切好的块和算好的向量,稳稳当当地存进MySQL。同时,我也顺手把 @xenova/transformers 库中那些容易被忽视的 env 配置参数做了一个深度整理。

填坑必备:Transformers.js 的 env 配置参数全解

在上一篇加载本地模型时,我们用到了 env.localModelPathenv.allowRemoteModels。其实在 Node.js 环境下,@xenova/transformers 提供了一套非常灵活的环境配置系统(完全对应 Python 版本的逻辑)。

这里我把常用的 env 参数整理成了一份清单,方便大家日后查阅和配置:

参数名 默认值 作用说明
allowRemoteModels true 核心开关 。设为 false 时,强制不联网,只走本地或缓存(离线环境必配)。
allowLocalModels true 设为 false 时,跳过本地检查,直接尝试远程下载(调试新版本时有用)。
remoteHost https://huggingface.co 换源关键 。如果你想用 HF 的国内镜像站(如 https://hf-mirror.com),改这里即可,无需修改模型ID。
localModelPath ./models 指定本地模型存放的根目录。代码中引用模型时仍用模型ID,它会自动去这个目录下找。
cacheDir ./.cache 下载模型时的临时缓存目录。
useFSCache true 是否启用文件系统缓存。
useCustomCache false 高级用法。如果你想把模型缓存到 Redis 或数据库,设为 true 并实现下方的 customCache 对象。
customCache null 需要实现 Web 标准的 Cache 接口(matchput 方法)。

关于换源的小贴士:

正如表格中提到的,昨天有朋友提醒,在 Node 中配置 env.remoteHost 应该就可以实现换源。确实,理论上这是最优雅的方式,但我目前为了绝对的稳定,依然采用了**"手动下载模型 + 配置 localModelPath"**的笨办法。如果你的网络环境较好,强烈建议试试直接改 remoteHost,能省去手动下载的步骤。

核心实操:如何在 MySQL 中高效存储向量?

既然我们在第三篇已经决定"退守 MySQL",那就得解决一个核心问题:MySQL 原生不支持向量类型,怎么存?

很多教程会建议你直接把向量转成 JSON 字符串(如 "[0.1, 0.5, ...]")存进 TEXTJSON 字段。但我实测后发现,这种方式不仅占用空间大,而且后续读取出来做相似度计算时,字符串转数组的开销也非常大。

最终方案:使用 BLOB(二进制大对象)存储。

将 JavaScript 中的 Float32Array(向量数据)直接转换为二进制 Buffer 存入数据库。

代码实现(TypeScript/Node.js):

ini 复制代码
// 将数据转换为Float32Buffer
const convertToFloat32Buffer = data => {
  const float32Array = new Float32Array(data);
  return Buffer.from(float32Array.buffer);
};

这种"土办法"的优势非常明显:

  • 节省空间:相比于存 JSON 字符串,二进制存储能节省约 60% 的磁盘空间。
  • 读写极快:数据库对二进制字段的 I/O 优化通常比解析长文本要好,且 Node.js 处理 Buffer 的效率极高。

架构升级预告:引入"任务"概念

细心的朋友可能已经发现了,向量化是一个非常消耗 CPU 和时间的过程。如果文档很大,或者并发请求进来,直接同步处理会导致 Node.js 服务卡死。

因此,在这一阶段,我们需要引入**"任务队列"**的概念:

  1. 用户上传文档 -> 立即返回"上传成功,正在处理中"。
  2. 后台生成任务 -> 将文档解析、切片、向量化封装成一个异步任务。
  3. 持久化到 DB -> 任务完成后,将向量写入 MySQL。

虽然这一篇没有贴具体的任务队列代码,但请务必在设计之初就预留好这个接口。

总结

这一篇虽然"技术含量"看起来不如前几篇高,但数据持久化是 RAG 项目从"玩具"变成"工具"的关键一步。

我们解决了两个核心问题:

  1. 怎么存:利用 MySQL 的二进制字段存储向量,兼顾了成本与性能。
  2. 怎么配:理清了 transformers.jsenv 对象的配置逻辑,为后续的模型管理打下基础。

下一篇文章,我们将迎来一个小高潮:实现全文检索。我们将从 MySQL 中读取二进制向量,计算余弦相似度,并结合关键词过滤,构建一个真正可用的检索系统。敬请期待!

相关推荐
神奇小汤圆3 小时前
Agent 框架别急着乱学:先用 LangChain 搞懂 7 个基本模块
后端
神奇小汤圆3 小时前
一次线上故障带你看懂 MySQL InnoDB 缓冲池
后端
啷里格啷3 小时前
第三章 Fast-DDS核心源码导读与流程拆解
后端·架构
爱编程的小新☆3 小时前
Spring-AI入门
java·后端·spring
蝎子莱莱爱打怪3 小时前
👋🏻👋🏻再见,拉勾网——那个"最懂互联网人"的招聘平台倒了😭
前端·后端·招聘
用户298698530143 小时前
Java 获取 Word 文档中修订记录的实现方法
java·后端
海上彼尚4 小时前
Nodejs也能写Agent - 7.基础篇 - MCP
前端·javascript·人工智能·node.js
TheRouter4 小时前
PromptCaching 工程实践:把LLM 调用成本砍掉80%
java·后端·spring·ai
Gopher_HBo4 小时前
Go pprof性能剖析
后端