Skip to content

Commit c947bc8

Browse files
committed
Merge commit '1e2431af2477f14b924f13c123f657aa7402f33d'
2 parents 92b8875 + 1e2431a commit c947bc8

File tree

7 files changed

+138
-17
lines changed

7 files changed

+138
-17
lines changed

package.json

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@
3737
{
3838
"title": "Llama coder",
3939
"properties": {
40+
"notebook.includeMarkup": {
41+
"type": "boolean",
42+
"default": true,
43+
"description": "Include markup cell types in prompt"
44+
},
45+
"notebook.includeCellOutputs": {
46+
"type": "boolean",
47+
"default": false,
48+
"description": "Include Cell previous output results in the prompt"
49+
},
50+
"notebook.cellOutputLimit": {
51+
"type": "number",
52+
"default": 256,
53+
"description": "truncate cell output result if exceeds this limit"
54+
},
4055
"inference.endpoint": {
4156
"type": "string",
4257
"default": "",
@@ -114,6 +129,14 @@
114129
"default": 256,
115130
"description": "Max number of new tokens to be generated.",
116131
"order": 7
132+
},
133+
"inference.delay": {
134+
"type": "number",
135+
"default": 250,
136+
"description": "Completion request delay in milliseconds (0 - no delay, -1 - no completions).",
137+
"order": 8,
138+
"minimum": -1,
139+
"maximum": 5000
117140
}
118141
}
119142
}
@@ -126,7 +149,7 @@
126149
"pretest": "yarn run compile && yarn run lint",
127150
"lint": "eslint src --ext ts",
128151
"test": "jest",
129-
"package": "vsce package"
152+
"package": "npx @vscode/vsce package"
130153
},
131154
"devDependencies": {
132155
"@types/jest": "^29.5.10",

src/config.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,30 @@ class Config {
3535
}
3636
}
3737

38+
let delay = config.get('delay') as number;
39+
3840
return {
3941
endpoint,
4042
maxLines,
4143
maxTokens,
4244
temperature,
4345
modelName,
44-
modelFormat
46+
modelFormat,
47+
delay
48+
};
49+
}
50+
51+
// Notebook
52+
get notebook() {
53+
let config = vscode.workspace.getConfiguration('notebook');
54+
55+
let includeMarkup = config.get('includeMarkup') as boolean;
56+
let includeCellOutputs = config.get('includeCellOutputs') as boolean;
57+
let cellOutputLimit = config.get('cellOutputLimit') as number;
58+
return {
59+
includeMarkup,
60+
includeCellOutputs,
61+
cellOutputLimit,
4562
};
4663
}
4764

src/prompts/filter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type vscode from 'vscode';
22

33
export function isSupported(doc: vscode.TextDocument) {
4-
return doc.uri.scheme === 'file';
4+
return doc.uri.scheme === 'file' || doc.uri.scheme === 'vscode-notebook-cell';
55
}
66

