向量数据库基础概念与分类

日期:2026年4月9日

什么是向量数据库

向量数据库是专门用于存储和检索高维向量数据的数据库系统,主要用于相似性搜索、推荐系统、语义搜索等AI应用场景。其核心目的是将各种数据转换为数值化的特征表示(向量),然后高效地进行相似性搜索和关联查询

核心工作原理

  1. 特征提取(Embedding)

    • 文本: 通过BERT、OpenAI Embedding等模型转换为向量
    • 图像: 使用ResNet、CLIP等模型提取视觉特征
    • 音频: 通过Whisper、VGGish等模型生成音频特征
    • 结构化数据: 数值化编码后形成特征向量
  2. 相似性度量

    • 余弦相似度: 最常用,关注方向而非大小
    • 欧氏距离: 关注绝对距离
    • 内积: 用于某些特定场景
  3. 高效检索

    • 通过专门的近似最近邻(ANN)算法实现快速搜索
    • 在百万/十亿级向量中毫秒级返回最相似结果

主要向量数据库分类

专用向量数据库

  • Pinecone: 完全托管的向量数据库服务,API简单易用
  • Weaviate: 开源向量搜索引擎,支持GraphQL查询
  • Milvus: 开源向量数据库,CNCF项目,功能丰富
  • Qdrant: Rust编写的开源向量搜索引擎,性能优秀
  • Vespa: Yahoo开源的大规模文本和向量搜索平台
  • Vald: Kubernetes原生的分布式向量搜索引擎

传统数据库的向量扩展

  • PostgreSQL + pgvector: 最流行的向量扩展方案
  • Redis + RedisVL: Redis的向量搜索模块
  • Elasticsearch: 8.x版本开始支持向量搜索
  • MongoDB Atlas: 支持向量搜索功能
  • Oracle Database: 23c版本引入向量数据类型
  • SQL Server: 支持向量函数

云服务商解决方案

  • AWS OpenSearch: 支持k-NN搜索
  • Google Vertex AI Matching Engine: Google Cloud的向量匹配服务
  • Azure Cognitive Search: 支持向量搜索
  • 阿里云OpenSearch: 支持向量检索

兼容性分析

API兼容性

大多数向量数据库不直接兼容,因为:

  • 比如搜索"如何修理自行车"能匹配到"自行车维修指南"

去重和聚合

  • 发现重复或相似的内容
  • 自动分组相关文档/图片

为什么需要专门的向量数据库?

传统数据库在处理高维向量时效率极低:

  • 维度灾难: 高维空间中距离概念失效
  • 计算复杂度: 暴力搜索O(n)无法满足实时需求
  • 内存效率: 专门的索引结构节省存储空间

向量数据库通过专门优化的数据结构和算法解决了这些问题,让AI应用能够实时处理大规模向量数据。

简单来说,向量数据库就是AI时代的"搜索引擎",只不过它搜索的是语义相似性而不是关键词匹配。

前端技术栈数据向量化方案推荐(DeepSeek 大模型)

核心场景

前端数据向量化主要覆盖以下场景:

场景 说明 典型应用
本地知识库搜索 用户文档/笔记的语义检索 个人知识管理、离线文档搜索
智能客服/FAQ 产品文档向量化后供用户自然语言查询 官网帮助中心、AI客服
内容推荐 基于内容的语义相似度推荐 文章推荐、商品发现
AI Copilot 代码库/设计稿向量化辅助开发 IDE插件、设计工具插件

方案一:纯前端向量化(浏览器端 Embedding)

适合隐私敏感、离线优先、轻量级场景。

┌─────────────────────────────────────────┐
│  浏览器                                    │
│  ┌──────────┐  ┌───────────┐  ┌────────┐ │
│  │ 用户输入   │→│Transformers│→│ 向量存储 │ │
│  │           │  │.js 嵌入模型│  │(IndexedDB)│ │
│  └──────────┘  └───────────┘  └────────┘ │
└─────────────────────────────────────────┘

技术组件:

