向量搜索(Vector Search)是构建智能问答、AI 搜索系统的基础能力。本文将介绍如何使用 Node.js、OpenAI Embedding API 和 MongoDB,实现一个轻量级的文本向量知识库搜索系统,支持语义检索和相似内容召回。
目标
实现一个可执行的完整流程:
原始文档 → 文本分块→ OpenAI 向量生成→ 存入 MongoDB → 用户查询 → 相似内容检索
📦 环境准备
- Node.js 18+MongoDB 本地或 Atlas 云服务OpenAI API Key
安装依赖
npm install axios mongodb dotenv
.env
配置:
OPENAI_API_KEY=你的OpenAI密钥MONGO_URI=mongodb://localhost:27017
文本切分与向量存储
我们将文档按固定长度切分为片段(chunk),再通过 OpenAI API 转为向量,并存入 MongoDB。
// index.jsrequire('dotenv').config();const axios = require('axios');const { MongoClient } = require('mongodb');const OPENAI_API_KEY = process.env.OPENAI_API_KEY;const MONGO_URI = process.env.MONGO_URI;const splitText = (text, size = 200) => Array.from({ length: Math.ceil(text.length / size) }, (_, i) => text.slice(i * size, (i + 1) * size));async function getEmbedding(text) { const res = await axios.post( 'https://api.openai.com/v1/embeddings', { input: text, model: 'text-embedding-ada-002' }, { headers: { Authorization: `Bearer ${OPENAI_API_KEY}` } } ); return res.data.data[0].embedding;}async function storeChunks(chunks) { const client = new MongoClient(MONGO_URI); await client.connect(); const col = client.db('vector_store').collection('docs'); for (const chunk of chunks) { const embedding = await getEmbedding(chunk); await col.insertOne({ chunk, embedding }); } await client.close();}(async () => { const text = '这是一个用于测试的知识库文档,将被切分并转为向量存储。'; const chunks = splitText(text); await storeChunks(chunks);})();
本地语义检索(余弦相似度)
用户输入问题后,我们获取其向量并与数据库中所有向量计算相似度,返回最相关的内容。
// search.jsconst similarity = (a, b) => a.reduce((sum, val, i) => sum + val * b[i], 0) / (Math.hypot(...a) * Math.hypot(...b));async function search(query, topK = 3) { const client = new MongoClient(MONGO_URI); await client.connect(); const col = client.db('vector_store').collection('docs'); const docs = await col.find({}).toArray(); const queryVec = await getEmbedding(query); const results = docs .map(doc => ({ ...doc, score: similarity(queryVec, doc.embedding) })) .sort((a, b) => b.score - a.score) .slice(0, topK); for (const r of results) { console.log(`\n[Score: ${r.score.toFixed(4)}]`); console.log(r.chunk); } await client.close();}search('向量存储是什么?');
使用 MongoDB Atlas 向量搜索(可选)
如果使用 MongoDB Atlas,可开启原生向量索引,提升搜索性能。
向量索引配置(Atlas → Search Index → Create Index)
{ "fields": { "embedding": { "type": "vector", "dimensions": 1536, "similarity": "cosine" } }}
修改检索逻辑:
const pipeline = [ { $vectorSearch: { index: "vector_index", path: "embedding", queryVector: queryVec, numCandidates: 100, limit: topK } }, { $project: { chunk: 1, score: { $meta: "vectorSearchScore" } } }];const results = await col.aggregate(pipeline).toArray();
本项目实现了一个基础的文本向量知识库,具备以下能力:
- 支持文档分块和语义向量生成支持本地余弦相似度检索可扩展到 MongoDB Atlas 向量搜索后续可接入 LLM(如 ChatGPT)做回答生成,实现 RAG 问答系统