Skip to content

Commit e700ece

Browse files
authored
Joh/languageModelInformation (microsoft#210490)
* add `LanguageModelInformation` interface * tweaks to the language models metadata API * update docs * 💄 * add removal comments
1 parent 26cf440 commit e700ece

File tree

7 files changed

+117
-54
lines changed

7 files changed

+117
-54
lines changed

src/vs/workbench/api/browser/mainThreadLanguageModels.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export class MainThreadLanguageModels implements MainThreadLanguageModelsShape {
123123
}
124124

125125

126-
$countTokens(provider: string, value: string, token: CancellationToken): Promise<number> {
126+
$countTokens(provider: string, value: string | IChatMessage, token: CancellationToken): Promise<number> {
127127
return this._chatProviderService.computeTokenLength(provider, value, token);
128128
}
129129

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { CancellationTokenSource } from 'vs/base/common/cancellation';
6+
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
77
import * as errors from 'vs/base/common/errors';
88
import { Emitter, Event } from 'vs/base/common/event';
99
import { combinedDisposable } from 'vs/base/common/lifecycle';
@@ -1448,6 +1448,15 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
14481448
sendChatRequest(languageModel: string, messages: vscode.LanguageModelChatMessage[], options: vscode.LanguageModelChatRequestOptions, token: vscode.CancellationToken) {
14491449
checkProposedApiEnabled(extension, 'languageModels');
14501450
return extHostLanguageModels.sendChatRequest(extension, languageModel, messages, options, token);
1451+
},
1452+
computeTokenLength(languageModel: string, text: string | vscode.LanguageModelChatMessage, token?: vscode.CancellationToken) {
1453+
checkProposedApiEnabled(extension, 'languageModels');
1454+
token ??= CancellationToken.None;
1455+
return extHostLanguageModels.computeTokenLength(languageModel, text, token);
1456+
},
1457+
getLanguageModelInformation(languageModel: string) {
1458+
checkProposedApiEnabled(extension, 'languageModels');
1459+
return extHostLanguageModels.getLanguageModelInfo(languageModel);
14511460
}
14521461
};
14531462

@@ -1703,9 +1712,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
17031712
LanguageModelChatSystemMessage: extHostTypes.LanguageModelChatSystemMessage,
17041713
LanguageModelChatUserMessage: extHostTypes.LanguageModelChatUserMessage,
17051714
LanguageModelChatAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage,
1706-
LanguageModelSystemMessage: extHostTypes.LanguageModelChatSystemMessage,
1707-
LanguageModelUserMessage: extHostTypes.LanguageModelChatUserMessage,
1708-
LanguageModelAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage,
1715+
LanguageModelSystemMessage: extHostTypes.LanguageModelChatSystemMessage, // TODO@jrieken REMOVE
1716+
LanguageModelUserMessage: extHostTypes.LanguageModelChatUserMessage, // TODO@jrieken REMOVE
1717+
LanguageModelAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage, // TODO@jrieken REMOVE
17091718
LanguageModelError: extHostTypes.LanguageModelError,
17101719
NewSymbolName: extHostTypes.NewSymbolName,
17111720
NewSymbolNameTag: extHostTypes.NewSymbolNameTag,

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,15 +1200,15 @@ export interface MainThreadLanguageModelsShape extends IDisposable {
12001200
$prepareChatAccess(extension: ExtensionIdentifier, providerId: string, justification?: string): Promise<ILanguageModelChatMetadata | undefined>;
12011201
$fetchResponse(extension: ExtensionIdentifier, provider: string, requestId: number, messages: IChatMessage[], options: {}, token: CancellationToken): Promise<any>;
12021202

1203-
$countTokens(provider: string, value: string, token: CancellationToken): Promise<number>;
1203+
$countTokens(provider: string, value: string | IChatMessage, token: CancellationToken): Promise<number>;
12041204
}
12051205

12061206
export interface ExtHostLanguageModelsShape {
12071207
$updateLanguageModels(data: { added?: ILanguageModelChatMetadata[]; removed?: string[] }): void;
12081208
$updateModelAccesslist(data: { from: ExtensionIdentifier; to: ExtensionIdentifier; enabled: boolean }[]): void;
12091209
$provideLanguageModelResponse(handle: number, requestId: number, from: ExtensionIdentifier, messages: IChatMessage[], options: { [name: string]: any }, token: CancellationToken): Promise<any>;
12101210
$handleResponseFragment(requestId: number, chunk: IChatResponseFragment): Promise<void>;
1211-
$provideTokenLength(handle: number, value: string, token: CancellationToken): Promise<number>;
1211+
$provideTokenLength(handle: number, value: string | IChatMessage, token: CancellationToken): Promise<number>;
12121212
}
12131213

12141214
export interface IExtensionChatAgentMetadata extends Dto<IChatAgentMetadata> {

src/vs/workbench/api/common/extHostLanguageModels.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
155155
this._proxy.$registerLanguageModelProvider(handle, identifier, {
156156
extension: extension.identifier,
157157
identifier: identifier,
158-
model: metadata.name ?? '',
158+
name: metadata.name ?? '',
159+
version: metadata.version,
160+
tokens: metadata.tokens,
159161
auth
160162
});
161163

@@ -201,7 +203,7 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
201203
if (data.added) {
202204
for (const metadata of data.added) {
203205
this._allLanguageModelData.set(metadata.identifier, metadata);
204-
added.push(metadata.model);
206+
added.push(metadata.identifier);
205207
}
206208
}
207209
if (data.removed) {
@@ -359,7 +361,36 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
359361
this._logService.error(err);
360362
}
361363
}
364+
}
365+
366+
async computeTokenLength(languageModelId: string, value: string | vscode.LanguageModelChatMessage, token: vscode.CancellationToken): Promise<number> {
367+
368+
const data = this._allLanguageModelData.get(languageModelId);
369+
if (!data) {
370+
throw LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
371+
}
372+
373+
const local = Iterable.find(this._languageModels.values(), candidate => candidate.languageModelId === languageModelId);
374+
if (local) {
375+
// stay inside the EH
376+
return local.provider.provideTokenCount(value, token);
377+
}
378+
379+
return this._proxy.$countTokens(data.identifier, (typeof value === 'string' ? value : typeConvert.LanguageModelMessage.from(value)), token);
380+
}
381+
382+
getLanguageModelInfo(languageModelId: string): vscode.LanguageModelInformation | undefined {
383+
const data = this._allLanguageModelData.get(languageModelId);
384+
if (!data) {
385+
return undefined;
386+
}
362387

388+
return {
389+
id: data.identifier,
390+
name: data.name,
391+
version: data.version,
392+
tokens: data.tokens,
393+
};
363394
}
364395

