96SEO 2026-04-24 02:15 1
在hen多项目里小王常常会抱怨:“它Neng跑通,但结果时好时坏。尤其是写代码、方案、时第一版总是差强人意。”这句话恰如一面镜子,映射出当前 LLM‑Agent 的Zui大短板——缺少“反思”和“再加工”。本文将从零搭建一个Neng够主动审查、纠错、优化的 ReflectionAgent,帮助你把“Neng跑”提升为“高质量”。

传统的 ReAct框架往往遵循「收到任务 → 直接生成答案 → 完事」的直线流程。虽然这种模式在简单查询上表现不错,却在需要严谨推理或代码生成的场景里频繁出现「答案半成品」的尴尬。
人类处理复杂任务时并非一次成稿,而是:
先写草稿;
审视自己的表达是否符合需求;
根据发现的问题进行修改;
循环往复直至满意。
把这套「先Zuo,再审,再改」的闭环移植到 LLM 中,就是我们所说的「自我迭代」或「Reflection」。有了它,Agent Neng在生成答案后主动检查是否漏掉关键细节、是否存在逻辑漏洞,从而实现持续提升。
二、整体结构一览reflection-agent-demo/
├── package.json
├── tsconfig.json
├── .env
└── src/
├── shared/
│ └── llm.ts
├── reflection/
│ ├── memory.ts
│ ├── prompts.ts
│ └── agent.ts
└── index.ts
下面我们一步步拆解每个文件的作用,并配合实际代码演示。
1️⃣ package.json – 项目入口配置{
"name": "reflection-agent-demo",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc"
},
"dependencies": {
"dotenv": "^16.4.5",
"openai": "^4.27.0"
},
"devDependencies": {
"@types/node": "^20.12.5",
"ts-node": "^10.9.2",
"typescript": "^5.4.2"
}
}
把依赖装好后执行 npm install 即可。
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"moduleResolution": "node",
"lib": ,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"types":
},
"include": ,
"exclude":
}
3️⃣ .env – 环境变量保密入口
LLM_API_KEY="在这里填入你的 OpenAI Key"
LLM_MODEL_ID="gpt-4o-mini"
LLM_BASE_URL="https://api.openai.com/v1"
三、共享层:封装一次性调用的 LLM 客户端
/src/shared/llm.ts
// src/shared/llm.ts
import 'dotenv/config';
import OpenAI from 'openai';
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions';
export interface LLMOptions {
model?: string;
apiKey?: string;
baseUrl?: string;
timeout?: number;
}
export class HelloAgentsLLM {
private readonly client: OpenAI;
private readonly model: string;
constructor {
const apiKey = opts.apiKey ?? process.env.LLM_API_KEY;
const baseUrl = opts.baseUrl ?? process.env.LLM_BASE_URL;
if {
throw new Error;
}
this.model = opts.model ?? process.env.LLM_MODEL_ID ?? 'gpt-4o-mini';
this.client = new OpenAI({
apiKey,
baseURL: baseUrl,
timeout: opts.timeout ?? 60_000,
});
}
async think: Promise {
const resp = await this.client.chat.completions.create({
model: this.model,
messages,
temperature,
});
return resp?.choices?.?.message?.content ?? '';
}
}
这样,无论是执行任务还是进行反思,dou只需要调用 HelloAgentsLLM.think 一句。
flowchart LR
E --> R
R --> F
F --> R
R --> D
Execution阶段: Agent 接收到用户指令后用 LLM 给出第一版答案。
Reflection阶段: 把刚才得到的内容当作新输入,询问模型 “这段回答有没有遗漏关键点?”、“逻辑是否连贯?”等,引导模型自评。
Refinement阶段: 根据自评返回的信息,对原始答案进行二次编辑或补充,然后回到审查环节,如此循环直至满足预设标准。
B) 如何让模型自己发现问题?提示工程技巧
PROMPT TEMPLATE #1 – 检查清单:
请对以下回答进行逐项核对:
1️⃣ 是否完整覆盖用户需求?
2️⃣ 是否出现事实错误或代码语法错误?
3️⃣ 表达是否简洁且易懂?
请用 “✅ 完整 / ❌ 缺失” 的格式列出检查结果,并给出对应修改建议。
text
{answer}
返回时仅包含检查表,不要额外解释。
PROMPT TEMPLATE #2 – 自然语言修正:
基于上面的检查结果,请重新组织答案,使其满足所有 ✅ 项,并解决 ❌ 项。保持原有结构,只在必要处添加或删减文字。
text
{answer}
返回完整文本。
以上两段提示Ke以分别放进「审查」与「改进」两个子函数中,实现全自动循环。
五、动手写一个具备自我迭代Neng力的 Agent 创建内存模块 – 用来保存历史交互// src/reflection/memory.ts
export interface MemoryItem {
role: 'user' | 'assistant';
content: string;
}
export class SimpleMemory {
private history: MemoryItem = ;
add { this.history.push; }
getAll: MemoryItem { return ; }
clear { this.history = ; }
}
编写 Prompt 集合
// src/reflection/prompts.ts
export const CHECK_PROMPT = => `
请对以下内容进行完整性与正确性检查,用 ✅ / ❌ 标记,并给出简短修改建议。
${answer}
`;
export const REWRITE_PROMPT = => `
依据以下检查反馈,对原文进行相应修改,使其全部通过 ✅。
原文:
${answer}
反馈:
${feedback}
`;
核心 Agent 实现
启动入口// src/reflection/agent.ts import { HelloAgentsLLM } from '../shared/llm'; import { SimpleMemory } from './memory'; import { CHECK_PROMPT, REWRITE_PROMPT } from './prompts'; export class ReflectionAgent { private llm = new HelloAgentsLLM; private memory = new SimpleMemory; async run: Promise { // 第一步:首次生成答案 let answer = await this.llm.think(); // 将初稿写入记忆,以便后续参考 this.memory.add; // 循环次数上限防止无限卡死 for { // 第二步:自检 const checkPrompt = CHECK_PROMPT; const feedback = await this.llm.think(); // 若全部 ✅ 则直接返回结果 if ) break; // 第三步:根据反馈重写 const rewritePrompt = REWRITE_PROMPT; answer = await this.llm.think(); // geng新记忆供下轮使用 this.memory.add; } return answer; } }
// src/index.ts
import { ReflectionAgent } from './reflection/agent';
=> {
const agent = new ReflectionAgent;
// 示例任务:实现一个高效素数检测函数
const taskDesc = `请用 TypeScript 写一个 O 的 isPrime:boolean 函数,并附带使用示例。`;
console.log;
const result = await agent.run;
console.log;
console.log;
});
运行
设置合理阈值: Ru果模型总是返回 “❌ 部分缺失”,Ke以适当放宽检查标准或者增大temperature 参数,让它geng具创造性。 SFT 数据辅助: 将几轮成功迭代后的对话保存下来用来微调专属模型,会显著提升收敛速度。 A/B 对比实验: 分别记录不加反思和加反思两条路径的耗时与错误率,以量化收益。实际项目中,我曾kan到错误率从 15% 降至 ≈ 4%。 日志噪声: 每轮循环打印简短摘要,如 “第 2 轮:检测到变量未声明”,既帮助定位问题,也让调试过程geng有人情味。 #TODO 标记: Ru果某轮仍未通过可在返回文本中加入 “#TODO” 注释,下一次循环自动聚焦该点。 CACHE 策略: 对相同任务使用Yi缓存的历史反馈,可大幅减少 API 调用次数,成本geng友好。
六、实战经验与调优技巧 🚀
| 问题描述 | 推荐处理方式 |
|---|---|
| - 循环次数过多导致费用飙升 | - 在 agent.run 中加入Zui大迭代次数限制;若仍未收敛,将任务拆分成子任务再尝试。 |
| - 检查提示经常返回空白 | - 确认 PROMPT 中占位符Yi被正确替换;使用 triple‑backticks 包裹原文以防 Markdown 截断。|
| - 模型自行产生无关废话 | - 在 system 消息里明确要求 “只返回检查表或修改后的代码,不要额外解释”。 | .
| - 内存泄漏导致历史记录过大 | - 每次完成一次完整任务后调用 memory.clear;也Ke以设置只保留Zui近两轮记录。 | .