🚀 Vercel AI SDK 使用指南:Call Options 动态配置 Agent

在使用 Vercel AI SDK 构建复杂的 AI 应用时,我们经常会遇到这样的痛点:Agent 的配置往往是静态的

在真实的业务场景中,我们可能需要根据"用户的会员等级"、"任务的复杂度"或者"用户的地理位置"来动态切换大模型修改工具(Tools)的上下文。如果每次都重新实例化一个 Agent,不仅代码冗余,状态管理也会变得极其混乱。

为了解决这个问题,Vercel AI SDK 引入了 Call Options 特性。本文将带你深度解析如何使用 Call Options,并结合阿里通义千问最新旗舰模型(qwen-max) ,手把手带你写出优雅的动态 Agent 代码。


💡 什么是 Call Options?

Call Options 允许你在每次调用 Agent(通过 generate()stream())时,安全地传入强类型的结构化数据。你可以利用这些数据,在请求发送给大模型之前,动态劫持并修改 Agent 的任何设置

它的核心工作流分为优雅的三步:

  1. 定义 Schema (callOptionsSchema):使用 Zod 定义你接受哪些动态参数。
  2. 拦截并配置 (prepareCall):在请求发送前,根据传入的参数修改模型、提示词或工具。
  3. 运行时传参 (options):在业务代码中按需传入参数。

🛠️ 核心实战:根据任务难度动态切换通义千问模型

在日常开发中,"杀鸡焉用牛刀"。对于简单的闲聊,我们用又快又便宜的 qwen-turbo 就足够了;但如果遇到复杂的代码生成或深度推理任务,我们就必须上性能最强的 qwen-max

利用 Call Options,我们可以轻松实现这个**"动态智能切模"**的逻辑。

1. 环境准备与模型接入

首先,我们需要安装依赖。Vercel AI SDK 提供了与 OpenAI 规范完全兼容的 Provider,这让我们可以零成本直接接入阿里云的 DashScope 服务:

Bash

bash 复制代码
npm install ai @ai-sdk/openai zod

2. 编写 Agent 逻辑

下面是完整的代码实现,展示了如何通过 Call Options 动态控制通义千问模型:

TypeScript

javascript 复制代码
import { createOpenAI } from '@ai-sdk/openai';
import { ToolLoopAgent } from 'ai';
import { z } from 'zod';

// 1. 初始化通义千问 Provider (利用 OpenAI 兼容接口)
// 请确保在环境变量中配置了 DASHSCOPE_API_KEY
const aliyun = createOpenAI({
  baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
  apiKey: process.env.DASHSCOPE_API_KEY,
});

// 2. 创建支持动态配置的 Agent
const dynamicAgent = new ToolLoopAgent({
  // 默认兜底使用轻量级模型
  model: aliyun('qwen-turbo'), 
  
  // 第一步:定义动态入参 Schema(享受 TypeScript 强类型校验和自动推导)
  callOptionsSchema: z.object({
    taskComplexity: z.enum(['simple', 'complex']).default('simple'),
  }),
  
  // 第二步:核心魔法!通过 prepareCall 拦截并修改配置
  prepareCall: ({ options, ...settings }) => ({
    ...settings, // 保留原有的 system prompt、tools 等配置
    // 根据外部传入的复杂度,动态决定使用哪款千问模型
    model: options?.taskComplexity === 'complex' 
            ? aliyun('qwen-max')   // 复杂任务:召唤最强模型
            : aliyun('qwen-turbo'),// 简单任务:使用极速模型
  }),
});

3. 在业务侧愉快地调用

在你的接口(如 Next.js Route Handler)或者 Node 脚本中,你现在可以根据业务上下文动态下发 options 了:

TypeScript

javascript 复制代码
async function main() {
  console.log('🤖 正在处理简单任务...');
  const simpleResult = await dynamicAgent.generate({
    prompt: '给我讲一个关于程序员脱发的冷笑话。',
    // 传入 simple,内部将自动使用 qwen-turbo
    options: { taskComplexity: 'simple' }, 
  });
  console.log('简单任务结果:', simpleResult.text);

  console.log('\n🧠 正在处理复杂推理任务...');
  const complexResult = await dynamicAgent.generate({
    prompt: '请分析 React 19 的 Compiler 机制是如何解决闭包陷阱的,并给出底层原理。',
    // 传入 complex,内部将无缝切换至最强的 qwen-max 模型!
    options: { taskComplexity: 'complex' }, 
  });
  console.log('复杂任务结果:', complexResult.text);
}

