@ai-sdk/perplexity 3.0.63 → 3.1.1
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 +19 -0
- package/README.md +18 -9
- package/dist/index.d.mts +112 -5
- package/dist/index.d.ts +112 -5
- package/dist/index.js +996 -340
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1000 -344
- package/dist/index.mjs.map +1 -1
- package/docs/70-perplexity.mdx +229 -70
- package/package.json +3 -3
- package/src/convert-perplexity-usage.ts +29 -15
- package/src/convert-to-perplexity-input.ts +199 -0
- package/src/index.ts +5 -0
- package/src/map-perplexity-finish-reason.ts +27 -8
- package/src/perplexity-agent-api.ts +206 -0
- package/src/perplexity-embedding-model.ts +5 -2
- package/src/perplexity-language-model-options.ts +124 -8
- package/src/perplexity-language-model-prompt.ts +25 -18
- package/src/perplexity-language-model.ts +653 -305
- package/src/perplexity-options.ts +11 -0
- package/src/perplexity-prepare-tools.ts +48 -0
- package/src/perplexity-provider.ts +4 -4
- package/src/convert-to-perplexity-messages.ts +0 -174
package/docs/70-perplexity.mdx
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Perplexity
|
|
3
|
-
description: Learn how to use Perplexity's
|
|
3
|
+
description: Learn how to use Perplexity's Agent API with the AI SDK.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Perplexity Provider
|
|
7
7
|
|
|
8
|
-
The [Perplexity](https://
|
|
8
|
+
The [Perplexity](https://www.perplexity.ai) provider offers access to the
|
|
9
|
+
[Agent API](https://docs.perplexity.ai/docs/agent-api/quickstart). The Agent API
|
|
10
|
+
can route across models, search the web, call tools, and return cited answers.
|
|
9
11
|
|
|
10
12
|
API keys can be obtained from the [Perplexity Platform](https://docs.perplexity.ai).
|
|
11
13
|
|
|
@@ -76,11 +78,20 @@ import { perplexity } from '@ai-sdk/perplexity';
|
|
|
76
78
|
import { generateText } from 'ai';
|
|
77
79
|
|
|
78
80
|
const { text } = await generateText({
|
|
79
|
-
model: perplexity('
|
|
81
|
+
model: perplexity('low'),
|
|
80
82
|
prompt: 'What are the latest developments in quantum computing?',
|
|
81
83
|
});
|
|
82
84
|
```
|
|
83
85
|
|
|
86
|
+
The Agent API provides the `fast`, `low`, `medium`, `high`, and `xhigh`
|
|
87
|
+
presets. You can also pass an Agent API model ID directly, such as
|
|
88
|
+
`perplexity/sonar`.
|
|
89
|
+
|
|
90
|
+
Starting with version 3.1.0, language generation uses the Agent API
|
|
91
|
+
exclusively. Legacy Sonar model IDs and provider options are not mapped; see
|
|
92
|
+
[Migrating from Sonar to the Agent API](#migrating-from-sonar-to-the-agent-api)
|
|
93
|
+
before upgrading.
|
|
94
|
+
|
|
84
95
|
### Sources
|
|
85
96
|
|
|
86
97
|
Websites that have been used to generate the response are included in the `sources` property of the result:
|
|
@@ -90,27 +101,101 @@ import { perplexity } from '@ai-sdk/perplexity';
|
|
|
90
101
|
import { generateText } from 'ai';
|
|
91
102
|
|
|
92
103
|
const { text, sources } = await generateText({
|
|
93
|
-
model: perplexity('
|
|
104
|
+
model: perplexity('low'),
|
|
94
105
|
prompt: 'What are the latest developments in quantum computing?',
|
|
95
106
|
});
|
|
96
107
|
|
|
97
108
|
console.log(sources);
|
|
98
109
|
```
|
|
99
110
|
|
|
100
|
-
###
|
|
111
|
+
### Agent Tools
|
|
112
|
+
|
|
113
|
+
Pass native Agent API tools through `providerOptions.perplexity.tools`:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import {
|
|
117
|
+
perplexity,
|
|
118
|
+
type PerplexityLanguageModelOptions,
|
|
119
|
+
} from '@ai-sdk/perplexity';
|
|
120
|
+
import { generateText } from 'ai';
|
|
121
|
+
|
|
122
|
+
const { text, sources } = await generateText({
|
|
123
|
+
model: perplexity('low'),
|
|
124
|
+
prompt: 'Summarize recent US federal AI policy from official sources.',
|
|
125
|
+
providerOptions: {
|
|
126
|
+
perplexity: {
|
|
127
|
+
tools: [
|
|
128
|
+
{
|
|
129
|
+
type: 'web_search',
|
|
130
|
+
filters: {
|
|
131
|
+
search_domain_filter: [
|
|
132
|
+
'whitehouse.gov',
|
|
133
|
+
'congress.gov',
|
|
134
|
+
'federalregister.gov',
|
|
135
|
+
],
|
|
136
|
+
search_recency_filter: 'month',
|
|
137
|
+
},
|
|
138
|
+
max_results: 10,
|
|
139
|
+
search_context_size: 'medium',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
} satisfies PerplexityLanguageModelOptions,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Supported native tools are `web_search`, `fetch_url`, `people_search`,
|
|
148
|
+
`finance_search`, `sandbox`, `mcp`, and `connector`. Agent API presets include
|
|
149
|
+
preconfigured tools that remain enabled; the `tools` option can add explicit
|
|
150
|
+
tools or supply tools when using a direct model ID.
|
|
151
|
+
|
|
152
|
+
Search and fetch results are exposed as AI SDK sources. Other native tool traces,
|
|
153
|
+
including finance, sandbox, and MCP results, are available in `response.body`
|
|
154
|
+
and raw stream chunks (`includeRawChunks: true`). They are not exposed as
|
|
155
|
+
AI SDK client tool calls. Accounts with zero data retention may reject
|
|
156
|
+
file-capable tools such as `finance_search` and `sandbox`.
|
|
157
|
+
|
|
158
|
+
AI SDK function tools can be passed through the top-level `tools` option:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { perplexity } from '@ai-sdk/perplexity';
|
|
162
|
+
import { generateText, tool } from 'ai';
|
|
163
|
+
import { z } from 'zod';
|
|
164
|
+
|
|
165
|
+
const result = await generateText({
|
|
166
|
+
model: perplexity('low'),
|
|
167
|
+
prompt: 'What is the weather in San Francisco?',
|
|
168
|
+
tools: {
|
|
169
|
+
weather: tool({
|
|
170
|
+
description: 'Get the weather for a city',
|
|
171
|
+
inputSchema: z.object({ city: z.string() }),
|
|
172
|
+
execute: async ({ city }) => ({ city, temperature: 18 }),
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Provider Options and Metadata
|
|
101
179
|
|
|
102
180
|
The Perplexity provider includes additional metadata in the response through `providerMetadata`.
|
|
103
181
|
Additional configuration options are available through `providerOptions`.
|
|
104
182
|
|
|
105
183
|
```ts
|
|
184
|
+
import {
|
|
185
|
+
perplexity,
|
|
186
|
+
type PerplexityLanguageModelOptions,
|
|
187
|
+
} from '@ai-sdk/perplexity';
|
|
188
|
+
import { generateText } from 'ai';
|
|
189
|
+
|
|
106
190
|
const result = await generateText({
|
|
107
|
-
model: perplexity('
|
|
191
|
+
model: perplexity('low'),
|
|
108
192
|
prompt: 'What are the latest developments in quantum computing?',
|
|
109
193
|
providerOptions: {
|
|
110
194
|
perplexity: {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
195
|
+
max_steps: 5,
|
|
196
|
+
store: true,
|
|
197
|
+
reasoning: { effort: 'low' },
|
|
198
|
+
} satisfies PerplexityLanguageModelOptions,
|
|
114
199
|
},
|
|
115
200
|
});
|
|
116
201
|
|
|
@@ -118,87 +203,161 @@ console.log(result.providerMetadata);
|
|
|
118
203
|
// Example output:
|
|
119
204
|
// {
|
|
120
205
|
// perplexity: {
|
|
121
|
-
// usage: { citationTokens:
|
|
122
|
-
// images:
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
// ]
|
|
206
|
+
// usage: { citationTokens: null, numSearchQueries: 1 },
|
|
207
|
+
// images: null,
|
|
208
|
+
// cost: { totalCost: 0.006, currency: 'USD', ... },
|
|
209
|
+
// toolCalls: { search_web: { invocation: 1 } },
|
|
126
210
|
// },
|
|
127
211
|
// }
|
|
128
212
|
```
|
|
129
213
|
|
|
130
214
|
#### Provider Options
|
|
131
215
|
|
|
132
|
-
The following
|
|
216
|
+
The following Agent API options are available:
|
|
217
|
+
|
|
218
|
+
- **instructions** _string_
|
|
219
|
+
|
|
220
|
+
Top-level instructions for the Agent API run.
|
|
221
|
+
|
|
222
|
+
- **tools** _array_
|
|
223
|
+
|
|
224
|
+
Native Agent API tools and their configuration.
|
|
133
225
|
|
|
134
|
-
- **
|
|
226
|
+
- **models** _string[]_
|
|
135
227
|
|
|
136
|
-
|
|
228
|
+
A fallback model list for Agent API routing.
|
|
137
229
|
|
|
138
|
-
- **
|
|
230
|
+
- **max_steps** _number_
|
|
139
231
|
|
|
140
|
-
|
|
232
|
+
The maximum number of agentic steps.
|
|
233
|
+
|
|
234
|
+
- **max_tool_calls** _number_
|
|
235
|
+
|
|
236
|
+
The maximum number of native tool calls. Setting this to `0` disables all
|
|
237
|
+
preset tools.
|
|
238
|
+
|
|
239
|
+
- **previous_response_id** _string_
|
|
240
|
+
|
|
241
|
+
Continue a conversation from an earlier Agent API response.
|
|
242
|
+
|
|
243
|
+
- **store** _boolean_
|
|
244
|
+
|
|
245
|
+
Whether the response can be retrieved later. Setting `store: false` hides it
|
|
246
|
+
from retrieval; it does not disable persistence, and the response can still
|
|
247
|
+
be used as a `previous_response_id` continuation source. See Perplexity's
|
|
248
|
+
[conversation state documentation](https://docs.perplexity.ai/docs/agent-api/conversation-state)
|
|
249
|
+
for retention behavior and account-specific zero data retention restrictions.
|
|
250
|
+
|
|
251
|
+
- **language_preference** _string_
|
|
252
|
+
|
|
253
|
+
Preferred response language as an ISO 639-1 language code.
|
|
254
|
+
|
|
255
|
+
- **reasoning** _object_
|
|
256
|
+
|
|
257
|
+
Reasoning configuration. `effort` supports `'minimal'`, `'low'`, `'medium'`,
|
|
258
|
+
`'high'`, and `'xhigh'`.
|
|
259
|
+
|
|
260
|
+
- **skills** _array_
|
|
261
|
+
|
|
262
|
+
Agent API skill configuration.
|
|
141
263
|
|
|
142
264
|
<Note>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
265
|
+
See the [Perplexity Agent API
|
|
266
|
+
documentation](https://docs.perplexity.ai/docs/agent-api/quickstart) for
|
|
267
|
+
details about native request fields.
|
|
146
268
|
</Note>
|
|
147
269
|
|
|
148
270
|
#### Provider Metadata
|
|
149
271
|
|
|
150
272
|
The response metadata includes:
|
|
151
273
|
|
|
152
|
-
- `usage`:
|
|
153
|
-
|
|
274
|
+
- `usage`: `citationTokens` (always `null` for Agent API responses) and the
|
|
275
|
+
number of search queries
|
|
276
|
+
- `cost`: Token, tool, and total costs returned by Perplexity
|
|
277
|
+
- `toolCalls`: Invocation counts grouped by native tool
|
|
278
|
+
- `images`: Always `null`; the Agent API does not return Sonar image results
|
|
154
279
|
|
|
155
|
-
###
|
|
280
|
+
### Structured Output
|
|
156
281
|
|
|
157
|
-
|
|
158
|
-
|
|
282
|
+
`Output.object` and `Output.array` send an Agent API JSON schema response
|
|
283
|
+
format. JSON output without a schema is not supported.
|
|
159
284
|
|
|
160
|
-
|
|
161
|
-
const result = await generateText({
|
|
162
|
-
model: perplexity('sonar-pro'),
|
|
163
|
-
messages: [
|
|
164
|
-
{
|
|
165
|
-
role: 'user',
|
|
166
|
-
content: [
|
|
167
|
-
{
|
|
168
|
-
type: 'text',
|
|
169
|
-
text: 'What is this document about?',
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
type: 'file',
|
|
173
|
-
data: fs.readFileSync('./data/ai.pdf'),
|
|
174
|
-
mediaType: 'application/pdf',
|
|
175
|
-
filename: 'ai.pdf', // optional
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
},
|
|
179
|
-
],
|
|
180
|
-
});
|
|
181
|
-
```
|
|
285
|
+
### Input Images
|
|
182
286
|
|
|
183
|
-
|
|
287
|
+
Image URL and data inputs are converted to Agent API `input_image` parts.
|
|
288
|
+
The Agent API does not provide a Sonar-equivalent PDF input field, so PDF file
|
|
289
|
+
parts are not supported.
|
|
184
290
|
|
|
185
|
-
|
|
186
|
-
{
|
|
187
|
-
type: 'file',
|
|
188
|
-
data: new URL('https://example.com/document.pdf'),
|
|
189
|
-
mediaType: 'application/pdf',
|
|
190
|
-
filename: 'document.pdf', // optional
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
The model will have access to the contents of the PDF file and
|
|
195
|
-
respond to questions about it.
|
|
291
|
+
### Migrating from Sonar to the Agent API
|
|
196
292
|
|
|
197
293
|
<Note>
|
|
198
|
-
|
|
199
|
-
|
|
294
|
+
Version 3.1.0 is a breaking migration from Sonar Chat Completions to the
|
|
295
|
+
Agent API. It does not provide legacy model aliases, translate Sonar provider
|
|
296
|
+
options, or emit migration warnings at runtime.
|
|
297
|
+
</Note>
|
|
298
|
+
|
|
299
|
+
<Note type="warning">
|
|
300
|
+
Perplexity supports Sonar Chat Completions only until September 27, 2026.
|
|
301
|
+
Upgrade language-generation applications to the Agent API before that date;
|
|
302
|
+
staying on version 3.0.63 or earlier does not preserve service after the
|
|
303
|
+
Sonar shutdown.
|
|
200
304
|
</Note>
|
|
201
305
|
|
|
306
|
+
Replace each Sonar model ID with an Agent API preset or direct Agent API model
|
|
307
|
+
ID. These presets are suggested starting points, not equivalent aliases: a
|
|
308
|
+
preset can select different models and tools, so cost, latency, and output can
|
|
309
|
+
change.
|
|
310
|
+
|
|
311
|
+
| Sonar model | Suggested Agent API starting point |
|
|
312
|
+
| --------------------- | ---------------------------------- |
|
|
313
|
+
| `sonar` | `fast` |
|
|
314
|
+
| `sonar-pro` | `low` |
|
|
315
|
+
| `sonar-reasoning` | `medium` |
|
|
316
|
+
| `sonar-reasoning-pro` | `medium` |
|
|
317
|
+
| `sonar-deep-research` | `high` |
|
|
318
|
+
|
|
319
|
+
For example:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
// 3.0.63 and earlier (Sonar)
|
|
323
|
+
perplexity('sonar-pro');
|
|
324
|
+
|
|
325
|
+
// 3.1.0 and later (Agent API)
|
|
326
|
+
perplexity('low');
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Move Sonar search and reasoning options to their Agent API locations:
|
|
330
|
+
|
|
331
|
+
| Sonar provider option | Agent API option |
|
|
332
|
+
| ---------------------------------------- | -------------------------------------- |
|
|
333
|
+
| Domain, recency, and date filters | `tools[].filters` on `web_search` |
|
|
334
|
+
| `num_search_results` | `tools[].max_results` |
|
|
335
|
+
| `web_search_options.search_context_size` | `tools[].search_context_size` |
|
|
336
|
+
| `web_search_options.user_location` | `tools[].user_location` |
|
|
337
|
+
| `reasoning_effort` | `reasoning.effort` |
|
|
338
|
+
| `disable_search` | Omit `web_search` for direct model IDs |
|
|
339
|
+
|
|
340
|
+
Preset tools cannot be removed individually. Use a direct model ID without a
|
|
341
|
+
`web_search` tool when search must be disabled, or set `max_tool_calls: 0` to
|
|
342
|
+
disable all preset tool calls.
|
|
343
|
+
|
|
344
|
+
The Agent API has no equivalent for Sonar PDF or video inputs, image or video
|
|
345
|
+
results, `search_language_filter`, or `stream_mode`. Related questions require
|
|
346
|
+
prompting or structured output. Remove these options during migration.
|
|
347
|
+
|
|
348
|
+
Language requests now use `/v1/agent`. Custom `baseURL` proxies must route that
|
|
349
|
+
path. Raw responses and streams use the Agent API's typed output and SSE event
|
|
350
|
+
formats, and Perplexity provider metadata, usage, cost, and source identifiers
|
|
351
|
+
can differ. The embeddings API is unchanged.
|
|
352
|
+
|
|
353
|
+
For PDF inputs, extract the document text before sending it to the Agent API,
|
|
354
|
+
or choose another provider that supports PDF input. Move image/video retrieval
|
|
355
|
+
and language-filtered search to a separate service if your application requires
|
|
356
|
+
those features. Rework consumers of raw Sonar stream events for typed Agent
|
|
357
|
+
events. See Perplexity's [migration
|
|
358
|
+
guide](https://docs.perplexity.ai/docs/agent-api/migrate-from-sonar/how-to)
|
|
359
|
+
for the full API-level comparison.
|
|
360
|
+
|
|
202
361
|
## Embedding Models
|
|
203
362
|
|
|
204
363
|
You can create models that call the [Perplexity embeddings API](https://docs.perplexity.ai/docs/embeddings/quickstart)
|
|
@@ -274,13 +433,13 @@ The following optional provider options are available for embedding models:
|
|
|
274
433
|
|
|
275
434
|
## Model Capabilities
|
|
276
435
|
|
|
277
|
-
| Model
|
|
278
|
-
|
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `
|
|
282
|
-
| `
|
|
283
|
-
| `
|
|
436
|
+
| Model | Image Input | Object Generation | Tool Usage | Tool Streaming |
|
|
437
|
+
| -------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
|
438
|
+
| `fast` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
439
|
+
| `low` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
440
|
+
| `medium` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
441
|
+
| `high` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
442
|
+
| `xhigh` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
284
443
|
|
|
285
444
|
<Note>
|
|
286
445
|
Please see the [Perplexity docs](https://docs.perplexity.ai) for detailed API
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/perplexity",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "3.0.
|
|
33
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
32
|
+
"@ai-sdk/provider": "3.0.18",
|
|
33
|
+
"@ai-sdk/provider-utils": "4.0.56"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "20.17.24",
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import type { LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
1
|
+
import type { JSONObject, LanguageModelV3Usage } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export function convertPerplexityUsage(
|
|
4
4
|
usage:
|
|
5
5
|
| {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
input_tokens?: number | null;
|
|
7
|
+
output_tokens?: number | null;
|
|
8
|
+
total_tokens?: number | null;
|
|
9
|
+
input_tokens_details?: {
|
|
10
|
+
cached_tokens?: number | null;
|
|
11
|
+
cache_creation_input_tokens?: number | null;
|
|
12
|
+
cache_read_input_tokens?: number | null;
|
|
13
|
+
} | null;
|
|
14
|
+
output_tokens_details?: {
|
|
15
|
+
reasoning_tokens?: number | null;
|
|
16
|
+
} | null;
|
|
17
|
+
[key: string]: unknown;
|
|
9
18
|
}
|
|
10
19
|
| undefined
|
|
11
20
|
| null,
|
|
@@ -27,23 +36,28 @@ export function convertPerplexityUsage(
|
|
|
27
36
|
};
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
39
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
40
|
+
const outputTokens = usage.output_tokens ?? 0;
|
|
41
|
+
const cacheReadTokens =
|
|
42
|
+
usage.input_tokens_details?.cache_read_input_tokens ??
|
|
43
|
+
usage.input_tokens_details?.cached_tokens ??
|
|
44
|
+
0;
|
|
45
|
+
const cacheWriteTokens =
|
|
46
|
+
usage.input_tokens_details?.cache_creation_input_tokens ?? 0;
|
|
47
|
+
const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
|
|
33
48
|
|
|
34
49
|
return {
|
|
35
50
|
inputTokens: {
|
|
36
|
-
total:
|
|
37
|
-
noCache:
|
|
38
|
-
cacheRead:
|
|
39
|
-
cacheWrite:
|
|
51
|
+
total: inputTokens,
|
|
52
|
+
noCache: Math.max(0, inputTokens - cacheReadTokens - cacheWriteTokens),
|
|
53
|
+
cacheRead: cacheReadTokens,
|
|
54
|
+
cacheWrite: cacheWriteTokens,
|
|
40
55
|
},
|
|
41
56
|
outputTokens: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
text: completionTokens,
|
|
57
|
+
total: outputTokens,
|
|
58
|
+
text: Math.max(0, outputTokens - reasoningTokens),
|
|
45
59
|
reasoning: reasoningTokens,
|
|
46
60
|
},
|
|
47
|
-
raw: usage,
|
|
61
|
+
raw: usage as JSONObject,
|
|
48
62
|
};
|
|
49
63
|
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnsupportedFunctionalityError,
|
|
3
|
+
type LanguageModelV3Prompt,
|
|
4
|
+
type LanguageModelV3ToolResultOutput,
|
|
5
|
+
type SharedV3Warning,
|
|
6
|
+
} from '@ai-sdk/provider';
|
|
7
|
+
import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils';
|
|
8
|
+
import type {
|
|
9
|
+
PerplexityAgentInput,
|
|
10
|
+
PerplexityAgentInputContent,
|
|
11
|
+
} from './perplexity-language-model-prompt';
|
|
12
|
+
|
|
13
|
+
function serializeToolOutput(output: LanguageModelV3ToolResultOutput): string {
|
|
14
|
+
switch (output.type) {
|
|
15
|
+
case 'text':
|
|
16
|
+
case 'error-text':
|
|
17
|
+
return output.value;
|
|
18
|
+
case 'json':
|
|
19
|
+
case 'error-json':
|
|
20
|
+
return JSON.stringify(output.value);
|
|
21
|
+
case 'execution-denied':
|
|
22
|
+
return output.reason ?? 'Tool call execution denied.';
|
|
23
|
+
case 'content': {
|
|
24
|
+
if (output.value.some(part => part.type !== 'text')) {
|
|
25
|
+
throw new UnsupportedFunctionalityError({
|
|
26
|
+
functionality: 'file and custom tool result content',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return output.value
|
|
30
|
+
.map(part => (part.type === 'text' ? part.text : ''))
|
|
31
|
+
.join('');
|
|
32
|
+
}
|
|
33
|
+
default: {
|
|
34
|
+
const _exhaustiveCheck: never = output;
|
|
35
|
+
throw new Error(`Unsupported tool output: ${_exhaustiveCheck}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getTopLevelMediaType(mediaType: string): string {
|
|
41
|
+
const slashIndex = mediaType.indexOf('/');
|
|
42
|
+
return slashIndex === -1 ? mediaType : mediaType.substring(0, slashIndex);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getThoughtSignature(
|
|
46
|
+
providerOptions:
|
|
47
|
+
| Record<string, Record<string, unknown> | undefined>
|
|
48
|
+
| undefined,
|
|
49
|
+
): string | undefined {
|
|
50
|
+
const thoughtSignature = providerOptions?.perplexity?.thoughtSignature;
|
|
51
|
+
return typeof thoughtSignature === 'string' ? thoughtSignature : undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function convertToPerplexityInput(prompt: LanguageModelV3Prompt): {
|
|
55
|
+
input: PerplexityAgentInput;
|
|
56
|
+
warnings: SharedV3Warning[];
|
|
57
|
+
} {
|
|
58
|
+
const input: PerplexityAgentInput = [];
|
|
59
|
+
const warnings: SharedV3Warning[] = [];
|
|
60
|
+
|
|
61
|
+
for (const { role, content } of prompt) {
|
|
62
|
+
switch (role) {
|
|
63
|
+
case 'system': {
|
|
64
|
+
input.push({ type: 'message', role: 'system', content });
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
case 'user': {
|
|
69
|
+
const convertedContent: PerplexityAgentInputContent[] = content.map(
|
|
70
|
+
part => {
|
|
71
|
+
switch (part.type) {
|
|
72
|
+
case 'text':
|
|
73
|
+
return { type: 'input_text', text: part.text };
|
|
74
|
+
case 'file': {
|
|
75
|
+
if (getTopLevelMediaType(part.mediaType) !== 'image') {
|
|
76
|
+
throw new UnsupportedFunctionalityError({
|
|
77
|
+
functionality: `file part media type ${part.mediaType}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (part.data instanceof URL) {
|
|
82
|
+
return {
|
|
83
|
+
type: 'input_image',
|
|
84
|
+
image_url: part.data.toString(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const mediaType =
|
|
89
|
+
part.mediaType === 'image/*' ? 'image/jpeg' : part.mediaType;
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
type: 'input_image',
|
|
93
|
+
image_url: `data:${mediaType};base64,${
|
|
94
|
+
typeof part.data === 'string'
|
|
95
|
+
? part.data
|
|
96
|
+
: convertUint8ArrayToBase64(part.data)
|
|
97
|
+
}`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const isTextOnly = convertedContent.every(
|
|
105
|
+
part => part.type === 'input_text',
|
|
106
|
+
);
|
|
107
|
+
input.push({
|
|
108
|
+
type: 'message',
|
|
109
|
+
role: 'user',
|
|
110
|
+
content: isTextOnly
|
|
111
|
+
? convertedContent
|
|
112
|
+
.map(part => (part.type === 'input_text' ? part.text : ''))
|
|
113
|
+
.join('')
|
|
114
|
+
: convertedContent,
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
case 'assistant': {
|
|
120
|
+
const text = content
|
|
121
|
+
.filter(part => part.type === 'text')
|
|
122
|
+
.map(part => part.text)
|
|
123
|
+
.join('');
|
|
124
|
+
|
|
125
|
+
if (text.length > 0) {
|
|
126
|
+
input.push({ type: 'message', role: 'assistant', content: text });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (const part of content) {
|
|
130
|
+
switch (part.type) {
|
|
131
|
+
case 'text':
|
|
132
|
+
break;
|
|
133
|
+
case 'tool-call':
|
|
134
|
+
input.push({
|
|
135
|
+
type: 'function_call',
|
|
136
|
+
call_id: part.toolCallId,
|
|
137
|
+
name: part.toolName,
|
|
138
|
+
arguments: JSON.stringify(part.input ?? {}),
|
|
139
|
+
thought_signature: getThoughtSignature(part.providerOptions),
|
|
140
|
+
});
|
|
141
|
+
break;
|
|
142
|
+
case 'tool-result':
|
|
143
|
+
input.push({
|
|
144
|
+
type: 'function_call_output',
|
|
145
|
+
call_id: part.toolCallId,
|
|
146
|
+
name: part.toolName,
|
|
147
|
+
output: serializeToolOutput(part.output),
|
|
148
|
+
thought_signature: getThoughtSignature(part.providerOptions),
|
|
149
|
+
});
|
|
150
|
+
break;
|
|
151
|
+
case 'reasoning':
|
|
152
|
+
warnings.push({
|
|
153
|
+
type: 'unsupported',
|
|
154
|
+
feature: 'reasoning content in prompt',
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
case 'file':
|
|
158
|
+
throw new UnsupportedFunctionalityError({
|
|
159
|
+
functionality: `assistant ${part.type} parts`,
|
|
160
|
+
});
|
|
161
|
+
default: {
|
|
162
|
+
const _exhaustiveCheck: never = part;
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Unsupported assistant part: ${_exhaustiveCheck}`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case 'tool': {
|
|
173
|
+
for (const part of content) {
|
|
174
|
+
if (part.type === 'tool-approval-response') {
|
|
175
|
+
throw new UnsupportedFunctionalityError({
|
|
176
|
+
functionality: 'tool approval responses',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
input.push({
|
|
181
|
+
type: 'function_call_output',
|
|
182
|
+
call_id: part.toolCallId,
|
|
183
|
+
name: part.toolName,
|
|
184
|
+
output: serializeToolOutput(part.output),
|
|
185
|
+
thought_signature: getThoughtSignature(part.providerOptions),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
default: {
|
|
192
|
+
const _exhaustiveCheck: never = role;
|
|
193
|
+
throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return { input, warnings };
|
|
199
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,11 @@ export type {
|
|
|
3
3
|
PerplexityProvider,
|
|
4
4
|
PerplexityProviderSettings,
|
|
5
5
|
} from './perplexity-provider';
|
|
6
|
+
export type { PerplexityLanguageModelOptions } from './perplexity-language-model-options';
|
|
7
|
+
export type {
|
|
8
|
+
PerplexityAgentPreset,
|
|
9
|
+
PerplexityLanguageModelId,
|
|
10
|
+
} from './perplexity-options';
|
|
6
11
|
export type {
|
|
7
12
|
PerplexityEmbeddingModelId,
|
|
8
13
|
PerplexityEmbeddingModelOptions,
|