基于模式提示的复杂多智能体系统构建——使用 GenAI 构建:参数、调优与项目阶段

0 阅读24分钟

如果你是第一次启动 GenAI 项目,那么你可以预期这个项目会与你过去经历过的其他非 AI 项目有所不同。造成这种差异的主要原因是,GenAI 项目在配置参数时需要解决循环依赖问题。GenAI 项目也更加关注配置参数的优化,而不是代码编写本身。

构建一个成功的 GenAI 项目,需要为多个参数找到最优设置。你会在本书中多次遇到这些变量,并学习每个变量的用途以及如何优化它。由于这些参数之间存在高度依赖关系,即便只改变一个参数,也可能导致系统停止正常工作,从而需要调整其他参数;而这些调整又可能产生新的不兼容问题,如此循环往复。大多数开发者都能理解这个问题,因为他们也曾在库依赖中面对过类似的循环依赖挑战。幸运的是,大多数编程语言至少都有一个包管理器,可以处理复杂的、循环的库依赖。

在本章中,我们将从高层视角考察构建 GenAI 应用的过程,重点关注参数调优。我们将探索如何识别需要优化的参数,并理解它们之间的依赖关系;通过一个 Harry Potter 问答应用的具体示例来走完整个过程;并考察 LLM temperature 及其对响应行为的影响。我们还会讨论常见的智能体式组件角色,以及最适合它们的 temperature 设置,同时介绍一些实用工具、快捷方法和最佳实践,帮助你按照三个阶段组织 GenAI 项目:项目启动、中间目标,以及冲过终点线。

优化 GenAI 变量需要良好的策略,也需要深入理解参数之间的关系。如果没有好的策略,你的 GenAI 应用可能需要很长时间才能完成。当 15 个相互依赖的变量同时发挥作用时,可能的组合数量会达到数十亿。不过不用担心:读完本章之后,你将深入理解 GenAI 变量之间的依赖关系,并学习如何对参数进行分组,使构建 GenAI 应用的过程变得更加线性、更加可管理。

本章将涵盖以下主题:

  • 调优 GenAI 系统:原则与实践
  • 调优你的 GenAI 项目参数
  • 配置一个能够回答任何 Harry Potter 书籍相关问题的 GenAI 应用
  • 构建 GenAI 项目的最佳实践

调优 GenAI 系统:原则与实践

本章将帮助你开始调优 GenAI 项目的参数,这是构建 GenAI 应用时所需的一项核心技能。需要调优的参数存在于 GenAI 应用的多个组件中,包括 LLM、文档切分器和向量数据库。本章所考虑的参数列表和 chunking 策略并不是穷尽的。阅读本章时请记住:比起记住参数名称或具体策略,更重要的是学习如何思考参数调优,以及应该遵循什么流程。

在深入参数调优策略之前,最好先回顾以下简单但符合常识的最佳实践:

严格控制你的环境: 在优化某个参数时,要确保没有其他人同时修改系统。

记录所有测试日志,最好纳入版本控制: 你可能以后需要回头查看已经尝试过什么,以及结果如何。

尽可能并行化: 并没有要求必须按顺序测试参数。如果你能够启动多个环境,就可以大幅提升测试不同参数组合的速度。

记录系统目标,帮助你之后在不同参数设置提供的选项之间做出选择: 识别目标可能包括构建客户画像、运行焦点小组,等等。

要把这些高层目标转化为可靠输出,需要采用更细粒度的方法来塑造模型环境,而这要从核心参数开始;接下来我们就会讨论这一点。

调优你的 GenAI 项目参数

如前所述,可调参数可以出现在向量数据库、文档切分器和 LLM 中。它们能让你控制从本地存储中返回的文档大小,调整 LLM 响应中允许的创造性程度,并决定文档如何被分组和搜索。最终目标是让 LLM 对你的 prompt 生成尽可能好的回答。

下面的列表包含你需要调优的标准参数。掌握如何调优这些参数,应当足以应对大多数项目。学会调优它们之后,你就已经准备好启动任何 GenAI 项目。

主要参数列表:

  • Chunking strategy
  • Document structures
  • Document types
  • Chunk overlap
  • Chunk size
  • Similarity function
  • Max. chunks returned
  • Vector database repository structure
  • LLM temperature
  • LLM
  • LLM version
  • Prompts
  • Max tokens
  • Context size of LLM
  • Chunk limit

