diff --git a/README.md b/README.md index 2422c77..fd23f94 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ -# Ollama Coder +# Ollama Autocoder -An ollama-based autocompletion engine. +A simple to use Ollama autocompletion engine with options exposed. + +## Requirements + +- Ollama must be serving on the API endpoint applied in settings + - For installation of Ollama, visit [ollama.ai](https://ollama.ai) +- Ollama must have the model applied in settings installed. +- For fastest results, an Nvidia GPU or Apple Silicon is recommended. CPU still works on small models. + +## How to Use + +1. In a text document, press space or go to a new line. The option `Autocomplete with Ollama` will appear. Press enter to start generation. +2. After startup, the tokens will be streamed to your cursor. +3. To stop the generation early, press the "Cancel" button on the "Ollama Autocoder" notification +4. Once generation stops, the notification will disappear. diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..a912fab Binary files /dev/null and b/icon.png differ diff --git a/package.json b/package.json index 3045b0b..99a3589 100644 --- a/package.json +++ b/package.json @@ -1,55 +1,75 @@ { - "name": "ollama-coder", - "displayName": "Ollama Coder", + "name": "ollama-autocoder", + "displayName": "Ollama Autocoder", + "description": "An Ollama autocompletion engine with options exposed", "version": "0.0.1", + "icon": "icon.png", "publisher": "10nates", "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/10Nates/ollama-coder" + "url": "https://github.com/10Nates/ollama-autocoder" }, "engines": { "vscode": "^1.73.0" }, "categories": [ - "Other" + "Machine Learning", + "Snippets", + "Programming Languages" + ], + "keywords": [ + "llama", + "ollama", + "gpt", + "coding", + "autocomplete", + "open source", + "assistant", + "ai", + "llm" ], "activationEvents": [ - "*" + "onStartupFinished" ], "main": "./out/extension.js", "contributes": { "configuration": { - "title": "Ollama Coder", - "properties": { - "ollama-coder.endpoint": { - "type": "string", - "default": "http://localhost:11434/api/generate", - "description": "The endpoint of the ollama REST API" - }, - "ollama-coder.model": { - "type": "string", - "default": "deepseek-coder", - "description": "The model to use for generating completions" - }, - "ollama-coder.system-message": { - "type": "string", - "default": "You are a code autocompletion engine. Respond with a continuation of the code provided and nothing else. Code should not be in a code block. Anything that is not code should be written as a code comment.", - "description": "The system message to use for code completions. Type DEFAULT for Makefile." - }, - "ollama-coder.max-tokens-predicted": { - "type": "integer", - "default": 500, - "description": "The maximum number of tokens generated by the model." - }, - "ollama-coder.prompt-window-size": { - "type": "integer", - "default": 2000, - "description": "The size of the prompt in characters. NOT tokens, so can be set about 1.5-2x the max tokens of the model (varies)." - } - } + "title": "Ollama Autocoder", + "properties": { + "ollama-autocoder.endpoint": { + "type": "string", + "default": "http://localhost:11434/api/generate", + "description": "The endpoint of the ollama REST API" + }, + "ollama-autocoder.model": { + "type": "string", + "default": "openhermes2.5-mistral:7b-q4_K_M", + "description": "The model to use for generating completions" + }, + "ollama-autocoder.raw-input": { + "type": "boolean", + "default": false, + "description": "Prompt the model without formatting. Disables system message." + }, + "ollama-autocoder.system-message": { + "type": "string", + "default": "You are a code autocompletion engine. Respond with a continuation of the code provided and nothing else. Code should not be in a code block. Anything that is not code should be written as a code comment.", + "description": "The system message to use for code completions. Type DEFAULT for Makefile." + }, + "ollama-autocoder.max-tokens-predicted": { + "type": "integer", + "default": 500, + "description": "The maximum number of tokens generated by the model." + }, + "ollama-autocoder.prompt-window-size": { + "type": "integer", + "default": 2000, + "description": "The size of the prompt in characters. NOT tokens, so can be set about 1.5-2x the max tokens of the model (varies)." + } + } } - }, + }, "scripts": { "vscode:prepublish": "npm run compile", "compile": "tsc -p ./", @@ -67,4 +87,4 @@ "dependencies": { "axios": "^1.6.2" } -} +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 79a3d9e..e1a58ac 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,36 +1,56 @@ // Significant help from GPT4 import * as vscode from "vscode"; -import axios, { AxiosResponse } from "axios"; +import axios from "axios"; -const VSConfig = vscode.workspace.getConfiguration("ollama-coder"); -const apiEndpoint: string = VSConfig.get("apiEndpoint") || "http://localhost:11434/api/generate"; -const apiModel: string = VSConfig.get("model") || "deepseek-coder"; -let apiSystemMessage: string | undefined = VSConfig.get("system-message"); -if (apiSystemMessage == "DEFAULT") apiSystemMessage = undefined; -const numPredict: number = VSConfig.get("max-tokens-predicted") || 500; -const promptWindowSize: number = VSConfig.get("prompt-window-size") || 2000; +let VSConfig: vscode.WorkspaceConfiguration; +let apiEndpoint: string; +let apiModel: string; +let apiSystemMessage: string | undefined; +let numPredict: number; +let promptWindowSize: number; +let rawInput: boolean; -// Function called on ollama-coder.autocomplete +function updateVSConfig() { + VSConfig = vscode.workspace.getConfiguration("ollama-autocoder"); + apiEndpoint = VSConfig.get("apiEndpoint") || "http://localhost:11434/api/generate"; + apiModel = VSConfig.get("model") || "openhermes2.5-mistral:7b-q4_K_M"; + apiSystemMessage = VSConfig.get("system-message"); + numPredict = VSConfig.get("max-tokens-predicted") || 500; + promptWindowSize = VSConfig.get("prompt-window-size") || 2000; + rawInput = VSConfig.get("raw-input") || false; + + if (apiSystemMessage == "DEFAULT" || rawInput) apiSystemMessage = undefined; +} + +updateVSConfig(); + +// No need for restart for any of these settings +vscode.workspace.onDidChangeConfiguration(updateVSConfig); + +// Function called on ollama-autocoder.autocomplete async function autocompleteCommand(document: vscode.TextDocument, position: vscode.Position, prompt: string, cancellationToken: vscode.CancellationToken) { // Show a progress message vscode.window.withProgress( { location: vscode.ProgressLocation.Notification, - title: "Getting a completion from Ollama...", + title: "Ollama Autocoder", cancellable: true, }, async (progress, progressCancellationToken) => { try { + progress.report({ message: "Starting model..." }); + // Make a request to the ollama.ai REST API const response = await axios.post(apiEndpoint, { model: apiModel, // Change this to the model you want to use prompt: prompt, stream: true, system: apiSystemMessage, + raw: rawInput, options: { num_predict: numPredict - }, + } }, { cancelToken: new axios.CancelToken((c) => { const cancelPost = function () { @@ -48,6 +68,8 @@ async function autocompleteCommand(document: vscode.TextDocument, position: vsco let currentPosition = position; response.data.on('data', async (d: Uint8Array) => { + progress.report({ message: "Generating..." }); + // Get a completion from the response const completion: string = JSON.parse(d.toString()).response; @@ -75,7 +97,7 @@ async function autocompleteCommand(document: vscode.TextDocument, position: vsco currentPosition = newPosition; // completion bar - progress.report({ increment: 1 / (numPredict/100) }); + progress.report({ message: "Generating...", increment: 1 / (numPredict/100) }); // move cursor const editor = vscode.window.activeTextEditor; @@ -97,12 +119,13 @@ async function autocompleteCommand(document: vscode.TextDocument, position: vsco vscode.window.showErrorMessage( "Ollama encountered an error: " + err.message ); + console.log(err); } } ); } -// This method is called when your extension is activated +// This method is called when extension is activated function activate(context: vscode.ExtensionContext) { // Register a completion provider for JavaScript files const provider = vscode.languages.registerCompletionItemProvider("*", { @@ -120,7 +143,7 @@ function activate(context: vscode.ExtensionContext) { item.documentation = new vscode.MarkdownString('Press `Enter` to get a completion from Ollama'); // Set the command to trigger the completion item.command = { - command: 'ollama-coder.autocomplete', + command: 'ollama-autocoder.autocomplete', title: 'Ollama', arguments: [document, position, prompt, cancellationToken] }; @@ -137,7 +160,7 @@ function activate(context: vscode.ExtensionContext) { // Register a command for getting a completion from Ollama const disposable = vscode.commands.registerCommand( - "ollama-coder.autocomplete", + "ollama-autocoder.autocomplete", autocompleteCommand ); @@ -145,7 +168,7 @@ function activate(context: vscode.ExtensionContext) { context.subscriptions.push(disposable); } -// This method is called when your extension is deactivated +// This method is called when extension is deactivated function deactivate() { } module.exports = {