Efficient Coding with AI: Create your own Co-Pilot

Meiyappan Kannappa
7 min readMar 31, 2024

In the modern age of software development, efficiency and productivity are paramount. Imagine having a personalized coding companion by your side, tailored to your unique needs and preferences. With the power of Artificial Intelligence (AI), creating your own coding CoPilot becomes a reality. This innovative solution revolutionizes the coding experience, using open source LLM models in your local developer machine.

What is Co-Pilot?

A coding co-pilot is like having a smart helper that suggests and completes code for you as you write it. It’s an AI tool that makes coding easier by giving you hints and automating some parts of the coding process. It’s designed to save time, reduce mistakes, and make coding more efficient and enjoyable.

Need of Co-Pilot for Developers

There are lot of benefits for developers using co-pilot

  • Developers can write faster codes with help of suggestions and automating repetitive tasks
  • Enhance developer productivity with intelligent assistance, allowing developers to solve complex problems
  • Supports developers to review the code and provide suggestions on issues in the code & coding standards
  • Helps developers to learn new things and advancements in programming languages
  • Streamlines coding tasks, to allow developers spend time on innovations and innovative ideas

In this article, we will outline how to create your own custom Co-Pilot using open source LLM llama2, Langchain JS and VS Code extension API.

But wait, why do even need to build Custom Co-Pilot. An organization or individual can build custom Co-Pilot to get the below advantages

Tailored Solutions: A custom co-pilot can be tailored to specific coding styles, preferences, and project requirements, providing more personalized and relevant suggestions.

Domain-Specific Knowledge: Custom co-pilots can be trained on domain-specific data, making them more adept at understanding and assisting with specialized tasks.

Enhanced Integration: Custom co-pilots can be seamlessly integrated with existing tools, workflows, and processes, enhancing overall development efficiency.

Privacy and Security: Developing a custom co-pilot allows for greater control over data privacy and security, especially when working with sensitive or proprietary code.

Innovation and Competitive Edge: Custom co-pilots can differentiate a development team or organization by offering unique features, improving productivity, and fostering innovation.

Scalability and Flexibility: Custom co-pilots can be scaled and adapted to evolving needs, ensuring they remain effective and relevant as projects grow and change.

Time to see code in action

We will create a co-pilot to analyze the selected code, analyze a file for issues, coding standards and then create a code based on the comments provided. I named this Co-Pilot as Mei’s Co-Pilot

Prerequsite

  1. Install ollama, it allows you to run open-source large language models, such as Llama 2, locally. Ollama bundles model weights, configuration, and data into a single package, defined by a Modelfile. It optimizes setup and configuration details, including GPU usage. Follow steps here
  2. Run llama2 as below from your terminal
ollama run llama2

Create VS Code extension

Create a vs code extension using the below command, and follow the instructions in terminal to create a vs code extension project. It will be very similar to npm project with package.json and file named extension.js, which is the entry file for the extension

npx --package yo --package generator-code -- yo code

Commands trigger actions in Visual Studio Code. If you have ever configured a keybinding, then you’ve worked with commands. Commands are also used by extensions to expose functionality to users, bind to actions in VS Code’s UI, and implement internal logic.

Now we need to create and register commands. For the same we need to add few lines as below in package.json. We need two types of commands editor and explorer commands. Editor commands will be available in right click within editor window, Explorer commands will be in file explorer window.

Add the commands in package.json

 "commands": [
{
"command": "extension.writecode",
"title": "Ask Mei to Code" // Text for the command which will be displayed in the menu
},
{
"command": "extension.analyzecode",
"title": "Ask Mei to Analyze Code"
},
{
"command": "uploadCurrentFile.analyze",
"title": "Ask Mei to Analyze",
"category": "Explorer"
}
],
"menus": {
// COMMANDS FOR EDITOR WINDOW
"editor/context": [
{
"command": "extension.createGist",// COMMANDS that will be registered to trigger action
"group": "YourGroup@1"
},
{
"command": "extension.writecode",
"group": "YourGroup@1"
},
{
"command": "extension.analyzecode",
"group": "YourGroup@1"
}
],
// COMMANDS FOR EXPLORER WINDOW
"explorer/context": [
{
"command": "uploadCurrentFile.analyze",
"group": "navigation"
}
]
}

Once the commands are configured in package.json, register these commands in extension.js under activate method, to act for when its clicked by the user.

function activate(context) {

const command = vscode.commands.registerCommand("uploadCurrentFile.analyze", async (currentFile, selectedFiles) => {
if(selectedFiles.length){
vscode.window.showInformationMessage('Multiple files cannot be analyzed at once by Mei!');
}else{
analyseFile(currentFile);
}
});

let writeCode = vscode.commands.registerCommand('extension.writecode', function () {
WriteCodeByMei();
});


let analysecode = vscode.commands.registerCommand('extension.analyzecode', function () {
vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Mei is Analyzing',
cancellable: false
}, () => {
return new Promise(resolve => {

askMeitoAnalyzeCode(resolve);
});
});

});
context.subscriptions.push(writeCode);
context.subscriptions.push(analysecode);
context.subscriptions.push(disposable);
context.subscriptions.push(command);
}

