@ai-sdk/perplexity 0.0.0-01d6317c-20260129172110

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.
@@ -0,0 +1,196 @@
1
+ ---
2
+ title: Perplexity
3
+ description: Learn how to use Perplexity's Sonar API with the AI SDK.
4
+ ---
5
+
6
+ # Perplexity Provider
7
+
8
+ The [Perplexity](https://sonar.perplexity.ai) provider offers access to Sonar API - a language model that uniquely combines real-time web search with natural language processing. Each response is grounded in current web data and includes detailed citations, making it ideal for research, fact-checking, and obtaining up-to-date information.
9
+
10
+ API keys can be obtained from the [Perplexity Platform](https://docs.perplexity.ai).
11
+
12
+ ## Setup
13
+
14
+ The Perplexity provider is available via the `@ai-sdk/perplexity` module. You can install it with:
15
+
16
+ <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
17
+ <Tab>
18
+ <Snippet text="pnpm add @ai-sdk/perplexity" dark />
19
+ </Tab>
20
+ <Tab>
21
+ <Snippet text="npm install @ai-sdk/perplexity" dark />
22
+ </Tab>
23
+ <Tab>
24
+ <Snippet text="yarn add @ai-sdk/perplexity" dark />
25
+ </Tab>
26
+
27
+ <Tab>
28
+ <Snippet text="bun add @ai-sdk/perplexity" dark />
29
+ </Tab>
30
+ </Tabs>
31
+
32
+ ## Provider Instance
33
+
34
+ You can import the default provider instance `perplexity` from `@ai-sdk/perplexity`:
35
+
36
+ ```ts
37
+ import { perplexity } from '@ai-sdk/perplexity';
38
+ ```
39
+
40
+ For custom configuration, you can import `createPerplexity` and create a provider instance with your settings:
41
+
42
+ ```ts
43
+ import { createPerplexity } from '@ai-sdk/perplexity';
44
+
45
+ const perplexity = createPerplexity({
46
+ apiKey: process.env.PERPLEXITY_API_KEY ?? '',
47
+ });
48
+ ```
49
+
50
+ You can use the following optional settings to customize the Perplexity provider instance:
51
+
52
+ - **baseURL** _string_
53
+
54
+ Use a different URL prefix for API calls.
55
+ The default prefix is `https://api.perplexity.ai`.
56
+
57
+ - **apiKey** _string_
58
+
59
+ API key that is being sent using the `Authorization` header. It defaults to
60
+ the `PERPLEXITY_API_KEY` environment variable.
61
+
62
+ - **headers** _Record&lt;string,string&gt;_
63
+
64
+ Custom headers to include in the requests.
65
+
66
+ - **fetch** _(input: RequestInfo, init?: RequestInit) => Promise&lt;Response&gt;_
67
+
68
+ Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation.
69
+
70
+ ## Language Models
71
+
72
+ You can create Perplexity models using a provider instance:
73
+
74
+ ```ts
75
+ import { perplexity } from '@ai-sdk/perplexity';
76
+ import { generateText } from 'ai';
77
+
78
+ const { text } = await generateText({
79
+ model: perplexity('sonar-pro'),
80
+ prompt: 'What are the latest developments in quantum computing?',
81
+ });
82
+ ```
83
+
84
+ ### Sources
85
+
86
+ Websites that have been used to generate the response are included in the `sources` property of the result:
87
+
88
+ ```ts
89
+ import { perplexity } from '@ai-sdk/perplexity';
90
+ import { generateText } from 'ai';
91
+
92
+ const { text, sources } = await generateText({
93
+ model: perplexity('sonar-pro'),
94
+ prompt: 'What are the latest developments in quantum computing?',
95
+ });
96
+
97
+ console.log(sources);
98
+ ```
99
+
100
+ ### Provider Options & Metadata
101
+
102
+ The Perplexity provider includes additional metadata in the response through `providerMetadata`.
103
+ Additional configuration options are available through `providerOptions`.
104
+
105
+ ```ts
106
+ const result = await generateText({
107
+ model: perplexity('sonar-pro'),
108
+ prompt: 'What are the latest developments in quantum computing?',
109
+ providerOptions: {
110
+ perplexity: {
111
+ return_images: true, // Enable image responses (Tier-2 Perplexity users only)
112
+ },
113
+ },
114
+ });
115
+
116
+ console.log(result.providerMetadata);
117
+ // Example output:
118
+ // {
119
+ // perplexity: {
120
+ // usage: { citationTokens: 5286, numSearchQueries: 1 },
121
+ // images: [
122
+ // { imageUrl: "https://example.com/image1.jpg", originUrl: "https://elsewhere.com/page1", height: 1280, width: 720 },
123
+ // { imageUrl: "https://example.com/image2.jpg", originUrl: "https://elsewhere.com/page2", height: 1280, width: 720 }
124
+ // ]
125
+ // },
126
+ // }
127
+ ```
128
+
129
+ The metadata includes:
130
+
131
+ - `usage`: Object containing `citationTokens` and `numSearchQueries` metrics
132
+ - `images`: Array of image URLs when `return_images` is enabled (Tier-2 users only)
133
+
134
+ You can enable image responses by setting `return_images: true` in the provider options. This feature is only available to Perplexity Tier-2 users and above.
135
+
136
+ ### PDF Support
137
+
138
+ The Perplexity provider supports reading PDF files.
139
+ You can pass PDF files as part of the message content using the `file` type:
140
+
141
+ ```ts
142
+ const result = await generateText({
143
+ model: perplexity('sonar-pro'),
144
+ messages: [
145
+ {
146
+ role: 'user',
147
+ content: [
148
+ {
149
+ type: 'text',
150
+ text: 'What is this document about?',
151
+ },
152
+ {
153
+ type: 'file',
154
+ data: fs.readFileSync('./data/ai.pdf'),
155
+ mediaType: 'application/pdf',
156
+ filename: 'ai.pdf', // optional
157
+ },
158
+ ],
159
+ },
160
+ ],
161
+ });
162
+ ```
163
+
164
+ You can also pass the URL of a PDF:
165
+
166
+ ```ts
167
+ {
168
+ type: 'file',
169
+ data: new URL('https://example.com/document.pdf'),
170
+ mediaType: 'application/pdf',
171
+ filename: 'document.pdf', // optional
172
+ }
173
+ ```
174
+
175
+ The model will have access to the contents of the PDF file and
176
+ respond to questions about it.
177
+
178
+ <Note>
179
+ For more details about Perplexity's capabilities, see the [Perplexity chat
180
+ completion docs](https://docs.perplexity.ai/api-reference/chat-completions).
181
+ </Note>
182
+
183
+ ## Model Capabilities
184
+
185
+ | Model | Image Input | Object Generation | Tool Usage | Tool Streaming |
186
+ | --------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
187
+ | `sonar-deep-research` | <Cross size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
188
+ | `sonar-reasoning-pro` | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
189
+ | `sonar-reasoning` | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
190
+ | `sonar-pro` | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
191
+ | `sonar` | <Check size={18} /> | <Check size={18} /> | <Cross size={18} /> | <Cross size={18} /> |
192
+
193
+ <Note>
194
+ Please see the [Perplexity docs](https://docs.perplexity.ai) for detailed API
195
+ documentation and the latest updates.
196
+ </Note>
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@ai-sdk/perplexity",
3
+ "version": "0.0.0-01d6317c-20260129172110",
4
+ "license": "Apache-2.0",
5
+ "sideEffects": false,
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist/**/*",
11
+ "docs/**/*",
12
+ "src",
13
+ "!src/**/*.test.ts",
14
+ "!src/**/*.test-d.ts",
15
+ "!src/**/__snapshots__",
16
+ "!src/**/__fixtures__",
17
+ "CHANGELOG.md",
18
+ "README.md"
19
+ ],
20
+ "directories": {
21
+ "doc": "./docs"
22
+ },
23
+ "exports": {
24
+ "./package.json": "./package.json",
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.mjs",
28
+ "require": "./dist/index.js"
29
+ }
30
+ },
31
+ "dependencies": {
32
+ "@ai-sdk/provider": "0.0.0-01d6317c-20260129172110",
33
+ "@ai-sdk/provider-utils": "0.0.0-01d6317c-20260129172110"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "20.17.24",
37
+ "tsup": "^8",
38
+ "typescript": "5.8.3",
39
+ "zod": "3.25.76",
40
+ "@ai-sdk/test-server": "1.0.3",
41
+ "@vercel/ai-tsconfig": "0.0.0"
42
+ },
43
+ "peerDependencies": {
44
+ "zod": "^3.25.76 || ^4.1.8"
45
+ },
46
+ "engines": {
47
+ "node": ">=18"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "homepage": "https://ai-sdk.dev/docs",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/vercel/ai.git"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/vercel/ai/issues"
59
+ },
60
+ "keywords": [
61
+ "ai"
62
+ ],
63
+ "scripts": {
64
+ "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
65
+ "build:watch": "pnpm clean && tsup --watch",
66
+ "clean": "del-cli dist docs *.tsbuildinfo",
67
+ "lint": "eslint \"./**/*.ts*\"",
68
+ "type-check": "tsc --build",
69
+ "prettier-check": "prettier --check \"./**/*.ts*\"",
70
+ "test": "pnpm test:node && pnpm test:edge",
71
+ "test:update": "pnpm test:node -u",
72
+ "test:watch": "vitest --config vitest.node.config.js",
73
+ "test:edge": "vitest --config vitest.edge.config.js --run",
74
+ "test:node": "vitest --config vitest.node.config.js --run"
75
+ }
76
+ }
@@ -0,0 +1,48 @@
1
+ import { LanguageModelV3Usage } from '@ai-sdk/provider';
2
+
3
+ export function convertPerplexityUsage(
4
+ usage:
5
+ | {
6
+ prompt_tokens?: number | null | undefined;
7
+ completion_tokens?: number | null | undefined;
8
+ reasoning_tokens?: number | null | undefined;
9
+ }
10
+ | undefined
11
+ | null,
12
+ ): LanguageModelV3Usage {
13
+ if (usage == null) {
14
+ return {
15
+ inputTokens: {
16
+ total: undefined,
17
+ noCache: undefined,
18
+ cacheRead: undefined,
19
+ cacheWrite: undefined,
20
+ },
21
+ outputTokens: {
22
+ total: undefined,
23
+ text: undefined,
24
+ reasoning: undefined,
25
+ },
26
+ raw: undefined,
27
+ };
28
+ }
29
+
30
+ const promptTokens = usage.prompt_tokens ?? 0;
31
+ const completionTokens = usage.completion_tokens ?? 0;
32
+ const reasoningTokens = usage.reasoning_tokens ?? 0;
33
+
34
+ return {
35
+ inputTokens: {
36
+ total: promptTokens,
37
+ noCache: promptTokens,
38
+ cacheRead: undefined,
39
+ cacheWrite: undefined,
40
+ },
41
+ outputTokens: {
42
+ total: completionTokens,
43
+ text: completionTokens - reasoningTokens,
44
+ reasoning: reasoningTokens,
45
+ },
46
+ raw: usage,
47
+ };
48
+ }
@@ -0,0 +1,107 @@
1
+ import {
2
+ LanguageModelV3Prompt,
3
+ UnsupportedFunctionalityError,
4
+ } from '@ai-sdk/provider';
5
+ import {
6
+ PerplexityMessageContent,
7
+ PerplexityPrompt,
8
+ } from './perplexity-language-model-prompt';
9
+ import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils';
10
+
11
+ export function convertToPerplexityMessages(
12
+ prompt: LanguageModelV3Prompt,
13
+ ): PerplexityPrompt {
14
+ const messages: PerplexityPrompt = [];
15
+
16
+ for (const { role, content } of prompt) {
17
+ switch (role) {
18
+ case 'system': {
19
+ messages.push({ role: 'system', content });
20
+ break;
21
+ }
22
+
23
+ case 'user':
24
+ case 'assistant': {
25
+ const hasMultipartContent = content.some(
26
+ part =>
27
+ (part.type === 'file' && part.mediaType.startsWith('image/')) ||
28
+ (part.type === 'file' && part.mediaType === 'application/pdf'),
29
+ );
30
+
31
+ const messageContent = content
32
+ .map((part, index) => {
33
+ switch (part.type) {
34
+ case 'text': {
35
+ return {
36
+ type: 'text',
37
+ text: part.text,
38
+ };
39
+ }
40
+ case 'file': {
41
+ if (part.mediaType === 'application/pdf') {
42
+ return part.data instanceof URL
43
+ ? {
44
+ type: 'file_url',
45
+ file_url: {
46
+ url: part.data.toString(),
47
+ },
48
+ file_name: part.filename,
49
+ }
50
+ : {
51
+ type: 'file_url',
52
+ file_url: {
53
+ url:
54
+ typeof part.data === 'string'
55
+ ? part.data
56
+ : convertUint8ArrayToBase64(part.data),
57
+ },
58
+ file_name: part.filename || `document-${index}.pdf`,
59
+ };
60
+ } else if (part.mediaType.startsWith('image/')) {
61
+ return part.data instanceof URL
62
+ ? {
63
+ type: 'image_url',
64
+ image_url: {
65
+ url: part.data.toString(),
66
+ },
67
+ }
68
+ : {
69
+ type: 'image_url',
70
+ image_url: {
71
+ url: `data:${part.mediaType ?? 'image/jpeg'};base64,${
72
+ typeof part.data === 'string'
73
+ ? part.data
74
+ : convertUint8ArrayToBase64(part.data)
75
+ }`,
76
+ },
77
+ };
78
+ }
79
+ }
80
+ }
81
+ })
82
+ .filter(Boolean) as PerplexityMessageContent[];
83
+ messages.push({
84
+ role,
85
+ content: hasMultipartContent
86
+ ? messageContent
87
+ : messageContent
88
+ .filter(part => part.type === 'text')
89
+ .map(part => part.text)
90
+ .join(''),
91
+ });
92
+ break;
93
+ }
94
+ case 'tool': {
95
+ throw new UnsupportedFunctionalityError({
96
+ functionality: 'Tool messages',
97
+ });
98
+ }
99
+ default: {
100
+ const _exhaustiveCheck: never = role;
101
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
102
+ }
103
+ }
104
+ }
105
+
106
+ return messages;
107
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { createPerplexity, perplexity } from './perplexity-provider';
2
+ export type {
3
+ PerplexityProvider,
4
+ PerplexityProviderSettings,
5
+ } from './perplexity-provider';
6
+ export { VERSION } from './version';
@@ -0,0 +1,13 @@
1
+ import { LanguageModelV3FinishReason } from '@ai-sdk/provider';
2
+
3
+ export function mapPerplexityFinishReason(
4
+ finishReason: string | null | undefined,
5
+ ): LanguageModelV3FinishReason['unified'] {
6
+ switch (finishReason) {
7
+ case 'stop':
8
+ case 'length':
9
+ return finishReason;
10
+ default:
11
+ return 'other';
12
+ }
13
+ }
@@ -0,0 +1,8 @@
1
+ // https://docs.perplexity.ai/models/model-cards
2
+ export type PerplexityLanguageModelId =
3
+ | 'sonar-deep-research'
4
+ | 'sonar-reasoning-pro'
5
+ | 'sonar-reasoning'
6
+ | 'sonar-pro'
7
+ | 'sonar'
8
+ | (string & {});
@@ -0,0 +1,25 @@
1
+ export type PerplexityPrompt = Array<PerplexityMessage>;
2
+
3
+ export type PerplexityMessage = {
4
+ role: 'system' | 'user' | 'assistant';
5
+ content: string | PerplexityMessageContent[];
6
+ };
7
+
8
+ export type PerplexityMessageContent =
9
+ | {
10
+ type: 'text';
11
+ text: string;
12
+ }
13
+ | {
14
+ type: 'image_url';
15
+ image_url: {
16
+ url: string;
17
+ };
18
+ }
19
+ | {
20
+ type: 'file_url';
21
+ file_url: {
22
+ url: string;
23
+ };
24
+ file_name?: string;
25
+ };