move service and add settings

pull/5370/head
yann300 1 year ago
parent b6b95aaedd
commit 0d92648e96
  1. 7
      apps/remix-ide/src/app.js
  2. 44
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/copilot-suggestion.ts
  3. 14
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/suggestion-service.ts
  4. 0
      apps/remix-ide/src/app/plugins/copilot/suggestion-service/worker.js
  5. 1
      apps/remix-ide/src/app/tabs/settings-tab.tsx
  6. 16
      libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts
  7. 76
      libs/remix-ui/settings/src/lib/remix-ui-settings.tsx
  8. 15
      libs/remix-ui/settings/src/lib/settingsAction.ts
  9. 45
      libs/remix-ui/settings/src/lib/settingsReducer.ts

@ -56,6 +56,7 @@ const remixLib = require('@remix-project/remix-lib')
import {QueryParams} from '@remix-project/remix-lib'
import {SearchPlugin} from './app/tabs/search'
import { SuggestionService } from './app/plugins/copilot/suggestion-service/suggestion-service'
const Storage = remixLib.Storage
const RemixDProvider = require('./app/files/remixDProvider')
@ -186,8 +187,9 @@ class AppComponent {
// ----------------- ContractFlattener ----------------------------
const contractFlattener = new ContractFlattener()
// ----------------- Open AI --------------------------------------
// ----------------- AI --------------------------------------
const openaigpt = new OpenAIGpt()
const copilotSuggestion = new SuggestionService()
// ----------------- import content service ------------------------
const contentImport = new CompilerImports()
@ -310,7 +312,8 @@ class AppComponent {
compilationDetails,
contractFlattener,
solidityScript,
openaigpt
openaigpt,
copilotSuggestion
])
// LAYOUT & SYSTEM VIEWS

@ -0,0 +1,44 @@
import {Plugin} from '@remixproject/engine'
import {SuggestionService, SuggestOptions} from './suggestion-service'
const _paq = (window._paq = window._paq || []) //eslint-disable-line
const profile = {
name: 'copilot-suggestion',
displayName: 'copilot-suggestion',
description: 'copilot-suggestion',
methods: ['suggest']
}
export class CopilotSuggestion extends Plugin {
service: SuggestionService
constructor() {
super(profile)
this.service = new SuggestionService()
this.service.events.on('progress', (data) => {
this.call('terminal', 'log', {type: 'info', value: `loading Solidity copilot: ${(data.loaded / data.total) * 100}% done.` })
})
this.service.events.on('done', (data) => {
this.call('terminal', 'log', { type: 'info', value: `Solidity copilot loaded.`})
})
this.service.events.on('ready', (data) => {
this.call('terminal', 'log', { type: 'info', value: `Solidity copilot ready to use.`})
})
}
async suggest(content: string) {
const options: SuggestOptions = {
do_sample: false,
top_k: 0,
temperature: await this.call('settings', 'get', 'settings/copilot/suggest/temperature'),
max_new_tokens: await this.call('settings', 'get', 'settings/copilot/suggest/max_new_tokens')
}
return this.service.suggest(content, options)
}
async init() {
return this.service.init()
}
async uninstall() {
}
}