77
export function isNotNeeded(doc: vscode.TextDocument, position: vscode.Position, context: vscode.InlineCompletionContext): boolean {

src/prompts/preparePrompt.ts

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import vscode from 'vscode';
22
import { detectLanguage } from './processors/detectLanguage';
33
import { fileHeaders } from './processors/fileHeaders';
44
import { languages } from './processors/languages';
5+
import { config } from '../config';
6+
7+
var decoder = new TextDecoder("utf8");
8+
9+
function getNotebookDocument(document: vscode.TextDocument): vscode.NotebookDocument | undefined {
10+
return vscode.workspace.notebookDocuments
11+
.find(x => x.uri.path === document.uri.path);
12+
}
513

614
export async function preparePrompt(document: vscode.TextDocument, position: vscode.Position, context: vscode.InlineCompletionContext) {
715

@@ -11,6 +19,75 @@ export async function preparePrompt(document: vscode.TextDocument, position: vsc
1119
let prefix = text.slice(0, offset);
1220
let suffix: string = text.slice(offset);
1321

22+
let notebookConfig = config.notebook;
23+
24+
// If this is a notebook, add the surrounding cells to the prefix and suffix
25+
let notebookDocument = getNotebookDocument(document);
26+
let language = detectLanguage(document.uri.fsPath, document.languageId);
27+
let commentStart: string | undefined = undefined;
28+
if (language) {
29+
commentStart = languages[language].comment?.start;
30+
}
31+
32+
if (notebookDocument) {
33+
let beforeCurrentCell = true;
34+
35+
let prefixCells = "";
36+
let suffixCells = "";
37+
38+
notebookDocument.getCells().forEach((cell) => {
39+
let out = "";
40+
41+
if (cell.document.uri.fragment === document.uri.fragment) {
42+
beforeCurrentCell = false; // switch to suffix mode
43+
return;
44+
}
45+
46+
// add the markdown cell output to the prompt as a comment
47+
if (cell.kind === vscode.NotebookCellKind.Markup && commentStart) {
48+
if (notebookConfig.includeMarkup) {
49+
for (const line of cell.document.getText().split('\n')) {
50+
out += `\n${commentStart}${line}`;
51+
}
52+
}
53+
} else {
54+
out += cell.document.getText();
55+
}
56+
57+
// if there is any outputs add them to the prompt as a comment
58+
const addCellOutputs = notebookConfig.includeCellOutputs
59+
&& beforeCurrentCell
60+
&& cell.kind === vscode.NotebookCellKind.Code
61+
&& commentStart;
62+
if (addCellOutputs) {
63+
let cellOutputs = cell.outputs
64+
.map(x => x.items
65+
.filter(x => x.mime === 'text/plain')
66+
.map(x => decoder.decode(x.data))
67+
.map(x => x.slice(0, notebookConfig.cellOutputLimit).split('\n')))
68+
.flat(3);
69+
70+
if (cellOutputs.length > 0) {
71+
out += `\n${commentStart}Output:`;
72+
for (const line of cellOutputs) {
73+
out += `\n${commentStart}${line}`;
74+
}
75+
}
76+
}
77+
78+
// update the prefix/suffix
79+
if (beforeCurrentCell) {
80+
prefixCells += out;
81+
} else {
82+
suffixCells += out;
83+
}
84+
85+
});
86+
87+
prefix = prefixCells + prefix;
88+
suffix = suffix + suffixCells;
89+
}
90+
1491
// Trim suffix
1592
// If suffix is too small it is safe to assume that it could be ignored which would allow us to use
1693
// more powerful completition instead of in middle one
@@ -22,7 +99,6 @@ export async function preparePrompt(document: vscode.TextDocument, position: vsc
2299
// NOTE: Most networks don't have a concept of filenames and expected language, but we expect that some files in training set has something in title that
23100
// would indicate filename and language
24101
// NOTE: If we can't detect language, we could ignore this since the number of languages that need detection is limited
25-
let language = detectLanguage(document.uri.fsPath, document.languageId);
26102
if (language) {
27103
prefix = fileHeaders(prefix, document.uri.fsPath, languages[language]);
28104
}

src/prompts/processors/languages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const languages: { [key in Language]: LanguageDescriptor } = {
111111
},
112112
python: {
113113
name: 'Python',
114-
extensions: ['.py'],
114+
extensions: ['.py', 'ipynb'],
115115
comment: { start: '#' }
116116
},
117117
c: {

src/prompts/processors/models.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function adaptPrompt(args: { format: ModelFormat, prefix: string, suffix:
1919
}
2020

2121
// Stable code FIM
22-
if (args.format === 'stable-code') {
22+
if (args.format === 'stable-code') {
2323
return {
2424
prompt: `<fim_prefix>${args.prefix}<fim_suffix>${args.suffix}<fim_middle>`,
2525
stop: [`<|endoftext|>`]
@@ -28,7 +28,7 @@ export function adaptPrompt(args: { format: ModelFormat, prefix: string, suffix:
2828

2929
// Codellama FIM
3030
return {
31-
prompt: `<PRE> ${args.prefix} <SUF>${args.suffix} <MID>`,
32-
stop: [`<PRE>`, `<SUF>`, `<MID>`, `<END>`]
31+
prompt: `<PRE> ${args.prefix} <SUF> ${args.suffix} <MID>`,
32+
stop: [`<END>`, `<EOD>`, `<EOT>`]
3333
};
3434
}

src/prompts/provider.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,21 @@ export class PromptProvider implements vscode.InlineCompletionItemProvider {
2020
this.context = context;
2121
}
2222

23+
async delayCompletion(delay: number, token: vscode.CancellationToken): Promise<boolean> {
24+
if (config.inference.delay < 0) {
25+
return false;
26+
}
27+
await new Promise(p => setTimeout(p, delay));
28+
if (token.isCancellationRequested) {
29+
return false;
30+
}
31+
return true;
32+
}
33+
2334
async provideInlineCompletionItems(document: vscode.TextDocument, position: vscode.Position, context: vscode.InlineCompletionContext, token: vscode.CancellationToken): Promise<vscode.InlineCompletionItem[] | vscode.InlineCompletionList | undefined | null> {
35+
if (!await this.delayCompletion(config.inference.delay, token)) {
36+
return;
37+
}
2438

2539
try {
2640

@@ -66,15 +80,6 @@ export class PromptProvider implements vscode.InlineCompletionItemProvider {
6680

6781
// Config
6882
let inferenceConfig = config.inference;
69-
// let config = vscode.workspace.getConfiguration('inference');
70-
// let endpoint = config.get('endpoint') as string;
71-
// let model = config.get('model') as string;
72-
// let maxLines = config.get('maxLines') as number;
73-
// let maxTokens = config.get('maxTokens') as number;
74-
// let temperature = config.get('temperature') as number;
75-
// if (endpoint.endsWith('/')) {
76-
// endpoint = endpoint.slice(0, endpoint.length - 1);
77-
// }
7883

7984
// Update status
8085
this.statusbar.text = `$(sync~spin) Llama Coder`;

0 commit comments

Comments
 (0)