简介
在海量数据中快速找到相似项是许多智能应用的核心需求,向量数据库正是解决这一问题的关键技术之一。
什么是向量数据库?

在数学中,向量是一个有序的数值序列。例如,二维平面中的一个点的位置可以用两个实数的向量(x, y)来表示。同理,三维空间中的点可以用 (x, y, z) 表示。而在计算机科学中,这些点可以表示为事务的特征或属性,向量数据库就是用来存储这些点的特征或属性的。
向量数据的来源
我们刚才说了,向量数据库存储的这些'点'其实是事务的特征,那么具体是指什么呢?
假设我们是一个犬类动物爱好者,我们可以通过体型大小、毛发长度、鼻子长短等特征为狗狗分类。如果将犬类的体型大小、毛发长度用二维向量记录下来,就是下面这个样子:

X 轴表示犬类体型,取值范围从大到小为 0 到 1。
再加上毛发长度的 Y 轴,就是下面的样子:

接下来,我们再延伸到三维坐标系,将犬类鼻子的长短记录到 Z 轴,便得到了下面的三维向量数据:

于是乎我们就得到了基于犬类体型大小、毛发长度等鼻子长短等特征的三维向量特征点,也就是 x、y、z 轴的坐标,这些数据便是向量数据,存储到向量数据库。
向量数据库有了这些数据,便可以提供向我们的向量检索。例如,我们想养一只与哈士奇相似的狗,那么会推荐金毛(0.6,0.65,0.66),而不会推荐泰迪(0.1,0.45,0.23)。
更高维度的向量数据
当然了,我们不能只根据三个特征就推荐你养哪只狗狗,很明显这样不够精确。那么我们可以将犬类更多的特征,例如眼睛大小、服从性、攻击性等用向量数据记录下来。
也许你很难想象这些数据记录到四维、五维空间会是什么样子,但这不重要,我们只需要知道这些特征换成向量数据就是在向后面追加数字即可,例如:(0.53,0.4,0.75,0.11,0.23,……)

我们可以用这种方式表示所有事物,不管是具象的还是抽象的,例如,一段话、一张照片、喜怒哀乐、悲欢离合。而且数据的维度越高,描述的数据就越精确。

如上图,OpenAI 的文本向量模型 text-embedding-ada-002 可以输出 1536 维的数据。实际上在真实的生产环境中,上千的向量维度和上亿的向量数据都是正常的。
在高维空间中,距离度量的意义会发生变化,这被称为'维度灾难'。随着维度增加,所有点之间的距离趋向于一致,使得区分最近邻变得困难。因此,选择合适的距离度量(如余弦相似度、欧氏距离)和索引算法至关重要。
向量数据的检索算法
ANN 算法
ANN(Approximate Nearest Neighbor,近似最近邻搜索)算法是一种用于在大规模数据集中快速找到一个或多个近似最近邻的技术。由于精确最近邻搜索(Exact Nearest Neighbor Search)在大数据量下计算成本过高,ANN 算法通过牺牲少量的精度来换取巨大的速度提升。
ANN 算法的类型很多,它们采用不同的技术实现和策略来在大规模数据集中加速最近邻搜索。常见的包括 Flat、k-means、LSH、HNSW 等。相似最近邻搜索问题是向量数据库产品的核心,一个成熟的向量数据库通常集成了多种 ANN 算法,并在搜索时综合各种指标选择最合适的策略来利用这些算法。
Flat
关于搜索我们首先能想到的就是遍历搜索,遍历比较目标点,最终找个你想要的数据,这种方式就是 Flat 的实现逻辑,即:暴力搜索、平推遍历。Flat 虽然很精确,但它的短板也很明显,那就是因为要遍历比较数据,它的检索速度非常慢,在海量数据线下我们一般不会使用它。
其时间复杂度为 O(N),其中 N 是数据量。当数据量达到百万级时,响应时间可能达到秒级甚至分钟级,无法满足实时业务需求。
k-means
聚类算法的原理是:将数据集中的样本划分为若干组,使得同一组内的样本彼此相似,而不同组之间的样本差异较大。
聚类算法的种类有很多,k-means 是其中最常见的算法。k-means 对数据的处理如下图,在搜索时我们只需要找出查询向量最近的哪个质心,然后在这个质心的簇中查找数据即可,达到缩小搜索范围的目的。