@ -1,15 +1,15 @@
import EventEmitter from 'events'
export type SuggestOptions = { max_new_tokens: number, temperature: number, top_k: number, do_sample: boolean }
export class SuggestionService {
worker: Worker
responses: Array<any>
events: EventEmitter
constructor() {
console.log('SuggestionService instanciate worker')
this.worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module'
});
this.init()
this.events = new EventEmitter()
this.responses = []
}
@ -69,16 +69,16 @@ export class SuggestionService {
})
}
suggest (content: string, max_new_tokens: number, temperature: number, top_k: number, do_sample: boolean) {
suggest (content: string, options: SuggestOptions) {
return new Promise((resolve, reject) => {
this.worker.postMessage({
id: this.responses.length,
cmd: 'suggest',
text: content,
max_new_tokens,
temperature,
top_k,
do_sample
max_new_tokens: options.max_new_tokens,
temperature: options.temperature,
top_k: options.top_k,
do_sample: options.do_sample
})
this.responses.push((error, result) => {
if (error) return reject(error)

@ -63,6 +63,7 @@ module.exports = class SettingsTab extends ViewPlugin {
updateComponent(state: any) {
return (
<RemixUiSettings
plugin={this}
config={state.config}
editor={state.editor}
_deps={state._deps}

@ -1,5 +1,4 @@
import { EditorUIProps, monacoTypes } from '@remix-ui/editor';
import { SuggestionService } from '../suggestion-service/suggestion-service'
const controller = new AbortController();
const { signal } = controller;
const result: string = ''
@ -7,20 +6,9 @@ const result: string = ''
export class RemixInLineCompletionProvider implements monacoTypes.languages.InlineCompletionsProvider {
props: EditorUIProps
monaco: any
suggestionService: SuggestionService
constructor(props: any, monaco: any) {
this.props = props
this.monaco = monaco
this.suggestionService = new SuggestionService()
this.suggestionService.events.on('progress', (data) => {
this.props.plugin.call('terminal', 'log', {type: 'info', value: `loading Solidity copilot: ${(data.loaded / data.total) * 100}% done.` })
})
this.suggestionService.events.on('done', (data) => {
this.props.plugin.call('terminal', 'log', { type: 'info', value: `Solidity copilot loaded.`})
})
this.suggestionService.events.on('ready', (data) => {
this.props.plugin.call('terminal', 'log', { type: 'info', value: `Solidity copilot ready to use.`})
})
this.monaco = monaco
}
async provideInlineCompletions(model: monacoTypes.editor.ITextModel, position: monacoTypes.Position, context: monacoTypes.languages.InlineCompletionContext, token: monacoTypes.CancellationToken): Promise<monacoTypes.languages.InlineCompletions<monacoTypes.languages.InlineCompletion>> {
@ -32,7 +20,7 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
endColumn: position.column,
});
const result = await this.suggestionService.suggest(word, 3, 0.5, 5, false)
const result = await this.props.plugin.call('copilot-suggestion', 'suggest', word)
const generatedText = (result as any).output[0].generated_text as string
console.log(word, result)

@ -1,3 +1,4 @@
import {ViewPlugin} from '@remixproject/engine-web'
import React, {useState, useReducer, useEffect, useCallback} from 'react' // eslint-disable-line
import {labels, textDark, textSecondary} from './constants'
@ -6,6 +7,9 @@ import './remix-ui-settings.css'
import {
generateContractMetadat,
personal,
copilotActivate,
copilotMaxNewToken,
copilotTemperature,
textWrapEventAction,
useMatomoAnalytics,
saveTokenToast,
@ -23,10 +27,10 @@ import {RemixUiLocaleModule, LocaleModule} from '@remix-ui/locale-module'
import {FormattedMessage, useIntl} from 'react-intl'
import {GithubSettings} from './github-settings'
import {EtherscanSettings} from './etherscan-settings'
import {CustomTooltip} from '@remix-ui/helper'
/* eslint-disable-next-line */
export interface RemixUiSettingsProps {
plugin: ViewPlugin
config: any
editor: any
_deps: any
@ -122,6 +126,22 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
textWrapEventAction(props.config, props.editor, event.target.checked, dispatch)
}
const onchangeCopilotActivate = (event) => {
copilotActivate(props.config, event.target.checked, dispatch)
if (event.target.checked) props.plugin.call('copilot-suggestion', 'init')
else {
props.plugin.call('copilot-suggestion', 'uninstall')
}
}
const onchangeCopilotMaxNewToken = (event) => {
copilotMaxNewToken(props.config, event.target.value, dispatch)
}
const onchangeCopilotTemperature = (event) => {
copilotTemperature(props.config, event.target.value, dispatch)
}
const onchangePersonal = (event) => {
personal(props.config, event.target.checked, dispatch)
}
@ -377,6 +397,59 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
saveIpfsSettingsToast(props.config, dispatchToast, ipfsUrl, ipfsProtocol, ipfsPort, ipfsProjectId, ipfsProjectSecret)
}
const isCopilotActivated = props.config.get('settings/copilot/suggest/activate') || false
const copilotMaxnewToken = props.config.get('settings/copilot/suggest/max_new_tokens') || 5
const copilotTemperatureValue = props.config.get('settings/copilot/suggest/temperature') || 0.5
const copilotSettings = () => (
<div className="border-top">
<div className="card-body pt-3 pb-2">
<h6 className="card-title">
<FormattedMessage id="settings.copilot" />
</h6>
<div className="pt-2 mb-0">
<div className="text-secondary mb-0 h6">
<div>
<div className="custom-control custom-checkbox mb-1">
<input onChange={onchangeCopilotActivate} id="copilot-activate" type="checkbox" className="custom-control-input" checked={isCopilotActivated} />
<label className={`form-check-label custom-control-label align-middle ${getTextClass('settings/copilot/suggest/activate')}`} htmlFor="copilot-activate">
<FormattedMessage id="settings.enablePersonalModeText" />
</label>
</div>
</div>
</div>
</div>
<div className="pt-2 mb-0">
<div className="text-secondary mb-0 h6">
<div>
<div className="custom-control custom-checkbox mb-1">
<input onChange={onchangeCopilotMaxNewToken} id="copilot-max-new-token" value={copilotMaxnewToken} min='1' max='150' type="range" className="custom-control-input" />
<label className={`form-check-label custom-control-label align-middle ${getTextClass('settings/copilot/suggest/max_new_tokens')}`} htmlFor="copilot-activate">
<FormattedMessage id="settings.enablePersonalModeText" />
</label>
</div>
</div>
</div>
</div>
<div className="pt-2 mb-0">
<div className="text-secondary mb-0 h6">
<div>
<div className="custom-control custom-checkbox mb-1">
<input onChange={onchangeCopilotTemperature} id="copilot-temperature" value={copilotTemperatureValue} min='0' max='1' type="range" className="custom-control-input" />
<label className={`form-check-label custom-control-label align-middle ${getTextClass('settings/copilot/suggest/temperature')}`} htmlFor="copilot-activate">
<FormattedMessage id="settings.enablePersonalModeText" />
</label>
</div>
</div>
</div>
</div>
</div>
</div>
)
const ipfsSettings = () => (
<div className="border-top">
<div className="card-body pt-3 pb-2">
@ -481,6 +554,7 @@ export const RemixUiSettings = (props: RemixUiSettingsProps) => {
{ipfsSettings()}
<RemixUiThemeModule themeModule={props._deps.themeModule} />
<RemixUiLocaleModule localeModule={props._deps.localeModule} />
{copilotSettings()}
</div>
)
}

@ -24,6 +24,21 @@ export const personal = (config, checked, dispatch) => {
dispatch({ type: 'personal', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } })
}
export const copilotActivate = (config, checked, dispatch) => {
config.set('settings/copilot/suggest/activate', checked)
dispatch({ type: 'copilot/suggest/activate', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } })
}
export const copilotMaxNewToken = (config, checked, dispatch) => {
config.set('settings/copilot/suggest/max_new_tokens', checked)
dispatch({ type: 'copilot/suggest/max_new_tokens', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } })
}
export const copilotTemperature = (config, checked, dispatch) => {
config.set('settings/copilot/suggest/temperature', checked)
dispatch({ type: 'copilot/suggest/temperature', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } })
}
export const useMatomoAnalytics = (config, checked, dispatch) => {
config.set('settings/matomo-analytics', checked)
dispatch({ type: 'useMatomoAnalytics', payload: { isChecked: checked, textClass: checked ? textDark : textSecondary } })

@ -41,6 +41,21 @@ export const initialState = {
name: 'displayErrors',
isChecked: true,
textClass: textSecondary
},
{
name: 'copilot/suggest/activate',
isChecked: false,
textClass: textSecondary
},
{
name: 'copilot/suggest/max_new_tokens',
value: 5,
textClass: textSecondary
},
{
name: 'copilot/suggest/temperature',
value: 0.5,
textClass: textSecondary
}
]
}
@ -128,6 +143,36 @@ export const settingReducer = (state, action) => {
return {
...state
}
case 'copilot/suggest/activate':
state.elementState.map(element => {
if (element.name === 'copilot/suggest/activate') {
element.isChecked = action.payload.isChecked
element.textClass = action.payload.textClass
}
})
return {
...state
}
case 'copilot/suggest/max_new_tokens':
state.elementState.map(element => {
if (element.name === 'copilot/suggest/max_new_tokens') {
element.value = action.payload.value
element.textClass = action.payload.textClass
}
})
return {
...state
}
case 'copilot/suggest/temperature':
state.elementState.map(element => {
if (element.name === 'useShowGasInEditor') {
element.value = action.payload.value
element.textClass = action.payload.textClass
}
})
return {
...state
}
default:
return initialState
}

Loading…
Cancel
Save