Vercel AI SDK 实战:在 Next.js 中实现人工干预流程
引言
在现代 AI 应用开发中,构建具备自主决策能力的代理系统(agentic systems)已成为趋势。然而,在某些关键场景下,我们往往需要引入人工干预机制(Human-in-the-Loop,简称 HITL),让用户能够审核并批准 AI 系统的操作。本文将基于 Vercel AI SDK,详细介绍如何在 Next.js 应用中实现这一功能。
技术背景
工具调用机制
在典型的 AI 对话应用中,工具调用(Tool Calling)的工作流程如下:
- 用户发起查询(如"纽约天气如何?")
- LLM 识别需要调用的工具(如 weather 工具)
- SDK 自动执行工具关联的 execute 函数
- 返回工具执行结果给用户
这种全自动流程虽然高效,但缺乏人工审核环节,可能带来潜在风险。
人工干预的价值
引入 HITL 机制后,流程变为:
- LLM 识别工具调用需求
- 前端展示确认界面
- 用户选择批准或拒绝
- 根据用户选择执行或取消操作
这种模式特别适用于涉及敏感操作或重要决策的场景。
基础实现方案
1. 移除自动执行功能
首先需要修改后端路由,移除工具的 execute 函数:
// api/chat/route.ts
export async function POST(req: Request) {
// ...
tools: {
getWeatherInformation: tool({
description: 'show the weather in a given city',
parameters: z.object({ city: z.string() }),
// 注意:移除了 execute 函数
}),
}
// ...
}
2. 前端拦截工具调用
在前端组件中,我们需要检测工具调用并渲染确认界面:
// app/page.tsx
{messages?.map(m => (
<div key={m.id}>
{m.parts?.map((part, i) => {
if (part.type === 'tool-invocation' &&
part.toolInvocation.toolName === 'getWeatherInformation') {
return (
<div>
确认获取 {part.toolInvocation.args.city} 的天气信息?
<button onClick={() => addToolResult({/* 确认 */})}>是</button>
<button onClick={() => addToolResult({/* 拒绝 */})}>否</button>
</div>
);
}
})}
</div>
))}
3. 处理用户响应
后端需要处理用户的选择:
// api/chat/route.ts
switch (toolInvocation.result) {
case 'Yes, confirmed.':
// 执行实际工具
const weather = await getWeather(toolInvocation.args.city);
dataStream.write(/* 发送结果 */);
break;
case 'No, denied.':
// 返回拒绝信息
dataStream.write(/* 发送拒绝消息 */);
break;
}
高级抽象方案
基础方案虽然可行,但在生产环境中不够优雅。我们可以构建更高级的抽象:
1. 创建工具定义文件
// tools.ts
export const tools = {
getWeather: tool({
description: '获取城市天气',
parameters: z.object({ city: z.string() }),
// 无 execute 函数,需要人工确认
}),
getTime: tool({
description: '获取当地时间',
parameters: z.object({ location: z.string() }),
execute: async ({ location }) => { /* 自动执行 */ }
})
};
2. 实现处理工具调用的高阶函数
// utils.ts
export async function processToolCalls({
tools,
dataStream,
messages
}, executeFunctions) {
// 处理需要确认的工具调用
// 自动处理已授权的工具执行
// 返回处理后的消息数组
}
3. 在后端路由中使用
// api/chat/route.ts
const processedMessages = await processToolCalls(
{ tools, dataStream, messages },
{
getWeather: async ({ city }) => {
// 实际天气获取逻辑
}
}
);
const result = streamText({
model: openai('gpt-4'),
messages: processedMessages,
tools
});
最佳实践建议
- 状态管理:确保前后端状态同步,使用唯一的 toolCallId 关联调用和结果
- 错误处理:为各种异常情况提供友好的用户反馈
- 性能优化:避免不必要的重新渲染,特别是长对话场景
- 用户体验:为等待中的工具调用提供加载状态指示
- 安全考虑:对敏感工具的参数进行验证和过滤
总结
通过 Vercel AI SDK,我们能够相对轻松地在 Next.js 应用中实现人工干预流程。基础方案适合快速验证概念,而抽象后的高阶方案更适合生产环境。开发者可以根据实际需求选择适合的实现方式,平衡自动化效率与人工控制的需求。
这种模式不仅适用于天气查询等简单场景,也可以扩展到更复杂的业务逻辑,如订单确认、敏感操作审核等关键业务流程,为 AI 应用增添一层可靠的人工保障。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考