@revenium/perplexity 1.0.22 ā 1.0.25
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 +391 -154
- package/dist/interfaces/meteringResponse.d.ts +28 -27
- package/dist/interfaces/meteringResponse.js +2 -2
- package/dist/models/Metering.js +23 -20
- package/dist/v1/perplexityV1.service.js +166 -0
- package/dist/v2/perplexityV2.service.js +178 -0
- package/examples/v1/basic.ts +50 -0
- package/examples/v1/chat.ts +40 -0
- package/examples/v1/metadata.ts +49 -0
- package/examples/v1/streaming.ts +44 -0
- package/examples/v2/basic.ts +49 -0
- package/examples/v2/chat.ts +60 -0
- package/examples/v2/metadata.ts +71 -0
- package/examples/v2/streaming.ts +61 -0
- package/package.json +26 -11
- package/playground/v1/basic.js +50 -0
- package/playground/v1/chat.js +46 -0
- package/playground/v1/metadata.js +50 -0
- package/playground/v1/streaming.js +44 -0
- package/playground/v2/basic.js +49 -0
- package/playground/v2/chat.js +72 -0
- package/playground/v2/metadata.js +76 -0
- package/playground/v2/streaming.js +67 -0
- package/src/index.ts +14 -1
- package/src/interfaces/chatCompletionRequest.ts +7 -2
- package/src/interfaces/meteringResponse.ts +1 -0
- package/src/interfaces/perplexityResponse.ts +63 -0
- package/src/interfaces/perplexityStreaming.ts +56 -0
- package/src/models/Metering.ts +9 -2
- package/src/utils/constants/perplexityModels.ts +71 -0
- package/src/v1/perplexityV1.controller.ts +164 -0
- package/src/v1/perplexityV1.service.ts +230 -0
- package/src/v2/perplexityV2.controller.ts +219 -0
- package/src/v2/perplexityV2.service.ts +260 -0
- package/dist/index.js +0 -19
- package/dist/interfaces/chatCompletionRequest.d.ts +0 -9
- package/dist/interfaces/chatCompletionRequest.js +0 -2
- package/dist/interfaces/credential.d.ts +0 -4
- package/dist/interfaces/credential.js +0 -2
- package/dist/interfaces/meteringRequest.d.ts +0 -13
- package/dist/interfaces/meteringRequest.js +0 -2
- package/dist/interfaces/operation.d.ts +0 -4
- package/dist/interfaces/operation.js +0 -8
- package/dist/interfaces/subscriber.d.ts +0 -8
- package/dist/interfaces/subscriber.js +0 -2
- package/dist/interfaces/tokenCounts.d.ts +0 -7
- package/dist/interfaces/tokenCounts.js +0 -2
- package/dist/interfaces/usageMetadata.d.ts +0 -27
- package/dist/interfaces/usageMetadata.js +0 -2
- package/dist/middleware.d.ts +0 -22
- package/dist/middleware.js +0 -129
- package/dist/models/Logger.js +0 -35
- package/dist/models/Metering.d.ts +0 -9
- package/dist/utils/calculateDurationMs.d.ts +0 -1
- package/dist/utils/calculateDurationMs.js +0 -6
- package/dist/utils/constants/constants.d.ts +0 -6
- package/dist/utils/constants/constants.js +0 -11
- package/dist/utils/constants/logLevels.d.ts +0 -1
- package/dist/utils/constants/logLevels.js +0 -4
- package/dist/utils/constants/messages.d.ts +0 -5
- package/dist/utils/constants/messages.js +0 -8
- package/dist/utils/constants/models.d.ts +0 -1
- package/dist/utils/constants/models.js +0 -21
- package/dist/utils/extractTokenCount.d.ts +0 -2
- package/dist/utils/extractTokenCount.js +0 -28
- package/dist/utils/formatTimeStamp.d.ts +0 -1
- package/dist/utils/formatTimeStamp.js +0 -6
- package/dist/utils/generateTransactionId.d.ts +0 -1
- package/dist/utils/generateTransactionId.js +0 -7
- package/dist/utils/index.d.ts +0 -6
- package/dist/utils/index.js +0 -23
- package/dist/utils/loadEnv.d.ts +0 -1
- package/dist/utils/loadEnv.js +0 -7
- package/dist/utils/safeExtract.d.ts +0 -29
- package/dist/utils/safeExtract.js +0 -67
- package/examples/basic.ts +0 -17
- package/examples/chat-completions.ts +0 -22
- package/examples/enhanced.ts +0 -20
- package/examples/metadata.ts +0 -43
- package/examples/streaming.ts +0 -24
- package/playground/basic.js +0 -17
- package/playground/chat-completions.js +0 -22
- package/playground/enhanced.js +0 -20
- package/playground/metadata.js +0 -43
- package/playground/streaming.js +0 -24
- package/src/middleware.ts +0 -157
- /package/src/utils/{formatTimeStamp.ts ā formatTimestamp.ts} +0 -0
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
import { ISubscriber } from "./subscriber";
|
|
2
|
-
export interface IMeteringResponse {
|
|
3
|
-
stopReason: string;
|
|
4
|
-
costType: string;
|
|
5
|
-
isStreamed: boolean;
|
|
6
|
-
taskType: string;
|
|
7
|
-
agent: string;
|
|
8
|
-
operationType: string;
|
|
9
|
-
inputTokenCount: number;
|
|
10
|
-
outputTokenCount: number;
|
|
11
|
-
reasoningTokenCount: number;
|
|
12
|
-
cacheCreationTokenCount: number;
|
|
13
|
-
cacheReadTokenCount: number;
|
|
14
|
-
totalTokenCount: number;
|
|
15
|
-
organizationId: string;
|
|
16
|
-
productId: string;
|
|
17
|
-
subscriber: ISubscriber;
|
|
18
|
-
model: string;
|
|
19
|
-
transactionId: string;
|
|
20
|
-
responseTime: string;
|
|
21
|
-
requestDuration: number;
|
|
22
|
-
provider: string;
|
|
23
|
-
requestTime: string;
|
|
24
|
-
completionStartTime: string;
|
|
25
|
-
timeToFirstToken: number;
|
|
26
|
-
middleware_source: string;
|
|
27
|
-
|
|
1
|
+
import { ISubscriber } from "./subscriber";
|
|
2
|
+
export interface IMeteringResponse {
|
|
3
|
+
stopReason: string;
|
|
4
|
+
costType: string;
|
|
5
|
+
isStreamed: boolean;
|
|
6
|
+
taskType: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
operationType: string;
|
|
9
|
+
inputTokenCount: number;
|
|
10
|
+
outputTokenCount: number;
|
|
11
|
+
reasoningTokenCount: number;
|
|
12
|
+
cacheCreationTokenCount: number;
|
|
13
|
+
cacheReadTokenCount: number;
|
|
14
|
+
totalTokenCount: number;
|
|
15
|
+
organizationId: string;
|
|
16
|
+
productId: string;
|
|
17
|
+
subscriber: ISubscriber;
|
|
18
|
+
model: string;
|
|
19
|
+
transactionId: string;
|
|
20
|
+
responseTime: string;
|
|
21
|
+
requestDuration: number;
|
|
22
|
+
provider: string;
|
|
23
|
+
requestTime: string;
|
|
24
|
+
completionStartTime: string;
|
|
25
|
+
timeToFirstToken: number;
|
|
26
|
+
middleware_source: string;
|
|
27
|
+
traceId?: string;
|
|
28
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/models/Metering.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Metering = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const calculateDurationMs_1 = require("../utils/calculateDurationMs");
|
|
6
|
-
const
|
|
6
|
+
const formatTimestamp_1 = require("../utils/formatTimestamp");
|
|
7
7
|
const generateTransactionId_1 = require("../utils/generateTransactionId");
|
|
8
8
|
const Logger_1 = require("./Logger");
|
|
9
9
|
class Metering {
|
|
@@ -12,6 +12,8 @@ class Metering {
|
|
|
12
12
|
this.apiKey = "";
|
|
13
13
|
this.sendMeteringData = async (metering) => {
|
|
14
14
|
try {
|
|
15
|
+
// Log the metering data being sent for debugging
|
|
16
|
+
Logger_1.logger.info("Sending metering data to Revenium:", JSON.stringify(metering, null, 2));
|
|
15
17
|
const response = await fetch(`${this.endpoint}/v2/ai/completions`, {
|
|
16
18
|
method: "POST",
|
|
17
19
|
headers: {
|
|
@@ -36,27 +38,27 @@ class Metering {
|
|
|
36
38
|
this.endpoint = clientEndpoint;
|
|
37
39
|
}
|
|
38
40
|
createMetering(metering, isStreamed) {
|
|
39
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
41
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
40
42
|
const usageMetadata = metering.usageMetadata;
|
|
41
43
|
const agent = "perplexity";
|
|
42
44
|
return {
|
|
43
45
|
stopReason: (_a = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.stopReason) !== null && _a !== void 0 ? _a : metering.stopReason,
|
|
44
46
|
costType: utils_1.COST_TYPE,
|
|
45
47
|
isStreamed,
|
|
46
|
-
taskType: utils_1.COST_TYPE,
|
|
47
|
-
agent: (
|
|
48
|
-
operationType: (
|
|
49
|
-
inputTokenCount: (
|
|
50
|
-
outputTokenCount: (
|
|
51
|
-
reasoningTokenCount: (
|
|
52
|
-
cacheCreationTokenCount: (
|
|
53
|
-
cacheReadTokenCount: (
|
|
54
|
-
totalTokenCount: (
|
|
55
|
-
organizationId: (
|
|
56
|
-
productId: (
|
|
48
|
+
taskType: (_b = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.taskType) !== null && _b !== void 0 ? _b : utils_1.COST_TYPE,
|
|
49
|
+
agent: (_c = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.agent) !== null && _c !== void 0 ? _c : agent,
|
|
50
|
+
operationType: (_d = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.operationType) !== null && _d !== void 0 ? _d : metering.operationType.toString(),
|
|
51
|
+
inputTokenCount: (_e = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.inputTokenCount) !== null && _e !== void 0 ? _e : metering.tokenCounts.inputTokens,
|
|
52
|
+
outputTokenCount: (_f = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.outputTokenCount) !== null && _f !== void 0 ? _f : metering.tokenCounts.outputTokens,
|
|
53
|
+
reasoningTokenCount: (_h = (_g = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.reasoningTokenCount) !== null && _g !== void 0 ? _g : metering.tokenCounts.reasoningTokens) !== null && _h !== void 0 ? _h : 0,
|
|
54
|
+
cacheCreationTokenCount: (_k = (_j = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheCreationTokenCount) !== null && _j !== void 0 ? _j : metering.tokenCounts.cachedTokens) !== null && _k !== void 0 ? _k : 0,
|
|
55
|
+
cacheReadTokenCount: (_l = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cacheReadTokenCount) !== null && _l !== void 0 ? _l : 0,
|
|
56
|
+
totalTokenCount: (_m = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.totalTokenCount) !== null && _m !== void 0 ? _m : metering.tokenCounts.totalTokens,
|
|
57
|
+
organizationId: (_o = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.organizationId) !== null && _o !== void 0 ? _o : `my-customer-name-${(0, generateTransactionId_1.generateTransactionId)()}`,
|
|
58
|
+
productId: (_p = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.productId) !== null && _p !== void 0 ? _p : utils_1.PRODUCT_ID_FREE,
|
|
57
59
|
subscriber: {
|
|
58
|
-
id: (
|
|
59
|
-
email: (
|
|
60
|
+
id: (_q = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberId) !== null && _q !== void 0 ? _q : `user-${(0, generateTransactionId_1.generateTransactionId)()}`,
|
|
61
|
+
email: (_r = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberEmail) !== null && _r !== void 0 ? _r : `user-@${agent.toLowerCase()}.ai`,
|
|
60
62
|
credential: (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberCredentialName) &&
|
|
61
63
|
(usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.subscriberCredential)
|
|
62
64
|
? {
|
|
@@ -66,14 +68,15 @@ class Metering {
|
|
|
66
68
|
: utils_1.CURRENT_CREDENTIAL,
|
|
67
69
|
},
|
|
68
70
|
model: metering.modelName,
|
|
69
|
-
transactionId: (
|
|
70
|
-
responseTime: (0,
|
|
71
|
+
transactionId: (_s = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.transactionId) !== null && _s !== void 0 ? _s : (0, generateTransactionId_1.generateTransactionId)(),
|
|
72
|
+
responseTime: (0, formatTimestamp_1.formatTimestamp)(metering.endTime),
|
|
71
73
|
requestDuration: (0, calculateDurationMs_1.calculateDurationMs)(metering.startTime, metering.endTime),
|
|
72
74
|
provider: agent,
|
|
73
|
-
requestTime: (
|
|
74
|
-
completionStartTime: (
|
|
75
|
-
timeToFirstToken: (
|
|
75
|
+
requestTime: (_u = (_t = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.requestTime) === null || _t === void 0 ? void 0 : _t.toString()) !== null && _u !== void 0 ? _u : (0, formatTimestamp_1.formatTimestamp)(metering.startTime),
|
|
76
|
+
completionStartTime: (_w = (_v = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.completionStartTime) === null || _v === void 0 ? void 0 : _v.toString()) !== null && _w !== void 0 ? _w : (0, formatTimestamp_1.formatTimestamp)(metering.endTime),
|
|
77
|
+
timeToFirstToken: (_x = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.timeToFirstToken) !== null && _x !== void 0 ? _x : 0,
|
|
76
78
|
middleware_source: utils_1.MIDDLEWARE_SOURCE,
|
|
79
|
+
traceId: usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.traceId,
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
82
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PerplexityV1Service = void 0;
|
|
7
|
+
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const Logger_1 = require("../models/Logger");
|
|
9
|
+
const Metering_1 = require("../models/Metering");
|
|
10
|
+
const generateTransactionId_1 = require("../utils/generateTransactionId");
|
|
11
|
+
const operation_1 = require("../interfaces/operation");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
class PerplexityV1Service {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.working = true;
|
|
16
|
+
this.client = new openai_1.default({
|
|
17
|
+
apiKey: utils_1.PERPLEXITY_API_KEY,
|
|
18
|
+
baseURL: utils_1.PERPLEXITY_API_BASE_URL,
|
|
19
|
+
});
|
|
20
|
+
Logger_1.logger.info(utils_1.PERPLEXITY_CLIENT_INITIALIZED_MESSAGE);
|
|
21
|
+
}
|
|
22
|
+
async createChatCompletion(params, model) {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
24
|
+
const transactionId = (0, generateTransactionId_1.generateTransactionId)();
|
|
25
|
+
const startTime = new Date();
|
|
26
|
+
try {
|
|
27
|
+
const { usageMetadata, ...openaiParams } = params;
|
|
28
|
+
const requestParams = {
|
|
29
|
+
...openaiParams,
|
|
30
|
+
model,
|
|
31
|
+
};
|
|
32
|
+
const result = (await this.client.chat.completions.create({
|
|
33
|
+
...requestParams,
|
|
34
|
+
stream: false,
|
|
35
|
+
}));
|
|
36
|
+
// Build V1 response format
|
|
37
|
+
const perplexityResponse = {
|
|
38
|
+
responses: [
|
|
39
|
+
{
|
|
40
|
+
text: ((_b = (_a = result.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) || "",
|
|
41
|
+
role: "assistant",
|
|
42
|
+
finishReason: (_c = result.choices[0]) === null || _c === void 0 ? void 0 : _c.finish_reason,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
usageMetadata: {
|
|
46
|
+
inputTokenCount: ((_d = result.usage) === null || _d === void 0 ? void 0 : _d.prompt_tokens) || 0,
|
|
47
|
+
outputTokenCount: ((_e = result.usage) === null || _e === void 0 ? void 0 : _e.completion_tokens) || 0,
|
|
48
|
+
totalTokenCount: ((_f = result.usage) === null || _f === void 0 ? void 0 : _f.total_tokens) || 0,
|
|
49
|
+
},
|
|
50
|
+
modelVersion: result.model,
|
|
51
|
+
transactionId,
|
|
52
|
+
};
|
|
53
|
+
// Send metering data (using current middleware logic)
|
|
54
|
+
if (this.working) {
|
|
55
|
+
const tokenCounts = {
|
|
56
|
+
inputTokens: ((_g = result.usage) === null || _g === void 0 ? void 0 : _g.prompt_tokens) || 0,
|
|
57
|
+
outputTokens: ((_h = result.usage) === null || _h === void 0 ? void 0 : _h.completion_tokens) || 0,
|
|
58
|
+
totalTokens: ((_j = result.usage) === null || _j === void 0 ? void 0 : _j.total_tokens) || 0,
|
|
59
|
+
};
|
|
60
|
+
const endTime = new Date();
|
|
61
|
+
Logger_1.logger.info("Metering is working.");
|
|
62
|
+
const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
|
|
63
|
+
// Combine user metadata with transaction ID
|
|
64
|
+
const combinedMetadata = {
|
|
65
|
+
...usageMetadata,
|
|
66
|
+
transactionId,
|
|
67
|
+
};
|
|
68
|
+
const getMetering = metering.createMetering({
|
|
69
|
+
modelName: model,
|
|
70
|
+
endTime,
|
|
71
|
+
startTime,
|
|
72
|
+
operationType: operation_1.IOperationType.CHAT,
|
|
73
|
+
stopReason: "END",
|
|
74
|
+
tokenCounts,
|
|
75
|
+
usageMetadata: combinedMetadata,
|
|
76
|
+
}, false);
|
|
77
|
+
await metering.sendMeteringData(getMetering);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
Logger_1.logger.warning("Metering is not working. Check your configuration.");
|
|
81
|
+
}
|
|
82
|
+
return perplexityResponse;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
Logger_1.logger.error("Error in Perplexity V1 chat completion:", error);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async createStreamingCompletion(params, model) {
|
|
90
|
+
const transactionId = (0, generateTransactionId_1.generateTransactionId)();
|
|
91
|
+
const startTime = new Date();
|
|
92
|
+
try {
|
|
93
|
+
const { usageMetadata, ...openaiParams } = params;
|
|
94
|
+
const requestParams = {
|
|
95
|
+
...openaiParams,
|
|
96
|
+
model,
|
|
97
|
+
};
|
|
98
|
+
const stream = await this.client.chat.completions.create({
|
|
99
|
+
...requestParams,
|
|
100
|
+
stream: true,
|
|
101
|
+
});
|
|
102
|
+
const wrappedStream = this.wrapStream(stream, transactionId, model, startTime, usageMetadata);
|
|
103
|
+
return {
|
|
104
|
+
stream: wrappedStream,
|
|
105
|
+
usageMetadata: {
|
|
106
|
+
inputTokenCount: 0, // Will be updated when stream completes
|
|
107
|
+
outputTokenCount: 0,
|
|
108
|
+
totalTokenCount: 0,
|
|
109
|
+
},
|
|
110
|
+
modelVersion: model,
|
|
111
|
+
transactionId,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
Logger_1.logger.error("Error in Perplexity V1 streaming:", error);
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async *wrapStream(stream, transactionId, model, startTime, usageMetadata) {
|
|
120
|
+
let lastChunk = null;
|
|
121
|
+
try {
|
|
122
|
+
for await (const chunk of stream) {
|
|
123
|
+
lastChunk = chunk;
|
|
124
|
+
yield chunk;
|
|
125
|
+
}
|
|
126
|
+
// Send metering data when stream completes (using current middleware logic)
|
|
127
|
+
if (this.working) {
|
|
128
|
+
// For streaming, we'll use the last chunk's usage data if available
|
|
129
|
+
const tokenCounts = {
|
|
130
|
+
inputTokens: 0, // Will be updated if lastChunk has usage data
|
|
131
|
+
outputTokens: 0,
|
|
132
|
+
totalTokens: 0,
|
|
133
|
+
};
|
|
134
|
+
const endTime = new Date();
|
|
135
|
+
Logger_1.logger.info("Metering is working.");
|
|
136
|
+
const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
|
|
137
|
+
// Combine user metadata with transaction ID
|
|
138
|
+
const combinedMetadata = {
|
|
139
|
+
...usageMetadata,
|
|
140
|
+
transactionId,
|
|
141
|
+
};
|
|
142
|
+
const getMetering = metering.createMetering({
|
|
143
|
+
modelName: model,
|
|
144
|
+
endTime,
|
|
145
|
+
startTime,
|
|
146
|
+
operationType: operation_1.IOperationType.CHAT,
|
|
147
|
+
stopReason: "END",
|
|
148
|
+
tokenCounts,
|
|
149
|
+
usageMetadata: combinedMetadata,
|
|
150
|
+
}, true);
|
|
151
|
+
await metering.sendMeteringData(getMetering);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
Logger_1.logger.warning("Metering is not working. Check your configuration.");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
Logger_1.logger.error("Error in Perplexity V1 stream processing:", error);
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
setWorking(working) {
|
|
163
|
+
this.working = working;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.PerplexityV1Service = PerplexityV1Service;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PerplexityV2Service = void 0;
|
|
7
|
+
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const Logger_1 = require("../models/Logger");
|
|
9
|
+
const Metering_1 = require("../models/Metering");
|
|
10
|
+
const generateTransactionId_1 = require("../utils/generateTransactionId");
|
|
11
|
+
const operation_1 = require("../interfaces/operation");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
class PerplexityV2Service {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.working = true;
|
|
16
|
+
this.client = new openai_1.default({
|
|
17
|
+
apiKey: utils_1.PERPLEXITY_API_KEY,
|
|
18
|
+
baseURL: utils_1.PERPLEXITY_API_BASE_URL,
|
|
19
|
+
});
|
|
20
|
+
Logger_1.logger.info(`${utils_1.PERPLEXITY_CLIENT_INITIALIZED_MESSAGE} (V2)`);
|
|
21
|
+
}
|
|
22
|
+
async createChatCompletion(params, model) {
|
|
23
|
+
var _a, _b, _c;
|
|
24
|
+
const transactionId = (0, generateTransactionId_1.generateTransactionId)();
|
|
25
|
+
const startTime = Date.now();
|
|
26
|
+
try {
|
|
27
|
+
const { usageMetadata, ...openaiParams } = params;
|
|
28
|
+
const requestParams = {
|
|
29
|
+
...openaiParams,
|
|
30
|
+
model,
|
|
31
|
+
};
|
|
32
|
+
const result = (await this.client.chat.completions.create({
|
|
33
|
+
...requestParams,
|
|
34
|
+
stream: false,
|
|
35
|
+
}));
|
|
36
|
+
const endTime = Date.now();
|
|
37
|
+
const processingTime = endTime - startTime;
|
|
38
|
+
// Build V2 enhanced response format (following OpenAI Responses API)
|
|
39
|
+
const perplexityV2Response = {
|
|
40
|
+
id: result.id,
|
|
41
|
+
object: "chat.completion",
|
|
42
|
+
created: result.created,
|
|
43
|
+
model: result.model,
|
|
44
|
+
choices: result.choices,
|
|
45
|
+
usage: {
|
|
46
|
+
prompt_tokens: ((_a = result.usage) === null || _a === void 0 ? void 0 : _a.prompt_tokens) || 0,
|
|
47
|
+
completion_tokens: ((_b = result.usage) === null || _b === void 0 ? void 0 : _b.completion_tokens) || 0,
|
|
48
|
+
total_tokens: ((_c = result.usage) === null || _c === void 0 ? void 0 : _c.total_tokens) || 0,
|
|
49
|
+
},
|
|
50
|
+
metadata: {
|
|
51
|
+
transactionId,
|
|
52
|
+
processingTime,
|
|
53
|
+
version: "v2",
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
// Send metering data (modernized approach)
|
|
57
|
+
await this.sendMeteringData(transactionId, model, operation_1.IOperationType.CHAT, {
|
|
58
|
+
inputTokenCount: perplexityV2Response.usage.prompt_tokens,
|
|
59
|
+
outputTokenCount: perplexityV2Response.usage.completion_tokens,
|
|
60
|
+
totalTokenCount: perplexityV2Response.usage.total_tokens,
|
|
61
|
+
}, processingTime, usageMetadata);
|
|
62
|
+
return perplexityV2Response;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
Logger_1.logger.error("Error in Perplexity V2 chat completion:", error);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async createStreamingCompletion(params, model) {
|
|
70
|
+
const transactionId = (0, generateTransactionId_1.generateTransactionId)();
|
|
71
|
+
const startTime = Date.now();
|
|
72
|
+
try {
|
|
73
|
+
const { usageMetadata, ...openaiParams } = params;
|
|
74
|
+
const requestParams = {
|
|
75
|
+
...openaiParams,
|
|
76
|
+
model,
|
|
77
|
+
};
|
|
78
|
+
const stream = await this.client.chat.completions.create({
|
|
79
|
+
...requestParams,
|
|
80
|
+
stream: true,
|
|
81
|
+
});
|
|
82
|
+
const wrappedStream = this.wrapStreamV2(stream, transactionId, model, startTime, usageMetadata);
|
|
83
|
+
return {
|
|
84
|
+
id: transactionId,
|
|
85
|
+
object: "chat.completion.chunk",
|
|
86
|
+
stream: wrappedStream,
|
|
87
|
+
metadata: {
|
|
88
|
+
transactionId,
|
|
89
|
+
startTime,
|
|
90
|
+
version: "v2",
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
Logger_1.logger.error("Error in Perplexity V2 streaming:", error);
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async *wrapStreamV2(stream, transactionId, model, startTime, usageMetadata) {
|
|
100
|
+
let lastChunk = null;
|
|
101
|
+
try {
|
|
102
|
+
for await (const chunk of stream) {
|
|
103
|
+
lastChunk = chunk;
|
|
104
|
+
// Transform to V2 format (following OpenAI Responses API)
|
|
105
|
+
const v2Chunk = {
|
|
106
|
+
id: chunk.id,
|
|
107
|
+
object: "chat.completion.chunk",
|
|
108
|
+
created: chunk.created,
|
|
109
|
+
model: chunk.model,
|
|
110
|
+
choices: chunk.choices,
|
|
111
|
+
usage: chunk.usage
|
|
112
|
+
? {
|
|
113
|
+
prompt_tokens: chunk.usage.prompt_tokens || 0,
|
|
114
|
+
completion_tokens: chunk.usage.completion_tokens || 0,
|
|
115
|
+
total_tokens: chunk.usage.total_tokens || 0,
|
|
116
|
+
}
|
|
117
|
+
: undefined,
|
|
118
|
+
};
|
|
119
|
+
yield v2Chunk;
|
|
120
|
+
}
|
|
121
|
+
// Send metering data when stream completes
|
|
122
|
+
const endTime = Date.now();
|
|
123
|
+
const processingTime = endTime - startTime;
|
|
124
|
+
if (lastChunk === null || lastChunk === void 0 ? void 0 : lastChunk.usage) {
|
|
125
|
+
await this.sendMeteringData(transactionId, model, operation_1.IOperationType.CHAT, {
|
|
126
|
+
inputTokenCount: lastChunk.usage.prompt_tokens || 0,
|
|
127
|
+
outputTokenCount: lastChunk.usage.completion_tokens || 0,
|
|
128
|
+
totalTokenCount: lastChunk.usage.total_tokens || 0,
|
|
129
|
+
}, processingTime, usageMetadata);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
Logger_1.logger.error("Error in Perplexity V2 stream processing:", error);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async sendMeteringData(transactionId, model, operationType, usageData, processingTime, customMetadata) {
|
|
138
|
+
if (!this.working) {
|
|
139
|
+
Logger_1.logger.warning("Metering is not working. Check your configuration.");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const startTime = new Date(Date.now() - processingTime);
|
|
144
|
+
const endTime = new Date();
|
|
145
|
+
const metering = new Metering_1.Metering(utils_1.REVENIUM_METERING_API_KEY !== null && utils_1.REVENIUM_METERING_API_KEY !== void 0 ? utils_1.REVENIUM_METERING_API_KEY : "", utils_1.REVENIUM_METERING_BASE_URL !== null && utils_1.REVENIUM_METERING_BASE_URL !== void 0 ? utils_1.REVENIUM_METERING_BASE_URL : "");
|
|
146
|
+
// Convert IUsageMetadata to ITokenCounts for metering
|
|
147
|
+
const tokenCounts = {
|
|
148
|
+
inputTokens: usageData.inputTokenCount || 0,
|
|
149
|
+
outputTokens: usageData.outputTokenCount || 0,
|
|
150
|
+
totalTokens: usageData.totalTokenCount || 0,
|
|
151
|
+
};
|
|
152
|
+
// Combine custom metadata with transaction ID (token counts are handled separately)
|
|
153
|
+
const combinedMetadata = {
|
|
154
|
+
...customMetadata,
|
|
155
|
+
transactionId,
|
|
156
|
+
};
|
|
157
|
+
// Use the same approach as V1 but with V2 enhancements
|
|
158
|
+
const meteringData = metering.createMetering({
|
|
159
|
+
modelName: model,
|
|
160
|
+
endTime,
|
|
161
|
+
startTime,
|
|
162
|
+
operationType,
|
|
163
|
+
stopReason: "END",
|
|
164
|
+
tokenCounts,
|
|
165
|
+
usageMetadata: combinedMetadata,
|
|
166
|
+
}, false);
|
|
167
|
+
await metering.sendMeteringData(meteringData);
|
|
168
|
+
Logger_1.logger.info("V2 Metering data sent successfully.");
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
Logger_1.logger.error("Error sending V2 metering data:", error);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
setWorking(working) {
|
|
175
|
+
this.working = working;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.PerplexityV2Service = PerplexityV2Service;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { PerplexityV1Controller } from "../../src/index";
|
|
2
|
+
|
|
3
|
+
const basicV1Example = async () => {
|
|
4
|
+
console.log("=".repeat(50));
|
|
5
|
+
console.log(
|
|
6
|
+
"š„ Perplexity V1 Basic Example (Compatible with current middleware)"
|
|
7
|
+
);
|
|
8
|
+
console.log("=".repeat(50));
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const controller = new PerplexityV1Controller();
|
|
12
|
+
|
|
13
|
+
// Basic chat completion
|
|
14
|
+
const result = await controller.createChat([
|
|
15
|
+
"What is artificial intelligence and how does it work?",
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
console.log("š Response:");
|
|
19
|
+
console.log(result.responses[0].text);
|
|
20
|
+
|
|
21
|
+
console.log("\nš Usage Metadata:");
|
|
22
|
+
console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
|
|
23
|
+
console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
|
|
24
|
+
console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
|
|
25
|
+
|
|
26
|
+
console.log("\nš§ Model Info:");
|
|
27
|
+
console.log(`Model: ${result.modelVersion}`);
|
|
28
|
+
console.log(`Transaction ID: ${result.transactionId}`);
|
|
29
|
+
|
|
30
|
+
// Test model capabilities
|
|
31
|
+
console.log("\nšÆ Model Capabilities:");
|
|
32
|
+
const models = controller.getAvailableModels();
|
|
33
|
+
console.log(`Available models: ${models.slice(0, 3).join(", ")}...`);
|
|
34
|
+
|
|
35
|
+
const supportsChat = controller.supportsCapability("sonar-pro", "chat");
|
|
36
|
+
const supportsStreaming = controller.supportsCapability(
|
|
37
|
+
"sonar-pro",
|
|
38
|
+
"streaming"
|
|
39
|
+
);
|
|
40
|
+
const supportsOnline = controller.supportsCapability("sonar-pro", "online");
|
|
41
|
+
|
|
42
|
+
console.log(
|
|
43
|
+
`Sonar-pro capabilities: chat=${supportsChat}, streaming=${supportsStreaming}, online=${supportsOnline}`
|
|
44
|
+
);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("ā Error:", error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
basicV1Example();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PerplexityV1Controller } from "../../src/index";
|
|
2
|
+
|
|
3
|
+
const chatV1Example = async () => {
|
|
4
|
+
console.log("=".repeat(50));
|
|
5
|
+
console.log("š¬ Perplexity V1 Multi-turn Chat Example");
|
|
6
|
+
console.log("=".repeat(50));
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const controller = new PerplexityV1Controller();
|
|
10
|
+
|
|
11
|
+
// Multi-turn conversation using message objects
|
|
12
|
+
const messages = [
|
|
13
|
+
{ role: "user", content: "What are the benefits of renewable energy?" },
|
|
14
|
+
{ role: "assistant", content: "Renewable energy offers several key benefits including environmental sustainability, reduced greenhouse gas emissions, and long-term cost savings." },
|
|
15
|
+
{ role: "user", content: "Can you elaborate on the cost savings aspect?" }
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const result = await controller.createChat(messages, "sonar-pro");
|
|
19
|
+
|
|
20
|
+
console.log("š Multi-turn Chat Response:");
|
|
21
|
+
console.log(result.responses[0].text);
|
|
22
|
+
|
|
23
|
+
console.log("\nš Usage Statistics:");
|
|
24
|
+
console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
|
|
25
|
+
console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
|
|
26
|
+
console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
|
|
27
|
+
|
|
28
|
+
console.log("\nš§ Model Information:");
|
|
29
|
+
const modelInfo = controller.getModelInfo("sonar-pro");
|
|
30
|
+
console.log(`Model: ${modelInfo.model}`);
|
|
31
|
+
console.log(`Version: ${modelInfo.version}`);
|
|
32
|
+
console.log(`Context Window: ${modelInfo.contextWindow} tokens`);
|
|
33
|
+
console.log(`Capabilities:`, modelInfo.capabilities);
|
|
34
|
+
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error("ā Error:", error);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
chatV1Example();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PerplexityV1Controller, IUsageMetadata } from "../../src/index";
|
|
2
|
+
|
|
3
|
+
const metadataV1Example = async () => {
|
|
4
|
+
console.log("=".repeat(50));
|
|
5
|
+
console.log("š Perplexity V1 Custom Metadata Example");
|
|
6
|
+
console.log("=".repeat(50));
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const controller = new PerplexityV1Controller();
|
|
10
|
+
|
|
11
|
+
// Custom metadata for tracking
|
|
12
|
+
const customMetadata: IUsageMetadata = {
|
|
13
|
+
traceId: "trace-12345",
|
|
14
|
+
taskType: "research-query",
|
|
15
|
+
subscriberEmail: "user@example.com",
|
|
16
|
+
subscriberId: "user-456",
|
|
17
|
+
organizationId: "org-789",
|
|
18
|
+
agent: "perplexity-v1-demo",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const result = await controller.createChat([
|
|
22
|
+
"Explain quantum computing in simple terms"
|
|
23
|
+
], "sonar-pro", customMetadata);
|
|
24
|
+
|
|
25
|
+
console.log("š Response:");
|
|
26
|
+
console.log(result.responses[0].text);
|
|
27
|
+
|
|
28
|
+
console.log("\nš Usage Metadata:");
|
|
29
|
+
console.log(`Input tokens: ${result.usageMetadata.inputTokenCount}`);
|
|
30
|
+
console.log(`Output tokens: ${result.usageMetadata.outputTokenCount}`);
|
|
31
|
+
console.log(`Total tokens: ${result.usageMetadata.totalTokenCount}`);
|
|
32
|
+
|
|
33
|
+
console.log("\nš·ļø Custom Metadata Sent:");
|
|
34
|
+
console.log(`Trace ID: ${customMetadata.traceId}`);
|
|
35
|
+
console.log(`Task Type: ${customMetadata.taskType}`);
|
|
36
|
+
console.log(`Subscriber: ${customMetadata.subscriberEmail}`);
|
|
37
|
+
console.log(`Organization: ${customMetadata.organizationId}`);
|
|
38
|
+
console.log(`Agent: ${customMetadata.agent}`);
|
|
39
|
+
|
|
40
|
+
console.log("\nš§ Transaction Info:");
|
|
41
|
+
console.log(`Model: ${result.modelVersion}`);
|
|
42
|
+
console.log(`Transaction ID: ${result.transactionId}`);
|
|
43
|
+
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error("ā Error:", error);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
metadataV1Example();
|