假设你问个人资料助手:
帮我查一下保存的读书会通知,报名截止日期是哪天?如果有调整,以调整后的通知为准。
助手有两个工具:“搜索通知”用于查找资料,“读取通知”用于取得某份资料的全文。模型根据问题提出工具请求,程序检查后执行,再把结果交给模型。
如果只有两份短通知,搜索时直接返回全文,就可能足够回答。现在换成资料较多、文件较长的情况:搜索先返回编号、标题和简短摘要,需要了解细节时,再按编号读取正文。
这样,第一次搜索完成以后,任务还没有结束。模型需要先看到找到了哪些通知,再决定读哪一份;读完之后,还要判断能否回答,或者是否需要继续查。
要让助手接着做,程序需要把每次执行的真实结果送回下一次判断。 “判断—行动—观察”的循环,就从这条反馈关系开始。
1. 下一步需要什么,可能要做完这一步才知道
先约定本次任务的范围:只根据当前用户获准访问的已保存通知回答,不查询报名系统的实时状态。两项工具也只读资料,不修改通知。
下面是一条用于解释流程的假设路径。本次搜索在约定范围内已查完,共找到 D1、D2 两份通知,属于同一主办方、同一场读书会;表中动作是设计示例。
| 用户要核对报名截止日期,尚未取得通知 | 搜索“读书会 报名” | 找到 D1《读书会报名通知》和 D2《读书会报名时间调整通知》,附编号、发布日期和摘要 |
| 搜索结果中有一份调整通知,但还没读到完整修改内容 | 读取 D2 | 正文写明:“本次读书会报名截止日期提前到2026年9月18日,原通知中的截止日期作废。” |
| 已取得 D2 的完整修改说明,且确认对应用户问的活动 | 给出有依据的回答 | 不再执行工具,向用户呈现答案 |
这时可以回答:
按查到的 D2《读书会报名时间调整通知》,报名截止日期已提前到 2026 年 9 月 18 日,原通知中的日期作废。
第一轮结束时,新增的是“找到了哪些资料”;第二轮结束时,新增的是“调整通知具体改了什么”。这些变化分别解决不同缺口,才使任务能够走到回答。
模型可以在最初就提出“先搜索,再读调整通知”的计划,但 D2 的编号和具体内容仍要等执行后才能取得。计划描述的是准备做什么,下一步操作所用的资料标识和回答依据,则应来自实际返回。
2. 程序怎样把一次调用接成循环
为便于看清回路,这里每轮只处理一个工具请求。程序每次将当前问题、工具说明和已有结果交给模型,接收一个下一步动作;执行并取得反馈后,再发起下一次模型请求。
#mermaid-svg-1Kkc6MnYy4YAcHPD{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1Kkc6MnYy4YAcHPD .error-icon{fill:#552222;}#mermaid-svg-1Kkc6MnYy4YAcHPD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1Kkc6MnYy4YAcHPD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .marker.cross{stroke:#333333;}#mermaid-svg-1Kkc6MnYy4YAcHPD svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1Kkc6MnYy4YAcHPD p{margin:0;}#mermaid-svg-1Kkc6MnYy4YAcHPD .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster-label text{fill:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster-label span{color:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster-label span p{background-color:transparent;}#mermaid-svg-1Kkc6MnYy4YAcHPD .label text,#mermaid-svg-1Kkc6MnYy4YAcHPD span{fill:#333;color:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .node rect,#mermaid-svg-1Kkc6MnYy4YAcHPD .node circle,#mermaid-svg-1Kkc6MnYy4YAcHPD .node ellipse,#mermaid-svg-1Kkc6MnYy4YAcHPD .node polygon,#mermaid-svg-1Kkc6MnYy4YAcHPD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .rough-node .label text,#mermaid-svg-1Kkc6MnYy4YAcHPD .node .label text,#mermaid-svg-1Kkc6MnYy4YAcHPD .image-shape .label,#mermaid-svg-1Kkc6MnYy4YAcHPD .icon-shape .label{text-anchor:middle;}#mermaid-svg-1Kkc6MnYy4YAcHPD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .rough-node .label,#mermaid-svg-1Kkc6MnYy4YAcHPD .node .label,#mermaid-svg-1Kkc6MnYy4YAcHPD .image-shape .label,#mermaid-svg-1Kkc6MnYy4YAcHPD .icon-shape .label{text-align:center;}#mermaid-svg-1Kkc6MnYy4YAcHPD .node.clickable{cursor:pointer;}#mermaid-svg-1Kkc6MnYy4YAcHPD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .arrowheadPath{fill:#333333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1Kkc6MnYy4YAcHPD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1Kkc6MnYy4YAcHPD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1Kkc6MnYy4YAcHPD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster text{fill:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD .cluster span{color:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1Kkc6MnYy4YAcHPD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1Kkc6MnYy4YAcHPD rect.text{fill:none;stroke-width:0;}#mermaid-svg-1Kkc6MnYy4YAcHPD .icon-shape,#mermaid-svg-1Kkc6MnYy4YAcHPD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1Kkc6MnYy4YAcHPD .icon-shape p,#mermaid-svg-1Kkc6MnYy4YAcHPD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1Kkc6MnYy4YAcHPD .icon-shape .label rect,#mermaid-svg-1Kkc6MnYy4YAcHPD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1Kkc6MnYy4YAcHPD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1Kkc6MnYy4YAcHPD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1Kkc6MnYy4YAcHPD :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
可以
达到上限
请求工具
回答、补问或说明限制
用户问题与已有记录
程序检查是否仍允许继续
模型根据当前信息选择下一步
结束本次处理并说明进度与限制
程序校验请求并执行允许的操作
取得实际结果或明确的拒绝与失败信息
保存调用与对应结果,加入后续输入
向用户回复,结束本次处理
沿着这张图看,三个动作各有具体含义:
- 判断:模型根据用户目标和当前依据,提出下一步需要做什么。例如读 D2,或者说明现有信息不足。
- 行动:程序检查工具名称、参数和权限,执行允许的操作。模型提出“读取 D2”以后,仍要由程序真正读取。
- 观察:程序把执行得到的内容带回,模型在后续请求中据此重新判断。这里的“观察”包括成功取得的正文,也包括未找到、拒绝访问或读取失败。
关键连接点是图中的回路:工具结果进入后续输入,下一次判断才能利用它。给同一个模型连续发三次请求,如果每次都只有原问题,新的查询结果没有带入,就没有建立这条反馈关系。
程序还要提供明确出口。这个小助手可以先设置模型请求次数上限,并为模型调用和工具执行设定超时,防止重复查询或等待一直持续;达到上限时,报告已完成什么、还缺什么。模型选择回复用户,也只表示本次处理告一段落:补问意味着还在等信息,给出答案则仍需要核对是否有依据。
3. 下一轮必须知道“为什么查”和“查到了什么”
假设读取 D2 成功,程序下一次只把通知正文发给模型。模型虽然看到了日期,却可能缺少原问题,不知道用户问的是报名截止日、通知发布日期,还是当前能否报名。
相反,如果程序只保留原问题,没有加入 D2 的结果,下一轮又缺少刚刚取得的依据。
所以,最小循环需要持续保留一份与当前任务有关的记录。对于前面的路径,这份记录可以按发生顺序组织为:
用户问题:核对保存的读书会通知中的报名截止日期,有调整则采用调整后的通知。
第 1 次工具请求:搜索“读书会 报名”。
对应结果:找到 D1、D2,附各自的标题、发布日期和摘要。
第 2 次工具请求:读取 D2。
对应结果:D2 的完整正文,说明截止日期提前到 2026 年 9 月 18 日,原日期作废。
这是记录内容的示意,不是某个接口要求的消息格式。实际使用时,应按接口约定保存模型返回的调用项,并把工具结果对应到原来的调用。这样才能辨认某份结果属于哪一次搜索或读取。
组织输入时,先保留稳定的任务规则和工具说明,再放本次用户问题,已经发生的调用与结果随进展追加。模型下一次能使用哪些信息,取决于程序实际传入了什么,或接口按约定续接了什么。程序在本地执行过一个函数,并不会自动让下一次模型请求知道结果。
失败也需要进入这份记录。例如,D2 读取超时,程序应带回“读取 D2 超时,未取得正文”。模型此时只能知道有一份调整通知,不能据标题猜出调整后的日期。如果允许再次尝试,可以提出重读;如果无法继续,就应说明仍未核实修改内容。
从这条失败分支可以看出,循环并不是每轮都离成功更近。它让后续判断得到最新情况,也可能让系统及时发现当前任务无法继续。
4. ReAct 怎样把判断、行动和反馈连起来
ReAct 研究项目将推理与行动交替组织:模型结合当前情况生成推理文字和下一步动作,外部环境执行动作并返回观察结果,再供后续判断使用。
作者公开的问答实现中,这个过程有明确的程序对应关系。其 HotpotQA 示例代码每轮先让模型生成推理文字和动作,并在准备生成观察结果的位置停止;随后由程序执行动作,取得环境返回,再把这一步的动作与真实观察追加到后续输入。
这解释了为什么工具反馈必须经过程序:搜索返回了什么,由搜索执行结果决定。模型生成的文字不能直接充当“这次已经查到的内容”。
作者编写的提示示例展示了一次调整动作的过程:搜索 High Plains 后,反馈指出这个名称可能指向不同地区,于是下一步改为更明确的 High Plains (United States)。新的搜索条件来自刚得到的歧义信息。这是用于向模型示范的轨迹,说明了反馈怎样影响动作选择;它本身不代表任意模型都能稳定完成同样的判断。
原始 ReAct 方案显式使用了推理文字。理解更一般的工具循环时,还可以直接观察模型提出了什么请求、程序执行了什么、返回了什么,以及下一步如何变化。这样的调用记录足以检查反馈有没有传回、动作是否有依据;不需要把可见的解释文字当作模型全部内部推理的记录。
5. 什么情况下值得让模型每轮重新判断
回看“搜索通知—读取 D2—回答”这条顺利路径,普通程序也可以安排相同的步骤。资料关系和处理规则足够稳定时,固定流程容易检查,也能减少中间的模型请求。
让模型每轮选择动作,更适合下一步取决于当时取得的内容,而且这些分支难以提前列全的任务。例如,通知正文引用了另一份补充说明,需要继续核对;搜索结果出现同名活动,需要判断是否先补问;读取失败后,需要结合已有依据决定能回答到哪里。
这种灵活性也有成本:每增加一次判断,通常会增加一次模型请求的等待和费用,传入的任务记录也会占用更多词元(Token)。模型还可能选择无关资料,或者反复执行没有进展的搜索。因此,应让每次新动作对应一个具体缺口,并由程序控制允许继续的范围。
可以用三个变化检验自己是否理解了循环:
- 搜索已经返回两份通知的完整正文,修改关系也很明确,还要再读取 D2 吗? 如果没有新的核对需求,就不必增加这一步。动作是否需要,取决于还缺什么依据。
- 读取 D2 失败,下一轮却仍然收到一份“读取成功”的旧结果,会怎样? 模型可能沿旧情况继续回答。需要核对结果与调用的对应关系,并准确带回本次失败,循环才能反映当前进展。
- 连续两次用同样条件搜索,都得到相同的空结果,还能因为“需要继续判断”而一直查吗? 如果没有新的信息、条件或暂时故障可供处理,重复执行缺少继续的理由;程序应限制次数,并让助手说明当前范围内未找到。
一个有用的循环,让每次行动取得的事实改变后续判断:有了充分依据就回答,出现新缺口就选择相应动作,条件不允许时就停止并说明。判断、执行和反馈之间的连接是否真实、完整,决定了多次调用能否共同推进同一个任务。
假设你问个人资料助手:
帮我查一下保存的读书会通知,报名截止日期是哪天?如果有调整,以调整后的通知为准。
助手可以搜索通知、读取正文。每次工具执行后,程序把结果交给模型,让模型决定继续查,还是给出回答。
找到第一份写着截止日期的通知,就能停了吗?如果搜索结果里还有一份“报名时间调整通知”,现在回答就可能漏掉修改。反过来,调整内容和适用对象已经核对清楚,再把相同资料读一遍,也没有增加回答所需的依据。
因此,停止条件要同时回答两个问题:什么情况下已经可以交付,什么情况下即使没完成也应该结束本次执行? 用户需要知道自己拿到了答案,还是只拿到了当前进展。
1. 是否完成,要看用户要的结果有没有依据
先明确这次任务的范围:根据当前用户获准访问的已保存通知核对日期,不查询报名系统的实时状态。
假设搜索已经覆盖约定的资料范围,共找到同一场读书会的两份通知。D1 是原通知,写着 9 月 20 日截止;D2 是调整通知,完整正文写着:
本次读书会报名截止日期提前到2026年9月18日,原通知中的截止日期作废。
对于这个问题,完成需要有几项相互关联的依据:通知对应用户问的活动;D2 明确修改了原日期;答案采用修改后的日期,并能指出出处。约定范围内如果还有未读的相关更新或没有解决的冲突,就还缺少核对。
这些条件满足以后,可以交付:
按保存的 D2《读书会报名时间调整通知》,报名截止日期已提前到 2026 年 9 月 18 日,原通知中的日期作废。
这里的“完成”有明确边界。回答保存通知中的截止日期,不要求顺便证明报名系统现在仍然开放;用户没有提出这个问题,也没有提供相应的查询条件。把任务扩展为“直到确定一切相关信息才停”,会让完成标准不断后移。
程序可以直接检查一些条件,例如引用的通知是否实际读取过、出处编号是否存在、回答中是否包含日期。通知是不是同一场活动、修改是否适用,则需要理解内容。模型可以参与判断,开发者仍需用包含同名活动、日期冲突等情况的样本检查它的可靠性。仅仅返回了一个“已完成”标记,不能替代这些依据。
2. 下一步补不上缺口时,要结束当前的自动执行
未完成,不一定意味着应该继续调用工具。先看缺少的信息从哪里才能得到。
假设搜索找到了两个主办方的读书会,用户只说了“读书会”,现有资料也无法确定他指哪一场。读取更多通知可能会让助手更了解这两场活动,却未必能知道用户想问哪一场。此时适合补问:
找到了青禾书店和市图书馆的两场读书会,你想查哪一场?
这次自动执行到这里就可以结束,等用户回复后再继续处理。系统应记录“等待用户确定活动”,不能记录为“截止日期已核实”。如果问题和已有对话已经能明确活动,就没有必要再问一遍。
另外一些缺口来自当前能力的限制:
- 资料没有访问权限。 应说明当前无法读取,等待授权条件发生变化。重复请求同一份资料不会补上权限。
- 在约定范围和搜索条件下没有找到通知。 如果还有合理的关键词或已获准访问的来源,可以继续查;这些办法已经用尽时,应说明查找范围和结果。
- 资料服务暂时失败。 在允许的次数和时间内,可以尝试恢复;达到限制以后,应带着失败原因结束。
判断是否值得继续,可以落到一个具体问题:下一次动作准备补哪个缺口,为什么有机会取得新信息?
相同关键词、相同范围连续返回相同的空结果,而条件没有变化,就缺少再次搜索的理由。但动作重复本身不能直接证明没有进展:读取下一页是在获取新内容,暂时故障后的重试也可能有意义。需要一起看执行条件和实际返回,不能只数工具名称出现了几次。
3. 次数、时间和费用上限,各自限制一种消耗
即使下一步看起来有理由,程序也不能无限执行。模型可能一直认为“再查一次就够了”,单次请求也可能迟迟没有返回。因此,需要由程序设置执行上限。
下面是一组用于说明区别的假设配置,具体数值要根据任务调整:
| 执行次数 | 模型请求最多 6 次,工具调用最多 4 次 | 防止反复判断、反复查询;两种调用分别计数,避免漏算 |
| 等待时间 | 整个任务最多 45 秒,单次调用最多 15 秒 | 次数很少也可能等待很久;每次都没超时,也可能累计超过用户能接受的时间 |
| 费用 | 为一次任务设置费用预算 | 同样的调用次数,输入长度、输出长度及付费工具不同,花费也可能不同 |
次数:限制的是实际执行,计数范围要说清
“最多执行 6 轮”还不够明确。一轮如果包含一次模型请求和两个工具调用,就已经发生了三次不同的操作。格式纠正、故障重试、最后一次整理回答,也可能增加模型请求。
这个小助手可以分别统计模型请求和工具调用,并把失败尝试、重试都算进对应上限。是否还允许发起下一次操作,应在执行前检查,不能执行完才发现已经超过次数。
时间:单次超时要服从整个任务的剩余时间
假设任务已经用掉 42 秒,总上限是 45 秒。即使单次调用允许 15 秒,接下来也只剩 3 秒可用,不能重新给它一份完整的 15 秒。
总时间应从本次处理开始累计,包括模型等待、工具执行和重试间隔。只在每轮结束后查看时间,无法约束一项一直没有返回的请求;调用本身也需要相应的超时或取消机制。
停止等待与远端停止执行还可能是两件事。是否能取消已经发出的请求,要看服务支持什么,不能据本地超时就认定远端没有产生费用。
费用:下一次操作要在发起前纳入预算
如果任务只剩 0.20 元预算,而下一次操作可能花费 0.30 元,等它完成后再统计,已经无法守住预算。
因此,需要结合输入规模、最大输出长度和服务的计费规则,为下一次调用预留费用;付费工具也应计入。词元(Token)用量可以帮助估算模型费用,但词元(Token)数量本身不等于金额,不同计费项目的价格可能不同。
调用完成后,再按服务返回的实际用量及计费规则更新记录。超时或失败时如果没有用量信息,应保留“费用待核实”,不能直接按零费用处理。如果服务无法提供可靠的费用上界,这套控制只能视为估算和预警,不能承诺精确封顶。
次数、时间和费用控制的是不同事情,不能相互替代。具体保留哪些限制,取决于任务会消耗什么;一旦配置了这些限制,开始下一次操作就必须同时满足它们。
4. 公开实现怎样区分“结束”与“答对”
ReAct 的公开问答示例提供了一个具体对照。它让模型搜索、查找资料,也允许模型提交 Finish[answer],表示给出答案并结束。
这段实现同时保留了由程序控制的出口:主循环最多执行 7 步;如果循环结束时仍未收到结束结果,程序会执行 finish[],以空答案结束这一轮。这个限制让运行不会仅仅因为模型还想继续,就一直增加步骤。7 是该示例采用的数值,并不是所有任务的推荐值。
代码里还有一个容易忽略的细节:如果模型输出不符合预期格式,程序可能再次请求模型补出动作。因此,最多 7 个循环步骤,并不等于最多 7 次模型请求。要限制真实调用数量,就要把这样的额外请求也算进去。
“结束”也没有被当成“答对”。环境执行代码收到结束动作后记录答案并设置结束标志;问答评估代码再拿答案与参考答案比较,单独计算结果。
这个设计说明了两个独立的判断:运行是否已经结束,以及交出的答案是否满足要求。资料助手通常没有一份预先给定的标准答案,就需要回到任务约定,核对资料、修改关系和出处。循环的结束标志只负责表达执行状态。
5. 停下以后,要交代这次拿到了什么
停止规则最终需要落到程序行为上:执行前检查是否还允许发起操作;执行后保存实际结果、更新消耗,再决定交付、补问、继续或结束。模型可以建议下一步,程序负责落实已经约定的限制。
达到上限时,也要区分已有结果的状态。如果完整答案及出处已经取得并通过检查,仍然可以交付,不能因为计数恰好到顶,就把成功结果改成失败。如果还缺关键依据,就说明缺口。
例如,程序已经读到 D1 的旧日期,但 D2 的正文读取超时,且本次执行时间已用尽。合适的交付应保留这项限制:
原通知 D1 写的是 9 月 20 日截止。我还找到了 D2《读书会报名时间调整通知》,但正文读取超时,本次未能核实调整后的日期。可以稍后重新读取 D2,或由你提供这份通知的正文。
这段说明让用户知道已经查到什么、为什么还不能确定,以及什么条件变化后可以继续。旧日期没有被包装成最终结论,已经完成的查找也没有被一句“失败了”抹掉。
如果还要请求模型整理这段说明,这次请求同样占用次数、时间和费用。可以提前为收尾留出预算;预算已经耗尽时,则由程序根据保存的事实生成简短状态说明,不能为了报告停止而无条件再增加一次调用。
可以用三个变化检查停止条件是否合理:
- 用户只问“D1 原通知写的日期是什么”,完整 D1 已经读取,还必须查完所有更新吗? 不需要为这个问题扩展搜索。可以回答 D1 原文,并明确这是原通知中的日期。
- 模型已经写出“核对完成”,但记录里只有 D2 的标题,没有正文,能按成功结束吗? 不能据此认定完成。还需要核对修改内容;无法继续时,应说明依据不足。
- 最后一次允许的调用已经返回完整、可交付的答案和出处,还要因为次数用尽而报错吗? 不必。上限阻止的是新增调用,已有结果仍然可以检查和交付。
助手什么时候该停,取决于任务的完成依据、尚缺信息的来源,以及继续执行的条件。让每次结束都能说明自己属于哪种情况,用户才知道可以采用结果,还是需要补充信息、等待恢复或调整任务范围。
网硕互联帮助中心



评论前必须登录!
注册