Skip to content
This page has been auto-translated and may contain errors.View in English

微调

docs.scrimba.com

微调 是指获取一个现有模型并继续在你自己的例子上训练它,使其默认行为转向你想要的方向。本章阐述了这种改变的具体内容、它的用途,以及何时应该选择微调而不是提示词或检索。

训练实际上做了什么

要了解微调改变了什么,需要知道模型的来源。模型分两个大阶段构建。

第一个是**预训练:模型阅读大量文本,反复学习预测下一个词元,直到语法、事实和推理模式作为副作用沉淀到其中。产出是一个基础模型**,流畅但未经调整。它乐意继续你的文本,但还没有被教会成为回答问题的有用助手。

第二个阶段是后训练:基础模型在经过筛选的好回答例子上继续训练,再加上人类反馈,指出哪些答案更好。这就是把原始的文本预测器变成你真正对话的指令跟随助手的方式。你从 API 调用的模型已经经历了这两个阶段。

两个阶段都通过相同的机制工作:向模型展示例子,推动其内部数字(即参数权重),使其预测更接近那些例子。训练是预测练习,让模型永久改变。

Juno训练实际上做了什么 模型分两个阶段构建。预训练让它在大量文本上预测下一个词元,产出流畅但未经调整的基础模型。后训练则在精选的好回答和人类反馈上训练它,将其变成有用的助手。两者都通过相同方式工作:调整模型的内部权重,使其预测匹配它所展示的例子。

模型到达你这里经历两个训练阶段,了解每个阶段的形态能告诉你微调可以改变什么。

预训练 首先进行:模型读取大量文本并执行一个训练,预测下一个词元,数十亿次。语法、世界知识和推理模式作为副作用沉淀到权重中。结果是一个基础模型,擅长继续文本但还不是助手。它不知道应该回答问题而不是扩展问题。

后训练 是第二个阶段,也是微调模仿的阶段。基础模型在精选的好回答例子加上人类偏好信号上继续训练,这些信号指出哪个答案更好。这就是产生你从 API 调用的指令跟随行为的原因。

两个阶段都运行相同的循环:向模型提供例子,比较其预测与目标,并调整权重以缩小差距。微调就是这个循环,作用范围限定于你的例子,运行在提供商的两个阶段之后。训练通过编辑权重改变行为,而不是添加查找表,这个区别是微调在某些工作中好而在其他工作中差的全部原因。

Juno训练实际上做了什么 两个阶段把模型带给你:预训练把下一个词元预测训练到流畅的基础模型,然后后训练用精选的例子和偏好数据把它塑造成助手。两者都运行相同的循环,提供例子,调整权重靠向它,微调就是这个循环限定于你的数据。它编辑权重,不添加查找表,这是它改变行为好而存储事实差的原因。

模型到达后经历两个训练阶段,它们之间的边界就是微调所在的地方。

预训练 是昂贵的、每个模型一次的阶段:大量文本语料库、单一的下一个词元预测目标,权重(模型的可调数字)作为副作用吸收语法、知识和推理。输出是一个基础模型,流畅但没有被指导帮助。后训练 然后使用精选的演示和人类偏好数据把基础模型对齐到助手。当你调用 API 模型时,两者都已运行。

微调是后训练的延续,范围限定于你的数据,运行在已经对齐的模型之上。机制是相同的:呈现例子,测量预测距离目标有多远,调整权重来减少该差距。在操作上有影响的后果是微调移动保持所有其他东西的相同全局参数。你不是附加模块,而是推动共享表面,这就是为什么微调可以改进你的目标任务并悄悄降低无关能力的原因。

这个共享表面属性设置了本章后续的每个失败模式:过度拟合、遗忘、漂移。微调重塑行为,它从不安装一个事实库。记住这点,你就会因为正确的原因而选择它,并因为错误的原因而跳过它。

Juno训练实际上做了什么 预训练是一次性的重量级工作,把下一个词元预测训练到基础模型,后训练把它对齐成助手,微调在你的数据上继续第二个阶段。每次相同的循环:呈现例子,调整权重靠向它。问题是你在推动共享的全局参数,而不是接上一个模块,所以微调可以提升你的任务,同时在同一次运行中损害无关的任务,这就是过度拟合和遗忘的来源。

