Node.js 本地下载并使用 Hugging Face 中文向量模型:以 bge-base-zh-v1.5 为例
在构建本地 AI 工作台、知识库问答、语义搜索、RAG 检索系统时,我们经常需要把一段文本转换成"向量"。文本向量可以用来计算语义相似度,比如判断两个句子是否表达了相近的意思,或者从大量文档中找出与用户问题最相关的内容。
本文将介绍如何使用 Node.js 和 @huggingface/transformers 下载并本地缓存一个中文向量模型:Xenova/bge-base-zh-v1.5,并完成一次简单的文本向量提取测试。
一、这段代码实现了什么?
这段代码主要做了三件事:
- 指定模型缓存目录,例如
D:/models/cache - 自动下载并加载 Hugging Face 上的中文向量模型
- 输入一段中文文本,生成对应的向量结果
完整代码如下:
js
const { pipeline, env } = require('@huggingface/transformers');
env.cacheDir = 'D:/models/cache';
async function downloadModel() {
const modelId = 'Xenova/bge-base-zh-v1.5';
console.log('开始加载模型:', modelId);
try {
const extractor = await pipeline(
'feature-extraction',
modelId,
{
revision: 'main',
// 可选:显示下载进度
progress_callback: (progress) => {
if (progress.status === 'progress') {
console.log(
`下载中: ${progress.file} ${progress.progress?.toFixed(2)}%`
);
} else {
console.log(progress.status, progress.file || '');
}
}
}
);
console.log('模型加载完成,说明模型已下载或已从缓存读取。');
// 测试模型是否可用
const output = await extractor('这是一个测试文本', {
pooling: 'mean',
normalize: true,
});
console.log('向量维度:', output.data.length);
console.log('前 10 个向量值:', Array.from(output.data.slice(0, 10)));
} catch (error) {
console.error('模型下载/加载失败:', error);
}
}
downloadModel();
二、核心依赖:@huggingface/transformers
代码中使用的核心库是:
js
const { pipeline, env } = require('@huggingface/transformers');
@huggingface/transformers 可以理解为 JavaScript 版本的 Transformers 推理库。它可以在 Node.js 环境中加载模型,并执行文本分类、文本生成、特征提取、语义向量生成等任务。
在本文代码中,我们使用的是:
js
pipeline('feature-extraction', modelId)
也就是"特征提取"任务。对于文本来说,特征提取通常就是把文本转换成向量。
三、指定模型缓存目录
代码中有一行非常关键:
js
env.cacheDir = 'D:/models/cache';
这表示模型文件会被缓存到本地的 D:/models/cache 目录。
第一次运行时,如果本地没有模型文件,程序会自动从 Hugging Face 下载模型。下载完成后,后续再次运行程序时,就会直接从本地缓存读取模型,不需要重复下载。
这样做有几个好处:
- 避免每次启动都重新下载模型
- 方便离线部署
- 可以统一管理本地模型文件
- 适合桌面端、本地 AI 工具、企业内网环境使用
例如,你可以把模型统一放在:
txt
D:/models/cache
后续应用启动时直接从这个目录读取模型。
四、选择中文向量模型
代码中使用的模型是:
js
const modelId = 'Xenova/bge-base-zh-v1.5';
bge-base-zh-v1.5 是一个中文语义向量模型,适合用于中文文本检索、语义匹配、知识库问答等场景。
例如,当用户输入:
txt
怎么实现本地 AI 工作台?
系统可以把这句话转换成向量,然后与知识库中所有文档的向量进行相似度计算,找到最相关的内容。
这类模型非常适合用于:
- 本地知识库
- 文档搜索
- AI 问答系统
- RAG 检索增强生成
- FAQ 智能匹配
- 商品、文章、工单的语义搜索
五、下载进度回调
代码中配置了 progress_callback:
js
progress_callback: (progress) => {
if (progress.status === 'progress') {
console.log(
`下载中: ${progress.file} ${progress.progress?.toFixed(2)}%`
);
} else {
console.log(progress.status, progress.file || '');
}
}
这个回调函数用于显示模型下载进度。
模型通常会包含多个文件,例如:
txt
config.json
tokenizer.json
model.onnx
special_tokens_map.json
当模型文件较大时,显示下载进度可以让用户知道程序没有卡死,而是在正常下载。
运行时可能看到类似输出:
txt
开始加载模型: Xenova/bge-base-zh-v1.5
initiate config.json
download model.onnx
下载中: model.onnx 35.26%
下载中: model.onnx 68.41%
done model.onnx
模型加载完成,说明模型已下载或已从缓存读取。
六、生成文本向量
模型加载完成后,代码会执行一次测试:
js
const output = await extractor('这是一个测试文本', {
pooling: 'mean',
normalize: true,
});
这里的输入文本是:
txt
这是一个测试文本
模型会把这段中文文本转换成一个向量。
参数说明:
js
pooling: 'mean'
表示使用平均池化,把 token 级别的向量合并成一个句子级别的向量。
js
normalize: true
表示对向量进行归一化处理。归一化后的向量更适合做余弦相似度计算。
最后打印向量维度和前 10 个向量值:
js
console.log('向量维度:', output.data.length);
console.log('前 10 个向量值:', Array.from(output.data.slice(0, 10)));
输出可能类似:
txt
向量维度: 768
前 10 个向量值: [
0.0123,
-0.0345,
0.0567,
...
]
向量维度通常由模型决定。对于 bge-base-zh-v1.5 这类 base 级别模型,常见输出维度是 768。
七、这段代码适合用在哪里?
这段代码可以作为本地向量模型的基础下载和验证脚本。
在实际项目中,它可以扩展成以下功能:
1. 本地 AI 知识库
把 PDF、Markdown、Word、TXT 等文档切分成小段,然后使用该模型生成向量,存入数据库。
用户提问时,再把问题转换成向量,与数据库中的文档向量进行相似度匹配。
2. 本地语义搜索
传统搜索依赖关键词匹配,例如用户搜索"付款失败",只能匹配包含"付款失败"的内容。
语义搜索可以匹配意思相近的内容,例如:
txt
支付不成功
订单付款异常
扫码支付失败
这些内容即使关键词不同,也可能被识别为语义相关。
3. FAQ 智能问答
可以把常见问题和答案提前向量化。
当用户输入问题时,系统自动找到最相似的 FAQ,并返回对应答案。
例如:
txt
用户问题:怎么修改密码?
匹配结果:忘记密码如何重置?
4. 本地 AI 工作台
如果要做一个本地 AI 工作台,可以把这个模型作为"本地嵌入模型",负责文档向量化和检索。
它可以和大语言模型配合使用:
txt
用户问题
↓
向量模型生成 query 向量
↓
从本地知识库检索相关文档
↓
把检索结果交给大模型
↓
生成最终回答
这就是常见的 RAG 架构。
八、常见问题
1. 第一次运行很慢怎么办?
第一次运行需要下载模型文件,所以会比较慢。只要模型成功下载到 D:/models/cache,后续运行就会快很多。
2. 下载失败怎么办?
如果出现网络错误,可以检查:
- 当前环境是否能访问 Hugging Face
- 是否需要代理
- 缓存目录是否有写入权限
- Node.js 版本是否兼容
- 依赖包是否正确安装
3. 可以离线使用吗?
可以。
前提是模型文件已经完整下载到本地缓存目录。后续运行时,程序会优先从缓存读取模型。
4. 为什么要设置 normalize: true?
因为归一化后的向量更适合做相似度计算。
在语义搜索中,常用余弦相似度来判断两个文本是否相似。归一化可以让向量比较更加稳定。
九、项目中的推荐封装方式
在真实项目中,可以把向量提取逻辑封装成一个单独模块,例如:
js
const { pipeline, env } = require('@huggingface/transformers');
env.cacheDir = 'D:/models/cache';
let extractor = null;
async function getExtractor() {
if (!extractor) {
extractor = await pipeline(
'feature-extraction',
'Xenova/bge-base-zh-v1.5'
);
}
return extractor;
}
async function embedText(text) {
const model = await getExtractor();
const output = await model(text, {
pooling: 'mean',
normalize: true,
});
return Array.from(output.data);
}
module.exports = {
embedText,
};
这样其他业务代码就可以直接调用:
js
const { embedText } = require('./embedding');
async function main() {
const vector = await embedText('本地 AI 工作台如何实现?');
console.log(vector.length);
}
main();
这种封装方式可以避免每次请求都重新加载模型,提高运行效率。
十、总结
本文通过一段 Node.js 代码,演示了如何使用 @huggingface/transformers 下载、缓存并运行中文向量模型 Xenova/bge-base-zh-v1.5。
这段代码虽然简单,但它是构建本地 AI 应用的重要基础。
它可以用于:
- 中文文本向量化
- 本地知识库检索
- FAQ 智能问答
- 语义搜索
- RAG 系统
- 本地 AI 工作台
整体流程可以概括为:
txt
安装依赖
↓
设置模型缓存目录
↓
加载 feature-extraction 模型
↓
输入中文文本
↓
生成归一化向量
↓
用于语义检索或相似度计算
如果你正在开发本地 AI 工作台、知识库系统或智能搜索功能,这段代码可以作为向量模型接入的第一步。