向量数据库与大语言模型集成实践指南
介绍向量数据库的概念及其与大语言模型(LLM)的集成方法。通过向量嵌入技术,将非结构化数据转化为高维向量,解决 LLM 知识滞后和幻觉问题。文章对比了向量数据库与传统数据库的差异,详细解析了索引策略如 HNSW 和 IVF 的性能优化方案。实战部分展示了基于 Falcon-7B 模型和 ChromaDB 构建封闭式问答机器人的流程,涵盖环境配置、知识库构建及上下文检索增强(RAG)的实现细节。最后提供读写优化建议,帮助开发者构建准确可靠的 AI 应用。

介绍向量数据库的概念及其与大语言模型(LLM)的集成方法。通过向量嵌入技术,将非结构化数据转化为高维向量,解决 LLM 知识滞后和幻觉问题。文章对比了向量数据库与传统数据库的差异,详细解析了索引策略如 HNSW 和 IVF 的性能优化方案。实战部分展示了基于 Falcon-7B 模型和 ChromaDB 构建封闭式问答机器人的流程,涵盖环境配置、知识库构建及上下文检索增强(RAG)的实现细节。最后提供读写优化建议,帮助开发者构建准确可靠的 AI 应用。

通常,大语言模型(LLM)在各种各样的数据上进行训练,这使它们具有广泛的理解能力,但可能会导致在特定的知识领域存在差距。有时,它们甚至可能产生与目标无关或带有偏见的信息——这是从广阔但未经筛选的网络学习的副产品。为了解决该问题,我们引入了向量数据库(Vector Database)的概念。这些数据库以一种称为'向量嵌入'的独特格式存储数据,可以让 LLMs 掌握和使用的信息更连贯和准确。
本文介绍了如何使用向量数据库构建一个 LLM,并改进 LLM 对该流程的使用。我们将看到二者的结合是如何让 LLMs 更加准确可靠(特别针对特定主题)。下面简单总结了向量数据库,解释向量嵌入的概念以及它在增加 AI 和机器学习应用方面的角色。之后会展示这些数据库和传统数据库的不同之处,以及为什么它们更适合 AI 任务,特别是与非结构化数据(如文本、图片和复杂模式)打交道时。
最后,你将清楚认识到如何使用 LLMs 和向量数据库来创建新颖、上下文相关并且可靠的应用。本指南将帮助你轻松自信地探索这个激动人心的领域。
在深入了解向量数据库之前,需要了解向量嵌入(vector embedding)的概念。向量嵌入是机器学习中用于将原始数据转换为 AI 系统可以理解的数值格式必不可少的一种技术,涉及数据转换,如将文本或图片转换为一系列数字,这些数字在高维度空间称之为向量。高维数据指包括很多属性或特征的数据,每个数据代表一个不同的维度,这些维度可以帮助捕获该数据的细微特征。
创建向量嵌入的过程开始于数据输入,可以是语句中的任意内容或是图片的像素等。大语言模型和其他 AI 算法会分析这些数据并确定其关键特征。例如,在文本数据中,可能涉及理解单词的意义和它在语句中的上下文。会将这些特征转换为一个数值格式,向量中的每个数值代表数据的一个特征,通过将这些特征数值封装到一起,就可以作为机器可以处理的输入。
之所以说这些向量是高维度的,是因为它们包含很多数值,每个数值对应数据中的某个(不同)特征。这种高维度使得向量能够捕捉复杂、详细的信息,使之成为强大的 AI 模型工具。模型使用这些嵌入向量来识别数据中的模式、关系和潜在结构。
向量数据库针对向量嵌入的特性提供了优化存储和查询的能力。它们擅长提供高效搜索、高性能、可扩展性,并通过比较和识别数据点之间的相似性,实现数据的快速检索。
这些数值代表了复杂的高维信息,使之有别于传统的主要使用文本和数字存储数据的系统。向量数据库的主要能力是管理和查询如图片、视频和文本格式的数据,当这些数据转换为向量格式后,特别适用于机器学习和 AI 应用。
在下面示例中,我们将一段文本转换为向量,这一步是神经语言处理的基本步骤,可以让我们量化和分析语言关系。例如,'puppy'的向量表达应该更接近'dog'的向量空间,而不是'house',反映了它们的语义接近性。这种方式还可以拓展到类似的关系中。'man'和'woman'的向量距离和方向类似于'king'和'queen'之间的距离和方向。下面展示了单词向量不仅仅代表单词,还可以在多维度向量空间中对它们的语义关系进行有意义的比较。

