prepareCall & callOptionsSchema

最近在看 vercel ai sdk 的文档, 边玩边看, 还有点打瞌睡, 最近才看到 Configuring Call Options 调用选项配置 这一块

CallOptionsSchema

在初始化一个 agent 时在配置里携带 callOptionsSchema 可以约束调用 agent 时可以传入的额外参数配置 ( 不仅仅是约束, 更是强制, 如果在调用时参数存在与配置中不一样的字段, 都会引发 Zod Validation Error), 比如对话用户的 用户信息|权限 之类的:

const agent = new ToolLoopAgent({
    model: "....",
    callOptionsSchema: z.object({
        userId: z.string(),
        userGender: z.enum(['male', 'female', 'helicopter']).optional(),
    }),
});

await agent.generate({
    prompt: 'guess my gender',
    options: {
        userId: '...',
        userGender: 'helicopter'
    },
});

需要注意的是, 当 agent 配置里存在 callOptionsSchema 时, 在调用 agent 时传入的额外参数对象只能叫做 options, 原因是在 ai sdk 中, 无论是 generate 还是 stream, 它们的底层都是抽象到同一个方法中, 其要求的输入结构就是 Input {prompt: string, options: T}
但如果你实在不喜欢 options 这个名称, 可以尝试对调用 agent 的方式进行额外的封装:

function generateParmas_Options(
    prompt: string,
    params: {
        userId: string,
        userGender: 'male' | 'female' | 'helicopter'
    }
) {
    return agent.generate({
        prompt,
        options: params, // 将你喜欢的名称做一次映射
    })
}

之后调用时则可以直接调用 generateParmas_Options 并使用你喜欢的 “params” 而非 “options”

prepareCall

既然有了 callOptionsSchema 用于约束自定义参数, 那么就需要一个东西用来处理这些参数, 这个东西就是 prepareCall, prepareCall 会在调用 agent 时基于初始化时已有的配置以及 options 动态生成新的配置 ( 如动态生成 prompt, 动态调整 Toolset 等 ):

const agent = new ToolLoopAgent({
    model: "....",
    callOptionsSchema: z.object({
        userId: z.string(),
        userGender: z.enum(['male', 'female', 'helicopter']).optional(),
    }),
    prepareCall: ({options, ...settings}) => ({
        ...settings,
        instructions: 
            settings.instructions + options.userGender ? `\n
            - User Gender: ${options.userGender}`: '',
        model: options.userGender === 'helicopter' ? HELICOPTER_MODEL : USUAL_MODEL
    }),
});

在这一次的 agent 初始配置中, 我添加了 prepareCall 用于处理调用 agent 时传入的 options, 而 settings 则是除 options 以外的 agent 核心配置如 model, tools

需要注意的是:

  1. prepareCall 是在 重构整个 agent 的配置对象, 它必须返回一个包含所有必需配置的对象, 如果在结构 settings 遗漏了某些核心属性或者在重构时错误地修改了某些只读属性, 都会导致运行时报错
  2. prepareCall 在每次 agent 被调用时都会执行一次, 所以不应该在里面写复杂的异步操作而应当是纯函数, 如果有需要异步操作才能获取到的参数, 应当在调用前完成操作并将结果作为 options 传入
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