下面是一张实用依赖图,也就是有向图。一个从某个参数指向另一个参数的箭头,例如 A → B,意味着如果你改变一个参数 A,那么你很可能也需要改变另一个参数 B,才能保持检索和生成在质量、成本与稳定性方面的一致性。

image.png

图 3.1——依赖关系图:箭头 A → B 表示改变 A 很可能需要改变 B

这些组件之间的关系,可以通过考察一个参数的变化如何影响系统中的其他参数来理解。

1)Document → Chunking

Document types and structures → chunking strategy: 不同格式,例如合同、发票、长篇 PDF,以及不同结构,例如表格、标题、页面、章节,会迫使我们采用不同的 chunk 边界。

Chunking strategy → chunk size、overlap 和 chunk limit: 一旦你选择了规则,例如按标题、按页面、按语义切分,就必须调优 size 和 overlap,并设置安全限制。

2)Chunking → Retrieval

Chunk size and overlap → chunk limit: 更大的 chunk 或更多 overlap,会使同一份文档产生更多 chunk。

Chunk limit → max. chunks returned: 如果你限制每份文档,或每个查询 pipeline 阶段中 chunk 的数量,那么它会约束 retrieval 能返回什么。

Vector database structure → similarity function: 仓库结构,例如单索引还是多索引、按文档类型划分的 collection、metadata filters、hybrid indexes,会影响哪一种 similarity method 更合适,以及它如何被计算或组合。

Similarity function → max. chunks returned: 改变 similarity,例如 cosine、dot-product 或 hybrid scoring,会改变 score distributions,因此最优 top-k,也就是 chunk limit,往往也会随之改变。

3)Retrieval ↔ Prompting

Max. chunks returned → prompts: prompt 需要围绕你输入多少 chunk 来组织,包括格式、引用、压缩和排序。

Prompts → max. chunks returned: 如果 prompt 需要更多证据或引用,你通常会增加 top-k;如果它需要更强的 grounding,你会减少 top-k,并提高 similarity threshold。

4)Model → Context/Tokens → Prompts

LLM → version → context size: 不同版本通常意味着不同的上下文窗口限制。

Context size → max. tokens and prompts: prompt 模板和输出限制必须适配模型的上下文窗口。

Max. tokens → prompts: 如果你降低最大输出 token 数,prompt 往往需要更强的约束、更多总结指令,或不同的回答格式。

5)Temperature 与 prompt 行为绑定

LLM temperature → prompts: 当 temperature 提高时,为了保持确定性和忠实性,prompt 的严格程度往往也需要提高;当 temperature 较低时,prompt 可以相对放松。

LLM version → temperature: 不同版本在相同 temperature 设置下可能表现不同,因此你通常需要重新调优。

图 3.2 展示了 pipeline 层级结构以及跨层耦合点。

image.png

图 3.2——Pipeline 拆解:ingestion、retrieval 和 generation 层,以及它们之间的跨层耦合点

理解如何调优参数,需要了解它们之间的相互依赖关系。在接下来的几个小节中,我们将密切关注图 3.1 中的依赖图,以及图 3.2 中的 pipeline 拆解。深入理解这些图,可以将你构建和调优 GenAI 应用所花费的时间减少几个数量级。理解这些图也有助于你在团队内划分任务,使团队成员不会相互掣肘。考察图 3.2,我们可以看到三个专业层级:ingestion、retrieval 和 generation,每个层级都需要自己独特的技能和专业知识。

到目前为止,我们的讨论都是理论性的。现在让我们看一个具体示例,看看这些依赖规则如何应用于构建 GenAI 应用。下一节中,我们将走过一个过程,为一个假设的应用寻找正确参数值,这个应用可以回答关于 Harry Potter 书籍的问题。

配置一个能够回答任何 Harry Potter 书籍相关问题的 GenAI 应用

调优 GenAI 一半是科学,一半是艺术。你第一次猜测的参数值,很可能与最优值相差很远。由于你不可能一开始就猜中正确值,调优就变成了一个不断修改和测试的迭代过程。在本节中,我们将展示一个如何走过这个过程的示例。你的 GenAI 应用的具体流程显然会因数据和应用不同而不同,中间结果也会不同。