向量数据库用于处理向量嵌入,已经有一些关键使用场景,特别是在机器学习和 AI 领域:
相似搜索:这是向量数据库的关键功能。它们可以在高维度空间内找出与给定请求相似的数据点。特别适用于图形和音频检索(希望找出和特定输入类似的内容),下面是一些业界使用场景:
推荐系统:向量数据库通过处理用户和商品嵌入来支持推荐系统。它可以将用户和他们感兴趣或过去有过互动的物品(如产品、电影或文章)关联起来。下面是一个业务使用场景:
基于内容的检索:这里向量数据库用于基于实际内容而非传统元数据来检索内容。特别对于非结构化数据,如文本和图像,需要首先对内容本身进行分析。下面是一些业界使用场景:
关于基于内容的检索的最后一点越来越重要,并促进了一种新的应用:使用上下文理解来增强 LLMs。通过存储和处理文本嵌入,向量数据库可以帮助 LLMs 实现更精细化以及上下文相关的检索工作。它们可以帮助理解大量文本的语义内容,在回答复杂搜索、维护对话上下文或生成相关内容等任务中起着关键作用。这种应用正迅速成为向量数据库的一个重要场景,展示了其在增强高级 AI 系统(如 LLM)能力方面起到的作用。
传统的 SQL 数据库在结构化数据管理方面表现出色,擅长处理精确匹配和明确定义的条件逻辑。它们维护数据的完整性,适合需要精确、结构化数据处理的应用程序。但这种刚性设计模式也使得它们不太适合处理非结构化数据的语义以及上下文之间的细微差别,而这正是 LLM 和生成式 AI 应用所需要的。
另一方面,相比传统的 SQL 系统,NoSQL 数据库则更加灵活。它们可以处理半结构化和非结构化数据,如 JSON 文档,这使得它们更适用于 AI 和机器学习场景。但即便如此,相比用于 LLMs 和生成式的向量数据库来说,NoSQL 数据库依然缺少某些方面的能力,如解析上下文、模式以及简单数据检索之外的语义内容。
向量数据库弥补了这一空白。它们以 AI 为中心,使用向量的方式处理数据,可以有效管理复杂的非结构化数据。当与 LLMs 协作时,向量数据库支持和上下文理解,提供了超出传统 SQL 和 NoSQL 数据库的能力。它们擅长处理近似值和模式识别,使之特别适用于对数据的微妙理解比精确数据匹配更重要的 AI 应用。
对于依赖速度和精确检索高维数据的应用来说,向量数据库的性能优化至关重要。这里面涉及提升查询速度、保证高准确性以及有效处理不断增长的数据量和用户请求。其中最重要的一部分是围绕索引策略进行优化(一种更有效组织和查询向量数据的技术)。下面,我们将介绍这些索引策略,以及它们是如何提升向量数据库性能的。
向量数据库的索引策略用于方便和准确检索与查询向量相似的向量。这些策略可以显著影响到查询操作的速度和准确性。
量化(Quantization):量化涉及将向量映射到向量空间中的一组有限的参考点,从而有效地压缩向量数据。这种策略通过将查询限制到有限点(而非整个数据库)的方式降低了存储需求并加快查询速度。量化的方式有很多种,如标量量化(Scalar Quantization,通过将大空间的向量转换成相对小空间的向量来减少整体的存储空间。通常是将浮点数(比如 f32)向量量化成整数(比如 int8)向量(存储的优化比是 4X)) 和向量量化(Vector Quantization,区别于 scalar quantization 是分别从每一个维度进行压缩,vector quantization 是通过将原始向量当做一个整体去看待,将一个向量映射到指定的参考向量里),每种量化方式都需要权衡查询速度和精度。
量化特别适用于管理大规模数据库的应用(存储和内存效率至关重要),这种方法在需要在查询速度和准确性之间取得平衡的环境中表现出色,这使得它非常适合对速度敏感且可以容忍一定精度损失的应用程序。但它不适合需要高度精确和最小化信息损失的场景,如精确科学研究。
HNSW(Hierarchical Navigable Small World,分层可导航小世界)图:HNSW 是一种构建分层图的索引策略,每层代表数据集中的一个不同粒度。查询从顶层开始,顶层具有较少、更远的点,然后向下移动到更详细的层级。这种方式可以快速遍历数据集,通过快速缩小相似向量的候选集合,大大减少了搜索时间。

