Update for tools changes

This commit is contained in:
Rob Lourens
2024-09-20 17:33:59 -07:00
parent ac66610947
commit 1c012edb7d
6 changed files with 90 additions and 79 deletions

View File

@ -49,7 +49,10 @@
"default": 0
}
}
}
},
"supportedContentTypes": [
"text/plain"
]
},
{
"id": "chat-sample_catVoice",
@ -58,7 +61,11 @@
"modelDescription": "Speak in a cat voice",
"userDescription": "Speak in a cat voice",
"icon": "$(files)",
"canBeInvokedManually": true
"canBeInvokedManually": true,
"supportedContentTypes": [
"text/plain",
"application/vnd.codechat.prompt+json.1"
]
}
]
},

View File

@ -1,6 +1,6 @@
import { contentType, renderElementJSON } from '@vscode/prompt-tsx';
import { contentType as promptTsxContentType, renderElementJSON } from '@vscode/prompt-tsx';
import * as vscode from 'vscode';
import { CatToolPrompt } from './play';
import { CatVoiceToolResult } from './tools';
export function activate(context: vscode.ExtensionContext) {
registerChatTool(context);
@ -10,12 +10,16 @@ export function activate(context: vscode.ExtensionContext) {
function registerChatTool(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.lm.registerTool('chat-sample_catVoice', {
async invoke(options, token) {
return {
[contentType]: await renderElementJSON(CatToolPrompt, {}, options.tokenOptions, token),
toString() {
return 'Reply in the voice of a cat! Use cat analogies when appropriate.';
},
};
const result: vscode.LanguageModelToolResult = {};
if (options.requestedContentTypes.includes(promptTsxContentType)) {
result[promptTsxContentType] = await renderElementJSON(CatVoiceToolResult, {}, options.tokenOptions, token);
}
if (options.requestedContentTypes.includes('text/plain')) {
result['text/plain'] = 'Reply in the voice of a cat! Use cat analogies when appropriate.';
}
return result;
},
}));
@ -25,19 +29,15 @@ function registerChatTool(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.lm.registerTool('chat-sample_tabCount', {
async invoke(options, token) {
return {
toString() {
const params = options.parameters as ITabCountParameters;
if (typeof params.tabGroup === 'number') {
const group = vscode.window.tabGroups.all[Math.max(params.tabGroup - 1, 0)];
const nth = params.tabGroup === 1 ? '1st' : params.tabGroup === 2 ? '2nd' : params.tabGroup === 3 ? '3rd' : `${params.tabGroup}th`;
return `There are ${group.tabs.length} tabs open in the ${nth} tab group.`;
} else {
const group = vscode.window.tabGroups.activeTabGroup;
return `There are ${group.tabs.length} tabs open.`;
}
},
};
const params = options.parameters as ITabCountParameters;
if (typeof params.tabGroup === 'number') {
const group = vscode.window.tabGroups.all[Math.max(params.tabGroup - 1, 0)];
const nth = params.tabGroup === 1 ? '1st' : params.tabGroup === 2 ? '2nd' : params.tabGroup === 3 ? '3rd' : `${params.tabGroup}th`;
return { 'text/plain': `There are ${group.tabs.length} tabs open in the ${nth} tab group.` };
} else {
const group = vscode.window.tabGroups.activeTabGroup;
return { 'text/plain': `There are ${group.tabs.length} tabs open.` };
}
},
}));
}
@ -107,28 +107,31 @@ function registerChatParticipant(context: vscode.ExtensionContext) {
}
stream.progress(`Calling tool: ${tool.id} with ${part.parameters}`);
// TODO support prompt-tsx here
const requestedContentType = 'text/plain';
toolCalls.push({
call: part,
result: vscode.lm.invokeTool(tool.id, { parameters: JSON.parse(part.parameters), toolInvocationToken: request.toolInvocationToken }, token),
result: vscode.lm.invokeTool(tool.id, { parameters: JSON.parse(part.parameters), toolInvocationToken: request.toolInvocationToken, requestedContentTypes: [requestedContentType] }, token),
tool
});
}
}
if (toolCalls.length) {
let assistantMsg = vscode.LanguageModelChatMessage.Assistant('');
const assistantMsg = vscode.LanguageModelChatMessage.Assistant('');
assistantMsg.content2 = toolCalls.map(toolCall => new vscode.LanguageModelChatResponseToolCallPart(toolCall.tool.id, toolCall.call.toolCallId, toolCall.call.parameters));
messages.push(assistantMsg);
for (const toolCall of toolCalls) {
// NOTE that the result of calling a function is a special content type of a USER-message
let message = vscode.LanguageModelChatMessage.User('');
const message = vscode.LanguageModelChatMessage.User('');
message.content2 = [new vscode.LanguageModelChatMessageToolResultPart(toolCall.call.toolCallId, (await toolCall.result).toString())];
messages.push(message);
}
// IMPORTANT The prompt must end with a USER message (with no tool call)
messages.push(vscode.LanguageModelChatMessage.User(`Above is the result of calling the functions ${toolCalls.map(call => call.tool.id).join(', ')}. The user cannot see this result, so you should explain it to the user if referencing it in your answer.`));
// RE-enter
return runWithFunctions();
}

View File

