Vercel AI SDK 提供方
在 Vercel AI SDK 7 中使用 PopNow 模型。generateImage 用于文生图和图片编辑,另有 generateSpeech、transcribe 和对话模型,一把 API 密钥,按美元从 API 余额扣费。
@popnow/ai-sdk-provider 把 PopNow 模型接入 Vercel AI SDK。使用一把 API 密钥,你可以通过 generateImage 调用图片生成和图片编辑模型,通过 generateSpeech 调用文本转语音,通过 transcribe 调用语音转文字,并通过 generateText 和 streamText 调用对话模型。所有费用都按美元从你单独的 API 余额扣除。
这个包以 MIT 许可证开源(GitHub)。它需要 AI SDK 7(ai@^7)和 Node.js 22 或更高版本。
概览
| AI SDK 函数 | PopNow 模型 | 工厂函数 |
|---|---|---|
generateImage | 文生图与图片编辑:Nano Banana、GPT Image、Seedream、FLUX、Qwen Image 等 | popnow.image(id) |
generateSpeech | 文本转语音 | popnow.speech(id) |
transcribe | 语音转文字 | popnow.transcription(id) |
generateText、streamText | 通过 OpenAI 兼容端点调用的对话模型 | popnow(id)、popnow.chat(id) |
设置
安装包
npm install @popnow/ai-sdk-provider ai把密钥放进环境变量
默认的 popnow 实例从 POPNOW_API_KEY 读取密钥:
export POPNOW_API_KEY="sk-popnow-..."请把密钥保存在你的服务器上。任何能读取它的人都可以花掉你的 API 余额。
生成一张图片
import { popnow } from '@popnow/ai-sdk-provider';
import { generateImage } from 'ai';
import fs from 'node:fs';
const { image } = await generateImage({
model: popnow.image('google/nano-banana-2.1/text-to-image'),
prompt: 'A cozy reading nook beside a rain-streaked window, warm lamp light',
aspectRatio: '16:9',
providerOptions: {
popnow: { resolution: '2k' },
},
});
await fs.promises.writeFile('nook.png', image.uint8Array);提供方设置
如需其他设置,请用 createPopNow 创建你自己的实例:
import { createPopNow } from '@popnow/ai-sdk-provider';
const popnow = createPopNow({
apiKey: process.env.POPNOW_API_KEY, // default: POPNOW_API_KEY
baseURL: 'https://api.popnow.ai', // default: POPNOW_BASE_URL or https://api.popnow.ai
headers: { 'X-PopNow-Tags': 'my-app' }, // optional, sent with every request
});createPopNow 还可以接收自定义的 fetch 函数。
编辑图片
编辑模型的 ID 以 /edit 结尾。把源图片传入 prompt;如果模型需要蒙版,也在 prompt 中一并传入:
import { popnow } from '@popnow/ai-sdk-provider';
import { generateImage } from 'ai';
const { image } = await generateImage({
model: popnow.image('google/nano-banana-2.1/edit'),
prompt: {
text: 'Change the jacket to deep forest green; keep the face and background',
images: ['https://example.com/portrait.jpg'],
},
});URL 会原样传递。以字节或 base64 提供的图片,如果是不超过 1 MiB 的 JPEG、PNG、WebP 或 GIF,会直接内联发送;其余的图片会先上传到 PopNow。
设置如何映射到 PopNow
每个 PopNow 模型都会用它自己的 JSON Schema 校验 input,并拒绝未知字段。提供方会读取模型的 Schema(GET /api/v1/models/{model},缓存十分钟),只有当模型存在对应字段时才发送该设置:
| AI SDK 设置 | PopNow 输入字段 |
|---|---|
prompt | prompt |
aspectRatio | aspect_ratio |
size | width 和 height;模型不支持时简化为 aspect_ratio,并给出 compatibility 警告 |
seed | seed |
n | num_outputs 或 num_images;两者都没有的模型,每张图片是一个单独的任务,由 AI SDK 发起多次调用 |
prompt 中的 images | image_urls,单图模型则为 image_url |
prompt 中的 mask | mask_url |
模型不支持的设置会被省略,并在 warnings 中以 unsupported 报告。其他模型字段放在 providerOptions.popnow 中,拼写必须与模型 Schema 完全一致(snake_case),例如 resolution、output_format 或 quality。这些值会覆盖映射得到的值。
文本转语音
import { popnow } from '@popnow/ai-sdk-provider';
import { generateSpeech } from 'ai';
import fs from 'node:fs';
const { audio } = await generateSpeech({
model: popnow.speech('openai/tts-1/text-to-speech'),
text: 'Hello from PopNow.',
voice: 'nova',
speed: 1.1,
});
await fs.promises.writeFile('hello.mp3', audio.uint8Array);voice 映射到 voice_id,outputFormat 映射到 output_format;instructions、speed 和 language 在模型支持时,映射到同名字段。每个模型的 Schema 都列出了它接受的音色。
语音转文字
import { popnow } from '@popnow/ai-sdk-provider';
import { transcribe } from 'ai';
import fs from 'node:fs';
const result = await transcribe({
model: popnow.transcription('openai/whisper-1/speech-to-text'),
audio: await fs.promises.readFile('meeting.mp3'),
providerOptions: { popnow: { language: 'en' } },
});
console.log(result.text, result.words);音频字节会先上传到 PopNow(支持 MP3 和 WAV,最大 90 MiB)。公开的 https:// URL(audio: new URL('https://...'))会直接交给 PopNow,不经下载。
对话模型
PopNow 通过 OpenAI 兼容的 API 提供对话模型,地址为 https://api.popnow.ai/v1。提供方使用 @ai-sdk/openai-compatible 调用它们,使用同一把 API 密钥和同一份余额:
import { popnow } from '@popnow/ai-sdk-provider';
import { generateText } from 'ai';
const { text } = await generateText({
model: popnow('anthropic/claude-haiku-5.5/chat'),
prompt: 'Suggest three names for a kite shop by the sea.',
});streamText 可以用同一个模型:
import { popnow } from '@popnow/ai-sdk-provider';
import { streamText } from 'ai';
const result = streamText({
model: popnow('anthropic/claude-haiku-5.5/chat'),
prompt: 'Write a short welcome message for a kite shop.',
});
for await (const delta of result.textStream) process.stdout.write(delta);对话模型按 token 计价,没有单次请求的最低收费。对话模型列出了所有模型及其支持的参数。
模型 ID
模型 ID 的格式为 <maker>/<model>/<task>,例如 google/nano-banana-2.1/text-to-image、openai/tts-1/text-to-speech 或 openai/whisper-1/speech-to-text。TypeScript 类型只提示其中几个;你的密钥能调用的任意 ID 都可以使用。模型列出了所有模型的参数和价格。如需在代码中连同输入 Schema 一起列出它们:
curl "https://api.popnow.ai/api/v1/models?modality=image&includeSchema=1" \
-H "Authorization: Bearer $POPNOW_API_KEY"modality 可取 image、video 或 audio。对话模型通过 GET https://api.popnow.ai/v1/models 列出。
价格
价格以美元计,依模型而定,单位是每张图片、每秒或每 1,000 个字符,并显示在模型页及每个模型的页面上。AI 价格指数也列出了这些价格。每个任务被接受时,会从你的 API 余额中冻结其最高价格,完成时按实际费用结算。失败或过期的任务不收费。详情见计费与报价。
每个图片条目在 providerMetadata.popnow.images 中都带有 taskId、costUsd(美元十进制字符串)以及费用是否已 settled(已结算)。语音和转写结果在 providerMetadata.popnow 中带有相同的字段。
任务、轮询与重试
PopNow 的生成是异步的。每次调用会创建一个任务,在创建请求上最多等待 60 秒,然后轮询任务(起初每 2 秒一次,逐步延长到每 15 秒一次),直到任务进入最终状态,再从签名链接下载输出文件。API 密钥从不会发送到这些链接。
以下选项放在 providerOptions.popnow 中,不会发送给模型:
| 选项 | 默认值 | 含义 |
|---|---|---|
pollIntervalMs | 2000 | 第一次轮询前的等待时间 |
pollTimeoutMs | 任务截止时间加两分钟 | 等待超过此时长即停止;任务会继续运行 |
waitSeconds | 60 | 创建请求保持打开的时长(0 到 60) |
idempotencyKey | 每次调用时生成 | 一次逻辑生成对应的稳定密钥 |
metadata | 无 | 你自己的标签,随任务一起保存 |
每个创建请求都会携带 Idempotency-Key。连接错误、429 以及可重试的 5xx 响应会用同一个密钥重试两次,因此重试不会启动第二个任务。如果你传入了自己的 idempotencyKey,AI SDK 自身的重试(maxRetries)也会复用它。参见幂等性。
abortSignal 会立即停止等待。已经被接受的任务会继续在 PopNow 上运行。
错误
APICallError(来自@ai-sdk/provider)表示 API 错误。错误信息中包含 PopNow 的业务码,例如40201(API 余额不足)或40301(该密钥不能调用此模型)。参见错误。PopNowTaskError表示任务以failed或expired结束。它包含taskId、state、errorCode(例如content_rejected)、errorMessage和costUsd。这些任务不收费。PopNowTaskTimeoutError表示pollTimeoutMs已耗尽。它包含taskId;任务会继续运行。
import { popnow, PopNowTaskError } from '@popnow/ai-sdk-provider';
import { generateImage } from 'ai';
try {
await generateImage({
model: popnow.image('google/nano-banana-2.1/text-to-image'),
prompt: 'A lighthouse at dawn, watercolor',
});
} catch (error) {
if (PopNowTaskError.isInstance(error)) console.log(error.taskId, error.errorCode);
}不包含的功能
- 视频。 AI SDK 的视频模型接口仍处于实验阶段(
experimental_generateVideo),因此这个包暂未实现它。PopNow 的视频模型可通过任务接口、官方 SDK 以及 OpenAI Videos 兼容端点使用。 - Embeddings。
embeddingModel会抛出NoSuchModelError。
需要哪个版本的 AI SDK?
AI SDK 7(ai@^7),运行环境为 Node.js 22 或更高版本。用 npm install @popnow/ai-sdk-provider ai 可以一次装好两者。
可以在浏览器中调用吗?
不能把你的 API 密钥放在页面里使用:任何能读取密钥的人都可以花掉你的 API 余额。请在服务端路由中调用 AI SDK,例如 Next.js 的 route handler 或 server action,再把结果发送到浏览器。
支持视频模型吗?
暂不支持,因为 AI SDK 的视频接口仍处于实验阶段。视频请使用任务接口或 JavaScript SDK。
如何查看一次调用花了多少钱?
读取 providerMetadata.popnow:每个任务都会报告它的 taskId、costUsd 以及费用是否已 settled。API 控制台会按密钥显示用量。

