Skip to content

Commit a22cd7e

Browse files
georgeglarsonclaude
andcommitted
feat: align SDK types with Venice API swagger spec v20260314
Comprehensive audit and update of all type definitions against the official Venice API swagger spec. Adds missing parameters, fixes incorrect response types, and adds test/example coverage for previously undocumented features. Types: - chat: add enable_e2ee, enable_x_search, stop_token_ids, user, store, text, include; response logprobs, stop_reason, prompt_tokens_details, reasoning_content, tool_calls, venice_parameters echo with citations - multimodal: add InputAudioContent, VideoUrlContent, CacheControl - models: expand Model.type to 9 values, add ModelCapabilities (13 fields), ModelPricing variants, ~40 new ModelSpec fields - audio: add 9 Qwen 3 voices, fix transcription response (timestamps) - images: fix ListImageStylesResponse to match swagger (string[]) - characters: add id, author, featured, photoUrl, modelId, expanded stats, review types - responses: add XSearch, CodeInterpreter, FileSearch, ComputerUse tools - embeddings: make model required - video: clarify image_url required for i2v models Endpoints: - characters: add getReviews() method Tests: - chat: 6 new parameter pass-through tests - responses: new test file (16 tests) - keys: new test file (36 tests) Examples: - 15: add web scraping example - 20: function calling - 21: structured output (json_schema) - 22: reasoning config - 23: video generation workflow - 24: audio transcription Docs: - README: add examples 16-24, fix model names, standardize on VeniceAI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2c5a345 commit a22cd7e

21 files changed

Lines changed: 2101 additions & 2567 deletions

examples/README.md

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,30 @@ Production-ready patterns for experienced developers.
111111
| [12-streaming-with-abort.ts](typescript/12-streaming-with-abort.ts) | Cancellable streaming requests | AbortController, cleanup, timeouts |
112112
| [13-api-keys-management.ts](typescript/13-api-keys-management.ts) | Programmatic API key CRUD | Key management, metadata |
113113
| [14-rate-limit-handling.ts](typescript/14-rate-limit-handling.ts) | Rate limit strategies | Queuing, backoff, batch processing |
114-
| [15-custom-parameters.ts](typescript/15-custom-parameters.ts) | Venice-specific features | Web search, characters, parameters |
114+
| [15-custom-parameters.ts](typescript/15-custom-parameters.ts) | Venice-specific features | Web search, web scraping, characters, parameters |
115+
116+
### Professional Patterns
117+
118+
Production-ready patterns and SDK internals.
119+
120+
| Example | Description | Key Concepts |
121+
|---------|-------------|--------------|
122+
| [16-middleware-system.ts](typescript/16-middleware-system.ts) | Request/response middleware | Middleware pipeline, logging, timing |
123+
| [17-streaming-utilities.ts](typescript/17-streaming-utilities.ts) | Stream transformation utilities | Stream filtering, buffering, transforms |
124+
| [18-error-recovery.ts](typescript/18-error-recovery.ts) | Structured error recovery | Recovery hints, graceful degradation |
125+
| [19-model-discovery.ts](typescript/19-model-discovery.ts) | Finding models by capability | Model traits, filtering, compatibility |
126+
127+
### API Features
128+
129+
Examples demonstrating specific API capabilities.
130+
131+
| Example | Description | Key Concepts |
132+
|---------|-------------|--------------|
133+
| [20-function-calling.ts](typescript/20-function-calling.ts) | Tool/function calling | Tools, tool_choice, tool_calls, multi-turn |
134+
| [21-structured-output.ts](typescript/21-structured-output.ts) | Structured JSON responses | JSON schema, response_format, extraction |
135+
| [22-reasoning-config.ts](typescript/22-reasoning-config.ts) | Reasoning/thinking models | Reasoning effort, summary, thinking content |
136+
| [23-video-generation.ts](typescript/23-video-generation.ts) | Video generation workflow | Queue, retrieve, complete, polling |
137+
| [24-audio-transcription.ts](typescript/24-audio-transcription.ts) | Speech-to-text transcription | Audio transcription, timestamps, segments |
115138

116139
### Language-Specific Examples
117140

@@ -169,9 +192,9 @@ VENICE_LOG_LEVEL=1
169192
### Text Generation
170193

