The Vercel AI SDK is the most popular way to build AI features in Next.js, React, Svelte, and Vue apps. Venice works out of the box as an OpenAI-compatible provider.
Setup
npm install ai @ai-sdk/openai
Provider Configuration
Create a Venice provider using the OpenAI-compatible 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',
});
// Use .chat() to ensure compatibility with Venice's chat completions endpoint
export const venice = (modelId: string) => openai.chat(modelId);
Using .chat() ensures requests go to Venice’s /chat/completions endpoint. The default openai('model') syntax may use newer OpenAI endpoints that Venice doesn’t support yet.
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 Component
// 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>
);
}
Generating Text (Non-Streaming)
import { generateText } from 'ai';
import { venice } from '@/lib/venice';
const { text } = await generateText({
model: venice('zai-org-glm-4.7'),
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-4.7'),
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 }) => {
// Your weather API call here
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 can be called directly alongside the AI SDK:
// 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 (Model Selector)
Let users choose between Venice models:
// app/api/chat/route.ts
import { streamText } from 'ai';
import { venice } from '@/lib/venice';
const ALLOWED_MODELS = [
'venice-uncensored',
'zai-org-glm-4.7',
'qwen3-vl-235b-a22b',
'qwen3-4b',
];
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 component with model selector
'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-4.7', name: 'GLM 4.7', desc: 'Most intelligent (private)' },
{ id: 'qwen3-vl-235b-a22b', name: 'Qwen Vision', desc: 'Advanced vision + text' },
{ id: 'qwen3-4b', name: 'Venice Small', 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
Pass Venice parameters for web search:
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-specific parameters
experimental_providerMetadata: {
venice_parameters: {
enable_web_search: 'auto',
},
},
});
If experimental_providerMetadata doesn’t pass through, you can use a custom fetch wrapper or call the Venice API directly for web search features.
Embeddings
For embeddings, use textEmbeddingModel() on the provider directly:
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',
});
// Single 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.',
],
});
Environment Variables
# .env.local
VENICE_API_KEY=your-venice-api-key
Recommended Models
| Use Case | Model | Why |
|---|
| Chat apps | venice-uncensored | Fast, cheap, no filtering |
| Complex tasks | zai-org-glm-4.7 | Private flagship reasoning |
| Vision apps | qwen3-vl-235b-a22b | Advanced image understanding |
| High-volume | qwen3-4b | Cheapest at $0.05/1M |
| Tool calling | zai-org-glm-4.7 | Reliable function calling |