组件 推荐方案 说明
Embedding 模型 Xenova/all-MiniLM-L6-v2 轻量,适合浏览器运行
Embedding 模型(中文) Xenova/bge-small-zh-v1.5 BGE 中文小模型,384维
向量存储 IndexedDB + 自定义索引 浏览器原生,无需服务端
运行时 @xenova/transformers Transformers.js,WASM运行

示例代码:

import { pipeline } from '@xenova/transformers';

// 创建前端 embedding pipeline
const embedder = await pipeline(
  'feature-extraction',
  'Xenova/bge-small-zh-v1.5'  // 中文轻量模型
);

// 文本转向量
const text = '如何配置DeepSeek API密钥?';
const output = await embedder(text, { pooling: 'mean', normalize: true });
const vector = Array.from(output.data);  // 384维向量

// 存储到 IndexedDB(可用 idb 库)
// 搜索时计算余弦相似度,取 Top-K

优缺点:

  • ✅ 零服务端成本,数据不出浏览器
  • ✅ 离线可用,隐私安全
  • ❌ 模型体积受限(几十MB),大模型无法运行
  • ❌ 嵌入质量不如服务端大模型

方案二:DeepSeek API 向量化(推荐)

DeepSeek 提供与 OpenAI 兼容的 Embedding API,适合生产级应用

┌──────────┐     HTTP/API     ┌──────────────┐
│  前端应用  │ ───────────────→ │ DeepSeek API  │
│ (浏览器)   │ ←─────────────── │ /v1/embeddings│
└──────────┘                  └──────────────┘
      │                              │
      │ 存储/检索向量                  │
      ▼                              ▼
┌──────────┐                  ┌──────────────┐
│ BFF 层    │ ←──────────────→ │  向量数据库    │
│ (Next.js) │                  │ (pgvector等)  │
└──────────┘                  └──────────────┘

为什么需要 BFF(Backend For Frontend)层:

  • API Key 不能暴露在前端
  • 向量数据库通常不支持浏览器直连
  • 需要做请求聚合、缓存、权限控制

DeepSeek Embedding API 调用:

// ===== BFF 层 (Next.js API Route / Express) =====
// POST /api/embed
export async function embedText(text: string) {
  const response = await fetch('https://api.deepseek.com/v1/embeddings', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'deepseek-embedding',  // DeepSeek 嵌入模型
      input: text,
    }),
  });
  const data = await response.json();
  return data.data[0].embedding;  // 返回向量数组
}

// 批量嵌入
export async function embedBatch(texts: string[]) {
  const response = await fetch('https://api.deepseek.com/v1/embeddings', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.DEEPSEEK_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'deepseek-embedding',
      input: texts,  // 支持数组输入
    }),
  });
  const data = await response.json();
  return data.data.map((item: any) => item.embedding);
}

前端调用示例(React):

// ===== 前端组件 =====
async function searchDocuments(query: string): Promise<SearchResult[]> {
  // 1. 通过 BFF 获取查询向量
  const embedRes = await fetch('/api/embed', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text: query }),
  });
  const queryVector = await embedRes.json();

  // 2. 通过 BFF 执行向量搜索
  const searchRes = await fetch('/api/search', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ vector: queryVector, topK: 5 }),
  });
  return searchRes.json();
}

// React 组件中使用
function SearchBox() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);

  const handleSearch = async () => {
    const res = await searchDocuments(query);
    setResults(res);
  };

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <button onClick={handleSearch}>搜索</button>
      {results.map(r => <ResultCard key={r.id} data={r} />)}
    </div>
  );
}

方案三:LangChain.js + DeepSeek 全链路方案

适合需要 Agent/RAG 能力的复杂前端应用

┌────────────────────────────────────────────────┐
│  前端 / Node.js BFF                              │
│                                                 │
│  LangChain.js                                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐ │
│  │ Document │→│ DeepSeek  │→│ VectorStore   │ │
│  │ Loader   │  │ Embedding│  │ (pgvector/    │ │
│  │ (PDF/MD) │  │          │  │  Qdrant)      │ │
│  └──────────┘  └──────────┘  └──────────────┘ │
│                       │              │          │
│                       ▼              ▼          │
│               ┌──────────┐  ┌──────────────┐  │
│               │ DeepSeek │←─│ Retriever    │  │
│               │ Chat (LLM)│  │              │  │
│               └──────────┘  └──────────────┘  │
└────────────────────────────────────────────────┘

