Skip to content

Commit 55e0109

Browse files
authored
Add acceptance ratio for suggestions (#260521)
Add the ratio of the suggestion which was accepted
1 parent 1b97fc2 commit 55e0109

File tree

7 files changed

+55
-9
lines changed

7 files changed

+55
-9
lines changed

src/vs/editor/common/languages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,9 @@ export type InlineCompletionEndOfLifeReason<TInlineCompletion = InlineCompletion
986986
export type LifetimeSummary = {
987987
requestUuid: string;
988988
partiallyAccepted: number;
989+
partiallyAcceptedCountSinceOriginal: number;
990+
partiallyAcceptedRatioSinceOriginal: number;
991+
partiallyAcceptedCharactersSinceOriginal: number;
989992
shown: boolean;
990993
shownDuration: number;
991994
shownDurationUncollapsed: number;

src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,11 @@ export class InlineCompletionsModel extends Disposable {
984984
// This assumes that the inline completion and the model use the same EOL style.
985985
const text = editor.getModel()!.getValueInRange(acceptedRange, EndOfLinePreference.LF);
986986
const acceptedLength = text.length;
987-
completion.reportPartialAccept(acceptedLength, { kind, acceptedLength: acceptedLength });
987+
completion.reportPartialAccept(
988+
acceptedLength,
989+
{ kind, acceptedLength: acceptedLength },
990+
{ characters: acceptUntilIndexExclusive, ratio: acceptUntilIndexExclusive / ghostTextVal.length, count: 1 }
991+
);
988992

989993
} finally {
990994
completion.removeRef();
@@ -1003,6 +1007,10 @@ export class InlineCompletionsModel extends Disposable {
10031007
augmentedCompletion.completion.reportPartialAccept(itemEdit.text.length, {
10041008
kind: PartialAcceptTriggerKind.Suggest,
10051009
acceptedLength,
1010+
}, {
1011+
characters: itemEdit.text.length,
1012+
count: 1,
1013+
ratio: 1
10061014
});
10071015
}
10081016

src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ class InlineCompletionsState extends Disposable {
421421
let item;
422422
if (oldItem && oldItem !== i) {
423423
item = i.withIdentity(oldItem.identity);
424+
i.setIsPreceeded(oldItem);
424425
oldItem.setEndOfLifeReason({ kind: InlineCompletionEndOfLifeReasonKind.Ignored, userTypingDisagreed: false, supersededBy: i.getSourceCompletion() });
425-
i.setIsPreceeded();
426426
} else {
427427
item = i;
428428
}

src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { linesDiffComputers } from '../../../../common/diff/linesDiffComputers.j
2121
import { InlineCompletion, InlineCompletionTriggerKind, Command, InlineCompletionWarning, PartialAcceptInfo, InlineCompletionEndOfLifeReason } from '../../../../common/languages.js';
2222
import { ITextModel, EndOfLinePreference } from '../../../../common/model.js';
2323
import { TextModelText } from '../../../../common/model/textModelText.js';
24-
import { IDisplayLocation, InlineSuggestData, InlineSuggestionList, SnippetInfo } from './provideInlineCompletions.js';
24+
import { IDisplayLocation, InlineSuggestData, InlineSuggestionList, PartialAcceptance, SnippetInfo } from './provideInlineCompletions.js';
2525
import { singleTextRemoveCommonPrefix } from './singleTextEditHelpers.js';
2626
import { getPositionOffsetTransformerFromTextModel } from '../../../../common/core/text/getPositionOffsetTransformerFromTextModel.js';
2727
import { InlineCompletionViewData, InlineCompletionViewKind } from '../view/inlineEdits/inlineEditsViewInterface.js';
@@ -75,6 +75,8 @@ abstract class InlineSuggestionItemBase {
7575

7676
public get requestUuid(): string { return this._data.context.requestUuid; }
7777

78+
public get partialAccepts(): PartialAcceptance { return this._data.partialAccepts; }
79+
7880
/**
7981
* A reference to the original inline completion this inline completion has been constructed from.
8082
* Used for event data to ensure referential equality.
@@ -104,8 +106,8 @@ abstract class InlineSuggestionItemBase {
104106
this._data.reportInlineEditShown(commandService, this.insertText, viewKind, viewData);
105107
}
106108

107-
public reportPartialAccept(acceptedCharacters: number, info: PartialAcceptInfo) {
108-
this._data.reportPartialAccept(acceptedCharacters, info);
109+
public reportPartialAccept(acceptedCharacters: number, info: PartialAcceptInfo, partialAcceptance: PartialAcceptance) {
110+
this._data.reportPartialAccept(acceptedCharacters, info, partialAcceptance);
109111
}
110112

111113
public reportEndOfLife(reason: InlineCompletionEndOfLifeReason): void {
@@ -120,8 +122,8 @@ abstract class InlineSuggestionItemBase {
120122
this._data.reportInlineEditError(reason);
121123
}
122124

123-
public setIsPreceeded(): void {
124-
this._data.setIsPreceeded();
125+
public setIsPreceeded(item: InlineSuggestionItem): void {
126+
this._data.setIsPreceeded(item.partialAccepts);
125127
}
126128

127129
/**

src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ export type InlineSuggestProviderRequestInfo = {
258258
endTime: number;
259259
};
260260

261+
export type PartialAcceptance = {
262+
characters: number;
263+
count: number;
264+
ratio: number;
265+
};
266+
261267
export type InlineSuggestViewData = {
262268
editorType: InlineCompletionEditorType;
263269
renderData?: InlineCompletionViewData;
@@ -278,6 +284,7 @@ export class InlineSuggestData {
278284
private _lastSetEndOfLifeReason: InlineCompletionEndOfLifeReason | undefined = undefined;
279285
private _isPreceeded = false;
280286
private _partiallyAcceptedCount = 0;
287+
private _partiallyAcceptedSinceOriginal: PartialAcceptance = { characters: 0, ratio: 0, count: 0 };
281288

282289
constructor(
283290
public readonly range: Range,
@@ -299,6 +306,8 @@ export class InlineSuggestData {
299306

300307
public get showInlineEditMenu() { return this.sourceInlineCompletion.showInlineEditMenu ?? false; }
301308

309+
public get partialAccepts(): PartialAcceptance { return this._partiallyAcceptedSinceOriginal; }
310+
302311
public getSingleTextEdit() {
303312
return new TextReplacement(this.range, this.insertText);
304313
}
@@ -321,8 +330,12 @@ export class InlineSuggestData {
321330
}
322331
}
323332

324-
public reportPartialAccept(acceptedCharacters: number, info: PartialAcceptInfo) {
333+
public reportPartialAccept(acceptedCharacters: number, info: PartialAcceptInfo, partialAcceptance: PartialAcceptance) {
325334
this._partiallyAcceptedCount++;
335+
this._partiallyAcceptedSinceOriginal.characters += partialAcceptance.characters;
336+
this._partiallyAcceptedSinceOriginal.ratio = Math.min(this._partiallyAcceptedSinceOriginal.ratio + (1 - this._partiallyAcceptedSinceOriginal.ratio) * partialAcceptance.ratio, 1);
337+
this._partiallyAcceptedSinceOriginal.count += partialAcceptance.count;
338+
326339
this.source.provider.handlePartialAccept?.(
327340
this.source.inlineSuggestions,
328341
this.sourceInlineCompletion,
@@ -355,6 +368,9 @@ export class InlineSuggestData {
355368
const summary: LifetimeSummary = {
356369
requestUuid: this.context.requestUuid,
357370
partiallyAccepted: this._partiallyAcceptedCount,
371+
partiallyAcceptedCountSinceOriginal: this._partiallyAcceptedSinceOriginal.count,
372+
partiallyAcceptedRatioSinceOriginal: this._partiallyAcceptedSinceOriginal.ratio,
373+
partiallyAcceptedCharactersSinceOriginal: this._partiallyAcceptedSinceOriginal.characters,
358374
shown: this._didShow,
359375
shownDuration: this._shownDuration,
360376
shownDurationUncollapsed: this._showUncollapsedDuration,
@@ -383,8 +399,13 @@ export class InlineSuggestData {
383399
}
384400
}
385401

386-
public setIsPreceeded(): void {
402+
public setIsPreceeded(partialAccepts: PartialAcceptance): void {
387403
this._isPreceeded = true;
404+
405+
if (this._partiallyAcceptedSinceOriginal.characters !== 0 || this._partiallyAcceptedSinceOriginal.ratio !== 0 || this._partiallyAcceptedSinceOriginal.count !== 0) {
406+
console.warn('Expected partiallyAcceptedCountSinceOriginal to be { characters: 0, rate: 0, partialAcceptances: 0 } before setIsPreceeded.');
407+
}
408+
this._partiallyAcceptedSinceOriginal = partialAccepts;
388409
}
389410

390411
/**

src/vs/monaco.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7626,6 +7626,9 @@ declare namespace monaco.languages {
76267626
export type LifetimeSummary = {
76277627
requestUuid: string;
76287628
partiallyAccepted: number;
7629+
partiallyAcceptedCountSinceOriginal: number;
7630+
partiallyAcceptedRatioSinceOriginal: number;
7631+
partiallyAcceptedCharactersSinceOriginal: number;
76297632
shown: boolean;
76307633
shownDuration: number;
76317634
shownDurationUncollapsed: number;

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,9 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
676676
extensionId,
677677
extensionVersion,
678678
partiallyAccepted: lifetimeSummary.partiallyAccepted,
679+
partiallyAcceptedCountSinceOriginal: lifetimeSummary.partiallyAcceptedCountSinceOriginal,
680+
partiallyAcceptedRatioSinceOriginal: lifetimeSummary.partiallyAcceptedRatioSinceOriginal,
681+
partiallyAcceptedCharactersSinceOriginal: lifetimeSummary.partiallyAcceptedCharactersSinceOriginal,
679682
superseded: reason.kind === InlineCompletionEndOfLifeReasonKind.Ignored && !!reason.supersededBy,
680683
reason: reason.kind === InlineCompletionEndOfLifeReasonKind.Accepted ? 'accepted'
681684
: reason.kind === InlineCompletionEndOfLifeReasonKind.Rejected ? 'rejected'
@@ -1317,6 +1320,9 @@ type InlineCompletionEndOfLifeEvent = {
13171320
timeUntilProviderResponse: number;
13181321
reason: 'accepted' | 'rejected' | 'ignored';
13191322
partiallyAccepted: number;
1323+
partiallyAcceptedCountSinceOriginal: number;
1324+
partiallyAcceptedRatioSinceOriginal: number;
1325+
partiallyAcceptedCharactersSinceOriginal: number;
13201326
preceeded: boolean;
13211327
requestReason: string;
13221328
languageId: string;
@@ -1350,6 +1356,9 @@ type InlineCompletionsEndOfLifeClassification = {
13501356
timeUntilProviderResponse: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The time it took for the inline completion to be shown after the request' };
13511357
reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The reason for the inline completion ending' };
13521358
partiallyAccepted: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'How often the inline completion was partially accepted by the user' };
1359+
partiallyAcceptedCountSinceOriginal: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'How often the inline completion was partially accepted since the original request' };
1360+
partiallyAcceptedRatioSinceOriginal: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The percentage of characters accepted since the original request' };
1361+
partiallyAcceptedCharactersSinceOriginal: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The character count accepted since the original request' };
13531362
preceeded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the inline completion was preceeded by another one' };
13541363
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The language ID of the document where the inline completion was shown' };
13551364
requestReason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The reason for the inline completion request' };

0 commit comments

Comments
 (0)