到本书结束时,我们将引导你完成构建端到端大型语言模型(LLM)产品的旅程。我们坚信,学习LLM和生产级机器学习(ML)的最佳方式是亲自动手,构建实际系统。本书将教你如何构建一个“LLM双生子”——一个能够学习模仿特定人物写作风格的AI角色,将其独特的风格、语气和个性融入LLM中。通过这一示例,我们将带你走过完整的ML生命周期,从数据收集到部署和监控。实现LLM双生子的过程中所学的许多概念,同样可以应用于其他基于LLM或ML的应用中。
从工程的角度来看,在实施一个新产品之前,我们需要完成三个规划步骤。首先,理解我们要解决的问题以及我们想要构建的内容至关重要。在我们的案例中,LLM双生子究竟是什么?为什么要构建它?这一步是我们需要畅想并专注于“为什么”的时刻。其次,为了反映真实场景,我们将设计一个具有最小功能的产品初始版本(MVP)。在这里,我们需要清晰地定义创建一个有效且有价值的产品所需的核心功能。选择基于时间线、资源和团队知识做出,这是我们将“梦想”与“现实”连接起来的一步,并最终回答以下问题:“我们要构建什么?”。
最后,我们将进行系统设计步骤,制定构建LLM系统的核心架构和设计选择。需要注意的是,前两个步骤主要涉及产品,而最后一步则是技术性的,重点在于“如何”实现。
这三个步骤是构建真实世界产品的自然流程。即使前两步不需要太多的ML知识,但它们对于清晰理解“如何”以明确的愿景来构建产品至关重要。本章简要概括了以下主题:
- 理解LLM双生子概念
- 规划LLM双生子产品的MVP
- 构建包含特征、训练和推理管道的ML系统
- 设计LLM双生子的系统架构
到本章结束时,你将对整个书籍的学习内容和构建目标有一个清晰的认识。
理解LLM双生子概念
第一步是明确我们想要创造什么以及构建它的价值所在。LLM双生子的概念是新的。因此,在深入技术细节之前,有必要了解它是什么、我们应该期待什么以及它应该如何工作。对最终目标有一个扎实的直觉将使本书中所涉及的理论、代码和基础设施更易理解。
什么是LLM双生子?
简单来说,LLM双生子是一个将你的写作风格、语气和个性融入大型语言模型(LLM)中的AI角色,是一个被投射到LLM中的数字化的“你”。与训练于整个互联网的通用LLM不同,LLM双生子是针对你的数据进行微调的。因为ML模型会反映其训练数据的特性,所以这个LLM将体现你的写作风格、语气和个性。我们有意使用了“投射”这个词,因为和任何其他投射一样,信息在过程中会有所损失。因此,这个LLM不会完全是“你”,而是反映了训练数据中的那个“你”的一面。
理解LLM会反映其训练数据非常重要。如果输入莎士比亚的作品,它将开始模仿他的写作风格;如果以Billie Eilish的作品为训练数据,它将模仿她的歌曲风格。这就是所谓的风格迁移,这一概念在生成图像中也非常流行。比如,你想用梵高的风格生成一张猫的图像。我们将在此基础上利用风格迁移策略,但不是选择一个名人个性,而是基于我们自己的个性。
为了使LLM适应特定的风格和语气,除了微调外,我们还将利用各种先进的检索增强生成(RAG)技术,通过之前的自我嵌入向量来为自回归过程提供条件。
在第5章中我们将深入探讨微调,第4章和第9章中将讨论RAG技术,但现在让我们通过几个示例直观地理解我们之前所提到的内容。
以下是一些可以将LLM微调成你“分身”的场景:
- LinkedIn帖子和X(推特)帖子:让LLM专注于撰写社交媒体内容。
- 与朋友和家人的聊天记录:使LLM适应真实的“你”。
- 学术论文和文章:校准LLM以撰写正式和教育性的内容。
- 代码:使LLM专注于以你的方式编写代码。
以上所有场景都可以归结为一个核心策略:收集你的数字数据(或其中的一部分),并使用不同的算法将其提供给LLM。最终,LLM反映了所收集数据的语气和风格。听起来很简单,对吧?
然而,这引发了许多技术和道德问题。首先,从技术角度看,我们如何获取这些数据?我们是否有足够的数字数据将自己投射到LLM中?哪些数据有价值?其次,从道德角度看,这样做是否合适?我们真的想创造一个“分身”吗?它会用我们的语气和个性写作,还是只是试图复制它?
记住,本节的重点不是“是什么”和“怎么做”,而是“为什么”。让我们理解拥有自己的LLM双生子为什么有意义,它为何有价值,以及如果我们正确地设定问题框架,为什么在道德上可以接受。
为什么构建LLM双生子很重要
作为一名工程师(或其他职业人士),构建个人品牌比传统简历更具价值。创建个人品牌的最大问题在于,在LinkedIn、X(推特)、Medium等平台上写作内容非常耗时。即使你热爱写作和内容创作,最终也会面临灵感枯竭或时间不足的困境,感到需要帮助。我们不想将这一部分变成广告,但我们确实需要清晰地理解这个产品/项目的范围。
我们希望构建一个LLM双生子,以我们的风格和语气在LinkedIn、X、Instagram、Substack和Medium(或其他博客)上编写个性化内容。它不会用于任何不道德的场景,而是作为你的写作副驾驶。基于本书教授的内容,你可以创造性地将其应用于不同的用例,但我们将专注于生成社交媒体内容和文章的细分领域。因此,我们可以将主意的框架输入LLM双生子,让它完成繁重的写作工作,而无需从头开始写作。
最终,我们需要检查内容的正确性并按我们的喜好进行格式化(更多具体功能将在“LLM双生子产品MVP规划”部分讨论)。通过这种方式,我们将自己投射到一个内容创作的LLM双生子中,以帮助自动化写作过程。如果我们尝试将这个特定的LLM用于不同的场景,它可能会失败,因为我们将通过微调、提示工程和RAG技术使其专注于某个特定领域。
那么,构建LLM双生子有什么意义?它能帮助你实现以下几点:
- 创建个人品牌
- 自动化写作过程
- 激发新的创意
副驾驶和LLM双生子的区别是什么?
副驾驶和数字双生子是两种不同的概念,但它们可以结合在一起形成强大的解决方案:
- 副驾驶是一个AI助手或工具,用于增强人类在编程、写作或内容创作等任务中的表现。
- 双生子则是一个1:1的数字表示,通常利用AI来缩小物理世界与数字世界之间的差距。例如,LLM双生子是一个可以模仿你的语气、个性和写作风格的LLM。
根据这些定义,一个能够像你一样进行写作和内容创作的AI助手就是你的LLM双生子副驾驶。
此外,理解构建LLM双生子是完全符合道德的也至关重要。LLM只会根据我们的个人数字数据进行微调。我们不会收集和使用他人的数据来尝试模仿他人的身份。我们有明确的目标:创建个性化的写作“复制体”。每个人都会有自己的LLM双生子,且访问权限将受到严格限制。
当然,其中涉及许多安全问题,但我们不会在此深入探讨,因为这一话题本身足以写成一本书。
为什么不用ChatGPT(或其他类似的聊天机器人)?
本节将仅在生成个性化内容的背景下讨论使用ChatGPT(或其他类似的聊天机器人)。
我们之前已经提供了答案:ChatGPT没有个性化到你的写作风格和语气上。相反,它的风格非常通用,缺乏细致和独特性。在构建个人品牌时,保持原有的语气对于长期成功至关重要。因此,直接使用ChatGPT或Gemini无法产生最理想的结果。即使你愿意分享非个性化的内容,随意使用ChatGPT可能导致以下问题:
- 幻觉带来的错误信息:手动检查结果中的幻觉或使用第三方工具评估结果是一项枯燥且低效的工作。
- 繁琐的手动提示:你必须手动编写提示词并注入外部信息,这非常耗时。此外,由于无法完全控制提示词和注入的数据,生成的答案在不同会话之间很难复制。虽然可以使用API和LangChain等工具解决部分问题,但需要编程经验。
根据我们的经验,如果你想要高质量、真正有价值的内容,调试生成的文本所耗费的时间比自己写还要多。
LLM双生子的关键在于以下几点:
- 我们收集哪些数据
- 如何预处理数据
- 如何将数据输入LLM
- 如何串联多个提示词以获得期望的结果
- 如何评估生成的内容
LLM本身固然重要,但要强调的是,使用ChatGPT的网页界面在管理和注入各种数据源或评估输出方面非常繁琐。解决方案是构建一个LLM系统,以封装和自动化以下所有步骤(每次手动重复这些操作既不可持续也不现实):
- 数据收集
- 数据预处理
- 数据存储、版本管理和检索
- LLM微调
- 检索增强生成(RAG)
- 内容生成评估
需要注意的是,我们并没有说不能使用OpenAI的GPT API,只是说我们将要展示的LLM框架是模型无关的。因此,如果可以通过编程操作并暴露微调接口,它就可以集成到我们将学习构建的LLM双生子系统中。大多数成功的ML产品的关键是以数据为中心,并使你的架构与模型无关。这样,你就可以在特定数据上快速尝试多个模型。
规划LLM双生子产品的MVP
既然我们了解了什么是LLM双生子以及我们为何要构建它,就必须明确定义产品的功能。在本书中,我们将专注于首个迭代,通常称为最小可行产品(MVP),以遵循大多数产品的自然周期。这里的主要目标是将我们的想法与可用资源相结合,以实现实际且可行的业务目标。即使作为一名工程师,随着责任的增长,也必须经历这些步骤,以缩小业务需求与可实现之间的差距。
什么是MVP?
MVP是包含足够功能以吸引早期用户并在开发初期测试产品概念可行性的产品版本。MVP的目的是通过最小的努力从市场中获取见解。
MVP是一种强大的策略,原因如下:
- 加速上市时间:快速推出产品以获得早期的市场反馈
- 验证创意:在对产品进行全面开发前,通过实际用户进行测试
- 市场调研:了解目标用户的偏好
- 降低风险:减少对可能无法取得市场成功的产品的时间和资源投入
坚持MVP中的“V”(可行性)至关重要,意味着产品必须是可行的。即使产品规模较小,也必须提供端到端的用户体验,不应有半成品功能。产品应是一个可正常使用并具有良好用户体验的成品,让用户喜欢并愿意持续使用,以观察其潜力的不断发展。
定义LLM双生子的MVP
作为一个思维实验,假设我们并不是为这本书构建这个项目,而是想打造一个真实的产品。在这种情况下,我们的资源是什么呢?很遗憾,并不多:
- 我们有一个由两名ML工程师和一名ML研究员组成的三人团队
- 仅有的设备是我们的笔记本电脑
- 个人资金用于计算(如训练LLM)
- 我们的热情
如你所见,我们的资源有限。即使这只是一个思维实验,也反映了大多数初创企业在起步阶段的真实情况。因此,我们在定义LLM双生子的MVP和选择功能时必须非常有策略性。我们的目标很简单:我们希望在投入的努力和资源与产品价值之间取得最大化平衡。
为了简化,我们将为LLM双生子构建以下功能:
-
从LinkedIn、Medium、Substack和GitHub个人资料中收集数据
-
使用收集的数据对开源LLM进行微调
-
使用我们的数字数据填充向量数据库,以支持检索增强生成(RAG)
-
利用以下资源创建LinkedIn帖子:
- 用户的提示词
- RAG以重用和引用旧内容
- 新的帖子、文章或论文作为LLM的附加知识
-
提供一个简单的网页界面,以便与LLM双生子互动并支持以下操作:
- 配置社交媒体链接并触发数据收集步骤
- 发送提示词或外部资源链接
这将是LLM双生子的MVP。尽管看起来功能不多,但请记住,我们必须使该系统具备成本效益、可扩展性和模块化。
即使我们仅关注本节定义的LLM双生子的核心功能,我们也会在构建产品时考虑最新的LLM研究成果以及最佳的软件工程和MLOps实践。我们的目标是展示如何构建一个具备成本效益且可扩展的LLM应用。
到目前为止,我们已经从用户和业务的角度审视了LLM双生子。最后一步是从工程角度分析它,并制定开发计划以技术上解决该问题。从现在起,本书将专注于LLM双生子的实现。
构建包含特征、训练和推理管道的ML系统
在深入探讨LLM双生子架构的具体细节之前,我们需要理解该架构核心的ML系统模式,即特征、训练和推理(FTI)架构。本节将概述FTI管道设计及其如何构建ML应用。
让我们看看如何将FTI管道应用于LLM双生子的架构。
构建ML系统的问题
构建生产级的ML系统远不止于训练模型。从工程角度来看,训练模型在大多数用例中是最简单的步骤。然而,当需要确定合适的架构和超参数时,训练模型会变得复杂。这不仅是工程问题,更是研究问题。
在这个阶段,我们关注如何设计一个面向生产的架构。虽然训练出高准确度的模型非常有价值,但仅仅在静态数据集上训练远不足以让其具备可靠的部署能力。我们必须考虑以下几个方面:
- 引入、清理和验证新数据
- 区分训练与推理设置
- 在适当的环境中计算并提供特征
- 以具成本效益的方式提供模型
- 对数据集和模型进行版本管理、跟踪和共享
- 监控基础设施和模型的运行状况
- 在可扩展的基础设施上部署模型
- 自动化部署和训练过程
这些是ML或MLOps工程师必须考虑的问题,而研究或数据科学团队通常负责训练模型。
前图展示了Google Cloud团队建议的成熟ML和MLOps系统所需的所有组件。除了ML代码外,系统中还涉及许多其他组件。系统的其他部分包括配置、自动化、数据收集、数据验证、测试和调试、资源管理、模型分析、过程和元数据管理、服务基础设施以及监控。这表明,当将ML模型投入生产时,我们必须考虑许多组件。
因此,关键问题是:如何将所有这些组件连接成一个统一的系统?我们必须创建一个模板,以便清晰地设计ML系统来回答这个问题。
在经典软件开发中已有类似的解决方案。例如,整体来看,大多数软件应用程序可以分为数据库、业务逻辑和UI层。每一层都可以根据需求变得复杂,但从高层次的视角看,标准软件的架构可以简化为上述三个组件。
那么,ML应用程序有类似的结构吗?第一步是研究以往的解决方案,并分析它们为何不适用于构建可扩展的ML系统。
以往解决方案的问题
在图1.2中,可以看到大多数ML应用程序中常见的架构。它基于一个单体批处理架构,将特征生成、模型训练和推理耦合在同一组件中。通过这种方式,快速解决了ML领域的一个关键问题:训练-服务偏差。训练-服务偏差发生在模型接收到的特征在训练和推理时被不同方式计算时。
在这种架构中,特征使用相同的代码生成,因此默认解决了训练-服务偏差问题。这种模式在处理小数据时效果良好。管道按计划在批处理模式下运行,预测结果由第三方应用程序(如仪表板)消费。
不幸的是,构建一个单体批处理系统会引发许多其他问题,例如:
- 特征无法复用(无论是在你的系统中还是在其他系统中)
- 如果数据量增加,必须重构整个代码以支持PySpark或Ray
- 很难用更高效的语言(如C++、Java或Rust)重写预测模块
- 难以在多个团队之间共享特征、训练和预测模块的工作
- 无法切换到实时流技术以支持实时训练
在图1.3中,我们可以看到类似的实时系统场景。这个用例除了前面提到的问题,还引入了另一个问题。为了进行预测,我们必须通过客户端请求传输整个状态,以便计算特征并将其传递给模型。
考虑为用户计算电影推荐的场景。我们不能仅传递用户ID,还必须传输完整的用户状态,包括其姓名、年龄、性别、观影历史等。此方法潜在错误较多,因为客户端必须了解如何访问这些状态,并且这种方法与模型服务紧密耦合。
另一个例子是在实现具有RAG(检索增强生成)支持的LLM时。我们随查询附加的文档表示我们的外部状态。如果不将这些记录存储在向量数据库中,我们就必须将它们与用户查询一起传递。要做到这一点,客户端必须知道如何查询和检索文档,但这在实际中不可行。让客户端应用了解如何访问或计算特征是一种反模式。如果你不了解RAG的工作原理,我们将在第8章和第9章中详细解释。
总之,我们的问题在于如何在不通过客户端请求传递特征的情况下访问特征以进行预测。以用户电影推荐的第一个示例为例,如何仅基于用户ID来预测推荐?请记住这些问题,我们很快会解答它们。
在另一端,Google Cloud提供了一个生产级的架构,如图1.4所示。不幸的是,即使这是一个可行的解决方案,它非常复杂且不直观。如果你在生产环境中部署和维护ML模型的经验不足,将很难理解。此外,如何从小规模开始并随时间逐步扩展系统并不容易理解。
以下图像来自Google的创作和共享,根据《知识共享4.0署名许可证》中的条款使用。
这正是FTI管道架构发挥作用的地方。下一节将向你展示如何使用直观的ML设计解决这些基本问题。
解决方案 —— 用于ML系统的ML管道
解决方案基于创建一个清晰简洁的思维导图,任何团队或个人都可以遵循此导图来计算特征、训练模型并进行预测。基于任何ML系统所需的这三个关键步骤,这种模式被称为FTI管道。那么,它与我们之前介绍的有何不同?
该模式表明,任何ML系统都可以简化为三个管道:特征、训练和推理(类似于经典软件中的数据库、业务逻辑和UI层)。这非常强大,因为我们可以清晰地定义每个管道的范围和接口。此外,这使得理解三个组件之间的交互更加容易。最终,我们只需处理三个组件,而不是图1.4中建议的20个,这更易于管理和定义。
如图1.5所示,我们有特征、训练和推理管道。接下来,我们将深入探讨每一个管道,了解它们的范围和接口。
在深入细节之前,重要的是要理解每个管道都是一个不同的组件,可以在不同的进程或硬件上运行。因此,每个管道可以使用不同的技术编写、由不同的团队开发,或者独立地进行扩展。关键在于,这种设计对团队的需求非常灵活,充当架构设计的思维导图。
特征管道
特征管道将原始数据作为输入,对其进行处理,并输出模型训练或推理所需的特征和标签。特征和标签不会直接传递给模型,而是存储在特征存储库中。特征存储库的职责是存储、版本化、跟踪和共享特征。通过将特征存储在特征存储库中,我们始终拥有特征的当前状态,因此可以轻松将这些特征发送到训练和推理管道。
由于数据是版本化的,我们可以确保训练和推理时的特征始终一致,从而避免了训练-服务偏差问题。
训练管道
训练管道从特征存储库中获取特征和标签作为输入,并输出一个或多个训练好的模型。模型存储在模型注册表中。其角色类似于特征存储库,但这里模型是核心对象。因此,模型注册表将存储、版本化、跟踪和共享模型,并将其提供给推理管道。
此外,大多数现代模型注册表支持元数据存储,这允许你指定模型训练过程中的重要信息,包括用于训练模型的特征、标签及其版本。这样,我们始终知道模型是基于哪些数据进行训练的。
推理管道
推理管道从特征存储库获取特征和标签,从模型注册表获取训练好的模型。通过这两个输入,推理可以轻松地在批处理模式或实时模式下进行。
作为一个灵活的模式,你可以决定如何处理预测结果。如果是批处理系统,预测结果可能会存储在数据库中;如果是实时系统,预测结果会直接提供给请求的客户端。此外,特征、标签和模型都是版本化的,使我们可以轻松地升级或回滚模型部署。例如,我们始终知道模型v1使用特征F1、F2和F3,而模型v2使用F2、F3和F4。因此,我们可以快速更改模型与特征之间的连接。
FTI架构的优势
最后,总结一下FTI管道的核心接口:
- 特征管道接收数据并输出存储在特征存储库中的特征和标签。
- 训练管道从特征存储库中查询特征和标签,并输出一个模型到模型注册表。
- 推理管道使用来自特征存储库的特征和模型注册表中的模型来进行预测。
无论你的ML系统多么复杂,这些接口都将保持不变。
现在我们对这一模式的工作方式有了更好的理解,以下是使用该模式的主要好处:
- 由于仅有三个组件,使用起来直观,易于理解。
- 每个组件可以用不同的技术栈来编写,因此我们可以快速调整以满足特定需求,例如大数据或流式数据处理。此外,这也允许我们选择最适合的工具。
- 三个组件之间有清晰的接口,因此每个组件都可以由不同的团队开发(如果需要),使开发更加易于管理和扩展。
- 每个组件都可以独立部署、扩展和监控。
关于FTI模式的最后一点需要理解的是,系统不必只包含这三个管道。在大多数情况下,它们可能会包括更多。例如,特征管道可以包含一个用于计算特征的服务和一个用于验证数据的服务。训练管道可以由训练和评估组件组成。
FTI管道充当逻辑层,因此每个管道可以非常复杂,包含多个服务。然而,关键在于保持FTI管道之间通过特征存储库和模型注册表进行交互的相同接口。通过这样做,每个FTI组件可以独立发展,而不必了解彼此的详细信息,也不会因系统更新而导致系统中断。
如果想了解更多关于FTI管道模式的内容,可以参考Jim Dowling(Hopsworks的CEO兼联合创始人)撰写的《从MLOps到具有特征/训练/推理管道的ML系统》:www.hopsworks.ai/post/mlops-…。他的文章为本节提供了灵感。
现在我们已经理解了FTI管道架构,本章的最后一步是看看它如何应用于LLM双生子的使用案例。
设计LLM双生子的系统架构
在本节中,我们将列出LLM双生子应用的具体技术细节,并了解如何通过使用FTI架构设计我们的LLM系统来解决这些问题。不过,在深入探讨管道之前,我们想强调,在这一阶段我们不会关注工具或技术栈。我们只想定义系统的高层架构,这一架构与语言、框架、平台和基础设施无关。我们将聚焦于每个组件的范围、接口和相互连接性。在后续章节中,我们会涵盖实现细节和技术栈。
列出LLM双生子架构的技术细节
到目前为止,我们已经从用户角度定义了LLM双生子应支持的功能。现在,让我们从纯技术角度明确ML系统的需求:
数据方面,我们需要执行以下操作:
- 完全自动化地从LinkedIn、Medium、Substack和GitHub采集数据,并按计划进行
- 标准化爬取的数据并存储在数据仓库中
- 清理原始数据
- 创建用于微调LLM的指令数据集
- 对清理后的数据进行分块和嵌入,将向量化数据存储到向量数据库中,以支持RAG
训练方面,我们需要完成以下任务:
- 微调各种规模的LLM(7B、14B、30B或70B参数)
- 微调多个大小的指令数据集
- 切换不同的LLM类型(例如在Mistral、Llama和GPT之间切换)
- 跟踪和比较实验
- 在部署前测试潜在的生产LLM候选模型
- 在有新指令数据集可用时自动启动训练
推理代码将具有以下特性:
- 一个供客户端与LLM双生子交互的REST API接口
- 实时访问向量数据库以支持RAG
- 能够使用不同规模的LLM进行推理
- 基于用户请求自动扩展
- 自动部署通过评估步骤的LLM
系统将支持以下LLMOps功能:
- 指令数据集的版本管理、追溯和可重用性
- 模型的版本管理、追溯和可重用性
- 实验跟踪
- 持续训练、持续集成和持续交付(CT/CI/CD)
- 提示词和系统监控
如果目前有任何技术需求不太理解,请继续跟随我们的说明。为避免重复,我们将在具体章节中详述每个需求。
以上列表相当全面。我们本可以更加细化,但在这个阶段,我们只关注核心功能。在实现每个组件时,我们将深入探讨所有细节。但目前,我们必须问自己的根本问题是:如何应用FTI管道设计来实现上述需求列表?
如何使用FTI管道设计构建LLM双生子架构
我们将系统分为四个核心组件。你可能会问:“四个?FTI管道设计不是说三个吗?”这是个好问题,幸运的是,答案很简单。我们还需要实现数据管道,除了特征、训练和推理管道之外。按照最佳实践:
- 数据工程团队负责数据管道
- ML工程团队负责FTI管道
鉴于我们的小团队目标是构建一个MVP,我们必须实现整个应用程序。这包括定义数据收集和FTI管道。对于资源有限、无法提供专门团队的初创公司而言,通常需要从端到端解决问题。因此,工程师需根据产品状态承担多重角色。然而,在任何情况下,了解端到端ML系统的工作原理都非常有助于更好地理解他人的工作。
图1.6展示了LLM系统架构。最好的理解方式是逐个审视这四个组件,并解释它们的工作原理。
数据收集管道
数据收集管道负责从Medium、Substack、LinkedIn和GitHub爬取个人数据。作为数据管道,我们将使用ETL(抽取、加载、转换)模式,从社交媒体平台提取数据,标准化后加载到数据仓库中。
需要特别强调的是,数据收集管道仅设计用于从你的社交媒体平台抓取数据,不会访问其他人的数据。作为本书的示例,我们同意将收集的数据用于学习目的。否则,未经他人同意使用他们的数据是不道德的。
此组件的输出将是一个NoSQL数据库,作为我们的数据仓库。由于我们处理的是自然非结构化的文本数据,NoSQL数据库非常适合此需求。
尽管像MongoDB这样的NoSQL数据库并非传统的数据仓库,但在我们看来,它将扮演这一角色。原因是它存储了通过ETL管道收集的标准化原始数据,可以被ML系统直接使用。
收集的数字数据分为三类:
- 文章(Medium、Substack)
- 帖子(LinkedIn)
- 代码(GitHub)
我们希望抽象化数据来源的平台。例如,在将一篇文章输入LLM时,了解其来自Medium还是Substack并不重要。我们可以将来源URL作为元数据保留以供参考。但从处理、微调和RAG的角度来看,了解数据的类型至关重要,因为每个类别需要不同的处理方式。例如,帖子、文章和代码的分块策略将有所不同。
此外,通过按类别而非来源对数据进行分组,我们可以轻松地接入其他平台的数据,例如将X的数据加入帖子或将GitLab的数据加入代码。作为一个模块化系统,我们只需在数据收集管道中添加一个ETL组件,其他部分无需进一步代码修改即可正常工作。
特征管道
特征管道的作用是从数据仓库中获取原始文章、帖子和代码数据点,对其进行处理,并将结果加载到特征存储中。
FTI模式的特性已在此处显现。以下是LLM双生子特征管道的一些自定义属性:
- 对三种数据(文章、帖子和代码)进行不同的处理
- 包含三大处理步骤,用于微调和RAG:清理、分块和嵌入
- 创建两种数字数据快照,一种用于清理后微调,一种用于嵌入后RAG
- 使用逻辑特征存储而非专用特征存储
我们来看一下逻辑特征存储部分。对于任何基于RAG的系统,基础设施的核心之一是向量数据库。我们没有集成其他数据库或专用特征存储,而是使用向量数据库加上一些附加逻辑,以满足系统对特征存储的需求。
向量数据库本身不提供训练数据集的概念,但它可以作为NoSQL数据库使用,这意味着我们可以通过ID和集合名称访问数据点。因此,我们可以轻松查询向量数据库以获取新数据点,而不需要向量搜索逻辑。最终,我们将检索的数据封装成一个具有版本化、追踪和可共享属性的工件——关于工件的更多信息将在第2章介绍。现在,你只需知道工件是MLOps中的一个概念,用于封装数据并丰富其属性。
系统的其他部分将如何访问逻辑特征存储?训练管道将使用指令数据集作为工件,推理管道将使用向量搜索技术查询向量数据库以获得额外上下文。
在我们的用例中,这已经足够,因为以下原因:
- 工件在训练等离线用例中表现良好
- 向量数据库适合在线访问,这是推理所需的。
在后续章节中,我们将详细说明三种数据类别(文章、帖子和代码)是如何被清理、分块和嵌入的。
总之,我们将原始的文章、帖子或代码数据点输入,进行处理,并存储在特征存储中,使其对训练和推理管道可访问。精简复杂性并仅专注于接口,这与FTI模式完全吻合。漂亮,对吧?
训练管道
训练管道从特征存储中获取指令数据集,对LLM进行微调,并将微调后的LLM权重存储在模型注册表中。具体而言,当逻辑特征存储中出现新的指令数据集时,我们将触发训练管道,获取工件并微调LLM。
在初期阶段,这一步由数据科学团队负责。他们通过自动超参数调优或手动运行多个实验,以找到最佳的模型和超参数组合。为了比较并选择最佳的超参数组合,我们将使用实验追踪器来记录所有有价值的数据,并在不同实验间进行比较。最终,他们将选择最佳的超参数和微调后的LLM,并将其作为生产候选模型。被提议的LLM随后存储在模型注册表中。在实验阶段结束后,我们将保存和重用找到的最佳超参数,以消除过程中的手动限制,从而可以完全自动化训练过程,即所谓的持续训练(CT)。
在微调之后,测试管道会被触发,以进行更严格的分析。在将新模型推向生产之前,必须对其进行更严格的测试,以确保最新的候选模型优于当前的生产模型。如果该步骤通过,模型将被标记为已接受并部署到生产推理管道中。即使在完全自动化的ML系统中,也建议在接受新的生产模型之前保留一个手动步骤。就像按下“红色按钮”一样,专家会查看测试组件生成的报告。如果一切正常,模型会被批准,自动化流程继续。
此组件的特殊性集中在LLM的几个方面,例如:
- 如何实现与LLM无关的管道?
- 应使用哪些微调技术?
- 如何在不同规模的LLM和数据集上扩展微调算法?
- 如何从多个实验中选择一个LLM生产候选模型?
- 如何测试LLM以决定是否将其推向生产?
在本书结束时,你将知道如何回答所有这些问题。
最后需要澄清的是持续训练(CT)。我们的模块化设计允许我们快速利用ML编排器来安排和触发系统的不同部分。例如,我们可以安排数据收集管道每周进行一次数据抓取。当数据仓库中有新数据时触发特征管道,而当有新的指令数据集时触发训练管道。
推理管道
推理管道是最后一个环节。它连接到模型注册表和逻辑特征存储。它从模型注册表中加载微调后的LLM,并从逻辑特征存储访问向量数据库以支持RAG。它通过REST API接收客户端请求作为查询,并使用微调后的LLM和对向量数据库的访问来执行RAG并回答查询。
所有客户端查询、通过RAG丰富的提示词以及生成的答案都发送到提示监控系统,以便分析、调试和更好地了解系统。根据特定需求,监控系统可以触发警报以手动或自动采取措施。
在接口层面上,此组件完全遵循FTI架构,但深入细节后,可以观察到LLM和RAG系统的独特特性,例如:
- 一个用于RAG的检索客户端,执行向量搜索
- 用于将用户查询和外部信息映射到LLM输入的提示模板
- 用于提示监控的特殊工具
对FTI设计和LLM双生子架构的最终思考
我们不必对FTI模式过于死板,它只是用于澄清ML系统设计的工具。例如,虽然通常使用专用特征存储,但在我们的系统中,基于向量数据库和工件的逻辑特征存储更为简单且成本更低。关键在于实现特征存储所需的功能,例如提供版本化和可重用的训练数据集。
最后,我们将简要说明每个组件的计算需求。数据收集和特征管道主要依赖CPU,不需要高性能机器。训练管道需要能加载和微调LLM的高性能GPU机器。推理管道的计算需求居中,仍需要高性能机器,但计算强度较训练步骤低。不过,推理管道直接与用户交互,因此必须仔细测试,以确保延迟符合良好用户体验的要求。通过FTI设计,我们可以为每个组件选择合适的计算资源。
此外,每个管道的扩展方式不同。数据和特征管道将根据CPU和内存负载进行横向扩展;训练管道将通过增加GPU实现纵向扩展;推理管道将基于客户端请求数量横向扩展。
总结来看,所提出的LLM架构符合本节开头列出的所有技术需求。它按要求处理数据,训练管道是模块化的,可以快速适配不同的LLM、数据集或微调技术。推理管道支持RAG并通过REST API公开。在LLMOps方面,系统支持数据集和模型的版本管理、追溯和可重用性,并拥有监控服务,且整个ML架构设计时考虑了持续训练、持续集成和持续交付(CT/CI/CD)。
以上内容概括了LLM双生子架构的高层次概览。
总结
本章对于理解本书的目标至关重要。作为一本以产品为导向的书籍,我们将带你构建一个端到端的ML系统,首先必须理解LLM双生子的概念。接下来,我们介绍了MVP的概念,以及如何根据现有资源规划LLM双生子的MVP。随后,我们将概念转化为具有具体需求的技术解决方案。在此背景下,我们介绍了FTI设计模式,并展示了其在设计模块化和可扩展系统中的实际应用。最终,我们成功应用FTI模式设计了符合所有技术需求的LLM双生子架构。
在构建系统时,清晰的全局视角至关重要。理解单个组件如何集成到整个应用程序中对于开发工作大有帮助。我们从LLM双生子架构的抽象概述开始,专注于每个组件的范围、接口和互连性。
接下来的章节将深入探讨如何实现和部署每个组件。在MLOps方面,我们将带你使用计算平台、编排器、模型注册表、工件及其他工具和概念,以支持所有的MLOps最佳实践。
参考文献
- Dowling, J. (2024年7月11日). 从MLOps到具有特征/训练/推理管道的ML系统. Hopsworks. www.hopsworks.ai/post/mlops-…
- Dowling, J. (2024年8月5日). 使用AI管道和共享存储实现AI系统的模块化和组合性. Hopsworks. www.hopsworks.ai/post/modula…
- Joseph, M. (2024年8月23日). AI系统中数据转换的分类. Hopsworks. www.hopsworks.ai/post/a-taxo…
- MLOps: 机器学习中的持续交付与自动化管道. (2024年8月28日). Google Cloud. cloud.google.com/architectur…
- Qwak. (2024年6月2日). 2024年机器学习CI/CD:构建、测试和部署的最佳实践 | Infer. Medium. medium.com/infer-qwak/…
- Qwak. (2024年7月23日). 2024年构建端到端MLOps管道的5个最佳开源工具. Medium. medium.com/infer-qwak/…
- Salama, K., Kazmierczak, J., & Schut, D. (2021). MLOps实用指南:机器学习的持续交付与自动化框架 (第1版) [PDF]. Google Cloud. services.google.com/fh/files/mi…