@ -1,38 +0,0 @@
import {
BasePromptElementProps,
PromptElement,
PromptSizing,
TextChunk,
UserMessage
} from '@vscode/prompt-tsx';
export interface PromptProps extends BasePromptElementProps {
userQuery: string;
}
export class PlayPrompt extends PromptElement<PromptProps, void> {
render(state: void, sizing: PromptSizing) {
return (
<>
<UserMessage>
You are a cat! Reply in the voice of a cat, using cat analogies when
appropriate. Be concise to prepare for cat play time. Give a small random
python code sample (that has cat names for variables).
</UserMessage>
<UserMessage>{this.props.userQuery}</UserMessage>
</>
);
}
}
export class CatToolPrompt extends PromptElement<BasePromptElementProps, void> {
render(state: void, sizing: PromptSizing) {
return (
<>
<TextChunk>
Reply in the voice of a cat! Use cat analogies when appropriate.
</TextChunk>
</>
);
}
}

19
chat-sample/src/tools.tsx Normal file
View File

@ -0,0 +1,19 @@
import {
BasePromptElementProps,
PromptElement,
PromptSizing,
TextChunk,
UserMessage
} from '@vscode/prompt-tsx';
export class CatVoiceToolResult extends PromptElement<BasePromptElementProps, void> {
render(state: void, sizing: PromptSizing) {
return (
<>
<TextChunk>
Reply in the voice of a cat! Use cat analogies when appropriate.
</TextChunk>
</>
);
}
}

View File

@ -214,6 +214,8 @@ declare module 'vscode' {
* The `data` for any confirmations that were rejected
*/
rejectedConfirmationData?: any[];
userSelectedModel?: LanguageModelChat;
}
// TODO@API fit this into the stream
@ -248,10 +250,6 @@ declare module 'vscode' {
export type ChatExtendedRequestHandler = (request: ChatRequest, context: ChatContext, response: ChatResponseStream, token: CancellationToken) => ProviderResult<ChatResult | void>;
export interface ChatRequest {
toolInvocationToken: ChatParticipantToolToken;
}
export interface ChatResult {
nextQuestion?: {
prompt: string;
@ -310,7 +308,14 @@ declare module 'vscode' {
codeBlockIndex: number;
totalCharacters: number;
newFile?: boolean;
userAction?: string;
}
export interface ChatApplyAction {
// eslint-disable-next-line local/vscode-dts-string-type-literals
kind: 'apply';
codeBlockIndex: number;
totalCharacters: number;
newFile?: boolean;
codeMapper?: string;
}
@ -345,7 +350,7 @@ declare module 'vscode' {
export interface ChatUserActionEvent {
readonly result: ChatResult;
readonly action: ChatCopyAction | ChatInsertAction | ChatTerminalAction | ChatCommandAction | ChatFollowupAction | ChatBugReportAction | ChatEditorAction;
readonly action: ChatCopyAction | ChatInsertAction | ChatApplyAction | ChatTerminalAction | ChatCommandAction | ChatFollowupAction | ChatBugReportAction | ChatEditorAction;
}
export interface ChatPromptReference {

View File

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// version: 6
// version: 7
// https://github.com/microsoft/vscode/issues/213274
declare module 'vscode' {
@ -73,14 +73,10 @@ declare module 'vscode' {
export interface LanguageModelToolResult {
/**
* The result can contain arbitrary representations of the content. An example might be a `PromptElementJSON` from `@vscode/prompt-tsx`, using the `contentType` exported by that library.
* The result can contain arbitrary representations of the content. Use {@link LanguageModelToolInvocationOptions.requested} to request particular types.
* `text/plain` is required to be supported by all tools. Another example might be a `PromptElementJSON` from `@vscode/prompt-tsx`, using the `contentType` exported by that library.
*/
[contentType: string]: any;
/**
* A string representation of the result which can be incorporated back into an LLM prompt without any special handling.
*/
toString(): string;
}
// Tool registration/invoking between extensions
@ -98,7 +94,6 @@ declare module 'vscode' {
/**
* Invoke a tool with the given parameters.
* TODO@API Could request a set of contentTypes to be returned so they don't all need to be computed?
*/
export function invokeTool(id: string, options: LanguageModelToolInvocationOptions, token: CancellationToken): Thenable<LanguageModelToolResult>;
}
@ -106,6 +101,11 @@ declare module 'vscode' {
export type ChatParticipantToolToken = unknown;
export interface LanguageModelToolInvocationOptions {
/**
* When this tool is being invoked within the context of a chat request, this token should be passed from {@link ChatRequest.toolInvocationToken}.
* In that case, a progress bar will be automatically shown for the tool invocation in the chat response view. If the tool is being invoked
* outside of a chat request, `undefined` should be passed instead.
*/
toolInvocationToken: ChatParticipantToolToken | undefined;
/**
@ -113,6 +113,11 @@ declare module 'vscode' {
*/
parameters: Object;
/**
* A tool invoker can request that particular content types be returned from the tool. All tools are required to support `text/plain`.
*/
requestedContentTypes: string[];
/**
* Options to hint at how many tokens the tool should return in its response.
*/
@ -154,6 +159,11 @@ declare module 'vscode' {
* A JSON schema for the parameters this tool accepts.
*/
parametersSchema?: JSONSchema;
/**
* The list of content types that the tool has declared support for.
*/
supportedContentTypes: string[];
}
export interface LanguageModelTool {
@ -188,6 +198,11 @@ declare module 'vscode' {
* string-manipulation of the prompt.
*/
readonly toolReferences: readonly ChatLanguageModelToolReference[];
/**
* A token that can be passed to {@link lm.invokeTool} when invoking a tool inside the context of handling a chat request.
*/
readonly toolInvocationToken: ChatParticipantToolToken;
}
export interface ChatRequestTurn {