Das Vercel AI SDK ist die beliebteste Möglichkeit, KI-Features in Next.js-, React-, Svelte- und Vue-Apps zu bauen. Venice funktioniert direkt als OpenAI-kompatibler Provider.
Einrichtung
npm install ai @ai-sdk/openai
Provider-Konfiguration
Erstelle einen Venice-Provider mit dem OpenAI-kompatiblen Adapter:
// lib/venice.ts
import { createOpenAI } from '@ai-sdk/openai' ;
const openai = createOpenAI ({
apiKey: process . env . VENICE_API_KEY ! ,
baseURL: 'https://api.venice.ai/api/v1' ,
});
// Verwende .chat(), um Kompatibilität mit Venices Chat-Completions-Endpoint sicherzustellen
export const venice = ( modelId : string ) => openai . chat ( modelId );
Das .chat() stellt sicher, dass Anfragen an Venices /chat/completions-Endpoint gehen. Die Standard-Syntax openai('model') verwendet möglicherweise neuere OpenAI-Endpoints, die Venice noch nicht unterstützt.
Streaming-Chat (Next.js App Router)
API-Route
// app/api/chat/route.ts
import { streamText } from 'ai' ;
import { venice } from '@/lib/venice' ;
export async function POST ( req : Request ) {
const { messages } = await req . json ();
const result = streamText ({
model: venice ( 'venice-uncensored' ),
system: 'You are a helpful, privacy-respecting AI assistant.' ,
messages ,
});
return result . toDataStreamResponse ();
}
React-Komponente
// app/page.tsx
'use client' ;
import { useChat } from '@ai-sdk/react' ;
export default function Chat () {
const { messages , input , handleInputChange , handleSubmit , isLoading } = useChat ();
return (
< div className = "max-w-2xl mx-auto p-4" >
< div className = "space-y-4 mb-4" >
{ messages . map (( m ) => (
< div key = { m . id } className = { m . role === 'user' ? 'text-right' : 'text-left' } >
< span className = "font-bold" > { m . role === 'user' ? 'You' : 'Venice' } : </ span >
< p className = "whitespace-pre-wrap" > { m . content } </ p >
</ div >
)) }
</ div >
< form onSubmit = { handleSubmit } className = "flex gap-2" >
< input
value = { input }
onChange = { handleInputChange }
placeholder = "Ask anything..."
className = "flex-1 border rounded px-3 py-2"
disabled = { isLoading }
/>
< button type = "submit" disabled = { isLoading } className = "bg-red-600 text-white px-4 py-2 rounded" >
Send
</ button >
</ form >
</ div >
);
}
Text generieren (ohne Streaming)
import { generateText } from 'ai' ;
import { venice } from '@/lib/venice' ;
const { text } = await generateText ({
model: venice ( 'zai-org-glm-5-1' ),
prompt: 'Explain zero-knowledge proofs in simple terms.' ,
});
console . log ( text );
Structured Output
import { generateObject } from 'ai' ;
import { venice } from '@/lib/venice' ;
import { z } from 'zod' ;
const { object } = await generateObject ({
model: venice ( 'venice-uncensored' ),
schema: z . object ({
recipe: z . object ({
name: z . string (),
ingredients: z . array ( z . string ()),
steps: z . array ( z . string ()),
prepTimeMinutes: z . number (),
}),
}),
prompt: 'Generate a recipe for chocolate chip cookies.' ,
});
console . log ( object . recipe . name );
console . log ( `Prep time: ${ object . recipe . prepTimeMinutes } minutes` );
import { streamText , tool } from 'ai' ;
import { venice } from '@/lib/venice' ;
import { z } from 'zod' ;
const result = streamText ({
model: venice ( 'zai-org-glm-5-1' ),
messages: [{ role: 'user' , content: 'What is the weather in Tokyo?' }],
tools: {
getWeather: tool ({
description: 'Get current weather for a location' ,
parameters: z . object ({
location: z . string (). describe ( 'City name' ),
}),
execute : async ({ location }) => {
// Hier dein Wetter-API-Aufruf
return { temperature: 22 , condition: 'Sunny' , location };
},
}),
},
});
for await ( const part of result . fullStream ) {
if ( part . type === 'text-delta' ) {
process . stdout . write ( part . textDelta );
} else if ( part . type === 'tool-result' ) {
console . log ( 'Tool result:' , part . result );
}
}
Image Generation
Venice Image Generation kann direkt parallel zum AI SDK aufgerufen werden:
// app/api/image/route.ts
export async function POST ( req : Request ) {
const { prompt } = await req . json ();
const response = await fetch ( 'https://api.venice.ai/api/v1/image/generate' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ process . env . VENICE_API_KEY } ` ,
'Content-Type' : 'application/json' ,
},
body: JSON . stringify ({
model: 'qwen-image' ,
prompt ,
width: 1024 ,
height: 1024 ,
}),
});
const data = await response . json ();
return Response . json ({ image: data . images [ 0 ] });
}
Multi-Model-Chat (Modellauswahl)
Lass Nutzer zwischen Venice-Modellen wählen:
// app/api/chat/route.ts
import { streamText } from 'ai' ;
import { venice } from '@/lib/venice' ;
const ALLOWED_MODELS = [
'venice-uncensored' ,
'zai-org-glm-5-1' ,
'qwen3-vl-235b-a22b' ,
'qwen3-5-9b' ,
];
export async function POST ( req : Request ) {
const { messages , model : modelId } = await req . json ();
if ( ! ALLOWED_MODELS . includes ( modelId )) {
return new Response ( 'Invalid model' , { status: 400 });
}
const result = streamText ({
model: venice ( modelId ),
messages ,
});
return result . toDataStreamResponse ();
}
// Client-Komponente mit Modellauswahl
'use client' ;
import { useChat } from '@ai-sdk/react' ;
import { useState } from 'react' ;
const MODELS = [
{ id: 'venice-uncensored' , name: 'Venice Uncensored' , desc: 'Fast & uncensored' },
{ id: 'zai-org-glm-5-1' , name: 'GLM 5.1' , desc: 'Most intelligent (private)' },
{ id: 'qwen3-vl-235b-a22b' , name: 'Qwen Vision' , desc: 'Advanced vision + text' },
{ id: 'qwen3-5-9b' , name: 'Qwen 3.5 9B' , desc: 'Fastest & cheapest' },
];
export default function Chat () {
const [ model , setModel ] = useState ( 'venice-uncensored' );
const { messages , input , handleInputChange , handleSubmit } = useChat ({
body: { model },
});
return (
< div >
< select value = { model } onChange = { ( e ) => setModel ( e . target . value ) } >
{ MODELS . map (( m ) => (
< option key = { m . id } value = { m . id } > { m . name } — { m . desc } </ option >
)) }
</ select >
{ /* ... Chat-UI ... */ }
</ div >
);
}
Web-Search-Integration
Übergib Venice-Parameter für die Websuche:
import { streamText } from 'ai' ;
import { venice } from '@/lib/venice' ;
const result = streamText ({
model: venice ( 'venice-uncensored' ),
messages: [{ role: 'user' , content: 'What happened in AI news today?' }],
// Venice-spezifische Parameter
experimental_providerMetadata: {
venice_parameters: {
enable_web_search: 'auto' ,
},
},
});
Wenn experimental_providerMetadata nicht durchgereicht wird, kannst du einen Custom-Fetch-Wrapper verwenden oder die Venice-API für Web-Search-Features direkt aufrufen.
Embeddings
Verwende für Embeddings textEmbeddingModel() direkt auf dem Provider:
import { embed , embedMany } from 'ai' ;
import { createOpenAI } from '@ai-sdk/openai' ;
const openai = createOpenAI ({
apiKey: process . env . VENICE_API_KEY ! ,
baseURL: 'https://api.venice.ai/api/v1' ,
});
// Einzelnes Embedding
const { embedding } = await embed ({
model: openai . textEmbeddingModel ( 'text-embedding-bge-m3' ),
value: 'Privacy-first AI infrastructure' ,
});
// Batch-Embeddings
const { embeddings } = await embedMany ({
model: openai . textEmbeddingModel ( 'text-embedding-bge-m3' ),
values: [
'Venice AI provides private inference.' ,
'Zero data retention guaranteed.' ,
'OpenAI SDK compatible.' ,
],
});
Umgebungsvariablen
# .env.local
VENICE_API_KEY = your-venice-api-key
Empfohlene Modelle
Anwendungsfall Modell Warum Chat-Apps venice-uncensoredSchnell, günstig, keine Filterung Komplexe Aufgaben zai-org-glm-5-1Privates Flaggschiff-Reasoning Vision-Apps qwen3-vl-235b-a22bFortschrittliches Bildverständnis Hohes Volumen qwen3-5-9bGünstigstes mit $0,10/1M Input, $0,15/1M Output Tool Calling zai-org-glm-5-1Zuverlässiges Function Calling
Vercel AI SDK Docs Offizielle Vercel AI SDK-Dokumentation
Venice-Modelle Alle Venice-Modelle durchsuchen