Code
Vercel AI SDK
Créez un fournisseur nokeep avec createOpenAICompatible depuis @ai-sdk/openai-compatible. Ensuite, generateText, streamText et les outils fonctionnent comme avec n'importe quel modèle de l'AI SDK.
Vérifié le 29 octobre 2026
Installer et configurer le fournisseur
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("<id du modèle>") vous donne un modèle. Les identifiants sont deepseek-v4.1-flash-uncensored et glm-5.3-flash-uncensored : comparez-les dans Modèles, ou lisez-les depuis GET /v1/models. includeUsage: true demande le nombre de jetons sur les réponses en flux ; sans cela, streamText n'en indique aucun.
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)Dans un gestionnaire de route Next.js, renvoyez result.toUIMessageStreamResponse() pour useChat, ou result.toTextStreamResponse() pour du texte brut. Arrêtez une réponse en annulant la requête (abortSignal) ; vous payez ce qui a été écrit avant l'arrêt. Voir Streaming.
Appel d'outils
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)Les deux modèles appellent des outils. glm-5.3-flash-uncensored choisit lui-même : toolChoice: "required" ou un outil nommé renvoie un 400, donc utilisez DeepSeek lorsqu'un outil doit s'exécuter. Voir Appels d'outils.
Effort de raisonnement
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)La clé sous providerOptions est le name donné au fournisseur. Elle est envoyée telle quelle sous reasoning_effort. DeepSeek V4.1 Flash Uncensored répond tout de suite, sauf si vous lui demandez de réfléchir : il accepte none, low, high, max. L'option reasoning: "high" de l'AI SDK envoie le même champ. Voir Réflexion.
Images (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-uncensoredlit jusqu'à 10 images par requête.glm-5.3-flash-uncensoredne lit que du texte et répond400 unsupported_input.- L'AI SDK envoie chaque image dans la requête, en base64. Si vous passez une
URLcommedata, il télécharge d'abord le fichier. Une requête peut aller jusqu'à 12 Mo : réduisez les grosses photos. - Les images sont des parties
fileavec un type médiaimage/*. L'ancienne partieimagefonctionne encore mais est dépréciée. - Les autres fichiers, comme les PDF ou l'audio, sont refusés avec
400 unsupported_input. Voir Images.
Pièges
- `reasoning_effort` n'accepte que les valeurs propres au modèle.
deepseek-v4.1-flash-uncensoredacceptenone,low,high,max;glm-5.3-flash-uncensoredacceptelow,high. Les valeursminimal,mediumetxhighd'autres applications passent au niveau le plus proche du modèle (mediumdevienthigh,xhighdevientmaxlorsque le modèle l'a) ; toute autre valeur renvoie400 invalid_reasoning_effort. Voir Réflexion. - Les champs qu'un modèle ne peut pas prendre sont retirés, pas refusés. L'appel répond quand même, et l'en-tête de réponse
x-nokeep-ignoredindique ce qui a été retiré. GLM ne garde quetools,tool_choiceetreasoning_effort, donc sontemperatureet sonresponse_formatsont retirés. Voir les champs acceptés par chaque modèle. - `n` doit valoir 1. Pour obtenir plusieurs réponses, faites plusieurs appels.
- Utilisez `@ai-sdk/openai-compatible`, pas `@ai-sdk/openai`. Le fournisseur OpenAI appelle
/v1/responsespar défaut, que nokeep ne propose pas.
Questions
Existe-t-il un paquet de fournisseur nokeep pour l'AI SDK ?
Vous n'en avez pas besoin. @ai-sdk/openai-compatible est le paquet officiel de l'AI SDK pour les API compatibles OpenAI, et toutes les fonctions de cette page passent par lui.
streamText indique-t-il l'usage ?
Oui, lorsque le fournisseur est créé avec includeUsage: true. await result.usage donne alors le nombre de jetons de l'appel.
Puis-je essayer sans payer ?
Oui. Utilisez la clé sk-nokeep-test : chaque appel renvoie une seule ligne fixe et ne coûte rien, ce qui vous permet de brancher votre application d'abord. La clé de test gratuite.