HNSW 图很好地均衡了查询速度和准确性,使其非常适于需要立即响应的实时查询应用和推荐系统。它们在中大型数据集中表现良好,提供可扩展的搜索能力。但对于超大型数据集来说,其内存需求可能会成为瓶颈,因此这种方式不适用于内存资源受限或数据集大小远超实际内存容量的场景。
倒排文件索引(Inverted File Index,IVF):IVF 使用 k-means 这样的算法将向量空间分为预定义数量的几个聚类。每个向量分配给最近的聚类,在一个搜索中,只会涉及到最相关聚类中的向量。这种方式降低了搜索空间,提升了查询速度。通过将 IVF 和其他技术(如 IVFADC-Inverted File Index with Asymmetric Distance Computation,就结合了 IVF 和 Quantization)相结合,可以通过进一步降低距离计算成本来提升性能。
IVF 方法适合处理可扩展查询环境中的高维数据,可以通过对相似项划分聚类来有效降低搜索空间,特别适用于相对静态的数据库,且可以允许偶尔重新聚类的场景。但对于低维数据(可能存在过分分割)或要求尽可能低延迟的应用(聚类过程和跨多个聚类查询可能会引入额外的查询时间)来说,IVF 可能不是最佳的选择。
通过这些索引策略和注意事项来提升向量数据库的性能需要深刻理解底层数据以及特定的应用需求。通过仔细选择并调节这些策略,开发者可以显著提高基于向量的应用的响应能力和可扩展性,保证其满足真实使用场景。
像 Facebook 的 Llama 或 TII UAE 的大语言模型具有先进的人工智能和类人类的文本生成能力,但由于它们是基于广泛、通用的数据集进行训练的,因此缺乏对特定上下文的处理能力。
可以使用如下两种方式解决上下文限制的问题:
第二种方式称为 RAG(Retrieval-Augmented Generation),我们将在下一章中详细介绍。

本章中,我们将介绍如何使用向量数据库来构建一个 LLM,是使用的模型是一个封闭式问题机器人(Closed Q&A bot),该机器人使用一组集成的技术组件来有效解答与科学相关的问题。
multi-qa-MiniLM-L6-cos-v1 模型,该模型特别适用于语义查询应用,负责生成嵌入向量,并将其存储在 Chroma 中。Falcon 7B 是一个由 TII 开发的一个仅包含 70 亿参数的解码器模型,Falcon 7B 模型使用了一个庞大的名为 RefinedWeb 的 1,500B tokens 数据集进行训练,并补充了经过筛选的语料库。值得注意的是,Falcon 40B 作为 Falcon 7B 的更大版本,在 Hugging Face 的 Open LLM 排行榜中名列前茅,是最顶尖的大型语言模型之一。实现架构如下。使用
multi-qa-MiniLM-L6-cos-v1作为嵌入模型,负责将数据集的数据导入数据库。在用户提问时,会使用嵌入模型对提问文本进行编码,生成向量数据库可以理解的格式,并由向量数据库返回应答。
Falcon 7B模型用于优化向量数据库的应答结果。下图有点问题,看起来请求和应答是异步执行的,但代码中是串行的。

