@revenium/perplexity 2.0.1 → 2.0.3
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/CHANGELOG.md +60 -0
- package/LICENSE +21 -21
- package/README.md +866 -625
- package/examples/README.md +323 -0
- package/examples/basic.ts +55 -0
- package/examples/chat.ts +87 -0
- package/examples/metadata.ts +72 -0
- package/examples/streaming.ts +61 -0
- package/package.json +76 -69
- package/dist/cjs/core/config/perplexity-config.js.map +0 -1
- package/dist/cjs/core/config/revenium-config.js.map +0 -1
- package/dist/cjs/core/tracking/metering.js.map +0 -1
- package/dist/cjs/core/wrapper/perplexity-client.js.map +0 -1
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/types/index.js.map +0 -1
- package/dist/cjs/utils/logger.js.map +0 -1
- package/dist/esm/core/config/perplexity-config.js.map +0 -1
- package/dist/esm/core/config/revenium-config.js.map +0 -1
- package/dist/esm/core/tracking/metering.js.map +0 -1
- package/dist/esm/core/wrapper/perplexity-client.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/types/index.js.map +0 -1
- package/dist/esm/utils/logger.js.map +0 -1
- package/dist/types/core/config/perplexity-config.d.ts.map +0 -1
- package/dist/types/core/config/revenium-config.d.ts.map +0 -1
- package/dist/types/core/tracking/metering.d.ts.map +0 -1
- package/dist/types/core/wrapper/perplexity-client.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/types/index.d.ts.map +0 -1
- package/dist/types/utils/logger.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,625 +1,866 @@
|
|
|
1
|
-
# Revenium Middleware for Perplexity
|
|
2
|
-
|
|
3
|
-
A lightweight, production-ready middleware that adds **Revenium metering and tracking** to Perplexity AI API calls.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@revenium/perplexity)
|
|
6
|
-
[](https://www.npmjs.com/package/@revenium/perplexity)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- ✅ **Zero Configuration** - Works out of the box with environment variables
|
|
11
|
+
- ✅ **Automatic Metering** - Tracks all API calls with detailed usage metrics
|
|
12
|
+
- ✅ **Streaming Support** - Full support for streaming responses
|
|
13
|
+
- ✅ **TypeScript First** - Built with TypeScript, includes full type definitions
|
|
14
|
+
- ✅ **Multi-Format** - Supports both ESM and CommonJS
|
|
15
|
+
- ✅ **Custom Metadata** - Add custom tracking metadata to any request
|
|
16
|
+
- ✅ **Production Ready** - Battle-tested and optimized for production use
|
|
17
|
+
|
|
18
|
+
## Package Migration
|
|
19
|
+
|
|
20
|
+
This package has been renamed from `revenium-middleware-perplexity-node` to `@revenium/perplexity` for better organization and simpler naming.
|
|
21
|
+
|
|
22
|
+
### Migration Steps
|
|
23
|
+
|
|
24
|
+
If you're upgrading from the old package:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Uninstall the old package
|
|
28
|
+
npm uninstall revenium-middleware-perplexity-node
|
|
29
|
+
|
|
30
|
+
# Install the new package
|
|
31
|
+
npm install @revenium/perplexity
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Update your imports:**
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Old import
|
|
38
|
+
import "revenium-middleware-perplexity-node";
|
|
39
|
+
|
|
40
|
+
// New import
|
|
41
|
+
import "@revenium/perplexity";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
All functionality remains exactly the same - only the package name has changed.
|
|
45
|
+
|
|
46
|
+
## Table of Contents
|
|
47
|
+
|
|
48
|
+
- [Installation](https://github.com/revenium/revenium-middleware-perplexity-node#-installation)
|
|
49
|
+
- [Three Ways to Use This Middleware](https://github.com/revenium/revenium-middleware-perplexity-node#-three-ways-to-use-this-middleware)
|
|
50
|
+
- [Option 1: New Project with npm Package](https://github.com/revenium/revenium-middleware-perplexity-node#option-1-new-project-with-npm-package-recommended)
|
|
51
|
+
- [Option 2: Clone and Use Locally](https://github.com/revenium/revenium-middleware-perplexity-node#option-2-clone-and-use-locally)
|
|
52
|
+
- [Option 3: Add to Existing Project](https://github.com/revenium/revenium-middleware-perplexity-node#option-3-add-to-existing-project)
|
|
53
|
+
- [Quick Start](https://github.com/revenium/revenium-middleware-perplexity-node#-quick-start)
|
|
54
|
+
- [API Reference](https://github.com/revenium/revenium-middleware-perplexity-node#-api-reference)
|
|
55
|
+
- [Examples](https://github.com/revenium/revenium-middleware-perplexity-node#-examples)
|
|
56
|
+
- [Environment Variables](https://github.com/revenium/revenium-middleware-perplexity-node#-environment-variables)
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install @revenium/perplexity
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Three Ways to Use This Middleware
|
|
65
|
+
|
|
66
|
+
### Option 1: New Project with npm Package (Recommended)
|
|
67
|
+
|
|
68
|
+
**Best for:** Starting a new project or adding Perplexity with Revenium to an existing project.
|
|
69
|
+
|
|
70
|
+
#### Step 1: Create a new project
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
mkdir my-perplexity-project
|
|
74
|
+
cd my-perplexity-project
|
|
75
|
+
npm init -y
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Step 2: Install the middleware
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install @revenium/perplexity dotenv
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Step 3: Create `.env` file
|
|
85
|
+
|
|
86
|
+
```env
|
|
87
|
+
# Perplexity API Configuration
|
|
88
|
+
PERPLEXITY_API_KEY=your_perplexity_api_key
|
|
89
|
+
|
|
90
|
+
# Revenium Metering Configuration
|
|
91
|
+
REVENIUM_METERING_API_KEY=your_revenium_api_key
|
|
92
|
+
REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### Step 4: Create `index.js`
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const {
|
|
99
|
+
initializeReveniumFromEnv,
|
|
100
|
+
initializePerplexityFromEnv,
|
|
101
|
+
createChatCompletion,
|
|
102
|
+
PERPLEXITY_MODELS,
|
|
103
|
+
} = require("@revenium/perplexity");
|
|
104
|
+
|
|
105
|
+
async function main() {
|
|
106
|
+
// Initialize configurations
|
|
107
|
+
initializeReveniumFromEnv();
|
|
108
|
+
initializePerplexityFromEnv();
|
|
109
|
+
|
|
110
|
+
// Create a chat completion
|
|
111
|
+
const result = await createChatCompletion({
|
|
112
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
113
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
console.log("Response:", result.content);
|
|
117
|
+
console.log("Tokens used:", result.usage.totalTokens);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
main().catch(console.error);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Step 5: Run your project
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
node index.js
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### Option 2: Clone and Use Locally
|
|
132
|
+
|
|
133
|
+
**Best for:** Development, testing, or contributing to the middleware.
|
|
134
|
+
|
|
135
|
+
#### Step 1: Clone the repository
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/revenium/revenium-middleware-perplexity-node.git
|
|
139
|
+
cd revenium-middleware-perplexity-node
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Step 2: Install dependencies
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm install
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Step 3: Create `.env` file
|
|
149
|
+
|
|
150
|
+
```env
|
|
151
|
+
# Perplexity API Configuration
|
|
152
|
+
PERPLEXITY_API_KEY=your_perplexity_api_key
|
|
153
|
+
|
|
154
|
+
# Revenium Metering Configuration
|
|
155
|
+
REVENIUM_METERING_API_KEY=your_revenium_api_key
|
|
156
|
+
REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Step 4: Build the project
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npm run build
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Step 5: Run examples
|
|
166
|
+
|
|
167
|
+
**TypeScript Examples:**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npm run example:basic # Basic chat completion
|
|
171
|
+
npm run example:streaming # Streaming response
|
|
172
|
+
npm run example:chat # Multi-turn conversation
|
|
173
|
+
npm run example:metadata # Custom metadata
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**JavaScript Playground:**
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npm run playground:basic # Basic chat completion
|
|
180
|
+
npm run playground:streaming # Streaming response
|
|
181
|
+
npm run playground:chat # Multi-turn conversation
|
|
182
|
+
npm run playground:metadata # Custom metadata
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Step 6: Use in your own code
|
|
186
|
+
|
|
187
|
+
After building, you can import from the local build:
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const {
|
|
191
|
+
initializeReveniumFromEnv,
|
|
192
|
+
initializePerplexityFromEnv,
|
|
193
|
+
createChatCompletion,
|
|
194
|
+
} = require("./dist/cjs");
|
|
195
|
+
|
|
196
|
+
// Your code here...
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### Option 3: Add to Existing Project
|
|
202
|
+
|
|
203
|
+
**Best for:** Integrating Perplexity with Revenium into an existing Node.js project.
|
|
204
|
+
|
|
205
|
+
#### Step 1: Install the middleware
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm install @revenium/perplexity
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Step 2: Add environment variables
|
|
212
|
+
|
|
213
|
+
Add to your existing `.env` file:
|
|
214
|
+
|
|
215
|
+
```env
|
|
216
|
+
# Perplexity API Configuration
|
|
217
|
+
PERPLEXITY_API_KEY=your_perplexity_api_key
|
|
218
|
+
|
|
219
|
+
# Revenium Metering Configuration
|
|
220
|
+
REVENIUM_METERING_API_KEY=your_revenium_api_key
|
|
221
|
+
REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Step 3: Initialize in your application
|
|
225
|
+
|
|
226
|
+
**For CommonJS projects:**
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
require("dotenv").config();
|
|
230
|
+
const {
|
|
231
|
+
initializeReveniumFromEnv,
|
|
232
|
+
initializePerplexityFromEnv,
|
|
233
|
+
createChatCompletion,
|
|
234
|
+
PERPLEXITY_MODELS,
|
|
235
|
+
} = require("@revenium/perplexity");
|
|
236
|
+
|
|
237
|
+
// Initialize once at app startup
|
|
238
|
+
initializeReveniumFromEnv();
|
|
239
|
+
initializePerplexityFromEnv();
|
|
240
|
+
|
|
241
|
+
// Use anywhere in your app
|
|
242
|
+
async function askPerplexity(question) {
|
|
243
|
+
const result = await createChatCompletion({
|
|
244
|
+
messages: [{ role: "user", content: question }],
|
|
245
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
246
|
+
});
|
|
247
|
+
return result.content;
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**For ES Modules projects:**
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
import "dotenv/config";
|
|
255
|
+
import {
|
|
256
|
+
initializeReveniumFromEnv,
|
|
257
|
+
initializePerplexityFromEnv,
|
|
258
|
+
createChatCompletion,
|
|
259
|
+
PERPLEXITY_MODELS,
|
|
260
|
+
} from "@revenium/perplexity";
|
|
261
|
+
|
|
262
|
+
// Initialize once at app startup
|
|
263
|
+
initializeReveniumFromEnv();
|
|
264
|
+
initializePerplexityFromEnv();
|
|
265
|
+
|
|
266
|
+
// Use anywhere in your app
|
|
267
|
+
export async function askPerplexity(question) {
|
|
268
|
+
const result = await createChatCompletion({
|
|
269
|
+
messages: [{ role: "user", content: question }],
|
|
270
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
271
|
+
});
|
|
272
|
+
return result.content;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**For TypeScript projects:**
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import "dotenv/config";
|
|
280
|
+
import {
|
|
281
|
+
initializeReveniumFromEnv,
|
|
282
|
+
initializePerplexityFromEnv,
|
|
283
|
+
createChatCompletion,
|
|
284
|
+
PERPLEXITY_MODELS,
|
|
285
|
+
type ChatCompletionResult,
|
|
286
|
+
} from "@revenium/perplexity";
|
|
287
|
+
|
|
288
|
+
// Initialize once at app startup
|
|
289
|
+
initializeReveniumFromEnv();
|
|
290
|
+
initializePerplexityFromEnv();
|
|
291
|
+
|
|
292
|
+
// Use anywhere in your app
|
|
293
|
+
export async function askPerplexity(question: string): Promise<string> {
|
|
294
|
+
const result: ChatCompletionResult = await createChatCompletion({
|
|
295
|
+
messages: [{ role: "user", content: question }],
|
|
296
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
297
|
+
});
|
|
298
|
+
return result.content;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Quick Start
|
|
305
|
+
|
|
306
|
+
### 1. Set up environment variables
|
|
307
|
+
|
|
308
|
+
Create a `.env` file in your project root:
|
|
309
|
+
|
|
310
|
+
```env
|
|
311
|
+
# Perplexity API Configuration
|
|
312
|
+
PERPLEXITY_API_KEY=your_perplexity_api_key
|
|
313
|
+
|
|
314
|
+
# Revenium Metering Configuration
|
|
315
|
+
REVENIUM_METERING_API_KEY=your_revenium_api_key
|
|
316
|
+
REVENIUM_METERING_BASE_URL=https://api.revenium.io/meter
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### 2. Initialize and use
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
import {
|
|
323
|
+
initializeReveniumFromEnv,
|
|
324
|
+
initializePerplexityFromEnv,
|
|
325
|
+
createChatCompletion,
|
|
326
|
+
PERPLEXITY_MODELS,
|
|
327
|
+
} from "@revenium/perplexity";
|
|
328
|
+
|
|
329
|
+
// Initialize configurations
|
|
330
|
+
initializeReveniumFromEnv();
|
|
331
|
+
initializePerplexityFromEnv();
|
|
332
|
+
|
|
333
|
+
// Create a chat completion
|
|
334
|
+
const result = await createChatCompletion({
|
|
335
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
336
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
console.log(result.content);
|
|
340
|
+
// Output: "The capital of France is Paris."
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## API Reference
|
|
344
|
+
|
|
345
|
+
### Configuration
|
|
346
|
+
|
|
347
|
+
#### `initializeReveniumFromEnv()`
|
|
348
|
+
|
|
349
|
+
Initialize Revenium configuration from environment variables.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
const config = initializeReveniumFromEnv();
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### `initializePerplexityFromEnv()`
|
|
356
|
+
|
|
357
|
+
Initialize Perplexity configuration from environment variables.
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const config = initializePerplexityFromEnv();
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### `initializeRevenium(config)`
|
|
364
|
+
|
|
365
|
+
Initialize Revenium with custom configuration.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
initializeRevenium({
|
|
369
|
+
meteringApiKey: "your_api_key",
|
|
370
|
+
meteringBaseUrl: "https://api.revenium.io/meter",
|
|
371
|
+
teamId: "your_team_id", // Optional
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### `initializePerplexity(config)`
|
|
376
|
+
|
|
377
|
+
Initialize Perplexity with custom configuration.
|
|
378
|
+
|
|
379
|
+
```typescript
|
|
380
|
+
initializePerplexity({
|
|
381
|
+
apiKey: "your_perplexity_api_key",
|
|
382
|
+
baseUrl: "https://api.perplexity.ai", // Optional
|
|
383
|
+
});
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Chat Completions
|
|
387
|
+
|
|
388
|
+
#### `createChatCompletion(params)`
|
|
389
|
+
|
|
390
|
+
Create a chat completion with automatic metering.
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
const result = await createChatCompletion({
|
|
394
|
+
messages: [
|
|
395
|
+
{ role: "system", content: "You are a helpful assistant." },
|
|
396
|
+
{ role: "user", content: "Hello!" },
|
|
397
|
+
],
|
|
398
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
399
|
+
maxTokens: 100,
|
|
400
|
+
temperature: 0.7,
|
|
401
|
+
usageMetadata: {
|
|
402
|
+
// Optional
|
|
403
|
+
subscriber: { id: "user-123" },
|
|
404
|
+
organizationId: "org-456",
|
|
405
|
+
productId: "product-789",
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
console.log(result.content);
|
|
410
|
+
console.log(result.usage);
|
|
411
|
+
console.log(result.transactionId);
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Parameters:**
|
|
415
|
+
|
|
416
|
+
- `messages` - Array of message objects with `role` and `content`
|
|
417
|
+
- `model` - Perplexity model to use (see [Available Models](https://github.com/revenium/revenium-middleware-perplexity-node#available-models))
|
|
418
|
+
- `maxTokens` - Maximum tokens to generate (optional)
|
|
419
|
+
- `temperature` - Sampling temperature 0-2 (optional)
|
|
420
|
+
- `topP` - Nucleus sampling parameter (optional)
|
|
421
|
+
- `presencePenalty` - Presence penalty -2 to 2 (optional)
|
|
422
|
+
- `frequencyPenalty` - Frequency penalty -2 to 2 (optional)
|
|
423
|
+
- `usageMetadata` - Custom metadata for tracking (optional)
|
|
424
|
+
|
|
425
|
+
**Returns:**
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
{
|
|
429
|
+
content: string;
|
|
430
|
+
role: string;
|
|
431
|
+
finishReason: string | null;
|
|
432
|
+
usage: {
|
|
433
|
+
promptTokens: number;
|
|
434
|
+
completionTokens: number;
|
|
435
|
+
totalTokens: number;
|
|
436
|
+
}
|
|
437
|
+
model: string;
|
|
438
|
+
transactionId: string;
|
|
439
|
+
rawResponse: PerplexityResponse;
|
|
440
|
+
}
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
#### `createStreamingChatCompletion(params)`
|
|
444
|
+
|
|
445
|
+
Create a streaming chat completion.
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
const result = await createStreamingChatCompletion({
|
|
449
|
+
messages: [{ role: "user", content: "Count from 1 to 5" }],
|
|
450
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
for await (const chunk of result.stream) {
|
|
454
|
+
const content = chunk.choices[0]?.delta?.content || "";
|
|
455
|
+
process.stdout.write(content);
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Returns:**
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
{
|
|
463
|
+
stream: AsyncGenerator<PerplexityStreamChunk>;
|
|
464
|
+
transactionId: string;
|
|
465
|
+
model: string;
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Available Models
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { PERPLEXITY_MODELS } from "@revenium/perplexity";
|
|
473
|
+
|
|
474
|
+
// Online Models (with internet access)
|
|
475
|
+
PERPLEXITY_MODELS.SONAR; // "sonar"
|
|
476
|
+
PERPLEXITY_MODELS.SONAR_PRO; // "sonar-pro"
|
|
477
|
+
PERPLEXITY_MODELS.SONAR_REASONING; // "sonar-reasoning"
|
|
478
|
+
|
|
479
|
+
// Chat Models (offline)
|
|
480
|
+
PERPLEXITY_MODELS.LLAMA_3_1_SONAR_SMALL_128K_CHAT; // "llama-3.1-sonar-small-128k-chat"
|
|
481
|
+
PERPLEXITY_MODELS.LLAMA_3_1_SONAR_LARGE_128K_CHAT; // "llama-3.1-sonar-large-128k-chat"
|
|
482
|
+
PERPLEXITY_MODELS.LLAMA_3_1_SONAR_HUGE_128K_CHAT; // "llama-3.1-sonar-huge-128k-chat"
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Utility Functions
|
|
486
|
+
|
|
487
|
+
#### `disableRevenium()` / `enableRevenium()`
|
|
488
|
+
|
|
489
|
+
Temporarily disable or enable Revenium metering.
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
import { disableRevenium, enableRevenium } from "@revenium/perplexity";
|
|
493
|
+
|
|
494
|
+
disableRevenium(); // Stop sending metering data
|
|
495
|
+
// ... make API calls ...
|
|
496
|
+
enableRevenium(); // Resume sending metering data
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### `generateTransactionId()`
|
|
500
|
+
|
|
501
|
+
Generate a unique transaction ID.
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
import { generateTransactionId } from "@revenium/perplexity";
|
|
505
|
+
|
|
506
|
+
const txnId = generateTransactionId();
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Examples
|
|
510
|
+
|
|
511
|
+
### Basic Chat Completion
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
import {
|
|
515
|
+
initializeReveniumFromEnv,
|
|
516
|
+
initializePerplexityFromEnv,
|
|
517
|
+
createChatCompletion,
|
|
518
|
+
PERPLEXITY_MODELS,
|
|
519
|
+
} from "@revenium/perplexity";
|
|
520
|
+
|
|
521
|
+
initializeReveniumFromEnv();
|
|
522
|
+
initializePerplexityFromEnv();
|
|
523
|
+
|
|
524
|
+
const result = await createChatCompletion({
|
|
525
|
+
messages: [{ role: "user", content: "What is the capital of France?" }],
|
|
526
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
console.log(result.content);
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Streaming Response
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
const result = await createStreamingChatCompletion({
|
|
536
|
+
messages: [{ role: "user", content: "Write a short poem about AI" }],
|
|
537
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
for await (const chunk of result.stream) {
|
|
541
|
+
const content = chunk.choices[0]?.delta?.content || "";
|
|
542
|
+
process.stdout.write(content);
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Multi-turn Conversation
|
|
547
|
+
|
|
548
|
+
```typescript
|
|
549
|
+
const messages = [
|
|
550
|
+
{ role: "system", content: "You are a helpful assistant." },
|
|
551
|
+
{ role: "user", content: "What is the capital of France?" },
|
|
552
|
+
];
|
|
553
|
+
|
|
554
|
+
const response1 = await createChatCompletion({
|
|
555
|
+
messages,
|
|
556
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
messages.push({ role: "assistant", content: response1.content });
|
|
560
|
+
messages.push({ role: "user", content: "What is its population?" });
|
|
561
|
+
|
|
562
|
+
const response2 = await createChatCompletion({
|
|
563
|
+
messages,
|
|
564
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
565
|
+
});
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Custom Metadata
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
const result = await createChatCompletion({
|
|
572
|
+
messages: [{ role: "user", content: "Hello!" }],
|
|
573
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
574
|
+
usageMetadata: {
|
|
575
|
+
subscriber: {
|
|
576
|
+
id: "user-123",
|
|
577
|
+
email: "user@example.com",
|
|
578
|
+
},
|
|
579
|
+
organizationId: "org-456",
|
|
580
|
+
productId: "premium-plan",
|
|
581
|
+
traceId: "trace-abc-123",
|
|
582
|
+
},
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## What Gets Tracked
|
|
587
|
+
|
|
588
|
+
The middleware automatically captures:
|
|
589
|
+
|
|
590
|
+
- **Token Usage**: Prompt and completion tokens for accurate billing
|
|
591
|
+
- **Request Duration**: Total time for each API call
|
|
592
|
+
- **Model Information**: Which Perplexity model was used
|
|
593
|
+
- **Operation Type**: Chat completion, streaming, etc.
|
|
594
|
+
- **Error Tracking**: Failed requests and error details
|
|
595
|
+
- **Streaming Metrics**: Time to first token for streaming responses
|
|
596
|
+
- **Custom Metadata**: Business context you provide
|
|
597
|
+
|
|
598
|
+
## Advanced Usage
|
|
599
|
+
|
|
600
|
+
### Streaming Responses
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
import {
|
|
604
|
+
initializeReveniumFromEnv,
|
|
605
|
+
initializePerplexityFromEnv,
|
|
606
|
+
createStreamingChatCompletion,
|
|
607
|
+
PERPLEXITY_MODELS,
|
|
608
|
+
} from "@revenium/perplexity";
|
|
609
|
+
|
|
610
|
+
initializeReveniumFromEnv();
|
|
611
|
+
initializePerplexityFromEnv();
|
|
612
|
+
|
|
613
|
+
const result = await createStreamingChatCompletion({
|
|
614
|
+
messages: [{ role: "user", content: "Count from 1 to 5" }],
|
|
615
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
616
|
+
usageMetadata: {
|
|
617
|
+
subscriber: { id: "user-123" },
|
|
618
|
+
taskType: "counting-demo",
|
|
619
|
+
},
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
for await (const chunk of result.stream) {
|
|
623
|
+
const content = chunk.choices[0]?.delta?.content || "";
|
|
624
|
+
process.stdout.write(content);
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
### Custom Metadata Tracking
|
|
629
|
+
|
|
630
|
+
Add business context to your AI usage:
|
|
631
|
+
|
|
632
|
+
```typescript
|
|
633
|
+
const customMetadata = {
|
|
634
|
+
subscriber: {
|
|
635
|
+
id: "user-789",
|
|
636
|
+
email: "user@company.com",
|
|
637
|
+
credential: {
|
|
638
|
+
name: "premium-user",
|
|
639
|
+
value: "tier-1",
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
organizationId: "org-456",
|
|
643
|
+
productId: "premium-plan",
|
|
644
|
+
taskType: "RESEARCH",
|
|
645
|
+
agent: "ResearchBot",
|
|
646
|
+
traceId: "session-123",
|
|
647
|
+
responseQualityScore: 9.2,
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
const result = await createChatCompletion({
|
|
651
|
+
messages: [{ role: "user", content: "Research AI trends" }],
|
|
652
|
+
model: PERPLEXITY_MODELS.SONAR_PRO,
|
|
653
|
+
usageMetadata: customMetadata,
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Usage Metadata Interface
|
|
658
|
+
|
|
659
|
+
All metadata fields are optional:
|
|
660
|
+
|
|
661
|
+
```typescript
|
|
662
|
+
interface UsageMetadata {
|
|
663
|
+
traceId?: string; // Session or conversation ID
|
|
664
|
+
taskType?: string; // Type of AI task
|
|
665
|
+
organizationId?: string; // Organization/company ID
|
|
666
|
+
subscriptionId?: string; // Billing plan ID
|
|
667
|
+
productId?: string; // Your product/feature ID
|
|
668
|
+
agent?: string; // AI agent identifier
|
|
669
|
+
responseQualityScore?: number; // Quality score (0-1)
|
|
670
|
+
subscriber?: {
|
|
671
|
+
id?: string; // User ID from your system
|
|
672
|
+
email?: string; // User's email address
|
|
673
|
+
credential?: {
|
|
674
|
+
name?: string; // Credential name
|
|
675
|
+
value?: string; // Credential value
|
|
676
|
+
};
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
## Configuration Options
|
|
682
|
+
|
|
683
|
+
### Environment Variables
|
|
684
|
+
|
|
685
|
+
| Variable | Required | Default | Description |
|
|
686
|
+
| ---------------------------- | -------- | ------------------------------- | --------------------------------- |
|
|
687
|
+
| `PERPLEXITY_API_KEY` | Yes | - | Your Perplexity API key |
|
|
688
|
+
| `REVENIUM_METERING_API_KEY` | Yes | - | Your Revenium API key |
|
|
689
|
+
| `REVENIUM_METERING_BASE_URL` | Yes | - | Revenium metering API base URL |
|
|
690
|
+
| `PERPLEXITY_API_BASE_URL` | No | `https://api.perplexity.ai` | Perplexity API base URL |
|
|
691
|
+
| `DEBUG` | No | `false` | Enable debug logging |
|
|
692
|
+
|
|
693
|
+
### Manual Configuration
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
import {
|
|
697
|
+
initializeRevenium,
|
|
698
|
+
initializePerplexity,
|
|
699
|
+
createChatCompletion,
|
|
700
|
+
} from "@revenium/perplexity";
|
|
701
|
+
|
|
702
|
+
// Manual configuration
|
|
703
|
+
initializeRevenium({
|
|
704
|
+
meteringApiKey: "hak_your_revenium_key",
|
|
705
|
+
meteringBaseUrl: "https://api.revenium.io/meter/v2",
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
initializePerplexity({
|
|
709
|
+
apiKey: "pplx_your_perplexity_key",
|
|
710
|
+
baseUrl: "https://api.perplexity.ai",
|
|
711
|
+
});
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
## Troubleshooting
|
|
715
|
+
|
|
716
|
+
### Common Issues
|
|
717
|
+
|
|
718
|
+
#### "Missing API Key" Error
|
|
719
|
+
|
|
720
|
+
```bash
|
|
721
|
+
# Make sure you've set the API keys
|
|
722
|
+
export PERPLEXITY_API_KEY="pplx_your_actual_api_key"
|
|
723
|
+
export REVENIUM_METERING_API_KEY="hak_your_actual_revenium_key"
|
|
724
|
+
|
|
725
|
+
# Verify they're set
|
|
726
|
+
echo $PERPLEXITY_API_KEY
|
|
727
|
+
echo $REVENIUM_METERING_API_KEY
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
#### "Requests not being tracked"
|
|
731
|
+
|
|
732
|
+
```bash
|
|
733
|
+
# Verify Revenium configuration
|
|
734
|
+
export REVENIUM_METERING_API_KEY="hak_your_actual_revenium_key"
|
|
735
|
+
export REVENIUM_METERING_BASE_URL="https://api.revenium.io/meter/v2"
|
|
736
|
+
|
|
737
|
+
# Enable debug logging to see what's happening
|
|
738
|
+
export DEBUG="true"
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
#### TypeScript errors with usageMetadata
|
|
742
|
+
|
|
743
|
+
- Ensure you're importing from `@revenium/perplexity`
|
|
744
|
+
- Check that your TypeScript version is 5.0+
|
|
745
|
+
- Verify you're using the latest version: `npm update @revenium/perplexity`
|
|
746
|
+
|
|
747
|
+
#### Build/Import Errors
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
# Clean and reinstall
|
|
751
|
+
rm -rf node_modules
|
|
752
|
+
npm install
|
|
753
|
+
|
|
754
|
+
# For TypeScript projects
|
|
755
|
+
npm run build
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
### Debug Mode
|
|
759
|
+
|
|
760
|
+
Enable debug logging to troubleshoot issues:
|
|
761
|
+
|
|
762
|
+
```bash
|
|
763
|
+
export DEBUG="true"
|
|
764
|
+
node your-script.js
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
This will show:
|
|
768
|
+
|
|
769
|
+
- Initialization details
|
|
770
|
+
- Configuration loading
|
|
771
|
+
- API call information
|
|
772
|
+
- Error details
|
|
773
|
+
|
|
774
|
+
## Project Structure
|
|
775
|
+
|
|
776
|
+
```
|
|
777
|
+
revenium-middleware-perplexity-node/
|
|
778
|
+
├── src/
|
|
779
|
+
│ ├── core/
|
|
780
|
+
│ │ ├── config/ # Configuration management
|
|
781
|
+
│ │ ├── tracking/ # Metering and tracking
|
|
782
|
+
│ │ └── wrapper/ # Perplexity API wrapper
|
|
783
|
+
│ ├── types/ # TypeScript type definitions
|
|
784
|
+
│ ├── utils/ # Utility functions
|
|
785
|
+
│ └── index.ts # Main entry point
|
|
786
|
+
├── examples/ # TypeScript examples
|
|
787
|
+
├── playground/ # JavaScript examples
|
|
788
|
+
└── dist/
|
|
789
|
+
├── cjs/ # CommonJS build
|
|
790
|
+
├── esm/ # ES Modules build
|
|
791
|
+
└── types/ # TypeScript definitions
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
## Running Examples
|
|
795
|
+
|
|
796
|
+
### TypeScript Examples
|
|
797
|
+
|
|
798
|
+
```bash
|
|
799
|
+
npm run example:basic # Basic chat completion
|
|
800
|
+
npm run example:streaming # Streaming response
|
|
801
|
+
npm run example:chat # Multi-turn conversation
|
|
802
|
+
npm run example:metadata # Custom metadata
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### JavaScript Playground
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
npm run playground:basic # Basic chat completion
|
|
809
|
+
npm run playground:streaming # Streaming response
|
|
810
|
+
npm run playground:chat # Multi-turn conversation
|
|
811
|
+
npm run playground:metadata # Custom metadata
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
## How It Works
|
|
815
|
+
|
|
816
|
+
1. **Initialization**: When you call `initializePerplexityFromEnv()` and `initializeReveniumFromEnv()`, the middleware sets up configurations
|
|
817
|
+
2. **Request Wrapping**: All Perplexity API calls go through the middleware wrapper
|
|
818
|
+
3. **Usage Extraction**: Token counts, model info, and timing data are captured from responses
|
|
819
|
+
4. **Async Tracking**: Usage data is sent to Revenium in the background (fire-and-forget)
|
|
820
|
+
5. **Transparent Response**: Original Perplexity responses are returned unchanged
|
|
821
|
+
|
|
822
|
+
The middleware never blocks your application - if Revenium tracking fails, your Perplexity requests continue normally.
|
|
823
|
+
|
|
824
|
+
## Requirements
|
|
825
|
+
|
|
826
|
+
- Node.js 16+
|
|
827
|
+
- TypeScript 5.0+ (for TypeScript projects)
|
|
828
|
+
- Revenium API key
|
|
829
|
+
- Perplexity API key
|
|
830
|
+
|
|
831
|
+
## Documentation
|
|
832
|
+
|
|
833
|
+
For detailed documentation, visit [docs.revenium.io](https://docs.revenium.io)
|
|
834
|
+
|
|
835
|
+
## Contributing
|
|
836
|
+
|
|
837
|
+
See [CONTRIBUTING.md](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/CONTRIBUTING.md)
|
|
838
|
+
|
|
839
|
+
## Code of Conduct
|
|
840
|
+
|
|
841
|
+
See [CODE_OF_CONDUCT.md](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/CODE_OF_CONDUCT.md)
|
|
842
|
+
|
|
843
|
+
## Security
|
|
844
|
+
|
|
845
|
+
See [SECURITY.md](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/SECURITY.md)
|
|
846
|
+
|
|
847
|
+
## License
|
|
848
|
+
|
|
849
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/LICENSE) file for details.
|
|
850
|
+
|
|
851
|
+
## Support
|
|
852
|
+
|
|
853
|
+
For issues, feature requests, or contributions:
|
|
854
|
+
|
|
855
|
+
- **GitHub Repository**: [revenium/revenium-middleware-perplexity-node](https://github.com/revenium/revenium-middleware-perplexity-node)
|
|
856
|
+
- **Issues**: [Report bugs or request features](https://github.com/revenium/revenium-middleware-perplexity-node/issues)
|
|
857
|
+
- **Documentation**: [docs.revenium.io](https://docs.revenium.io)
|
|
858
|
+
- **Contact**: Reach out to the Revenium team for additional support
|
|
859
|
+
|
|
860
|
+
## Development
|
|
861
|
+
|
|
862
|
+
For development and testing instructions, see [DEVELOPMENT.md](https://github.com/revenium/revenium-middleware-perplexity-node/blob/HEAD/DEVELOPMENT.md).
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
**Built by Revenium**
|