<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue3+NodeJS 接入文心一言, 發(fā)布一個 VSCode 大模型問答插件

          共 30971字,需瀏覽 62分鐘

           ·

          2023-11-09 16:37

             
             

          大廠技術(shù)  高級前端  Node進(jìn)階

          點擊上方 程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群


          隨著大模型能力越來越卷,在垂直領(lǐng)域的落地也在加快,對于大模型代碼生成能力而言,最簡潔高效的方式就是集成為常用IDE的插件,在vscode的插件戰(zhàn)場中,比較知名的就有 GitHub Copilot, 智譜清言的codegeex, 訊飛星火的iFlyCode。

          那么我們就以開發(fā)一個簡易的大模型對話插件,來探究一下vscode插件開發(fā)到發(fā)布的流程,研究一下文心一言大模型api的接入

          跟著操作大約30-60分鐘,你需要

          • 安裝vscode,npm/yarn等,node版本 >12.0
          • 最好有時間提前看一看 vscode 官網(wǎng)api開發(fā)文檔[1]

          萬字長文 Action!

          一:首先明確插件開發(fā)方式

          1. 如果你的插件只提供原生vscode能力,沒有復(fù)雜的UI需求,只需要在vscode插件項目上開發(fā)即可,類似插件比如Volar Git History Eslint
          2. 如果提供復(fù)雜UI交互,定制化界面,就需要在vscode插件內(nèi)嵌iframe頁面(用iframe展示線上web地址與使用vscode提供的一套UI組件皆可,詳見第三節(jié)),我這里選擇訪問線上地址,因此需要開發(fā)一個vscode插件項目與一個vue3項目(其他框架亦可),類似的復(fù)雜插件比如 CodeGeeX iFlyCode,會將web頁面展示在側(cè)邊欄中。
          image.png

          本文主要講解 如何在vscode插件中通過iframe展示web頁面,獲得更好的拓展性與可維護(hù)性

          二:新建一個Vscode 插件項目

          1. 官網(wǎng)教程地址

          開始你的第一個插件項目[2]

          2. 一步一步來創(chuàng)建

          • 找到一個比較舒服的文件夾,打開cmd,通過以下命令安裝 vscode項目腳手架,取的是 registry.npmjs.org[3] 鏡像源,因此可能會有科學(xué)問題
            npm install -g yo generator-code
          • 安裝完成后,直接用命令創(chuàng)建新的插件項目
           yo code
          • 進(jìn)入配置頁面,默認(rèn)就選擇 NewExtension(TypeScript),后面的按照圖中來就可
          • 然后會自動創(chuàng)建好項目,并執(zhí)行npm i,然后用 vscode 打開項目

          3. 分析目錄結(jié)構(gòu)以及運行插件

          目錄結(jié)構(gòu)就很清晰了,我們主要涉及修改 extension.ts 以及 package.json文件
          上圖中,extension.ts 中 activate() 方法就是插件的入口函數(shù),每次插件啟動都會執(zhí)行此函數(shù),當(dāng)前代碼是注冊了一個hello world命令,當(dāng)你在vscode中通過 ctrl+shift+p 調(diào)出輸入框并輸入hello world,就會執(zhí)行此注冊命令的回調(diào),彈出一個message框,下面我們來試一下

          在當(dāng)前項目中,直接按F5,會啟動一個擴展開發(fā)宿主,你的插件就運行在這個vscode窗口上啦 下面我們調(diào)出命令輸入框ctrl+shift+p ,輸入 hello world, 會提示命令,選中執(zhí)行,右下角會發(fā)現(xiàn)彈了一個message?。?!
          什么?你的沒彈出?那你豈不是和我當(dāng)時一樣倒霉,但你不需要花時間去挖這個奇怪的~bug !
          首先看一下你的vscode版本

          image.png

          當(dāng)前vscode版本不能低于 package.json 中的最低版本要求!

          這樣寫表示最低支持到1.83.0版本!改一下重新reload一下宿主插件,再試試命令就可以彈出啦!到此我們的插件側(cè)項目就搭建好了,下面我們簡單建一個vue項目,嵌入到側(cè)邊欄中

          三:新建一個Vue3 項目,在側(cè)邊欄中展示,實現(xiàn)vscode插件 <=> vue項目 雙向消息傳遞

          文章開頭我們提到,插件內(nèi)展示豐富的UI,既可以用iframe展示線上web網(wǎng)頁,也可以在插件內(nèi)部用vsode ui實現(xiàn)。下面我主要演示用iframe的方式,另一種嵌入方式推薦大家去看一下 CodeGeeX 插件[4]源碼如何做的,引入了一套vscode風(fēng)格的UI組件@vscode/webview-ui-toolkit,源碼里面的webviewUI文件夾與translationWebviewProvider.ts文件都是相關(guān)代碼。

          1. 新建vue3+vite+ts項目

          找一個舒服的文件夾,打開cmd

              npm init vite

          執(zhí)行后按需選擇自己的框架與開發(fā)環(huán)境,然后run dev一下子,拿到地址, 比如 http://localhost:5173/

          2. 將web頁面展示在vscode側(cè)邊欄

          (1) 插件項目修改,把視圖注冊到側(cè)邊欄,完成消息傳遞

          第一步當(dāng)然是先建一個iframe把我們的web項目的地址填進(jìn)去唄,開始。

          vscode 提供了兩種創(chuàng)建iframe的方法,WebviewViewProvider 和 createWebviewPanel,選其一即可,這里我們介紹一下WebviewViewProvider如何使用

          首先在extension.ts 同級目錄下新建 chatWebview.ts

          • WebviewViewProvider 是一個接口,因此建一個自己的類實現(xiàn)它的方法即可下面我們創(chuàng)建一個實現(xiàn)WebviewViewProvider接口的類ChatWebview

            chatWebview.ts 文件: (可直接運行)
            具體代碼作用看注釋

          import { window, Position, WebviewView, WebviewViewProvider } from "vscode";
          export class ChatWebview implements WebviewViewProvider {
            // 寫一個public變量,方便對象引用創(chuàng)建后的webview實例,但是可能存在還未完全解析完成時,訪問值為null
            // 看了vscode api發(fā)現(xiàn),resolveWebView 返回一個 Thenable,可以在解析完成后拿到webview實例
            // 但是這個函數(shù)是在webview容器第一次顯示時自動執(zhí)行,不需要手動調(diào)用,不知道怎么拿到Thenable
            public webview: WebviewView | null = null;
            resolveWebviewView(webviewView: WebviewView): void | Thenable<void> {
              this.webview = webviewView;
              webviewView.webview.options = {
                enableScripts: true,
              };
              // 監(jiān)聽web端傳來的消息
              webviewView.webview.onDidReceiveMessage((message) => {
                switch (message.command) {
                  case "WebSendMesToVscode":
                    // 實現(xiàn)一個簡單的功能,將web端傳遞過來的消息插入到當(dāng)前活動編輯器中
                    let editor = window.activeTextEditor;
                    editor?.edit((edit) => {
                      let position = editor?.selection
                        ? editor?.selection.start
                        : new Position(00);
                      edit.insert(position, message.data);
                    });
                    return;
                }
              }, undefined);
              // webview 展示的內(nèi)容本身就是嵌套在一個iframe中,因此在此html中再嵌套一個iframe時,需要傳遞兩次postMessage
              webviewView.webview.html = `
              <!DOCTYPE html>
                <html lang="en">
                <head>
                  <meta charset="UTF-8">
                  <meta http-equiv="X-UA-Compatible" content="IE=edge">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <style>
                  html,
                  body {
                      margin: 0;
                      padding: 0;
                      width: 100%;
                      height: 100%;
                      background-color:#000000;
                      overflow:hidden;
                  }
                  .webView_iframe {
                      width: 100%;
                      height: 100%;
                      border: none;
                  }
                  .outer{
                    width: 100%;
                    height: 100%;
                    overflow: hidden;
                  }
                </style>
              </head>
              <body>
                <script>
                
                console.log('Hello from the webview!');
                // 向vscode 傳遞消息的固定寫法, vscode 為我們封裝好了postMessage
                const vscode = acquireVsCodeApi();
                // 接收來自web頁面的消息
                window.addEventListener('message', event => {
                    const message = event.data;
                    switch (message.command) {
                         // 插件傳遞消息給web端
                        case 'vscodeSendMesToWeb':
                            let iframe = document.getElementById('WebviewIframe')
                            WebviewIframe.contentWindow.postMessage(message, "*")
                            console.log("fromWebViewIframe: "+message.data)
                            break;
                        // web端發(fā)送消息給插件
                        case 'WebSendMesToVscode':
                              vscode.postMessage(message);
                              break;
                    }
                });

               </script>
                  <div class="outer">
                     <iframe id='WebviewIframe' class="webView_iframe" sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads" allow="cross-origin-isolated; clipboard-read; clipboard-write;" src="http://localhost:5173/"></iframe>
                  </div>
              </body>
              </html>
              `
          ;
            }
          }

          提供webview視圖的類創(chuàng)建好了,然后我們需要在入口函數(shù)中實例化一個webview,然后把這個視圖注冊到vscode側(cè)邊欄中

          打開extension.ts文件,修改如下 (代碼可直接運行)

          // The module 'vscode' contains the VS Code extensibility API
          // Import the module and reference it with the alias vscode in your code below
          import * as vscode from "vscode";
          import { ChatWebview } from "./chatWebview";
          // This method is called when your extension is activated
          // vscode 插件入口函數(shù),當(dāng)插件第一次加載時會執(zhí)行activate
          export function activate(context: vscode.ExtensionContext{
            console.log('Congratulations, your extension "Chat" is now active!');

            // 實現(xiàn)側(cè)邊欄的初始化
            // 實例化一個chatWebview
            const chatWebview = new ChatWebview();
            // 注冊webview 到id為 Chat-sidebar 的views中,這個id為 Chat-sidebar 的視圖我們稍后會在
            // package.json 中聲明,先理解為我們要把iframe渲染在那個地方(側(cè)邊欄還是標(biāo)簽頁)需要在
            // packagea.json 中控制
            context.subscriptions.push(
              vscode.window.registerWebviewViewProvider("Chat-sidebar", chatWebview, {
                webviewOptions: {
                  // 這是一個比較有用的配置項,可以確保你的插件在不可見時不會被銷毀,建議開啟,否側(cè)每次打開都會重新加載一次插件
                  retainContextWhenHidden: true,
                },
              })
            );
            // 這里實現(xiàn)了一個簡單的功能,在vscode打開的文件中,選中代碼時會實時展示在web頁面上
            // 監(jiān)聽用戶選中文本事件
            vscode.window.onDidChangeTextEditorSelection((event) => {
              const editor = event.textEditor;
              let document = editor.document;
              let selection = editor.selection;
             // 獲取當(dāng)前窗口的文本
              let text = document.getText(selection);
              // 上文提到chatWebview可能為null 因此需要可選鏈寫法,所以這里存在不穩(wěn)定性,不過測試沒問題~
              chatWebview?.webview?.webview.postMessage({
                // 第一次postMessage,下一次在chatWebview文件的iframe中 
                command: "vscodeSendMesToWeb",
                data: text,
              });
            });
          }

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

          至此,我們實例化了ChatWebview,并將其與視圖Chat-siderbar綁定

          下面我們需要在package.json中將視圖注冊到側(cè)邊欄中,并指定名字,圖標(biāo)等 打開package.json 文件,修改如下 將原本的 contributes 字段替換一下

          確保activitybar 中的id,在views中有對應(yīng)的視圖,我們這里id是Chat-sidebar-view,在views就要有對應(yīng)名字的視圖, 并且該視圖 Chat-sidebar-view 的id為我們 ChatWebview 綁定的視圖id

          "contributes": {
              "commands": [],
              "viewsContainers": {
                "activitybar": [
                  {
                    "id""Chat-sidebar-view",
                    "title""Chat",
                    "icon""images/vite.svg"
                  }
                ]
              },
              "views": {
                "Chat-sidebar-view": [
                  {
                    "type""webview",
                    "id""Chat-sidebar",
                    "name"" Chat",
                    "icon""images/vite.svg",
                    "contextualTitle""Chat"
                  }
                ]
              }
            },

          至此!我們的視圖和雙向通訊在插件側(cè)已經(jīng)完成了,我們試一下!直接F5運行,打開拓展開發(fā)宿主

          image.png

          點擊左側(cè)欄圖標(biāo),會看見我們deweb頁面加載出來啦!
          再試一下選中文本的事件和postMessage通訊,點擊上方help,選擇倒數(shù)第三個Toggle developer tools或者按ctrl+shift+i 可以打開谷歌開發(fā)者工具,調(diào)試vscode

          隨便打開一個項目文件,在窗口中選中文本,會發(fā)現(xiàn)控制臺一直在輸出 fromWebViewIframe: ...... ,我們第一步通訊通了,下面在vue項目中加一下消息接收和發(fā)送。

          (2) web項目修改,增加事件監(jiān)聽

          打開index.html,增加message的監(jiān)聽,收到消息時插入到container中

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <link rel="icon" type="image/svg+xml" href="/vite.svg" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>Vite + Vue + TS</title>
            </head>
            <body>
              <div id="app"></div>
              <script type="module" src="/src/main.ts"></script>
              <script type="module">
                window.addEventListener("message", (event) => {
                  const message = event.data;
                  switch (message.command) {
                    case "vscodeSendMesToWeb":
                      const div = document.getElementById("container");
                      div.innerHTML = message.data;
                      break;
                  }
                });
              
          </script>
            </body>
          </html>

          我們試一下,在拓展開發(fā)宿主中選中文本,會實時展示在頁面上!

          image.png

          下面我們發(fā)送消息試一下 簡單修改一下 HellowWord.vue 組件,增加一個sendMessage 方法

          <script setup lang="ts">
          import { ref } from "vue";

          defineProps<{ msg: string }>();

          const count = ref(0);

          const sendMessage = () => {
            window.parent.postMessage(
              {
                command: "WebSendMesToVscode",
                data: "this message is from vue3",
              },
              "*"
            );
          };
          </script>

          <template>
            <h1>{{ msg }}</
          h1>

            <div class="card">
              <button type="button" @click="sendMessage">click</button>
              <p>
                Edit
                <code>components/
          HelloWorld.vue</code> to test HMR
              </
          p>
            </div>

            <p>
              Check out
              <a href="https://vuejs.org/gui
          de/quick-start.html#local" target="_blank"
                >create-vue</a
              >, the official Vue + Vite starter
            </p>
            <p>
              Install
              <a href="
          https://github.com/vuejs/language-tools" target="_blank">Volar</a>
              in your IDE for a better DX
            </p>
            <p class="read-the-docs">Click on the Vite and Vue logos to learn more</
          p>
          </template>

          <style scoped>
          .read-the-docs {
            color: #888;
          }
          </
          style>

          我們點擊一下按鈕,會發(fā)現(xiàn)在當(dāng)前文件光標(biāo)處插入了一條信息。this message is from vue3!

          到此我們的小插件展示出來了,也實現(xiàn)了數(shù)據(jù)互通。下面我們實現(xiàn)一個簡單對話UI,并接入百度文心一言大模型,做一個自己的插件小助手,如果他能記住我們之前問過的代碼,并幫我們舉一反三,并提醒我們查漏補缺就好了。

          四:接入大模型對話能力,實現(xiàn)ChatUI

          1. 大模型接入準(zhǔn)備

          我分別注冊了智譜清言(chatGLM)與文心一言(ERNIE-Bot),發(fā)現(xiàn)兩者都有基礎(chǔ)的免費額度,前者相對于后者代碼能力貌似更強一些,我們這里做一個簡單類似于代碼錯題本的對話助手,就接入文心一言吧

          首先我們要去官網(wǎng)[5],注冊一下開發(fā)者賬號,并且實名認(rèn)證 整個過程很簡單,然后我們看一下api 文檔[6]

          下面我把主要步驟說一下 首先我們要創(chuàng)建一個自己的應(yīng)用,獲取到Secret KeyAPI Key

          進(jìn)入下面頁面,點擊創(chuàng)建應(yīng)用,輸入應(yīng)用名稱和應(yīng)用描述直接確定即可,然后會有一個應(yīng)用生成,里面就有我們的Secret KeyAPI Key

          我們要拿這兩個key,去獲取 access_token 和 refresh_token, 用于JWT鑒權(quán),有兩種方式,其一我們可以在網(wǎng)頁中訪問一下拿到一次性30天的access_token用于臨時測試,其二最好在項目http請求前自動用refresh_token去獲取access_token

          下面我們訪問一下這個地址,當(dāng)然你要把雙key換成你自己的應(yīng)用的~!https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=你的key&client_secret=你的key

          直接用瀏覽器訪問一下呢,然后就在請求里拿到了access_token (不能有小可愛找不到吧~) 拿到token了我們來這里測試一下 測試地址[7]

          填入標(biāo)出的這兩項,第二項示例如下

          [
            {
              "role""user",
              "content""介紹一下自己"
            },
          ]

          可以看到接口調(diào)用結(jié)果

          image.png

          2. nodejs調(diào)用api

          首先找一個舒服的文件夾,新建一個node項目,我們這里選用express框架,可以參考我這里的命令行

          image.png

          npm init 后會生成一個package.json,然后我們安裝一下常用包
          npm install express sequelize mysql2 axios body-parser cors --save 之后就可以在vscode中打開我們的項目了,我們先新建一個server.js,作為我們的入口文件,再建一個chat.js 作為我們的大模型調(diào)用文件

          兩個文件代碼如下,具體解析見注釋,可以直接復(fù)制過去,然后在控制臺執(zhí)行node server.js 直接啟動服務(wù)~

          //server.js
          const Conversation = require("./chat.js");
          const express = require("express");
          const bodyParser = require("body-parser");
          const cors = require("cors");

          const app = express();
          // 暫時允許所有跨域請求
          let corsOptions = {
            origin"*",
          };
          app.use(cors(corsOptions));
          // content-type:application/json
          app.use(bodyParser.json());
          // content-type:application/x-www-form-urlencoded
          app.use(bodyParser.urlencoded({ extendedtrue }));
          // 對話類
          const conversation = new Conversation();
          // 定義/chat路由處理POST請求
          app.post("/chat"async (req, res) => {
            const { messages = "" } = req.body || {};
            if (typeof messages !== "string") {
              return res.status(400).send({ error"Invalid messages type" });
            }
            try {
              // 調(diào)用ask方法獲取大模型結(jié)果
              const response = await conversation.ask(messages);
              return res.status(200).send({ message: response });
            } catch (error) {
              return res.status(500).send({ error: error.messages });
            }
          });
          // 設(shè)置監(jiān)聽端口
          const PORT = process.env.PORT || 8080;
          app.listen(PORT, () => {
            console.log(`服務(wù)器運行端口: ${PORT}.`);
          });


          chat.js
          // 訪問模型服務(wù)
          const axios = require("axios");
          // 這里就是你的accessToken,我改了兩個數(shù),所以你得替換成自己的嘍~
          const accessToken =
            "24.88635a1444105db00bb6684c0598a9a3.2542000.1741590285.281335-42231960";
          const ERNIEB4 =
            "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro";
          const ERNIEB =
            "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions";

          class Conversation {
            constructor() {
              // 上下文數(shù)據(jù)存在這里,文心的調(diào)用是需要把所有的歷史對話數(shù)據(jù)全部傳過去,所以上下文窗口大小得注意
              this.messages = [];
            }

            async ask(prompt) {
              // 問句push進(jìn)去
              this.messages.push({ role"user"content: prompt });
              console.log("message" + this.messages[0]);
              try {
                const res = await axios.post(
                  ERNIEB,
                  { messagesthis.messages },
                  { params: { access_token: accessToken } }
                );
                const { data } = res;
                console.log(data);
                // 答案也放進(jìn)去
                this.messages.push({ role"assistant"content: data.result });
                return data.result;
              } catch (error) {
                console.log("調(diào)用模型失敗" + error);
              }
            }
          }
          // 導(dǎo)出函數(shù)
          module.exports = Conversation;

          所以我們的服務(wù)起了嗎?網(wǎng)頁試一下8080唄,通了就可以

          image.png

          下面我們在前端代碼中加一下接口調(diào)用,就大功告成啦!

          想必看到這里你也累了,我們?nèi)フ{(diào)戲一下 Sydney

          image.png

          看來一時半會我們還是不可替代的 o_O

          3. 前端接口調(diào)試

          言歸正傳,我們來增加接口調(diào)用吧,順便畫一個看得過去的UI界面

          先裝一下 npm install @ant-design/icons-vue
          然后把App.vue刪一下

          // app.vue
          <script setup lang="ts">
          import ChatUI from "./components/chatUI.vue";
          </script>

          <template>
            <div class="container">
              <ChatUI /
          >
            </div>
          </
          template>

          <style scoped>
          .container {
            width100%;
            height100%;
          }
          </style>


          無需多言,**chatUI.vue代碼**奉上(主要界面gpt畫的,我加了接口調(diào)用)\

          // chatUI.vue
          <template>
            <div class="chat-container">
              <div class="messages">
                <div
                  v-for="(item, index) in chatList"
                  :key="index"
                  :class="['message', item.type]"
                >

                  <div class="bubble">{{ item.content }}</div>
                  <div class="avatar">
                    <component
                      :is="item.type === 'question' ? UserOutlined : RobotOutlined"
                    />

                  </div>
                </div>
              </div>
              <div class="input-area">
                <a-input
                  v-model:value="inputValue"
                  placeholder="Type a message..."
                  @pressEnter="handleSend"
                />

                <a-button type="primary" @click="handleSend">send</a-button>
              </div>
            </div>

          </template>

          <script setup lang="ts">
          import axios from "axios";
          import { ref } from "vue";
          import { UserOutlined, RobotOutlined } from "@ant-design/i
          cons-vue";
          const inputValue = ref("");
          let chatList = ref<any[]>([]);

          const handleSend = () => {
            const question = inputValue.value.trim();
            if (question) {
              getAnswer(question);
              chatList.value.push({ type: "
          question", content: question });
              inputValue.value = ""; // 清空輸入框
            }
          };
          function getAnswer(question: string) {
            const URL = "
          http://localhost:8080/chat";
            const payload = {
              messages: question,
            };
            sendPost(
              URL,
              payload,
              {},
              (res: any) => {
                console.log(res.data.message);
                chatList.value.push({ type"answer"content: res.data.message });
              },
              (err: any) => {
                console.log(err);
              }
            );
          }

          //post方法
          function sendPost(
            url: string,
            data: any,
            headers = {},
            funcSuccess: any,
            funcError: any
          {
            const headerTem = {
              "content-Type""application/json;charset=UTF-8",
            };
            if (JSON.stringify(headers) != "{}") {
              Object.assign(headerTem, headers);
            }
            axios
              .post(url, data, {
                headers: headerTem,
              })
              .then(function (res{
                console.log("sendPost res info :", res);
                funcSuccess(res);
              })
              .catch((err) => {
                console.log("sendPost err info :" + err);
                if (funcError) {
                  funcError(err);
                }
              });
          }
          </script>

          <style scoped>
          .chat-container {
            min-width: 300px;
            height: 100%;
            display: flex;
            flex-direction: column;
            /
          * background-color: #1e1e1e; */
            border: 1px solid #999;
            border-radius: 8px;
          }

          .messages {
            height: 650px;
            overflow-y: auto;
            padding: 10px;
            display: flex;
            flex-direction: column;
            gap: 10px;
          }
          .bubble {
            color: #333;
            text-align: right;
            margin-right: 8px;
          }
          .input-area {
            display: flex;
          }
          .message {
            display: flex;
            align-items: center;
          }

          .question {
            justify-content: flex-end;
          }

          .answer {
            justify-content: flex-start;
          }
          </
          style>


          這個就是簡單的調(diào)用接口,我就不注釋了,我們試一下接口
          我們在vscode中看一下當(dāng)前效果

          image.png

          還可以吧,也不能要求AI太高,哈哈,我們問幾個問題試試

          image.png

          啊?文心一言還挺強,緊跟時事哦

          所以你的接口通了嗎?通了的話點個贊吧,好人一生平安~
          沒通的話原因有點多,代碼是沒問題的,其他的可以評論區(qū)討論下

          至此我們的聊天小插件算是開發(fā)完成了,我們學(xué)習(xí)了如何創(chuàng)建一個vscode插件,隨后搭建了一個vue3項目展示在了側(cè)邊欄里,然后我們用nodejs接入了文心一言api,前端調(diào)用接口簡單實現(xiàn)了對話功能,希望你看完這篇文章有所收獲,有所感想!

          五:注冊開發(fā)者賬號并發(fā)布插件

          1. 推薦教程

          插件開發(fā)手冊[8]

          根據(jù)教程注冊賬號,拿到自己的Token,通過vsce publish 1.0.x 來更新版本

          2. 增加插件商店圖標(biāo)

          插件商店的圖標(biāo)是通過讀取package.json中的icon來展示的,該字段與publisher同級

          "icon": "images/icon.png",

          3. 前端資源的緩存策略會影響插件web頁面的實時更新

          因為插件實時訪問的前端服務(wù),當(dāng)我們更新前端資源時,當(dāng)然希望插件能同步更新,此時要注意前端資源的緩存策略,最好是配置為 cache-control:no-store no-cache

          六:實戰(zhàn)能力探討(會持續(xù)更新,歡迎探討)

          1. 行內(nèi)提示功能的設(shè)計與實現(xiàn)(InlineCompletionItemProvider[9]

          先說一個思路,就是用InlineCompletionItemProvider實現(xiàn)行內(nèi)提示

          2. SSH 遠(yuǎn)程打開文件能力(使用 remote-ssh 插件提供的命令)

          先說一個思路,就是通過在控制臺執(zhí)行 remote-ssh 的命令 :code --reuse-window vscode-remote://ssh-remote+${hostname}${path} 來實現(xiàn)打開遠(yuǎn)程ssh地址的文件,需要安裝remote-ssh插件

          3. Json 文件可視化編輯(JsonToHtml)

          先說一個思路,就是監(jiān)聽用戶打開文件夾時的事件,然后再窗口中打開一個新的webview,試用了一些jsonToHtml的包不如自己手動格式化,將bool格式化為checkbox等

          作者:零念 

          原文鏈接:https://juejin.cn/post/7298160530291376140

          Node 社群

              
              


          我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進(jìn)行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。

             “分享、點贊、在看” 支持一下


          瀏覽 2051
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  视频久久小说网站 | 三级片毛片视频 | 国产欧美日韩 | 美女AV操逼 | 黄色性爱视频网站 |