海外访问:www.kdjingpai.com
Ctrl + D 收藏本站
当前位置:首页 » 课程资料

《12-Factor Agents》我们是如何走到这一步的:软件简史

2025-07-22 19

详细版:我们是如何走到这一步的

你不必听我的

无论你是刚接触智能体的新手,还是像我一样脾气古怪的资深人士,我都会试着说服你,抛弃你对 AI 智能体的大部分既有看法,退一步,从第一性原理重新思考它们。 (如果你几周前错过了 OpenAI 的 API 功能发布,这里剧透一下:将更多的智能体逻辑推到 API 后面并不是正确的方向)

智能体即软件,及其简史

我们来谈谈是如何走到这一步的

60 年前

我们将大量讨论有向图 (DGs) 和它的无环朋友——有向无环图 (DAGs) 。我首先要指出的是……嗯……软件就是一个有向图。我们过去习惯用流程图来表示程序是有原因的。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

20 年前

大约 20 年前,我们开始看到 DAG 编排器变得流行起来。我们谈论的是像 AirflowPrefect 这样的经典工具,以及一些前辈和一些较新的工具,比如 (dagsteringgestwindmill) 。它们遵循相同的图模式,并增加了可观测性、模块化、重试、管理等优点。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

10-15 年前

当机器学习模型开始变得足够好用时,我们开始看到 DAGs 中点缀着机器学习模型。你可能会想到这样的步骤:“将此列中的文本摘要到一个新列中”或“按严重性或情感对支持问题进行分类”。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

但归根结底,它仍然基本上是同样的老式确定性软件。

智能体的未来前景

我不是第一个 ,但在我开始学习智能体时,我最大的心得是,你可以抛弃 DAG。软件工程师不再需要为每个步骤和边缘情况编写代码,你可以给智能体一个目标和一组转换:

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

然后让大语言模型实时做出决策来找出路径。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

这里的前景是,你编写的软件更少,你只需给大语言模型图的“边”,让它自己找出“节点”。你可以从错误中恢复,可以编写更少的代码,而且你可能会发现大语言模型能为问题找到新颖的解决方案。

作为循环的智能体

换句话说,你有一个由 3 个步骤组成的循环:

  1. 大语言模型确定工作流的下一步,输出结构化的 JSON (“工具调用”)
  2. 确定性代码执行工具调用
  3. 结果被附加到上下文窗口
  4. 重复此过程,直到下一步被确定为“完成”
initial_event = {"message": "..."}
context = [initial_event]
while True:
next_step = await llm.determine_next_step(context)
context.append(next_step)
if (next_step.intent === "done"):
return next_step.final_answer
result = await execute_step(next_step)
context.append(result)

我们的初始上下文只是启动事件 (可能是一条用户消息、一次 cron 任务触发、一个 webhook 等) ,然后我们让大语言模型选择下一步 (工具) 或判断任务是否完成。

这是一个多步骤示例:

 

而生成的“物化” DAG 大概是这个样子:

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

这种“循环直到解决”模式的问题

这种模式最大的问题是:

  • 当上下文窗口变得过长时,智能体会迷失方向——它们会不断地重复尝试同样失败的方法。
  • 真的就这一个问题,但这足以让这种方法寸步难行。

即使你没有手动构建过智能体,你可能也在使用智能体编码工具时见过这种长上下文问题。它们用着用着就迷失了,你需要开启一个新的聊天。

我甚至想提出一个我经常听到的观点,而且你可能也已经凭直觉领悟到了:

即使模型支持越来越长的上下文窗口,使用简短、集中的提示和上下文,你总能获得更好的结果

我交流过的大多数开发者在意识到超过 10-20 轮对话后,事情就会变得一团糟,大语言模型无法从中恢复时,都把“工具调用循环”这个想法搁置一旁了。即使智能体 90% 的时间都能做对,这也远未达到“足以交到客户手中”的水平。你能想象一个有 10% 页面加载会崩溃的 web 应用吗?

2025-06-09 更新 – 我非常喜欢 @swyx 的这个说法:

《12-Factor Agents》我们是如何走到这一步的:软件简史-8

