Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/context/node/resolvers/extensionApi.tsx
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import { BasePromptElementProps, PromptElement, PromptPiece, PromptSizing, TextChunk } from '@vscode/prompt-tsx';
6
import { ChatResponsePart } from '@vscode/prompt-tsx/dist/base/vscodeTypes';
7
import { Embedding, EmbeddingType, EmbeddingVector, IEmbeddingsComputer, rankEmbeddings } from '../../../../platform/embeddings/common/embeddingsComputer';
8
import { EmbeddingCacheType, IEmbeddingsCache, LocalEmbeddingsCache, RemoteCacheType, RemoteEmbeddingsCache } from '../../../../platform/embeddings/common/embeddingsIndex';
9
import { IEnvService } from '../../../../platform/env/common/envService';
10
import { Progress } from '../../../../platform/notification/common/notificationService';
11
import { createFencedCodeBlock } from '../../../../util/common/markdown';
12
import { TelemetryCorrelationId } from '../../../../util/common/telemetryCorrelationId';
13
import { sanitizeVSCodeVersion } from '../../../../util/common/vscodeVersion';
14
import { CancellationToken } from '../../../../util/vs/base/common/cancellation';
15
import { createDecorator, IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
16
17
type BaseApiContext = { text: string; embedding: EmbeddingVector; type: 'code' | 'command' | 'documentationCodeBlock' };
18
type CodeApiContext = BaseApiContext & { type: 'code'; lang: string };
19
type CommandApiContext = BaseApiContext & { type: 'command' };
20
type DocumentationCodeBlockApiContext = BaseApiContext & { type: 'documentationCodeBlock'; lang: string };
21
type ApiContext = CodeApiContext | CommandApiContext | DocumentationCodeBlockApiContext;
22
23
export class ApiEmbeddingsIndex implements IApiEmbeddingsIndex {
24
declare readonly _serviceBrand: undefined;
25
private readonly embeddingsCache: IEmbeddingsCache;
26
private apiChunks: ApiContext[] | undefined;
27
28
constructor(
29
useRemoteCache: boolean = true,
30
@IEnvService envService: IEnvService,
31
@IInstantiationService instantiationService: IInstantiationService
32
) {
33
const cacheVersion = sanitizeVSCodeVersion(envService.getEditorInfo().version);
34
this.embeddingsCache = useRemoteCache ?
35
instantiationService.createInstance(RemoteEmbeddingsCache, EmbeddingCacheType.GLOBAL, 'api', cacheVersion, EmbeddingType.text3small_512, RemoteCacheType.Api) :
36
instantiationService.createInstance(LocalEmbeddingsCache, EmbeddingCacheType.GLOBAL, 'api', cacheVersion, EmbeddingType.text3small_512);
37
}
38
39
async updateIndex(): Promise<void> {
40
this.apiChunks = await this.embeddingsCache.getCache();
41
}
42
43
public nClosestValues(queryEmbedding: Embedding, n: number): string[] {
44
if (!this.apiChunks) {
45
return [];
46
}
47
48
return rankEmbeddings(queryEmbedding, this.apiChunks.map(item => [item, { type: this.embeddingsCache.embeddingType, value: item.embedding } satisfies Embedding]), n)
49
.map(x => this.toContextString(x.value));
50
}
51
52
private toContextString(context: ApiContext): string {
53
if (context.type === 'code') {
54
return `API Reference Code Snippet from vscode.d.ts:\n${createFencedCodeBlock(context.lang, context.text)}`;
55
} else if (context.type === 'command') {
56
return `${context.text}`;
57
} else if (context.type === 'documentationCodeBlock') {
58
return `Example code from VS Code documentation:\n${createFencedCodeBlock(context.lang, context.text)}`;
59
}
60
61
return '';
62
}
63
}
64
65
export interface IApiEmbeddingsIndex {
66
readonly _serviceBrand: undefined;
67
68
updateIndex(): Promise<void>;
69
nClosestValues(embedding: Embedding, n: number): string[];
70
}
71
72
export const IApiEmbeddingsIndex = createDecorator<IApiEmbeddingsIndex>('IApiEmbeddingsIndex');
73
74
export interface VSCodeAPIContextProps extends BasePromptElementProps {
75
query: string;
76
}
77
78
export class VSCodeAPIContextElement extends PromptElement<VSCodeAPIContextProps> {
79
constructor(
80
props: VSCodeAPIContextProps,
81
@IApiEmbeddingsIndex private readonly apiEmbeddingsIndex: IApiEmbeddingsIndex,
82
@IEmbeddingsComputer private readonly embeddingsComputer: IEmbeddingsComputer,
83
) {
84
super(props);
85
}
86
87
async renderAsString(): Promise<string> {
88
const snippets = await this.getSnippets(undefined);
89
return `Below are some potentially relevant code samples related to VS Code extension development. You may use information from these samples to help you answer the question if you believe it is relevant.\n${snippets.join('\n\n')}`;
90
}
91
92
private async getSnippets(token: CancellationToken | undefined): Promise<string[]> {
93
await this.apiEmbeddingsIndex.updateIndex();
94
if (token?.isCancellationRequested) {
95
return [];
96
}
97
98
const embeddingResult = await this.embeddingsComputer.computeEmbeddings(EmbeddingType.text3small_512, [this.props.query], {}, new TelemetryCorrelationId('VSCodeAPIContextElement::getSnippets'), token);
99
return this.apiEmbeddingsIndex.nClosestValues(embeddingResult.values[0], 5);
100
}
101
102
override async render(state: undefined, sizing: PromptSizing, progress?: Progress<ChatResponsePart>, token?: CancellationToken): Promise<PromptPiece<any, any> | undefined> {
103
const snippets = await this.getSnippets(token);
104
if (snippets.length) {
105
return <>
106
Below are some potentially relevant code samples related to VS Code extension development. You may use information from these samples to help you answer the question if you believe it is relevant.<br />
107
{snippets.map(s => {
108
return <><TextChunk>{s}</TextChunk><br /><br /></>;
109
})}
110
</>;
111
}
112
}
113
}
114
115