main().catch(console.error);

🔥 进阶玩法:为 Tools 动态注入用户上下文

Call Options 的威力不仅在于切换模型,它还可以用来动态修改 Tools 的行为

假设你写了一个"附近新闻"查询的 Tool。如果把用户的地理位置写进 Prompt 里,大模型有可能会"幻觉"或者没有准确地把参数传给 Tool。

更稳妥的做法是:通过 Call Options 把用户的地理位置安全地硬编码塞进该次请求的 Tool 配置中。

TypeScript

css 复制代码
const newsAgent = new ToolLoopAgent({
  model: aliyun('qwen-max'),
  
  // 1. 定义接受用户城市作为入参
  callOptionsSchema: z.object({
    userCity: z.string().optional(),
  }),
  
  // 默认的工具配置...
  tools: {
    // 这里的 searchTool 是你之前定义好的某个具备地理位置偏好的搜索工具
    localSearch: searchTool, 
  },
  
  // 2. 运行时劫持工具配置
  prepareCall: ({ options, ...settings }) => ({
    ...settings,
    tools: {
      ...settings.tools,
      // 动态重写这个工具,将该次请求的 userCity 注入进去
      localSearch: searchTool.withConfig({
        location: options?.userCity || '默认城市',
      })
    }
  })
});

// 调用时:直接将上下文中取到的城市传给大模型
await newsAgent.generate({
  prompt: '今天我家附近有什么好玩的新闻?',
  options: { userCity: '杭州市余杭区' } 
});

🎯 总结

通过 callOptionsSchemaprepareCall,Vercel AI SDK 为我们提供了一个极具扩展性的拦截口。它的优势在于:

  1. 类型安全 :Zod 和 TypeScript 的结合,让你在编写业务逻辑 generate({ options: {...} }) 时,能获得完美的语法提示。
  2. 职责分离:Agent 的核心定义(Instructions, Default Model, Tools)和运行时的业务逻辑(按用户区分的 Context、降级策略)被完美解耦。
  3. 国产模型无缝对接 :借助于标准化的 Provider 体系,像阿里云 qwen-max 这样顶级的国产大模型可以直接享受全球最前沿的 AI 框架生态。

赶快在你的下一个 AI Agent 项目中用起来吧!如果有帮助,别忘了点个赞和关注 ❤️

相关推荐
玉鸯2 小时前
多 Agent 系统通信的实现原理与最佳实践
llm·agent·mcp
Tsonglew2 小时前
OpenWorker 代码解剖:一个 AI 同事"敢让它干活"的工程学
agent·ai编程
测试开发技术4 小时前
AI 测试提效 | 告别手工写脚本,分享我的 Playwright + Skill 批量生成 UI 自动化脚本方案
自动化测试·人工智能·ui·自动化·agent·skill·ai测试
濮水大叔4 小时前
不必把 Vue3 写成“麻花”:从状态碎片到对象协作,重新理解 Zova 的前端心智模型
前端·typescript·vue3·ioc·tsx·zova
喜欢的名字被抢了4 小时前
langgraph教程系列-06-让流程可暂停 - 持久化与 checkpoint
agent·langgraph
喜欢的名字被抢了4 小时前
langgraph教程系列-05-给 agent 装上手脚 - 工具调用
agent·教程·langgraph
leeyi5 小时前
Embedder 接口 + 缓存层源码:一个把 key 撑大 3 倍的实现(第71篇-E57)
aigc·agent·ai编程
JaydenAI5 小时前
[Agent的评估-07]整合MEAI针对自然语言处理相关的评估器
ai·nlp·agent·evaluation·maf
CZW5 小时前
RAG系统核心解析:文档向量化与检索的实践探索
agent
code_371495 小时前
Agent 设计及实现 demo
agent