-
Notifications
You must be signed in to change notification settings - Fork 2k
Add Perplexity as a BYOK provider #5094
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,116 @@ | ||||||||||||||||||||||
| /*--------------------------------------------------------------------------------------------- | ||||||||||||||||||||||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||||||||||||||||||||||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||||||||||||||||||||||
| *--------------------------------------------------------------------------------------------*/ | ||||||||||||||||||||||
| import { IConfigurationService } from '../../../platform/configuration/common/configurationService'; | ||||||||||||||||||||||
| import { ILogService } from '../../../platform/log/common/logService'; | ||||||||||||||||||||||
| import { IFetcherService } from '../../../platform/networking/common/fetcherService'; | ||||||||||||||||||||||
| import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService'; | ||||||||||||||||||||||
| import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation'; | ||||||||||||||||||||||
| import { packageJson } from '../../../platform/env/common/packagejson'; | ||||||||||||||||||||||
| import { BYOKKnownModels, BYOKModelCapabilities } from '../common/byokProvider'; | ||||||||||||||||||||||
| import { AbstractOpenAICompatibleLMProvider } from './abstractLanguageModelChatProvider'; | ||||||||||||||||||||||
| import { IBYOKStorageService } from './byokStorageService'; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // https://docs.perplexity.ai/models/model-cards | ||||||||||||||||||||||
| // Perplexity exposes an OpenAI-compatible chat completions API at https://api.perplexity.ai | ||||||||||||||||||||||
| // but does not provide a stable `/models` discovery endpoint. We ship a curated list. | ||||||||||||||||||||||
| const PERPLEXITY_INTEGRATION_HEADER = 'X-Pplx-Integration'; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const PERPLEXITY_KNOWN_MODELS: BYOKKnownModels = { | ||||||||||||||||||||||
| 'sonar-pro': { | ||||||||||||||||||||||
| name: 'Sonar Pro', | ||||||||||||||||||||||
| toolCalling: true, | ||||||||||||||||||||||
| vision: false, | ||||||||||||||||||||||
| maxInputTokens: 200000, | ||||||||||||||||||||||
| maxOutputTokens: 8000, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| 'sonar': { | ||||||||||||||||||||||
| name: 'Sonar', | ||||||||||||||||||||||
| toolCalling: true, | ||||||||||||||||||||||
| vision: false, | ||||||||||||||||||||||
| maxInputTokens: 128000, | ||||||||||||||||||||||
| maxOutputTokens: 8000, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| 'sonar-reasoning-pro': { | ||||||||||||||||||||||
| name: 'Sonar Reasoning Pro', | ||||||||||||||||||||||
| toolCalling: true, | ||||||||||||||||||||||
| vision: false, | ||||||||||||||||||||||
| maxInputTokens: 128000, | ||||||||||||||||||||||
| maxOutputTokens: 8000, | ||||||||||||||||||||||
| thinking: true, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| 'sonar-reasoning': { | ||||||||||||||||||||||
| name: 'Sonar Reasoning', | ||||||||||||||||||||||
| toolCalling: true, | ||||||||||||||||||||||
| vision: false, | ||||||||||||||||||||||
| maxInputTokens: 128000, | ||||||||||||||||||||||
| maxOutputTokens: 8000, | ||||||||||||||||||||||
| thinking: true, | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export class PerplexityLMProvider extends AbstractOpenAICompatibleLMProvider { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| public static readonly providerName = 'Perplexity'; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| constructor( | ||||||||||||||||||||||
| knownModels: BYOKKnownModels | undefined, | ||||||||||||||||||||||
| byokStorageService: IBYOKStorageService, | ||||||||||||||||||||||
| @IFetcherService fetcherService: IFetcherService, | ||||||||||||||||||||||
| @ILogService logService: ILogService, | ||||||||||||||||||||||
| @IInstantiationService instantiationService: IInstantiationService, | ||||||||||||||||||||||
| @IConfigurationService configurationService: IConfigurationService, | ||||||||||||||||||||||
| @IExperimentationService expService: IExperimentationService | ||||||||||||||||||||||
| ) { | ||||||||||||||||||||||
| super( | ||||||||||||||||||||||
| PerplexityLMProvider.providerName.toLowerCase(), | ||||||||||||||||||||||
| PerplexityLMProvider.providerName, | ||||||||||||||||||||||
| PerplexityLMProvider.mergeKnownModels(knownModels), | ||||||||||||||||||||||
| byokStorageService, | ||||||||||||||||||||||
| fetcherService, | ||||||||||||||||||||||
| logService, | ||||||||||||||||||||||
| instantiationService, | ||||||||||||||||||||||
| configurationService, | ||||||||||||||||||||||
| expService | ||||||||||||||||||||||
| ); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private static mergeKnownModels(remote: BYOKKnownModels | undefined): BYOKKnownModels { | ||||||||||||||||||||||
| const integrationHeader = { | ||||||||||||||||||||||
| [PERPLEXITY_INTEGRATION_HEADER]: `vscode-copilot/${packageJson.version}`, | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
| const merged: BYOKKnownModels = {}; | ||||||||||||||||||||||
| for (const [id, caps] of Object.entries(PERPLEXITY_KNOWN_MODELS)) { | ||||||||||||||||||||||
| merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } }; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if (remote) { | ||||||||||||||||||||||
| for (const [id, caps] of Object.entries(remote)) { | ||||||||||||||||||||||
| merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } }; | ||||||||||||||||||||||
|
||||||||||||||||||||||
| merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } }; | |
| } | |
| if (remote) { | |
| for (const [id, caps] of Object.entries(remote)) { | |
| merged[id] = { ...caps, requestHeaders: { ...integrationHeader, ...(caps.requestHeaders ?? {}) } }; | |
| merged[id] = { ...caps, requestHeaders: { ...(caps.requestHeaders ?? {}), ...integrationHeader } }; | |
| } | |
| if (remote) { | |
| for (const [id, caps] of Object.entries(remote)) { | |
| merged[id] = { ...caps, requestHeaders: { ...(caps.requestHeaders ?? {}), ...integrationHeader } }; |
Copilot
AI
Apr 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getModelsBaseUrl() returns a base URL, which causes AbstractOpenAICompatibleLMProvider to always call ${baseUrl}/models for discovery. That contradicts the comment/PR description that Perplexity doesn't have a stable /models endpoint, and it also means the curated PERPLEXITY_KNOWN_MODELS list will never be shown unless the discovery call succeeds and returns those IDs. Consider overriding getAllModels (like CustomOAI does) to return the curated/merged known-model list with url set to the Perplexity base URL, optionally attempting discovery as a best-effort fallback rather than a hard dependency.
| return 'https://api.perplexity.ai'; | |
| // Perplexity does not provide a stable /models discovery endpoint for this provider. | |
| // Rely on the curated known-model list instead of enabling generic discovery. | |
| return undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A new BYOK provider is introduced but there are no accompanying unit tests under
src/extension/byok/vscode-node/test/(other providers like Ollama/Gemini/Azure have coverage). Adding a Perplexity provider spec would help lock in: the curated model list shown in the picker and thatX-Pplx-Integrationis present in each model'srequestHeaders.