Skip to content

Commit

Permalink
fix: filter long and invalid prompts in future messages VSCODE-614 (#861
Browse files Browse the repository at this point in the history
)
  • Loading branch information
gagik authored Nov 7, 2024
1 parent 0f8cfe0 commit 6ba9dd2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/participant/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import {
} from './prompts/schema';
import {
chatResultFeedbackKindToTelemetryValue,
ParticipantErrorTypes,
TelemetryEventTypes,
} from '../telemetry/telemetryService';
import { DocsChatbotAIService } from './docsChatbotAIService';
Expand All @@ -44,6 +43,7 @@ import formatError from '../utils/formatError';
import type { ModelInput } from './prompts/promptBase';
import { processStreamWithIdentifiers } from './streamParsing';
import type { PromptIntent } from './prompts/intent';
import { ParticipantErrorTypes } from '../test/suite/participant/participantErrorTypes';

const log = createLogger('participant');

Expand Down
11 changes: 11 additions & 0 deletions src/participant/prompts/promptBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
InternalPromptPurpose,
ParticipantPromptProperties,
} from '../../telemetry/telemetryService';
import { ParticipantErrorTypes } from '../../test/suite/participant/participantErrorTypes';

export interface PromptArgsBase {
request: {
Expand Down Expand Up @@ -188,6 +189,16 @@ export abstract class PromptBase<TArgs extends PromptArgsBase> {
}

if (historyItem instanceof vscode.ChatResponseTurn) {
if (
historyItem.result.errorDetails?.message ===
ParticipantErrorTypes.FILTERED
) {
// If the response led to a filtered error, we do not want the
// error-causing message to be sent again so we remove it.
messages.pop();
continue;
}

let message = '';

// Skip a response to an empty user prompt message or connect message.
Expand Down
9 changes: 1 addition & 8 deletions src/telemetry/telemetryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { NewConnectionTelemetryEventProperties } from './connectionTelemetr
import type { ShellEvaluateResult } from '../types/playgroundType';
import type { StorageController } from '../storage';
import type { ParticipantResponseType } from '../participant/constants';
import { ParticipantErrorTypes } from '../test/suite/participant/participantErrorTypes';

const log = createLogger('telemetry');
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand Down Expand Up @@ -193,14 +194,6 @@ export enum TelemetryEventTypes {
PARTICIPANT_RESPONSE_GENERATED = 'Participant Response Generated',
}

export enum ParticipantErrorTypes {
CHAT_MODEL_OFF_TOPIC = 'Chat Model Off Topic',
INVALID_PROMPT = 'Invalid Prompt',
FILTERED = 'Filtered by Responsible AI Service',
OTHER = 'Other',
DOCS_CHATBOT_API = 'Docs Chatbot API Issue',
}

/**
* This controller manages telemetry.
*/
Expand Down
63 changes: 63 additions & 0 deletions src/test/suite/participant/participant.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { Prompts } from '../../../participant/prompts';
import { createMarkdownLink } from '../../../participant/markdown';
import EXTENSION_COMMANDS from '../../../commands';
import { getContentLength } from '../../../participant/prompts/promptBase';
import { ParticipantErrorTypes } from './participantErrorTypes';

// The Copilot's model in not available in tests,
// therefore we need to mock its methods and returning values.
Expand Down Expand Up @@ -2125,6 +2126,68 @@ Schema:
getContentLength(messages[1])
);
});

suite('with invalid messages', function () {
test('filters disallowed messages', async function () {
const chatRequestMock = {
prompt: 'find all docs by a name example',
};

chatContextStub = {
history: [
Object.assign(Object.create(vscode.ChatRequestTurn.prototype), {
prompt: 'give me the count of all people in the prod database',
command: 'query',
references: [],
participant: CHAT_PARTICIPANT_ID,
}),
Object.assign(Object.create(vscode.ChatRequestTurn.prototype), {
prompt: 'some disallowed message',
command: 'query',
references: [],
participant: CHAT_PARTICIPANT_ID,
}),
Object.assign(Object.create(vscode.ChatResponseTurn.prototype), {
result: {
errorDetails: {
message: ParticipantErrorTypes.FILTERED,
},
},
response: [],
participant: CHAT_PARTICIPANT_ID,
}),
Object.assign(Object.create(vscode.ChatRequestTurn.prototype), {
prompt: 'ok message',
references: [],
participant: CHAT_PARTICIPANT_ID,
}),
],
};
const { messages } = await Prompts.generic.buildMessages({
context: chatContextStub,
request: chatRequestMock,
connectionNames: [],
});

expect(messages).to.have.lengthOf(4);

const messageContents = messages.map((message) => {
// There may be different types for the messages' content
const content = Array.isArray(message.content)
? message.content.map((sub) => sub.value).join('')
: message.content;

return content;
});

// Skip the preset prompt and check that the rest are correct.
expect(messageContents.slice(1)).deep.equal([
'give me the count of all people in the prod database',
'ok message',
'find all docs by a name example',
]);
});
});
});

suite('telemetry', function () {
Expand Down
7 changes: 7 additions & 0 deletions src/test/suite/participant/participantErrorTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum ParticipantErrorTypes {
CHAT_MODEL_OFF_TOPIC = 'Chat Model Off Topic',
INVALID_PROMPT = 'Invalid Prompt',
FILTERED = 'Filtered by Responsible AI Service',
OTHER = 'Other',
DOCS_CHATBOT_API = 'Docs Chatbot API Issue',
}

0 comments on commit 6ba9dd2

Please sign in to comment.