mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-15 16:34:50 +01:00
* return LanguageModelChatMessageRole and the simple chat message LanguageModelChatMessage2 because all types became same, same
* deprecate the other types and prepare deletion * move System-role into its own proposal because of API and RAI concerns * more API notes
This commit is contained in:
@@ -1438,7 +1438,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension, 'languageModels');
|
||||
return extHostLanguageModels.onDidChangeProviders(listener, thisArgs, disposables);
|
||||
},
|
||||
sendChatRequest(languageModel: string, messages: vscode.LanguageModelChatMessage[], options: vscode.LanguageModelChatRequestOptions, token: vscode.CancellationToken) {
|
||||
sendChatRequest(languageModel: string, messages: (vscode.LanguageModelChatMessage | vscode.LanguageModelChatMessage2)[], options: vscode.LanguageModelChatRequestOptions, token: vscode.CancellationToken) {
|
||||
checkProposedApiEnabled(extension, 'languageModels');
|
||||
return extHostLanguageModels.sendChatRequest(extension, languageModel, messages, options, token);
|
||||
},
|
||||
@@ -1707,12 +1707,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
ChatRequestTurn: extHostTypes.ChatRequestTurn,
|
||||
ChatResponseTurn: extHostTypes.ChatResponseTurn,
|
||||
ChatLocation: extHostTypes.ChatLocation,
|
||||
LanguageModelChatSystemMessage: extHostTypes.LanguageModelChatSystemMessage,
|
||||
LanguageModelChatUserMessage: extHostTypes.LanguageModelChatUserMessage,
|
||||
LanguageModelChatAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage,
|
||||
LanguageModelSystemMessage: extHostTypes.LanguageModelChatSystemMessage, // TODO@jrieken REMOVE
|
||||
LanguageModelUserMessage: extHostTypes.LanguageModelChatUserMessage, // TODO@jrieken REMOVE
|
||||
LanguageModelAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage, // TODO@jrieken REMOVE
|
||||
LanguageModelChatMessageRole: extHostTypes.LanguageModelChatMessageRole,
|
||||
LanguageModelChatMessage2: extHostTypes.LanguageModelChatMessage2,
|
||||
LanguageModelChatSystemMessage: extHostTypes.LanguageModelChatSystemMessage,// TODO@jrieken REMOVE
|
||||
LanguageModelChatUserMessage: extHostTypes.LanguageModelChatUserMessage,// TODO@jrieken REMOVE
|
||||
LanguageModelChatAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage,// TODO@jrieken REMOVE
|
||||
LanguageModelError: extHostTypes.LanguageModelError,
|
||||
NewSymbolName: extHostTypes.NewSymbolName,
|
||||
NewSymbolNameTag: extHostTypes.NewSymbolNameTag,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ExtHostLanguageModelsShape, MainContext, MainThreadLanguageModelsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { LanguageModelError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import type * as vscode from 'vscode';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
import { IChatMessage, IChatResponseFragment, ILanguageModelChatMetadata } from 'vs/workbench/contrib/chat/common/languageModels';
|
||||
@@ -22,6 +22,7 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
export interface IExtHostLanguageModels extends ExtHostLanguageModels { }
|
||||
|
||||
@@ -185,7 +186,11 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
this._proxy.$handleProgressChunk(requestId, { index: fragment.index, part: fragment.part });
|
||||
});
|
||||
|
||||
return data.provider.provideLanguageModelResponse2(messages.map(typeConvert.LanguageModelMessage.to), options, ExtensionIdentifier.toKey(from), progress, token);
|
||||
if (data.provider.provideLanguageModelResponse) {
|
||||
return data.provider.provideLanguageModelResponse(messages.map(typeConvert.LanguageModelChatMessage.to), options, ExtensionIdentifier.toKey(from), progress, token);
|
||||
} else {
|
||||
return data.provider.provideLanguageModelResponse2(messages.map(typeConvert.LanguageModelMessage.to), options, ExtensionIdentifier.toKey(from), progress, token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,25 +264,27 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
}
|
||||
}
|
||||
|
||||
async sendChatRequest(extension: IExtensionDescription, languageModelId: string, messages: vscode.LanguageModelChatMessage[], options: vscode.LanguageModelChatRequestOptions, token: CancellationToken) {
|
||||
async sendChatRequest(extension: IExtensionDescription, languageModelId: string, messages: (vscode.LanguageModelChatMessage | vscode.LanguageModelChatMessage2)[], options: vscode.LanguageModelChatRequestOptions, token: CancellationToken) {
|
||||
|
||||
const internalMessages: IChatMessage[] = this._convertMessages(extension, messages);
|
||||
|
||||
const from = extension.identifier;
|
||||
const metadata = await this._proxy.$prepareChatAccess(from, languageModelId, options.justification);
|
||||
|
||||
if (!metadata || !this._allLanguageModelData.has(languageModelId)) {
|
||||
throw LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
|
||||
throw extHostTypes.LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
|
||||
}
|
||||
|
||||
if (this._isUsingAuth(from, metadata)) {
|
||||
const success = await this._getAuthAccess(extension, { identifier: metadata.extension, displayName: metadata.auth.providerLabel }, options.justification, options.silent);
|
||||
|
||||
if (!success || !this._modelAccessList.get(from)?.has(metadata.extension)) {
|
||||
throw LanguageModelError.NoPermissions(`Language model '${languageModelId}' cannot be used by '${from.value}'.`);
|
||||
throw extHostTypes.LanguageModelError.NoPermissions(`Language model '${languageModelId}' cannot be used by '${from.value}'.`);
|
||||
}
|
||||
}
|
||||
|
||||
const requestId = (Math.random() * 1e6) | 0;
|
||||
const requestPromise = this._proxy.$fetchResponse(from, languageModelId, requestId, messages.map(typeConvert.LanguageModelMessage.from), options.modelOptions ?? {}, token);
|
||||
const requestPromise = this._proxy.$fetchResponse(from, languageModelId, requestId, internalMessages, options.modelOptions ?? {}, token);
|
||||
|
||||
const barrier = new Barrier();
|
||||
|
||||
@@ -303,11 +310,11 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
await barrier.wait();
|
||||
|
||||
if (error) {
|
||||
if (error.name === LanguageModelError.name) {
|
||||
if (error.name === extHostTypes.LanguageModelError.name) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new LanguageModelError(
|
||||
throw new extHostTypes.LanguageModelError(
|
||||
`Language model '${languageModelId}' errored, check cause for more details`,
|
||||
'Unknown',
|
||||
error
|
||||
@@ -317,6 +324,24 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
return res.apiObject;
|
||||
}
|
||||
|
||||
private _convertMessages(extension: IExtensionDescription, messages: (vscode.LanguageModelChatMessage2 | vscode.LanguageModelChatMessage)[]) {
|
||||
const internalMessages: IChatMessage[] = [];
|
||||
for (const message of messages) {
|
||||
if (message instanceof extHostTypes.LanguageModelChatMessage2) {
|
||||
if (message.role as number === extHostTypes.LanguageModelChatMessageRole.System) {
|
||||
checkProposedApiEnabled(extension, 'languageModelSystem');
|
||||
}
|
||||
internalMessages.push(typeConvert.LanguageModelChatMessage.from(message));
|
||||
} else {
|
||||
if (message instanceof extHostTypes.LanguageModelChatSystemMessage) {
|
||||
checkProposedApiEnabled(extension, 'languageModelSystem');
|
||||
}
|
||||
internalMessages.push(typeConvert.LanguageModelMessage.from(message));
|
||||
}
|
||||
}
|
||||
return internalMessages;
|
||||
}
|
||||
|
||||
async $handleResponseFragment(requestId: number, chunk: IChatResponseFragment): Promise<void> {
|
||||
const data = this._pendingRequest.get(requestId);//.report(chunk);
|
||||
if (data) {
|
||||
@@ -376,7 +401,7 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
|
||||
|
||||
const data = this._allLanguageModelData.get(languageModelId);
|
||||
if (!data) {
|
||||
throw LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
|
||||
throw extHostTypes.LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
|
||||
}
|
||||
|
||||
const local = Iterable.find(this._languageModels.values(), candidate => candidate.languageModelId === languageModelId);
|
||||
|
||||
@@ -2239,6 +2239,29 @@ export namespace ChatFollowup {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export namespace LanguageModelChatMessage {
|
||||
|
||||
export function to(message: chatProvider.IChatMessage): vscode.LanguageModelChatMessage2 {
|
||||
switch (message.role) {
|
||||
case chatProvider.ChatMessageRole.System: return new types.LanguageModelChatMessage2(<number>types.LanguageModelChatMessageRole.System, message.content);
|
||||
case chatProvider.ChatMessageRole.User: return new types.LanguageModelChatMessage2(<number>types.LanguageModelChatMessageRole.User, message.content);
|
||||
case chatProvider.ChatMessageRole.Assistant: return new types.LanguageModelChatMessage2(<number>types.LanguageModelChatMessageRole.Assistant, message.content);
|
||||
}
|
||||
}
|
||||
|
||||
export function from(message: vscode.LanguageModelChatMessage2): chatProvider.IChatMessage {
|
||||
switch (message.role as types.LanguageModelChatMessageRole) {
|
||||
case types.LanguageModelChatMessageRole.System: return { role: chatProvider.ChatMessageRole.System, content: message.content };
|
||||
case types.LanguageModelChatMessageRole.User: return { role: chatProvider.ChatMessageRole.User, content: message.content };
|
||||
case types.LanguageModelChatMessageRole.Assistant: return { role: chatProvider.ChatMessageRole.Assistant, content: message.content };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export namespace LanguageModelMessage {
|
||||
|
||||
export function to(message: chatProvider.IChatMessage): vscode.LanguageModelChatMessage {
|
||||
|
||||
@@ -4424,6 +4424,25 @@ export enum ChatLocation {
|
||||
Editor = 4,
|
||||
}
|
||||
|
||||
export enum LanguageModelChatMessageRole {
|
||||
User = 1,
|
||||
Assistant = 2,
|
||||
System = 3
|
||||
}
|
||||
|
||||
export class LanguageModelChatMessage2 implements vscode.LanguageModelChatMessage2 {
|
||||
|
||||
role: vscode.LanguageModelChatMessageRole;
|
||||
content: string;
|
||||
name: string | undefined;
|
||||
|
||||
constructor(role: vscode.LanguageModelChatMessageRole, content: string, name?: string) {
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
export class LanguageModelChatSystemMessage {
|
||||
content: string;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ export const allApiProposals = Object.freeze({
|
||||
interactive: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.interactive.d.ts',
|
||||
interactiveWindow: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.interactiveWindow.d.ts',
|
||||
ipc: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.ipc.d.ts',
|
||||
languageModelSystem: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageModelSystem.d.ts',
|
||||
languageModels: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageModels.d.ts',
|
||||
languageStatusText: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageStatusText.d.ts',
|
||||
mappedEditsProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts',
|
||||
|
||||
@@ -19,6 +19,8 @@ declare module 'vscode' {
|
||||
|
||||
onDidReceiveLanguageModelResponse2?: Event<{ readonly extensionId: string; readonly participant?: string; readonly tokenCount?: number }>;
|
||||
|
||||
provideLanguageModelResponse?(messages: LanguageModelChatMessage2[], options: { [name: string]: any }, extensionId: string, progress: Progress<ChatResponseFragment>, token: CancellationToken): Thenable<any>;
|
||||
|
||||
provideLanguageModelResponse2(messages: LanguageModelChatMessage[], options: { [name: string]: any }, extensionId: string, progress: Progress<ChatResponseFragment>, token: CancellationToken): Thenable<any>;
|
||||
|
||||
provideTokenCount(text: string | LanguageModelChatMessage, token: CancellationToken): Thenable<number>;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/206265
|
||||
|
||||
// TODO@API don't have this dedicated type but as property, e.g anthropic doesn't have a system-role, see
|
||||
// https://github.com/anthropics/anthropic-sdk-typescript/blob/c2da9604646ff103fbdbca016a9a9d49b03b387b/src/resources/messages.ts#L384
|
||||
// So, we could have `LanguageModelChatRequestOptions#system` which would be more limiting but also more natural?
|
||||
|
||||
export enum LanguageModelChatMessageRole {
|
||||
System = 3
|
||||
}
|
||||
}
|
||||
+38
-33
@@ -5,6 +5,8 @@
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/206265
|
||||
|
||||
/**
|
||||
* Represents a language model response.
|
||||
*
|
||||
@@ -12,11 +14,6 @@ declare module 'vscode' {
|
||||
*/
|
||||
export interface LanguageModelChatResponse {
|
||||
|
||||
//TODO@API give this some structure
|
||||
// https://github.com/openai/openai-openapi/blob/master/openapi.yaml#L7700, https://platform.openai.com/docs/guides/text-generation/chat-completions-api
|
||||
// https://github.com/ollama/ollama/blob/main/docs/api.md#response-7
|
||||
// https://docs.anthropic.com/claude/reference/messages_post
|
||||
|
||||
/**
|
||||
* An async iterable that is a stream of text chunks forming the overall response.
|
||||
*
|
||||
@@ -40,12 +37,35 @@ declare module 'vscode' {
|
||||
stream: AsyncIterable<string>;
|
||||
}
|
||||
|
||||
export enum LanguageModelChatMessageRole {
|
||||
User,
|
||||
Assistant,
|
||||
// System see https://github.com/anthropics/anthropic-sdk-typescript/blob/c2da9604646ff103fbdbca016a9a9d49b03b387b/src/resources/messages.ts#L384
|
||||
//TODO@API give this some structure
|
||||
// https://github.com/openai/openai-openapi/blob/master/openapi.yaml#L7700, https://platform.openai.com/docs/guides/text-generation/chat-completions-api
|
||||
// https://github.com/ollama/ollama/blob/main/docs/api.md#response-7
|
||||
// https://docs.anthropic.com/claude/reference/messages_post
|
||||
export interface LanguageModelChatResponse2 {
|
||||
|
||||
message: {
|
||||
role: LanguageModelChatMessageRole;
|
||||
content: AsyncIterable<string>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the role of a chat message. This is either the user or the assistant/model.
|
||||
*/
|
||||
export enum LanguageModelChatMessageRole {
|
||||
/**
|
||||
* The user role, e.g the human interacting with a language model.
|
||||
*/
|
||||
User = 1,
|
||||
|
||||
/**
|
||||
* The assistant role, e.g. the language model generating responses.
|
||||
*/
|
||||
// TODO@API name: model?
|
||||
Assistant = 2
|
||||
}
|
||||
|
||||
// TODO@API name: LanguageModelChatMessage once the deprecated stuff is removed
|
||||
export class LanguageModelChatMessage2 {
|
||||
/**
|
||||
* The role of this message.
|
||||
@@ -71,26 +91,9 @@ declare module 'vscode' {
|
||||
constructor(role: LanguageModelChatMessageRole, content: string, name?: string);
|
||||
}
|
||||
|
||||
export interface LanguageModelChatResponse2 {
|
||||
|
||||
message: {
|
||||
role: LanguageModelChatMessageRole;
|
||||
content: AsyncIterable<string>;
|
||||
};
|
||||
}
|
||||
|
||||
// TODO@API have just LanguageModelChatMessage & LanguageModelChatMessageRole
|
||||
// TODO@API don't have SystemChatMessage because it encourages to mix system and user messages
|
||||
// but AFAIK system message should/must come first (https://github.com/anthropics/anthropic-sdk-typescript/blob/c2da9604646ff103fbdbca016a9a9d49b03b387b/src/resources/messages.ts#L384)
|
||||
|
||||
/**
|
||||
* A language model message that represents a system message.
|
||||
*
|
||||
* System messages provide instructions to the language model that define the context in
|
||||
* which user messages are interpreted.
|
||||
*
|
||||
* *Note* that a language model may choose to add additional system messages to the ones
|
||||
* provided by extensions.
|
||||
* @deprecated
|
||||
*/
|
||||
export class LanguageModelChatSystemMessage {
|
||||
|
||||
@@ -108,7 +111,7 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
/**
|
||||
* A language model message that represents a user message.
|
||||
* @deprecated
|
||||
*/
|
||||
export class LanguageModelChatUserMessage {
|
||||
|
||||
@@ -132,8 +135,7 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
/**
|
||||
* A language model message that represents an assistant message, usually in response to a user message
|
||||
* or as a sample response/reply-pair.
|
||||
* @deprecated
|
||||
*/
|
||||
export class LanguageModelChatAssistantMessage {
|
||||
|
||||
@@ -158,6 +160,7 @@ declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* Different types of language model messages.
|
||||
* @deprecated
|
||||
*/
|
||||
export type LanguageModelChatMessage = LanguageModelChatSystemMessage | LanguageModelChatUserMessage | LanguageModelChatAssistantMessage;
|
||||
|
||||
@@ -263,7 +266,6 @@ declare module 'vscode' {
|
||||
// TODO@API Revisit this, how do you do the first request?
|
||||
silent?: boolean;
|
||||
|
||||
// TODO@API add system messages here?
|
||||
|
||||
/**
|
||||
* A set of options that control the behavior of the language model. These options are specific to the language model
|
||||
@@ -317,7 +319,7 @@ declare module 'vscode' {
|
||||
* @param token A cancellation token which controls the request. See {@link CancellationTokenSource} for how to create one.
|
||||
* @returns A thenable that resolves to a {@link LanguageModelChatResponse}. The promise will reject when the request couldn't be made.
|
||||
*/
|
||||
export function sendChatRequest(languageModel: string, messages: LanguageModelChatMessage[], options: LanguageModelChatRequestOptions, token: CancellationToken): Thenable<LanguageModelChatResponse>;
|
||||
export function sendChatRequest(languageModel: string, messages: (LanguageModelChatMessage | LanguageModelChatMessage2)[], options: LanguageModelChatRequestOptions, token: CancellationToken): Thenable<LanguageModelChatResponse>;
|
||||
|
||||
/**
|
||||
* Uses the language model specific tokenzier and computes the length in token of a given message.
|
||||
@@ -329,7 +331,10 @@ declare module 'vscode' {
|
||||
* @param token Optional cancellation token.
|
||||
* @returns A thenable that resolves to the length of the message in tokens.
|
||||
*/
|
||||
export function computeTokenLength(languageModel: string, text: string | LanguageModelChatMessage, token?: CancellationToken): Thenable<number>;
|
||||
// TODO@API optional?
|
||||
// ollama has nothing
|
||||
// anthropic suggests to count after the fact https://github.com/anthropics/anthropic-tokenizer-typescript?tab=readme-ov-file#anthropic-typescript-tokenizer
|
||||
export function computeTokenLength(languageModel: string, text: string | LanguageModelChatMessage | LanguageModelChatMessage2, token?: CancellationToken): Thenable<number>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user