@revenium/perplexity 1.0.19 → 1.0.20
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/README.md +59 -1
- package/examples/metadata.ts +43 -0
- package/package.json +3 -2
- package/playground/metadata.js +43 -0
- package/src/interfaces/chatCompletionRequest.ts +2 -1
- package/src/interfaces/usageMetadata.ts +14 -0
- package/src/middleware.ts +24 -18
- package/src/models/Metering.ts +48 -20
package/README.md
CHANGED
|
@@ -187,6 +187,58 @@ const streamingExample = async () => {
|
|
|
187
187
|
streamingExample();
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
+
#### METADATA Example
|
|
191
|
+
|
|
192
|
+
Create `examples/metadata-perplexity.js`:
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
// examples/metadata-perplexity.js
|
|
196
|
+
import { PerplexityReveniumMiddleware } from "@revenium/perplexity";
|
|
197
|
+
|
|
198
|
+
const metadataExample = async () => {
|
|
199
|
+
try {
|
|
200
|
+
const middleware = new PerplexityReveniumMiddleware();
|
|
201
|
+
const model = middleware.getGenerativeModel("sonar-pro");
|
|
202
|
+
const result = await model.createChatCompletion({
|
|
203
|
+
model: "sonar-pro",
|
|
204
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
205
|
+
usageMetadata: {
|
|
206
|
+
taskType: "test",
|
|
207
|
+
subscriberEmail: "test@revenium.ai",
|
|
208
|
+
subscriberId: "123456",
|
|
209
|
+
subscriberCredentialName: "apiKey",
|
|
210
|
+
subscriberCredential: "keyValue",
|
|
211
|
+
organizationId: "123456",
|
|
212
|
+
subscriptionId: "123456",
|
|
213
|
+
productId: "free-trial",
|
|
214
|
+
agent: "perplexity",
|
|
215
|
+
responseQualityScore: 100,
|
|
216
|
+
transactionId: "123456",
|
|
217
|
+
timeToFirstToken: 1000,
|
|
218
|
+
requestTime: new Date(),
|
|
219
|
+
completionStartTime: new Date(),
|
|
220
|
+
operationType: "CHAT",
|
|
221
|
+
inputTokenCount: 10,
|
|
222
|
+
outputTokenCount: 10,
|
|
223
|
+
reasoningTokenCount: 20,
|
|
224
|
+
cacheCreationTokenCount: 0,
|
|
225
|
+
cacheReadTokenCount: 0,
|
|
226
|
+
totalTokenCount: 40,
|
|
227
|
+
responseTime: new Date(),
|
|
228
|
+
requestDuration: 1000,
|
|
229
|
+
stopReason: "END",
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
console.log("[BASIC REQUEST]", result.choices[0].message);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error("❌ Perplexity streaming example failed:", error);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
metadataExample();
|
|
240
|
+
```
|
|
241
|
+
|
|
190
242
|
### Step 8: Update package.json
|
|
191
243
|
|
|
192
244
|
```json
|
|
@@ -196,7 +248,8 @@ streamingExample();
|
|
|
196
248
|
"type": "module",
|
|
197
249
|
"scripts": {
|
|
198
250
|
"test-perplexity": "node test-perplexity.js",
|
|
199
|
-
"test-perplexity-stream": "node examples/streaming-perplexity.js"
|
|
251
|
+
"test-perplexity-stream": "node examples/streaming-perplexity.js",
|
|
252
|
+
"test-perplexity-metadata": "node examples/metadata-perplexity.js"
|
|
200
253
|
},
|
|
201
254
|
"dependencies": {
|
|
202
255
|
"@revenium/perplexity": "^1.0.0"
|
|
@@ -210,6 +263,9 @@ streamingExample();
|
|
|
210
263
|
# Test streaming
|
|
211
264
|
npm run test-perplexity-stream
|
|
212
265
|
|
|
266
|
+
# Test metadata
|
|
267
|
+
npm run test-perplexity-metadata
|
|
268
|
+
|
|
213
269
|
```
|
|
214
270
|
|
|
215
271
|
---
|
|
@@ -252,6 +308,7 @@ npm run e-basic # Basic chat completion
|
|
|
252
308
|
npm run e-streaming # Streaming response
|
|
253
309
|
npm run e-enhanced # Enhanced request
|
|
254
310
|
npm run e-chat-completions # Chat completions
|
|
311
|
+
npm run e-metadata # Metadata request
|
|
255
312
|
|
|
256
313
|
# Playground examples
|
|
257
314
|
# Required build first
|
|
@@ -260,6 +317,7 @@ npm run build
|
|
|
260
317
|
npm run p-basic
|
|
261
318
|
npm run p-streaming
|
|
262
319
|
npm run p-enhanced
|
|
320
|
+
npm run p-metadata
|
|
263
321
|
```
|
|
264
322
|
|
|
265
323
|
---
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PerplexityReveniumMiddleware } from "../src";
|
|
2
|
+
|
|
3
|
+
async function metadataRequest() {
|
|
4
|
+
console.log("=".repeat(50));
|
|
5
|
+
try {
|
|
6
|
+
const middleware = new PerplexityReveniumMiddleware();
|
|
7
|
+
const model = middleware.getGenerativeModel("sonar-pro");
|
|
8
|
+
const result = await model.createChatCompletion({
|
|
9
|
+
model: "sonar-pro",
|
|
10
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
11
|
+
usageMetadata: {
|
|
12
|
+
taskType: "test",
|
|
13
|
+
subscriberEmail: "test@revenium.ai",
|
|
14
|
+
subscriberId: "123456",
|
|
15
|
+
subscriberCredentialName: "apiKey",
|
|
16
|
+
subscriberCredential: "keyValue",
|
|
17
|
+
organizationId: "123456",
|
|
18
|
+
subscriptionId: "123456",
|
|
19
|
+
productId: "free-trial",
|
|
20
|
+
agent: "perplexity",
|
|
21
|
+
responseQualityScore: 100,
|
|
22
|
+
transactionId: "123456",
|
|
23
|
+
timeToFirstToken: 1000,
|
|
24
|
+
requestTime: new Date(),
|
|
25
|
+
completionStartTime: new Date(),
|
|
26
|
+
operationType: "CHAT",
|
|
27
|
+
inputTokenCount: 10,
|
|
28
|
+
outputTokenCount: 10,
|
|
29
|
+
reasoningTokenCount: 20,
|
|
30
|
+
cacheCreationTokenCount: 0,
|
|
31
|
+
cacheReadTokenCount: 0,
|
|
32
|
+
totalTokenCount: 40,
|
|
33
|
+
responseTime: new Date(),
|
|
34
|
+
requestDuration: 1000,
|
|
35
|
+
stopReason: "END",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
console.log("[METADATA REQUEST]", result.choices[0].message);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.log(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
metadataRequest();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revenium/perplexity",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "NodeJS middleware for perplexity's AI API",
|
|
5
5
|
"homepage": "https://github.com/revenium/revenium-middleware-perplexity-node#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"e-basic": "npx ts-node examples/basic.ts",
|
|
21
21
|
"e-streaming": "npx ts-node examples/streaming.ts",
|
|
22
22
|
"e-chat-completions": "npx ts-node examples/chat-completions.ts",
|
|
23
|
-
"e-enhanced": "npx ts-node examples/enhanced.ts"
|
|
23
|
+
"e-enhanced": "npx ts-node examples/enhanced.ts",
|
|
24
|
+
"e-metadata": "npx ts-node examples/metadata.ts"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"revenium",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PerplexityReveniumMiddleware } from "@revenium/perplexity";
|
|
2
|
+
|
|
3
|
+
async function metadataRequest() {
|
|
4
|
+
console.log("=".repeat(50));
|
|
5
|
+
try {
|
|
6
|
+
const middleware = new PerplexityReveniumMiddleware();
|
|
7
|
+
const model = middleware.getGenerativeModel("sonar-pro");
|
|
8
|
+
const result = await model.createChatCompletion({
|
|
9
|
+
model: "sonar-pro",
|
|
10
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
11
|
+
usageMetadata: {
|
|
12
|
+
taskType: "test",
|
|
13
|
+
subscriberEmail: "test@revenium.ai",
|
|
14
|
+
subscriberId: "123456",
|
|
15
|
+
subscriberCredentialName: "apiKey",
|
|
16
|
+
subscriberCredential: "keyValue",
|
|
17
|
+
organizationId: "123456",
|
|
18
|
+
subscriptionId: "123456",
|
|
19
|
+
productId: "free-trial",
|
|
20
|
+
agent: "perplexity",
|
|
21
|
+
responseQualityScore: 100,
|
|
22
|
+
transactionId: "123456",
|
|
23
|
+
timeToFirstToken: 1000,
|
|
24
|
+
requestTime: new Date(),
|
|
25
|
+
completionStartTime: new Date(),
|
|
26
|
+
operationType: "CHAT",
|
|
27
|
+
inputTokenCount: 10,
|
|
28
|
+
outputTokenCount: 10,
|
|
29
|
+
reasoningTokenCount: 20,
|
|
30
|
+
cacheCreationTokenCount: 0,
|
|
31
|
+
cacheReadTokenCount: 0,
|
|
32
|
+
totalTokenCount: 40,
|
|
33
|
+
responseTime: new Date(),
|
|
34
|
+
requestDuration: 1000,
|
|
35
|
+
stopReason: "END",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
console.log("[METADATA REQUEST]", result.choices[0].message);
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.log(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
metadataRequest();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ChatCompletionMessageParam } from "openai/resources/index";
|
|
2
|
+
import { IUsageMetadata } from "./usageMetadata";
|
|
2
3
|
|
|
3
4
|
export interface IChatCompletionRequest {
|
|
4
5
|
model?: string;
|
|
5
6
|
messages: ChatCompletionMessageParam[];
|
|
6
7
|
stream?: boolean;
|
|
7
|
-
usageMetadata?:
|
|
8
|
+
usageMetadata?: IUsageMetadata;
|
|
8
9
|
[key: string]: any;
|
|
9
10
|
}
|
|
@@ -10,4 +10,18 @@ export interface IUsageMetadata {
|
|
|
10
10
|
productId?: string;
|
|
11
11
|
agent?: string;
|
|
12
12
|
responseQualityScore?: number;
|
|
13
|
+
transactionId?: string;
|
|
14
|
+
timeToFirstToken?: number;
|
|
15
|
+
requestTime?: Date;
|
|
16
|
+
completionStartTime?: Date;
|
|
17
|
+
operationType?: string;
|
|
18
|
+
inputTokenCount?: number;
|
|
19
|
+
outputTokenCount?: number;
|
|
20
|
+
reasoningTokenCount?: number;
|
|
21
|
+
cacheCreationTokenCount?: number;
|
|
22
|
+
cacheReadTokenCount?: number;
|
|
23
|
+
totalTokenCount?: number;
|
|
24
|
+
responseTime?: Date;
|
|
25
|
+
requestDuration?: number;
|
|
26
|
+
stopReason?: string;
|
|
13
27
|
}
|
package/src/middleware.ts
CHANGED
|
@@ -70,15 +70,18 @@ export class PerplexityReveniumMiddleware {
|
|
|
70
70
|
REVENIUM_METERING_API_KEY ?? "",
|
|
71
71
|
REVENIUM_METERING_BASE_URL ?? ""
|
|
72
72
|
);
|
|
73
|
-
const getMetering = metering.createMetering(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
const getMetering = metering.createMetering(
|
|
74
|
+
{
|
|
75
|
+
modelName: this.modelName,
|
|
76
|
+
endTime,
|
|
77
|
+
startTime,
|
|
78
|
+
operationType: IOperationType.CHAT,
|
|
79
|
+
stopReason: "END",
|
|
80
|
+
tokenCounts,
|
|
81
|
+
usageMetadata,
|
|
82
|
+
},
|
|
83
|
+
true
|
|
84
|
+
);
|
|
82
85
|
await metering.sendMeteringData(getMetering);
|
|
83
86
|
return result;
|
|
84
87
|
} catch (error) {
|
|
@@ -111,15 +114,18 @@ export class PerplexityReveniumMiddleware {
|
|
|
111
114
|
REVENIUM_METERING_API_KEY ?? "",
|
|
112
115
|
REVENIUM_METERING_BASE_URL ?? ""
|
|
113
116
|
);
|
|
114
|
-
const getMetering = metering.createMetering(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
const getMetering = metering.createMetering(
|
|
118
|
+
{
|
|
119
|
+
modelName: this.modelName,
|
|
120
|
+
endTime,
|
|
121
|
+
startTime,
|
|
122
|
+
operationType: IOperationType.CHAT,
|
|
123
|
+
stopReason: "END",
|
|
124
|
+
tokenCounts,
|
|
125
|
+
usageMetadata,
|
|
126
|
+
},
|
|
127
|
+
false
|
|
128
|
+
);
|
|
123
129
|
await metering.sendMeteringData(getMetering);
|
|
124
130
|
return result;
|
|
125
131
|
} catch (error) {
|
package/src/models/Metering.ts
CHANGED
|
@@ -21,39 +21,67 @@ export class Metering {
|
|
|
21
21
|
this.endpoint = clientEndpoint;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public createMetering(
|
|
24
|
+
public createMetering(
|
|
25
|
+
metering: IMeteringRequest,
|
|
26
|
+
isStreamed: boolean
|
|
27
|
+
): IMeteringResponse {
|
|
28
|
+
const usageMetadata = metering.usageMetadata;
|
|
25
29
|
const agent: string = "perplexity";
|
|
26
30
|
return {
|
|
27
|
-
stopReason: metering.stopReason,
|
|
31
|
+
stopReason: usageMetadata?.stopReason ?? metering.stopReason,
|
|
28
32
|
costType: COST_TYPE,
|
|
29
|
-
isStreamed
|
|
33
|
+
isStreamed,
|
|
30
34
|
taskType: COST_TYPE,
|
|
31
|
-
agent,
|
|
32
|
-
operationType:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
agent: usageMetadata?.agent ?? agent,
|
|
36
|
+
operationType:
|
|
37
|
+
usageMetadata?.operationType ?? metering.operationType.toString(),
|
|
38
|
+
inputTokenCount:
|
|
39
|
+
usageMetadata?.inputTokenCount ?? metering.tokenCounts.inputTokens,
|
|
40
|
+
outputTokenCount:
|
|
41
|
+
usageMetadata?.outputTokenCount ?? metering.tokenCounts.outputTokens,
|
|
42
|
+
reasoningTokenCount:
|
|
43
|
+
usageMetadata?.reasoningTokenCount ??
|
|
44
|
+
metering.tokenCounts.reasoningTokens ??
|
|
45
|
+
0,
|
|
46
|
+
cacheCreationTokenCount:
|
|
47
|
+
usageMetadata?.cacheCreationTokenCount ??
|
|
48
|
+
metering.tokenCounts.cachedTokens ??
|
|
49
|
+
0,
|
|
50
|
+
cacheReadTokenCount: usageMetadata?.cacheReadTokenCount ?? 0,
|
|
51
|
+
totalTokenCount:
|
|
52
|
+
usageMetadata?.totalTokenCount ?? metering.tokenCounts.totalTokens,
|
|
53
|
+
organizationId:
|
|
54
|
+
usageMetadata?.organizationId ??
|
|
55
|
+
`my-customer-name-${generateTransactionId()}`,
|
|
56
|
+
productId: usageMetadata?.productId ?? PRODUCT_ID_FREE,
|
|
41
57
|
subscriber: {
|
|
42
|
-
id: `user-${generateTransactionId()}`,
|
|
43
|
-
email:
|
|
44
|
-
|
|
58
|
+
id: usageMetadata?.subscriberId ?? `user-${generateTransactionId()}`,
|
|
59
|
+
email:
|
|
60
|
+
usageMetadata?.subscriberEmail ?? `user-@${agent.toLowerCase()}.ai`,
|
|
61
|
+
credential:
|
|
62
|
+
usageMetadata?.subscriberCredentialName &&
|
|
63
|
+
usageMetadata?.subscriberCredential
|
|
64
|
+
? {
|
|
65
|
+
name: usageMetadata.subscriberCredentialName,
|
|
66
|
+
value: usageMetadata.subscriberCredential,
|
|
67
|
+
}
|
|
68
|
+
: CURRENT_CREDENTIAL,
|
|
45
69
|
},
|
|
46
70
|
model: metering.modelName,
|
|
47
|
-
transactionId: generateTransactionId(),
|
|
71
|
+
transactionId: usageMetadata?.transactionId ?? generateTransactionId(),
|
|
48
72
|
responseTime: formatTimestamp(metering.endTime),
|
|
49
73
|
requestDuration: calculateDurationMs(
|
|
50
74
|
metering.startTime,
|
|
51
75
|
metering.endTime
|
|
52
76
|
),
|
|
53
77
|
provider: agent,
|
|
54
|
-
requestTime:
|
|
55
|
-
|
|
56
|
-
|
|
78
|
+
requestTime:
|
|
79
|
+
usageMetadata?.requestTime?.toString() ??
|
|
80
|
+
formatTimestamp(metering.startTime),
|
|
81
|
+
completionStartTime:
|
|
82
|
+
usageMetadata?.completionStartTime?.toString() ??
|
|
83
|
+
formatTimestamp(metering.endTime),
|
|
84
|
+
timeToFirstToken: usageMetadata?.timeToFirstToken ?? 0,
|
|
57
85
|
middleware_source: MIDDLEWARE_SOURCE,
|
|
58
86
|
};
|
|
59
87
|
}
|