什么是微调

微调是那第二个阶段的一个小的、有针对性的版本,由你运行。你获取一个已经训练过的模型并继续在你自己的例子集上训练它,每个例子是一个输入配对你希望它产生的输出。足够多的例子后,模型的权重移动,使得这种响应成为它的默认值,不需要你在提示词中每次都要求。

与提示词和 RAG 的真正区别在于改变住在哪里。提示词和 RAG 让模型冻结,并通过你在调用时刻提供的上下文来引导它。微调改变模型本身,所以新行为被烤入并即使用短提示词也会显示。你不是在运行时给出更好的指令;你是在运送一个已经按你想要的方向倾斜的模型。

实际上你把一个示例对话文件交给提供商,它运行一个训练工作,然后给你返回一个新的**模型 id**。你调用这个 id 的方式正好就像任何其他模型,除了它的答案现在反映你训练的内容。微调把行为移进模型,提示词和 RAG 引导冻结的模型。

Juno什么是微调 微调是后训练的一个小版本,由你运行:继续在你自己的输入-输出例子上训练现有模型,直到你想要的行为成为默认值。不像提示词和 RAG 通过上下文引导冻结的模型,微调改变模型的权重,所以行为被烤入并即使用短提示词也会显示。你交付一个例子文件并获得一个新的模型 id,你像调用任何其他模型一样调用它。

微调是限定于一个任务的后训练,由你运行。你从一个已经训练过的模型开始,继续在例子上训练它,每个是一个输入配对你希望它产生的输出。提供足够多的例子,权重沉淀,使得响应成为默认值,提示词中没有指令要求它。

重要的界线是引导住在哪里。提示词和 RAG 让权重冻结,通过在调用时提供的上下文塑造行为,所以每个调用都携带指令。微调一次性编辑权重,预先,所以行为运输在**模型 id** 内并且能承受短提示词。运行时引导对比烤入行为:这就是你在做的权衡。

工作流是具体的。你组装一个示例对话文件,开始一个训练工作,提供商返回一个新的模型 id。你像调用任何其他模型一样调用这个 id。

python
# 每个例子是一个对话,形态正好就像你在运行时发送的,
# 以你希望模型学习的输出结尾。
training_examples = [
    {"messages": [
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "我这周被收费两次,今天必须修复。"},
        {"role": "assistant", "content": "high"},
    ]},
    {"messages": [
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "有没有深色模式设置?"},
        {"role": "assistant", "content": "low"},
    ]},
    # ... 数百到数千个更多的,覆盖你期望的输入的全部范围
]
# 消息形态和训练工作 API 因提供商而异;想法是相同的。
Juno什么是微调 微调是限定于你任务的后训练:继续在输入-输出例子上训练模型,直到你想要的行为是默认值。提示词和 RAG 通过每次调用的上下文引导冻结的模型,微调一次性编辑权重,使行为在模型 id 内。你构建一个示例对话文件,运行一个训练工作,并像调用任何其他模型一样调用返回的 id。

微调是在你控制的数据集上继续后训练,在一个新 id 后面产生一个派生模型。每个训练例子是一个输入配对一个目标输出,工作推动权重直到你的目标响应成为模型的默认值。行为运输在权重中,所以短提示词足以唤起它。

精确地把它与替代方案对比,因为区别是操作上的,而不是哲学上的。提示词和 RAG 保持权重冻结,并通过**上下文**(模型在调用时读取的文本)注入行为,这意味着你可以通过编辑一个字符串在秒内改变行为。微调把行为烤入权重,这意味着改变它需要一个新的训练运行、一个评估通过和一个新模型 id 的重新部署。运行时引导在秒内可编辑,微调仅在训练循环中可编辑。

python
# 一个微调的模型是另一个 id;调用形态不变。
response = client.chat.completions.create(
    model="your-org/urgency-classifier-v1",  # 锁定这个;把它当作你契约的一部分
    messages=[
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "导出按钮点击时什么都不做。"},
    ],
)
# response.choices[0].message.content -> "low"  (仅标签,你训练的行为)
# 显示的调用形态是 OpenAI-SDK 风格;因提供商而异。

