智能体自主闭环:从单次问答到多步迭代的工程实践

发布时间:2026/9/7 9:36:32
智能体自主闭环:从单次问答到多步迭代的工程实践 在实际的智能体项目里最难的部分往往不是让模型生成一次内容而是让智能体根据目标持续判断“当前结果是否足够好不够好该怎么改改完以后是否真的变好了”。这就是自主驱动的 AI 闭环系统要解决的核心问题把一次问答变成多步迭代把“生成后不管”变成“生成、评估、改进、再验证”的循环工程。本文从闭环系统的组成讲起给出一个可运行的最小 Python 示例再讨论参数设计、状态管理、效果评估和线上排查方式帮助读者建立一套能落地的智能体闭环开发思路。1. 从一次问答到自动迭代智能体闭环系统的核心矛盾1.1 单次调用模型不等于智能体很多人第一次接触智能体时会误以为“接入一个大模型 API 就是智能体”。从工程角度看单次调用模型只是完成了一次文本生成它没有目标检查没有过程记忆也没有失败恢复能力。比如让模型“写一份测试用例”模型能写出内容但它不会主动检查用例是否覆盖了所有需求也不会因为漏了一条边界条件就去修改自己的输出。智能体的关键差异在于它能围绕一个目标反复执行“生成结果、判断结果、根据判断修正”的过程。这个过程不是一次性请求而是一个有状态的循环。每一次循环都产生新的信息这些信息又成为下一次决策的依据。1.2 闭环系统的四个环节感知、规划、执行、反馈一个自主驱动的 AI 闭环系统可以拆成四个环节感知收集当前任务信息、环境状态、用户输入、历史记录。规划根据目标拆解步骤决定下一步执行什么。执行调用模型、工具或代码产生一个中间结果。反馈用评价函数或人工规则检查结果是否达标并把差距信息送回规划环节。这四个环节不断循环直到结果满足终止条件或者预算耗尽。这里的“预算”可以指大模型调用次数、金额、时间、上下文长度也可以是安全限制和人工审批门槛。1.3 为什么“循环”本身是一种工程对象把循环当作工程对象意味着要回答几个问题循环什么时候停止一个误差信号如何进入下一轮如果循环退化了怎么发现如果某个环节产生了错误输入是继续循环还是立即兜底这些问题在静态提示词工程里不需要考虑因为每次请求相互独立。但进入智能体闭环后状态、参数、日志、评估和预算控制都必须纳入设计。否则“自主驱动”很容易退化成“失控循环”模型反复生成、反复推翻、成本越来越高最终结果却和第一版差不多。2. 自主驱动闭环的架构与关键设计2.1 目标、状态、动作、反馈四要素在设计闭环系统时建议先定义四个要素而不是先写代码。目标任务的最终评价标准。比如“生成一份覆盖全部需求且格式合法的测试用例”。状态当前智能体已经知道的信息包括用户输入、中间结果、历史反馈、剩余预算。动作每一步可以执行的操作例如生成草稿、调用搜索工具、查询数据库、请求人工确认。反馈对上一个动作结果的量化评价例如覆盖度分数、格式是否合法、是否包含幻觉内容。以下几个问题必须在实现前对齐目标是否可被程序判断还是必须靠模型打分状态放在内存、文件还是数据库动作列表是固定还是动态生成反馈是数值、文本还是结构化错误列表这四个问题直接决定闭环系统的复杂度和稳定性。2.2 反馈回路与终止条件反馈回路的目标不是“无限优化”而是“在有限资源内逼近可接受结果”。因此终止条件至少要有两个维度质量维度结果通过评估阈值例如分数不低于 85 分。资源维度达到最大循环次数、最大 token 数或最大耗时。两者必须同时存在。只保留质量维度可能出现死循环只保留资源维度可能第一轮就退出失去闭环意义。此外反馈要尽量结构化。让模型比较“上一版和这一版哪个更好”很有必要但更可靠的做法是提取结构化问题列表例如{ pass: false, score: 62, issues: [ {type: coverage, message: 缺少对空参数的测试场景}, {type: format, message: 步骤列表没有使用数字编号} ] }相比一段自然语言的评价结构化问题列表更容易被后续代码解析也更容易定位改进方向。2.3 自主驱动不等于无限循环护栏设计自主驱动的价值是减少人工介入但完全不设护栏在工程上不可行。生产环境至少要设置四类护栏循环护栏最多迭代次数、最大 token 数、最大耗时。权限护栏智能体只能调用被授权的工具外部接口需要白名单。内容护栏对输出做敏感词、脱敏和合规检查必要时请求人工确认。回滚护栏保留每一轮迭代历史异常时能回退到上一版或初始版本。不要把护栏设计成“出错时停下来”而是设计成“出错时有明确路径”记录原因、保留上下文、触发兜底策略。3. 最小可运行示例用 Python 实现一个自动改进闭环3.1 环境准备下面的示例用 Python 3.9 以上版本即可运行不需要外部大模型 API核心是展示闭环结构。建议在虚拟环境里操作mkdir agent-loop-demo cd agent-loop-demo python -m venv venv source venv/bin/activate示例只依赖 Python 标准库因此不需要安装额外包。如果希望后面替换成真实大模型再按实际 SDK 补充依赖比如openai、requests或企业内部 SDK。3.2 项目结构与核心代码目录结构保持简单agent-loop-demo/ ├── agent_loop.py └── README.mdagent_loop.py实现一个最小闭环任务是从用户需求中生成测试用例然后用评估函数检查覆盖度和格式如果未达标就把问题列表送回生成器修改后重新评估。from dataclasses import dataclass, field from typing import Callable, Optional dataclass class Task: requirement: str max_rounds: int 5 pass_score: float 80.0 dataclass class EvalResult: score: float pass_result: bool issues: list field(default_factorylist) class BaseGenerator: 生成器接口实际项目里可以替换成大模型调用。 def generate(self, requirement: str, previous_result: Optional[str], issues: Optional[list]) - str: raise NotImplementedError class SimpleGenerator(BaseGenerator): 模拟生成器根据反馈不断补充测试场景。 def generate(self, requirement: str, previous_result: Optional[str], issues: Optional[list]) - str: if previous_result is None: return f测试用例\n1. 验证{requirement}正常流程 lines [ f测试用例\n1. 验证{requirement}正常流程, ] for i, issue in enumerate(issues or []): lines.append(f{i 2}. 补充{issue}) return \n.join(lines) class Evaluator: 评估器检查用例是否覆盖关键词并且格式正确。 def evaluate(self, requirement: str, result: str) - EvalResult: score 0.0 issues [] if requirement in result: score 40 else: issues.append(没有在用例中提及核心需求) if 负数 in result or 空值 in result: score 30 else: issues.append(缺少边界值场景如空值、负数) if result.strip().startswith(测试用例) and \n1. in result: score 30 else: issues.append(用例格式不符合预期需要以数字编号列出) return EvalResult(scorescore, pass_resultscore 80.0, issuesissues) dataclass class LoopStats: rounds: int 0 final_score: float 0.0 history: list field(default_factorylist) def run_loop(task: Task, generator: BaseGenerator, evaluator: Evaluator) - LoopStats: stats LoopStats() result: Optional[str] None issues: Optional[list] None for round_index in range(1, task.max_rounds 1): print(f[Round {round_index}] 生成结果...) result generator.generate(task.requirement, result, issues) eval_result evaluator.evaluate(task.requirement, result) stats.rounds round_index stats.final_score eval_result.score stats.history.append({}) print(f[Round {round_index}] 当前分数: {eval_result.score}) print(result) print(---) if eval_result.pass_result: print(评估通过循环结束。) return stats issues eval_result.issues print(f未通过改进意见: {issues}) print(达到最大循环次数使用当前最优结果。) return stats if __name__ __main__: task Task( requirement用户提现金额校验, max_rounds5, pass_score80.0, ) generator SimpleGenerator() evaluator Evaluator() stats run_loop(task, generator, evaluator) print(f实际循环轮数: {stats.rounds}) print(f最终分数: {stats.final_score})这段代码实现了“生成 - 评估 - 反馈 - 再生成”的闭环。Evaluator是纯代码规则因此结果可复现适合学习闭环结构。实际项目中评估器可能是模型打分、规则检查、单元测试结果、用户反馈或多指标加权。3.3 运行验证与输出运行示例python agent_loop.py预期输出类似[Round 1] 生成结果... [Round 1] 当前分数: 40 测试用例 1. 验证用户提现金额校验正常流程 --- 未通过改进意见: [缺少边界值场景如空值、负数, 用例格式不符合预期需要以数字编号列出] [Round 2] 生成结果... [Round 2] 当前分数: 70 测试用例 1. 验证用户提现金额校验正常流程 2. 补充缺少边界值场景如空值、负数 3. 补充用例格式不符合预期需要以数字编号列出 --- 未通过改进意见: [缺少边界值场景如空值、负数] [Round 3] 生成结果... [Round 3] 当前分数: 70 ...这个输出说明两件事第一闭环确实在根据反馈迭代第二如果生成器只知道“把问题列表塞回去”可能导致问题修复不彻底甚至重复出现。这种情况在真实项目中同样常见是后续要优化的重点。3.4 把模拟模型替换成真实模型真实项目中BaseGenerator可以替换成大模型调用。下面是一个示意结构不绑定具体厂商 SDKimport os class LLMGenerator(BaseGenerator): def __init__(self, model: str): self.model model def generate(self, requirement: str, previous_result: Optional[str], issues: Optional[list]) - str: if previous_result is None: prompt f你是测试工程师。请针对需求生成测试用例{requirement} else: prompt ( f需求{requirement}\n f上一版用例\n{previous_result}\n f评审意见\n{issues}\n 请根据评审意见修改用例保留正确的部分只补充缺失场景。 ) # 这里替换成真实的大模型请求函数 return call_llm(self.model, prompt) def call_llm(model: str, prompt: str) - str: # 在实际项目中这里调用选定的模型服务。 # 注意控制超时、重试和 token 上限。 response os.environ.get(FAKE_LLM_RESPONSE, 模拟返回结果) return response替换真实模型后最需要注意的是提示词结构。不要把上一版结果和评审意见混在一起而要让模型明确知道“哪些内容保持不变哪些内容必须修改”。否则模型可能把整篇内容重写导致评估分数震荡。4. 参数设计与状态管理避免闭环失控4.1 反馈信号如何量化反馈信号是整个闭环的“方向盘”。如果反馈信号不准循环再多轮也是白费。常见做法是组合三类信号规则信号基于代码检查结果例如格式、字段完整性、是否包含关键词。模型信号让大模型作为评审者输出分数和结构化问题。任务信号来自真实执行结果例如接口测试是否通过、代码编译是否成功、用户点击率是否提升。建议优先用规则和任务信号兜底模型信号作为辅助。因为模型评审可能不稳定同一条输出在不同的 temperature 设置下评分差异很大。4.2 循环参数速查以下是闭环系统常用参数的参考说明参数含义默认值参考调小的影响调大的影响max_rounds最大迭代轮数3 到 5成本低但可能未达标就退出更可能达标但成本和时间上升pass_score评估通过阈值80更容易通过质量可能不足更难通过需要更多轮次temperature生成随机性0.2 到 0.7更稳定但可能缺乏变化更多样但可能偏离目标max_tokens单轮生成上限随任务调整降低成本可能截断结果结果更完整成本更高timeout单次模型调用超时30 到 60 秒快速失败但复杂任务易超时更容错但故障感知变慢eval_interval评估频率每轮评估响应更快成本高评估少可能浪费多轮这些参数不应该是静态写死的。线上环境建议做成动态配置至少能在不改代码的情况下调整最大轮数和通过阈值。4.3 状态持久化与可观测性闭环系统的状态比普通 API 请求复杂。普通接口只需要记录一次请求和响应闭环系统需要记录每一轮的关键信息轮次编号输入提示词结构生成结果评估分数与问题列表当前累计 token 和费用是否触发人工确认日志建议采用结构化 JSON方便后续查询和分析{ trace_id: req_20250101_001, round: 2, action: generate, score: 70, issues_count: 1, cost_yuan: 0.012, status: retry }生产环境不要只记录最终结果。没有过程日志线上出问题时很难判断是哪一轮引入的错误。5. 闭环效果怎么评估5.1 过程指标与结果指标评估一个自主驱动闭环系统不能只看最终分数。还需要看过程指标平均迭代轮数轮数越高说明初始质量越差或反馈信号不明确。收敛速度从第一轮到分数稳定中间需要几轮。分数震荡如果分数在 40、80、50 之间波动说明反馈没有真正驱动改进。成本指标总 token 数、总调用次数、单任务成本。结果指标则包括最终通过率、达到阈值所需时间、人工介入频率、用户满意度。5.2 评估集与人工抽检闭环系统很容易出现“自我感觉良好”的情况即模型生成的评审意见和生成器配合默契但真实任务表现并不好。因此必须准备离线评估集。每个评估样本包含用户原始需求标准答案或关键覆盖点允许的格式约束通过阈值每次修改提示词或评估函数后都用同一套评估集跑一遍对比通过率和成本。如果通过率下降或成本翻倍就要谨慎上线。人工抽检不能省。即使系统能自动评估也要保留抽检机制特别是涉及对外输出、财务、医疗等高风险场景。5.3 学习、测试、生产环境的差异学习环境可以用模拟模型控制循环轮数重点理解机制。测试环境接真实模型但使用小模型或 mock 接口先验证闭环逻辑和参数配置。生产环境必须加入预算告警、超时兜底、日志采样、失败重试、人工审批和版本回滚。下面用一个表格概括维度学习环境测试环境生产环境模型模拟模型真实模型但限额真实模型 多路兜底循环轮数固定 3 到 5固定上限动态配置 告警评估方式规则规则 模型评审规则 模型 任务结果日志控制台打印结构化日志日志平台 监控告警成本控制不敏感关注成本每日预算和单任务预算人工介入不需要按需高风险操作必须介入6. 常见问题与排查链路6.1 现象、原因、检查方式、处理建议速查表问题现象常见原因检查方式处理建议总是循环到最大轮数才退出评估阈值过高或反馈不明确查看每轮分数和问题列表调整阈值或精简评审意见分数来回震荡生成器随机性过大固定 seed、降低 temperature引入历史最优结果保护问题修复不彻底提示词没有区分“保留”和“修改”检查输入给模型的提示词明确要求只修改问题对应部分成本快速上升没有设置单任务预算检查 token 和调用次数添加 max_rounds、max_tokens 等参数线上结果和离线评估差异大线上输入分布与评估集不一致抽样对比线上日志扩展评估集覆盖线上场景模型评审评分不稳定温度过高多次调用观察方差降低温度或改成规则评估6.2 三个容易踩的坑第一个坑是“反馈信息太模糊”。如果评估器只输出“结果不够好”生成器很难知道如何修改。解决办法是让反馈变成结构化问题列表至少要说明哪个环节不达标。第二个坑是“没有历史最优保护”。生成器在某一轮可能把原本 90 分的结果改成 70 分。如果没有保存上一版系统就会丢失更优结果。推荐做法是每一轮评估后如果当前分数高于历史最优则更新最优结果循环结束时返回历史最优而不是最后一轮。第三个坑是“把人工审批做成系统瓶颈”。如果每个任务都请求人工确认闭环会变得低效。建议按风险分级低风险任务自动放行高风险任务人工确认并规定等待超时后的默认动作。6.3 线上闭环异常的排查顺序线上排查闭环问题建议按“任务上下文 - 循环过程 - 评估规则 - 模型输出 - 成本告警”的顺序进行先看任务上下文是否正常用户输入、目标、参数。再查过程日志每一轮的分数、问题列表、触发条件。然后检查评估规则是否是规则 bug 导致误判。再抽样看模型原始输出和提示词。最后确认成本、超时和失败重试是否触发。不要一上来就怀疑模型本身。很多闭环异常都是评估规则和参数配置导致的。7. 可落地的实践清单与扩展方向7.1 发布前检查清单在把一个自主驱动闭环系统发布到生产环境前建议逐项检查是否设置了最大循环轮数、最大 token 数、最大耗时是否有单任务成本预算和全局日预算告警是否存在历史最优结果保护评估器是否同时包含规则信号和模型信号每一轮日志是否包含结构化状态记录高风险操作是否有人工确认路径异常退出时是否有兜底返回策略模型调用是否有超时、重试和熔断是否准备离线评估集和回归对比流程是否确认过“自主驱动”的权限边界智能体只能访问授权工具7.2 下一步扩展方向闭环系统的扩展方向很多常见的有多智能体协作一个智能体负责生成另一个负责评审第三个负责执行和验证。工具接入把搜索、数据库查询、代码执行、文件读写作为可执行动作让“反馈”来自真实结果。长期记忆把多轮任务的状态存入向量库或关系表让智能体可以跨会话使用历史经验。人类反馈强化在闭环中引入人工打分信号持续优化生成策略和评估策略。可解释审计为每一轮决策保留理由字段让用户在结果页看到“为什么这么改”。对新手来说最值得练习的不是接入复杂框架而是先用几十行代码把自己的业务任务实现成“生成 - 评估 - 修正”循环再逐步增加护栏、日志和多轮记忆。能把这个循环跑稳再去研究多智能体和复杂编排才有足够的调试基础。