随着大模型(LLM)能力的日益增强,它们不再仅仅是辅助工具,而是逐步演化为能够自主与环境交互的AI Agent。这些Agent通过ReAct模式,能够自主选择和调用工具,从而实现真正的智能化。然而,这种转变也对API的设计提出了新的挑战。传统的API设计主要面向人类开发者,而现在,我们需要设计出更“AI友好”的API,以便大模型能够正确、可靠地使用它们,并最大程度地减少幻觉现象。本文将基于Sergei的文章,深入探讨七个关键的API设计指南,帮助您为AI Agent打造更强大的工具。
1. 条件API:将逻辑封装于工具之中
在大模型调用工具时,条件逻辑的出现频率远超想象。人类可以轻松理解“如果天气冷,就打开暖气”这样的条件,但大模型在没有外部执行环境(例如代码解释器)的帮助下,无法可靠地处理这类数值逻辑,它们只能通过自然语言进行推理。因此,我们需要将条件判断封装在API内部,而非让大模型自行判断。
举例来说,智能家居系统中,用户发出指令“我45分钟后到家,把家里弄得舒服点”。AI Agent可能会做出如下推理:
- “用户将于下午6:15到达。”
- “检查室内温度。”
- “如果温度 < 21°C,打开暖气。”
- “调暗灯光。”
- “播放爵士乐。”
其中,第三步包含条件判断。如果让大模型直接处理这个条件,它可能会基于语言的语义理解来推断,而非进行真正的数值比较。例如,如果Prompt中包含“当前温度是18°C。如果低于21°C,是否应该打开暖气?”,大模型很可能会回答“是”,但这仍然是基于语言的推断,而非真正的逻辑执行。
为了解决这个问题,我们可以将条件判断逻辑封装在set_thermostat
函数中:
def set_thermostat(req_temp, threshold=None):
if threshold and get_indoor_temperature() >= threshold:
return # already warm
adjust_thermostat(req_temp)
这样,我们只需要调用set_thermostat(22, threshold=21)
即可,无需大模型自行判断温度是否低于阈值。
将条件判断封装在API内部的优势在于:
- 降低Prompt复杂度: 每个分支都会增加prompt复杂度和token的使用量
- 降低幻觉风险: 因为逻辑判断交给代码,而不是大模型本身,更加安全。
- 提高可靠性: 代码中的条件、回退和安全措施能够得到一致的处理,方便调试且行为可预测。
- 符合软件设计原则: “协调者应该委托 what,而不是 how。”
尽管如此,这种方法也需要对API设计进行额外思考,需要考虑到潜在的条件用例,并且并非所有条件都能包含在工具中。
2. 向量化API:批量处理,提高效率
当AI Agent处理用户请求时,可能会遇到需要重复执行相同操作的情况。例如,用户要求“从社交网络的所有群组中删除我的用户”,如果AI Agent逐个群组删除用户,将会浪费大量的tokens、时间和金钱。
为了解决这个问题,我们可以使用向量化API,让API能够批量处理多个操作。例如,将delete_group(user.id, group.id)
替换为delete_groups(user.id, groups)
。
这种批量处理方法可以带来以下好处:
- 更快的执行速度: 通过并行处理多个操作,可以显著提高执行速度。
- 更低的Token使用量: 减少了Prompt中的重复信息,降低了Token使用量。
- 更简洁的逻辑: 简化了大模型的调用流程,使逻辑更加清晰。
- 更简单的错误处理: 可以一次性处理多个操作的错误,提高了错误处理的效率。
- 更自然的声明式Prompt: 大模型只需要声明需要执行的操作,而无需关注具体的执行细节。
此外,许多服务(内部和外部)都会对请求进行速率限制。执行100个单独的更新可能会导致限流或延迟。大模型本质上是顺序执行的。如果它等待每个结果来决定下一步(除非流水线化),则会受到瓶颈限制,并且让大模型思考每次迭代的结果可能会非常缓慢。如果一个操作失败并且重试逻辑不完善,最终可能会得到部分更新。
向量化API不仅优雅地解决了大模型的管理问题,还具有以下优点:
- 能够优雅地处理空列表 (直接无操作)
- 能够无缝地处理单元素调用
- 能够在一个返回中提供批量反馈
这种设计理念类似于ML库 NumPy 或 Pandas 中的向量化操作:“不要循环 —— 操作数组。”
然而,批量API也存在滥用或拒绝服务(DoS)的风险。为了解决这个问题,我们可以采取以下措施:
- 配置批量限制: 限制每次批量操作的最大数量。
- 按身份进行速率限制 (Token/IP/User): 限制每个用户或IP地址的请求频率。
- 身份验证和审计跟踪: 确保只有授权用户才能访问批量API,并记录所有操作的审计日志。
- 为 AI 包装批量 API 以覆盖单实体 API: 这还提供了额外的好处:
- 提高大模型/Agent 效率。
- 保持向后兼容性。
- 保持系统的安全性和可扩展性。
此外,如果get_groups
返回的群组数量过多,可能会占用大模型的上下文窗口,影响其性能。为了解决这个问题,我们可以添加条件逻辑,允许外部指定群组,否则工具将内部获取所有可用群组:
def delete_groups(user_id, groups=None):
groups = groups or get_groups(user_id)
for group in groups:
_delete_group(user_id, group.id)
总而言之,没有一劳永逸的解决方案,每个案例都需要根据需求和预期进行考虑和调整。
3. 丰富的工具参数:传递对象,而非原始值
在将底层逻辑抽象到工具中时,我们应该传递丰富的对象,而非仅仅是原始值。
例如,不要使用:
user = get_me()
groups = get_groups(user.id)
delete_groups(user.id, groups)
而是使用:
user = get_me()
groups = get_groups(user)
delete_groups(user, groups)
让工具(而非大模型)提取内部属性,例如user.id
或group.id
。这可以保持高层次的协调,并使大模型无需管理内部细节。
这种方法的优势在于:
- 更简洁的Prompt和工具设计: 减少了Prompt中的冗余信息,使工具设计更加清晰。
- 减少了因格式错误或缺少字段而导致的错误: 降低了出错的可能性。
- 提高了工具的可重用性和灵活性: 使工具更易于重用和扩展。
记住:“协调者应该委托 what,而不是 how。” 就像你启动洗衣机的精细洗涤模式一样,无需对滚筒速度、洗涤时间或水温进行任何微调,只需进行添加洗衣粉、放入衣物和选择洗涤模式等常见操作。
4. 计数API:提供总数提示,避免分页遍历
用户经常需要知道一些数字,例如未读消息的数量、新邮件的数量、即将采取的行动的数量等。然而,数字对大模型来说是一个挑战,因为它们无法进行精确的计数。
为了解决这个问题,一方面我们可以提供外部计算工具,例如Python脚本。另一方面,我们可以设置一个API,直接返回计数结果。
例如,用户询问“今天早上我收到了多少未读邮件?”,这对应于请求GET /api/emails?unread=true
。如果响应返回一个分页的未读邮件列表,大模型需要遍历所有页面才能计算总数。这非常不理想。
为了解决这个问题,我们可以在响应中包含一个额外的字段totalCount
,提示大模型分页查询中满足条件的实体总数。我们可以通过以下两个选项来控制totalCount
:
withCount
: 如果为true,则将totalCount
注入到响应中,与分页数据一起返回。countOnly
: 如果为true,则仅返回totalCount
。隐式地意味着withCount=true
。
因此,如果大模型只需要获取未读消息的数量,它可以调用API:GET /api/emails?unread=true&countOnly=true
。
5. 工具,而非Prompt:避免将指令嵌入Prompt
避免将所有指令都嵌入到系统Prompt中。如果对于某些查询有标准回复,例如“你不能做什么?”,请将其实现为工具,而非直接写入Prompt文本。
原因如下:
- Prompt指导可能会抑制工具的使用: 大模型可能会优先使用Prompt中的指令,而非调用工具。
- 系统Prompt在所有用例中共享: 可能会导致某些用例出现不必要的限制。
- 大模型可能会将指导误解为行为约束: 大模型可能会将Prompt中的指令误解为必须遵守的规则。
将面向用户的响应移动到工具输出中。系统Prompt应该协调工具的使用;输出应该来自工具。任何与保护或指示无关的内容都应该移动到函数输出中,而不是系统Prompt中。这可以避免混淆,并防止大模型将面向用户的指导误解为内部行为约束。
6. 丰富的描述:清晰的元数据定义
使用清晰、详细的元数据定义您的工具:
- 函数描述
- 参数类型和约束
- 用例示例
- 相关工具或预期排序
这有助于大模型更有效地进行推理,并减少误用。这是一次性投资,但可以带来长期的收益。
7. 零信任Prompt:最小化系统Prompt,最大化工具权限
使用AI Agent的系统Prompt时,首选以下风格:
- 最小化的系统Prompt: 概括Agent的目标,并说明如何以及使用哪些工具,例如ReAct风格。
- 将大部分逻辑委托给工具: 工具决定答案中要呈现的内容。
- 也可以使用LLM作为工具进行语言处理: 例如文本摘要、生成、情感分析。
这种方法的优势在于:
- Prompt是公开的或非关键的: 降低了安全风险。
- 大模型是一个决策助手,而不是一个行动者: 降低了大模型出错的可能性。
- 工具强制执行权限和策略: 提高了系统的安全性。
- 行为是可观察的、可追溯的和可外部审计的: 方便进行故障排除和安全审查。
结论:为机器之心设计API
设计AI友好的API不仅仅是关于语法,还关乎语义、可用性和自主执行的鲁棒性。大模型并非完美无缺,它们是强大的语言预测器,而不是执行引擎。我们越是将底层逻辑和计算委托给API,就能获得越好的结果:更少的幻觉,更快的响应,更清晰的协调,以及更强大的Agent体验。因此,我们需要为机器之心设计API,充分发挥大模型的潜力,构建真正智能化的AI Agent。大模型的强大能力需要高效的API设计来支撑,才能真正赋能AI Agent,最终实现人与机器的完美协作。拥抱AI友好的API设计,是构建未来智能世界的关键一步。