Merge pull request #4809 from ethereum/ask_sol_gpt

switched open gpt to solcoder for error explaining
pull/4865/head
Aniket 5 months ago committed by GitHub
commit 2a4235b78a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      apps/circuit-compiler/src/app/components/container.tsx
  2. 2
      apps/circuit-compiler/src/app/components/feedbackAlert.tsx
  3. 6
      apps/remix-ide/src/app.js
  4. 49
      apps/remix-ide/src/app/plugins/openaigpt.tsx
  5. 44
      apps/remix-ide/src/app/plugins/solcoderAI.tsx
  6. 1
      apps/remix-ide/src/remixAppManager.js
  7. 1
      apps/remix-ide/src/remixEngine.js
  8. 2
      apps/vyper/src/app/components/CompileErrorCard.tsx
  9. 4
      apps/vyper/src/app/utils/remix-client.tsx
  10. 3
      libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts
  11. 8
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  12. 6
      libs/remix-ui/renderer/src/lib/renderer.tsx
  13. 5
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  14. 3
      libs/remix-ui/terminal/src/lib/terminalWelcome.tsx

@ -73,7 +73,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
} else {
const message = `
error message: ${error}
@ -81,7 +81,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
}
} else {
const error = report.message
@ -91,7 +91,7 @@ export function Container () {
explain why the error occurred and how to fix it.
`
// @ts-ignore
await circuitApp.plugin.call('openaigpt', 'message', message)
await circuitApp.plugin.call('solcoder', 'error_explaining', message)
}
}

@ -24,7 +24,7 @@ export function FeedbackAlert ({ message, askGPT }: FeedbackAlertProps) {
<span className="border border-success text-success btn-sm" onClick={(e) => {
e.stopPropagation()
askGPT()
}}>ASK GPT</span>
}}>Ask RemixAI</span>
</div>
</>
</RenderIf>

@ -54,8 +54,6 @@ import { electronTemplates } from './app/plugins/electron/templatesPlugin'
import { xtermPlugin } from './app/plugins/electron/xtermPlugin'
import { ripgrepPlugin } from './app/plugins/electron/ripgrepPlugin'
import { compilerLoaderPlugin, compilerLoaderPluginDesktop } from './app/plugins/electron/compilerLoaderPlugin'
import {OpenAIGpt} from './app/plugins/openaigpt'
import {SolCoder} from './app/plugins/solcoderAI'
const isElectron = require('is-electron')
@ -233,7 +231,6 @@ class AppComponent {
const contractFlattener = new ContractFlattener()
// ----------------- AI --------------------------------------
const openaigpt = new OpenAIGpt()
const solcoder = new SolCoder()
// ----------------- import content service ------------------------
@ -352,7 +349,6 @@ class AppComponent {
contractFlattener,
solidityScript,
templates,
openaigpt,
solcoder,
pluginStateLogger
])
@ -512,7 +508,7 @@ class AppComponent {
await this.appManager.registerContextMenuItems()
}
)
await this.appManager.activatePlugin(['solidity-script', 'openaigpt'])
await this.appManager.activatePlugin(['solidity-script'])
await this.appManager.activatePlugin(['solcoder'])

