کد
Vercel AI SDK
یک ارائهدهندهٔ nokeep با createOpenAICompatible از @ai-sdk/openai-compatible بساز. بعد generateText، streamText و ابزارها مثل هر مدل AI SDK کار میکنند.
بررسیشده در ۷ آبان ۱۴۰۵
نصب و راهاندازی ارائهدهنده
npm install ai @ai-sdk/openai-compatible zod
export NOKEEP_API_KEY="sk-nokeep-test" # your own key once it connectsimport { createOpenAICompatible } from "@ai-sdk/openai-compatible"
export const nokeep = createOpenAICompatible({
name: "nokeep",
apiKey: process.env.NOKEEP_API_KEY,
baseURL: "https://nokeep.ai/v1",
includeUsage: true, // token counts on streamed replies too
})nokeep("<model id>") یک مدل به تو میدهد. شناسهها deepseek-v4.1-flash-uncensored و glm-5.3-flash-uncensored هستند: آنها را در Models مقایسه کن، یا از GET /v1/models بخوان. includeUsage: true شمارش توکنها را برای پاسخهای استریمشده هم میخواهد؛ بدون آن، streamText هیچ شمارشی گزارش نمیکند.
generateText
import { generateText } from "ai"
import { nokeep } from "./nokeep.js"
const { text, usage } = await generateText({
model: nokeep("deepseek-v4.1-flash-uncensored"),
system: "You are a blunt editor.",
prompt: "Cut this opening line to ten words: ...",
})
console.log(text)
console.log(usage.inputTokens, usage.outputTokens)streamText
import { streamText } from "ai"
import { nokeep } from "./nokeep.js"
const result = streamText({
model: nokeep("deepseek-v4.1-flash-uncensored"),
prompt: "Tell me a story in three lines.",
})
for await (const text of result.textStream) process.stdout.write(text)
// With includeUsage on, the counts arrive once the stream ends.
console.log(await result.usage)در یک route handler در Next.js، برای useChat مقدار result.toUIMessageStreamResponse() را برگردان، یا برای متن ساده result.toTextStreamResponse(). پاسخ را با لغو درخواست (abortSignal) متوقف کن؛ برای آنچه تا لحظهٔ توقف نوشته شده هزینه میپردازی. بخش Streaming را ببین.
فراخوانی ابزار
import { generateText, stepCountIs, tool } from "ai"
import { z } from "zod"
import { nokeep } from "./nokeep.js"
const { text } = await generateText({
model: nokeep("deepseek-v4.1-flash-uncensored"),
tools: {
weather: tool({
description: "Get the weather in a city",
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city, celsius: 18 }),
}),
},
stopWhen: stepCountIs(5), // let the model call the tool, read the result and answer
prompt: "What's the weather in Lisbon?",
})
console.log(text)هر دو مدل ابزار را صدا میزنند. glm-5.3-flash-uncensored خودش انتخاب میکند: toolChoice: "required" یا نام یک ابزار خطای 400 میدهد، پس وقتی ابزار باید اجرا شود از DeepSeek استفاده کن. بخش Tool calls را ببین.
میزان استدلال
import { generateText } from "ai"
import { nokeep } from "./nokeep.js"
const { text, reasoningText } = await generateText({
model: nokeep("deepseek-v4.1-flash-uncensored"),
prompt: "Plan a three-act heist story in five bullet points.",
maxOutputTokens: 4000, // thinking counts toward the limit
providerOptions: { nokeep: { reasoningEffort: "high" } },
})
console.log(reasoningText) // the thinking, apart from the answer
console.log(text)کلید زیر providerOptions همان name است که به ارائهدهنده دادهای. بدون تغییر بهصورت reasoning_effort فرستاده میشود. DeepSeek V4.1 Flash Uncensored بیدرنگ جواب میدهد، مگر اینکه از آن بخواهی فکر کند: مقادیر none، low، high و max را میپذیرد. گزینهٔ reasoning: "high" خود AI SDK همان فیلد را میفرستد. بخش Thinking را ببین.
تصویرها (DeepSeek)
import { readFile } from "node:fs/promises"
import { generateText } from "ai"
import { nokeep } from "./nokeep.js"
const { text } = await generateText({
model: nokeep("deepseek-v4.1-flash-uncensored"),
messages: [{
role: "user",
content: [
{ type: "text", text: "What is in this picture?" },
{ type: "file", mediaType: "image/jpeg", data: await readFile("photo.jpg") },
],
}],
})
console.log(text)deepseek-v4.1-flash-uncensoredدر هر درخواست تا ۱۰ تصویر میخواند.glm-5.3-flash-uncensoredفقط متن میخواند و400 unsupported_inputمیدهد.- AI SDK هر تصویر را داخل درخواست و بهصورت base64 میفرستد. اگر
URLرا بهعنوانdataبده، ابتدا فایل را دانلود میکند. هر درخواست میتواند تا ۱۲ مگابایت باشد، پس عکسهای بزرگ را کوچک کن. - تصویرها بهصورت بخشهای
fileبا نوع رسانهٔimage/*فرستاده میشوند. بخش قدیمیترimageهنوز کار میکند ولی منسوخ شده است. - فایلهای دیگر، مثل PDF یا صوت، با
400 unsupported_inputرد میشوند. بخش Pictures را ببین.
نکات و دامها
- `reasoning_effort` فقط مقادیر خود مدل را میپذیرد.
deepseek-v4.1-flash-uncensoredمقادیرnone،low،highوmaxرا میگیرد؛glm-5.3-flash-uncensoredمقادیرlowوhighرا. مقادیرminimal،mediumوxhighاز برنامههای دیگر، در نزدیکترین سطح مدل اجرا میشوند (mediumبهصورتhigh، وxhighبهصورتmaxدر جایی که مدل آن را دارد)؛ هر مقدار دیگری400 invalid_reasoning_effortمیگیرد. بخش Thinking را ببین. - فیلدهایی که مدل نمیپذیرد رد نمیشوند، حذف میشوند. تماس همچنان جواب میدهد و هدر پاسخ
x-nokeep-ignoredنام آنچه حذف شده را میگوید. GLM فقطtools،tool_choiceوreasoning_effortرا نگه میدارد، پسtemperatureوresponse_formatآن حذف میشوند. بخش هر مدل کدام فیلدها را میپذیرد را ببین. - `n` باید ۱ باشد. برای چند پاسخ، چند تماس جدا بفرست.
- از `@ai-sdk/openai-compatible` استفاده کن، نه `@ai-sdk/openai`. ارائهدهندهٔ OpenAI بهطور پیشفرض
/v1/responsesرا صدا میزند و nokeep آن را ندارد.
پرسشها
آیا برای AI SDK بستهٔ ارائهدهندهٔ nokeep وجود دارد؟
لازم نیست. @ai-sdk/openai-compatible بستهٔ خود AI SDK برای APIهای سازگار با OpenAI است و هر قابلیتی که در این صفحه آمده از طریق آن کار میکند.
آیا streamText مصرف را گزارش میدهد؟
بله، وقتی ارائهدهنده با includeUsage: true ساخته شده باشد. با await result.usage شمارش توکنهای آن تماس را میگیری.
میشود بدون پرداخت امتحان کرد؟
بله. از کلید sk-nokeep-test استفاده کن: هر تماس یک خط ثابت برمیگرداند و هزینهای ندارد، پس میتوانی اول برنامهات را وصل کن. کلید آزمایشی رایگان.