将向量数据库与LLM集成:实践指南
探索如何利用向量数据库增强大型语言模型(LLMs),构建更智能、上下文感知的AI解决方案。学习使用Qwak构建更智能的聊天机器人。
欢迎来到我们的实践指南,我们将深入探讨大型语言模型(LLMs)与向量数据库的结合。LLMs在技术领域掀起了一场革命,但它们的全部潜力往往在孤立使用时无法完全发挥。这就是向量数据库的用武之地——它们能帮助LLMs生成不仅准确,而且上下文相关的响应。
通常,LLMs是在广泛的数据集上进行训练的,这使它们具有广泛的理解能力,但也可能导致特定领域知识的空白。有时,它们甚至可能输出偏离主题或带有偏差的信息——这是从未经过滤的网络数据中学习的副产品。为了解决这个问题,我们引入了向量数据库的概念。这些数据库以“向量嵌入”的格式存储数据,使LLMs能够更上下文化和准确地利用信息。
本指南将指导你如何构建一个结合向量数据库的LLM,并改进其工作流程。我们将展示如何通过结合这两种技术来提高LLMs的准确性和实用性,特别是在特定主题上。
接下来,我们将简要介绍向量数据库,解释向量嵌入的概念及其在增强AI和机器学习应用中的作用。我们将展示它们与传统数据库的区别,以及为什么它们更适合处理AI驱动的任务,尤其是处理非结构化数据如文本、图像和复杂模式。
此外,我们将通过构建一个基于Falcon-7B和ChromaDB的封闭式问答机器人,展示这些技术的实际应用。这个机器人证明了当LLMs与正确的工具和技巧结合时,能够发挥的强大功能。
到本指南结束时,你将清楚如何利用向量数据库和LLMs的力量,创建既创新又具备上下文感知和可靠性的应用程序。无论你是AI爱好者还是经验丰富的开发者,本指南都将帮助你轻松自信地驾驭这个激动人心的领域。
向量数据库概述
在深入了解什么是向量数据库之前,我们需要理解向量嵌入(vector embedding)的概念。向量嵌入是机器学习中将原始数据转换为机器学习系统可理解的数值格式的关键步骤。这涉及将数据(如文本或图像)转换为高维空间中的数值序列,即向量。高维数据指的是具有许多属性或特征的数据,每个特征代表一个不同的维度。这些维度能够捕捉数据的细微特征。
向量嵌入的创建过程始于输入数据,可以是句子中的单词,也可以是图像中的像素。大型语言模型和其他AI算法分析这些数据,识别其关键特征。例如,在文本数据中,这可能涉及理解单词在句子中的含义和上下文。嵌入模型(embedding model)随后将这些特征转换为数值形式,为每个数据点创建一个向量。向量中的每个数字代表数据的一个特定特征,这些数字共同捕捉原始输入的本质,使其适合机器学习模型处理。
这些向量是高维的,因为它们包含大量数字,每个数字对应数据的一个不同特征。这种高维性使向量能够捕捉复杂、详细的信息,使其成为强大的AI模型工具。模型使用这些嵌入来识别数据中的模式、关系和潜在结构。
向量数据库专门设计用于高效存储和查询这些向量嵌入,提供优化的存储和查询能力,特别适合处理向量嵌入的独特性质。它们在提供高效的搜索能力、高性能、可扩展性和数据检索方面表现出色,通过比较和识别数据点之间的相似性来实现。
与传统的以文本和数字为主的存储方式不同,向量数据库通过将数据转换为向量格式,使其适用于机器学习和AI应用,特别是在处理非结构化数据(如文本、视频和图像)时。下面的示例展示了文本到词向量的转换过程,这是自然语言处理中的基础步骤。这使我们能够量化和分析语言关系。例如,“puppy”(小狗)的向量在向量空间中会更接近”dog”(狗),而非”house”(房子),反映了它们的语义相似性。这种方法还可扩展到类比关系,例如”man”(男人)与”woman”(女人)之间的向量距离和方向,可能类似于”king”(国王)与”queen”(王后)之间的关系。
来源:Plos
向量数据库在LLMs出现前的应用
向量数据库在LLMs兴起之前已有多种关键应用场景,特别是在机器学习和AI领域:
相似性搜索(Similarity Search):这是向量数据库的核心功能。它们能够在高维空间中快速找到与给定查询最相似的数据点。这对于图像或音频检索等应用至关重要,例如根据参考图像搜索视觉上相似的产品。
- 电子商务:通过视觉相似性提升产品发现,让用户根据参考图像搜索类似商品。
- 音乐流媒体服务:根据用户喜欢的曲目推荐具有相似音频特征的歌曲。
- 医疗影像:帮助放射科医生通过比较类似病理的医学影像(如X光或MRI)进行诊断分析。
推荐系统(Recommendation Systems):向量数据库支持推荐系统,通过处理用户和物品的嵌入(embeddings)来匹配用户兴趣或历史交互。例如:
- 流媒体平台:根据观看历史个性化推荐电影和电视剧。
- 在线零售商:根据浏览和购买历史推荐产品,提升交叉销售和向上销售机会。
- 新闻聚合器:根据用户过去的互动模式和偏好提供个性化新闻源。
基于内容的检索(Content-Based Retrieval):这里,向量数据库根据内容本身而非元数据进行搜索,这对非结构化数据(如文本和图像)至关重要:
- 数字资产管理:通过分析视觉或音频特征管理大量数字媒体库。
- 法律与合规:在大量文档中搜索特定信息或上下文相关的法律案件或合规问题。
- 学术研究:帮助研究人员找到与他们工作语义相似的学术论文,即使这些论文未明确提及关键词。
最后一个应用场景——基于内容的检索——在增强LLMs的上下文理解方面尤为重要。通过存储和处理文本嵌入,向量数据库使LLMs能够进行更细致、上下文相关的信息检索。这对于复杂查询、对话上下文维护或生成相关内容至关重要,这已成为向量数据库的重要应用方向。
向量数据库 vs 传统数据库
传统SQL数据库擅长结构化数据管理,在精确匹配和条件逻辑方面表现出色。它们在维护数据完整性方面表现出色,适合需要精确结构化数据处理的应用。然而,它们的刚性架构使得处理AI应用中的语义和上下文细微差别变得困难。
NoSQL数据库相比传统SQL更具灵活性,能够处理半结构化和非结构化数据(如JSON文档),使其在一定程度上更适合AI和机器学习应用。尽管如此,即使是NoSQL数据库在处理LLMs和生成式AI所需的复杂、高维向量数据时,也可能存在不足,难以捕捉上下文和语义内容。
向量数据库填补了这一空白。专门针对AI场景设计,它们以向量形式处理数据,有效管理非结构化数据的复杂性。与LLMs结合时,它们支持相似性搜索和上下文理解等操作,提供了超越传统SQL和NoSQL数据库的能力。它们在模式识别和近似匹配方面的专业性,使它们成为依赖语义理解的AI应用(如LLMs和生成式AI)的理想选择。
提高向量数据库性能
优化向量数据库的性能对于依赖快速、准确检索高维数据的应用至关重要。这包括提高查询速度、确保高精度以及在处理不断增长的数据量和用户请求时保持可扩展性。索引策略是优化的核心,这些策略旨在组织和搜索向量数据更高效。
索引策略
索引策略用于向量数据库中,以快速准确地检索与查询向量最相似的向量。这些策略对搜索速度和准确性有显著影响。
- 量化(Quantization):量化将向量映射到向量空间中的有限参考点,从而压缩数据。这减少了存储需求并加速搜索,因为搜索仅限于子集参考点而非整个数据集。量化包括标量量化和向量量化等多种形式,各有其在速度和精度之间的权衡。
量化特别适用于需要高效存储和内存的大规模数据集。它在速度敏感的应用中表现出色,这些应用可以接受一定的精度损失。然而,它并不适合需要最高精度或最小信息丢失的应用,如精密科学研究。
- 分层可导航小世界图(HNSW):HNSW通过构建分层图,每个层级代表数据集的不同粒度。搜索从顶层(数据点较少且距离较远)开始,逐步深入更详细的层级。这种方法通过快速缩小候选集来显著减少搜索时间。
HNSW在实时搜索和推荐系统等需要快速响应的应用中表现出色,平衡了速度和准确性。然而,它们的内存消耗可能成为处理极端大规模数据集的限制因素。
- 倒排文件索引(IVF):IVF方法通过k-means等算法将向量空间划分为预定义的聚类。每个向量被分配到最近的聚类,搜索时仅考虑最相关的聚类中的向量。结合量化(如IVFADC)可以进一步提高性能,减少距离计算的计算成本。
IVF方法适合处理高维数据的大规模搜索环境,在静态数据集上尤其有效。然而,它在低维数据或需要最低延迟的应用中可能表现不佳。
其他优化考量
- 降维(Dimensionality Reduction):在应用索引策略前,通过PCA或自编码器等技术减少向量维度,可以保留数据的关键特征同时降低复杂度,从而提高索引效率和搜索速度。
- 并行处理:许多索引策略可以在CPU多核或GPU上并行化,提升吞吐量和响应时间。
- 动态索引:对于频繁更新数据的数据库,动态索引策略允许高效插入和删除向量,而无需频繁重组索引,确保系统响应迅速且数据最新。
通过精心选择和调整这些策略,开发者可以显著提升基于向量的应用程序的响应速度和可扩展性,满足实际应用场景的需求。
增强LLMs的上下文理解能力
大型语言模型(如Meta的LLama2或TIIUAE的Falcon)在文本生成方面取得了显著进展,但它们在处理特定上下文时面临挑战,因为其训练数据广泛而通用。
解决这一局限性的两种主要方法:
- 定向训练(Targeted Training):在特定领域的数据集上重新训练或微调LLM。虽然这能显著提升模型在特定主题或行业的专业性,但对许多组织或个人而言,这可能不现实。原因包括计算资源成本高昂和需要专业知识。
- 通过向量数据库增强上下文:LLM可以通过从向量数据库检索的数据增强提示来补充其知识。向量数据库存储特定领域信息的嵌入,这些嵌入可被检索并用于增强LLM的响应。这种方法无需重新训练模型,适合资源有限的场景。
第二种方法称为RAG(检索增强生成),我们将在后续章节深入探讨。
来源:KDnuggets
使用Falcon-7B和ChromaDB构建封闭式问答机器人
本节将分步骤说明如何构建结合向量数据库的LLM应用。我们的示例是一个封闭式问答机器人(Closed Q&A Bot),整合以下技术组件:
- databricks-dolly-15k HuggingFace数据集:一个开源指令遵循数据集,用于训练LLMs、合成数据生成和数据增强。包含多种提示和响应类型,如头脑风暴、分类、封闭式问答等。
- Chroma作为向量存储(知识库):我们使用Chroma作为主要向量存储,构建知识库。
- Sentence Transformers进行语义搜索:具体使用’multi-qa-MiniLM-L6-cos-v1’模型生成嵌入。
- Falcon 7B Instruct模型:开源生成模型,具有70亿参数,训练于1.5万亿token的RefinedWeb数据集。
环境配置
运行本教程代码前需安装以下库:
!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
代码在Qwak Workspaces的gpu.a10.2xl实例上运行。具体Falcon-7B-Instruct模型的硬件配置可能有所不同。
构建“知识库”
首先,我们获取databricks-dolly-15k数据集中的封闭式问答(closed_qa)类别数据。这些条目通常需要精确信息,对一般训练的LLM来说较为困难。
from datasets import load_dataset
# 加载训练集
train_dataset = load_dataset("databricks/databricks-dolly-15k", split='train')
# 筛选封闭式问答类别
closed_qa_dataset = train_dataset.filter(lambda example: example['category'] == 'closed_qa')
print(closed_qa_dataset[0])
一个典型的数据集条目如下:
{
"instruction": "Tomoaki Komorida的出生日期是什么时候?",
"context": "Komorida于1981年7月10日出生于熊本县。高中毕业后,他于2000年加入J1联赛俱乐部Avispa Fukuoka。他的职业生涯涉及多个位置和俱乐部,从Avispa Fukuoka的中场球员到Oita Trinita、Montedio Yamagata、Vissel Kobe和Rosso Kumamoto的防守型中场和中后卫。他还效力于印尼的Persela Lamongan,后返回日本加入Giravanz Kitakyushu,于2012年退役。",
"response": "Tomoaki Komorida出生于1981年7月10日。",
"category": "closed_qa"
}
接下来,我们为每个指令和上下文生成词向量嵌入,并将其存储在ChromaDB中。
Chroma DB 是一个开源向量数据库,专为语义搜索等任务设计。其内存内存储特性使其快速高效,Python友好性使其易于集成到项目中。文档:Chroma DB文档。
来源:https://docs.trychroma.com/
我们使用’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)
if __name__ == "__main__":
vector_store = VectorStore("knowledge-base")
vector_store.populate_vectors(closed_qa_dataset)
对于每个数据集条目,我们生成并存储了指令和上下文字段的组合嵌入,其中上下文作为文档用于LLM提示。
接下来,我们将使用Falcon-7B-Instruct模型生成回答,展示增强知识库的效果。
生成基础回答
我们使用Hugging Face的Falcon-7B-Instruct模型,该模型在Qwak Workspaces的GPU实例上运行。模型需要至少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 = AutoTokenizer.from_pretrained(model_name)
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):
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,
)
return sequences[0]['generated_text']
# 示例用法
falcon_model = Falcon7BInstructModel()
user_question = "Tomoaki Komorida的出生日期是什么时候?"
answer = falcon_model.generate_answer(user_question)
print(f"结果: {answer}")
模型输出:
结果: 我没有关于Tomoaki Komorida出生日期的信息。
这表明,未使用上下文的Falcon-7B-Instruct模型无法回答此问题,突显了增强上下文的重要性。
生成上下文感知的回答
现在,我们通过从向量存储检索的上下文来增强模型:
# 从VectorStore检索上下文
context_response = vector_store.search_context(user_question)
context = "".join(context_response['context'][0])
# 使用检索到的上下文生成回答
enriched_answer = falcon_model.generate_answer(user_question, context=context)
print(f"结果: {enriched_answer}")
输出:
Tomoaki Komorida出生于1981年7月10日。
总结
通过本指南,我们展示了如何构建一个增强型LLM应用。虽然管理这些模型、实验数据集、设置基础设施并实现解决方案并非易事,但Qwak简化了这一过程。Qwak不仅帮助管理模型,还通过其向量存储功能(如ETL和可视化改进)不断优化体验。
未来,我们将继续改进Qwak的向量存储功能,提供更强大的ETL和可视化工具。当前的焦点是增强与向量存储的集成。
下一步行动
要查看本教程讨论的应用程序的完整示例,请访问我们的示例仓库。我们已准备好一切,助您顺利开始。
立即开始使用Qwak,免费探索构建上下文感知LLM的旅程。点击此处免费开始。