就像 Flat 算法,聚类算法 k-means 也有自己的缺点,例如下图:虽然查询的向量距离他最近的向量点在质心 B 的簇里,但由于它距离质心近 A 更近,这种情况下就只能搜索到 A 簇的数据,导致召回率下降。

解决上面的问题的方式很多,例如:K-Means++ 初始化、谱聚类、层次聚类、DBSCAN 等。在实际工程中,常结合 IVF(倒排文件索引)使用,先定位到几个候选簇,再在簇内进行搜索。
LSH
位置敏感 Hash 算法(Locality Sensitive Hashing, LSH)使用一组哈希函数将相似向量映射到'桶'中,从而使相似向量具有相同的哈希值,这样,就可以通过比较哈希值来判断向量之间的相似度。

LSH 算法的优势在于构建索引速度快,适合动态数据。但其不足在于参数调优复杂,且在大型数据集中使用随机投影算法获取 hash 值时,生成质量好的随机的投影矩阵计算成本会很高,且召回率受阈值影响较大。
HNSW
分层导航小世界算法(Hierarchical Navigable Small World, HNSW)是目前工业界应用最广泛的算法之一。它构建了一个多层级的图结构,上层节点稀疏,下层节点密集。搜索时从顶层开始,逐步向下层逼近,能够快速收敛到局部最优解。
HNSW 结合了图的灵活性和树结构的效率,能够在保持较高召回率的同时提供极低的延迟。其构建索引的时间复杂度约为 O(N log N),查询复杂度约为 O(log N)。
其他算法
此外还有很多算法,他们有各自的优点和短板,例如:
- IVF-PQ:倒排文件 + 乘积量化,适合超大规模数据压缩存储。
- SCANN:Google 提出的算法,针对 TensorFlow 优化,支持量化加速。
- DiskANN:微软提出,适用于内存受限场景,将部分索引存储在磁盘上。
ANN-基准
[ANN-基准] 是一种用于评估各种向量数据库和近似最近邻(ANN)算法性能的工具。
- 数据集和参数规格:ANN 基准提供大小、类型、维度不同数据集。每套数据集匹配一套参数,如:检索的最近邻数量、使用的距离计算公式等。
- 计算召回率(search recall):ANN 基准计算召回率,即返回的 k 个近邻中包含真正最近邻的比例。召回率是用于评估系统向量检索准确性的重要指标。通常设定 Recall@10 或 Recall@100。
- 计算 RPS/QPS:ANN 基准还可以计算 RPS(或者也叫 QPS,query per second),即向量数据库和 ANN 算法处理 query(查询请求)的速度。RPS 是用于评估系统速度和可扩展性的重要指标。
我们可以使用 ANN 基准,在同一条件下比较不同向量数据库和 ANN 算法的性能,从而更快速找到最合适的选择。
小结
从上面的例子我们可以看出,算法并非解决问题的'银弹',每种算法都有自己的优势的短板,我们在使用时需要根据实际情况加以区分。此外 ANN 算法也是向量数据库产品的核心,你可以用 ANN-基准来对向量数据库做评估,找到你需要的产品。
向量数据库产品

随着这一轮人工智能的热潮,向量数据库的热度也从年初一直延续至今。目前市面上的向量数据库产品已经非常丰富。
我们可以将它们'向量化'做一个比较分类,直观的看一下他们的特征。
将他们按照本地部署和云部署分类如下:

按照实现方式、开源程度可以做如下区分:

每种向量数据库支持的搜索算法也不尽相同:

除此之外,在实际的业务场景中,向量数据库选型中,你还需要关注如下问题:
- 分布式能力:CAP 如何取舍的,可用性和稳定性如何。是否支持水平扩展(Sharding)。
- 支持的数据类型和维度:确保向量数据库支持你的数据类型和维度。有些数据库可能更适合特定类型的数据,如文本、图像或数值型数据。
- 可扩展性:确认向量数据库的可扩展性。考虑到项目可能的增长,确保数据库可以有效地处理大量的数据和查询请求。
- API 和集成:评估数据库的 API 和集成能力。确保数据库可以轻松地集成到你的应用程序中,并且提供方便易用的 API。
- 安全性:安全性是任何数据库选择的一个关键因素。确保向量数据库提供适当的安全性特性,如数据加密、数据隔离、访问控制和身份验证。
- 社区和支持:考察数据库的社区支持和文档。一个活跃的社区通常能够提供更好的支持和解决问题的资源。
- 成本:评估数据库的总体成本,包括许可费、运维成本以及可能的扩展成本。确保数据库符合你的预算和资源限制。
关于向量数据库产品更详细的内容,我这里就不展开了。如果你没有接触过向量数据库,建议了解下以下几款产品。
- 专业的向量数据库产品:
ChromaDB(轻量级)、Milvus(高性能开源)、Pinecone(SaaS 托管)、Weaviate(多模态)。
- 具有向量数据库能力的产品:
PostgreSQL & pgvector(关系型增强)、ElasticSearch 8.0+(全文检索增强)、Redis(内存缓存增强)。
向量数据库与 LLMs 的融合
市场前景
你可能看过 Zilliz 的融资新闻,这家向量数据库公司借着这轮大语言模型的东风,拿到了 B+轮融资 6000 万美元,融资规模达到了 1.13 亿美元,Zilliz 的开源向量数据库产品,就是我们上面提到的 Milvus。
可以看出,向量数据库应用的前景市场还是认可的。它是连接非结构化数据与大语言模型的关键桥梁。
向量数据库与 LLM 的对接
我们上一篇文章讲到了 LangChain,并以 ChromaDB 为例,演示了如何用 LangChain 对接向量数据,做一个本地的文档知识库。
在这篇文章里,我们在开发本地文档知识库时做了如下几件事情:
- 配置环境:Python、LangChain、ChatGLM2、ChromaDB 等。
- 将本地数据切片向量化:Docs -> Embeddings -> ChromaDB。
- 编码对接 ChatGLM2、ChromaDB 等,完成开发。
接下来我们讲一下步骤二:将本地数据切片向量化,这是向量数据库与 LLM 对接的核心。
分词(Tokenization)

在使用向量数据库时,分词(tokenization)的意义与处理自然语言文本的相关任务密切相关。分词是将连续的文本数据切分成词(或称为单词)的过程。对于自然语言处理(NLP)和文本检索等任务,分词是一个重要的预处理步骤,因为它将文本数据转化为更易于处理的语言单元,每个语言单元可以是一个字母、数个词或一句话。
在 LangChain 中,我们可以通过 tiktoken 分词器对文档进行拆分,tiktoken 是由 OpenAI 开源的快速 BPE 分词器。
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
chunk_size=100, chunk_overlap=0
)
texts = text_splitter.split_text(state_of_the_union)
除了字符分割,还可以使用语义分割(Semantic Splitter),根据句子边界或段落结构进行切分,以保持上下文的完整性。
嵌入(Embeddings)

