Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { LanguageModelChat, type ChatRequest } from 'vscode';
7
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
8
import { IConfigurationService } from '../../../platform/configuration/common/configurationService';
9
import { ChatEndpointFamily, EmbeddingsEndpointFamily, IChatModelInformation, ICompletionModelInformation, IEmbeddingModelInformation, IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';
10
import { AutoChatEndpoint } from '../../../platform/endpoint/node/autoChatEndpoint';
11
import { IAutomodeService } from '../../../platform/endpoint/node/automodeService';
12
import { CopilotChatEndpoint } from '../../../platform/endpoint/node/copilotChatEndpoint';
13
import { EmbeddingEndpoint } from '../../../platform/endpoint/node/embeddingsEndpoint';
14
import { IModelMetadataFetcher, ModelMetadataFetcher } from '../../../platform/endpoint/node/modelMetadataFetcher';
15
import { ExtensionContributedChatEndpoint } from '../../../platform/endpoint/vscode-node/extChatEndpoint';
16
import { ILogService } from '../../../platform/log/common/logService';
17
import { IChatEndpoint, IEmbeddingsEndpoint } from '../../../platform/networking/common/networking';
18
import { Emitter, Event } from '../../../util/vs/base/common/event';
19
import { Disposable } from '../../../util/vs/base/common/lifecycle';
20
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
21
22
23
export class ProductionEndpointProvider extends Disposable implements IEndpointProvider {
24
25
declare readonly _serviceBrand: undefined;
26
27
private readonly _onDidModelsRefresh = this._register(new Emitter<void>());
28
readonly onDidModelsRefresh: Event<void> = this._onDidModelsRefresh.event;
29
30
private _chatEndpoints: Map<string, IChatEndpoint> = new Map();
31
private _embeddingEndpoints: Map<string, IEmbeddingsEndpoint> = new Map();
32
private readonly _modelFetcher: IModelMetadataFetcher;
33
34
constructor(
35
@IAutomodeService private readonly _autoModeService: IAutomodeService,
36
@ILogService protected readonly _logService: ILogService,
37
@IConfigurationService protected readonly _configService: IConfigurationService,
38
@IInstantiationService protected readonly _instantiationService: IInstantiationService,
39
@IAuthenticationService protected readonly _authService: IAuthenticationService,
40
) {
41
super();
42
43
this._modelFetcher = this._instantiationService.createInstance(ModelMetadataFetcher,
44
false,
45
);
46
47
// When new models come in from CAPI we want to clear our local caches and let the endpoints be recreated since there may be new info
48
this._register(this._modelFetcher.onDidModelsRefresh(() => {
49
this._chatEndpoints.clear();
50
this._embeddingEndpoints.clear();
51
this._onDidModelsRefresh.fire();
52
}));
53
}
54
55
private getOrCreateChatEndpointInstance(modelMetadata: IChatModelInformation): IChatEndpoint {
56
const modelId = modelMetadata.id;
57
let chatEndpoint = this._chatEndpoints.get(modelId);
58
if (!chatEndpoint) {
59
chatEndpoint = this._instantiationService.createInstance(CopilotChatEndpoint, modelMetadata);
60
this._chatEndpoints.set(modelId, chatEndpoint);
61
}
62
return chatEndpoint;
63
}
64
65
async getChatEndpoint(requestOrFamilyOrModel: LanguageModelChat | ChatRequest | ChatEndpointFamily): Promise<IChatEndpoint> {
66
this._logService.trace(`Resolving chat model`);
67
68
if (typeof requestOrFamilyOrModel === 'string') {
69
const modelMetadata = await this._modelFetcher.getChatModelFromFamily(requestOrFamilyOrModel);
70
return this.getOrCreateChatEndpointInstance(modelMetadata!);
71
}
72
73
const model = 'model' in requestOrFamilyOrModel ? requestOrFamilyOrModel.model : requestOrFamilyOrModel;
74
75
if (!model) {
76
return this.getChatEndpoint('copilot-base');
77
}
78
79
if (model.vendor !== 'copilot') {
80
return this._instantiationService.createInstance(ExtensionContributedChatEndpoint, model);
81
}
82
83
if (model.id === AutoChatEndpoint.pseudoModelId) {
84
try {
85
const allEndpoints = await this.getAllChatEndpoints();
86
return this._autoModeService.resolveAutoModeEndpoint(requestOrFamilyOrModel as ChatRequest, allEndpoints);
87
} catch {
88
return this.getChatEndpoint('copilot-base');
89
}
90
}
91
92
const modelMetadata = await this._modelFetcher.getChatModelFromApiModel(model);
93
// If we fail to resolve a model since this is panel we give copilot base. This really should never happen as the picker is powered by the same service.
94
return modelMetadata ? this.getOrCreateChatEndpointInstance(modelMetadata) : this.getChatEndpoint('copilot-base');
95
}
96
97
async getEmbeddingsEndpoint(family?: EmbeddingsEndpointFamily): Promise<IEmbeddingsEndpoint> {
98
this._logService.trace(`Resolving embedding model`);
99
const modelMetadata = await this._modelFetcher.getEmbeddingsModel('text-embedding-3-small');
100
const model = await this.getOrCreateEmbeddingEndpointInstance(modelMetadata);
101
this._logService.trace(`Resolved embedding model`);
102
return model;
103
}
104
105
private async getOrCreateEmbeddingEndpointInstance(modelMetadata: IEmbeddingModelInformation): Promise<IEmbeddingsEndpoint> {
106
const modelId = 'text-embedding-3-small';
107
let embeddingEndpoint = this._embeddingEndpoints.get(modelId);
108
if (!embeddingEndpoint) {
109
embeddingEndpoint = this._instantiationService.createInstance(EmbeddingEndpoint, modelMetadata);
110
this._embeddingEndpoints.set(modelId, embeddingEndpoint);
111
}
112
return embeddingEndpoint;
113
}
114
115
async getAllCompletionModels(forceRefresh?: boolean): Promise<ICompletionModelInformation[]> {
116
return this._modelFetcher.getAllCompletionModels(forceRefresh ?? false);
117
}
118
119
async getAllChatEndpoints(): Promise<IChatEndpoint[]> {
120
const models: IChatModelInformation[] = await this._modelFetcher.getAllChatModels();
121
return models.map(model => this.getOrCreateChatEndpointInstance(model));
122
}
123
}
124
125