理解如何调优 GenAI 参数的最佳方式,是看一个能够建立直觉并帮助理解调参决策标准的示例。让我们从一个简单问题开始。假设我们正在做一个项目,目标是开发一个 GenAI 应用,用来回答 Harry Potter 书籍中的问题,并且在项目开始时,我们已经拥有全部七本 Harry Potter 书籍的 PDF 版本。

对于不熟悉 Harry Potter 系列的人来说:这些书是 J.K. Rowling 创作的一组奇幻小说。它们讲述了一位年轻巫师在 Hogwarts 的成长旅程,以及他与黑魔王 Voldemort 的斗争。整个系列横跨七本书,探索了友谊、勇气,以及善与恶之间斗争等主题,并启发了八部 Harry Potter 电影。

我们将使用以下查询,作为系统可能被问到的问题示例:

QuestionGround Truth Answer
What magic is used in Harry Potter?Witchcraft and wizardry, performed through spells, charms, curses, potions, and magical objects.
Why does Harry Potter have a lightning-shaped scar?He got it as a baby when Lord Voldemort tried to kill him with the Killing Curse, which rebounded.
What is a wand used for in Harry Potter?A wand channels a wizard's or witch's magic to cast spells.
What kind of creature is Hagrid's pet, and what is its name?A giant three-headed dog named Fluffy.

表 3.1——Harry Potter 问答应用的示例查询和 ground truth 答案

对于每个问题,我们都建立一个 “ground truth” 答案,用来与 LLM 的输出进行比较。在一个拥有更多数据的项目中,我们至少会创建 120 个查询,其中包括需要不止一句话才能回答的多跳问题,也包括像 “What magic is used?” 这样拥有许多有效答案的宽泛问题。就本示例而言,四个问题已经足够。

接下来,我们列出目标和约束:

  • 对用户查询的回答应该简短且切中要点,少于五句话。
  • 对于给定问题,LLM 至少应在 97% 的情况下返回相同结果。

至于我们将使用的微架构,我们会使用图 3.3 所示的简单检索增强生成,也就是 RAG 架构。要理解本章,并不需要深入理解这个框架;下一章会深入处理 RAG 架构。现在请注意,我们只关心从向量数据库返回了哪些文本 chunk。

image.png

图 3.3——RAG 架构模型:用户问题触发语义搜索,随后检索相关 chunk 并加入 prompt,LLM 生成响应

在下一步中,我们通常会识别 LLM 和 LLM version,但由于本节是理论性的,并且本章不会使用 LLM,所以可以跳过这一步。本章讨论并不依赖具体 LLM 模型。

到这里,我们已经准备好开始调优 GenAI 应用了。我们已经定义了架构,以及一些目标和约束;我们也充分理解了数据集,也就是 Harry Potter 书籍,并且写下了一组多样化的示例问题。在真实项目中,我们很可能会定义更多目标、约束和示例查询,但就我们的目的而言,这已经足够。

在本章余下部分,我们将研究不同参数设置,并看看这些设置如何影响我们假设中的 GenAI 应用性能。请注意,虽然确实存在糟糕选择,包括会导致系统完全失败的选择,但很少存在唯一正确的选择。

让我们从 chunking strategy 开始研究参数调优。在这个过程中,我们也会看到如何使用 chunk overlap 和 chunk size 来调优结果。

Chunking strategies

Chunking strategy 是我们需要从图 3.1 依赖树右侧分支中的参数里做出的第一个选择;它并不是在开发之前就固定下来的。此时,我们已经知道 chunking strategy 上方节点的值,也就是 document type 是 PDF,document structure 是 chapters。

Chunking strategy 决定我们如何将一份大型文档划分为较小的 chunk。在本节中,我们将考察 PDF 文档的切分。还有许多其他文档类型,例如 DOCX、XLSX、JSON、原始文本,甚至图像。虽然其他文档类型的 API 可能会有小差异,但用于决定最优调优方式的思考过程,可以很容易地适配到所有文档类型。

由于 Harry Potter 书籍以 PDF 形式提供,我们可以考虑以下任何一种 chunking strategy:

  1. 将整本 PDF 书作为一个 chunk
  2. 按章节切分
  3. 按子章节切分
  4. 切分为少于 100 token 的片段
  5. 使用少于 100 token 的 chunk,并进行智能断行

让我们看看每一种 chunking 选择的影响。请注意,并不存在唯一正确的选择。这些示例的设计目的,是帮助我们理解 chunking strategy 决策背后的权衡。

