added solidity answer and restricted model input to 1000 words

inlinecompletion_update
Stéphane Tetsing 12 months ago
parent ce953750e6
commit 183840f424
  1. 36
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/copilot-suggestion.ts
  2. 7
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/suggestion-service.ts
  3. 16
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/worker.js
  4. 55
      apps/remix-ide/src/app/plugins/solcoderAI.tsx
  5. 16
      libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts
  6. 40
      libs/remix-ui/settings/src/lib/remix-ui-settings.tsx
  7. 4
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  8. 2
      libs/remix-ui/terminal/src/lib/utils/wrapScript.ts

@ -8,14 +8,13 @@ const profile = {
name: 'copilot-suggestion', name: 'copilot-suggestion',
displayName: 'copilot-suggestion', displayName: 'copilot-suggestion',
description: 'Get Solidity suggestions in editor', description: 'Get Solidity suggestions in editor',
methods: ['suggest', 'init', 'uninstall', 'status', 'isActivate', 'useRemoteService', 'discardRemoteService', 'useconfig'], methods: ['suggest', 'init', 'uninstall', 'status', 'isActivate', 'discardRemoteService', 'useconfig'],
version: '0.1.0-alpha', version: '0.1.0-alpha',
maintainedBy: "Remix" maintainedBy: "Remix"
} }
export class CopilotSuggestion extends Plugin { export class CopilotSuggestion extends Plugin {
service: SuggestionService service: SuggestionService
remoteService: string
context: string context: string
ready: boolean ready: boolean
config: { [id: string]: string } config: { [id: string]: string }
@ -23,27 +22,17 @@ export class CopilotSuggestion extends Plugin {
super(profile) super(profile)
this.service = new SuggestionService() this.service = new SuggestionService()
this.context = '' this.context = ''
this.service.events.on('progress', (data) => { this.ready = true // always ready for service
this.emit('loading', data)
})
this.service.events.on('done', (data) => {
})
this.service.events.on('ready', (data) => {
this.ready = true
})
this.config = {} this.config = {}
} }
useRemoteService(service: string) {
this.remoteService = service
}
useconfig(config ){ useconfig(config ){
this.config = config this.config = config
} }
discardRemoteService() { discardRemoteService() {
this.remoteService = null this.ready = false
} }
status () { status () {
@ -65,22 +54,19 @@ export class CopilotSuggestion extends Plugin {
const max_new_tokens = await this.call('settings', 'get', 'settings/copilot/suggest/max_new_tokens') const max_new_tokens = await this.call('settings', 'get', 'settings/copilot/suggest/max_new_tokens')
const temperature = await this.call('settings', 'get', 'settings/copilot/suggest/temperature') const temperature = await this.call('settings', 'get', 'settings/copilot/suggest/temperature')
const options: SuggestOptions = { const options: SuggestOptions = {
do_sample: false, top_k: 50,
top_k: 0, top_p: 0.92,
top_p: 0,
stream_result: false, stream_result: false,
temperature: temperature || 0, temperature: temperature || 0.9,
max_new_tokens: max_new_tokens || 0 max_new_tokens: max_new_tokens || 0
} }
if (this.remoteService) { if (this.ready){
let confs = {context: content, max_new_words: options.max_new_tokens, temperature: options.temperature} const data = await this.call('solcoder', 'code_completion', content.split(" ").slice(-1000).join(" "), options)
// confs = {confs, ...this.config} const parsedData = data[0].trimStart()
const {data} = await axios.post(this.remoteService, confs)
const parsedData = JSON.parse(data).trimStart()
return {output: [{generated_text: parsedData}]} return {output: [{generated_text: parsedData}]}
} else { }else{
return this.service.suggest(this.context ? this.context + '\n\n' + content : content, options) return
} }
} }

@ -1,6 +1,10 @@
import EventEmitter from 'events' import EventEmitter from 'events'
export type SuggestOptions = { max_new_tokens: number, temperature: number, top_k: number, top_p:number, do_sample: boolean, stream_result:boolean} export type SuggestOptions = { max_new_tokens: number,
temperature: number,
top_k: number,
top_p:number,
stream_result:boolean}
export class SuggestionService { export class SuggestionService {
worker: Worker worker: Worker
@ -89,7 +93,6 @@ export class SuggestionService {
max_new_tokens: options.max_new_tokens, max_new_tokens: options.max_new_tokens,
temperature: options.temperature, temperature: options.temperature,
top_k: options.top_k, top_k: options.top_k,
do_sample: options.do_sample
}) })
this.responses[timespan] = (error, result) => { this.responses[timespan] = (error, result) => {
if (error) return reject(error) if (error) return reject(error)

@ -35,12 +35,12 @@ self.addEventListener('message', async (event) => {
if (cmd === 'init') { if (cmd === 'init') {
// Retrieve the code-completion pipeline. When called for the first time, // Retrieve the code-completion pipeline. When called for the first time,
// this will load the pipeline and save it for future use. // this will load the pipeline and save it for future use.
CodeCompletionPipeline.model = model // CodeCompletionPipeline.model = model
await CodeCompletionPipeline.getInstance(x => { // await CodeCompletionPipeline.getInstance(x => {
// We also add a progress callback to the pipeline so that we can // // We also add a progress callback to the pipeline so that we can
// track model loading. // // track model loading.
self.postMessage(x); // self.postMessage(x);
}); // });
return return
} }
@ -48,8 +48,8 @@ self.addEventListener('message', async (event) => {
// Send the output back to the main thread // Send the output back to the main thread
self.postMessage({ self.postMessage({
id, id,
status: 'error', status: 'info',
message: 'model not yet loaded' message: 'model not longer supported'
}); });
} }

@ -1,4 +1,5 @@
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import {SuggestOptions} from './copilot/suggestion-service/suggestion-service'
const _paq = (window._paq = window._paq || []) const _paq = (window._paq = window._paq || [])
@ -6,7 +7,7 @@ const profile = {
name: 'solcoder', name: 'solcoder',
displayName: 'solcoder', displayName: 'solcoder',
description: 'solcoder', description: 'solcoder',
methods: ['code_generation', 'code_completion'], methods: ['code_generation', 'code_completion', "solidity_answer"],
events: [], events: [],
maintainedBy: 'Remix', maintainedBy: 'Remix',
} }
@ -31,6 +32,28 @@ export class SolCoder extends Plugin {
body: JSON.stringify({"data":[prompt,false,1000,0.2,0.8,50]}), body: JSON.stringify({"data":[prompt,false,1000,0.2,0.8,50]}),
}) })
).json() ).json()
return result.data[0]
} catch (e) {
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` })
return
}
}
async solidity_answer(prompt): Promise<any> {
this.call('layout', 'maximizeTerminal')
this.call('terminal', 'log', 'Waiting for Solcoder answer...')
let result
try {
result = await(
await fetch("https://hkfll35zthu6e2-7861.proxy.runpod.net/api/solidity_answer", {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({"data":[prompt,false,1000,0.9,0.8,50]}),
})
).json()
} catch (e) { } catch (e) {
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` }) this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` })
return return
@ -44,7 +67,7 @@ export class SolCoder extends Plugin {
} }
async code_completion(prompt): Promise<any> { async code_completion(prompt, options:SuggestOptions=null): Promise<any> {
let result let result
try { try {
result = await( result = await(
@ -54,19 +77,27 @@ export class SolCoder extends Plugin {
Accept: 'application/json', Accept: 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({"data":[ body: JSON.stringify({"data": !options? [
prompt, // string in 'context_code' Textbox component prompt, // string in 'context_code' Textbox component
"", // string in 'comment' Textbox component "", // string in 'comment' Textbox component
false, // boolean in 'stream_result' Checkbox component false, // boolean in 'stream_result' Checkbox component
200, // number (numeric value between 0 and 2000) in 'max_new_tokens' Slider component 200, // number (numeric value between 0 and 2000) in 'max_new_tokens' Slider component
0.4, // number (numeric value between 0.01 and 1) in 'temperature' Slider component 0.9, // number (numeric value between 0.01 and 1) in 'temperature' Slider component
0.90, // number (numeric value between 0 and 1) in 'top_p' Slider component 0.90, // number (numeric value between 0 and 1) in 'top_p' Slider component
50, // number (numeric value between 1 and 200) in 'top_k' Slider component 50, // number (numeric value between 1 and 200) in 'top_k' Slider component
]}), ] : [
prompt,
"",
options.stream_result,
options.max_new_tokens,
options.temperature,
options.top_p,
options.top_k
]
}),
}) })
).json() ).json()
console.log('solcoder result', result.data)
return result.data return result.data
} catch (e) { } catch (e) {
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` }) this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` })

@ -41,10 +41,9 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
if (split.length < 2) return if (split.length < 2) return
const ask = split[split.length - 2].trimStart() const ask = split[split.length - 2].trimStart()
if (split[split.length - 1].trim() === '' && ask.startsWith('///')) { if (split[split.length - 1].trim() === '' && ask.startsWith('///')) {
// use the code generation model // use the code generation model, only take max 1000 word as context
const data = await this.props.plugin.call('solcoder', 'code_completion', word.split(" ").slice(-1000).join(" "))
const data = await this.props.plugin.call('solcoder', 'code_completion', word) console.log("solcoder completion data", data)
console.log("received solcoder data", data)
const parsedData = data[0].trimStart() //JSON.parse(data).trimStart() const parsedData = data[0].trimStart() //JSON.parse(data).trimStart()
const item: monacoTypes.languages.InlineCompletion = { const item: monacoTypes.languages.InlineCompletion = {
insertText: parsedData insertText: parsedData
@ -62,8 +61,17 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
if (token.isCancellationRequested) { if (token.isCancellationRequested) {
return return
} }
let result
try {
result = await this.props.plugin.call('copilot-suggestion', 'suggest', word)
} catch (err) {
return
}
const generatedText = (result as any).output[0].generated_text as string const generatedText = (result as any).output[0].generated_text as string
let clean = generatedText let clean = generatedText
console.log('solcoder inline data:\n', clean)
const item: monacoTypes.languages.InlineCompletion = { const item: monacoTypes.languages.InlineCompletion = {
insertText: clean insertText: clean

@ -134,41 +134,15 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
copilotActivate(props.config, event.target.checked, dispatch) copilotActivate(props.config, event.target.checked, dispatch)
props.plugin.call('copilot-suggestion', 'uninstall') props.plugin.call('copilot-suggestion', 'uninstall')
return return
} }
const message = <div>Please wait while the copilot is downloaded. <span ref={copilotDownload}>0</span>/100 .</div> if (await props.plugin.call('copilot-suggestion', 'status')) {
props.plugin.on('copilot-suggestion', 'loading', (data) => { copilotActivate(props.config, true, dispatch)
if (!copilotDownload.current) return } else {
const loaded = ((data.loaded / data.total) * 100).toString() props.plugin.call('copilot-suggestion', 'uninstall')
const dot = loaded.match(/(.*)\./g) copilotActivate(props.config, false, dispatch)
copilotDownload.current.innerText = dot ? dot[0].replace('.', '') : loaded
})
const modalActivate: AppModal = {
id: 'loadcopilotActivate',
title: 'Download Solidity copilot',
modalType: ModalTypes.default,
okLabel: 'Close',
message,
okFn: async() => {
props.plugin.off('copilot-suggestion', 'loading')
if (await props.plugin.call('copilot-suggestion', 'status')) {
copilotActivate(props.config, true, dispatch)
} else {
props.plugin.call('copilot-suggestion', 'uninstall')
copilotActivate(props.config, false, dispatch)
}
},
hideFn: async () => {
props.plugin.off('copilot-suggestion', 'loading')
if (await props.plugin.call('copilot-suggestion', 'status')) {
copilotActivate(props.config, true, dispatch)
} else {
props.plugin.call('copilot-suggestion', 'uninstall')
copilotActivate(props.config, false, dispatch)
}
}
} }
props.plugin.call('copilot-suggestion', 'init') props.plugin.call('copilot-suggestion', 'init')
props.plugin.call('notification', 'modal', modalActivate)
} }

@ -239,9 +239,9 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` }) call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('openaigpt', 'message', script) await call('openaigpt', 'message', script)
_paq.push(['trackEvent', 'ai', 'openai', 'askFromTerminal']) _paq.push(['trackEvent', 'ai', 'openai', 'askFromTerminal'])
} else if (script.trim().startsWith('gpt-sol')) { } else if (script.trim().startsWith('sol-gpt')) {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` }) call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('solcoder', 'code_generation', script) await call('solcoder', 'solidity_answer', script)
_paq.push(['trackEvent', 'ai', 'solcoder', 'askFromTerminal']) _paq.push(['trackEvent', 'ai', 'solcoder', 'askFromTerminal'])
}else { }else {
await call('scriptRunner', 'execute', script) await call('scriptRunner', 'execute', script)

@ -1,5 +1,5 @@
export const wrapScript = (script) => { export const wrapScript = (script) => {
const isKnownScript = ['remix.', 'console.', 'git', 'gpt'].some(prefix => script.trim().startsWith(prefix)) const isKnownScript = ['remix.', 'console.', 'git', 'gpt', 'sol-gpt'].some(prefix => script.trim().startsWith(prefix))
if (isKnownScript) return script if (isKnownScript) return script
return ` return `
try { try {

Loading…
Cancel
Save