为了实现本文的代码,需要安装如下库:
!pip install -qU \
transformers==4.30.2 \
torch==2.0.1+cu118 \
einops==0.6.1 \
accelerate==0.20.3 \
datasets==2.14.5 \
chromadb \
sentence-transformers==2.2.2
本代码运行在云环境中的一台实例上。需要注意的是运行 Falcon-7B-Instruct 模型的代码可能会根据硬件配置而变化。
一开始,我们需要拉取 Databricks-Dolly 数据集,重点关注 closed_qa 一类的数据集。这些数据条目通常以对精确信息的需求为特征,这种专一性给通用性大语言模型的训练带来了一定挑战。
在 HuggingFace 的 dataset card 中可以查看支持的 split 和过滤字段。
from datasets import load_dataset
# Load only the training split of the dataset
train_dataset = load_dataset("databricks/databricks-dolly-15k", split='train')
# 通过过滤拉取 category 为 closed_qa 的一组数据
closed_qa_dataset = train_dataset.filter(lambda example: example['category'] == 'closed_qa')
print(closed_qa_dataset[0])
数据库通常可以分为:training、validating 和 evaluating。分别用于训练、校验和评估模型。
典型的数据集条目的格式如下:
{
"instruction": "When was Tomoaki Komorida born?",
"context": "Komorida was born in Kumamoto Prefecture on July 10, 1981. After graduating from high school, he joined the J1 League club Avispa Fukuoka in 2000. His career involved various positions and clubs, from a midfielder at Avispa Fukuoka to a defensive midfielder and center back at clubs such as Oita Trinita, Montedio Yamagata, Vissel Kobe, and Rosso Kumamoto. He also played for Persela Lamongan in Indonesia before returning to Japan and joining Giravanz Kitakyushu, retiring in 2012.",
"response": "Tomoaki Komorida was born on July 10, 1981.",
"category": "closed_qa"
}
下面,我们将重点为每组指令及其各自的上下文生成词嵌入,并将它们集成到向量数据库 ChromaDB 中。
Chroma 是一个开源的向量数据库系统,擅长管理向量嵌入,专为语义查询引擎之类的应用量身定做,这种能力在自然语言处理和机器学习领域至关重要。Chroma DB 作为一个内存型数据库,支持数据的快速访问和高速处理。其友好的 Python 设置增强了对我们项目的吸引力,简化了与我们工作流程的集成。