这个成本不对称是你承诺前要内化的东西。一个微调的 id 是一个版本化的工件:你拥有它的生命周期、它的评估和每次所需行为移动时的重新训练。锁定 id,版本化它,并预算事实上每个所学内容的改变都是另一个工作,而不是另一个提交。

Juno什么是微调 微调是在你的数据上继续后训练,产出一个新 id 后面的派生模型,其行为住在权重中。与提示词和 RAG 的对比是操作上的:运行时引导是一个可编辑的字符串你在秒内重新部署,微调是一个版本化的工件你仅通过训练运行、评估通过和重新部署来改变。锁定 id,把它当作一个契约,并预算事实上每个行为改变都是另一个工作。

它擅长什么,不擅长什么

微调获得它的位置当你需要一个**一致的行为**,是提示词难以确定的:每次精确的输出格式、特定的语调或品牌风格,或像分类这样的狭窄任务在数千个调用中可靠地完成。它也可以使调用更便宜和更快,因为你会以其他方式在长提示词中拼写的行为被烤入模型,所以你的提示词变短了。

它失败的地方是知识。微调在教一个模型新事实上很差,在事实改变时更差。训练例子模糊成一般模式而不是被存储为精确的、可查找的条目,所以一个微调的模型仍然编造细节,在你的信息更新的一刻就过时。每次价格或策略改变时重新训练是慢的和昂贵的。当问题是"模型不知道 X"时,答案几乎总是 RAG,而不是微调。

经验法则:微调来改变形式,不是来添加事实。教模型如何回答,让检索处理用什么回答。

Juno它擅长什么,不擅长什么 微调擅长一致的行为:固定的输出格式、特定的语调、或狭窄任务可靠地完成,它可以缩短提示词使调用成本更低。它在知识上差:它不可靠地存储事实,在它们改变时过时,重新训练很昂贵。规则是微调来改变形式,不是来添加事实,让 RAG 处理事实。

微调为**形式** 付出代价:每个调用上精确的输出形态、固定的语调或品牌风格、或像分类这样的狭窄任务在数千个请求间保持稳定。当单独提示词保持漂移时,赢利复合,模型大多数时间尊重格式但不足以可靠地解析下游。把行为烤入,格式停止是你每个调用希望的东西。

它也缩短了提示词,在规模上这是一个真实的成本杠杆。如果你目前在每个请求中拼写格式和一些例子,那些指令词元在每个单一调用上被计费。把它们折叠到权重中,按调用的提示词缩小。算术是值得做的:微调有一个固定的训练成本支付一次,而长提示词有一个按调用的成本永远支付,所以提示词缩短在调用量足够高,保存的词元超过训练账单时付出代价。

它在知识上失败。训练例子模糊成一般模式,不是精确的可检索条目,所以一个微调的模型仍然编造细节,在价格或策略改变的一刻就过时。更新一个事实意味着另一个训练运行。微调形式,使用 RAG 来处理事实,并结合它们。强模式是同时两者:微调模型来获取你的格式和语调,然后在运行时检索当前事实并让调好的模型来措辞它们。

在你爬到微调前,确认提示词真的失败了。"失败"意味着一个清晰的指令加上几个精选的例子,跨越变化的输入测试,仍然错过目标速率,而不是你的第一个单行提示词看起来不对。如果你没有运行那个测试,你还没准备好微调。

Juno它擅长什么,不擅长什么 微调是为了形式:固定的输出形态、设定的语调、狭窄任务保持稳定,加上缩短的提示词在每个调用上节省词元。成本数学是固定的一次训练对比永远支付的提示词词元,所以提示词缩短在高量时付出代价。它在事实上差,模糊成模式并过时,所以配对一个调好的模型与 RAG:形式来自权重,事实来自检索。并在你爬上微调前证明提示词真的失败了,一个真实的提示词加上例子跨越输入测试。

微调对形式 是可靠的,对事实 是不可靠的,原因是机械的。形式、输出形态、语调、任务习惯,是权重可以跨许多例子吸收的行为规律。事实是离散的和可改变的,权重把它们存储为模糊的混合模式,而不是可检索的行,所以调好的模型仍然进行虚幻,在底层事实一移动就立刻过时。

