The author of this article is a development engineer of 360 Qiwu Troupe
introduction
OpenAI
Released ChatGPT
, it was like throwing a blockbuster on the Internet lake that had been calm for a long time, and everyone was chasing and learning it in an instant. The reason for this is that it is actually a mobile phone in the true sense 人工智能对话机器人
. It uses deep learning technology, trained with a large amount of training data and self-supervised learning methods, to simulate human dialogue ability and generate natural language responses. Making good use of ChatGPT
this tool in daily production and learning can definitely improve our work efficiency, which should be especially obvious to us programmers. Many of our most commonly used development tools VSCode
have already integrated functions with many plug-ins ChatGPT
. This article will start from scratch and introduce the implementation principles and ideas of these plug-ins. I hope it will be helpful to you.
basic needs
Realize a plug-in that can ChatGPT
talk to you, you can have a dialogue in the form of a question and an answer, and you can send the code we selected to ChatGPT
, so that it can optimize the code. Of course, if you want to access ChatGPT
, you first need to bind OpenAI
the ApiKey
.
VSCode plug-in basic configuration
First, briefly introduce VSCode
the basic process of plug-in development
Install scaffolding
npm install -g yo generator-code
Then cd
go to your working directory, run it yo code
, and choose step by step according to the wizard. There is nothing to say. After running, a clean and runnable plug-in project will be generated.
2. Introduction to the project directory
View the current directory, the core of the project is package.json
and extension.js
. First look at package.json
the configuration file:
name
:project namedisplayName
: App market namedescription
: Application descriptionversion
: current plugin versionengines
: Indicates the minimum supported vscode version of the plugincategories
: Plug-in application market classificationmain
: The main entry file of the programactivationEvents
: Important , an array of extended activation events, indicating which events can activate the current plugin. for example:
"activationEvents": [
"onView:chatgpt-for-vscode.view",
"onCommand:chatgpt-for-vscode.setAPIKey",
"onCommand:chatgpt-for-vscode.askGPT",
"onCommand:chatgpt-for-vscode.whyBroken",
"onCommand:chatgpt-for-vscode.optimizeCode",
"onCommand:chatgpt-for-vscode.explainCode",
"onCommand:chatgpt-for-vscode.refactor"
],
onView
: Indicates that it is triggered by a view, chatgpt-for-vscode.view
which is the view ID. When this view is triggered, the current plug-in is invoked onCommand
: Indicates that it is triggered by a command, followed by the command Id, these are our custom commands. Press the shortcut key in VSCode
: After Command + Shift + P
entering the command title
, the plug-in will be invoked. The command title
is contributes
defined commands
in the module, which will be introduced later.
In addition to these two, there are: onLanguage
, onUri
, onDebug
, workspaceContains
, onFileSystem
etc. If set to , the plug-in will be activated *
as soon as it is started . Of course, for the user experience, this is not officially recommended.VSCode
contributes
: Important , configure the main function points of the plugin. for example:
"contributes": {
"commands": [
{
"command": "chatgpt-for-vscode.setAPIKey",
"title": "GPT:绑定APIKey"
},
{
"command": "chatgpt-for-vscode.askGPT",
"title": "GPT:询问 GPT"
},
{
"command": "chatgpt-for-vscode.whyBroken",
"title": "GPT:说明这段代码存在的问题"
},
{
"command": "chatgpt-for-vscode.optimizeCode",
"title": "GPT:优化这段代码"
},
{
"command": "chatgpt-for-vscode.explainCode",
"title": "GPT:解释这段代码"
},
{
"command": "chatgpt-for-vscode.refactor",
"title": "GPT:重构这段代码"
}
],
"menus": {
"editor/context": [
{
"command": "chatgpt-for-vscode.askGPT",
"group": "navigation@1"
},
{
"command": "chatgpt-for-vscode.whyBroken",
"group": "navigation@2"
},
{
"command": "chatgpt-for-vscode.optimizeCode",
"group": "navigation@3"
},
{
"command": "chatgpt-for-vscode.explainCode",
"group": "navigation@4"
},
{
"command": "chatgpt-for-vscode.refactor",
"group": "navigation@5"
},
{
"command": "chatgpt-for-vscode.setAPIKey",
"group": "navigation@6"
}
]
},
"viewsContainers": {
"activitybar": [
{
"id": "chatgpt-for-vscode",
"title": "ChatGPT",
"icon": "images/ChatGPT.png"
}
]
},
"views": {
"chatgpt-for-vscode": [
{
"type": "webview",
"id": "chatgpt-for-vscode.view",
"name": "ChatGPT"
}
]
}
},
commands:
command
: Command Id, this command IdactivationEvents
is the same as the command Id configured in .title
: The name of the entered command.Command + Shift + P
Enter the command title and find the corresponding command.menus:
editor/context
: Configure the editor to right-click to display the content.command
Is the command Id,group
: Display the command position of the Kanban after right-clicking. Herenavigation
the representation is shown at the top of the module.@*
Indicates sorting.viewsContainers
:activitybar
: Configure the right toolbar view entry, and display it after configuration. Note here that it must be consistent with the view key value in theid
later module, which means that the view displayed after clicking on the right is your local image path.views
icon
icon
views
: Configure the view, here is used towebview
display the custom view
After the configuration is complete
package.json
, the right-click command is displayed, the icon on the left status bar, and the top command line selects the input command, which can already be displayed. After running,npm run test
it will open the panel where your plug-in is installed by defaultVSCode
. The next step is to improve the code logic after triggering the command, and the core isextension.ts
implemented in .
extension.ts
module development
extension.ts
It is the entry file of the program, and there are two core methods in it:
export function activate(context: vscode.ExtensionContext) {}
export function deactivate() {}
It is easy to understand the literal meaning, which means the life cycle method called by the plug-in when it is activated and released.
1. Binding APIKey
command logic
To use the api, you first need to associate OpenAI
your own with the plug-in. ApiKey
This uses VSCode
its own API vscode.window.showInputBox
to get user input.
this.apiKey = await this.context.globalState.get('chatgpt-api-key');
if (!this.apiKey) {
const apiKeyInput = await vscode.window.showInputBox({
prompt: "请输入你的API Key",
ignoreFocusOut: true,
});
this.apiKey = apiKeyInput;
this.context.globalState.update('chatgpt-api-key', this.apiKey);
}
globalState
Persistence using the contextApiKey
For this command to take effect, it needs
activate
to be registered in
context.subscriptions.push(vscode.commands.registerCommand('chatgpt-for-vscode.setAPIKey', resetToken))
async function resetToken() {
await vscode.window.showInputBox({
prompt: "请输入OpenAI API Key",
ignoreFocusOut: true,
});
}
After executing
command + shift + p
the input command titleGPT:绑定APIKey
, the display effect is as follows:
In this way, the binding logic to the user is completedApiKey
.
2. Command trigger logic
Similar to binding users ApiKey
, the execution of other commands is also the same process, here is onCommand:chatgpt-for-vscode.askGPT
the command to illustrate:
// 注册命令
vscode.commands.registerCommand('chatgpt-for-vscode.askGPT', askChatGPT)
// 命令实现
async function askChatGPT(userInput: string) {
let editor = vscode.window.activeTextEditor;
if (editor) {
const selectedCode = editor.document.getText(vscode.window.activeTextEditor?.selection);
if(selectedCode.length) {
chatViewProvider.sendOpenAiApiRequest(userInput, selectedCode);
vscode.window.showInformationMessage(selectedCode);
}else {
vscode.window.showInformationMessage(`请选中一段代码`);
}
}
}
After registering the command, use it
editor.document.getText(vscode.window.activeTextEditor?.selection)
to get the selected code paragraph and judge it as empty.Use
chatViewProvider.sendOpenAiApiRequest(userInput, selectedCode);
this methodPrompt
to pass the code input and selected by the user. The implementation of this method will be introduced later. After registering all the commands,activate
the method is as follows
export function activate(context: vscode.ExtensionContext) {
const chatViewProvider = new view_provider.default(context);
context.subscriptions.push(
vscode.commands.registerCommand('chatgpt-for-vscode.askGPT', askChatGPT),
vscode.commands.registerCommand('chatgpt-for-vscode.whyBroken', askGPTWhyBroken),
vscode.commands.registerCommand('chatgpt-for-vscode.explainCode', askGPTToExplain),
vscode.commands.registerCommand('chatgpt-for-vscode.refactor', askGPTToRefactor),
vscode.commands.registerCommand('chatgpt-for-vscode.optimizeCode', askGPTToOptimize),
vscode.commands.registerCommand('chatgpt-for-vscode.setAPIKey', resetToken),
vscode.window.registerWebviewViewProvider("chatgpt-for-vscode.view", chatViewProvider, {
webviewOptions: { retainContextWhenHidden: true }})
);
async function askGPTWhyBroken() { await askChatGPT('说明下面的代码会出现什么问题?'); }
async function askGPTToExplain() { await askChatGPT('请帮我解释一下下面的代码?'); }
async function askGPTToRefactor() { await askChatGPT('帮我重构下面的代码'); }
async function askGPTToOptimize() { await askChatGPT('帮我优化下面的代码'); }
async function resetToken() {
await chatViewProvider.ensureApiKey();
}
async function askChatGPT(userInput: string) {
let editor = vscode.window.activeTextEditor;
if (editor) {
const selectedCode = editor.document.getText(vscode.window.activeTextEditor?.selection);
if(selectedCode.length) {
chatViewProvider.sendOpenAiApiRequest(userInput, selectedCode);
vscode.window.showInformationMessage(selectedCode);
}else {
vscode.window.showInformationMessage(`请选中一段代码`);
}
}
}
}
3. webView and chatViewProvider
In addition to the API for registering commands, the above code registerCommand
also has an API for registering custom webview
views. registerWebviewViewProvider
The function is to display our custom ones webview
. It has three parameters:
chatgpt-for-vscode.view
Is the view Id, which is the same as the Id corresponding to the modulepackage.json
in the middle , indicating that it is registered for that view Id .views
provider
chatViewProvider
view provider.The third parameter:
webview
the attribute configuration,retainContextWhenHidden: true
which means:webview
keep the state when it is hidden, and avoid being reset.
Next, focus onchatViewProvider
:
as a custom view,provider
you first need to inheritvscode.WebviewViewProvider
this interface
export interface WebviewViewProvider {
/**
* Revolves a webview view.
*
* `resolveWebviewView` is called when a view first becomes visible. This may happen when the view is
* first loaded or when the user hides and then shows a view again.
*
* @param webviewView Webview view to restore. The provider should take ownership of this view. The
* provider must set the webview's `.html` and hook up all webview events it is interested in.
* @param context Additional metadata about the view being resolved.
* @param token Cancellation token indicating that the view being provided is no longer needed.
*
* @return Optional thenable indicating that the view has been fully resolved.
*/
resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext, token: CancellationToken): Thenable<void> | void;
}
This interface has only one method, which resolveWebviewView
is called when the view is first made visible. This can happen when the view first loads, or when the user hides and then shows the view again. Inside this aspect is set webview
the html
same view properties.
export default class ChatGptViewProvider implements vscode.WebviewViewProvider {
private webView?: vscode.WebviewView;
private apiKey?: string;
private message?: any;
constructor(private context: vscode.ExtensionContext) { }
public resolveWebviewView(
webviewView: vscode.WebviewView,
_context: vscode.WebviewViewResolveContext,
_token: vscode.CancellationToken,
) {
this.webView = webviewView;
// webview属性设置
webviewView.webview.options = {
enableScripts: true,
localResourceRoots: [this.context.extensionUri]
};
// 返回Html代码
webviewView.webview.html = this.getHtml(webviewView.webview);
// 接收
webviewView.webview.onDidReceiveMessage(data => {
if (data.type === 'askChatGPT') {
this.sendOpenAiApiRequest(data.value);
}
});
if (this.message !== null) {
this.sendMessageToWebView(this.message);
this.message = null;
}
}
}
4. Communication mechanism
Custom webview
web pages are very similar to ordinary web pages, and they cannot be called directly VSCodeAPI
. However, their only special feature is that there is an additional acquireVsCodeApi
method named, and executing this method will return a super castrated version of the vscode
object. Using this object, you can implement Communication webview
with plugins, that is .provider
provider
Send a message towebview
:
this.webView?.webview.postMessage(message);
webview
The terminal receives the message:
window.addEventListener('message', event => {
const message = event.data;
console.log('Webview接收到的消息:', message);
}
webview
Proactively send a message toprovider
:
const vscode = acquireVsCodeApi();
vscode.postMessage({text: '你好,我是Webview啊!'});
provider
Receive message:
this.webView?.webview.onDidReceiveMessage(data => {
if (data.type === 'askChatGPT') {
this.sendOpenAiApiRequest(data.value);
}
});
After understanding the communication mechanism between the two parties, the basic logic is: when the button webview
is clicked 发送
, the user input is sent to ChatGPT
, ChatGPT
after the processing is completed, the return information is sent to webview
, and webview
the answer information is displayed to complete a dialogue logic.
// 按钮绑定点击事件
document.getElementById("ask-button")?.addEventListener("click", submitHandler);
let submitHandler = function (e) {
e.preventDefault();
e.stopPropagation();
const input = document.getElementById("question-input");
if (input.value?.length > 0) {
// 发送消息给 插件,使其完成ChatGPT请求
vscode.postMessage({
type: "askChatGPT",
value: input.value,
});
input.value = "";
}
};
5. Call OPenAI
interface
To complete a conversation, you need to call OPenAI
the API. You can find the specific API on the official website:
The parameter
model
is the code of the model you want to talk toChatGPT
, and different models will have different answers to the same question. For specific module differences, please refer to the picture below:
For more models, click here to viewParameters
messages
: your question informationParameter
temperature
: It is a parameter used to control the creativity of the generated text, and its value is between 0 and 2. A value of 1 means the model will use its default sampling strategy, while values below 1.0 will result in more conservative and predictable responses, and values above 1.0 will result in more creative and diverse responses.Parameters
max_tokens
: The maximum number of dialogs to generatetoken
. Heretoken
can be understood as the building blocks of the model. After understanding the above parameters, you can use it tofetch
initiate a request:
let completion = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
body: JSON.stringify({
model: "text-davinci-003",
messages: [{ role: "user", content: question }],
temperature: 0.7
}),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
"Content-Type": 'application/json',
Authorization: 'Bearer ' + this.apiKey,
},
}) as any;
According to the returned data structure, parse the response data, and send the result to webview
display to complete the development.
Publish plugin
Extension installation The
development of the plug-in is basically completed through the above steps. Next, there are two ways to publish our plug-in. If your plug-in is only used on the intranet, you can use the command: , to package the plug-in into a plug-vsce package
invsix
packageVSCode
.VSIX
Installation.
Of course, you must first installvsce
this tool
npm i vsce -g
Upload to Apps
VSCode
MarketplaceTo upload a plug-in to
VSCode
the application market, you need an account in the application marketpublisher
. The specific account creation process is not involved here. After creating an account, log in to the current account and execute it.vsce publish
It will take a few minutes to find it in the application market after the release is successful. There are a few caveats:README.md
The file will be displayed on the plugin home page by default;README.md
The resources in must all be HTTPS, if it is HTTP, the publishing will fail;CHANGELOG.md
will be displayed in the Changes tab;If the code is placed in
git
the warehouse and the field is setrepository
, it must be submitted before publishinggit
, otherwise it will promptGit working directory not clean
It takes a few minutes for the application market to be updated after release;
Of course, you can search in the plug-in market
chatgpt-for-vscode
to try this plug-in;
Summarize
The above is ChatGPT
the basic creation process of a plug-in, the core is the understanding and use of VSCode API
and ChatGPT API
. Of course, all the functions you need can be found in the corresponding official documents.
references:
https://code.visualstudio.com/api/extension-guides/overview
https://platform.openai.com/docs/api-reference/chat/create
http://blog.haoji.me/vscode-plugin-publish.html
- END -
About Qi Wu Troupe
Qi Wu Troupe is the largest front-end team of 360 Group, and participates in the work of W3C and ECMA members (TC39) on behalf of the group. Qi Wu Troupe attaches great importance to talent training. There are engineers, lecturers, translators, business interface people, team leaders and other development directions for employees to choose from, and supplemented by providing corresponding training on technical skills, professional skills, general skills, leadership skills, etc. course. Qi Dance Troupe welcomes all kinds of outstanding talents to pay attention to and join Qi Dance Troupe with an open and talent-seeking attitude.