为了给回答生成嵌入向量,我们使用了 multi-qa-MiniLM-L6-cos-v1 模型,该模型专为语义搜索场景而训练。给定一个问题/搜索请求,该模型可以找到相关的文本信息,这正是我们所需要的。
在下面例子中,解释了如何将嵌入向量存储在 Chroma 的内存集合中。
import chromadb
from sentence_transformers import SentenceTransformer
class VectorStore:
def __init__(self, collection_name):
# 初始化嵌入模型和向量数据库
self.embedding_model = SentenceTransformer('sentence-transformers/multi-qa-MiniLM-L6-cos-v1')
self.chroma_client = chromadb.Client()
self.collection = self.chroma_client.create_collection(name=collection_name)
# 该方法用于将输入的数据集转换为向量,并保存到向量数据库中
def populate_vectors(self, dataset):
for i, item in enumerate(dataset):
combined_text = f"{item['instruction']}. {item['context']}"
embeddings = self.embedding_model.encode(combined_text).tolist()
self.collection.add(embeddings=[embeddings], documents=[item['context']], ids=[f"id_{i}"])
# 该方法直接从向量数据库中与查询相关的上下文
def search_context(self, query, n_results=1):
query_embeddings = self.embedding_model.encode(query).tolist()
return self.collection.query(query_embeddings=query_embeddings, n_results=n_results)
# Example usage
if __name__ == "__main__":
# Initialize the handler with collection name
vector_store = VectorStore("knowledge-base")
# 输入上一步拉取的 closed_qa 数据集
vector_store.populate_vectors(closed_qa_dataset)
对于每个数据集条目,我们会生成一个结合了 instruction 和 context 字段的嵌入向量,在我们的 LLM 提示中,context 充当要检索的文档。
下面,我们使用 Falcon-7b-instruct LLM 来生成封闭式信息查询的应答(无需额外的上下文),并展示知识库的重要性。
为了实现文本生成任务,我们采用了来自 Hugging Face 的 Falcon-7b-instruct 模型。该模型是 Falcon 的革新系列,由 Abu Dhabi 的 Technology Innovation Institute 开发。
Falcon-7B-Instruct 引人注目的一点是其有效平衡了高级功能和管理大小,用于理解复杂的文本和生成任务,其性能可以与更大的封闭源代码模型相媲美,但包更精简。这也是它成为我们理想选择的原因(可以深入语言理解,但不会带来跟更大模型一样的开销)。
如果你打算运行 Falcon-7B-Instruct 模型(无论是本地机器或远程服务器),需要注意硬件要求。官方文档中提到,该模型最少需要 16GB 的内存来满足最佳的性能和更快的响应次数,最好使用 GPU。
import transformers
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
class Falcon7BInstructModel:
def __init__(self):
# 初始化模型
model_name = "tiiuae/falcon-7b-instruct"
self.pipeline, self.tokenizer = self.initialize_model(model_name)
def initialize_model(self, model_name):
# 初始化 Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
# Pipeline setup for text generation
pipeline = transformers.pipeline(
"text-generation",
model=model_name,
tokenizer=tokenizer,
torch_dtype=torch.bfloat16,
trust_remote_code=True,
device_map="auto",
)
return pipeline, tokenizer
def generate_answer(self, question, context=None):
# Preparing the input prompt
prompt = question if context is None else f"{context}\n\n{question}"
# 生成应答
sequences = self.pipeline(
prompt,
max_length=500,
do_sample=True,
top_k=10,
num_return_sequences=1,
eos_token_id=self.tokenizer.eos_token_id,
)
# Extracting and returning the generated text
return sequences['generated_text']
可以参考 Hugging Face 的官方文档来编写上述代码:
tokenizer 的设计,这些 tokens 可以是单词、子单词(subword)甚至是特征。在 Falcon-7B-Instruct 模型的上下文中,AutoTokenizer.from_pretrained(model) 调用会加载一个专为该模型设计的 tokenizer,保证能够遵循该模型训练的方式来将文本转化为 token。使用方式如下:
# 初始化 Falcon 模型类
falcon_model = Falcon7BInstructModel()
user_question = "When was Tomoaki Komorida born?"
# LLM 使用 LLM 来为用户提问生成回答
answer = falcon_model.generate_answer(user_question)
print(f"Result: {answer}")
你可能已经猜到模型的输出:
{ answer: 'I don't have information about Tomoaki Komorida's birthdate.' }
使用 Falcon-7B-Instruct 时,如果没有相关的上下文,就会返回一个否定响应。这说明需要进一步丰富背景知识,为非一般性问题提供更有针对性和有用的答案。
下面我们通过向量存储来为模型提供相关上下文,从而提升模型能力。
有趣的是,我们使用相同的 VectorStore 类来同时生成嵌入向量和从用户提问中获取上下文。
# Assuming vector_store and falcon_model have already been initialized
# 从 VectorStore 中获取上下文 (假设数据集已经导入数据库)
context_response = vector_store.search_context(user_question)
# 从向量数据库的响应中抽取上下文,上下文应该是 context 关键字的第一个元素
context = "".join(context_response['context'][0])
# Falcon 模型结合提取的上下文生成应答
enriched_answer = falcon_model.generate_answer(user_question, context=context)
print(f"Result: {enriched_answer}")
最后可以得到准确的回答:
Tomoaki Komorida was born on July 10, 1981.
Hugging Face 上的 Models 和 Datasets 都按照任务类型进行了划分,在找到感兴趣的 task 之后,还可以依据 Trending、Most likes、Most downloads、Recently created 和 Recently Updated 进行排序查找。
huggingface 的各个模块都提供了对应的 Example,参考编写即可。
当我们讨论到检索(retrieval)时,通常指一系列与查询最接近、且以某种格式保存在相同隐空间(Latent space,一个潜在的多维向量空间,其中每个向量表示一个潜在的特征或属性)中的向量。检索流程会使用最近邻居(Approximate Nearest Neighbour - ANN)方式进行搜索。
查询可以是某种格式的对象,如查找相似的图片或检索后续传递给 LLM 的相关上下文。
写/更新数据:
读数据
针对向量数据库的查询通常分为两部分:
通过元数据索引来执行元数据查询,可以在 ANN 查询流程之前或之后
使用和写入数据相同的模型将请求数据嵌入到隐空间中
使用 ANN 搜索来检索到一组向量嵌入。ANN 搜索使用的相似性测量方式有:Cosine Similarity, Euclidean Distance, Dot Product
从下面图可以看到,元数据索引可以减低检索的范围,在执行搜索时,会将请求数据一并嵌入隐空间中,然后围绕该向量嵌入找出和它最近的向量嵌入(数据)。

本文详细介绍了向量数据库与大语言模型(LLM)集成的核心概念与实践方法。通过向量嵌入技术,我们可以将非结构化数据转化为 AI 可理解的形式,有效解决了 LLM 的知识滞后和幻觉问题。文章对比了向量数据库与传统数据库的差异,深入解析了 HNSW、IVF 等索引策略的性能优化方案。实战部分展示了基于 Falcon-7B 模型和 ChromaDB 构建封闭式问答机器人的完整流程,涵盖了环境配置、知识库构建及上下文检索增强(RAG)的实现细节。此外,还提供了关于读写优化和部署的最佳实践建议。开发者可以根据实际需求选择合适的工具和策略,构建出准确、可靠且高效的 AI 应用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online