@revenium/openai 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +20 -0
- package/CHANGELOG.md +21 -47
- package/README.md +141 -690
- package/dist/cjs/core/config/loader.js +1 -1
- package/dist/cjs/core/config/loader.js.map +1 -1
- package/dist/cjs/core/tracking/api-client.js +1 -1
- package/dist/cjs/core/tracking/api-client.js.map +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/utils/url-builder.js +32 -7
- package/dist/cjs/utils/url-builder.js.map +1 -1
- package/dist/esm/core/config/loader.js +1 -1
- package/dist/esm/core/config/loader.js.map +1 -1
- package/dist/esm/core/tracking/api-client.js +1 -1
- package/dist/esm/core/tracking/api-client.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/url-builder.js +32 -7
- package/dist/esm/utils/url-builder.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types/index.d.ts +2 -2
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/utils/url-builder.d.ts +11 -3
- package/dist/types/utils/url-builder.d.ts.map +1 -1
- package/examples/README.md +250 -254
- package/examples/azure-basic.ts +25 -13
- package/examples/azure-responses-basic.ts +36 -7
- package/examples/azure-responses-streaming.ts +36 -7
- package/examples/azure-streaming.ts +40 -19
- package/examples/getting_started.ts +54 -0
- package/examples/openai-basic.ts +39 -17
- package/examples/openai-function-calling.ts +259 -0
- package/examples/openai-responses-basic.ts +36 -7
- package/examples/openai-responses-streaming.ts +36 -7
- package/examples/openai-streaming.ts +24 -13
- package/examples/openai-vision.ts +289 -0
- package/package.json +3 -9
- package/src/core/config/azure-config.ts +72 -0
- package/src/core/config/index.ts +23 -0
- package/src/core/config/loader.ts +66 -0
- package/src/core/config/manager.ts +94 -0
- package/src/core/config/validator.ts +89 -0
- package/src/core/providers/detector.ts +159 -0
- package/src/core/providers/index.ts +16 -0
- package/src/core/tracking/api-client.ts +78 -0
- package/src/core/tracking/index.ts +21 -0
- package/src/core/tracking/payload-builder.ts +132 -0
- package/src/core/tracking/usage-tracker.ts +189 -0
- package/src/core/wrapper/index.ts +9 -0
- package/src/core/wrapper/instance-patcher.ts +288 -0
- package/src/core/wrapper/request-handler.ts +423 -0
- package/src/core/wrapper/stream-wrapper.ts +100 -0
- package/src/index.ts +336 -0
- package/src/types/function-parameters.ts +251 -0
- package/src/types/index.ts +313 -0
- package/src/types/openai-augmentation.ts +233 -0
- package/src/types/responses-api.ts +308 -0
- package/src/utils/azure-model-resolver.ts +220 -0
- package/src/utils/constants.ts +21 -0
- package/src/utils/error-handler.ts +251 -0
- package/src/utils/metadata-builder.ts +219 -0
- package/src/utils/provider-detection.ts +257 -0
- package/src/utils/request-handler-factory.ts +285 -0
- package/src/utils/stop-reason-mapper.ts +74 -0
- package/src/utils/type-guards.ts +202 -0
- package/src/utils/url-builder.ts +68 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Function Calling Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how Revenium middleware seamlessly tracks function/tool calling usage
|
|
5
|
+
* with OpenAI chat completions. Shows automatic tracking of:
|
|
6
|
+
* - Function definitions and calls
|
|
7
|
+
* - Token usage including function call overhead
|
|
8
|
+
* - Multi-turn conversations with function execution
|
|
9
|
+
* - Cost calculation for function calling features
|
|
10
|
+
*
|
|
11
|
+
* All metadata fields are optional and work seamlessly with function calling!
|
|
12
|
+
*
|
|
13
|
+
* For complete metadata field reference, see:
|
|
14
|
+
* https://revenium.readme.io/reference/meter_ai_completion
|
|
15
|
+
*
|
|
16
|
+
* OpenAI Function Calling Reference:
|
|
17
|
+
* https://platform.openai.com/docs/guides/function-calling
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import 'dotenv/config';
|
|
21
|
+
import { initializeReveniumFromEnv, patchOpenAIInstance } from '@revenium/openai';
|
|
22
|
+
import OpenAI from 'openai';
|
|
23
|
+
|
|
24
|
+
// Simulated weather API function
|
|
25
|
+
function getCurrentWeather(location: string, unit: 'celsius' | 'fahrenheit' = 'celsius'): string {
|
|
26
|
+
// Simulate weather data
|
|
27
|
+
const temperature = unit === 'celsius' ? 22 : 72;
|
|
28
|
+
const conditions = 'sunny';
|
|
29
|
+
|
|
30
|
+
return JSON.stringify({
|
|
31
|
+
location,
|
|
32
|
+
temperature,
|
|
33
|
+
unit,
|
|
34
|
+
conditions,
|
|
35
|
+
forecast: 'Clear skies throughout the day',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function openAIFunctionCallingExample() {
|
|
40
|
+
console.log('🔧 OpenAI Function Calling with Revenium Tracking\n');
|
|
41
|
+
|
|
42
|
+
// Initialize Revenium middleware
|
|
43
|
+
const initResult = initializeReveniumFromEnv();
|
|
44
|
+
if (!initResult.success) {
|
|
45
|
+
console.error('❌ Failed to initialize Revenium:', initResult.message);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Create and patch OpenAI instance
|
|
50
|
+
const openai = patchOpenAIInstance(new OpenAI());
|
|
51
|
+
|
|
52
|
+
// Define function schema for OpenAI
|
|
53
|
+
const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
|
|
54
|
+
{
|
|
55
|
+
type: 'function',
|
|
56
|
+
function: {
|
|
57
|
+
name: 'get_current_weather',
|
|
58
|
+
description: 'Get the current weather in a given location',
|
|
59
|
+
parameters: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
location: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'The city and state, e.g. San Francisco, CA',
|
|
65
|
+
},
|
|
66
|
+
unit: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
enum: ['celsius', 'fahrenheit'],
|
|
69
|
+
description: 'The temperature unit to use',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
required: ['location'],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// Example 1: Function calling without metadata (automatic tracking)
|
|
79
|
+
console.log('📍 Example 1: Basic function calling (automatic tracking)\n');
|
|
80
|
+
|
|
81
|
+
const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
|
|
82
|
+
{
|
|
83
|
+
role: 'user',
|
|
84
|
+
content: "What's the weather like in San Francisco?",
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// First call - AI decides to use the function
|
|
89
|
+
const firstResponse = await openai.chat.completions.create({
|
|
90
|
+
model: 'gpt-4o-mini',
|
|
91
|
+
messages: messages,
|
|
92
|
+
tools: tools,
|
|
93
|
+
tool_choice: 'auto',
|
|
94
|
+
// No usageMetadata - still automatically tracked!
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
console.log('AI Response (First call):');
|
|
98
|
+
console.log('Usage:', firstResponse.usage);
|
|
99
|
+
|
|
100
|
+
const firstMessage = firstResponse.choices[0]?.message;
|
|
101
|
+
console.log('Finish reason:', firstResponse.choices[0]?.finish_reason);
|
|
102
|
+
|
|
103
|
+
// Check if AI wants to call a function
|
|
104
|
+
if (firstMessage?.tool_calls) {
|
|
105
|
+
console.log('\n🔧 AI decided to call function:', firstMessage.tool_calls[0]?.function.name);
|
|
106
|
+
console.log('Function arguments:', firstMessage.tool_calls[0]?.function.arguments);
|
|
107
|
+
|
|
108
|
+
// Execute the function
|
|
109
|
+
const functionCall = firstMessage.tool_calls[0];
|
|
110
|
+
const functionArgs = JSON.parse(functionCall?.function.arguments || '{}');
|
|
111
|
+
const functionResponse = getCurrentWeather(
|
|
112
|
+
functionArgs.location,
|
|
113
|
+
functionArgs.unit
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
console.log('Function result:', functionResponse);
|
|
117
|
+
|
|
118
|
+
// Add function call and result to conversation
|
|
119
|
+
messages.push(firstMessage);
|
|
120
|
+
messages.push({
|
|
121
|
+
role: 'tool',
|
|
122
|
+
tool_call_id: functionCall.id,
|
|
123
|
+
content: functionResponse,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Second call - AI uses function result to answer
|
|
127
|
+
const secondResponse = await openai.chat.completions.create({
|
|
128
|
+
model: 'gpt-4o-mini',
|
|
129
|
+
messages: messages,
|
|
130
|
+
tools: tools,
|
|
131
|
+
// No usageMetadata - still automatically tracked!
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
console.log('\n💬 AI Final Response:');
|
|
135
|
+
console.log('Content:', secondResponse.choices[0]?.message?.content);
|
|
136
|
+
console.log('Usage:', secondResponse.usage);
|
|
137
|
+
console.log('✅ Function calling automatically tracked without metadata\n');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Example 2: Function calling with rich metadata
|
|
141
|
+
console.log('📊 Example 2: Function calling with comprehensive metadata\n');
|
|
142
|
+
|
|
143
|
+
const metadataMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
|
|
144
|
+
{
|
|
145
|
+
role: 'user',
|
|
146
|
+
content: "I'm planning a trip. What's the weather in Boston and should I bring a jacket?",
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
// First call with metadata
|
|
151
|
+
const metadataFirstResponse = await openai.chat.completions.create({
|
|
152
|
+
model: 'gpt-4o',
|
|
153
|
+
messages: metadataMessages,
|
|
154
|
+
tools: tools,
|
|
155
|
+
tool_choice: 'auto',
|
|
156
|
+
|
|
157
|
+
// ✨ All metadata fields are optional - perfect for tracking AI agents!
|
|
158
|
+
usageMetadata: {
|
|
159
|
+
subscriber: {
|
|
160
|
+
id: 'travel-user-456',
|
|
161
|
+
email: 'traveler@company.com',
|
|
162
|
+
credential: {
|
|
163
|
+
name: 'api-key',
|
|
164
|
+
value: 'travel-key-789',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
organizationId: 'travel-agency-corp',
|
|
168
|
+
productId: 'ai-travel-assistant',
|
|
169
|
+
subscriptionId: 'sub-pro-travel-123',
|
|
170
|
+
taskType: 'function-calling-weather',
|
|
171
|
+
traceId: `func-call-${Date.now()}`,
|
|
172
|
+
agent: 'weather-assistant-node',
|
|
173
|
+
responseQualityScore: 0.95,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
console.log('AI Response with Metadata (First call):');
|
|
178
|
+
console.log('Usage:', metadataFirstResponse.usage);
|
|
179
|
+
|
|
180
|
+
const metadataFirstMessage = metadataFirstResponse.choices[0]?.message;
|
|
181
|
+
console.log('Finish reason:', metadataFirstResponse.choices[0]?.finish_reason);
|
|
182
|
+
|
|
183
|
+
// Process function calls if any
|
|
184
|
+
if (metadataFirstMessage?.tool_calls) {
|
|
185
|
+
console.log('\n🔧 Function calls requested:', metadataFirstMessage.tool_calls.length);
|
|
186
|
+
|
|
187
|
+
// Execute each function call
|
|
188
|
+
for (const toolCall of metadataFirstMessage.tool_calls) {
|
|
189
|
+
console.log(' - Function:', toolCall.function.name);
|
|
190
|
+
console.log(' Arguments:', toolCall.function.arguments);
|
|
191
|
+
|
|
192
|
+
const functionArgs = JSON.parse(toolCall.function.arguments);
|
|
193
|
+
const functionResponse = getCurrentWeather(
|
|
194
|
+
functionArgs.location,
|
|
195
|
+
functionArgs.unit
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
console.log(' Result:', functionResponse);
|
|
199
|
+
|
|
200
|
+
// Add function result to conversation
|
|
201
|
+
metadataMessages.push(metadataFirstMessage);
|
|
202
|
+
metadataMessages.push({
|
|
203
|
+
role: 'tool',
|
|
204
|
+
tool_call_id: toolCall.id,
|
|
205
|
+
content: functionResponse,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Second call with metadata - AI generates final response
|
|
210
|
+
const metadataSecondResponse = await openai.chat.completions.create({
|
|
211
|
+
model: 'gpt-4o',
|
|
212
|
+
messages: metadataMessages,
|
|
213
|
+
tools: tools,
|
|
214
|
+
|
|
215
|
+
// ✨ Same metadata carried through the conversation
|
|
216
|
+
usageMetadata: {
|
|
217
|
+
subscriber: {
|
|
218
|
+
id: 'travel-user-456',
|
|
219
|
+
email: 'traveler@company.com',
|
|
220
|
+
credential: {
|
|
221
|
+
name: 'api-key',
|
|
222
|
+
value: 'travel-key-789',
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
organizationId: 'travel-agency-corp',
|
|
226
|
+
productId: 'ai-travel-assistant',
|
|
227
|
+
subscriptionId: 'sub-pro-travel-123',
|
|
228
|
+
taskType: 'function-calling-weather',
|
|
229
|
+
traceId: `func-call-${Date.now()}`,
|
|
230
|
+
agent: 'weather-assistant-node',
|
|
231
|
+
responseQualityScore: 0.98,
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
console.log('\n💬 AI Final Response with Metadata:');
|
|
236
|
+
console.log('Content:', metadataSecondResponse.choices[0]?.message?.content);
|
|
237
|
+
console.log('Usage:', metadataSecondResponse.usage);
|
|
238
|
+
console.log('✅ Function calling tracked with rich metadata for AI agent analytics\n');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Summary
|
|
242
|
+
console.log('📈 Function Calling Summary:');
|
|
243
|
+
console.log('✅ Function definitions work seamlessly with middleware');
|
|
244
|
+
console.log('✅ Token usage tracked including function call overhead');
|
|
245
|
+
console.log('✅ Multi-turn conversations fully supported');
|
|
246
|
+
console.log('✅ All metadata fields optional and work perfectly');
|
|
247
|
+
console.log('✅ Cost calculation includes function calling tokens');
|
|
248
|
+
console.log('✅ No type casting required - native TypeScript support');
|
|
249
|
+
console.log('✅ Perfect for tracking AI agents and tool usage\n');
|
|
250
|
+
|
|
251
|
+
console.log('💡 Use Cases:');
|
|
252
|
+
console.log(' - AI agents with tool access');
|
|
253
|
+
console.log(' - Customer support bots with API integrations');
|
|
254
|
+
console.log(' - Data analysis assistants with function execution');
|
|
255
|
+
console.log(' - Multi-step workflows with external tools');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Run the example
|
|
259
|
+
openAIFunctionCallingExample().catch(console.error);
|
|
@@ -5,7 +5,16 @@
|
|
|
5
5
|
* The Responses API is a new stateful API that brings together capabilities from chat completions
|
|
6
6
|
* and assistants API in one unified experience.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Metadata Options:
|
|
9
|
+
* - Start with basic usage (no metadata) - tracking works automatically
|
|
10
|
+
* - Add subscriber info for user tracking
|
|
11
|
+
* - Include organization/product IDs for business analytics
|
|
12
|
+
* - Use task type and trace ID for detailed analysis
|
|
13
|
+
*
|
|
14
|
+
* For complete metadata field reference, see:
|
|
15
|
+
* https://revenium.readme.io/reference/meter_ai_completion
|
|
16
|
+
*
|
|
17
|
+
* Responses API Reference: https://platform.openai.com/docs/api-reference/responses
|
|
9
18
|
*/
|
|
10
19
|
|
|
11
20
|
import 'dotenv/config';
|
|
@@ -71,19 +80,29 @@ async function main() {
|
|
|
71
80
|
],
|
|
72
81
|
max_output_tokens: 150,
|
|
73
82
|
usageMetadata: {
|
|
83
|
+
// User identification
|
|
74
84
|
subscriber: {
|
|
75
85
|
id: 'user-123',
|
|
76
86
|
email: 'user@example.com',
|
|
77
87
|
credential: {
|
|
78
|
-
name: 'api-key',
|
|
79
|
-
value: '
|
|
88
|
+
name: 'api-key-prod',
|
|
89
|
+
value: 'key-efg-123',
|
|
80
90
|
},
|
|
81
91
|
},
|
|
92
|
+
|
|
93
|
+
// Organization & billing
|
|
82
94
|
organizationId: 'org-456',
|
|
95
|
+
subscriptionId: 'plan-responses-2024',
|
|
96
|
+
|
|
97
|
+
// Product & task tracking
|
|
83
98
|
productId: 'quantum-explainer',
|
|
84
99
|
taskType: 'educational-content',
|
|
85
|
-
traceId: 'trace-789',
|
|
86
100
|
agent: 'quantum-tutor',
|
|
101
|
+
|
|
102
|
+
// Session tracking
|
|
103
|
+
traceId: 'trace-789',
|
|
104
|
+
|
|
105
|
+
// Quality metrics
|
|
87
106
|
responseQualityScore: 0.95,
|
|
88
107
|
},
|
|
89
108
|
} as ResponsesCreateParams);
|
|
@@ -146,19 +165,29 @@ async function main() {
|
|
|
146
165
|
max_output_tokens: 200,
|
|
147
166
|
instructions: 'You are a helpful AI assistant specializing in API documentation.',
|
|
148
167
|
usageMetadata: {
|
|
168
|
+
// User identification
|
|
149
169
|
subscriber: {
|
|
150
170
|
id: 'enterprise-user-456',
|
|
151
171
|
email: 'enterprise@company.com',
|
|
152
172
|
credential: {
|
|
153
|
-
name: '
|
|
154
|
-
value: '
|
|
173
|
+
name: 'api-key-prod',
|
|
174
|
+
value: 'key-hij-456',
|
|
155
175
|
},
|
|
156
176
|
},
|
|
177
|
+
|
|
178
|
+
// Organization & billing
|
|
157
179
|
organizationId: 'enterprise-org-789',
|
|
180
|
+
subscriptionId: 'plan-enterprise-docs-2024',
|
|
181
|
+
|
|
182
|
+
// Product & task tracking
|
|
158
183
|
productId: 'api-documentation-assistant',
|
|
159
184
|
taskType: 'technical-documentation',
|
|
160
|
-
traceId: 'enterprise-trace-012',
|
|
161
185
|
agent: 'documentation-expert',
|
|
186
|
+
|
|
187
|
+
// Session tracking
|
|
188
|
+
traceId: 'enterprise-trace-012',
|
|
189
|
+
|
|
190
|
+
// Quality metrics
|
|
162
191
|
responseQualityScore: 0.98,
|
|
163
192
|
},
|
|
164
193
|
} as ResponsesCreateParams);
|
|
@@ -5,7 +5,16 @@
|
|
|
5
5
|
* using the Revenium middleware. The Responses API supports streaming for real-time
|
|
6
6
|
* response generation.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Metadata Options:
|
|
9
|
+
* - Start with basic usage (no metadata) - tracking works automatically
|
|
10
|
+
* - Add subscriber info for user tracking
|
|
11
|
+
* - Include organization/product IDs for business analytics
|
|
12
|
+
* - Use task type and trace ID for detailed analysis
|
|
13
|
+
*
|
|
14
|
+
* For complete metadata field reference, see:
|
|
15
|
+
* https://revenium.readme.io/reference/meter_ai_completion
|
|
16
|
+
*
|
|
17
|
+
* Responses API Reference: https://platform.openai.com/docs/api-reference/responses
|
|
9
18
|
*/
|
|
10
19
|
|
|
11
20
|
import 'dotenv/config';
|
|
@@ -75,19 +84,29 @@ async function main() {
|
|
|
75
84
|
stream: true,
|
|
76
85
|
max_output_tokens: 200,
|
|
77
86
|
usageMetadata: {
|
|
87
|
+
// User identification
|
|
78
88
|
subscriber: {
|
|
79
89
|
id: 'streaming-user-123',
|
|
80
90
|
email: 'streaming@example.com',
|
|
81
91
|
credential: {
|
|
82
|
-
name: '
|
|
83
|
-
value: '
|
|
92
|
+
name: 'api-key-prod',
|
|
93
|
+
value: 'key-klm-789',
|
|
84
94
|
},
|
|
85
95
|
},
|
|
96
|
+
|
|
97
|
+
// Organization & billing
|
|
86
98
|
organizationId: 'streaming-org-456',
|
|
99
|
+
subscriptionId: 'plan-streaming-edu-2024',
|
|
100
|
+
|
|
101
|
+
// Product & task tracking
|
|
87
102
|
productId: 'ml-educator',
|
|
88
103
|
taskType: 'educational-streaming',
|
|
89
|
-
traceId: 'stream-trace-789',
|
|
90
104
|
agent: 'ml-tutor-stream',
|
|
105
|
+
|
|
106
|
+
// Session tracking
|
|
107
|
+
traceId: 'stream-trace-789',
|
|
108
|
+
|
|
109
|
+
// Quality metrics
|
|
91
110
|
responseQualityScore: 0.92,
|
|
92
111
|
},
|
|
93
112
|
} as ResponsesCreateParams);
|
|
@@ -163,19 +182,29 @@ async function main() {
|
|
|
163
182
|
instructions:
|
|
164
183
|
'You are a technical expert explaining streaming APIs with practical examples.',
|
|
165
184
|
usageMetadata: {
|
|
185
|
+
// User identification
|
|
166
186
|
subscriber: {
|
|
167
187
|
id: 'advanced-streaming-user-789',
|
|
168
188
|
email: 'advanced@enterprise.com',
|
|
169
189
|
credential: {
|
|
170
|
-
name: '
|
|
171
|
-
value: '
|
|
190
|
+
name: 'api-key-prod',
|
|
191
|
+
value: 'key-nop-012',
|
|
172
192
|
},
|
|
173
193
|
},
|
|
194
|
+
|
|
195
|
+
// Organization & billing
|
|
174
196
|
organizationId: 'enterprise-streaming-org-012',
|
|
197
|
+
subscriptionId: 'plan-enterprise-stream-2024',
|
|
198
|
+
|
|
199
|
+
// Product & task tracking
|
|
175
200
|
productId: 'streaming-api-educator',
|
|
176
201
|
taskType: 'advanced-technical-streaming',
|
|
177
|
-
traceId: 'advanced-stream-trace-345',
|
|
178
202
|
agent: 'streaming-expert',
|
|
203
|
+
|
|
204
|
+
// Session tracking
|
|
205
|
+
traceId: 'advanced-stream-trace-345',
|
|
206
|
+
|
|
207
|
+
// Quality metrics
|
|
179
208
|
responseQualityScore: 0.97,
|
|
180
209
|
},
|
|
181
210
|
} as ResponsesCreateParams);
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* OpenAI Streaming Example
|
|
3
3
|
*
|
|
4
4
|
* Shows how to use Revenium middleware with streaming OpenAI responses and batch embeddings.
|
|
5
5
|
* Demonstrates seamless metadata integration with streaming - all metadata fields are optional!
|
|
6
|
+
*
|
|
7
|
+
* Metadata Options:
|
|
8
|
+
* - Start with basic usage (no metadata) - tracking works automatically
|
|
9
|
+
* - Add subscriber info for user tracking
|
|
10
|
+
* - Include organization/product IDs for business analytics
|
|
11
|
+
* - Use task type and trace ID for detailed analysis
|
|
12
|
+
*
|
|
13
|
+
* For complete metadata field reference, see:
|
|
14
|
+
* https://revenium.readme.io/reference/meter_ai_completion
|
|
6
15
|
*/
|
|
7
16
|
|
|
8
17
|
import 'dotenv/config';
|
|
@@ -52,30 +61,32 @@ async function openaiStreamingExample() {
|
|
|
52
61
|
messages: [{ role: 'user', content: 'Write a haiku about middleware' }],
|
|
53
62
|
stream: true,
|
|
54
63
|
|
|
55
|
-
//
|
|
56
|
-
// Note: Nested subscriber structure matches Python middleware implementation
|
|
64
|
+
// Optional metadata for advanced reporting, lineage tracking, and cost allocation
|
|
57
65
|
usageMetadata: {
|
|
58
|
-
// User
|
|
66
|
+
// User identification
|
|
59
67
|
subscriber: {
|
|
60
68
|
id: 'streaming-user-456',
|
|
61
69
|
email: 'poet@company.com',
|
|
62
70
|
credential: {
|
|
63
|
-
name: '
|
|
64
|
-
value: '
|
|
71
|
+
name: 'api-key-prod',
|
|
72
|
+
value: 'key-ghi-789',
|
|
65
73
|
},
|
|
66
74
|
},
|
|
67
75
|
|
|
68
|
-
//
|
|
76
|
+
// Organization & billing
|
|
69
77
|
organizationId: 'creative-company',
|
|
70
|
-
|
|
78
|
+
subscriptionId: 'plan-creative-2024',
|
|
71
79
|
|
|
72
|
-
//
|
|
80
|
+
// Product & task tracking
|
|
81
|
+
productId: 'ai-poet',
|
|
73
82
|
taskType: 'creative-writing',
|
|
74
|
-
|
|
83
|
+
agent: 'openai-streaming-chat-node',
|
|
75
84
|
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
// Session tracking
|
|
86
|
+
traceId: 'stream-' + Date.now(),
|
|
87
|
+
|
|
88
|
+
// Quality metrics
|
|
89
|
+
responseQualityScore: 0.92,
|
|
79
90
|
},
|
|
80
91
|
});
|
|
81
92
|
|