示例代码(Node.js BFF):

import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { PGVectorStore } from '@langchain/community/vectorstores/pgvector';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents';
import { createRetrievalChain } from 'langchain/chains/retrieval';

// DeepSeek Embedding(兼容 OpenAI 接口)
const embeddings = new OpenAIEmbeddings({
  model: 'deepseek-embedding',
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1',
  },
});

// DeepSeek Chat(大模型)
const llm = new ChatOpenAI({
  model: 'deepseek-chat',
  temperature: 0.7,
  apiKey: process.env.DEEPSEEK_API_KEY,
  configuration: {
    baseURL: 'https://api.deepseek.com/v1',
  },
});

// 1. 文档向量化入库
async function indexDocuments(docs: string[]) {
  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 500,
    chunkOverlap: 50,
  });

  const splitDocs = await splitter.createDocuments(docs);

  await PGVectorStore.fromDocuments(splitDocs, embeddings, {
    tableName: 'documents',
    connectionString: process.env.DATABASE_URL,
  });
}

// 2. RAG 检索链
async function askWithContext(question: string): Promise<string> {
  const vectorStore = await PGVectorStore.initialize(embeddings, {
    tableName: 'documents',
    connectionString: process.env.DATABASE_URL,
  });

  const retriever = vectorStore.asRetriever({ k: 5 });

  const prompt = ChatPromptTemplate.fromTemplate(`
    根据以下上下文回答问题。如果上下文中没有相关信息,请如实说明。

    上下文:
    {context}

    问题:{input}
  `);

  const combineDocsChain = await createStuffDocumentsChain({
    llm,
    prompt,
    outputParser: new StringOutputParser(),
  });

  const retrievalChain = await createRetrievalChain({
    retriever,
    combineDocsChain,
  });

  const result = await retrievalChain.invoke({ input: question });
  return result.answer;
}

向量数据库选型(前端视角)

向量数据库 适用场景 前端接入方式 推荐度
pgvector (PostgreSQL) 已有 PG 的项目 BFF → SQL 查询 ⭐⭐⭐⭐⭐
Qdrant 高性能、独立部署 BFF → REST/gRPC ⭐⭐⭐⭐⭐
LanceDB 纯前端/边缘计算 WASM 直连浏览器 ⭐⭐⭐⭐
Weaviate 全功能、GraphQL BFF → GraphQL ⭐⭐⭐⭐
Pinecone 免运维、快速上线 BFF → REST API ⭐⭐⭐⭐
Chroma 本地开发/原型 BFF → Python/JS SDK ⭐⭐⭐

推荐方案总结

需求层级 推荐方案 技术组合
轻量原型/PoC 纯前端 Transformers.js + IndexedDB + 内积搜索
中小型应用 DeepSeek API + pgvector Next.js BFF + DeepSeek Embedding + pgvector
生产级 RAG LangChain.js 全链路 Node.js BFF + DeepSeek Embedding + DeepSeek Chat + Qdrant/pgvector
离线优先应用 混合模式 Transformers.js(本地)+ DeepSeek(联网增强)

关键注意事项

  1. API Key 安全:DeepSeek API Key 绝对不能暴露在前端代码中,必须通过 BFF 层中转
  2. 向量维度匹配:DeepSeek Embedding 输出维度需与向量数据库索引维度一致,更换模型后需重新建库
  3. 文档分块策略:前端展示时需考虑分块大小(建议 300-500 token),过大会稀释语义,过小会丢失上下文
  4. 流式输出:DeepSeek Chat 支持 SSE 流式返回,前端可使用 EventSourcefetch + ReadableStream 实现打字机效果
  5. 缓存策略:高频查询的 Embedding 结果建议在 BFF 层缓存(Redis),减少 API 调用成本
  6. 降级方案:当 DeepSeek API 不可用时可切换到本地 Transformers.js 嵌入模型作为 fallback

