Vai al contenuto

Vercel AI SDK

Un solo middleware marca per l’AI Act e la California ciò che genera l’AI SDK: ogni immagine di generateImage e, con un modello incapsulato, ogni clip audio di generateSpeech e ogni video di experimental_generateVideo. Funziona con qualsiasi modello raggiungibile dall’SDK, tramite l’AI Gateway o il pacchetto di un provider.

In breve

  • Pacchetto: npm install @kennmarq/ai-sdk, con la chiave in KENNMARQ_API_KEY sul server.
  • Passaggio: incapsula il modello: generateImage restituirà le immagini marcate, e genererà un errore se una non si può marcare.
  • Modelli: qualsiasi, tra cui FLUX, GPT Image, Imagen e Recraft; le credenziali già aggiunte da un provider vengono conservate.
  • Scritto per: AI SDK 7 (il pacchetto ai), verificato il 4 novembre 2026.

Marca ogni immagine: il middleware

app/api/image/route.ts
// app/api/image/route.ts
import { generateImage, wrapImageModel } from "ai";
import { openai } from "@ai-sdk/openai";
import { kennmarqImageMiddleware } from "@kennmarq/ai-sdk";

const model = wrapImageModel({
  model: openai.image("gpt-image-1"), // any image model, any provider
  middleware: kennmarqImageMiddleware({
    provider: "Acme Inc.",    // your legal name
    appName: "Acme Studio",   // your AI system, with its version
    appVersion: "2.1",
    markets: ["eu", "us-ca"],
  }),
});

export async function POST(request: Request) {
  const { prompt } = await request.json();
  const { image } = await generateImage({ model, prompt }); // already marked
  return new Response(image.uint8Array, { headers: { "Content-Type": image.mediaType } });
}

Le immagini create a partire da immagini di input vengono marcate come edited, le altre come created. La marcatura di ogni immagine è in providerMetadata.kennmarq.images, per la sua ricevuta. Per marcare ogni immagine creata da un provider, passa il middleware a wrapProvider, nel suo imageModelMiddleware.

Voce e video

TypeScript
import { experimental_generateVideo, generateSpeech } from "ai";
import { fal } from "@ai-sdk/fal";
import { openai } from "@ai-sdk/openai";
import { kennmarqSpeechModel, kennmarqVideoModel } from "@kennmarq/ai-sdk";

const origin = { provider: "Acme Inc.", appName: "Acme Studio", appVersion: "2.1", markets: ["eu"] };

const { audio } = await generateSpeech({
  model: kennmarqSpeechModel(openai.speech("gpt-4o-mini-tts"), origin),
  text: "Hello!",
  outputFormat: "mp3", // MP3, WAV or M4A
});

const { video } = await experimental_generateVideo({
  model: kennmarqVideoModel(fal.video("luma-ray-2"), origin),
  prompt: "Waves at dusk",
});

La voce riceve AudioSeal nel suono, che nessuno sente; i video (MP4) ricevono Video Seal in ogni fotogramma. Un video viene marcato come job, quindi la chiamata lo attende, e l’attesa rientra nel limite di tempo di experimental_generateVideo.

Oppure genera, poi marca

app/api/image/route.ts
// app/api/image/route.ts
import { generateImage } from "ai";
import { mark } from "@/lib/kennmarq"; // the helper from the Next.js guide

export const maxDuration = 60;

export async function POST(request: Request) {
  const { prompt } = await request.json();
  const { image } = await generateImage({ model: "bfl/flux-3-image", prompt });

  const file = new Blob([image.uint8Array], { type: image.mediaType });
  const marked = await mark(file, `image.${image.mediaType.split("/")[1]}`, { model: "FLUX.3" });

  // Only the marked copy leaves this route. If mark() threw, the request fails instead.
  return new Response(marked, { headers: { "Content-Type": image.mediaType } });
}

Le stesse due righe funzionano in una server action, o ovunque il tuo server chiami generateImage. Il modello qui viene dall’AI Gateway; con il pacchetto di un provider, passa invece il suo modello.

Più immagini insieme

TypeScript
const { images } = await generateImage({ model: "bfl/flux-3-image", prompt, n: 4 });

// One call each. One after another keeps a Free plan (10 calls a minute) well within its limit.
const marked: Blob[] = [];
for (const image of images) {
  marked.push(await mark(new Blob([image.uint8Array], { type: image.mediaType }), "image.png"));
}

Immagini che contengono già credenziali

Alcuni provider firmano le loro immagini con proprie Content Credentials. Le conserviamo come ingrediente delle nostre, come chiede il codice di buone pratiche dell’UE, e aggiungiamo la tua azienda e la tua app, la filigrana e i cinque elementi della California.

Prossimi passi