真正有效的方法 —— 微型智能体

我在实际应用中确实经常看到的一种做法是,将智能体模式采纳并点缀到一个更广泛、更具确定性的 DAG 中。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

你可能会问 —— “在这种情况下为什么还要使用智能体?” —— 我们稍后会谈到,但基本上,让语言模型管理范围明确的任务集,可以轻松地整合实时的真人反馈,并将其转化为工作流步骤,而不会陷入上下文错误循环。 (要素 1要素 3要素 7) 。

让语言模型管理范围明确的任务集,可以轻松地整合真人实时反馈……而不会陷入上下文错误循环

一个真实的微型智能体实例

这是一个例子,说明确定性代码如何运行一个微型智能体,该智能体负责处理部署过程中“人在回路中”的步骤。

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

  • 人类 将 PR 合并到 GitHub 的 main 分支
  • 确定性代码 部署到预发布 (staging) 环境
  • 确定性代码 针对预发布环境运行端到端 (e2e) 测试
  • 确定性代码 将任务交给智能体进行生产环境部署,初始上下文为:“将 SHA 4af9ec0 部署到生产环境”
  • 智能体 调用 deploy_frontend_to_prod(4af9ec0)
  • 确定性代码 请求人类批准此操作
  • 人类 拒绝该操作,并反馈:“可以先部署后端吗?”
  • 智能体 调用 deploy_backend_to_prod(4af9ec0)
  • 确定性代码 请求人类批准此操作
  • 人类 批准该操作
  • 确定性代码 执行后端部署
  • 智能体 调用 deploy_frontend_to_prod(4af9ec0)
  • 确定性代码 请求人类批准此操作
  • 人类 批准该操作
  • 确定性代码 执行前端部署
  • 智能体 判断任务成功完成,结束!
  • 确定性代码 针对生产环境运行端到端测试
  • 确定性代码 任务完成,或者将任务传递给回滚智能体以审查失败并可能进行回滚

这个例子基于一个我们 Humanlayer 发布的、用于管理我们部署的 真实开源智能体 —— 这是上周我与它的一段真实对话:

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

我们没有给这个智能体大量的工具或任务。大语言模型的主要价值在于解析人类的纯文本反馈,并提出更新的行动方案。我们尽可能地隔离任务和上下文,以保持大语言模型专注于一个小的、5-10 个步骤的工作流。

这是另一个 更经典的支持/聊天机器人演示

那么,智能体到底是什么?

  • 提示 (prompt) – 告诉大语言模型如何行动,以及它有哪些可用的“工具”。提示的输出是一个 JSON 对象,描述了工作流的下一步 ( “工具调用” 或 “函数调用” ) 。 (要素 2)
  • switch 语句 – 根据大语言模型返回的 JSON,决定如何处理它。 ( 要素 8 的一部分)
  • 累积的上下文 – 存储已发生的步骤及其结果的列表。 (要素 3)
  • for 循环 – 在大语言模型发出某种“终止”工具调用 (或纯文本响应) 之前,将 switch 语句的结果添加到上下文窗口,并要求大语言模型选择下一步。 (要素 8)

《12-Factor Agents》我们是如何走到这一步的:软件简史-1

在 “deploybot” 示例中,我们通过掌握控制流和上下文累积获得了几个好处:

  • 在我们的 switch 语句 和 for 循环 中,我们可以劫持控制流,以暂停等待人类输入或等待长时间运行任务的完成。
  • 我们可以轻松地序列化 上下文 窗口,以实现暂停和恢复。
  • 在我们的 提示 (prompt) 中,我们可以极力优化向大语言模型传递指令和“目前为止发生了什么”的方式。

第二部分 将 将这些模式形式化,以便它们可以被应用于任何软件项目,为其添加令人印象深刻的 AI 功能,而无需全盘采纳“AI 智能体”的传统实现/定义。

相关推荐

找不到AI工具?在这试试!

输入关键词,即可 无障碍访问 必应 搜索,快速找到本站所有 AI 工具。

邮箱

联系我们

回顶部

zh_CN简体中文