LLM 语义打分:一种轻量向量化方案

传统 Embedding 靠专用模型把数据"算"成高维向量(384~1536 维),而 LLM 方案是把向量化变成一个"理解后打分"的认知任务:人工定义一组语义维度,LLM 理解内容后逐个维度输出评分。

工作原理

文本 → DeepSeek Chat API
     → System Prompt 定义 N 个语义维度(如:技术性、实用性、AI相关性等)
     → LLM 对每个维度打分 [0.00 ~ 1.00]
     → 形成 N 维语义向量

示例:8 维语义维度

维度 说明 示例文本打分(前端向量化文章)
技术性 涉及编程/工程实现的程度 0.85
实用性 可直接落地的程度 0.90
理论性 底层原理/数学推导的程度 0.25
AI/ML 相关性 与人工智能的关联度 0.95
前端相关性 与前端/浏览器/UI 的关联度 0.88
后端相关性 与后端/服务端/数据库的关联度 0.15
入门友好度 对初学者易于理解的程度 0.80
创新性/前沿性 涉及新技术/新思路的程度 0.70

为什么传统 Embedding 不需要指定维度?

传统 Embedding 模型(BERT、BGE、OpenAI text-embedding 等)是专门为"文本→向量"这个任务训练的

训练过程:
海量文本 → 让模型学会"语义相近的文本向量也接近"
         → 模型内部自动学会提取 768 维(或更多)特征
         → 每个维度代表模型"自己发现"的语义特征,人类看不懂

这些维度是模型在训练过程中自动涌现的,不是人工定义的。比如 BERT 的 768 维向量,第 127 维可能模糊地代表"与金融相关",但没人能确切说出它是什么——这就是"黑盒"。

为什么 LLM 方案必须指定维度?

LLM(如 DeepSeek)是通用对话模型,不是专用 Embedding 模型。它不会直接输出数值向量:

LLM 能做到:   "这篇文章是关于前端的"    ← 自然语言输出
LLM 做不到:   直接输出一个 [0.88, 0.15, ...]   ← 没有这个原生能力

所以必须通过 prompt 把"输出向量"这个需求翻译成 LLM 能理解的"文字打分任务",人为定义每个维度的含义,LLM 才能执行。

两种方案本质区别

传统 Embedding 模型 LLM 语义打分
核心机制 模型自动提取语义特征 人工定义维度 → LLM 理解打分
"谁定义维度" 训练数据决定(人类不可控) 人类显式定义
维度含义 黑盒,不可解释 白盒,每个维度有名称
实现方式 专用 Embedding API Prompt + Chat API
向量维度 384 ~ 1536(模型固定) 8 ~ N(人类灵活调整)
跨模态 需要为每种模态训练独立模型 天然统一:先转文字,再打同一套分
准确度 高(专门优化) 中(依赖 LLM 理解能力)
成本 低(专用 API 便宜) 较高(走 Chat API,按 token 计费)
适用场景 生产级语义搜索 原型验证、小数据集、需要可解释性、跨模态

优势:天然跨模态

传统 Embedding 需要为每种模态准备专用模型(文本用 BERT、图片用 CLIP、音频用 Whisper),不同模态产生的向量不在同一个语义空间。

LLM 语义打分方案天然统一:

图片  → VLM/OCR 描述成文字 → LLM 在统一维度上打分 → 同一向量空间
音频  → ASR 转文字          → LLM 在统一维度上打分 → 同一向量空间
视频  → 抽帧 + ASR 转文字   → LLM 在统一维度上打分 → 同一向量空间
文本  → 直接输入            → LLM 在统一维度上打分 → 同一向量空间

关键点:无论什么模态,最终都落入同一套语义维度空间,"搜图片找相关文档""用语音搜视频"等跨模态搜索天然成立。

关键注意事项

  1. 维度设计:维度必须覆盖业务关心的一切语义面,太少区分度不够,太多成本上升
  2. 确定性temperature=0,确保同一文本多次调用返回一致结果
  3. 大小写归一:输入前统一 .toLowerCase(),避免 LLM 对大小写产生不同的语义判断
  4. 适用边界:适合文档量 < 10000 的轻量场景,大数据量建议走专用 Embedding 模型