如果我们选择策略 1,也就是把整本 PDF 作为一个 chunk,那么查询 “What kind of creature is Hagrid's pet, and what is its name?” 将会在《Harry Potter and the Sorcerer's Stone》中的两个地方找到相关文本:

  • 第 9 章:The Midnight Duel——Fluffy the three-headed dog
  • 第 14 章:Norbert the Norwegian Ridgeback——Hagrid's baby dragon

《Harry Potter and the Sorcerer's Stone》是一本超过 250 页的大书。选择策略 1 意味着为了回答这个查询,整本书都需要被加载。由于这本书很长,请求可能会因为内存耗尽,或者超过 LLM 或 embedding model 的 token limit 而失败。即使请求没有导致内存错误,仍然可能由于 LLM 必须处理整本书而产生 latency 问题。此外,如果我们正在跟踪用户的 conversation history,那么随着每次新请求都包含历史记录,每个新请求都会变得极其庞大。除此之外,由于调用 LLM API 的成本是 token 数量的函数,这种策略也可能非常昂贵。虽然策略 1 可能适用于 JSON 响应这样的小型文档,但它看起来并不是搜索 Harry Potter 书籍的好方案。让我们继续看下一个策略。

如果我们选择策略 2,也就是按章节切分,那么查询 “What magic is used by Harry Potter?” 会在全部七本书的许多章节中找到语义匹配,导致策略 2 需要大量内存,并遭遇我们在策略 1 中提到的所有缺点。这个策略还有另一个值得理解的缺点:一本书的章节可能覆盖很多主题,其中有些与请求相关,有些不相关;而且可能只有章节中的一个小句子真正涉及 magic。由于每一章都很大,我们需要限制返回的 chunk 数量,这意味着某些相关数据可能位于我们没有返回的 chunk 中,因为我们没有空间返回它们。策略 2 可能适合一组较小且彼此无关的文档,例如产品库存,但不适合我们的 Harry Potter 大规模书籍集合。我们可以把策略 2 从列表中划掉。

策略 3 看起来很有前景。按子章节切分可能会降低 chunk size,并减少 chunk 之间的依赖。不幸的是,Harry Potter 书籍没有子章节,因此这个选项不可用。

使用策略 4 时,我们将每个 chunk 限制为 100 token。100 token 本身没有什么特殊之处;它只是本示例中任意选择的一个数字。使用这种策略时,LLM 处理的数据会获得更高精度,并且返回 chunk 的大小也会降低。因此,策略 4 应该能够解决我们在策略 1 和策略 2 中遇到的问题。然而,如果查询非常具体,例如 “What kind of creature is Hagrid's pet, and what is its name?”,语义匹配可能只局限于某本书中的一个位置。由于相关数据仅限于一个位置,我们大概率希望从这个位置获得尽可能多的相关上下文:匹配文本前后的几句话。将 chunk size 限制为只有 100 token,可能会让我们跳过附近那些同样有用的 chunk。这种策略的另一个问题是,chunk 可能会在句子中间被截断。例如,我们最终可能得到一个 chunk,内容是 “Hagrid's pet is a kind of …”,而句子的后半部分却在下一个 chunk 中。

虽然策略 4 比前面几个选项更好,但仍有改进空间,以应对 chunk 在句中断裂或丢失重要上下文的风险。

基于上述讨论,对于查询 Harry Potter 书籍,我们可能想选择策略 5,并将 chunk size 提高到每个 chunk 600 token。这样可以让我们检索到匹配文本前后更多句子。策略 5 使用智能切分方法,不会在句子中间切断 chunk,导致半句话留在一个 chunk 中,另一半留在下一个 chunk 中。

我们可能还想限制返回的 chunk 数量,以免面对一个在集合中许多位置都有匹配的查询时,被数百个 chunk 淹没。比如,我们选择 5 个 chunk 作为初始限制,同时知道,如果之后发现自己错过了位于第五个 chunk 之后的重要数据,就可以重新调整这个限制。Chunk 会按相关性排序。

思考完这些策略之后,我们得出结论:策略 5 是最适合 Harry Potter 书籍集合的 chunking strategy。