365396
private readonly _languageAccessInformationExtensions = new Set<Readonly<IExtensionDescription>>();
@@ -391,23 +422,6 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
391422
return undefined;
392423
}
393424
return list.has(data.extension);
394-
},
395-
async computeTokenLength(languageModelId: string, value: string, token?: vscode.CancellationToken): Promise<number> {
396-
397-
token ??= CancellationToken.None;
398-
399-
const data = that._allLanguageModelData.get(languageModelId);
400-
if (!data) {
401-
throw LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
402-
}
403-
404-
const local = Iterable.find(that._languageModels.values(), candidate => candidate.languageModelId === languageModelId);
405-
if (local) {
406-
// stay inside the EH
407-
return local.provider.provideTokenCount(value, token);
408-
}
409-
410-
return that._proxy.$countTokens(data.identifier, value, token);
411425
}
412426
};
413427
}

src/vs/workbench/contrib/chat/common/languageModels.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ export interface IChatResponseFragment {
2929
export interface ILanguageModelChatMetadata {
3030
readonly extension: ExtensionIdentifier;
3131
readonly identifier: string;
32-
readonly model: string;
33-
readonly description?: string;
32+
readonly name: string;
33+
readonly version: string;
34+
readonly tokens: number;
35+
3436
readonly auth?: {
3537
readonly providerLabel: string;
3638
readonly accountLabel?: string;
@@ -40,7 +42,7 @@ export interface ILanguageModelChatMetadata {
4042
export interface ILanguageModelChat {
4143
metadata: ILanguageModelChatMetadata;
4244
provideChatResponse(messages: IChatMessage[], from: ExtensionIdentifier, options: { [name: string]: any }, progress: IProgress<IChatResponseFragment>, token: CancellationToken): Promise<any>;
43-
provideTokenCount(str: string, token: CancellationToken): Promise<number>;
45+
provideTokenCount(message: string | IChatMessage, token: CancellationToken): Promise<number>;
4446
}
4547

4648
export const ILanguageModelsService = createDecorator<ILanguageModelsService>('ILanguageModelsService');
@@ -59,7 +61,7 @@ export interface ILanguageModelsService {
5961

6062
makeLanguageModelChatRequest(identifier: string, from: ExtensionIdentifier, messages: IChatMessage[], options: { [name: string]: any }, progress: IProgress<IChatResponseFragment>, token: CancellationToken): Promise<any>;
6163

62-
computeTokenLength(identifier: string, message: string, token: CancellationToken): Promise<number>;
64+
computeTokenLength(identifier: string, message: string | IChatMessage, token: CancellationToken): Promise<number>;
6365
}
6466

6567
export class LanguageModelsService implements ILanguageModelsService {
@@ -104,7 +106,7 @@ export class LanguageModelsService implements ILanguageModelsService {
104106
return provider.provideChatResponse(messages, from, options, progress, token);
105107
}
106108

107-
computeTokenLength(identifier: string, message: string, token: CancellationToken): Promise<number> {
109+
computeTokenLength(identifier: string, message: string | IChatMessage, token: CancellationToken): Promise<number> {
108110
const provider = this._providers.get(identifier);
109111
if (!provider) {
110112
throw new Error(`Chat response provider with identifier ${identifier} is not registered.`);

src/vscode-dts/vscode.proposed.chatProvider.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ declare module 'vscode' {
1818
export interface ChatResponseProvider {
1919
provideLanguageModelResponse2(messages: LanguageModelChatMessage[], options: { [name: string]: any }, extensionId: string, progress: Progress<ChatResponseFragment>, token: CancellationToken): Thenable<any>;
2020

21-
provideTokenCount(text: string, token: CancellationToken): Thenable<number>;
21+
provideTokenCount(text: string | LanguageModelChatMessage, token: CancellationToken): Thenable<number>;
2222
}
2323

2424
export interface ChatResponseProviderMetadata {
@@ -29,6 +29,10 @@ declare module 'vscode' {
2929
// TODO@API rename to model
3030
name: string;
3131

32+
version: string;
33+
34+
tokens: number;
35+
3236
/**
3337
* When present, this gates the use of `requestLanguageModelAccess` behind an authorization flow where
3438
* the user must approve of another extension accessing the models contributed by this extension.

src/vscode-dts/vscode.proposed.languageModels.d.ts

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,38 @@ declare module 'vscode' {
9898
*/
9999
export type LanguageModelChatMessage = LanguageModelChatSystemMessage | LanguageModelChatUserMessage | LanguageModelChatAssistantMessage;
100100

101+
/**
102+
* Represents information about a registered language model.
103+
*/
104+
export interface LanguageModelInformation {
105+
/**
106+
* The identifier of the language model.
107+
*/
108+
readonly id: string;
109+
110+
/**
111+
* The human-readable name of the language model.
112+
*/
113+
readonly name: string;
114+
115+
/**
116+
* The version of the language model.
117+
*/
118+
readonly version: string;
119+
120+
/**
121+
* The number of available tokens that can be used when sending requests
122+
* to the language model.
123+
*
124+
* @see {@link lm.sendChatRequest}
125+
*/
126+
readonly tokens: number;
127+
}
128+
101129
/**
102130
* An event describing the change in the set of available language models.
103131
*/
132+
// TODO@API use LanguageModelInformation instead of string?
104133
export interface LanguageModelChangeEvent {
105134
/**
106135
* Added language models.
@@ -173,6 +202,24 @@ declare module 'vscode' {
173202
*/
174203
export namespace lm {
175204

205+
/**
206+
* The identifiers of all language models that are currently available.
207+
*/
208+
export const languageModels: readonly string[];
209+
210+
/**
211+
* An event that is fired when the set of available language models changes.
212+
*/
213+
export const onDidChangeLanguageModels: Event<LanguageModelChangeEvent>;
214+
215+
/**
216+
* Retrieve information about a language model.
217+
*
218+
* @param languageModel A language model identifier.
219+
* @returns A {@link LanguageModelInformation} instance or `undefined` if the language model does not exist.
220+
*/
221+
export function getLanguageModelInformation(languageModel: string): LanguageModelInformation | undefined;
222+
176223
/**
177224
* Make a chat request using a language model.
178225
*
@@ -198,14 +245,16 @@ declare module 'vscode' {
198245
export function sendChatRequest(languageModel: string, messages: LanguageModelChatMessage[], options: LanguageModelChatRequestOptions, token: CancellationToken): Thenable<LanguageModelChatResponse>;
199246

200247
/**
201-
* The identifiers of all language models that are currently available.
202-
*/
203-
export const languageModels: readonly string[];
204-
205-
/**
206-
* An event that is fired when the set of available language models changes.
248+
* Uses the language model specific tokenzier and computes the length in token of a given message.
249+
*
250+
* *Note* that this function will throw when the language model does not exist.
251+
*
252+
* @param languageModel A language model identifier.
253+
* @param text A string or a message instance.
254+
* @param token Optional cancellation token.
255+
* @returns A thenable that resolves to the length of the message in tokens.
207256
*/
208-
export const onDidChangeLanguageModels: Event<LanguageModelChangeEvent>;
257+
export function computeTokenLength(languageModel: string, text: string | LanguageModelChatMessage, token?: CancellationToken): Thenable<number>;
209258
}
210259

211260
/**
@@ -228,21 +277,6 @@ declare module 'vscode' {
228277
* model does not exist or consent hasn't been asked for.
229278
*/
230279
canSendRequest(languageModelId: string): boolean | undefined;
231-
232-
// TODO@API SYNC or ASYNC?
233-
// TODO@API future
234-
// retrieveQuota(languageModelId: string): { remaining: number; resets: Date };
235-
236-
// TODO@API SHOULD THIS BE in vscode.lm?
237-
// TODO@API should this check for access/permissions?
238-
/**
239-
*
240-
* Compute the token length for the given text
241-
* @param languageModelId
242-
* @param text
243-
* @param token
244-
*/
245-
computeTokenLength(languageModelId: string, text: string, token?: CancellationToken): Thenable<number>;
246280
}
247281

248282
export interface ExtensionContext {

0 commit comments

Comments
 (0)