推向那个头线,真实的风险是微调贬低的方式。过度拟合 是模型记住你的训练集,包括它的怪癖,而不是学习一般行为,所以它钉住你的例子而在输入不同时跌跤。灾难性遗忘 是另一个一面:在狭窄任务上训练很硬可以侵蚀无关一般能力基础模型有,因为你在移动共享权重,所以你的分类器变得更锋利而它在任何其他东西上的推理变得更钝。分布漂移 是慢的一个:一个在上个季度输入分布上调好的模型随着真实流量远离它看到的东西而腐烂,漂移是沉默的直到你测量它。

两个结果塑造你实际上如何运行这个。首先,你不能在直觉上运送微调;你需要一个评估集,一个输入的保留批次与已知好的答案,前后评分,来证明目标改进了,而且同等重要,一般能力没有回归。其次,每个改变所需行为都是另一个完整工作:重新精选数据、重新训练、重新评估、重新部署一个新 id。这个操作拖累是为什么参数高效方法存在,通过训练一个小集合的添加权重而不是整个模型来微调的方式,更便宜运行和存储,虽然是否微调的决定由它们未改变。无论如何,在你运送它前证明微调没有回归。

Juno它擅长什么,不擅长什么 形式吸收到权重,事实不:微调仍然进行虚幻并过时,所以把事实保留在检索。风险是过度拟合(记住你的集合,在新输入上跌跤)、灾难性遗忘(狭窄训练侵蚀无关能力因为权重是共享的)和分布漂移为实际流量移开你的训练数据。所以门控每个微调在一个保留的评估上评分前后来证明没有回归,并预算事实上每个行为改变都是一个完整的重新训练-评估-重新部署循环,这正是参数高效方法存在的原因。

提示词、RAG 还是微调?

大多数时候你不是从这里开始的。三个技术形成一个**阶梯**,最便宜和最快改变先:

  1. 提示词。 总是先尝试这个。它是即时迭代的,成本没有额外的,清晰的提示词加上一两个例子解决了比人们期望的更多。如果你还没有让提示词工作,你还没准备好微调。
  2. RAG。 当差距是知识时选择这个:模型需要它没有的事实,或随时间改变的事实。RAG 在问题时刻提供它们而不接触模型。
  3. 微调。 当差距是行为而不是知识,且提示词不能使它足够一致时,或当你的提示词已经长到把指令烤入模型是规模上更便宜和更快时,选择这个。

它们不是互斥的,最强系统结合它们:微调一个模型为你的格式和语调,然后在运行时使用 RAG 来提供它当前事实。来自训练的行为,来自检索的知识。

所以在你微调前的快速测试。你能用更好的提示词到达那里吗?然后做那个。差距是缺少知识吗?然后它是 RAG。

爬阶梯;微调是最后的梯级,不是第一个。仅当提示词已经正确、事实已经可用、模型仍然不足够一致地表现,微调才成为适合的工具。

Juno提示词、RAG 还是微调? 把三个作为阶梯:首先提示词因为它是即时和便宜的,当模型缺少知识时加 RAG,仅当差距是提示词不能使一致的行为,或为规模缩短长提示词时微调。它们结合得很好:微调成形式,使用 RAG 来获取事实。微调是最后的梯级你到达,不是第一个。

三个技术形成一个**阶梯**,按照改变有多快和多便宜排序,你从底部爬它。

  1. 提示词 首先,总是。你在秒内无额外训练成本迭代,清晰的指令加上几个例子覆盖比人们期望的更多地面。直到一个真实的提示词已被测试并失败,更高的梯级是过早的。
  2. RAG 当差距是知识,模型缺少或随时间改变的事实,检索在问题时刻提供它们而留权重单独。更新一个事实是更新你的来源,不是重新训练。
  3. 微调。 当差距是提示词不能确定的行为,或当提示词已经长到把指令烤入权重是规模上更便宜时。

把你放到正确梯级的诊断是命名差距。错的格式或语调是一个行为差距,所以提示词,然后微调。缺少或过时的事实是一个知识差距,所以检索。误读差距,你将微调来修复知识问题并看它过时,或把事实填充到一个检索步骤应该已经提取的提示词。

它们不是互斥的,结合的模式是生产中你应该到达的:微调为形式,RAG 为事实,一起。一个模型调好你的格式和语调,在运行时提供当前事实,给你一致的形态和新鲜内容一次,这两个都是另一个技术不会单独提供的。

