@revenium/perplexity 1.0.18 → 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 +32 -25
- 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,7 +187,7 @@ const streamingExample = async () => {
|
|
|
187
187
|
streamingExample();
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
####
|
|
190
|
+
#### METADATA Example
|
|
191
191
|
|
|
192
192
|
Create `examples/metadata-perplexity.js`:
|
|
193
193
|
|
|
@@ -200,34 +200,38 @@ const metadataExample = async () => {
|
|
|
200
200
|
const middleware = new PerplexityReveniumMiddleware();
|
|
201
201
|
const model = middleware.getGenerativeModel("sonar-pro");
|
|
202
202
|
const result = await model.createChatCompletion({
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
role: "user",
|
|
206
|
-
content: "Analyze this quarterly report",
|
|
207
|
-
},
|
|
208
|
-
],
|
|
203
|
+
model: "sonar-pro",
|
|
204
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
209
205
|
usageMetadata: {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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",
|
|
223
230
|
},
|
|
224
231
|
});
|
|
225
|
-
|
|
226
|
-
console.log("*** METADATA RESPONSE ***");
|
|
227
|
-
console.log("Response:", result.choices[0]?.message?.content);
|
|
228
|
-
console.log("✅ Metadata tracking with metering successful!");
|
|
232
|
+
console.log("[BASIC REQUEST]", result.choices[0].message);
|
|
229
233
|
} catch (error) {
|
|
230
|
-
console.error("❌ Perplexity
|
|
234
|
+
console.error("❌ Perplexity streaming example failed:", error);
|
|
231
235
|
process.exit(1);
|
|
232
236
|
}
|
|
233
237
|
};
|
|
@@ -261,6 +265,7 @@ npm run test-perplexity-stream
|
|
|
261
265
|
|
|
262
266
|
# Test metadata
|
|
263
267
|
npm run test-perplexity-metadata
|
|
268
|
+
|
|
264
269
|
```
|
|
265
270
|
|
|
266
271
|
---
|
|
@@ -303,6 +308,7 @@ npm run e-basic # Basic chat completion
|
|
|
303
308
|
npm run e-streaming # Streaming response
|
|
304
309
|
npm run e-enhanced # Enhanced request
|
|
305
310
|
npm run e-chat-completions # Chat completions
|
|
311
|
+
npm run e-metadata # Metadata request
|
|
306
312
|
|
|
307
313
|
# Playground examples
|
|
308
314
|
# Required build first
|
|
@@ -311,6 +317,7 @@ npm run build
|
|
|
311
317
|
npm run p-basic
|
|
312
318
|
npm run p-streaming
|
|
313
319
|
npm run p-enhanced
|
|
320
|
+
npm run p-metadata
|
|
314
321
|
```
|
|
315
322
|
|
|
316
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
|
}
|