mirror of
https://github.com/voideditor/void
synced 2026-05-24 01:48:25 +00:00
Add basic system prompt
This commit is contained in:
parent
9b878a9fc0
commit
652f64cd14
5 changed files with 32 additions and 166 deletions
|
|
@ -14,7 +14,7 @@ type Autocompletion = {
|
|||
result: string,
|
||||
}
|
||||
|
||||
const TIMEOUT_TIME = 10000
|
||||
const TIMEOUT_TIME = 60000
|
||||
|
||||
const toInlineCompletion = ({ prefix, suffix, autocompletion }: { prefix: string, suffix: string, autocompletion: Autocompletion }): vscode.InlineCompletionItem => {
|
||||
|
||||
|
|
@ -37,13 +37,8 @@ const toInlineCompletion = ({ prefix, suffix, autocompletion }: { prefix: string
|
|||
remainingText = generatedMiddle.substring(index + 1)
|
||||
}
|
||||
|
||||
console.log('----')
|
||||
console.log('fullPrefix', fullPrefix)
|
||||
console.log('----')
|
||||
console.log('----')
|
||||
console.log('prefix', prefix)
|
||||
console.log('----')
|
||||
console.log('completion: ', remainingText)
|
||||
console.log('generated middle: ', JSON.stringify(generatedMiddle))
|
||||
console.log('remaining text: ', JSON.stringify(remainingText))
|
||||
|
||||
return new vscode.InlineCompletionItem(remainingText)
|
||||
|
||||
|
|
@ -55,6 +50,10 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
|
||||
private _autocompletionsOfDocument: { [docUriStr: string]: Autocompletion[] } = {}
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
this._extensionContext = context
|
||||
}
|
||||
|
||||
// used internally by vscode
|
||||
// fires after every keystroke
|
||||
async provideInlineCompletionItems(
|
||||
|
|
@ -66,10 +65,12 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
|
||||
const docUriStr = document.uri.toString()
|
||||
|
||||
console.log('initial _autocompletionsOfDocument', this._autocompletionsOfDocument[docUriStr])
|
||||
|
||||
const fullText = document.getText();
|
||||
const cursorOffset = document.offsetAt(position);
|
||||
const prefix = fullText.substring(0, cursorOffset);
|
||||
const suffix = fullText.substring(cursorOffset);
|
||||
const prefix = fullText.substring(0, cursorOffset)
|
||||
const suffix = fullText.substring(cursorOffset)
|
||||
|
||||
if (!this._autocompletionsOfDocument[docUriStr]) {
|
||||
this._autocompletionsOfDocument[docUriStr] = []
|
||||
|
|
@ -94,44 +95,45 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
if (cachedAutocompletion) {
|
||||
|
||||
if (cachedAutocompletion.status === 'finished') {
|
||||
console.log('AAA1')
|
||||
|
||||
const inlineCompletion = toInlineCompletion({ autocompletion: cachedAutocompletion, prefix, suffix, })
|
||||
return [inlineCompletion]
|
||||
|
||||
} else if (cachedAutocompletion.status === 'pending') {
|
||||
console.log('AAA2')
|
||||
|
||||
try {
|
||||
// await the result; if it hasnt resolved in 10 seconds assume the request is dead
|
||||
await Promise.race([
|
||||
cachedAutocompletion.promise,
|
||||
new Promise<string>((resolve, reject) => setTimeout(() => reject('Request timed out'), TIMEOUT_TIME)),
|
||||
])
|
||||
await cachedAutocompletion.promise;
|
||||
const inlineCompletion = toInlineCompletion({ autocompletion: cachedAutocompletion, prefix, suffix, })
|
||||
return [inlineCompletion]
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error creating autocompletion (1): ' + e)
|
||||
return []
|
||||
}
|
||||
|
||||
} else {
|
||||
return []
|
||||
} else if (cachedAutocompletion.status === 'error') {
|
||||
console.log('AAA3')
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
console.log('BBB')
|
||||
|
||||
// if there is no autocomplete for this line, create it and add it to cache
|
||||
let messages: LLMMessage[] = []
|
||||
switch (voidConfig.default.whichApi) {
|
||||
case 'ollama':
|
||||
messages = [
|
||||
{ role: 'user', content: `[SUFFIX]${suffix}[PREFIX]${prefix} ` }
|
||||
{ role: 'user', content: `[SUFFIX]${suffix}[PREFIX]${prefix} Fill in the middle between the prefix and suffix. Return only the middle. [MIDDLE]` }
|
||||
]
|
||||
break;
|
||||
case 'anthropic':
|
||||
case 'openAI':
|
||||
messages = [
|
||||
{ role: 'system', content: '' },
|
||||
{ role: 'system', content: 'Fill in the prefix up to the suffix. Return only the result and be very concise.' },
|
||||
{ role: 'user', content: `[SUFFIX]${suffix}[PREFIX]${prefix}` },
|
||||
]
|
||||
break;
|
||||
|
|
@ -161,7 +163,6 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
newAutocompletion.result = completionStr
|
||||
},
|
||||
onFinalMessage: (finalMessage) => {
|
||||
console.log('finalMessage:', finalMessage);
|
||||
|
||||
// newAutocompletion.prefix = prefix
|
||||
// newAutocompletion.suffix = suffix
|
||||
|
|
@ -184,16 +185,19 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
voidConfig,
|
||||
abortRef: newAutocompletion.abortRef,
|
||||
})
|
||||
|
||||
setTimeout(() => { // if the request hasnt resolved in TIMEOUT_TIME seconds, end it
|
||||
if (newAutocompletion.status === 'pending') {
|
||||
reject('Timeout')
|
||||
}
|
||||
}, TIMEOUT_TIME)
|
||||
})
|
||||
|
||||
this._autocompletionsOfDocument[docUriStr]!.push(newAutocompletion)
|
||||
|
||||
|
||||
try {
|
||||
const result = await Promise.race([
|
||||
newAutocompletion.promise,
|
||||
new Promise<string>((resolve, reject) => setTimeout(() => reject('Request timed out'), TIMEOUT_TIME)),
|
||||
])
|
||||
await newAutocompletion.promise;
|
||||
|
||||
const inlineCompletion = toInlineCompletion({ autocompletion: newAutocompletion, prefix, suffix, })
|
||||
return [inlineCompletion]
|
||||
|
|
@ -203,13 +207,6 @@ export class AutocompleteProvider implements vscode.InlineCompletionItemProvider
|
|||
return []
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
|
||||
this._extensionContext = context
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { AbortRef, OnFinalMessage, OnText, sendLLMMessage } from "../common/sendLLMMessage"
|
||||
import { VoidConfig } from '../webviews/common/contextForConfig';
|
||||
|
||||
type AutocompletionStatus = 'pending' | 'complete' | 'error';
|
||||
type Autocompletion = {
|
||||
prefix: string,
|
||||
suffix: string,
|
||||
startTime: number,
|
||||
endTime: number,
|
||||
abortRef: AbortRef,
|
||||
status: AutocompletionStatus,
|
||||
result: string,
|
||||
}
|
||||
|
||||
const recentEdits = []
|
||||
const autocompletionsOfDocument: { [docUriStr: string]: Autocompletion[] } = {}
|
||||
|
||||
|
||||
const showRecentAutocompletion = () => {
|
||||
console.log('showRecentAutocompletion')
|
||||
const editor = vscode.window.activeTextEditor
|
||||
if (!editor) return;
|
||||
|
||||
const docUriStr = editor.document.uri.toString();
|
||||
const autocompletions = autocompletionsOfDocument[docUriStr]
|
||||
if (!autocompletions || autocompletions.length === 0) return;
|
||||
|
||||
const completion = autocompletions[autocompletions.length - 1]
|
||||
if (completion.status === 'pending') return;
|
||||
if (completion.status === 'error') return;
|
||||
|
||||
const decorationType = vscode.window.createTextEditorDecorationType({
|
||||
after: { contentText: completion.result, color: '#888', }
|
||||
});
|
||||
const position = editor.document.positionAt(completion.prefix.length);
|
||||
const decorationOptions = [{ range: new vscode.Range(position, position) }];
|
||||
editor.setDecorations(decorationType, decorationOptions);
|
||||
|
||||
|
||||
}
|
||||
|
||||
export const setupAutocomplete = ({ voidConfig, abortRef }: { voidConfig: VoidConfig, abortRef: AbortRef }) => {
|
||||
|
||||
|
||||
vscode.workspace.onDidChangeTextDocument(e => {
|
||||
let shouldAutocomplete = true;
|
||||
// 1. determine if we should do an autocomplete
|
||||
// -check that we're not predicting too many changes at a time
|
||||
// -look at cache and see if current location has already been predicted
|
||||
// -check if the user's selection has overlap with the current prediction they are selecting
|
||||
|
||||
const editor = vscode.window.activeTextEditor
|
||||
if (!editor) return;
|
||||
if (e.document !== editor.document) return;
|
||||
if (e.contentChanges.length === 0) return;
|
||||
|
||||
const docUriStr = editor.document.uri.toString();
|
||||
|
||||
// get the prefix + suffix
|
||||
const change = e.contentChanges[e.contentChanges.length - 1];
|
||||
const fullText = editor.document.getText();
|
||||
const startOffset = editor.document.offsetAt(change.range.start);
|
||||
const cursorOffset = startOffset + (change.text.length > 0 ? change.text.length : 0);
|
||||
const prefix = fullText.substring(0, cursorOffset);
|
||||
const suffix = fullText.substring(cursorOffset);
|
||||
|
||||
// TODO do checks as mentioned above
|
||||
|
||||
if (!shouldAutocomplete) return;
|
||||
// 2. if we should do an autocomplete, get the relevant quantities
|
||||
// -LSP types of variables around the cursor
|
||||
// -LSP imports of variables around the cursor
|
||||
// -code context of recent edits
|
||||
|
||||
// 3. create an autocompletion
|
||||
|
||||
if (!autocompletionsOfDocument[docUriStr]) {
|
||||
autocompletionsOfDocument[docUriStr] = []
|
||||
}
|
||||
|
||||
let promptContent = ``;
|
||||
switch (voidConfig.default.whichApi) {
|
||||
case 'ollama':
|
||||
promptContent = `[SUFFIX]${suffix}[PREFIX]${prefix}`;
|
||||
break;
|
||||
case 'anthropic':
|
||||
case 'openAI':
|
||||
promptContent = `[SUFFIX]${suffix}[PREFIX]${prefix}`;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`We do not recommend using autocomplete with your selected provider (${voidConfig.default.whichApi}).`);
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
sendLLMMessage({
|
||||
messages: [{ role: 'user', content: promptContent, }],
|
||||
onText: async (tokenStr, completionStr) => {
|
||||
// TODO filter out bad responses here
|
||||
},
|
||||
onFinalMessage: (finalMessage) => {
|
||||
console.log('finalMessage:', finalMessage);
|
||||
const autocompletion: Autocompletion = {
|
||||
prefix,
|
||||
suffix,
|
||||
abortRef,
|
||||
startTime,
|
||||
endTime: Date.now(),
|
||||
status: 'complete',
|
||||
result: finalMessage,
|
||||
}
|
||||
autocompletionsOfDocument[docUriStr].push(autocompletion)
|
||||
showRecentAutocompletion()
|
||||
},
|
||||
onError: (e) => {
|
||||
console.error('Error generating autocompletion:', e);
|
||||
},
|
||||
voidConfig,
|
||||
abortRef,
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import { DiffProvider } from './DiffProvider';
|
|||
import { readFileContentOfUri } from './extensionLib/readFileContentOfUri';
|
||||
import { SidebarWebviewProvider } from './providers/SidebarWebviewProvider';
|
||||
import { CtrlKWebviewProvider } from './providers/CtrlKWebviewProvider';
|
||||
import { setupAutocomplete } from './autocomplete';
|
||||
import { AutocompleteProvider } from './AutcompleteProvider';
|
||||
|
||||
// // this comes from vscode.proposed.editorInsets.d.ts
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@ const voidConfigInfo: Record<
|
|||
// TODO we should allow user to select model inside Void, but for now we'll just let them handle the Ollama setup on their own
|
||||
model: configEnum(
|
||||
'Ollama model to use.',
|
||||
'llama3.1',
|
||||
["codegemma", "codegemma:2b", "codegemma:7b", "codellama", "codellama:7b", "codellama:13b", "codellama:34b", "codellama:70b", "codellama:code", "codellama:python", "command-r", "command-r:35b", "command-r-plus", "command-r-plus:104b", "deepseek-coder-v2", "deepseek-coder-v2:16b", "deepseek-coder-v2:236b", "falcon2", "falcon2:11b", "firefunction-v2", "firefunction-v2:70b", "gemma", "gemma:2b", "gemma:7b", "gemma2", "gemma2:2b", "gemma2:9b", "gemma2:27b", "llama2", "llama2:7b", "llama2:13b", "llama2:70b", "llama3", "llama3:8b", "llama3:70b", "llama3-chatqa", "llama3-chatqa:8b", "llama3-chatqa:70b", "llama3-gradient", "llama3-gradient:8b", "llama3-gradient:70b", "llama3.1", "llama3.2", "llama3.1:8b", "llama3.1:70b", "llama3.1:405b", "llava", "llava:7b", "llava:13b", "llava:34b", "llava-llama3", "llava-llama3:8b", "llava-phi3", "llava-phi3:3.8b", "mistral", "mistral:7b", "mistral-large", "mistral-large:123b", "mistral-nemo", "mistral-nemo:12b", "mixtral", "mixtral:8x7b", "mixtral:8x22b", "moondream", "moondream:1.8b", "openhermes", "openhermes:v2.5", "phi3", "phi3:3.8b", "phi3:14b", "phi3.5", "phi3.5:3.8b", "qwen", "qwen:7b", "qwen:14b", "qwen:32b", "qwen:72b", "qwen:110b", "qwen2", "qwen2:0.5b", "qwen2:1.5b", "qwen2:7b", "qwen2:72b", "smollm", "smollm:135m", "smollm:360m", "smollm:1.7b"] as const
|
||||
'codestral',
|
||||
["codestral", "codegemma", "codegemma:2b", "codegemma:7b", "codellama", "codellama:7b", "codellama:13b", "codellama:34b", "codellama:70b", "codellama:code", "codellama:python", "command-r", "command-r:35b", "command-r-plus", "command-r-plus:104b", "deepseek-coder-v2", "deepseek-coder-v2:16b", "deepseek-coder-v2:236b", "falcon2", "falcon2:11b", "firefunction-v2", "firefunction-v2:70b", "gemma", "gemma:2b", "gemma:7b", "gemma2", "gemma2:2b", "gemma2:9b", "gemma2:27b", "llama2", "llama2:7b", "llama2:13b", "llama2:70b", "llama3", "llama3:8b", "llama3:70b", "llama3-chatqa", "llama3-chatqa:8b", "llama3-chatqa:70b", "llama3-gradient", "llama3-gradient:8b", "llama3-gradient:70b", "llama3.1", "llama3.2", "llama3.1:8b", "llama3.1:70b", "llama3.1:405b", "llava", "llava:7b", "llava:13b", "llava:34b", "llava-llama3", "llava-llama3:8b", "llava-phi3", "llava-phi3:3.8b", "mistral", "mistral:7b", "mistral-large", "mistral-large:123b", "mistral-nemo", "mistral-nemo:12b", "mixtral", "mixtral:8x7b", "mixtral:8x22b", "moondream", "moondream:1.8b", "openhermes", "openhermes:v2.5", "phi3", "phi3:3.8b", "phi3:14b", "phi3.5", "phi3.5:3.8b", "qwen", "qwen:7b", "qwen:14b", "qwen:32b", "qwen:72b", "qwen:110b", "qwen2", "qwen2:0.5b", "qwen2:1.5b", "qwen2:7b", "qwen2:72b", "smollm", "smollm:135m", "smollm:360m", "smollm:1.7b"] as const
|
||||
),
|
||||
},
|
||||
openRouter: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
, "../../src/vs/workbench/contrib/welcomeGettingStarted/common/AutcompleteProvider.tsx" ],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
|
|
@ -27,4 +27,4 @@
|
|||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue