在实际 AI 应用开发中,很多开发者会遇到一个困惑:我写好了提示词,但 AI 的输出总是不稳定,或者无法完成多步骤的复杂任务。于是,大家开始接触“循环工程”、“工作流”和“AI Agent”这些概念。它们看起来都和“提示词工程”有关,但又似乎在做不同层面的事情。有人甚至开始讨论“Prompt Engineering 已死”,认为未来是 Agent 和工作流的天下。
这种讨论背后,其实是对 AI 应用开发范式演进的不同理解。提示词工程是让单次 AI 调用更精准,而循环工程、工作流和 AI Agent 则是在解决如何将多个 AI 调用(或 AI 与工具调用)组织起来,以完成更复杂、更动态的任务。它们不是替代关系,而是不同抽象层级、不同职责范围的协作关系。理解这层关系,对于设计稳定、可靠且可维护的 AI 应用至关重要。
本文将从一线开发者的视角,为你梳理提示词工程、循环工程、工作流和 AI Agent 的核心概念、相互关系及其底层逻辑。我们会先厘清每个术语解决的具体问题,然后通过一个从简单到复杂的案例演进,展示它们如何协同工作。最后,我们会探讨在实际项目中,如何根据任务复杂度选择合适的架构模式,并给出具体的工程实践建议。
1. 核心概念辨析:从静态指令到动态系统
在深入技术实现之前,我们必须先统一对几个关键术语的理解。混淆这些概念是导致设计混乱的根源。
1.1 提示词工程:优化单次交互的“输入设计”
提示词工程的核心目标是:通过精心设计输入文本,引导大语言模型生成更符合预期的输出。它关注的是单次请求-响应的质量。
- 通俗理解:就像向一个知识渊博但有点“死脑筋”的专家提问。问得模糊,他答得也模糊;问得具体、有上下文、有格式要求,他才能给出你想要的答案。
- 技术定义:一套设计、测试和优化自然语言提示的方法论,旨在提高大语言模型在特定任务上的性能、可靠性和可控性。这包括角色设定、上下文提供、步骤分解、输出格式约束等技巧。
- 作用场景:翻译、总结、分类、代码生成、问答等所有单轮或上下文有限的对话任务。
- 最小示例:
# 差的提示词 prompt = "写一首诗。" # 经过提示词工程优化的提示词 optimized_prompt = """ 你是一位擅长创作中国古典诗词的诗人。请以“秋思”为主题,创作一首七言绝句。 要求: 1. 符合平仄格律。 2. 意境深远,包含典型的秋季意象(如枫叶、大雁、明月等)。 3. 输出格式为:先给出诗题,然后是四句诗文,最后用白话文简要解释诗意。 """ - 常见误解:
- 提示词工程等于“咒语”:它不是魔法,而是基于对模型能力、训练数据和任务理解的系统性设计。好的提示词是清晰、具体、可执行的指令。
- 提示词越复杂越好:过于冗长或复杂的提示词可能超出模型的上下文窗口,或引入矛盾指令,反而降低效果。需要追求简洁与明确的平衡。
1.2 循环工程:为任务添加“反馈与迭代”机制
当单次提示无法保证结果正确或完整时,就需要引入循环。循环工程的核心是:基于模型的输出或外部反馈,自动或半自动地生成新的提示词,进行多轮调用,直至满足某个终止条件。
- 通俗理解:专家第一次给出的方案不完美,你根据他的方案和你的目标,提出更具体的问题或修改意见,让他继续完善,直到你满意为止。这个过程可以自动化。
- 技术定义:一种程序设计模式,其中大语言模型的输出被作为后续模型调用的输入(或输入的一部分),形成一个循环。循环的驱动逻辑可以是基于规则(如解析输出中的特定标记)、基于模型自身(如让模型判断任务是否完成),或基于外部验证(如代码编译、单元测试)。
- 作用场景:代码调试与迭代、长文本生成(如分章节写小说)、复杂问题求解(如 Chain-of-Thought)、需要外部验证的任务(如生成代码并运行)。
- 关键模式:
- 固定次数循环:例如,将一篇文章分成5段,循环调用模型生成每一段。
- 条件循环:例如,生成代码 -> 运行测试 -> 如果测试失败,则将错误信息作为新提示词的一部分,重新生成代码,直到测试通过或达到最大重试次数。
- 与提示词工程的关系:循环工程依赖于提示词工程。每一轮循环中的提示词都需要精心设计,以确保模型能理解当前上下文(包括历史输出和本轮目标)。
1.3 工作流:将复杂任务“流程化”与“可视化”
工作流是循环工程的一种更结构化、更可视化的表现形式。它强调将任务分解为多个定义明确的步骤(节点),并规定步骤之间的执行顺序和数据流向。
- 通俗理解:就像工厂的流水线,原材料(输入)经过A车间(步骤1)处理,变成半成品,再流到B车间(步骤2)加工,最后成为成品(输出)。每个车间做什么、接收什么、产出什么都是规定好的。
- 技术定义:一个由节点和有向边组成的图。节点代表一个处理单元(如调用LLM、执行Python函数、条件判断、调用API),边代表数据或控制流的传递方向。工作流引擎负责按既定逻辑调度节点执行。
- 作用场景:多步骤、多工具协作的固定流程。例如:用户输入需求 -> LLM分析需求并生成SQL -> 执行SQL查询数据库 -> LLM将查询结果总结成报告 -> 将报告通过邮件发送。
- 典型工具:Dify、Coze(扣子)、n8n、Camunda、Flowable、ComfyUI(图像生成领域)。这些工具提供了可视化界面来拖拽组装工作流。
- 与循环工程的关系:工作流是实现循环工程的一种强大工具。循环可以体现为工作流中的一个“循环”节点,或者通过条件分支和跳转来实现。工作流使得复杂的循环逻辑更易于设计、理解和维护。
1.4 AI Agent:具备“感知-决策-执行”循环的自主实体
AI Agent 是更高层次的抽象。一个 AI Agent拥有一个持续运行的“感知-决策-执行”循环,并且通常具备长期记忆、工具使用能力和明确的目标。
- 通俗理解:一个虚拟的“员工”或“助手”。你给它一个目标(如“管理我的日程”),它会自主地观察环境(读取新邮件、查看日历)、思考该做什么(判断是否有冲突会议)、使用工具(发送邮件、创建日历事件)去行动,并记住之前发生的事情,持续为你工作。
- 技术定义:一个能够感知环境、自主决策、执行动作以实现目标的软件实体。在LLM语境下,其核心通常是一个“大脑”(LLM),配合记忆模块、工具集(函数调用)和一个驱动其循环运行的控制机制(如 ReAct 框架)。
- 核心组件:
- 规划:分解目标,制定步骤。
- 记忆:短期记忆(上下文),长期记忆(向量数据库等)。
- 工具使用:调用外部API、执行代码、操作软件。
- 行动:执行规划好的步骤。
- 与工作流的关系:一个复杂的 AI Agent 内部,可能包含多个固定的工作流来执行标准化子任务。但 Agent 本身更强调自主性和适应性。工作流是预设的路径,而 Agent 可以根据环境变化动态调整其计划。你可以把工作流看作是 Agent 可以调用的一个“技能”或“子程序”。
为了更清晰地展示四者的关系和职责范围,可以参考下表:
| 概念 | 核心目标 | 抽象层级 | 关键特征 | 类比 |
|---|---|---|---|---|
| 提示词工程 | 优化单次LLM调用的输入输出质量。 | 最低(语句级) | 静态设计、上下文构造、格式约束。 | 向专家提问的“话术”。 |
| 循环工程 | 通过多轮LLM调用迭代逼近目标。 | 较低(会话级) | 反馈循环、条件判断、迭代优化。 | 与专家进行多轮“评审-修改”讨论。 |
| 工作流 | 将多步骤任务流程化、可视化、可靠化。 | 中高(流程级) | 节点化、有向图、数据流、可视化编排。 | 工厂的“标准化生产流水线”。 |
| AI Agent | 创建能自主感知、决策、执行以实现长期目标的实体。 | 最高(系统级) | 自主性、记忆、工具使用、目标导向、持续运行。 | 一位拥有工具和记忆的“虚拟员工”。 |
2. 从提示词到Agent:一个代码生成任务的演进案例
让我们通过一个具体的任务——“根据用户描述生成可运行的Python代码”——来演示如何从简单的提示词工程,逐步演进到引入循环、工作流,最终构建一个简单的AI Agent。
2.1 阶段一:基础提示词工程
最初,我们尝试用一次提示词解决问题。
目标:用户说“帮我写一个爬取某新闻网站头条新闻标题的Python脚本”,我们直接让LLM生成完整代码。
实现:
import openai def generate_code_with_prompt(user_request): prompt = f""" 你是一个资深的Python开发工程师。请根据用户需求,生成完整、可直接运行的Python代码。 用户需求:{user_request} 要求: 1. 代码必须包含必要的导入语句。 2. 代码必须包含详细的注释。 3. 输出只包含代码,不要有任何解释性文字。 """ response = openai.ChatCompletion.create( model="gpt-4", messages=[{"role": "user", "content": prompt}] ) return response.choices[0].message.content # 使用 user_request = "帮我写一个爬取某新闻网站头条新闻标题的Python脚本" code = generate_code_with_prompt(user_request) print(code)问题:
- 模糊性:“某新闻网站”是哪个?LLM可能会瞎猜或生成通用模板。
- 依赖缺失:生成的代码可能需要
requests,BeautifulSoup等库,但用户环境未必安装。 - 运行错误:生成的代码很可能因为网站结构变化、反爬策略等无法直接运行。
- 无验证:我们不知道代码是否真的能工作。
这个阶段,成败完全依赖于单次提示词的质量和LLM的“运气”,非常脆弱。
2.2 阶段二:引入循环工程(对话式澄清与迭代)
我们改进流程,加入与用户的交互(模拟)和多轮生成。
目标:先让LLM分析需求,主动询问模糊点,然后基于澄清后的需求生成代码,并尝试自动运行和修复。
实现(简化逻辑):
import subprocess import sys def clarify_and_generate(user_request): # 第一轮:分析需求,提出澄清问题 analysis_prompt = f""" 用户请求:{user_request} 你是一个AI助手。请分析这个请求,找出所有模糊、缺失或可能出错的点。 然后,生成一个清晰的、具体的问题来向用户澄清。 只输出你的澄清问题。 """ # ... 调用LLM获取澄清问题 ... clarification_question = "您想爬取哪个具体的新闻网站?请提供完整的URL。" # (模拟)假设我们从某个渠道获得了用户回答 user_answer = "https://news.example.com" # 第二轮:基于澄清后的需求生成代码 final_prompt = f""" 用户原始请求:{user_request} 已澄清信息:目标网站是 {user_answer} 请生成爬取该网站头条新闻标题的Python代码。要求代码健壮,包含异常处理。 """ # ... 调用LLM生成最终代码 ... final_code = """ import requests from bs4 import BeautifulSoup url = 'https://news.example.com' try: resp = requests.get(url, timeout=10) resp.raise_for_status() soup = BeautifulSoup(resp.text, 'html.parser') # 假设标题在 h1 标签里,实际需要根据网站结构调整 title = soup.find('h1').text print(f'头条新闻标题:{title}') except Exception as e: print(f'爬取失败:{e}') """ return final_code def run_and_fix_code(code_string, max_retries=3): """尝试运行代码,如果失败,将错误信息反馈给LLM进行修复""" for i in range(max_retries): try: # 将代码写入临时文件并执行 with open('temp_code.py', 'w', encoding='utf-8') as f: f.write(code_string) result = subprocess.run([sys.executable, 'temp_code.py'], capture_output=True, text=True, timeout=30) if result.returncode == 0: print("代码运行成功!") print("输出:", result.stdout) return True, code_string else: error_msg = result.stderr print(f"第{i+1}次运行失败,错误:{error_msg[:200]}...") except subprocess.TimeoutExpired: error_msg = "Execution timeout." except Exception as e: error_msg = str(e) # 基于错误信息让LLM修复代码 fix_prompt = f""" 以下Python代码运行失败,错误信息如下: ``` {error_msg} ``` 请分析错误原因,并提供修复后的完整代码。 原代码: ```python {code_string} ``` """ # ... 调用LLM获取修复后的代码 ... code_string = fixed_code # 假设获取到了修复后的代码 print("达到最大重试次数,修复失败。") return False, code_string # 主流程 user_request = "帮我写一个爬取某新闻网站头条新闻标题的Python脚本" clarified_code = clarify_and_generate(user_request) success, final_code = run_and_fix_code(clarified_code)进步:
- 交互性:通过“澄清循环”解决了需求模糊的问题。
- 健壮性:通过“运行-修复循环”尝试自动解决代码错误。
- 自动化:将多轮对话和调试过程自动化。
新问题:
- 逻辑复杂:代码中混杂了对话管理、代码生成、代码执行、错误处理等多种逻辑,不易维护。
- 状态管理困难:多轮对话和历史错误信息需要妥善管理。
- 可扩展性差:如果想加入“检查依赖”、“优化代码风格”等新步骤,需要大幅修改主函数。
2.3 阶段三:使用工作流引擎进行编排
我们将上述流程用工作流的思想进行重构。这里我们用伪代码和节点描述来示意,类似于 Dify、n8n 等工具的可视化逻辑。
工作流节点设计:
- 节点1:接收用户输入(
user_request)。 - 节点2:需求分析节点(LLM)。分析输入,判断是否需要澄清。如果需要,生成问题并暂停工作流,等待外部输入(用户回答)。将澄清后的需求传递给下游。
- 节点3:代码生成节点(LLM)。基于清晰需求生成代码。
- 节点4:依赖检查节点(Python函数)。解析生成的代码,检查
import语句,判断是否需要安装requests,beautifulsoup4等包。 - 节点5:代码执行节点(Python函数)。在安全环境(如沙箱)中运行代码,捕获输出和错误。
- 节点6:条件判断节点。检查代码执行结果。
- 如果成功,跳转到节点8:成功处理。
- 如果失败且重试次数未超限,跳转到节点7:代码修复节点。
- 如果失败且重试次数超限,跳转到节点9:失败处理。
- 节点7:代码修复节点(LLM)。将错误信息和原代码传给LLM,请求修复。然后将修复后的代码重新导向到节点4(依赖检查),开始新一轮循环。
- 节点8/节点9:处理最终结果(输出代码/报告失败)。
优势:
- 模块化:每个节点职责单一,易于开发和测试。
- 可视化:流程一目了然,非开发者也能理解业务逻辑。
- 可维护:修改或增加步骤(如添加“代码安全检查节点”)只需调整工作流图,无需重写核心逻辑。
- 状态管理:工作流引擎通常自带上下文管理,负责在节点间传递数据。
这个工作流已经是一个功能比较完善的自动化代码生成系统。但它仍然是被动响应型的:必须由用户触发一个具体请求,然后执行一个预设的、固定的流程。
2.4 阶段四:构建AI Agent(自主代码助手)
现在,我们尝试构建一个更“主动”的AI Agent。假设它是一个运行在后台的“代码助手Agent”。
目标:Agent持续监控一个指定目录。当发现该目录下新增了requirements.txt文件时,自动分析项目结构,为该项目生成一份初始的单元测试文件,并尝试运行这些测试,将结果报告给开发者。
核心循环(ReAct模式简化版):
import time import os from pathlib import Path # 假设有LLM调用函数 llm_call, 工具函数 analyze_project, generate_test_file, run_tests class CodeAssistantAgent: def __init__(self, watch_directory): self.watch_dir = Path(watch_directory) self.memory = [] # 简单的记忆,记录处理过的项目 def perceive(self): """感知环境:检查监控目录是否有新的requirements.txt""" new_projects = [] for project_path in self.watch_dir.iterdir(): if project_path.is_dir(): req_file = project_path / "requirements.txt" if req_file.exists() and project_path not in self.memory: new_projects.append(project_path) return new_projects def think(self, project_path): """思考:决定为这个新项目做什么""" # 这里可以用LLM来分析项目结构,决定测试策略 thought_prompt = f""" 这是一个Python项目路径:{project_path}。 它刚刚创建了requirements.txt,可能是一个新项目。 你的任务是为它创建初始的单元测试,以提高代码质量。 请规划你的行动步骤。 """ plan = llm_call(thought_prompt) # 可能输出:1. 分析主代码文件。2. 确定测试框架(pytest)。3. 为关键函数生成测试用例。 return plan def act(self, project_path, plan): """执行:使用工具完成任务""" # 1. 分析项目(工具) project_structure = analyze_project(project_path) # 2. 生成测试文件(工具,内部可能调用LLM) test_file_path = generate_test_file(project_path, project_structure, plan) # 3. 运行测试(工具) test_result = run_tests(project_path) # 4. 记录到记忆 self.memory.append(project_path) return test_result def run(self): """主循环:持续感知-思考-执行""" while True: new_projects = self.perceive() for project in new_projects: print(f"发现新项目: {project}") plan = self.think(project) result = self.act(project, plan) print(f"项目 {project} 测试生成完成,结果: {result}") time.sleep(60) # 每分钟检查一次 # 启动Agent agent = CodeAssistantAgent("/path/to/watch") agent.run()质变:
- 自主性:Agent主动监控环境,无需用户每次手动触发。
- 目标导向:它有明确的目标(为项目生成测试),并自主规划步骤(Think)来实现。
- 工具使用:它调用了
analyze_project,generate_test_file,run_tests等外部工具。 - 记忆:它记录了处理过的项目,避免重复劳动。
- 持续运行:它是一个长期运行的过程。
在这个Agent内部,generate_test_file这个动作,完全可以复用我们阶段三构建的那个“代码生成工作流”。Agent负责高层决策和调度,工作流负责执行具体的、复杂的标准化子任务。
3. 工程实践:如何选择与设计你的AI应用架构
理解了四者的关系后,在实际项目中如何选择?
3.1 决策流程图:从需求到技术选型
你可以遵循以下决策路径:
你的任务是否单轮对话就能解决?
- 是-> 专注于提示词工程。投入精力设计清晰、具体、少歧义的提示词模板。这是成本最低、见效最快的方式。
- 否-> 进入第2步。
你的任务是否有固定、清晰的多步骤流程?
- 是-> 使用工作流。特别是当步骤涉及LLM、API调用、条件判断、数据转换等多种操作时,工作流能极大提升开发效率和可维护性。选择如Dify、n8n等成熟工具。
- 否(流程动态、需自主决策)-> 进入第3步。
你的任务是否需要长期运行、主动感知环境、并动态规划行动?
- 是-> 你需要构建AI Agent。设计其感知器、记忆模块、规划器(LLM)和工具集。可以从ReAct、AutoGPT等框架入手。
- 否-> 你可能只需要循环工程。在代码中实现一个简单的多轮调用循环,例如“生成-验证-修复”模式。
3.2 提示词工程远未“已死”,而是基础
“Prompt Engineering已死”的论调是片面的。准确地说,仅靠提示词工程构建复杂应用的时代过去了。但对于任何基于LLM的系统,提示词工程依然是不可或缺的底层技能。
- 在循环中:每一轮新的提示,都需要根据上一轮的输出和当前目标来精心构造。
- 在工作流中:每个LLM节点的输入模板,就是提示词工程。
- 在Agent中:Agent“思考”(planning)时发出的提示词,以及调用工具前对工具输入的描述,都需要高超的提示词技巧。
提示词工程从“前台明星”变成了“幕后基石”。它的重要性没有降低,而是变得更加基础化和专业化。
3.3 混合架构是常态
在实际生产系统中,你很少会只使用其中一种模式。更常见的是混合架构:
- Agent 驱动 Workflow:一个自主Agent在决策后,触发一个预设的工作流来执行标准化复杂任务。
- Workflow 内含 Loop:一个工作流中包含循环节点,用于实现“重试”、“轮询”或“迭代优化”。
- Loop 依赖 Prompt:每一次循环迭代,都使用经过精心设计的提示词模板来生成本次的查询。
例如,一个客服Agent的架构可能是:
用户提问 -> Agent(理解意图,规划步骤) -> 步骤1:查询知识库(调用检索工具,本质是一个固定工作流) -> 步骤2:若未找到,询问澄清(进入一个“澄清循环”) -> 步骤3:生成回答(使用高质量的“回答生成”提示词模板) -> 步骤4:记录对话到记忆(调用记忆工具)3.4 常见陷阱与避坑指南
在构建复杂AI应用时,以下陷阱需要特别注意:
| 陷阱 | 现象 | 根本原因 | 解决方案 |
|---|---|---|---|
| 提示词幻觉 | 在循环或工作流中,LLM逐渐偏离主题或胡言乱语。 | 上下文窗口积累了大量历史信息,导致关键指令被稀释。 | 1. 定期清理或总结上下文。2. 在关键步骤重新注入系统指令和约束。3. 使用更短的、目标明确的提示词。 |
| 循环失控 | 程序陷入无限循环,或重试次数过多。 | 终止条件定义不清晰,或LLM无法正确判断任务是否完成。 | 1. 设置硬性限制(如最大循环次数、超时时间)。2. 使用更可靠的完成判断(如基于规则或外部验证)。3. 增加监控和告警。 |
| 工作流僵化 | 工作流无法处理预期之外的边缘情况,频繁报错中断。 | 工作流设计时只考虑了“快乐路径”,缺少异常处理和补偿逻辑。 | 1. 为每个可能失败的节点设计重试和降级策略。2. 增加全局异常捕获和错误处理节点。3. 设计人工审核节点处理复杂异常。 |
| Agent“瞎忙” | Agent不断执行动作,但始终无法接近目标,或执行无关动作。 | Agent的规划能力不足,或目标定义过于模糊。 | 1. 为Agent提供更具体、可分解的子目标。2. 增强其反思(Reflection)能力,定期评估进展。3. 限制其可用工具的范围,避免无关操作。 |
| 成本与延迟飙升 | 应用响应慢,API调用费用激增。 | 不必要的复杂循环、过长的上下文、频繁调用昂贵模型。 | 1. 优化提示词,减少token消耗。2. 对简单任务使用小模型。3. 缓存频繁使用的中间结果。4. 异步执行非关键路径任务。 |
4. 总结与展望:把握底层逻辑,灵活组合运用
提示词工程、循环工程、工作流和AI Agent,构成了现代AI应用开发的四层工具箱。
- 提示词工程是砖瓦,决定了你与模型每次交互的质量。
- 循环工程是粘合剂,让你能将多次交互组合起来,完成更复杂的任务。
- 工作流是预制件和施工图,让你能可视化、标准化地组装复杂流程,提升工程效率。
- AI Agent是具备自主意识的智能体,是前三种技术的集大成者,用于构建能够主动适应环境、追求长期目标的系统。
它们的关系是层层递进、相互依赖的,而非彼此取代。“Prompt Engineering已死”的说法,混淆了“基础技术”和“最终产品”的界限。
对于开发者的启示是:
- 不要忽视基础:无论架构多复杂,与LLM交互的边界始终是提示词。持续打磨这项技能。
- 从问题出发,而非技术:先明确你要解决什么问题,再根据问题的特性(是否固定流程、是否需要自主性)选择合适的技术组合。
- 渐进式复杂化:从一个优秀的提示词开始。如果不够,加入循环。如果流程固定且复杂,引入工作流。如果需要长期自主运行,再考虑Agent。
- 重视可观测性与控制:系统越复杂,越需要完善的日志、监控和人工干预通道。确保你能看清每一步发生了什么,并在必要时能够接管。
未来的趋势将是这些技术的更深层次融合。工作流工具会内置更强大的Agent节点,而Agent框架也会提供可视化的工作流编排能力。作为开发者,理解每一层的原理和适用边界,才能在这个快速演进的技术栈中,设计出既强大又可靠的AI应用。