想象你家厨房来了一位不知疲倦的机器人厨师。他煮汤时永远遵循同一套动作:舀一勺、尝一口、觉得淡了就加盐,再尝、再微调,直到味道刚刚好才关火。如果他只“炒一次菜”就停下,大概率端出一盘夹生饭;但如果没人喊停,他又可能把整罐盐都倒进去。要让他真正靠谱地“自己做完一整顿饭”,你需要设计三样东西:让他不停循环的“回路”、让他知道何时停下的“红线”、以及他手里那本记录火候与配方的“小本子”。 LLM 的自动循环系统也是如此。过去我们调用大模型就像“点一道菜”——提问、等待、得到结果。而 Loop Engineering 要构建的,是让模型自己重复“观察→决策→执行→评估”这个循环,自主完成任务并持续改进的引擎。这篇文章不堆数学推导,而是带你用“机器人厨师”的视角,把循环结构、执行引擎、终止条件、状态管理、安全防护和反思改进这六块骨架一次看清。
学会设计自动循环系统,你就掌握了让 LLM 从“回答者”升级为“自主 Agent”的核心能力——这是搭建自动化工作流与自我迭代系统的必修课,也是 AI 应用工程师进阶的关键一环。
可视化演示
交互展示LLM自动循环系统的设计架构:循环执行引擎、状态管理、安全边界和终止条件。
本节配有交互动效(进入视口后自动加载,约 3KB)。
循环执行:持续迭代引擎 LLM在循环中持续执行任务并自我改进 每次迭代包含执行、反思、优化三个阶段 Execute → Reflect → Improve 自动循环让LLM自主完成复杂任务
循环结构设计
机器人厨师做一桌宴席,绝不会把十道菜一次性全部“想好”。他的真实工作方式是:拿起一道菜放到火上,翻炒两下,夹起一块尝一口,判断火候,再决定继续炒、加料还是出锅。这个“尝一口→判断→动手→再尝”的回路,就是循环。没有这个回路,他切完菜就会发呆等指令,一顿饭永远做不完。
LLM 的自动循环系统长得一模一样。把“尝”换成“观察当前状态”,把“判断”换成“让大模型做决策”,把“动手”换成“调用工具或生成文本”。在 Loop Engineering 的框架里,一个循环单元由四个环节组成:感知(observe)、决策(decide)、执行(act)、评估(evaluate),然后回到感知,周而复始。所谓“循环结构设计”,就是把这四个环节焊成一个环,让每轮结束自动回到起点,而不是靠用户手动触发下一轮。
用公式表示一轮循环:当前状态 \(x_t\) 传入决策策略 \(\pi\)(即 LLM),LLM 依据上下文 \(ctx_t\) 产生动作 \(a_t\),执行器 \(\mathcal{E}\) 把动作落到真实环境,得到新状态 \(x_{t+1}\)。循环结构的设计重点,就是明确这条链路的每个环节由谁承担、输出什么、如何衔接。
回到厨房:如果厨师尝完一口停下发呆,等主人下令才决定下一步,那这顿饭永远做不完。循环结构解决的就是“做完一步,自动做下一步”的引擎问题——它是整台自动机器的底盘,其余一切设计都建立在它之上。
- x_t 状态第 t 轮开始时任务所处的状态,相当于厨师眼里“汤的咸淡、火候、剩余配料”。
- a_t 动作大模型决策出的本轮要执行的动作,比如“加半勺盐”或“继续翻炒三分钟”。
- ctx_t 上下文传递到本轮的背景信息,包括历史动作、观察结果与反思结论。
- π 决策策略LLM 本身,输入状态与上下文,输出动作,写作 \(a_t = \pi(x_t, ctx_t)\)。
- E 执行器把动作落到现实中的工具或环境,比如炉灶与锅铲;输出新状态。
执行引擎设计
宴席上不止一道菜。机器人厨师同时管理四个灶口、八道菜,他要决定:先热哪口锅、哪个菜需要翻面、哪个已经可以装盘。这就是“调度”。没有调度,他会对着第一道菜反复翻炒,其他菜全部烧糊。
执行引擎就是那块掌勺调度台。它由三部分组成:任务队列 \(Q\)(还有哪些子任务没做)、调度器(决定下一个执行谁)、执行器与采集器(真正调用工具并把结果写回状态)。在自主 Agent 里,任务队列里装的可能是“查文档”“写代码”“跑测试”这样的子任务。引擎必须支持工具调用:LLM 只负责“说”,执行引擎负责“做”,采集器再把工具的结果(测试通过与否、网页内容、代码 diff)变成下一轮可用的观察。
调度器给每个任务打一个加权分:紧急度 \(u_i\) 越高的越该先做,就绪度 \(p_i\)(前置依赖是否完成)越高的越具备执行条件。分数最高的任务优先执行:
回扣厨房:执行引擎就是墙上那块“今日菜品看板”——谁先做、谁后做、谁已完成,一目了然。有了它,循环才能同时管理多个子任务而不乱,这台机器才配叫“引擎”,而不只是一条单行道上的传送带。
- u_i 紧急度任务还剩多少时间窗口,剩得越少越紧急,比如“出锅倒计时 30 秒”。
- p_i 就绪度前置依赖是否完成,比如“跑测试”依赖“写完代码”已完成。
- α、β 权重紧急与就绪的相对重要程度,由系统配置决定。
- 打分与选择每个任务算一个加权分,调度器从队列中挑分数最高的执行。
终止条件与安全边界
厨师再勤快,也不能永远炒下去。一个合格的自动厨房必须有三条“下班红线”:菜达标了(出锅)、时间到了(打烊)、食材用完了(停火)。任何一条被触发,厨师都必须立刻停下。如果只有“尝到味道刚好”这一条,万一永远尝不到刚好,他就会把整个厨房的盐都倒进去。
LLM 循环同样需要三条终止红线。第一,目标达成:验证器确认输出满足要求;第二,轮数上限:到 \(T_{\max}\) 轮还没搞定就放弃并转交人工;第三,预算红线:累计花费超过 \(B\) 就熔断。三条红线构成“终止条件函数”,逻辑上任何一个条件为真,就退出循环。
特别提醒:第一条“目标达成”不能只靠 LLM 自己说“我完成了”。模型很可能为了迎合指令而假装完成,所以最好由外部验证器把关——测试用例是否通过、JSON 是否合法、得分是否超过 \(\theta\)。回到厨房:只靠厨师“我觉得行了”出锅是危险的,需要计时器、称重秤这些外部工具来兜底。终止条件设计,就是把“人觉得好了”翻译成可编程校验的“红线集合”。
- G(x_t) 达成度外部验证器对当前状态的打分,比如单元测试通过率或评分函数输出。
- θ 阈值达到多少分算“成功出锅”,例如测试通过率 100%。
- T_max 最大轮数防止无限循环的硬顶,循环超过这个数就强制退出。
- Cost_t 累计成本从第 1 轮到当前轮消耗的 token 费用总和。
- B 预算上限总成本红线,累计花费超过它就熔断。
- ∨ 逻辑或三条红线任一命中即终止,等价于“三条下班路,走到哪条算哪条”。
状态管理与上下文传递
机器人厨师身上永远别着一本小本子:每道菜的火候、哪位客人说太咸、下一道菜要少放糖——都记下来。但如果本子越写越厚,翻起来越来越慢,所以他会定期把本子浓缩成一页“关键便签”,只留最有用的信息。自动循环系统里的“状态”,就是这本小本子。
循环每走一轮,都会产生新的观察:工具返回、中间输出、错误信息。这些信息不能丢,否则下一轮就像失忆的厨师,从头开始瞎忙。状态管理干三件事:状态持久化(存到数据库或文件,进程崩溃也不丢)、上下文传递(把上一轮的观察和结论带给下一轮)、记忆压缩(把塞不下的历史浓缩成摘要)。
小本子决定了一个 Agent 是“越干越懂行”还是“每轮从零开始”。状态管理做得好,循环才有记忆,上下文传递才顺畅;做不好,循环就是原地打转的失忆厨师——每轮都很努力,但永远记不住上一轮犯过的错。
- ctx_t 上下文第 t 轮带入的历史信息,相当于便签上记下的要点。
- obs_t 观察本轮执行完后环境返回的新信息,比如工具输出或报错信息。
- ⊕ 拼接把新旧信息拼在一起,准备统一处理。
- B_win 窗口预算上下文窗口的 token 上限,超过就放不下。
- Compress 压缩在预算内保留关键状态、丢弃冗余。压缩不是简单截断,而是“摘要式保留”:目标、已完成动作、待办、当前结论必须留;冗长原始日志可以丢。
循环安全与资源限制
再聪明的厨师也可能闯祸:炖汤忘关火、油锅起火、把辣椒当成白糖。所以厨房里必须有灭火器、燃气阀和烟感报警器。自动循环系统对“失控”的容忍度更低,因为模型跑错了烧掉的是真金白银和真实系统,而不是一锅汤。
四种高风险场景必须防护。死循环:模型反复输出相同动作,消耗 token 却不推进任务;成本爆炸:单轮输出过长或多轮累积超预算;权限滥用:模型被提示词注入后调用危险工具;外部故障:工具返回异常、API 超时。每一类都要有对应的闸门。核心闸门有两道:成本闸门与失败闸门。
失败闸门与成本闸门配合:连续失败达到 \(k\) 次或单轮超时达到 \(q\) 次,同样打开熔断器,转入降级流程——换小模型、退避重试、交还人工。再配合工具白名单(Agent 只能调用预先允许的工具)和速率限制(每分钟最多调用几次),“失控”就变成了“受控失败”。灭火器不是为了把厨房点着再灭火,而是为了“万一着火也烧不塌房子”。循环安全设计的目标不是杜绝失败,而是让失败有代价上限、有退出路径。
- n_t^in 输入 token 数第 t 轮送入模型的 token 数量,上下文越长越大。
- n_t^out 输出 token 数第 t 轮模型生成的 token 数量。
- p 单价每个 token 对应的价格系数,由所用模型决定。
- ∑ 求和从第 1 轮到第 T 轮,把每一轮的花费累加起来。
- ⇒ 熔断累计成本一旦超过预算 B,就打开熔断器,停止后续调用。
自主Agent与自我改进
顶级厨师还有一个习惯:收工后复盘。今天哪道菜客人没吃完,说明配方有问题,明天就改那道菜的做法。一个只会“循环干活”的机器人还称不上聪明,真正的自主 Agent 要在循环中不断反思、提炼教训、改进下一轮的动作——这就是“反思(Reflection)”环节。
每轮执行完之后,系统额外加一个评估器 Evaluate:目标达成度如何、本轮犯了什么错、有哪些可复用的经验。反思产出“改进指令”Improve,并把它写进状态,供下一轮使用。循环因此从“执行环”升级为“学习环”:执行不再是简单的重复,而是每轮都比上一轮更接近目标。
厨房里,会复盘的厨师第二天做同一道菜会少放盐;会学习的 Agent 第二次执行同类任务时也会少走弯路。当循环结构、状态管理与反思机制组合起来,LLM 就不再是“问一句答一句”的工具,而是一个能自己跑起来、越跑越好的引擎——这正是“自动循环系统”四个字的完整含义。
- Eval(x_t) 评估对当前方案打分并找出问题所在,比如“测试挂了,错误在输入解析”。
- Impr 改进把评估结论转成具体的修改指令,比如“修复输入解析的边界条件”。
- ⊕ 合并把改进指令应用到当前方案上,得到一个新版本。
- x_{t+1} 新方案改进后的方案进入下一轮循环,作为新一轮的起点。
AI 应用场景
自动化 Bug 修复 Agent
阶段:推理与执行阶段(自主循环 + 工具调用)
解决的问题:传统 CI 流水线发现测试失败后,工程师要停下手头工作去排查日志、定位改动、修复并重跑,来回至少半小时。接入自动循环系统后,Agent 自己“跑测试→读报错→改代码→重跑”,直到测试通过或达到轮数上限。
具体案例:某团队将 Python 单测失败接入自主修复 Agent,设置最大轮数 5、单轮超时 90 秒、成本预算 1 元。实测约 70% 的常规失败在 5 轮内被自动修复,未修复的自动转人工,并附带 Agent 写的排查报告,工程师接手时间缩短一半。
自主调研报告生成
阶段:规划与检索阶段
解决的问题:传统调研要反复搜索、阅读、对照提纲补漏,人工耗时数小时。循环系统让 Agent“写提纲→逐节检索→总结→对照提纲查漏→重写”,每轮把上一轮的缺陷作为下一轮的输入,持续迭代优化。
具体案例:市场分析师让 Agent 调研“2025 年国产大模型价格战”:第 1 轮生成粗提纲,第 2 轮逐条检索补充数据,第 3 轮检查事实引用缺失,第 4 轮统稿并标注信息来源,最终产出一份带引用的初稿,分析师只需做最后润色。
Python 演示
from dataclasses import dataclass, field @dataclassclass AgentState: memory: list = field(default_factory=list) round_count: int = 0 cost_total: float = 0.0 done: bool = False class AutoLoopEngine: """Auto loop engine: let LLM run in its own loop""" def __init__(self, llm_call, max_rounds=10, budget=2.0, price=2e-5): self.llm_call = llm_call self.max_rounds = max_rounds self.budget = budget self.price = price self.state = AgentState() def _calc_cost(self, tokens_in, tokens_out): return (tokens_in + tokens_out) * self.price def _goal_met(self, reply): return "任务完成" in reply def _compress(self, full_text): return full_text[-120:] def run(self, task): context = task while not self.state.done: self.state.round_count += 1 rounds = self.state.round_count if rounds > self.max_rounds: print("reach max rounds, force stop") break reply, token_in, token_out = self.llm_call(context) self.state.cost_total += self._calc_cost(token_in, token_out) self.state.memory.append(reply[:50]) if self.state.cost_total >= self.budget: print("cost over budget, circuit break") break if self._goal_met(reply): print("goal met at round", rounds) self.state.done = True break context = self._compress(context + reply) print("final memory:", self.state.memory) print("total cost: %.4f" % self.state.cost_total) class FakeLLM: """Mock LLM: fail in first 3 rounds, succeed in round 4""" def __init__(self): self.call_count = 0 def __call__(self, prompt): self.call_count += 1 token_in = len(prompt) * 3 token_out = 30 if self.call_count >= 4: return "方案已完善,任务完成", token_in, token_out return "方案还不够完善,建议补充细节", token_in, token_out if __name__ == "__main__": engine = AutoLoopEngine(FakeLLM(), max_rounds=10, budget=2.0) engine.run("写一份产品需求文档")
while not self.state.done:循环主闸门:只要还没完成,就继续跑下一轮。if rounds > self.max_rounds:终止条件 1:超过最大轮数就强制停止。reply, token_in, token_out = self.llm_call(context)调用 LLM,同时记录输入输出 token 数。self.state.cost_total += self._calc_cost(token_in, token_out)每轮记账,累计成本。if self.state.cost_total >= self.budget:终止条件 2:成本超预算就熔断。if self._goal_met(reply):终止条件 3:外部信号确认目标达成(这里用关键词模拟)。context = self._compress(context + reply)上下文传递与压缩:只保留最近信息,避免窗口爆掉。if self.call_count >= 4:模拟真实场景:前 3 轮都不达标,第 4 轮才完成任务。
常见误区
误区“让 LLM 多跑几轮,输出总会越来越好,所以循环次数设得越大越保险。”
正解循环的收益是递减的,甚至可能是负的。第 3 轮反思可能已经收敛,第 8 轮可能还在重复同样的错误——模型并没有真正的“练习”,它只是把同一段历史再读一遍。真正有效的改进来自外部验证信号(测试是否通过、评分是否上升),而不是轮数本身。轮数上限应该在收益下降点附近设定,比如 5-10 轮。
为何常见:“熟能生巧”的直觉让人以为重复调用等于练习,忽略了 LLM 在单次任务内并不会真正学习。
误区“上下文窗口有几十万 token,把每轮对话原样带进去,信息就不会丢。”
正解上下文窗口再大也有硬上限,而且窗口越长,单轮成本越高,真正被模型注意到的有效信息反而被稀释。正确做法是压缩:保留目标、已完成动作、关键结论和待办,把冗长的工具日志、中间草稿摘要化或丢弃,让每一轮都在预算内携带最有效的记忆。
为何常见:大窗口数值给人“足够用”的错觉,小规模演示也暴露不出成本问题,直到线上账单出来才后悔。
误区“每次循环末尾问一句'任务完成了吗',模型说完成就停止,省事又灵活。”
正解模型可能误判:为了迎合指令而声称完成,或者把“部分完成”当成“全部完成”。终止条件必须由外部可验证的信号把关,比如测试通过率、输出格式校验、成本与轮次上限。模型可以“提议完成”,但“最终批准权”要握在验证器手里。
为何常见:对话场景中人类天然充当验证器,把同样的交互搬到 Agent 时,忘了补上这个角色。
误区“给循环加上 max_rounds 就不会死循环,安全防护就已经完成。”
正解轮数上限只挡“停不下来”,挡不住成本爆炸、工具被滥用、异常反复重试。还需要成本预算熔断、连续失败熔断、工具白名单、速率限制和异常分类,让每一次失败都有代价上限和退路。安全是一个体系,不是一个参数。
为何常见:单点防护最容易想到,而系统性风险(成本、权限、异常)需要整体设计,新手往往只盯着循环次数。
面试题
Q1. 自动循环系统中,“一轮循环”指的是什么?
- A.模型一次完整的前向推理过程
- B.一次感知-决策-执行-评估闭环← 正确答案
- C.用户与模型之间的一整轮对话
- D.训练数据集被完整扫描一遍
答案:B。循环以“感知→决策→执行→评估”为一个完整迭代单元(一轮),结束后自动进入下一轮。A 只是单次推理,C 是对话交互,D 是训练术语,都不构成任务推进意义上的“一轮”。
Q2. 下面哪一项属于安全可靠的循环终止条件?
- A.上下文窗口刚好被完全塞满
- B.目标达成或达到最大轮次上限← 正确答案
- C.模型输出内容超过五个自然段
- D.等待用户手动点击停止按钮
答案:B。可靠的终止条件由三条红线组成:目标达成(外部验证)、最大轮次、成本预算。A、C 都不是任务完成的信号,D 依赖人工介入,失去了“自主循环”的意义。
Q3. 在循环系统中,上下文压缩的主要目的是什么?
- A.降低token消耗并保留关键信息← 正确答案
- B.让模型生成内容更加简短明了
- C.提高模型训练时候的收敛速度
- D.防止模型生成不实幻觉内容
答案:A。压缩是在窗口预算内“留关键、丢冗余”,既控制 token 消耗又保住有效记忆。B 说的是输出风格,C 是训练话题,D 是幻觉问题,与上下文压缩的目的无关。
Q4. 哪些措施属于循环安全防护的关键手段?
- A.设置最大轮次并限制成本预算← 正确答案
- B.连续失败达到阈值后触发熔断← 正确答案
- C.限制Agent可调用的工具白名单← 正确答案
- D.每轮失败之后进行无限次重试
答案:ABC。轮次与预算限制、失败熔断、工具白名单都是安全体系的关键闸门。D 的“无限重试”恰恰是失控行为,会放大成本和风险,应当被熔断机制制止。
Q5. 执行引擎中调度器负责的核心任务是什么?
- A.决定下一步优先执行哪个子任务← 正确答案
- B.生成语言模型的概率分布结果
- C.判断整个任务是否已全部结束
- D.压缩传递到下一轮的上下文内容
答案:A。调度器按紧急度和就绪度给任务队列里的子任务打分,选择下一个执行对象。B 是模型生成环节,C 是终止条件判断,D 是状态管理职责,都不属于调度器。
Q6. 熔断机制与简单重试之间最大的区别是什么?
- A.熔断会停止尝试并转入降级流程← 正确答案
- B.重试可以显著降低调用总成本
- C.熔断只适用于网络超时的场景
- D.重试能够消除系统所有类型故障
答案:A。熔断不是“再试一次”,而是在连续失败或成本超限后停止尝试、转入降级(换模型、交人工、退避)。重试本就是被熔断约束的对象,B、C、D 都误解了二者的关系。
Q7. 设计状态管理机制时需要覆盖哪些要点?
- A.状态持久化到外部存储防止丢失← 正确答案
- B.控制上下文窗口的token预算← 正确答案
- C.定期压缩记忆只保留关键信息← 正确答案
- D.将所有原始日志永久保存下来
答案:ABC。状态管理三件事:持久化(防崩溃丢失)、窗口预算控制、记忆压缩。D 的“永久保存所有日志”既不现实也无必要,关键信息经压缩摘要保留即可,原始日志按策略淘汰。
Q8. 反思(Reflection)环节在自我改进循环中的作用是什么?
- A.提取失误教训并改进下轮策略← 正确答案
- B.完全替代轮次与成本终止条件
- C.减少模型输出的token总数量
- D.扩大上下文窗口的可用空间
答案:A。反思通过评估当前输出,提炼可复用的教训并生成改进指令,让下一轮做得更好。它不替代终止条件(B),也不直接优化 token 数或窗口大小(C、D)。
Q9. 循环成本公式中的符号 p 代表什么?
- A.单个token对应的价格系数← 正确答案
- B.模型执行任务的总轮次
- C.每轮输入token的总数量
- D.模型生成文本的平均速度
答案:A。成本公式为每轮(输入 token + 输出 token)之和乘以单价 p,再逐轮累加。p 是 token 单价,B 对应 T,C 对应 n,D 与成本公式无关。
Q10. 哪些信息应当被传递到循环的下一轮?
- A.上一轮收集到的观察结果← 正确答案
- B.反思后提炼出的关键结论← 正确答案
- C.全部的原始日志和中间数据
- D.目标约束与历史状态的摘要← 正确答案
答案:ABD。观察结果、反思结论、目标与状态摘要是下一轮决策必需的“便签”。C 的全部原始日志应在压缩环节被摘要化,原样全传会导致窗口溢出和成本膨胀。