🤖 别再手动改 Prompt 了!用 AI Loop 让 AI 自己跟自己较劲,直到满意为止
一条推文,700 万人围观。Claude Code 作者公开说:"我不写 prompt,我用 Loop。"
这篇文章,帮你从"改稿工具人"变成"AI 闭环设计师"。
📌 导语:你才是那个"循环"
打开 ChatGPT,输入 Prompt,回车。AI 吐出一段文字。你扫一眼,不满意,删掉重写 Prompt,再回车。AI 又吐出一段。你还是不满意,再改……
这场景太熟悉了,以至于我们从来没意识到一个问题:明明被循环的是 AI,真正在循环里转不出去的,是你。
每一次"不满意→改 Prompt→再发",都是一次迭代。但执行迭代的是你,不是 AI。你成了那个 while 循环里的引擎,而 AI 只是循环体里一行被动执行的代码。
这很荒谬。计算机最擅长的事就是循环——CPU 每秒重复几十亿次"取指令→执行→取下一指令",大模型也是靠万亿次循环训练出来的。但到了我们手上,这个最擅长循环的工具,却被用成了"一次性的生成器"。
AI Loop 要翻转的,就是这个关系。
你不再站在循环里当那个喊"再来一次"的人。你退到循环外面,设计好三件事:目标是什么、什么算合格、什么时候该停。然后让 AI 自己在循环里转,直到交出让你满意的东西。
你从"操作者"变成了"设计者"。从"改稿工具人"变成了"闭环架构师"。
一、先让大脑"叮"一下的事实 🧠
计算机最底层的本事,就是循环。你按开机键,主板就开始跑 while(true),直到你关机。这个死循环里,CPU 一刻不停地"取指令 → 执行 → 取下一指令",每秒重复几十亿次。
我们平时聊天用的 DeepSeek、Claude、GPT,它们是怎么变聪明的?也是循环喂出来的:拿海量数据给模型看 → 算一下错了多少 → 调整参数 → 再来一轮。万亿次循环后,AI 才学会了对话和推理。
Loop 包含三件事(三个要素):
| 要素 | 问题 | 缺了会怎样 |
|---|---|---|
| 1️⃣ 从哪里开始 | 初始状态是什么? | 跑不起来 |
| 2️⃣ 重复做什么 | 每轮干什么活? | 没有意义 |
| 3️⃣ 什么时候停 | 满足什么条件退出? | 死循环,跑崩为止 |
但有意思的是:我们用 AI 的方式,却几乎没人用循环。 我们把最擅长干重复活的 AI,用成了"一次性工具"。这就像请了个世界级大厨,却只让他给你煮泡面——还每次都得你亲自告诉他"水开了没、面软了没"。
二、99% 的人正在用的"旧模式":人在环内 👤
回想一下你平时怎么用 AI:
打开 ChatGPT / Claude
→ 写一段 Prompt → 看结果 → 不满意?→ 手动改 Prompt → 再发一次 → ……直到你觉得"算了就这样吧"
我们把工作丢给了 AI,但自己是那个推动循环的引擎——没有你的判断和修改,AI 一步就停了。这就是 人在环内(Human in the Loop)。
| 你做的事 | AI 做的事 |
|---|---|
| ✍️ 写 Prompt | 生成一个结果 |
| 👀 判断好不好 | 等你下指令 |
| 🔧 修改 Prompt | 生成下一个结果 |
| 🔄 再判断 | 再等... |
这个模式的问题在哪?你把最宝贵的精力花在了重复劳动上。 更亏的是,AI 其实完全有能力自己判断、自己修正——我们却把它当成了"指一步动一步"的提线木偶。
三、翻转思路:人在环外 🚀
把上面那张表翻转过来:别让人当循环引擎,让 AI 自己闭环。
生成 → 检查 → 没通过?再生成 → 再检查 → …… → 通过,退出
你提前做好三件事,然后就可以走开:
| 你做的事 | 对应代码 | 大白话 |
|---|---|---|
| 📋 告诉 AI 你要什么 | task.desc | 目标(写一篇小红书文案) |
| 📏 告诉 AI 怎么算合格 | task.rules | 规则(标题带数字、正文<300字、有行动号召) |
| 🛡️ 设定安全边界 | limit | 最多试几次、最多花多少钱 |
| 以前(人在环内) | 现在(人在环外) | |
|---|---|---|
| 执行者 | AI 干一步就停 | AI 循环干到底 |
| 判断者 | 你手动看 | AI 自己检查 |
| 你做什么 | 反复改 Prompt | 一次性定目标、定规则 |
| 循环引擎 | 你 | AI |
四、用一个生活例子秒懂 🌰
想象你是一个新店长,要训练客服回复话术。
旧模式:你亲自盯每个客服,每回复一条消息,你看看合不合格,不合格就让他重写。一天下来你嗓子哑了,手边还攒了 200 条未读。
新模式:你写一份《客服回复手册》,里面写清楚"语气要亲切、不能超 100 字、结尾必须有解决方案"。然后把手册发给客服,告诉他:"每条消息按手册自查,不合格就自己改,改到符合手册为止才提交。" 你只需要抽查最终结果。你从"监工"变成了"规则制定者"。
AI Loop 做的就是这件事——只不过那个"客服"是 AI,那个"手册"是 task.rules。
五、不到 100 行的完整示例(可直接运行)📁
5.1 文件结构
loop-demo/
├── .env ← 放你的密钥(不提交 git)
├── package.json
└── main.mjs ← 全部代码,不到 100 行
// package.json
{
"dependencies": {
"openai": "^6.44.0",
"dotenv": "^17.4.2"
}
}
5.2 环境变量
# .env
DEEPSEEK_API_KEY=你的key
DEEPSEEK_BASE_URL=https://api.deepseek.com
六、逐行拆解:Loop 三要素在代码里长什么样 👨💻
整个程序的核心是一个 runLoop() 函数。先看整体调用关系:
runLoop() ← 入口
│
┌─────────────┼─────────────┐
│ │ │
task limit needStop() ← 要素一、三:目标+刹车
(从哪开始) (什么时候停)
│
┌─────┴─────┐
│ │
gen() check() ← 要素二:重复做什么(生成+校验)
(生成) (打分)
│ │
└─────┬─────┘
│
while 循环
要素一:从哪里开始?定义任务目标和规则 📝
import { OpenAI } from 'openai'
import dotenv from 'dotenv'
dotenv.config();
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: process.env.DEEPSEEK_BASE_URL,
})
// 👇 这就是要素一:告诉 AI 要什么 + 怎么算合格
const task = {
desc: "小红书美妆文案",
rules: [
"标题要带上数字",
"正文<300字",
"结尾有行动号召"
]
}
desc 是方向,rules 是尺子。两者分开的好处是:后面 gen() 和 check() 都从这个对象读数据,改任务只需要改这一个地方。rules 用数组存,后面用 join("、") 自动拼成自然语言塞进 Prompt。
要素二:重复做什么?gen() + check() 双函数 ⚙️
// 干活:调用 AI 生成文案
async function gen() {
const res = await client.chat.completions.create({
model: "deepseek-chat", // 可换成你的模型
messages: [{
role: "user",
content: `假如你是一位资深小红书美妆博主,
写一篇${task.desc},严格遵守${task.rules.join("、")}。
【输出格式要求】
第一行必须是:标题:xxx
正文从第二行开始
结尾单独一行,用emoji引导行动号召
只输出文案,不要多余的解释`
}]
})
const text = res.choices[0].message.content;
console.log(`生成token数:${res.usage.total_tokens}\n${text}`);
return { text, token: res.usage.total_tokens };
}
⚠️ 注意 1:输出格式乱变
每次运行 AI 输出格式可能不一样——有时【标题】xxx,有时标题:xxx,有时干脆没"标题"二字。上面的【输出格式要求】就是为了锁死格式,防止 check 解析失败。如果发现格式还是乱,可以进一步收紧 prompt,比如加一句"违反格式直接判定为不合格"。
// 裁判:调用 AI 检查文案是否达标
async function check(text) {
const res = await client.chat.completions.create({
model: "deepseek-chat",
messages: [{
role: "user",
content: `校验这篇文案:${text}
对照规则:${task.rules.join("、")}
仅输出JSON,格式:{"pass":true,"fail":[]}
不要输出其他任何内容`
}]
})
return JSON.parse(res.choices[0].message.content.trim());
}
⚠️ 注意 2:gen 里的规则只是"提示",不是"强制"
gen()的 prompt 里写了严格遵守${task.rules.join("、")},但这只是"告诉 AI 规则",AI 可能嘴上答应实际上产出违规内容——所以才需要check()再验一遍。gen 里的规则是提示,check 才是守门员。 别以为 gen 写了规则就可以省掉 check。
⚠️ 注意 3:JSON.parse 可能因多余字符报错
AI 返回的 JSON 前后可能带空格或换行,上面用.trim()处理了。但如果 AI 在 JSON 外面包了 markdown 代码块,.trim()也救不了。更健壮的做法见下方「拓展优化建议」。
要素二 = gen + check 双函数,每轮循环跑一次。gen 产出,check 打分——AI 自己当选手又当裁判。
check 返回的 JSON 长这样:
{"pass": false, "fail": ["标题没有数字", "正文超过300字"]}
// 或
{"pass": true, "fail": []}
要素三:什么时候停?三道安全刹车线 🛑
// 👇 刹车配置 —— 三道防线
const limit = { maxRound: 5, maxToken: 2000, sameStep: 2 };
// 计数器 —— 追踪当前状态
let round = 0, totalToken = 0, lastText = "", sameCount = 0;
// 👇 刹车判断 —— 任一触发就停
function needStop() {
return round >= limit.maxRound // 防线1:轮数耗尽
|| totalToken >= limit.maxToken // 防线2:预算花光
|| sameCount >= limit.sameStep; // 防线3:AI 卡死(连续输出相同内容)
}
async function runLoop() {
console.log(`🚀 AI Loop 开始`);
while (!needStop()) {
round++;
console.log(`\n📌 第${round}轮`);
const { text, token } = await gen(); // 1. 干活
totalToken += token;
sameCount = text === lastText ? sameCount + 1 : 0;
lastText = text;
const { pass, fail } = await check(text); // 2. 检查
if (pass) {
console.log(`✅ 全部规则通过,循环结束 🎉`);
console.log(`📄 最终文案:\n${text}`);
return; // 达标!愉快退出
}
console.log(`❌ 不满足规则:${fail.join("、")}`); // 不通过,进入下一轮
}
console.log(`\n⛔ 触发刹车强制停止,最后一次内容:${lastText}`);
}
runLoop(); // ← 程序从这里启动
要素三 = 三道刹车线:
| 刹车线 | 防什么 | 大白话 |
|---|---|---|
maxRound: 5 | 死循环 | "试了 5 次还不对?放弃" |
maxToken: 2000 | 超预算 | "花太多钱了,停" |
sameStep: 2 | AI 卡死 | "连续 2 次输出一样?它在糊弄" |
sameStep 的计数逻辑:一旦 text 和 lastText 不同就归零,必须是连续相同才刹车——偶尔一次重复不算。
| 轮次 | lastText | 本次text | 判断 | sameCount |
|---|---|---|---|---|
| 1 | "" | "文案A" | 不同 | 0 |
| 2 | "文案A" | "文案A" | 相同 | 1 |
| 3 | "文案A" | "文案A" | 相同 | 2 → 刹车 |
七、实际跑起来长什么样?🎬
最理想——一次通过:
🚀 AI Loop 开始
📌 第1轮
生成token数:320
标题:3步搞定夏日不脱妆!油皮亲妈底妆大法🔥
正文:夏天到了……
结尾:👉 评论区告诉我你的肤质,我来帮你选!
✅ 全部规则通过,循环结束 🎉
最终文案:……
需要多轮修正:
📌 第1轮
标题:超好用底妆大法(缺少数字)
❌ 不满足规则:标题没有数字、正文超过300字
📌 第2轮
标题:3步搞定夏日底妆...
✅ 全部规则通过,循环结束 🎉
第一轮被打回,第二轮自动修正——全程不用人插手。
八、拓展优化建议 🔧
上面这个 Demo 能跑通,但离"生产可用"还差几步。以下是三个常见的优化方向:
优化 1:check() 返回的 JSON 被包在 Markdown 代码块里
AI 有时候不听话,虽然 prompt 说了"仅输出JSON,不要输出其他任何内容",它偶尔还是会返回:
当然可以,以下是校验结果:
```json
{"pass": true, "fail": []}
`.trim()` 也救不了,`JSON.parse` 直接炸。
**解决:** 用正则把 JSON 从返回内容里抠出来:
```js
async function check(text) {
const res = await client.chat.completions.create({
model: "deepseek-chat",
messages: [{ role: "user", content: `校验这篇文案:${text}...` }]
})
const raw = res.choices[0].message.content;
const match = raw.match(/\{[\s\S]*\}/); // 匹配第一个 { 到最后一个 }
if (!match) throw new Error("check 返回内容中没有找到 JSON");
return JSON.parse(match[0].trim());
}
优化 2:API 调用没有重试,网络波动直接崩
gen() 和 check() 里 await client.chat.completions.create(...) 都没包 try-catch,万一 DeepSeek 瞬时限流或网络抖一下,整个程序就挂了。
解决: 加个简单的重试:
async function gen() {
for (let i = 0; i < 3; i++) {
try {
const res = await client.chat.completions.create({...});
return { text: res.choices[0].message.content, token: res.usage.total_tokens };
} catch (e) {
if (i === 2) throw e; // 3次都失败就真挂了
console.log(`gen 第${i + 1}次失败,1秒后重试...`);
await new Promise(r => setTimeout(r, 1000));
}
}
}
check() 同理加上重试逻辑。
优化 3:check() 太贵了——每轮都要调用一次 AI
目前的实现里,每生成一次就要调用一次 check,相当于每一轮花两份 token 的钱(gen 一份 + check 一份)。对简单任务来说,这个成本可能翻倍。
解决思路 A:规则优先用程序校验
能用代码判断的规则就别交给 AI。比如:
- "正文<300字" →
text.length < 300 - "标题要带上数字" →
/\d/.test(title)
只有程序判不了的主观规则(如"大爆款"、"语气亲切")才交给 AI 去 check。
async function check(text) {
const fails = [];
// 程序校验
if (text.length > 300) fails.push("正文超过300字");
// ... 其他可编程规则
// 只有程序判不了的才调 AI
if (需要AI判断的规则.length > 0) {
const aiResult = await aiCheck(text);
fails.push(...aiResult.fail);
}
return { pass: fails.length === 0, fail: fails };
}
解决思路 B:check() 精简 prompt
把 check 的 prompt 压到最短,用更少的 token。比如用英文或缩写:
Validate this text against rules. Output JSON: {"pass":bool,"fail":[]}. Rules: ...
解决思路 C:放宽 check 频率
不是每一轮都 check,而是每 2 轮或每 3 轮 check 一次。缺点是可能浪费几轮在错误方向上——适合 gen 本身就比较稳定、只需要最终把关的场景。
九、这个模式还能用在哪儿?🔧
任何 "生成 → 校验 → 重来" 的任务都能套用:
| 场景 | gen(生成) | check(校验) |
|---|---|---|
| 💻 写代码 | AI 写功能代码 | 跑单元测试 |
| 🌐 翻译 | 翻译英文 | 回译检查 + 语法检查 |
| 📊 写周报 | 生成草稿 | 检查字数、格式、指标 |
| ➗ 数学题 | 给出解答 | 验算答案 |
| 💬 客服回复 | 生成话术 | 检查语气和合规 |
三步定制你自己的 AI Loop:
// 只改这两个对象 + gen 里的 prompt,其他代码不动
const task = { desc: "你的目标", rules: ["规则1", "规则2", "规则3"] };
const limit = { maxRound: 5, maxToken: 2000, sameStep: 2 };
- ✏️ 改
task—— 写清楚目标 + 合格规则 - 💰 改
limit—— 给预算,别让 AI 跑飞 - 🎭 改
gen()里的 Prompt —— 换角色和场景
其他代码基本不用动。
十、核心思想:你从"操作者"变成"设计者" 🧠
| 维度 | 旧模式(人在环内) | 新模式(人在环外) |
|---|---|---|
| 你的工作 | 反复改 Prompt、盯结果 | 一次性定目标、定规则 |
| AI 行为 | 干一步就停 | 循环干到底 |
| 你消耗的 | 精力 | token(预算可控) |
以前你写 Prompt 是在"告诉 AI 怎么做",现在你设计的是一个自动达标系统——告诉 AI 要什么、什么算好,然后让它自己跟自己较劲。
关键不是 AI 有多强,而是你设计的这个闭环有多聪明。
🎯 行动起来
今天就可以试试:
- 打开终端,复制上面的代码,跑一次感受流程
- 把你日常一个重复性 AI 任务(写周报、翻译、代码审查)改造成 Loop
- 在评论区分享:你打算用 AI Loop 改造哪个场景?