你可以把 chunking strategy 理解成在选择是用小手网捕鱼,还是用拖网捕鱼。使用小网时,你更可能精确捕到想要的鱼,同时花更少力气把不想要的鱼放回去。使用大网时,你可以一次捕获很多鱼,包括那些不想要的鱼,这就需要更多处理时间来整理捕获物。与使用小网的渔夫不同,拖网船不能在许多地方撒网,因此它的捕获结果很可能只反映它选择拖网的那一个位置。

image.png

图 3.4——按大小切分:小网,也就是小 chunk,提供精度和灵活性;拖网,也就是大 chunk,提供广度,但代价是需要更多整理工作

在设置好 chunk size、top-k,也就是 chunk limit、chunking strategy 以及 chunking overlap,也就是第 2 章中讨论过的内容之后,让我们进入另一个参数:temperature。

Temperature

Temperature 是衡量 LLM 响应相对于用户预期而言有多可预测的一个指标。但我们并不总是希望 LLM 返回几乎相同的响应。例如,如果我们想为一封重要邮件的开头生成几个选项,那么我们会看重拥有多样化选择。为了同时处理这两类情况,LLM 允许你设置所谓的 temperature。它是一个数字,用来决定当 LLM 使用同一个 prompt 被多次调用时,响应有多独特。更高的 temperature 会产生更多变化的响应;更低的 temperature 会产生更一致的响应。

例如,如果 prompt 是 “What is a wand used for in Harry Potter?”,LLM 可能会基于向量数据库中的数据找到两个可行答案:

  • Casting spells
  • Focusing magical energy

如果我们把 temperature 设置得很低,接近 0,那么可以预期几乎每次都会返回同一个答案。例如,如果一个 LLM 被调用 100 次,其中 99 次可能都会返回 “Casting spells”。另一方面,如果我们把 temperature 设置到接近或高于 1,那么可以预期会以相近频率返回更多变化的答案。例如,LLM 可能返回 “Focusing magical energy” 的次数大致与 “Casting spells” 一样多。

低 temperature 会让你的应用返回可预测的答案。这对某些用例来说是理想的。问题 “What kind of creature is Hagrid's pet, and what is its name?” 确实要求每次都返回相同答案。对于其他允许更多解释的问题,例如 “What magic is used by Harry Potter?”,有许多好的答案,你不一定需要,也不一定想要每次得到完全相同的响应。这个选择很微妙,在决定选择什么 temperature 时,你应该仔细思考自己的用例,并研究你的 LLM 还支持哪些其他参数。

image.png

图 3.5——Temperature:低 temperature,也就是小丑鱼,会产生可预测、相似的响应;高 temperature,也就是多样化海洋生物,会产生变化丰富、有创造性的响应

图 3.5 展示了低 temperature 与高 temperature 之间的区别。高 temperature 提供更多多样性;低 temperature 提供更多可预测性。

让我们通过考察几个常见组件角色,看看在哪些情况下你可能希望设置高 temperature,哪些情况下希望设置低 temperature。

GenAI 微架构包含一个或多个组件,这些组件通常高度专门化,用于执行某个特定任务。你希望给 LLM 多大灵活度,让它返回并非最可能的响应,这通常取决于组件角色。让我们考虑一些我们可能会在组件中看到的常见角色:

Judge: Judge 会评估来自多个数据源的响应,并判断哪个响应更好,或哪条陈述为真。由于在做这类判断时,创造性很少有用,因此更偏好较低的 temperature 值。

Router: Router 会把请求导向一个专门的 LLM 组件进行处理,并使用从向量数据库中检索到的文本来做路由决策。较高的 temperature 设置,以及 chunking strategy,可能会导致同一个 prompt 产生不同响应,从而被路由到不同组件,并产生非常不同的结果。因此,低 temperature 设置是 Router 的最佳选择。

Actor: Actor 执行操作并与外部世界交互。这个动作可能很简单,例如调用 API 或查询向量数据库。Actor 通常需要将原始数据转换为人类可读格式。Actor 通常是确定性的,并且最适合低 temperature 设置。

Guard: Guard 通过检测并拒绝幻觉、冒犯性语言和不适当内容,来确保用户安全。Guard 应该使用低 temperature 设置,因为它们不应该具有创造性。

Critic: Critic 根据定义好的标准评估响应或输出的质量,例如准确性、相关性或完整性。由于这个角色需要谨慎且一致的判断,因此通常适合较低的 temperature 设置。

