Skip to content

Commit 0826d4f

Browse files
Add basic AI SDK example extracted from wrapper repo
1 parent 2fbc45d commit 0826d4f

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
/**
2+
* Idiomatic Vercel AI SDK example with OpenRouter provider
3+
*
4+
* This example demonstrates key AI SDK concepts:
5+
* - Creating and configuring the OpenRouter provider
6+
* - Using generateText for non-streaming chat completions
7+
* - Using streamText for streaming responses
8+
* - Defining and using tools (function calling)
9+
* - Usage accounting to track token usage and costs
10+
* - Multi-turn conversations with system messages
11+
*/
12+
13+
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
14+
import { generateText, streamText, tool } from 'ai';
15+
import { z } from 'zod';
16+
17+
// Create the OpenRouter provider instance
18+
// The provider acts as a factory for creating model instances
19+
const openrouter = createOpenRouter({
20+
apiKey: process.env.OPENROUTER_API_KEY,
21+
});
22+
23+
// Example 1: Simple text generation (non-streaming)
24+
async function simpleGeneration() {
25+
console.log('\n=== Example 1: Simple Text Generation ===\n');
26+
27+
// Create a model instance - each model can have its own configuration
28+
const model = openrouter('openai/gpt-4o-mini');
29+
30+
// generateText returns the complete response once generation is finished
31+
const { text, usage, finishReason } = await generateText({
32+
model,
33+
prompt: 'Explain what the Vercel AI SDK is in one sentence.',
34+
});
35+
36+
console.log('Response:', text);
37+
console.log('\nUsage:', usage);
38+
console.log('Finish Reason:', finishReason);
39+
}
40+
41+
// Example 2: Streaming text generation
42+
async function streamingGeneration() {
43+
console.log('\n=== Example 2: Streaming Text Generation ===\n');
44+
45+
const model = openrouter('openai/gpt-4o-mini');
46+
47+
// streamText returns a stream that yields tokens as they're generated
48+
const result = streamText({
49+
model,
50+
prompt: 'Write a haiku about TypeScript.',
51+
});
52+
53+
// Stream the response token by token
54+
process.stdout.write('Streaming response: ');
55+
for await (const chunk of result.textStream) {
56+
process.stdout.write(chunk);
57+
}
58+
console.log('\n');
59+
60+
// After streaming completes, you can access the full response and metadata
61+
const finalText = await result.text;
62+
const finalUsage = await result.usage;
63+
console.log('Final text length:', finalText.length, 'characters');
64+
console.log('Tokens used:', finalUsage.totalTokens);
65+
}
66+
67+
// Example 3: Tools (Function Calling)
68+
async function toolCalling() {
69+
console.log('\n=== Example 3: Tools (Function Calling) ===\n');
70+
71+
// Define tools using the tool() helper and Zod schemas
72+
// Tools allow the model to call functions to perform actions or retrieve data
73+
// Note: Use 'inputSchema' not 'parameters' for AI SDK v5
74+
const weatherTool = tool({
75+
description: 'Get the current weather for a location',
76+
inputSchema: z.object({
77+
location: z.string().describe('The city and country, e.g., San Francisco, CA'),
78+
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
79+
}),
80+
execute: async (params) => {
81+
// In a real app, you'd call a weather API here
82+
return {
83+
location: params.location,
84+
temperature: params.unit === 'celsius' ? 22 : 72,
85+
unit: params.unit,
86+
condition: 'Partly cloudy',
87+
};
88+
},
89+
});
90+
91+
const calculatorTool = tool({
92+
description: 'Perform basic arithmetic calculations',
93+
inputSchema: z.object({
94+
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
95+
a: z.number(),
96+
b: z.number(),
97+
}),
98+
execute: async (params) => {
99+
const operations: Record<string, number | string> = {
100+
add: params.a + params.b,
101+
subtract: params.a - params.b,
102+
multiply: params.a * params.b,
103+
divide: params.b !== 0 ? params.a / params.b : 'Cannot divide by zero',
104+
};
105+
return { result: operations[params.operation] };
106+
},
107+
});
108+
109+
const model = openrouter('openai/gpt-4o-mini');
110+
111+
// generateText with tools automatically handles tool calls
112+
// The SDK will call tools as needed and include results in the conversation
113+
const { text, toolCalls, toolResults } = await generateText({
114+
model,
115+
prompt: "What's the weather in Tokyo, Japan? Also, what's 42 multiplied by 17?",
116+
tools: {
117+
getWeather: weatherTool,
118+
calculate: calculatorTool,
119+
},
120+
});
121+
122+
console.log('Final Response:', text);
123+
console.log('\nTool Calls:', toolCalls);
124+
console.log('Tool Results:', toolResults);
125+
}
126+
127+
// Example 4: Usage Accounting
128+
async function usageAccounting() {
129+
console.log('\n=== Example 4: Usage Accounting ===\n');
130+
131+
// Enable usage accounting to get detailed token usage and cost information
132+
// This is an OpenRouter-specific feature that provides cost tracking
133+
const model = openrouter('openai/gpt-4o-mini', {
134+
usage: {
135+
include: true, // Request detailed usage information
136+
},
137+
});
138+
139+
const result = await generateText({
140+
model,
141+
prompt: 'What are the benefits of using TypeScript?',
142+
});
143+
144+
console.log('Response:', result.text);
145+
console.log('\nStandard Usage:', result.usage);
146+
147+
// OpenRouter-specific metadata with cost information
148+
if (result.providerMetadata?.openrouter?.usage) {
149+
const usage = result.providerMetadata.openrouter.usage as any;
150+
console.log('\nOpenRouter Usage Details:');
151+
console.log('- Total Tokens:', usage.totalTokens);
152+
console.log('- Prompt Tokens:', usage.promptTokens);
153+
console.log('- Completion Tokens:', usage.completionTokens);
154+
if (usage.cost) {
155+
console.log('- Cost: $' + usage.cost.toFixed(6));
156+
}
157+
}
158+
}
159+
160+
// Example 5: Multi-turn conversation with system messages
161+
async function conversationExample() {
162+
console.log('\n=== Example 5: Multi-turn Conversation ===\n');
163+
164+
const model = openrouter('openai/gpt-4o-mini');
165+
166+
// Use messages array for multi-turn conversations
167+
// System messages set the behavior and context for the model
168+
const { text } = await generateText({
169+
model,
170+
system: 'You are a helpful coding assistant specializing in TypeScript and modern web development.',
171+
messages: [
172+
{
173+
role: 'user',
174+
content: 'How do I define a generic function in TypeScript?',
175+
},
176+
{
177+
role: 'assistant',
178+
content: 'You define a generic function using angle brackets with a type parameter, like this: `function identity<T>(arg: T): T { return arg; }`',
179+
},
180+
{
181+
role: 'user',
182+
content: 'Can you show me an example with multiple type parameters?',
183+
},
184+
],
185+
});
186+
187+
console.log('Assistant:', text);
188+
}
189+
190+
// Example 6: Provider-specific options
191+
async function providerOptions() {
192+
console.log('\n=== Example 6: Provider-Specific Options ===\n');
193+
194+
const model = openrouter('openai/gpt-4o-mini');
195+
196+
// You can pass OpenRouter-specific options via providerOptions
197+
// Different providers support different options
198+
const { text } = await generateText({
199+
model,
200+
prompt: 'Tell me about OpenRouter.',
201+
providerOptions: {
202+
openrouter: {
203+
// OpenRouter-specific options can be passed here
204+
// For example, transforms or other provider features
205+
},
206+
},
207+
});
208+
209+
console.log('Response:', text);
210+
}
211+
212+
// Run all examples
213+
async function main() {
214+
console.log('Vercel AI SDK with OpenRouter Provider Examples');
215+
console.log('='.repeat(50));
216+
217+
try {
218+
await simpleGeneration();
219+
await streamingGeneration();
220+
await toolCalling();
221+
await usageAccounting();
222+
await conversationExample();
223+
await providerOptions();
224+
225+
console.log('\n' + '='.repeat(50));
226+
console.log('All examples completed successfully!');
227+
} catch (error) {
228+
console.error('\nError:', error);
229+
process.exit(1);
230+
}
231+
}
232+
233+
// Execute if run directly
234+
main();

0 commit comments

Comments
 (0)