@ -1,49 +0,0 @@
import { Plugin } from '@remixproject/engine'
import { CreateChatCompletionResponse } from 'openai'
const _paq = (window._paq = window._paq || [])
const profile = {
name: 'openaigpt',
displayName: 'openaigpt',
description: 'openaigpt',
methods: ['message'],
events: [],
maintainedBy: 'Remix',
}
export class OpenAIGpt extends Plugin {
constructor() {
super(profile)
}
async message(prompt): Promise<CreateChatCompletionResponse> {
this.call('layout', 'maximizeTerminal')
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: 'Waiting for GPT answer...' })
let result
try {
result = await (
await fetch('https://openai-gpt.remixproject.org', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ prompt }),
})
).json()
} catch (e) {
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` })
return
}
if (result && result.choices && result.choices.length) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: result.choices[0].message.content })
} else if (result.error) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: result.error })
} else {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: 'No response...' })
}
return result.data
}
}

@ -15,7 +15,7 @@ const profile = {
name: 'solcoder',
displayName: 'solcoder',
description: 'solcoder',
methods: ['code_generation', 'code_completion', "solidity_answer", "code_explaining", "code_insertion"],
methods: ['code_generation', 'code_completion', "solidity_answer", "code_explaining", "code_insertion", "error_explaining"],
events: [],
maintainedBy: 'Remix',
}
@ -50,6 +50,8 @@ export class SolCoder extends Plugin {
async code_generation(prompt): Promise<any> {
this.emit("aiInfering")
this.call('layout', 'maximizeTerminal')
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_generation'])
let result
try {
result = await(
@ -78,6 +80,9 @@ export class SolCoder extends Plugin {
async solidity_answer(prompt): Promise<any> {
this.emit("aiInfering")
this.call('layout', 'maximizeTerminal')
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: `\n\nWaiting for RemixAI answer...` })
_paq.push(['trackEvent', 'ai', 'solcoder', 'answering'])
let result
try {
const main_prompt = this._build_solgpt_promt(prompt)
@ -112,6 +117,9 @@ export class SolCoder extends Plugin {
async code_explaining(prompt, context:string=""): Promise<any> {
this.emit("aiInfering")
this.call('layout', 'maximizeTerminal')
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: `\n\nWaiting for RemixAI answer...` })
_paq.push(['trackEvent', 'ai', 'solcoder', 'explaining'])
let result
try {
result = await(
@ -138,6 +146,8 @@ export class SolCoder extends Plugin {
async code_completion(prompt, options:SuggestOptions=null): Promise<any> {
this.emit("aiInfering")
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_completion'])
let result
try {
result = await(
@ -184,6 +194,8 @@ export class SolCoder extends Plugin {
async code_insertion(msg_pfx, msg_sfx): Promise<any> {
this.emit("aiInfering")
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_insertion'])
let result
try {
result = await(
@ -218,6 +230,36 @@ export class SolCoder extends Plugin {
}
}
async error_explaining(prompt): Promise<any> {
this.emit("aiInfering")
this.call('layout', 'maximizeTerminal')
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: `\n\nWaiting for RemixAI answer...` })
_paq.push(['trackEvent', 'ai', 'solcoder', 'explaining'])
let result
try {
result = await(
await fetch(this.api_url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ "data":[prompt, "error_explaining", false,2000,0.9,0.8,50]}),
})
).json()
if (result) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: result.data[0] })
}
return result.data[0]
} catch (e) {
this.call('terminal', 'log', { type: 'typewritererror', value: `Unable to get a response ${e.message}` })
return
} finally {
this.emit("aiInferingDone")
}
}
_build_solgpt_promt(user_promt:string){
if (this.solgpt_chat_history.length === 0){
return user_promt

@ -71,7 +71,6 @@ let requiredModules = [ // services + layout views + system views
'vyperCompilationDetails',
'contractflattener',
'solidity-script',
'openaigpt',
'solcoder',
'home',
'doc-viewer',

@ -26,7 +26,6 @@ export class RemixEngine extends Engine {
if (name === 'compilerloader') return { queueTimeout: 60000 * 4 }
if (name === 'filePanel') return { queueTimeout: 60000 * 20 }
if (name === 'fileManager') return { queueTimeout: 60000 * 20 }
if (name === 'openaigpt') return { queueTimeout: 60000 * 2 }
if (name === 'solcoder') return { queueTimeout: 60000 * 2 }
if (name === 'cookbookdev') return { queueTimeout: 60000 * 3 }
return { queueTimeout: 10000 }

@ -21,7 +21,7 @@ export function CompileErrorCard(props: { output: any, plugin: RemixClient }) {
<div className="d-flex flex-column pt-3 align-items-end mb-2">
<div>
<span className="border border-ai text-ai btn-sm" onClick={async () => await props.plugin.askGpt(props.output.message)}>
Ask GPT
Ask RemixAI
</span>
<span className="ml-3 pt-1 py-1">
<CopyToClipboard content={props.output.message} className={`p-0 m-0 far fa-copy alert alert-danger`} direction={'top'} />

@ -6,7 +6,6 @@ import {Contract, compileContract} from './compiler'
import {ExampleContract} from '../components/VyperResult'
import EventEmitter from 'events'
export type VyperComplierAddress = 'https://vyper2.remixproject.org/' | 'http://localhost:8000/'
export class RemixClient extends PluginClient {
private client = createClient<Api, Readonly<RemixApi>>(this)
@ -66,11 +65,12 @@ export class RemixClient extends PluginClient {
return
}
try {
// TODO: remove! no formatting required since already handled on server
const formattedMessage = `
${message}
can you explain why this error occurred and how to fix it?
`
await this.client.call('openaigpt' as any, 'message', formattedMessage)
await this.client.call('solcoder' as any, 'error_explaining', message)
} catch (err) {
console.error('unable to askGpt')
console.error(err)

@ -66,7 +66,6 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
this.props.plugin.call('terminal', 'log', { type: 'aitypewriterwarning', value: 'Solcoder - generating code for following comment: ' + ask.replace('///', '') })
const data = await this.props.plugin.call('solcoder', 'code_generation', word)
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_generation'])
const parsedData = data[0].trimStart() //JSON.parse(data).trimStart()
const item: monacoTypes.languages.InlineCompletion = {
@ -105,7 +104,6 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
// Code insertion
try {
const output = await this.props.plugin.call('solcoder', 'code_insertion', word, word_after)
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_insertion'])
const generatedText = output[0] // no need to clean it. should already be
const item: monacoTypes.languages.InlineCompletion = {
@ -130,7 +128,6 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
try {
// Code completion
const output = await this.props.plugin.call('solcoder', 'code_completion', word)
_paq.push(['trackEvent', 'ai', 'solcoder', 'code_completion'])
const generatedText = output[0]
let clean = generatedText

@ -723,8 +723,8 @@ export const EditorUI = (props: EditorUIProps) => {
const file = await props.plugin.call('fileManager', 'getCurrentFile')
const content = await props.plugin.call('fileManager', 'readFile', file)
const message = intl.formatMessage({ id: 'editor.generateDocumentationByAI' }, { content, currentFunction: currentFunction.current })
await props.plugin.call('openaigpt', 'message', message)
_paq.push(['trackEvent', 'ai', 'openai', 'generateDocumentation'])
await props.plugin.call('solcoder', 'code_explaining', message)
_paq.push(['trackEvent', 'ai', 'solcoder', 'generateDocumentation'])
},
}
@ -739,8 +739,8 @@ export const EditorUI = (props: EditorUIProps) => {
const file = await props.plugin.call('fileManager', 'getCurrentFile')
const content = await props.plugin.call('fileManager', 'readFile', file)
const message = intl.formatMessage({ id: 'editor.explainFunctionByAI' }, { content, currentFunction: currentFunction.current })
await props.plugin.call('openaigpt', 'message', message)
_paq.push(['trackEvent', 'ai', 'openai', 'explainFunction'])
await props.plugin.call('solcoder', 'code_explaining', message, content)
_paq.push(['trackEvent', 'ai', 'solcoder', 'explainFunction'])
},
}

@ -75,8 +75,8 @@ export const Renderer = ({ message, opt = {}, plugin }: RendererProps) => {
try {
const content = await plugin.call('fileManager', 'readFile', editorOptions.errFile)
const message = intl.formatMessage({ id: 'solidity.openaigptMessage' }, { content, messageText })
await plugin.call('openaigpt', 'message', message)
_paq.push(['trackEvent', 'ai', 'openai', 'explainSolidityError'])
await plugin.call('solcoder', 'error_explaining', message)
_paq.push(['trackEvent', 'ai', 'solcoder', 'error_explaining_SolidityError'])
} catch (err) {
console.error('unable to askGtp')
console.error(err)
@ -111,7 +111,7 @@ export const Renderer = ({ message, opt = {}, plugin }: RendererProps) => {
onClick={() => { askGtp() }}
style={{ borderColor: "var(--ai)" }}
>
ASK GPT
Ask RemixAI
</span>
</div>

@ -235,10 +235,11 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
try {
if (script.trim().startsWith('git')) {
// await this.call('git', 'execute', script) code might be used in the future
// TODO: rm gpt or redirect gpt to sol-pgt
} else if (script.trim().startsWith('gpt')) {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('openaigpt', 'message', script)
_paq.push(['trackEvent', 'ai', 'openai', 'askFromTerminal'])
await call('solcoder', 'solidity_answer', script)
_paq.push(['trackEvent', 'ai', 'solcoder', 'askFromTerminal'])
} else if (script.trim().startsWith('sol-gpt')) {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('solcoder', 'solidity_answer', script)

@ -54,9 +54,6 @@ const TerminalWelcomeMessage = ({ packageJson, storage }) => {
ethers.js
</a>{' '}
</li>
<li key="gpt">
gpt <i>&lt;your question here&gt;</i> {' '}
</li>
<li key="sol-gpt">
sol-gpt <i>&lt;your Solidity question here&gt;</i> {' '}
</li>

Loading…
Cancel
Save