Editor: 如果 prompt 被用来缩短、拉长或为文本响应添加风格,那么使用高 temperature 会产生更多样化、也可能更有创造性的输出。根据需求不同,更高的创造性可能非常适合 Editor。

image.png

图 3.6——智能体式角色:每种角色都有其典型的 temperature 偏好

希望读完本节之后,你已经对构建 GenAI 项目所需内容形成了良好直觉。接下来,让我们看看如何有效组织和执行 GenAI 项目。

构建 GenAI 项目的最佳实践

良好流程的目标,应当是尽量减少团队内部依赖,并提高成员生产力。本节将从高层概述在设置 GenAI 项目流程时应该遵循的最佳实践。

一个 GenAI 项目可以分为三个不同阶段:理解产品并收集测试数据、成功调优参数,以及在发布前为项目做最后润色。

项目启动

在项目启动阶段,我们收集外部信息,这些信息将作为决定参数设置的输入:

  • 基于对产品用户的深入理解,创建一组测试 prompt。
  • 识别微架构。
  • 识别 collection 中将使用的文档。在大型组织中,文档可能分布在多个存储位置,包括邮件服务器、文档管理系统和本地硬盘。
  • 识别将被摄取到向量数据库中的文档类型,例如电子表格、PDF 等。
  • 通过检查随机抽样的文档,识别 chunking strategy。在某些情况下,文档数量会达到数千份,并需要更复杂的 chunking strategy,考虑按类型、来源、大小、内容和主题将文档分组成 collection。
  • 识别并记录 UX 因素,例如可接受的响应时间、复杂性要求和服务等级协议。
  • 基于类型、来源位置、主题、年龄等因素,开发一套文档分类系统。如有需要,可以使用自动化 AI 分类模型。
  • 创建一个样本文档仓库,其中包含能够代表应用中所用文档的样本文档。包含描述文档、来源、创建日期和作者的 metadata。
  • 为样本 prompt 识别正确的 temperature 设置。

中间目标

一旦你已经梳理好流程,就需要把文档从其当前所在位置迁移出来。通常这些位置可能是数据库、文档管理系统或文件服务器,然后将文档放入向量数据库:

  • 构建一个 ETL,也就是 Extract、Transform、Load pipeline,用于从源系统加载文档、切分文档,并将 chunk 摄取到向量数据库中。将文档摄取进向量数据库,是构建 GenAI 应用时的一个关键步骤。我们将在第 5 章和第 6 章中构建一个高级 ETL pipeline。

image.png 图 3.7——数据 pipeline:ETL 流程从多个来源抽取文档,通过 chunking 和 embedding 对其进行转换,并将其加载到向量数据库中

  • 使用 pipeline 将文档摄取到向量数据库中,并运行样本 prompt。
  • 迭代式地摄取文档、使用查询调用向量数据库,并评估结果。每一次迭代后都测试 chunking strategy。

冲过终点线

在发布应用以进行测试和部署之前,分析以下内容:

  • 基于微架构设计,验证 prompt 是否返回期望响应。如有需要,可以使用 LLM 生成测试输入。
  • 如果你有多个组件,要独立测试每个组件。如果有帮助,也可以使用 LLM 来分析响应。
  • 问问自己:文档分类是否按预期工作?文档分组之间是否有足够的独立性,以至于值得让每个分组在向量数据库中拥有自己的 collection?

image.png

图 3.8——冲过终点线:GenAI 项目发布前的最后阶段

总结

构建 GenAI 应用,需要为一组相互依赖的参数组合找到正确值。充分理解参数之间的依赖关系,并结合良好的流程实践,可以将构建 GenAI 应用所需的时间和精力减少几个数量级。在本章中,我们花了大量时间考察图 3.1 中的参数依赖图,并学习如何在调优参数时避免陷入无限循环。我们通过一次思维演练,为构建一个能够回答 Harry Potter 书籍相关问题的应用做准备。我们还深入考察了 LLM temperature,探索了智能体式组件角色及其偏好的 temperature 设置,并以对 GenAI 项目流程的高层审视作为结尾,包括如何设定中间目标、收集样本数据和用户输入,以及测试 GenAI 应用。

下一章中,我们将动手构建一个使用 RAG 微架构的真实应用。RAG 是 GenAI 应用的一个基础构建块。你将看到本章讨论的参数如何在一个可运行系统中落地实践。