你是否可以微调取决于模型。闭源提供商提供他们自己模型的管理微调;一个开源权重模型你可以在你自己的条款上自己微调,这是到达开源权重的一个原因(开源和闭源模型)。

Juno提示词、RAG 还是微调? 从最便宜的梯级爬阶梯:首先提示词,当差距是知识时加 RAG,仅当它是提示词不能确定的行为或为规模缩短提示词时微调。诊断是命名差距,格式或语调意味着行为,缺少或陈旧的事实意味着检索。生产动作同时两者:微调形式,RAG 为事实,所以你一次获得一致的形态和新鲜内容。

阶梯,提示词然后 RAG 然后微调,按**迭代成本** 排序:一旦运送后改变行为有多快和多便宜。提示词是一个字符串你编辑并在秒内重新部署。检索来源是数据你更新而不接触模型。微调是一个训练运行、一个评估通过和一个新模型 id。按这个顺序爬意味着你仅当更便宜的梯级可证明地不能到达时才支付更高迭代成本。

真实的技能是正确诊断差距,因为失败模式是选择不解决它的工具。一个行为差距(错的形态、错的语调、不一致的任务坚持)是提示词然后微调修复的。一个知识差距(模型缺少一个事实,或一个改变的事实)是检索修复的,微调一个知识差距是经典昂贵的错误:你训练事实,它们下一次更新时陈旧,你不能引用它们。

把操作不对称靠着诊断。RAG 的经常成本是检索质量和每个调用的延迟,永远支付但活调整。微调的经常成本是每个改变所学行为时的一个重新运行,加上每个运行携带的回归风险。

所以结合的架构不是一个妥协,它是设计:把形式调入权重,把事实保留在检索,版本每个独立地。形式很少改变,容忍缓慢的更新循环;事实频繁改变,要求快速的。分裂它们让每个以自己的速度移动,让你重新评估调好的模型而不重新索引你的语料库,或刷新语料库而不重新运行训练工作。

Juno提示词、RAG 还是微调? 阶梯按迭代成本排序:提示词在秒内编辑,来源无模型更新,微调是完整的训练-评估-重新部署。诊断差距前选择,行为去到提示词然后微调,知识去到检索,微调一个知识差距是昂贵的错误,运送陈旧的、不可引用的事实。生产架构分裂它们有目的:把形式调入权重,把事实保留在检索,版本每个独立,所以形式可以缓慢移动,事实可以快速移动。

实际上

微调数据没有什么特别的。每个例子是一个短对话,形态正好就像你在运行时发送的,以你希望模型给出的答案结尾:

python
# 这里显示几个;真实数据集是数百到数千个例子,
# 覆盖你在运行时期望的输入的全部范围。
training_examples = [
    {"messages": [
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "我这周被收费两次,今天必须修复。"},
        {"role": "assistant", "content": "high"},
    ]},
    {"messages": [
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "有没有深色模式设置?"},
        {"role": "assistant", "content": "low"},
    ]},
    # ...
]

你把这些保存到一个文件,用提供商开始训练工作,然后等待它完成。回来的是一个新的模型 id,你然后调用它正好就像任何其他模型:

python
# 微调的模型是另一个 id;其他所有东西都不变。
response = client.chat.completions.create(
    model="your-org/urgency-classifier-v1",
    messages=[
        {"role": "system", "content": "Classify the ticket's urgency as low, medium, or high."},
        {"role": "user", "content": "导出按钮点击时什么都不做。"},
    ],
)
# response.choices[0].message.content -> "low"  (仅标签,你训练的行为)

赢利是行为现在住在模型。指令可以更短,格式在数千个调用上保持,你不需要成长提示词来到达那里。成本是周围的所有东西:你需要一个质量**数据集**,一个训练运行,每次你想改变它学了什么时的一个新鲜工作,这正好是为什么这座在阶梯底部。上传例子,获得一个模型 id,像调用任何其他一样调用它。

Juno实际上 微调数据是以你想要的答案结尾的示例对话,几百到几千个。你上传文件,运行训练工作,获得一个新的模型 id 你像调用任何其他一样调用。行为然后被烤入,所以提示词变短,格式保持一致,以构建数据集和每次它需要改变时重新运行工作为成本。