Before we proceed further, install the below npm packages

  "dependencies": {
"@langchain/community": "^0.0.43",
"@langchain/openai": "^0.0.24",
"markdown-it": "^14.1.0",
"request-promise": "^4.2.6"
}

If you notice we have installed couple of langchain.js libraries, we will use langchain as a framework to build applications using large language models (LLMs), in our case llama2.

To know more about LLMs, Langchain please checkout my previous blog

To create your Co-Pilot you need to have some understanding around prompt engineering, which is key to make the LLM understand your question & respond with what you are looking for. I would suggest the readers to listen to this session by Prof. Andrew on Prompt Engineering here

Lets implement the method for the commands we configured and registered.

  1. Write code for the comments given — When we write a comment, select the same and invoke the “Ask Mei to code” from right click, the LLM should generate code, and extension should insert in the next line. Below is the code, which identifies the file and then get the comment as text to feed in both to the LLM prompt, along with our question in the prompt.
async function WriteCodeByMei() {

const editor = vscode.window.activeTextEditor;

// This line reads the selected comment from editor

const selection = editor.selection;
const newPosition = selection.active.with(selection.end.line+1);

const text = editor.document.getText(editor.selection);

const fileExtension = editor.document.fileName.split('.').pop();
const res = await ollama.invoke(text + ", Provide response as code in "+fileExtension+". Just code, do not give any additional text");

editor.edit(editBuilder => {
editBuilder.insert(newPosition, '\n'+res.replace(/```/g, '')+' \n');

});

}

Work in Action

Below is the complete code, with implementation for all the commands.

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');
const editor = vscode.window.activeTextEditor;
const rp = require("request-promise");
const Ollama = require('@langchain/community/llms/ollama').Ollama;
const markdown = require('markdown-it')();

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed

const ollama = new Ollama({
baseUrl: "http://localhost:11434", // Default value
model: "llama2", // Default value
});
console.log(ollama)

function displayResultsInPanel(resultData) {

const panel = vscode.window.createWebviewPanel(
'markdownPanel',
'Mei\'s Results',
vscode.ViewColumn.One,
{}
);
const htmlContent = markdown.render(resultData);

panel.webview.html = htmlContent;
}



async function askMeitoAnalyzeCode(resolve) {
const text = editor.document.getText(editor.selection);

const fileExtension = editor.document.fileName.split('.').pop();
const res = await ollama.invoke("Analyze the "+fileExtension +" code and identify any issues and coding standard not followed in the given code . Provide response in md format```" + text + "```");
resolve();
displayResultsInPanel(res);
}

async function analyseFile(currentFile) {

}

async function WriteCodeByMei() {

const editor = vscode.window.activeTextEditor;
const selection = editor.selection;
const newPosition = selection.active.with(selection.end.line+1);

const text = editor.document.getText(editor.selection);

const fileExtension = editor.document.fileName.split('.').pop();
const res = await ollama.invoke(text + ", Provide resonse as code in "+fileExtension+". Just code, do not give any additional text");

editor.edit(editBuilder => {
editBuilder.insert(newPosition, '\n'+res.replace(/```/g, '')+' \n');

});

}

/**
* @param {vscode.ExtensionContext} context
*/
function activate(context) {

// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated

// this code runs whenever your click 'Create Gist' from the context menu in your browser.
let disposable = vscode.commands.registerCommand(
"extension.createGist",
function () {
CreateGist();
}
);

const command = vscode.commands.registerCommand("uploadCurrentFile.analyze", async (currentFile, selectedFiles) => {
if(selectedFiles.length){
vscode.window.showInformationMessage('Multiple files cannot be analyzed at once by Mei!');
}else{
analyseFile(currentFile);
}
});

let writeCode = vscode.commands.registerCommand('extension.writecode', function () {
WriteCodeByMei();
});


let analysecode = vscode.commands.registerCommand('extension.analyzecode', function () {
vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Analyzing',
cancellable: false
}, () => {
return new Promise(resolve => {

askMeitoAnalyzeCode(resolve);
});
});

});
context.subscriptions.push(writeCode);
context.subscriptions.push(analysecode);
context.subscriptions.push(disposable);
context.subscriptions.push(command);
}



// This method is called when your extension is deactivated
function deactivate() { }

module.exports = {
activate,
deactivate
}

Final Thoughts

There are several advantages in creating a own Co-Pilot as listed above, in addition most of the Co-Pilot available in the market comes for a cost, perhaps the data is shared and the LLMs are enriched with the data that you share. However if you are an organization or an individual too deep in to coding & technology, its wise to build your own co-pilot with your needs and your data. Most of all thing, your data is safe with you.

--

--

Meiyappan Kannappa

Technical enthusiast, daydreamer. Design of involute software architecture for digital transformation, sustainability and cost optimization.