171194
```typescript
172-
import { VeniceClient } from '@venice-dev-tools/core';
195+
import { VeniceAI } from '@venice-dev-tools/core';
173196

174-
const client = new VeniceClient({ apiKey: process.env.VENICE_API_KEY });
197+
const client = new VeniceAI({ apiKey: process.env.VENICE_API_KEY! });
175198

176199
const response = await client.chat.completions.create({
177200
model: 'llama-3.3-70b',
@@ -235,7 +258,7 @@ See: [11-vision-multimodal.ts](typescript/11-vision-multimodal.ts)
235258

236259
```typescript
237260
const response = await client.embeddings.create({
238-
model: 'text-embedding-004',
261+
model: 'text-embedding-bge-m3',
239262
input: 'The quick brown fox jumps over the lazy dog',
240263
});
241264

@@ -249,9 +272,9 @@ See: [07-embeddings.ts](typescript/07-embeddings.ts)
249272

250273
```typescript
251274
const audio = await client.audio.speech.create({
252-
model: 'musicgen-stereo-small',
275+
model: 'tts-kokoro',
253276
input: 'Hello, this is a test of the Venice AI text to speech system.',
254-
voice: 'alloy',
277+
voice: 'af_sky',
255278
});
256279

257280
await fs.promises.writeFile('output.mp3', Buffer.from(await audio.arrayBuffer()));
@@ -294,7 +317,7 @@ See: [03-error-handling.ts](typescript/03-error-handling.ts)
294317
## Configuration Options
295318

296319
```typescript
297-
const client = new VeniceClient({
320+
const client = new VeniceAI({
298321
apiKey: process.env.VENICE_API_KEY,
299322

300323
// Timeout settings
@@ -372,7 +395,7 @@ bun run examples/typescript/01-hello-world.ts
372395

373396
**Solution:**
374397
```typescript
375-
const client = new VeniceClient({
398+
const client = new VeniceAI({
376399
apiKey: process.env.VENICE_API_KEY,
377400
timeout: 120000, // Increase to 120 seconds
378401
});
@@ -410,12 +433,12 @@ pnpm install
410433

411434
```typescript
412435
// ✅ Good
413-
const client = new VeniceClient({
436+
const client = new VeniceAI({
414437
apiKey: process.env.VENICE_API_KEY
415438
});
416439

417440
// ❌ Bad - never hardcode keys
418-
const client = new VeniceClient({
441+
const client = new VeniceAI({
419442
apiKey: 'sk-1234567890'
420443
});
421444
```
@@ -481,7 +504,7 @@ const stream = await client.chat.completions.create({
481504

482505
```typescript
483506
// ✅ Good - robust retry configuration
484-
const client = new VeniceClient({
507+
const client = new VeniceAI({
485508
apiKey: process.env.VENICE_API_KEY,
486509
retry: {
487510
maxRetries: 3,
@@ -493,7 +516,7 @@ const client = new VeniceClient({
493516
});
494517

495518
// ❌ Bad - default retry may not suit production needs
496-
const client = new VeniceClient({
519+
const client = new VeniceAI({
497520
apiKey: process.env.VENICE_API_KEY,
498521
});
499522
```

examples/typescript/15-custom-parameters.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*
77
* Features:
88
* - Web search integration
9+
* - Web scraping (Firecrawl) for URL content extraction
910
* - Character personas
1011
* - Custom system prompts
1112
* - Temperature and creativity controls
@@ -69,8 +70,35 @@ async function main() {
6970
console.error('❌ Error:', error.message);
7071
}
7172

72-
// Example 2: Character Personas
73-
console.log('\n👤 Example 2: Character Personas');
73+
// Example 2: Web Scraping (Firecrawl)
74+
console.log('\n🔍 Example 2: Web Scraping (URL Content Extraction)');
75+
console.log('═'.repeat(50));
76+
77+
try {
78+
const rawScrapingResponse = await venice.chat.completions.create({
79+
model: 'llama-3.3-70b',
80+
messages: [
81+
{
82+
role: 'user',
83+
content: 'Summarize the content at https://venice.ai/blog'
84+
}
85+
],
86+
venice_parameters: {
87+
enable_web_scraping: true, // Scrapes URLs in the user message via Firecrawl
88+
} as any
89+
});
90+
const scrapingResponse = ensureChatCompletionResponse(rawScrapingResponse, 'Web scraping example');
91+
92+
console.log('✅ Response with web scraping:');
93+
console.log(toText(scrapingResponse.choices[0].message.content));
94+
console.log('');
95+
96+
} catch (error: any) {
97+
console.error('❌ Error:', error.message);
98+
}
99+
100+
// Example 3: Character Personas
101+
console.log('\n👤 Example 3: Character Personas');
74102
console.log('═'.repeat(50));
75103

76104
try {
@@ -109,8 +137,8 @@ async function main() {
109137
console.error('❌ Error:', error.message);
110138
}
111139

112-
// Example 3: Creativity Controls
113-
console.log('\n🎨 Example 3: Creativity Controls');
140+
// Example 4: Creativity Controls
141+
console.log('\n🎨 Example 4: Creativity Controls');
114142
console.log('═'.repeat(50));
115143

116144
const prompt = 'Write a creative tagline for a coffee shop';
@@ -143,8 +171,8 @@ async function main() {
143171
console.log(toText(creativeResponse.choices[0].message.content));
144172
console.log('');
145173

146-
// Example 4: Response Format Control
147-
console.log('\n📋 Example 4: Response Format Control');
174+
// Example 5: Response Format Control
175+
console.log('\n📋 Example 5: Response Format Control');
148176
console.log('═'.repeat(50));
149177

150178
const rawFormatResponse = await venice.chat.completions.create({
@@ -175,6 +203,8 @@ async function main() {
175203
console.log('');
176204
console.log(' Venice-specific:');
177205
console.log(' • enable_web_search: real-time web results');
206+
console.log(' • enable_web_scraping: extract content from URLs via Firecrawl');
207+
console.log(' • enable_web_citations: annotate responses with sources');
178208
console.log(' • character_slug: use character personas');
179209
console.log(' • include_venice_system_prompt: use Venice defaults');
180210
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* Function Calling - Tool use with chat completions
3+
*
4+
* This example demonstrates how to use function/tool calling
5+
* with Venice AI's chat completions API.
6+
*
7+
* Features:
8+
* - Defining function tools with JSON Schema
9+
* - Automatic tool choice by the model
10+
* - Parsing tool_calls from assistant responses
11+
* - Sending tool results back with role: 'tool'
12+
* - Multi-turn conversation with tool use
13+
*
14+
* Prerequisites:
15+
* - VENICE_API_KEY environment variable set
16+
*
17+
* Run with: npx tsx examples/typescript/20-function-calling.ts
18+
*/
19+
20+
import { VeniceAI } from '@venice-dev-tools/core';
21+
import { ensureChatCompletionResponse } from './utils';
22+
import { requireEnv } from './env-config';
23+
24+
// Simulated weather database
25+
function getWeather(location: string, unit: string = 'fahrenheit'): string {
26+
const weatherData: Record<string, { temp_f: number; temp_c: number; condition: string }> = {
27+
'san francisco': { temp_f: 62, temp_c: 17, condition: 'foggy' },
28+
'new york': { temp_f: 78, temp_c: 26, condition: 'sunny' },
29+
'london': { temp_f: 59, temp_c: 15, condition: 'rainy' },
30+
'tokyo': { temp_f: 85, temp_c: 29, condition: 'humid' },
31+
};
32+
33+
const key = location.toLowerCase();
34+
const data = weatherData[key];
35+
if (!data) {
36+
return JSON.stringify({ error: `No weather data available for "${location}"` });
37+
}
38+
39+
const temp = unit === 'celsius' ? data.temp_c : data.temp_f;
40+
const unitLabel = unit === 'celsius' ? 'C' : 'F';
41+
return JSON.stringify({
42+
location,
43+
temperature: temp,
44+
unit: unitLabel,
45+
condition: data.condition,
46+
});
47+
}
48+
49+
// Define the tool for the model
50+
const weatherTool = {
51+
type: 'function' as const,
52+
function: {
53+
name: 'get_weather',
54+
description: 'Get the current weather for a given location',
55+
parameters: {
56+
type: 'object',
57+
properties: {
58+
location: {
59+
type: 'string',
60+
description: 'The city name, e.g. "San Francisco"',
61+
},
62+
unit: {
63+
type: 'string',
64+
enum: ['celsius', 'fahrenheit'],
65+
description: 'Temperature unit (default: fahrenheit)',
66+
},
67+
},
68+
required: ['location'],
69+
},
70+
},
71+
};
72+
73+
async function main() {
74+
const apiKey = requireEnv('VENICE_API_KEY');
75+
const venice = new VeniceAI({ apiKey });
76+
77+
console.log('🔧 Function Calling Demo\n');
78+
79+
// Step 1: Send a message that should trigger tool use
80+
console.log('📤 Step 1: Sending user message with tools defined');
81+
console.log('═'.repeat(50));
82+
83+
const messages: any[] = [
84+
{
85+
role: 'user',
86+
content: 'What is the weather like in San Francisco and Tokyo?',
87+
},
88+
];
89+
90+
try {
91+
const rawResponse = await venice.chat.completions.create({
92+
model: 'llama-3.3-70b',
93+
messages,
94+
tools: [weatherTool],
95+
tool_choice: 'auto',
96+
});
97+
const response = ensureChatCompletionResponse(rawResponse, 'Function calling step 1');
98+
99+
const assistantMessage = response.choices[0].message;
100+
console.log('✅ Model response received');
101+
102+
// Check if the model wants to call tools
103+
if (assistantMessage.tool_calls && assistantMessage.tool_calls.length > 0) {
104+
console.log(`🔧 Model requested ${assistantMessage.tool_calls.length} tool call(s):\n`);
105+
106+
// Add the assistant message (with tool_calls) to conversation
107+
messages.push(assistantMessage);
108+
109+
// Step 2: Execute each tool call and send results back
110+
console.log('📤 Step 2: Executing tool calls and sending results');
111+
console.log('═'.repeat(50));
112+
113+
for (const toolCall of assistantMessage.tool_calls) {
114+
const functionName = toolCall.function.name;
115+
const args = JSON.parse(toolCall.function.arguments);
116+
117+
console.log(` 📌 Calling: ${functionName}(${JSON.stringify(args)})`);
118+
119+
let result: string;
120+
if (functionName === 'get_weather') {
121+
result = getWeather(args.location, args.unit);
122+
} else {
123+
result = JSON.stringify({ error: `Unknown function: ${functionName}` });
124+
}
125+
126+
console.log(` 📋 Result: ${result}\n`);
127+
128+
// Add the tool result to the conversation
129+
messages.push({
130+
role: 'tool',
131+
tool_call_id: toolCall.id,
132+
content: result,
133+
});
134+
}
135+
136+
// Step 3: Get the final response with tool results
137+
console.log('📤 Step 3: Getting final response with tool results');
138+
console.log('═'.repeat(50));
139+
140+
const rawFinalResponse = await venice.chat.completions.create({
141+
model: 'llama-3.3-70b',
142+
messages,
143+
tools: [weatherTool],
144+
});
145+
const finalResponse = ensureChatCompletionResponse(rawFinalResponse, 'Function calling step 3');
146+
147+
const finalContent = finalResponse.choices[0].message.content;
148+
console.log('✅ Final response:');
149+
console.log(typeof finalContent === 'string' ? finalContent : JSON.stringify(finalContent));
150+
} else {
151+
// Model responded directly without tool calls
152+
console.log('ℹ️ Model responded without using tools:');
153+
const content = assistantMessage.content;
154+
console.log(typeof content === 'string' ? content : JSON.stringify(content));
155+
}
156+
157+
} catch (error: any) {
158+
console.error('❌ Error:', error.message);
159+
}
160+
161+
// Summary
162+
console.log('\n💡 Function Calling Tips:');
163+
console.log(' • Define tools with clear descriptions and JSON Schema parameters');
164+
console.log(' • Use tool_choice: "auto" to let the model decide when to call tools');
165+
console.log(' • Use tool_choice: "required" to force tool use');
166+
console.log(' • Always include tool_call_id when sending tool results back');
167+
console.log(' • The model can request multiple tool calls in a single response');
168+
}
169+
170+
main().catch((error) => {
171+
console.error('❌ Fatal error:', error.message);
172+
process.exit(1);
173+
});

0 commit comments

Comments
 (0)