赞
踩
最近在开发vscode插件相关的项目,网上很少有关于大模型作为AI 编程助手这方面的教程。因此,借此机会把最近写的几个demo分享记录一下。
思路:
下面直接上代码。
extension.ts 文件:
import * as vscode from 'vscode'; import { BaseUrlApiConfiguration, openaicompatible, streamText, } from 'modelfusion'; import{ previewInsertion, getBeforeText, getAfterText }from '../src/main' export function activate(context: vscode.ExtensionContext) { // 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 console.log('Congratulations, your extension "dytest" is now active!'); let globalText:string|undefined ; let globalindex: vscode.Position | undefined; // 如何删除字符 const editor = vscode.window.activeTextEditor; // 代码补全命令 const disposable = vscode.commands.registerCommand('dytest.helloWorld', async () => { if (!editor) { return; } // 代码所在位置 const code =editor.document.getText(); //光标所在位置 const offset =editor.document.offsetAt(editor.selection.active); const index = editor.document.positionAt(offset); const position = editor.selection.active; const document = editor.document; const beforeText = getBeforeText(document, position); const afterText = getAfterText(document, position); // 调用大模型 const code_prompt='提示词'; const code_instruction='{{{prefix}}}[BLANK]{{{suffix}}}'; const code_instruction_2=code_instruction.replace("{{{prefix}}}", beforeText).replace("{{{suffix}}}",afterText) console.log(code_instruction_2) const text2 = await streamText({ model: openaicompatible .ChatTextGenerator({ // 这里使用的是自己部署的大模型,url和openai的一样。但是模型不是用的openai系列的。如果要改,可以换成openai的。 api: new BaseUrlApiConfiguration({ baseUrl: "模型的url", headers: { Authorization: `模型的api`, }, }), provider: "openaicompatible-fireworksai", // optional, only needed for logging and custom configs model: "自己的模型", }) .withInstructionPrompt(), prompt: { system: code_prompt, instruction: code_instruction_2 }, }); let responseUntilNow = ""; for await (const textPart of text2) { // process.stdout.write(textPart); responseUntilNow += textPart; } console.log(responseUntilNow) // 进行代码补全的提示 const previewinsertion =previewInsertion(editor,index,responseUntilNow); globalText=responseUntilNow; globalindex=index vscode.window.showInformationMessage('Hello World from dy_test!'); }); context.subscriptions.push(disposable); const disposable2 = vscode.commands.registerCommand('extension.myCommand', async () => { editor?.edit((editBuilder => { if (!globalindex || !globalText){ return; } const lines = globalText.split(/\r\n|\n/); // 分割文本 editBuilder.insert(globalindex, lines[0]) globalindex=undefined; globalText=undefined; })); vscode.window.showInformationMessage('Hello World from myextension!'); }); let timeout: NodeJS.Timeout | undefined; context.subscriptions.push(disposable2); // 注册事件监听器以在特定条件下调用命令 context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => { if (editor) { // 延迟调用命令 if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { vscode.commands.executeCommand('dytest.helloWorld'); }, 200); // 延迟 } })); context.subscriptions.push(vscode.window.onDidChangeTextEditorSelection(event => { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { vscode.commands.executeCommand('dytest.helloWorld'); }, 200); // 延迟 })); } export function deactivate() {}
main.ts文件:
import {parse}from '@babel/parser' import traverse from '@babel/traverse' import * as vscode from 'vscode'; // 代码补全插入 export function previewInsertion(editor: vscode.TextEditor, position: vscode.Position, text: string, ) { const range = new vscode.Range(position, position.translate({characterDelta: text.length})); let currentDecoration: vscode.DecorationOptions[] | undefined = undefined; let decorationType: vscode.TextEditorDecorationType | undefined = undefined; const lines = text.split(/\r\n|\n/); // 分割文本 let lineCount = 0; let totalCharacterCount = 0; // 计算总行数和总字符数 for (const line of lines) { lineCount++; totalCharacterCount += line.length; } totalCharacterCount--; console.log(lineCount); // 输出非空行数 if (!decorationType) { decorationType = vscode.window.createTextEditorDecorationType({ light: { // Light theme settings after: { contentText: lines[0], fontStyle: 'italic', color: '#7f8c8d', // 灰色 backgroundColor: 'transparent', // textDecoration: 'none', margin: '0 0 0 0', }, }, dark: { // Dark theme settings after: { contentText: lines[0], fontStyle: 'italic', color: '#95a5a6', // 灰色,适合深色主题 backgroundColor: 'transparent', // textDecoration: 'none', margin: '0 0 0 0', }, } }); } const endPosition=position.translate({lineDelta:lineCount-1,characterDelta:totalCharacterCount }) console.log("position:",position) console.log("endPosition:",endPosition) // 创建装饰器选项 currentDecoration = [{ range: new vscode.Range(position, position), hoverMessage: new vscode.MarkdownString('按“tab”键确认'), }]; // 应用装饰器 editor.setDecorations(decorationType, currentDecoration); // 监听鼠标移动事件,移除装饰 const mouseMoveDisposable = vscode.window.onDidChangeTextEditorSelection( (event) => { if (event.textEditor === editor) { editor.setDecorations(decorationType, []); currentDecoration = undefined; } }, null, ); } // 获取文本上下文信息 export function getBeforeText(document: vscode.TextDocument, position: vscode.Position): string { const range = new vscode.Range(new vscode.Position(0, 0), position); return document.getText(range); } export function getAfterText(document: vscode.TextDocument, position: vscode.Position): string { const lastLine = document.lineCount - 1; const lastLineLength = document.lineAt(lastLine).text.length; const range = new vscode.Range(position, new vscode.Position(lastLine, lastLineLength)); return document.getText(range); }
package.json
添加两个命令
"commands": [
{
"command": "dytest.helloWorld",
"title": "Hello World"
},
{ "command": "extension.myCommand",
"title": "My Command"
}
]
快捷键
"keybindings": [
{
"command": "extension.myCommand",
"key": "ctrl+shift",
"when": "editorTextFocus"
}
]
实现效果:
代码补全(2)
目前遇到的问题:函数级代码生成后,通过Decoration装饰器无法显示全部的。希望有大佬指点一下。
async function baiduSearch(query, page = 1) { const start = (page - 1) * 10; const encodedQuery = encodeURIComponent(query); const url = `https://www.abd.com/s?wd=${encodedQuery}&pn=${start}`; try { const response = await axios.get(url); if (response.status === 200) { // 假设你想解析返回的HTML并获取搜索结果 const html = response.data; console.log(html) // 这里你可以使用cheerio或类似的库来解析HTML // 并从中抽取你需要的信息 } else { console.error(`Request failed with status ${response.status}`); } } catch (error) { console.error(error); } } // 使用函数 baiduSearch('阿里巴巴');
import Exa from "exa-js"; // 根据输入的关键词到搜索引擎中进行查询,然后通过LLM得到所需要的信息。 async function ExaSearch(topic=null,numresults=null,categorys=null,includehtmltag=null,maxcharacters=1024,startpublisheddate=null,endpublisheddate=null,startcrawldate=null,endcrawldate=null) { const exa = new Exa("null"); const result = await exa.searchAndContents( topic, { type: "neural", useAutoprompt: true, numResults: numresults, text: { includeHtmlTags: includehtmltag, maxCharacters: maxcharacters }, startPublishedDate:startpublisheddate, endPublishedDate: endpublisheddate, startCrawlDate: startcrawldate, endCrawlDate: endcrawldate, category: categorys } ) console.log(result); const text= JSON.stringify(extractAllValues(result));// 解析网页返回的json格式中的所有的文本内容。 console.log(text); const model=直接使用modelfusion中的模型进行调用。 const prompt =null; prompt.replace('${topic}', topic) const engeernering = await generateText({ model, prompt: { system: prompt, // optional instruction: text, }, }); // console.log(test) console.log("engeernering: ",engeernering); // extract the topic from the text: return engeernering } const startPublishedDate="2024-01-01T06:31:37.881Z"; const endPublishedDate= "2024-07-29T06:31:37.881Z"; const startCrawlDate="2024-01-01T06:31:37.881Z"; const endCrawlDate= "2024-07-29T06:31:37.881Z"; const query= "找一下agent相关的文章。" const categorys='research paper' ExaSearch(query,2,categorys,null,1024,startPublishedDate,endPublishedDate,startCrawlDate,endCrawlDate)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。