由 Qwak 的解决方案架构师 Grig Duta 撰写
欢迎来到我们的实战指南,在这里我们将深入探讨大型语言模型(LLMs)及其与向量数据库的协同作用。LLMs 在科技界已成为游戏规则的改变者,推动了应用程序开发的创新。然而,当它们单独使用时,其全部潜力往往未能充分发挥。这时,向量数据库登场了,它们增强了 LLMs 的能力,使其不仅能生成任何响应,而且能生成正确的响应。
通常,大型语言模型(LLMs)是在广泛的数据集上进行训练的,这使它们具有广泛的知识,但也可能导致特定知识领域的空白。有时,它们甚至会输出偏离主题或有偏见的信息——这是从浩瀚且未经过滤的网络中学习的副产品。为了解决这个问题,我们引入了向量数据库的概念。这些数据库以一种称为“向量嵌入”的独特格式存储数据,使LLMs能够更准确地理解和利用信息。
本指南介绍如何使用向量数据库构建大型语言模型(LLM),并改进LLM在此流程中的使用。我们将探讨如何结合这两种技术使LLM更加准确和有用,特别是在特定主题上。
接下来,我们简要概述向量数据库,解释向量嵌入的概念及其在增强AI和机器学习应用中的作用。我们将向您展示这些数据库与传统数据库有何不同,以及为什么它们更适合处理诸如文本、图像和复杂模式等非结构化数据的AI驱动任务。
进一步,我们将探讨这项技术在构建一个Closed-QA机器人的实际应用。这个机器人由Falcon-7B和ChromaDB驱动,展示了当大型语言模型(LLMs)与合适的工具和技术结合时的有效性。
到本指南结束时,你将更清楚地了解如何利用大型语言模型(LLMs)和向量数据库的力量来创建不仅创新而且具有上下文感知和可靠性的应用程序。无论你是AI爱好者还是资深开发者,本指南都旨在帮助你轻松自信地掌握这一激动人心的领域。
在深入了解什么是向量数据库之前,理解向量嵌入的概念至关重要。向量嵌入在机器学习中非常重要,用于将原始数据转换为AI系统可以理解的数值格式。这包括将数据(如文本或图像)转换为高维空间中的数字序列,称为向量。高维数据指的是具有许多属性或特征的数据,每个特征代表一个不同的维度。这些维度有助于捕捉数据的细微特征。
创建向量嵌入的过程始于输入数据,这些数据可以是句子中的单词或图像中的像素。大型语言模型和其他AI算法分析这些数据并识别其关键特征。例如,在文本数据中,这可能涉及理解单词的意义及其在句子中的上下文。然后,嵌入模型将这些特征转换为数值形式,为每条数据创建一个向量。向量中的每个数字代表数据的一个特定特征,而这些数字共同封装了原始输入的精髓,使其能够被机器处理。
这些向量是高维的,因为它们包含了许多数字,每个数字对应数据的不同特征。这种高维度使得向量能够捕捉到复杂且详细的信息,从而成为AI模型的强大工具。模型使用这些嵌入来识别数据中的模式、关系和潜在结构。
向量数据库设计用于提供优化的存储和查询能力,以适应向量嵌入的独特性质。它们在提供高效搜索能力、高性能、可扩展性和通过比较和识别数据点之间的相似性来进行数据检索方面表现出色。
这些复杂的高维信息的数值表示使向量数据库区别于主要存储文本和数字等格式数据的传统系统。它们的主要优势在于管理和查询诸如图像、视频和文本等数据类型,特别是在这些数据被转换为向量格式用于机器学习和人工智能应用时尤为有用。
在接下来的说明中,我们展示了将文本转换为word向量的过程。这一步在自然语言处理中至关重要,使我们能够量化和分析语言关系。例如,“小狗”的向量表示在向量空间中会比“房子”更接近“狗”,这反映了它们的语义接近度。这种向量表示方法同样适用于类比关系。例如,“男人”和“女人”之间的向量距离和方向可以类似于“国王”和“王后”之间的距离和方向。这说明了词向量不仅表示单词,还允许在多维向量空间中对它们的语义关系进行有意义的比较。
来源
向量数据库,设计用于处理向量嵌入,在机器学习和AI领域有几个关键应用场景:
相似性搜索: 这是向量数据库的核心功能之一。它们可以在高维空间中快速找到与给定查询相似的数据点。这对于图像或音频检索等应用非常重要,因为在这些应用中,你需要找到与特定输入相似的项目。以下是一些行业用例示例:
推荐系统:向量数据库通过处理用户和项目的嵌入来支持推荐系统。它们可以将用户与最符合其兴趣或过去互动的项目(如产品、电影或文章)进行匹配。以下是行业中的几个用例:
基于内容的检索: 在这里,使用向量数据库根据内容的实际内容进行搜索,而不是传统的元数据。这在处理像文本和图像这样的非结构化数据时特别相关,因为需要分析内容本身来进行检索。以下是几个行业用例:
这一点关于基于内容的检索越来越重要,并且促进了新型应用:
增强LLM的上下文理解能力:通过存储和处理文本嵌入,向量数据库使LLM能够执行更细致和上下文感知的信息检索。它们有助于理解大量文本的语义内容,在回答复杂查询、保持对话上下文或生成相关内容等任务中至关重要。这一应用正迅速成为向量数据库的重要用例,展示了它们增强高级AI系统如LLM的能力。
传统的关系型数据库在管理结构化数据方面表现出色,依赖精确匹配和明确的条件逻辑。它们维护数据完整性,适合需要精确、结构化数据处理的应用程序。然而,它们严格的模式设计使得在处理像大型语言模型(LLMs)和生成式AI这样的AI应用中所需的非结构化数据的语义和上下文细微差别时,适应性较差。
另一方面,NoSQL 数据库相比传统的 SQL 系统提供了更多的灵活性。它们可以处理半结构化和非结构化数据,如 JSON 文档,这使得它们在 AI 和机器学习应用场景中更具适应性。尽管如此,即使是 NoSQL 数据库在处理 LLMs 和生成式 AI 所必需的复杂、高维向量数据方面也可能存在不足,这些数据通常涉及解释上下文、模式和语义内容,而不仅仅是简单的数据检索。
向量数据库填补了这一空白。它们专为AI为中心的场景设计,将数据处理为向量,能够有效地管理非结构化数据的复杂性。在与大型语言模型(LLMs)一起工作时,向量数据库支持诸如相似性搜索和上下文理解等操作,提供了超越传统SQL和灵活NoSQL数据库的能力。它们在近似值处理和模式识别方面的熟练程度,使其特别适合需要精细数据解释而非精确数据匹配的AI应用。
优化向量数据库的性能对于依赖快速和准确检索高维数据的应用程序来说非常重要。这包括提高查询速度、确保高准确性以及保持可扩展性以高效处理不断增长的数据量和用户请求。优化的一个重要部分围绕着索引策略,这些策略用于更高效地组织和搜索向量数据。以下我们将进一步探讨这些索引策略以及它们如何有助于提高向量数据库的性能。
向量数据库中的索引策略旨在促进快速准确地检索与查询向量相似的向量。这些策略可以显著影响搜索操作的速度和准确性。
量化技术特别适合于管理大规模数据集的应用程序,其中存储和内存效率至关重要。它在需要在查询速度和准确性之间取得平衡的环境中表现出色,因此非常适合可以容忍一定程度精度损失的速度敏感型应用。然而,对于需要最高精度和最小信息损失的应用场景(如精确的科学研究),由于数据压缩和搜索精度之间的固有取舍,不太推荐使用量化技术。
HNSW 图在查询速度和准确性之间取得了很好的平衡,非常适合需要即时响应时间的实时搜索应用和推荐系统。它们在中等至大型数据集上表现良好,提供了可扩展的搜索能力。然而,对于极大数据集,它们的内存消耗可能会成为一个限制,因此在内存资源受限或数据集大小远超实际内存容量的场景中,它们可能不太理想。
倒排文件索引(IVF)方法推荐用于处理可扩展搜索环境中高维数据,通过聚类相似项高效地缩小搜索范围。这种方法特别适用于相对静态的数据集,在这种情况下,偶尔重新聚类的开销是可以管理的。然而,对于低维数据,IVF可能不是最佳选择,因为可能会出现过度分割的情况,或者对于需要最低可能延迟的应用程序来说,聚类过程和跨多个聚类进行搜索的需求可能会引入额外的查询时间。
通过这些索引策略和考虑因素来提升向量数据库的性能,需要深入了解底层数据和应用程序的具体需求。通过仔细选择和调整这些策略,开发人员可以显著提高基于向量的应用程序的响应速度和可扩展性,确保它们满足实际应用场景的需求。
大型语言模型(LLMs)如 Facebook 的 LLama2 或 TIIUAE 的 Falcon,通过生成类似人类的文本大大提升了 AI 的能力。然而,由于它们是基于广泛、通用的数据集进行训练的,因此在处理专业化的上下文时面临挑战。
解决上下文限制可以采用两种主要方法:
第二种选项称为 RAG,我们将在接下来的章节中更详细地探讨它。
来源
在本节中,我们将概述如何使用向量数据库构建大型语言模型(LLM)的过程。该模型是一个Closed-QA bot。此机器人旨在通过一系列集成的技术组件有效回答科学相关的问题:
为了实现本文讨论的代码,需要安装以下内容:
!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 数据集,重点关注 closed_qa 类别。这些条目通常因其对精确信息的需求而具有特定性,这使得它们对一般训练的大型语言模型 (LLM) 构成了挑战。
from datasets import load_dataset # 加载数据集的训练部分 train_dataset = load_dataset("databricks/databricks-dolly-15k", split='train') # 过滤数据集,仅保留类别为 'closed_qa' 的条目 closed_qa_dataset = train_dataset.filter(lambda example: example['category'] == 'closed_qa') print(closed_qa_dataset[0])
一个典型的数据集条目如下所示:
{ "instruction": "田村知明是什么时候出生的?", "context": "田村知明于1981年7月10日出生在日本熊本县。高中毕业后,他在2000年加入了J1联赛俱乐部福冈AVISPA。他的职业生涯涉及多个位置和俱乐部,从福冈AVISPA的中场球员到奥ita Trinita、山形山头队、神户维斯特尔和熊本红队等俱乐部的防守中场和中后卫。他还曾在印度尼西亚的佩塞拉·拉蒙甘队效力,之后回到日本加入吉拉万茨·北九州队,并于2012年退役。", "response": "田村知明出生于1981年7月10日。", "category": "closed_qa" }
接下来,我们将专注于为每组指令及其相应上下文生成词嵌入,并将它们整合到我们的向量数据库ChromaDB中。
Chroma DB 是一个开源的向量存储系统,特别擅长管理向量嵌入。它适用于语义搜索引擎等应用,在自然语言处理和机器学习领域尤为重要。作为内存数据库,Chroma DB 的高效性使得快速访问和操作数据成为可能,这对于高速数据处理至关重要。其友好的 Python 设置增强了它在我们项目中的吸引力,简化了集成到我们工作流程的过程。更多详细文档请参阅:Chroma DB 文档。
来源
为了生成答案的嵌入,我们使用了 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}"]) # 方法用于根据查询在ChromaDB集合中搜索相关上下文 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("知识库") # 假设closed_qa_dataset已定义并可用 vector_store.populate_vectors(closed_qa_dataset)
对于每个数据集条目,我们生成并存储将“指令”和“上下文”字段结合后的嵌入,其中上下文作为检索时LLM提示中的文档。
接下来,我们将使用 Falcon-7b-instruct LLM 生成对封闭信息查询的响应,无需额外上下文,展示我们丰富知识库的有效性。
对于我们的生成文本任务,我们将利用来自Hugging Face的falcon-7b-instruct模型的能力。该模型是阿布扎比科技创新研究所开发的创新Falcon系列的一部分。
让Falcon-7B-Instruct脱颖而出的是它高效地平衡了高级功能和可管理的规模。它设计用于复杂的文本理解和生成任务,提供与更大、闭源模型相当的性能,但以更精简的形式呈现。这使得它成为我们项目的理想选择,在需要深入的语言理解而不受更大模型开销影响的情况下尤为合适。
如果你计划运行Falcon-7B-Instruct模型,无论是本地机器还是远程服务器,都需要注意硬件要求。如HuggingFace的文档中所述,该模型至少需要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['generated_text']
这段代码示例基于Hugging Face的文档,非常清晰易懂。
让我们拆解其主要组件以更好地理解:
AutoTokenizer.from_pretrained(model)
这个调用加载了一个专门为此模型设计的分词器,确保文本的分词方式与模型的训练方式一致。示例用法:
# 初始化Falcon模型类 falcon_model = Falcon7BInstructModel() user_question = "Tomoaki Komorida是什么时候出生的?" # 使用LLM生成用户问题的答案 answer = falcon_model.generate_answer(user_question) print(f"结果: {answer}")
正如你可能猜到的,这里是给定用户问题的模型输出:
{ answer: “我没有关于古本耕治的出生日期的信息。” }
利用 Falcon-7B-Instruct 而不提供额外上下文会得到一个负面回应,因为它没有经过这种“鲜为人知”的信息的训练。这说明了在生成更具体和有用的答案时,需要提供更丰富的上下文。
现在,让我们通过从向量存储中检索相关上下文来提升生成模型的能力。
有趣的是,我们使用相同的 VectorStore 类来生成嵌入并向量以及从用户问题中获取上下文:
# 假设 vector_store 和 falcon_model 已经初始化 # 从 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"结果: {enriched_answer}")
当然,我们LLM提供的上下文丰富答案准确而迅速:
古居.tomosaic.智生于1981年7月10日。
注:人名“Tomoaki Komorida”在中文中通常保留原文,此处假设为“古居智”,请根据实际情况调整。
在我们的详细探索中,我们已经向您展示了如何构建一个大型语言模型(LLM)应用程序,并通过自定义数据集丰富了该模型。很明显,管理这样一个模型、实验不同的数据集、设置必要的基础设施并实现一个功能性的解决方案绝非易事。然而,这就是 Qwak 的优势所在,它简化了这一复杂的过程。使用 Qwak,您不仅在管理模型,更是在从概念到部署的旅程中有效提高了效率,使您的环境中上下文感知的 LLM 在短短几个小时内即可运行。
展望未来,我们非常激动能够通过不断改进现有功能来提升您使用 Qwak 的体验。我们当前的重点是增强与我们 向量存储 的集成,提供更强大的 ETL(提取、转换、加载)和可视化功能。
要查看本文中讨论的应用程序的全面构建和部署示例,请访问我们的示例仓库。我们已经详细准备了所有内容,以确保您的旅程既顺畅又富有信息。
我们希望这篇文章能激发你的兴趣和好奇心。我们邀请你开始自己的冒险,使用 Qwak 和向量数据库构建大型语言模型 (LLM)。今天就开始你的旅程,探索这个前沿平台提供的各种可能性,完全免费。祝你建模愉快!
原发布于 https://www.qwak.com .