Embeddings(嵌入):向量数据库存储的是向量数据,我们的本地语料需要通过 Embeddings 的方式将自然语言转成成向量,也就是将数据映射到低维空间的表示形式。
最常见的例子是词嵌入(Word Embeddings),它是将单词映射到实数向量的表示。词嵌入模型(如 Word2Vec、GloVe、FastText)通过学习大量文本语料库中的上下文关系,将每个单词映射到一个固定维度的实数向量。这样的词嵌入向量能够捕捉到单词之间的语义关系,使得在向量空间中相似的词语距离更近。
在 LangChain 中,我们可以使用 OpenAIEmbeddings 将文档转换成向量,并存储到向量数据库。
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
docsearch = Chroma.from_documents(split_docs, embeddings)
对接 LLM
最终我们通过 LangChain 的问答链实现与用户的交互。
embeddings = OpenAIEmbeddings()
vector_store = Chroma.from_documents(documents, embeddings)
retriever = vector_store.as_retriever(search_kwargs={"k": 5})
system_template = """
Use the following context to answer the user's question.
If you don't know the answer, say you don't, don't try to make it up. And answer in Chinese.
-----------
{question}
-----------
{chat_history}
"""
messages = [
SystemMessagePromptTemplate.from_template(system_template),
HumanMessagePromptTemplate.from_template('{question}')
]
prompt = ChatPromptTemplate.from_messages(messages)
qa = ConversationalRetrievalChain.from_llm(
ChatOpenAI(temperature=0.1, max_tokens=2048),
retriever,
condense_question_prompt=prompt
)
chat_history = []
while True:
question = input('问题:')
result = qa({'question': question, 'chat_history': chat_history})
chat_history.append((question, result['answer']))
print(result['answer'])
实现效果

更多的 Embeddings
我们之前有提到文本向量可以通过 OpenAI 的 text-embedding-ada-002 模型生成,相似的:
- 图像向量可以通过 clip-vit-base-patch32 模型生成。
- 音频向量可以通过 wav2vec2-base-960h 模型生成。
- 还有一些对中文支持更好的,例如:shibing624/text2vec-base-chinese。
这些向量都是通过 AI 模型生成的,所以它们都是具有语义信息的。在生产环境中,建议根据业务场景选择本地部署的开源模型以降低延迟和成本,或使用商业 API 以获得更高的精度。
高级实践:混合检索与重排序
单一的向量检索可能无法覆盖所有查询意图。为了提高准确率,业界常采用混合检索(Hybrid Search)策略。
- 关键词检索:使用 BM25 等传统算法匹配精确术语。
- 向量检索:使用 ANN 算法匹配语义相似内容。
- 结果融合:使用 RR-Fusion 或 Reciprocal Rank Fusion 算法合并两份结果列表。
- 重排序(Rerank):使用 Cross-Encoder 模型对 Top-K 结果进行精细打分排序。
这种流程虽然增加了计算开销,但在金融、医疗等高精度要求场景下是必要的。
总结与展望
在本文中,我们探讨了向量数据库及其在解决大语言模型(LLM)应用中的局限性的重要性。我们了解了向量数据库的基本概念、数据存储方式以及如何进行向量数据的检索,同时介绍了一些常见的 ANN 算法,如 Flat、k-means、LSH、HNSW 等,以及它们在向量数据库中的应用。
我们还详细介绍了向量数据库的产品分类、市场前景以及与 LLMs 的融合。通过对接 LLMs,我们能够将自然语言的语义信息嵌入到向量数据库中,从而实现更智能、更灵活的数据检索与分析。通过示例展示了 LangChain 在向量数据库与 LLMs 的对接过程,包括分词、嵌入、以及与用户的交互。
最后,我们提到了更多类型的 Embeddings,包括图像、音频等领域的向量表示,这些向量都能够通过相应的 AI 模型生成,为不同领域的应用提供更多可能性。
在未来,随着向量数据库技术的不断发展和 LLMs 的广泛应用,我们可以期待更多创新性的解决方案和应用场景的涌现。例如,实时向量更新、多模态统一索引、以及边缘计算设备上的轻量化向量检索。同时,对于开发者和研究者来说,需要根据具体问题的特点选择合适的向量数据库产品和相应的 ANN 算法,以实现更高效、更精准的数据处理与分析。
生产环境注意事项
在将向量数据库投入生产前,还需注意以下几点:
- 一致性保障:向量写入后,何时可被检索?需考虑最终一致性带来的延迟风险。
- 数据生命周期管理:旧数据是否需要定期清理?冷数据归档策略是什么?
- 监控告警:建立对 QPS、延迟、召回率的实时监控,防止服务退化。
- 容灾备份:向量数据通常不可再生,需做好持久化备份方案。
通过上述措施,可以构建稳定可靠的智能检索系统。