→ 12节课中的第5节LLM Twin 免费课程
什么是你的LLM Twin? 它是一个AI角色,通过将你的风格、个性和声音融入到LLM中,写出像你一样的内容。
图片由 DALL-E 创建
通过完成“ LLM Twin:构建您的生产就绪AI副本 ” 免费课程,您将学习如何设计、训练和部署一个由LLM、向量数据库和LLMOps最佳实践驱动的生产就绪的LLM副本。
为什么你应该在意呢? 🫵
→ 再也没有孤立的脚本或笔记本了!通过构建和部署一个端到端的生产级LLM系统来学习生产级别的机器学习。
你将 学习 如何 设计 和 构建一个真实的LLM系统 —— 从 数据收集 到 部署,全程掌握。
你还将 学习 如何 利用MLOps最佳实践 ,例如实验跟踪器、模型注册表、提示监控和版本控制。
最终目标? 构建并部署你自己的LLM孪生模型。
的 架构 由 4个Python微服务 组成:
LLM 双胞胎系统架构 [作者绘制的图片]
沿着这4个微服务,你将学习如何集成3个无服务器工具:
受众: 希望学习使用LLMOps良好原则构建可投入生产的LLM系统的MLE、DE、DS或SWE。
级别: 中级
前提条件: 具备Python、机器学习和云的基础知识
该课程 包含 10个动手实践课时 和你可以 访问 GitHub 获取 的 开源代码,展示如何构建一个端到端的LLM系统。
此外,还包括 2个 bonus 课程,教你如何 改进 RAG系统。
你可以按照自己的节奏阅读所有内容。
→ 为了最大限度地利用本课程,我们鼓励你在学习过程中克隆并运行该仓库。
文章和代码是完全免费的。它们将永远保持免费。
但是如果你打算在阅读代码时运行代码,你必须知道我们使用了几个云工具,这些工具可能会产生额外的成本。
云计算平台(AWS,Qwak)采用按需付费的计费方式。Qwak 提供了几小时的免费计算时间。因此,我们尽量将成本降到最低。
对于其他无服务器工具(Qdrant,Comet),我们将使用它们的免费版本,这是免费的。
该课程由以下人员在 Decoding ML 的支持下创建:
🔗查看 我们在GitHub上的代码 [1],并给我们一个⭐️支持
→ 快速概览 每节课的内容概览。
课程分为12节课。每篇Medium文章将是一节课:
要更好地理解课程的目标、技术细节和系统设计 → 查看第1课
让我们开始 第5课 ↓↓↓
在 第5课 中,我们将重点介绍用于RAG的高级检索模块的构建。
我们将向您展示如何实现4种检索和检索后高级优化技术,以提高您的RAG检索步骤的准确性。
在这节课中,我们将只关注RAG系统中的检索部分。
在Lesson 4中,我们展示了如何清理、切分、嵌入并将社交媒体数据加载到Qdrant向量数据库(RAG的数据摄入部分)。
在未来的课程中,我们将把这个检索模块集成到推理管道中,以构建一个完整的RAG系统。
检索 Python 模块架构
我们假设你已经熟悉了什么是简单的RAG。如果不熟悉,可以查看来自Decoding ML的以下文章,文章在2分钟内介绍了什么是简单的RAG:
🔗查看我们在GitHub上的代码 [1],并用一个⭐️支持我们
一个生产环境中的RAG系统分为 3个主要组件 :
摄入组件位于特征管道中,而检索和生成组件则实现在推理管道中。
你也可以在你的 训练管道 中使用 检索 和 生成 组件,进一步针对特定领域的提示微调你的大语言模型。
你可以应用高级技术来优化你的RAG系统在数据摄入、检索和生成方面的性能。
说归说,有三种主要的高级RAG技术:
通过微调或提示工程可以改进生成步骤,这将在未来的课程中进行解释。
预检索优化技术在Lesson 4中有解释。
在本课中,我们将向您展示一些流行的检索和检索后优化技术。
我们将结合3种技术:
我们将 使用 重排序 模式 利用 GPT-4 和 提示工程,而不是使用 Cohere 或一个 开源重排序器 cross-encoder [4]。
我不想花太多时间在理论方面。这方面的文章已经很多了。
所以我们将直接实现并集成_这些技术到我们的LLM Twin系统中。
但在这之前,让我们先澄清一些事情 ↓
高级RAG架构
我们将展示一个自定义实现,而不会使用 LangChain,来演示这些高级技术。
我们的主要 目标 是 建立 你对他们 背后工作原理 的 直觉。然而,我们将 附上 LangChain 的等效实现,这样你就可以在你的应用中使用它们了。
自定义 LangChain 可能会让人 头疼。因此,了解其工具背后的运作原理可以帮助你构建实际的应用程序。
另外,至关重要的是要知道,如果你不使用LangChain来导入数据,你也无法使用他们的检索功能,因为它们期望数据以特定的格式存在。
我们也没有在Lesson 4中使用LangChain的加载功能(将数据加载到Qdrant的特性管道),因为我们想“亲手”完成所有操作。
有太多的向量数据库……
但自从我们发现了 Qdrant,我们就爱上了它。
为什么?
为了说明这一点, 其中一个主要竞争对手 Pinecone 只支持最多 40k 令牌的文档和最多 20k 维度的向量……并且需要一个专有许可。
我还可以继续说……
…但如果你 想了解更多 ,查看 Qdrant ←
在典型的检索步骤中,你使用一个点查询你的向量数据库。
该方法的问题在于,通过使用一个单一向量,你只能覆盖你嵌入空间中的一小部分。
因此,如果你的嵌入不包含所有所需的信息,检索到的上下文将不会相关。
如果我们可以用多个语义相关的数据点查询向量数据库会怎么样?
那就是“查询扩展”技术在做的事情!
查询扩展非常直观。
你使用一个大语言模型生成多个查询,基于你的初始查询。
这些查询应该包含初始查询的多个视角。
因此,当嵌入时,它们会击中你嵌入空间中与我们初始问题仍然相关的不同区域。
你可以通过一个详细的零样本提示来扩展查询。
这里是我们简单且自定义的解决方案 ↓
查询扩展模板 → GitHub 代码 ←
这里是 LangChain的 MultiQueryRetriever 类 [5](他们的等效实现)。
在嵌入您的查询时,您不能保证嵌入向量中包含了您用例所需的所有方面。
例如,你希望确保你的检索完全依赖于查询中提供的标签。
问题在于,通过嵌入查询提示,你永远无法确定标签是否被包含在嵌入向量中,或者在与其他向量计算距离时是否有足够的信号。
如果你能提取查询中的标签并将其与嵌入查询一起使用会怎么样?
那就是自查询的全部内容!
你使用一个大型语言模型(LLM)来提取对你业务用例至关重要的各种元数据字段(例如,标签、作者ID、评论数量、点赞数、分享数等)。
在我们的自定义解决方案中,我们只提取作者ID。因此,零样本提示工程技术可以完成任务。
但是,在提取多种元数据类型时,你也应该使用少量样本学习来优化提取步骤。
自查询与向量过滤搜索紧密配合,我们将在下一节解释这一点。
这里是我们的问题解决方案 ↓
自查询模板 → GitHub 代码 ←
这里是 LangChain 的 SelfQueryRetriever 类 [6] 的等效实现,这是 使用 Qdrant 的示例 [8]。
嵌入式表示非常适合捕捉特定片段的一般语义。
但它们对于查询特定关键词不是很好。
例如,如果我们想要从我们的 Qdrant 向量数据库检索关于 LLM 的文章片段,仅使用嵌入就足够了。
然而,如果我们想要查询特定的LLM类型(例如,LLama 3),仅使用嵌入之间的相似性是不够的。
因此,嵌入式表示不适合用于精确查找特定术语的短语匹配。
结合向量搜索技术与一种(或多种)互补的搜索策略,这对于查找确切的单词非常有效。
它没有定义组合哪些算法,但混合搜索最标准的策略是结合传统的基于关键词的搜索和现代的向量搜索。
这些是如何结合的?
第一种方法** 是将2种技术的相似度分数合并如下:
hybrid_score = (1 - alpha) * sparse_score + alpha * dense_score
其中 alpha 的取值范围为 [0, 1],具体为:
此外,相似度得分定义如下:
dense_score: 是向量搜索的结果,通常使用诸如余弦距离之类的相似度度量。
第二种方法仍然使用向量搜索技术,并在检索结果的元数据上根据您的关键词应用过滤器。
→ 这也被称为过滤向量搜索。
在这个用例中,相似分数 不会根据 提供的 关键词 进行更改。
它只是你在向量的元数据上应用的一个简单的过滤器的花哨说法。
但是理解第一和第二方法之间的区别是至关重要的:
记得在自我查询步骤中,我们提取了 author_id 作为需要匹配的精确字段。
因此,我们将使用关键词搜索算法查找 author_id,并将其附加到查询扩展步骤生成的5个查询中。
当我们想要从某个特定作者获取最相关的片段时,最合理的做法是使用一个以作者ID作为过滤条件的过滤器(过滤向量搜索_)如下 ↓
self._qdrant_client.search( collection_name="vector_posts", query_filter=models.Filter( must=[ models.FieldCondition( key="author_id", match=models.MatchValue( value=metadata_filter_value, ), ) ] ), query_vector=self._embedder.encode(generated_query).tolist(), limit=k, )
注意,我们可以轻松地用多个关键词(例如,标签)扩展这一点,使自查询和混合搜索的结合成为一个强大的检索组合。
你唯一需要问自己的问题是,我们是否希望使用简单的向量搜索过滤器还是更复杂的混合搜索策略。
注意,LangChain 的 SelfQueryRetriever 类在幕后结合了自查询和混合搜索技术,如其 Qdrant 示例 [8] 所示。这就是为什么我们想从头开始构建所有内容。
现在你已经理解了我们使用的_高级检索优化技术,让我们将它们_结合起来,形成一个_Python检索类_。
这里就是主检索器函数的样子 ↓
VectorRetriever: 主要检索函数 → GitHub ←
使用 Python 的 ThreadPoolExecutor 非常强大,可以解决 I/O 瓶颈问题,因为这些操作不会受到 Python GIL 限制的影响。
这里是我们将每个高级检索步骤封装到自己的类中的方式 ↓
查询扩展链封装 → GitHub ←
The SelfQuery 类看起来非常相似 — 🔗 访问它在这里 [1] ←.
现在最后一步是为查询扩展步骤生成的每个查询调用 Qdrant ↓
VectorRetriever: 主搜索函数 → GitHub ←
注意我们有3种类型的数据_:帖子、文章和代码仓库。
因此,我们需要为每个集合分别进行查询,并最终合并结果。
最高效的方法是使用多索引技术,这样可以一次性查询多种类型的数据。
但在我撰写这篇文章时,这还不是在生产环境中解决的问题。
因此,我们分别从每个集合中收集数据,并使用重排序保留了最佳检索结果。
这是文章的最后一步。
我们在Qdrant向量数据库中为N个由查询扩展步骤生成的提示进行了不同的搜索。
每个 搜索 返回 K 个结果。
因此,我们最终得到了 N x K 个片段。
在我们特定的情况下,N = 5 & K = 3。因此,我们最终得到了15个片段。
检索后优化:重新排序
检索到的上下文可能包含仅与查询不相关的片段,这些片段仅:
我们将使用 rerank 根据每个片段相对于初始问题的相关性来对所有 N x K 个片段进行排序,其中第一个片段最为相关,最后一个片段相关性最低。
最终,我们将挑选出最相关的TOP K个片段。
Rerank 在与查询扩展结合使用时表现非常出色。
使用 rerank 时的自然流程如下:
搜索 >K 个片段 >>> 使用 rerank 重新排序 >>> 取前 K 个
因此,结合查询扩展,我们从多个空间点收集潜在有用的上下文,而不仅仅是在一个位置查找超过 K 个样本。
现在流程看起来像:
搜索 N x K 块 >>> 重新排序使用 rerank >>> 取 top K
一个典型的重新排序解决方案使用了来自句子转换器的开源Cross-Encoder模型 [4]。
这些解决方案将问题和上下文作为输入,并返回一个从0到1的分数。
在本文中,我们想采用不同的方法,使用 GPT-4 + 提示工程作为我们的重排器。
如果你想了解如何使用开源算法进行重排序,可以查看 Decoding ML 的这篇实战文章:
现在让我们看看使用 GPT-4 和提示工程的实现。
类似于我们为扩展和自我查询链所做的,我们定义了一个模板和一个链构建器 ↓
重排链 → GitHub ←
这里是我们如何将重排序链集成到检索器中的:
检索器: 重新排序步骤 → GitHub ←
…就这样!
注意这是一个实验性过程。因此,你可以进一步调整你的提示以获得更好的结果,但主要思路是相同的。
最后一步是运行整个流程。
但是有一个陷阱。
正如开头所说,检索器不会作为独立组件在LLM系统中使用。
它将作为层存在于数据和Qdrant __向量数据库之间:
推理管道 用于执行RAG
→ 那就是为什么在这个课程中没有任何基础设施的参与!
但是,为了测试检索,我们编写了一个简单的脚本 __ ↓
检索器测试入口 → GitHub ←
看看用我们自定义的检索器调用整个链路是多么简单——不需要复杂的LangChain!
现在,要调用这个脚本,运行以下Make命令:
make local-test-retriever
…就这样!
在未来的课程中,我们将学习如何将其集成到训练和推理管道中。
→ 查看LLM Twin GitHub 仓库并亲自尝试! … 当然,别忘了给它点个 ⭐️ 以便及时了解最新更新。
恭喜!
在 第5课 中,你学习了如何 构建 一个 高级RAG检索模块,该模块经过优化,可以搜索来自 Qdrant向量数据库 的帖子、文章和代码库。
首先,你了解了RAG管道可以被优化的地方:
在你学会从零开始(不使用LangChain的工具)构建以下高级RAG检索及检索后优化技术之后:
最终,你理解了检索组件在一个生成式检索和生成(RAG)大型语言模型系统中的位置,代码被多个微服务共享,并不单独存在于一个Notebook中。
在第6课中,我们将进入训练管道,并向您展示如何自动将从LinkedIn、Substack、Medium和GitHub爬取的数据转换为指令数据集,以使用GPT-4微调您的LLM Twin。
再见啦!🤗
🔗查看我们在GitHub上的代码 [1],并用一个⭐️支持我们
加入Decoding ML Newsletter 以获取经过实战检验的内容,关于设计、编码和部署生产级的ML及MLOps系统_。每周免费提供↓
[1] 您的 LLM 双胞胎课程 — GitHub 仓库 (2024), Decoding ML GitHub 组织
[2] Bytewax,Bytewax 主页
[3] Qdrant, Qdrant 文档
[4] 检索与重排序,Sentence Transformers 文档
[5] MultiQueryRetriever, LangChain 文档
[6] 自我查询, LangChain 的文档
[7] Okapi BM25,维基百科
[8] Qdrant 自查询示例, LangChain 文档
如果没有特别说明,所有图片均由作者创建。