主流云端 Embedding API

如果你不需要自定义维度,只想做通用语义搜索,以下云端 API 可以直接调用:

服务商 推荐模型 维度 中文效果 成本 特点
OpenAI text-embedding-3-small 512/1536 ⭐⭐ ~$0.02/百万token 生态最完善
OpenAI text-embedding-3-large 256/1024/3072 ⭐⭐ ~$0.13/百万token 可调维度,精度最高
Cohere embed-multilingual-v3 1024 ⭐⭐⭐⭐ 有免费额度 多语言支持好
Voyage AI voyage-multilingual-2 1024 ⭐⭐⭐⭐⭐ ~$0.05/百万token 中文日文韩文顶级
Jina AI jina-embeddings-v3 1024 ⭐⭐⭐⭐ 有免费额度 支持 8192 token 长文本
硅基流动 BAAI/bge-large-zh-v1.5 1024 ⭐⭐⭐⭐⭐ 极便宜 兼容 OpenAI 格式,中文 SOTA

本地开源模型(不需联网)

模型 维度 中文效果 适用场景
BGE-large-zh-v1.5 1024 ⭐⭐⭐⭐⭐ 中文 SOTA,智源出品
BGE-small-zh-v1.5 512 ⭐⭐⭐⭐ 轻量版,适合本地/边缘部署
BGE-M3 1024 ⭐⭐⭐⭐⭐ 多语言 + sparse/dense 双模
GTE-Qwen2 768/1536 ⭐⭐⭐⭐⭐ 阿里出品,新晋强手
M3E 768 ⭐⭐⭐⭐ 国产轻量,社区使用广泛
text2vec-large-chinese 1024 ⭐⭐⭐⭐ CoSENT 训练,经典方案

选型建议

  • 个人项目/原型:硅基流动 API(BGE-large),免部署,一个月几块钱
  • 公司内部应用:BGE-M3 本地部署,数据不出内网
  • 英文/海外场景:OpenAI text-embedding-3-small,生态最好
  • 多语言混合:Voyage AI,中日韩效果最强

场景选择指南

核心判断标准:你的搜索是"通用语义相似"还是"带业务维度的偏好过滤"

传统 Embedding 适用场景

特征:需求是通用的,不绑定特定业务视角

场景 说明
RAG 知识库问答 用户问"Redis 持久化有几种方式",从文档库召回最相关段落
代码搜索 输入代码片段,找出库中最相似实现
相似商品推荐 用户看了一双鞋,推荐其他类似的鞋
内容去重 找出数据库中语义重复的文章
翻译记忆库 做过类似翻译的句子检索

LLM 语义打分适用场景

特征:需要从特定角度评价/过滤内容,而且这个角度可能变化

场景 说明
内容运营筛选 找"技术性高但入门友好度低"的文章(需要改写科普版)
多模态素材库 图片/视频/音频/文档混在一起,按"前端相关性 + 入门友好度"统一检索
个性化搜索 A 用户偏好理论深度,B 用户偏好实用教程,同一查询给不同维度权重
可解释推荐 结果附带"技术性 0.92, 实用性 0.88",用户知道为什么推荐
MVP 快速验证 只有几百篇文档,不想搭 Embedding 服务 + 向量数据库
跨模态检索 图片/视频/音频都先转文字描述,再用同一套维度打分

一句话总结

需求 方案 原因
"找和这段文字最像的内容" 传统 不需要人工定义标准
"按技术性高、入门度低筛选" LLM 带了业务维度过滤
万级文档,通用 RAG 传统 量大 + 通用需求
百级文档 + 跨模态 LLM 量小 + 跨模态天然统一
需要告诉用户"为什么推荐" LLM 可解释性
不需要解释,结果对就行 传统 成本更低

两个方案不是替代关系——类似 搜索引擎 vs 标签筛选系统:日常 RAG 走传统 Embedding,当业务需要按特定视角过滤或 curation 时,LLM 打分更有优势。

示例

demo/deepseek_ts_embedding