工作流是上传、训练、调用,但决定它是否工作的部分是**数据集**,不是工作。质量和覆盖比原始数量更重要。数百个干净的、一致的例子跨越真实输入范围击败数千个嘈杂或矛盾的,因为模型学习无论什么规律实际上在数据中,包括错误。

分裂你的数据前你训练。保留一个切片模型在训练期间从不看到,验证集,并检查那里的准确性而不是在它已经训练过的例子上。一个模型可以在它已经看到的数据上评分接近完美,同时在任何新东西上做得很差,所以保留的数字是告诉你行为是否泛化的。

python
# 保留一个训练工作从不看到的部分,来测量真实性能。
split = int(len(training_examples) * 0.8)
train_set = training_examples[:split]        # 工作在这些上训练
validation_set = training_examples[split:]   # 你在这些上评分结果
# 提供商返回一个新的模型 id;你像调用任何其他一样调用它。
# 工作 API 和分裂处理因提供商而异;有些直接获取验证文件。

两个判断调用坐在机制之上。首先,确认提示词实际上在花费训练运行前失败了:一个真实的指令加上几个例子,跨越变化的输入测试,不是你的第一个粗糙的草稿。其次,仔细权衡成本。微调是一个固定训练成本支付一次对抗长提示词的按调用成本永远支付,所以提示词缩短仅当调用量使保存的词元值得工作时支付。并记住结合的模式:一个调好的模型为形式,RAG 为它不应该试图记住的事实。

Juno实际上 工作是上传-训练-调用,但数据集决定结果:几百个干净的、变化的例子击败数千个嘈杂的,因为模型学习无论什么实际在数据。保留验证切片并在那里评分,而不是在训练例子上,或一个记住的模型看起来比它好。首先确认提示词真的失败,权衡固定训练成本对抗永远支付的提示词词元,并配对调好的模型与 RAG,所以它处理形式而检索处理事实。

管道是上传、训练、评估、部署,工程住在数据集 和**评估集** 中,不是训练调用。两个分裂纪律承载它。一个验证集,从训练保留,告诉你行为是否泛化而不是被记住。一个分开的保留评估集,前后评分,是什么证明微调帮助了你的目标而不回归一般能力,最后一部分的灾难性遗忘检查成为具体。

python
# 三个分离的切片:在一个训练,在另一个调好决定,在第三个判断。
train_set      = examples[:8000]        # 工作在这些上训练
validation_set = examples[8000:9000]    # 在运行期间观察过度拟合
eval_set       = examples[9000:]        # 前后评分来证明没有回归

# 在同一 eval_set 上评分基础模型和微调,然后比较。
base_score = run_eval(base_model_id, eval_set)
tuned_score = run_eval(fine_tuned_id, eval_set)
# 仅当 tuned_score 击败基础在目标且在一般能力检查上保持时运送。
# 评估评分和训练 API 因提供商而异;纪律不。

数据集质量是过度拟合和漂移被赢或失的地方。狭窄或古怪的数据集训练一个记住你的集合的怪癖的模型,在不同的输入上跌跤,所以真实输入分布的覆盖比数量更要紧,你重新测量为生产流量离开你训练的东西。陈旧的评估是一个默默漂移的模型如何通过审查并使用户失败的。

设计的操作真实是每个改变所学行为都是一个完整重新运行,不是编辑。重新精选、重新训练、重新评估、重新部署一个锁定的新 id,每次。那个经常成本,加上每个运行的回归风险,是为什么你保留事实在 RAG 其中它们在线更新,保留微调为缓慢改变的行为,把每个调好的 id 当作一个版本化的工件你当新运行回归时可以回滚。

Juno实际上 管道是上传-训练-评估-部署,工作在数据分裂,不是调用:验证集捕获记住,保留评估集前后评分证明没有回归。数据集覆盖真实输入分布是如何击败过度拟合和漂移,所以当流量离开你的训练数据时重新测量。设计经常成本,每个行为改变是完整的重新训练-评估-重新部署,这是参数高效方法存在的原因,事实属于 RAG 和每个调好的 id 是版本化的工件你可以回滚。

这是最后一个塑造模型知道什么和如何回答的方式,所有这些留它在你安排的桌子上预测文本。下一章给它行动能力:在 工具使用 模型调用你自己的函数,然后在循环中运行它们作为代理。