Loop Engineering实战:用迭代自纠让大模型输出稳定可用
1. 先搞清楚Loop Engineering 到底解决什么问题1.1 模型输出的随机性是逼着你上循环的根本原因Loop Engineering 这个词最近在大模型应用开发圈子里出现的频率越来越高。说白了它不是什么高深莫测的新算法而是把很多开发者早就做过的一件事——生成结果不满意就让它重来——系统化、工程化成了一套有反馈、有终止条件、可复用的循环框架。核心词就四个字迭代自纠。你拿同一个 prompt 连续问同一个模型十次大概率拿到十份略有不同的答案里面可能只有两三份是能直接拿去用的。原因在于大模型的解码过程是个概率采样temperature 参数大于 0 时每次生成的 token 序列都带着随机性。这有点像去一家随机餐厅点同一个菜厨师手艺在线但今天盐多放半勺、明天摆盘歪一点味道时好时坏。做实验、写玩具项目无所谓可一旦要做智能客服、自动化报告、内容生产工具这类真实业务没人能接受碰运气。Loop Engineering 解决的就是这件事怎么把单次生成的高波动输出通过可控的循环稳定地捞出一个达到质量线的结果。这篇文章特别适合两类人。一类是刚入门大模型应用开发、还在靠反复改 prompt 撞运气的新手另一类是已经在做内容生成、数据清洗、客服问答这类项目被输出质量不稳定折腾得头疼的开发者。接下来我会先把循环的三种基础模式讲透再给你一个能直接改改就用的最小代码框架最后用一个完整项目把这些知识点串起来。1.2 普通重试和带反馈的循环差着十万八千里很多人的第一反应是不满意就重新生成嘛多调几次不就行了这其实是两种完全不同的思路。普通重试是闭卷考试不及格什么也不学重新再考一次。每次尝试彼此独立失败信息完全没有被利用成功率不会因为多试了几次而提升。如果单次生成达到合格线的概率是 30%你重试五次依旧可能一无所获。带反馈的循环是另一套逻辑上一轮输出的问题被找出来作为下一轮生成的条件信息重新喂进去。这相当于带错题本复习然后再考。模型在下一轮生成时看到的不是空白而是这里有三个问题请针对这三个问题修改生成分布被信息改变了成功概率会一轮轮往上走。这也是为什么我一再强调循环工程的重点从来不是多调几次而是每一次失败都要留下有价值的反馈。1.3 三类基础循环模式先建立全局认识在我见过的实际项目里用得最多的循环模式就三种自评循环、结构校验循环、多智能体循环。它们解决的问题不一样适合的场景也不一样。循环类型核心思路典型场景优点缺点自评循环模型评估自己生成的输出发现问题后修订再生成文案写作、代码生成、报告润色实现简单一套流程走到底评估环节可能不够客观结构校验循环用代码规则校验输出格式校验失败则把错误信息回喂JSON 解析、字段抽取、接口参数生成校验结果确定性强硬标准只能发现规则类问题管不了内容质量多智能体循环一个模型负责生成另一个模型扮演评审意见回喂高质量长文、复杂方案设计评审更客观不容易护短成本翻倍延迟更高先记住这张表后面每一类我都会展开讲原理、给模板、贴代码。你不需要一开始就全上大多数项目先从自评循环入手就够用了。2. 三种核心循环模式逐个拆开揉碎讲2.1 自评循环让模型当自己的审稿人自评循环是最通用、最好上手的一类。流程长这样生成 → 自评 → 修订 → 再评直到评分达到预设阈值。你可能会说让模型评价自己的输出它不就成了既当运动员又当裁判这话有道理但实践下来只要评估 prompt 设计得当自评循环的效果依然非常显著。关键在设计评估环节而不是让模型笼统地说这篇写得不错。我常用的评估 prompt 结构是任务背景 明确的质量维度 打分要求 必须给出可修改的问题清单。拿技术文章生成举例评估维度可以拆成四条逻辑连贯性段落之间是否有清晰递进有没有突然跳转术语准确性技术名词是否用对有没有含糊表述表达自然度读起来像不像人话有没有明显翻译腔实操价值结论是否落地有没有给读者可操作的信息。注意评分动作和问题清单必须同时输出。我给模型的格式要求是这样的{ score: 0, problems: [必须是具体可修改的问题禁止写整体不错这类空话, ...] }为什么要强制问题清单因为只给一个分数模型修订的时候就不知道往哪个方向使劲只有把问题拆到第二段对某某技术的表述不够准确这个粒度下一轮生成才有明确目标。还有一个容易被忽略的点评估的 temperature 要调低最好调到 0 附近。评估要的是稳定和严格不是发散和创意。生成环节可以用 0.7 左右的温度保持表达多样性评估环节用 0.1两类 prompt 的采样策略最好分开。2.2 结构校验循环用代码的硬规则卡住格式自评循环管的是内容质量结构校验循环管的是输出格式。你以为格式问题简单实际上在大模型应用里这是翻车率最高的地方。模型输出的 JSON 经常出现这些问题字段名大小写不一致、必填字段缺失、文本末尾被截断导致 JSON 不完整、外面包了一层 markdown 代码块标记。这些问题靠模型自评是看不出来的必须用代码去校验。实现思路很直接先定义一份期望的 JSON schema然后写一个校验函数把模型输出扔进去验证。验证不通过就把校验器返回的原始错误信息拼到下一轮 prompt 里让模型对照错误去修改。这一步有个很重要的细节错误信息不要自己加工直接把校验器的报错原文贴给模型。诸如article.body is a required property这种原汁原味的错误模型反而理解得最准确。def validate_json_output(raw_text: str): # 去掉可能存在的 markdown 代码块标记 cleaned raw_text.strip() if cleaned.startswith(): cleaned cleaned.strip() if cleaned.startswith(json): cleaned cleaned[4:] # 取第一对花括号之间的内容 start cleaned.find({) end cleaned.rfind(}) if start -1 or end -1: return None, [找不到 JSON 花括号请只输出 JSON] try: data json.loads(cleaned[start:end1]) except json.JSONDecodeError as e: return None, [fJSON 解析失败{e}] # 必填字段校验 errors [] if title not in data: errors.append(缺少 title 字段) if body not in data: errors.append(缺少 body 字段) return data, errors结构校验循环最大的价值在于确定性高通过就是通过不通过就是要把错误修掉。它特别适合那些输出会被下游程序消费的场景比如生成结构化数据、工具调用参数、批量处理任务。2.3 多智能体循环让挑刺这件事彻底独立自评循环有个天然短板模型倾向于维护自己刚才生成的答案术语叫自我一致性偏差。尤其是当输出已经写了很长、整体看起来也挺像样的时候模型在评估环节容易手下留情。多智能体循环就是冲着这个问题去的。思路是把生成者和评审者分开各用一套独立的 system prompt。生成者负责写评审者被设定成严格的项目评审员任务就是挑毛病。两个角色中间不直接对话评审意见作为下一轮生成的输入条件。我试过这个方案效果确实比自评更狠。评审 prompt 里只要加一句你的任务是从最苛刻的角度找出所有问题哪怕是小瑕疵也要指出来评审意见的犀利程度会明显不一样。原因不复杂模型在不同角色设定下会进入不同的语义空间扮演挑剔甲方的时候它的评估标准会被角色 prompt 拉高。代价也摆在那里。多跑一个评审角色意味着每轮循环要多消耗一份 token延迟也会增加。我的建议是常规内容用自评循环就够了只有对质量要求特别高的场景比如对外发布的品牌稿件、复杂技术方案才上多智能体循环。3. 保姆级实操从零搭一个最小可用的循环框架3.1 环境准备与最小代码骨架这一节我尽量把步骤写到照着敲就能跑的程度。先准备环境Python 3.9 以上版本安装你实际在用的模型 SDK然后设置环境变量来存放密钥。密钥务必用环境变量管理不要写死在代码里否则一个不小心把项目推到公开仓库密钥就泄露了。下面这段代码把具体 SDK 的细节都屏蔽了只留一个最通用的 chat 函数。跑项目的时候把它替换成你自己的调用方式即可。import os import json from llm_sdk import LLMClient # 换成你实际在用的 SDK client LLMClient( api_keyos.environ[LLM_API_KEY], base_urlos.environ.get(LLM_BASE_URL, ) ) def chat(system: str, user: str, temperature: float 0.7) - str: resp client.chat.completions.create( modelos.environ.get(LLM_MODEL, default), messages[ {role: system, content: system}, {role: user, content: user}, ], temperaturetemperature, ) return resp.choices[0].message.content注意如果你实际用的客户端接口不是这种风格没关系函数名叫 chat参数列表保持一致就行。后面所有循环逻辑都只依赖这个函数不关心底层 SDK 长什么样。3.2 循环终止条件没有止损线的循环都是烧钱很多新手写循环容易热血上头让模型一次次改改到满意为止。问题是满意这个标准如果不量化循环就可能是无穷的。每一次循环都在烧 token 和等待时间所以终止条件必须提前定好而且用代码硬性卡住。我建议一个循环框架至少包含三个终止条件最大迭代次数默认 3 次起步最多别超过 5 次质量阈值评分达到这个值就收工超时保护超过指定时间或累计 token 数强制停止并返回当前最佳结果。最大迭代次数是最重要的安全阀。哪怕模型评分一直不达标到了第三轮也必须停下来。为什么是 3 而不是 10因为从实际项目经验看带反馈的循环通常两三轮就能把质量从 6 分拉到 8 分之后再迭代收益急剧下降纯粹交学费。class LoopEngine: def __init__(self, max_iterations3, quality_threshold8.0): self.max_iterations max_iterations self.quality_threshold quality_threshold def run(self, gen_system, gen_user, eval_system, eval_user_template): output chat(gen_system, gen_user, temperature0.7) for i in range(1, self.max_iterations 1): eval_prompt eval_user_template.format(outputoutput) eval_result chat(eval_system, eval_prompt, temperature0.1) score, problems parse_eval_result(eval_result) if score self.quality_threshold: print(f第 {i} 轮评分 {score}达标结束循环) return output, i, score # 把问题清单拼进修订 prompt feedback \n.join(f- {p} for p in problems) revise_user f以下是上一版内容\n{output}\n\n请针对这些问题修订\n{feedback} output chat(你是负责修订的助手, revise_user, temperature0.7) print(达到最大迭代次数返回最后版本) return output, self.max_iterations, score这个骨架已经能跑生产环境里建议再补两个细节每轮结果要落日志方便回头排查访问失败要加重试和熔断不能让网络抖动把整个流程搞挂。3.3 让模型输出结构化结果解析层一定要稳自评循环里最气人的一件事就是模型不好好给你 JSON输出一通我认为这篇内容在逻辑方面还不错……的散文或者把 JSON 包在 markdown 的代码块里。所以解析层必须写得足够皮实。我的解析函数就干三件事剥掉代码块标记、抽取花括号内容、用 json.loads 解析并捕获异常。解析失败时不要崩溃而是把它当成一次修订机会把你的评估结果无法解析请严格按 JSON 格式输出作为一条反馈喂回去。还有个经验要求模型输出的 JSON schema 结构一定要保持稳定不要这次五个字段下次三个字段。字段越固定解析函数越简单出错的概率越低。而且固定的 schema 还能让你把所有历史评估结果存进表格做分析观察循环质量的走势。3.4 参数选择与成本估算这笔账必须心里有数参数怎么定直接决定循环效果和成本。我的经验值如下环节temperature说明生成0.7 左右保留一定的表达多样性避免每次生成都像复印机评估0.1 以下要稳定、严格不需要发散修订0.5 到 0.7既要针对问题改也不要改得面目全非成本估算给个公式单次循环成本 生成 token 评估 token 修订 token× 单价 × 循环轮数。按一篇 1500 字的中文技术文章来算生成大概消耗 2500 token评估 600 token修订 2000 token一轮循环合计 5100 token。跑 3 轮就是 1.5 万 token 左右。不同模型单价差异很大具体用你实际的模型价格乘一下就知道。心里有这么一笔账你就会明白为什么我总是强调先定好最大迭代次数——每一轮循环都是钱。4. 项目实战带自反馈的技术文章初稿生成助手4.1 项目背景与方案设计光讲概念容易飘我拿一个实际做过的项目来完整演示。某团队要做内部用的技术文章初稿生成助手。输入是技术主题 一份大纲 若干参考要点。输出是一篇 1500 字左右、可以直接当初稿的技术推文。需求拆下来有四条硬标准结构完整有开头引入、核心讲解、实操步骤、结尾建议术语准确技术名词不能含糊参考要点里的关键表述必须保留表达自然读起来像技术人在说话不像翻译腔有实操价值不能讲完原理就完事必须给出能落地的操作建议。方案分三步走。第一版先做单轮生成搞清楚基线水平第二版接入自评循环第三版加入事实核对与风格偏好控制逐步升维。4.2 第一版单轮生成暴露的三个问题第一版很简单一份生成 prompt 直接出稿。生成 prompt 长这样节选你是资深技术博主擅长把复杂技术概念讲得通俗易懂。 请按以下大纲写一篇技术推文初稿目标读者是刚入门的开发者。 要求 1. 开头用 200 字以内说清楚要解决什么问题 2. 中间部分每个小节都给具体例子 3. 结尾给出至少两条实操建议。 主题与大纲……人工审读初稿后列出的问题集中在三处开头引入和正文风格明显割裂开头像官方通告正文又突然口语化一处技术术语的表述不够准确把异步和并行两个概念混在了一起结尾的建议部分比较空泛停留在要注意这些问题这种层面完全没落到操作上。这三个问题非常有代表性单轮生成的模型不是没有能力写好而是它在一次前向生成里很难同时照顾好所有约束。这就给自评循环提供了充分的发挥空间。4.3 第二版自评循环把及格线从 6 分拉到 8 分第二版接入循环框架。评估系统 prompt 我设计成你是一位严格的文字编辑擅长审核技术文章。 请从以下四个维度评估文章质量 1. 逻辑连贯性段落衔接是否自然结构是否递进 2. 术语准确性技术表述是否准确是否混淆概念 3. 表达自然度是否像真人写的有无翻译腔或官腔 4. 实操价值建议是否具体能不能照着做。 输出 JSON{score: 0到10的整数, problems: [具体问题1, 具体问题2]} 问题必须具体到段落和句子禁止写空话。修订的系统 prompt 则写成你是文章修改助手。请阅读上一版内容与评审意见仅针对意见指出的问题进行修改。 不要推翻整体结构不要引入新内容保持原有的语气和篇幅。实测跑了两轮。第一轮评分 6.5问题清单里明确点出开头两段像官方公告与正文口语风格冲突第二段把异步与并行混用结尾第三点建议可以给出具体工具名称和适用场景。修订后的第二轮评分到了 8.2三个问题都改掉了循环结束。看一下修订前后的对比开头从随着微服务架构的广泛应用……改成了你在做微服务的时候有没有遇到过明明接口都调通了页面还是转圈半天这种情况——这一改口语化的问题直接解决示例感也出来了。这个例子最能说明 Loop Engineering 的价值模型第一版不是不行而是它需要被有人拿着放大镜指出问题之后才能在下一轮集中发力。反馈的颗粒度决定了修订的质量。4.4 第三版事实核对与风格偏好把循环引向纵深第二版解决了表达质量但还不解决事实一致性。技术文章最怕的就是模型一本正经地编造。于是第三版在评估维度里加了一条事实核对。做法是把项目输入时的参考要点原文逐条塞进评估 prompt要求评估者核对文章里是否忠实保留了这些要点有没有超出范围的自创表述。同时加了风格偏好控制。在生成 prompt 里放一个风格参数0 代表严谨正式10 代表活泼口语。修订 prompt 里也带着这个参数防止模型把语气改歪。这两处调整并不复杂但效果是立竿见影的。事实核对维度上线后有一轮文章把某个技术名词的适用范围写大了被评估环节准确抓出来参考要点中该技术仅适用于 X 场景正文第 5 段写成了适用于所有场景。修订后被纠正。这个能力纯靠单轮生成很难保证但摆在循环里就变成了一条自动化的质检线。4.5 三版效果对比数据不会骗人我用同一批五组选题做了对比测试结果整理成一张表版本平均质量分平均迭代轮数单篇平均成本可用率第一版 单轮生成6.31较低20%第二版 自评循环8.12.2中等80%第三版 事实核对风格8.42.6中等偏高90%注意第二版到第三版成本增加不多可用率却从 80% 提到 90%。数据最想传达的信息是循环轮数不是越多越好关键是每一轮反馈的质量。两到三轮就能把可用率拉高一大截再多就是边际递减。5. 高频踩坑与排查技巧实录5.1 循环不收敛评分反复横跳怎么办最常见的问题是评分振荡。第一轮 7.5修订后 8.5再修一轮反而掉到 7.0又修一轮回到 8.0。这种情况我碰过不止一次原因基本出在修订环节用力过猛模型拿到评审意见后不仅改了问题点还把原本写得不错的部分也推翻了。解决办法有两个。一是在修订 prompt 里加红线只针对评审意见指出的问题修改其他部分保持原样。二是放宽质量阈值从必须 8.5 分降到8 分就收手在质量和成本之间取平衡点。还有一个技巧是记录历史评分如果连续三轮评分没有上涨趋势直接止损返回当前最高分版本别恋战。5.2 输出截断与 JSON 解析失败老三样问题截断是结构化输出的头号杀手。文章写长了max_tokens 设小了模型生成到一半被切断JSON 只剩半个括号。这类问题靠解析层的清洗函数能救一半救不了另一半——截断本身丢掉了信息硬补括号也是错的。我的处理办法是防御性设计生成阶段就在 prompt 里强调如果内容较长请优先保证 JSON 完整正文内容可以适当精简同时把 max_tokens 设置为估算最大输出长度的 1.2 倍以上留出余量。解析失败时的兜底策略是把失败当作一条反馈重新发起一轮修订但最多重试一次再失败就返回上一次成功的结果。5.3 成本失控循环框架最隐蔽的坑自评循环上线初期成本会比单轮生成高出一大截这是正常的。但不正常的是有的人会发现成本翻了好几倍检查日志才发现某几个文档的循环一直在跑满 5 轮而且每轮输出越改越长token 消耗滚雪球。要控制成本除了前面说的最大迭代次数还有一个很实用的细节修订 prompt 里明确保持与原版本大致相同的篇幅。模型在修订时容易默认多写点显得有诚意你不卡它它就膨胀给你看。另外可以在循环框架里加一个累计 token 计数器超过预算直接强制结束这个保护比人工盯日志可靠得多。5.4 自评变成自我表扬评估失效的破解方法自评循环最让人头疼的时刻是模型给你打出一个 9 分但你人眼一看这稿子根本没法用。遇到这种评估失灵按下面这个顺序排查先检查评估温度。很多开发者忘了给评估环节单独设 temperature还在用 0.7导致评估结果随机波动。评估温度必须降到 0.1 以下。再检查评估 prompt 有没有要求给证据。只要求打分的评估是虚的要求每个问题必须引述原文片段之后模型想糊弄就得先找到原文依据严谨程度立刻不一样。最后考虑角色分离。如果改了这些还是自我表扬说明这个模型在当前任务上的自评能力确实有限那就换多智能体循环让独立评审者来挑刺。我在实际项目里遇到过一次这种情况换成双角色后评分明显回归理性。还有一个贯穿所有问题的经验循环日志一定要完整记录包括每轮的输入、输出、评分、问题清单。有了日志前面提到的所有问题都能在五分钟内定位。没有日志你只能对着黑盒猜效率完全不是一个量级。6. 一些容易被忽略的实战经验最后分享几条我在实际项目中反复验证过的体会。第一条循环质量的上限由评估 prompt 决定而不是生成 prompt。这句话值得记下来。很多团队花大量精力调生成 prompt却随便写两句评估要求效果自然上不去。把评估维度设计得越具体、越可操作循环的改进空间就越大。我甚至见过一个项目评估 prompt 一个字没改生成侧完全没动只把评估的评分规则从打分改成打分并要求给出证据整体输出质量就涨了一截。反馈的质量才是循环工程真正的杠杆。第二条不要贪心。循环轮数不是越多越好我强烈建议从 3 轮上限开始跑先看一轮数据再决定要不要放宽。多数任务 3 轮以内就能达到可用水平强行跑更多轮看到的只会是成本曲线飙升和质量曲线趋于平缓。第三条善用历史评分数据。把每轮评估的分数、问题类别、修改前后文本都存在表格里跑一段时间后你会发现自己项目的常见问题分布。比如有的场景问题集中在术语混淆有的集中在结构松散知道这些之后你在写生成 prompt、设计评估维度时就能提前打补丁甚至能把常见问题直接写进第一轮生成的要求里让模型从一开始就别犯。把 Loop Engineering 理解成一个质量漏斗就好每一层循环都在筛掉有问题的输出而筛孔的尺寸就是你的评估标准。筛孔太粗坏结果漏过去筛孔太细成本失控。学会调节这个筛孔你就真正掌握了大模型应用从能生成走向稳定可用的那一步。希望这篇文章能让你少走我走过的弯路。