2023-08-19 01:28:40 +02:00
< template >
2023-08-19 19:26:15 +02:00
< div class = "container bg-bg-light dark:bg-bg-dark shadow-lg overflow-y-auto scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" >
2023-08-20 00:12:08 +02:00
< div class = "container flex flex-row m-2" >
2023-08-19 19:26:15 +02:00
< div class = "flex-grow m-2" >
2023-08-20 00:12:08 +02:00
< div class = "flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4" >
2023-08-19 01:28:40 +02:00
< label class = "mt-2" > Presets < / label >
2023-08-20 00:12:08 +02:00
< select v-model = "selectedPreset" class="m-2 border-2 rounded-md shadow-sm w-full" >
2023-08-19 01:28:40 +02:00
< option v-for ="preset in Object.keys(presets)" :key="preset" :value ="preset" >
{ { preset } }
< / option >
< / select >
2023-08-19 03:25:36 +02:00
< button class = "bg-green-500 hover:bg-green-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2 " @click ="setPreset" title = "Use preset" > < i data -feather = " check " > < / i > < / button >
< button class = "bg-green-500 hover:bg-green-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2 " @click ="addPreset" title = "Add this text as a preset" > < i data -feather = " plus " > < / i > < / button >
< button class = "bg-red-500 hover:bg-red-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2" @click ="removePreset" title = "Remove preset" > < i data -feather = " x " > < / i > < / button >
< button class = "bg-green-500 hover:bg-green-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2" @click ="savePreset" title = "Save presets list" > < i data -feather = " save " > < / i > < / button >
< button class = "bg-green-500 hover:bg-green-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2" @click ="reloadPresets" title = "Reload presets list" > < i data -feather = " refresh -ccw " > < / i > < / button >
2023-08-19 01:28:40 +02:00
< / div >
2023-08-19 19:26:15 +02:00
< div class = "flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4" >
2023-08-20 00:12:08 +02:00
< textarea v-model = "text" id="text_element" class="mt-4 h-64 overflow-y-scroll w-full dark:bg-bg-dark scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" type="text" > < / textarea >
< span > Cursor position { { cursorPosition } } < / span >
2023-08-19 01:28:40 +02:00
< / div >
2023-08-19 03:25:36 +02:00
< div class = "flex justify-between" >
< div class = "m-0" >
< button v-show = "!generating" id="generate-button" @click="generate" class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white font-bold py-2 px-4 rounded ml-2" > Generate Text < / button >
< button v-show = "generating" id="stop-button" @click="stopGeneration" class="bg-red-500 hover:bg-red-600 active:bg-red-700 text-white font-bold py-2 px-4 rounded ml-2 " > Stop Generation < / button >
2023-08-21 01:31:05 +02:00
< button v-show = "!generating" id="export-button" @click="exportText" class="bg-green-500 hover:bg-green-600 active:bg-green-700 text-white font-bold py-2 px-4 rounded ml-2"><i data-feather="upload" > < / i > < / button >
< button v-show = "!generating" id="import-button" @click="importText" class="bg-green-500 hover:bg-green-600 active:bg-green-700 text-white font-bold py-2 px-4 rounded ml-2"><i data-feather="download" > < / i > < / button >
< input type = "file" id = "import-input" class = "hidden" >
2023-08-19 03:25:36 +02:00
< / div >
< / div >
2023-08-19 19:26:15 +02:00
< div class = "flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4" >
< MarkdownRenderer ref = "mdRender" :markdown-text = "text" class = "dark:bg-bg-dark" >
< / MarkdownRenderer >
< / div >
2023-08-19 01:28:40 +02:00
< / div >
2023-08-20 00:12:08 +02:00
< div id = "settings" class = "border border-blue-300 bg-blue-200 mt-4 w-25 mr-2 h-full mb-10 min-w-500" style = "align-items: center; height: fit-content; margin: 10px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); border-radius: 4px;" >
2023-08-19 19:26:15 +02:00
< div id = "title" class = "border border-blue-600 bg-blue-300 m-0 flex justify-center items-center box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) border-radius: 4px;" >
2023-08-19 01:28:40 +02:00
< h3 class = "text-gray-600 mb-4 text-center m-0" > Settings < / h3 >
2023-08-19 19:26:15 +02:00
< / div >
2023-08-19 01:28:40 +02:00
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Temperature < / h3 >
< input type = "range" v-model = "temperature" min="0" max="5" step="0.1" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { temperature } } < / span >
< / div >
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Top K < / h3 >
< input type = "range" v-model = "top_k" min="1" max="100" step="1" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { top _k } } < / span >
< / div >
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Top P < / h3 >
< input type = "range" v-model = "top_p" min="0" max="1" step="0.1" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { top _p } } < / span >
< / div >
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Repeat Penalty < / h3 >
< input type = "range" v-model = "repeat_penalty" min="0" max="5" step="0.1" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { repeat _penalty } } < / span >
< / div >
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Repeat Last N < / h3 >
< input type = "range" v-model = "repeat_last_n" min="0" max="100" step="1" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { repeat _last _n } } < / span >
< / div >
2023-08-19 14:06:24 +02:00
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Number of tokens to crop the text to < / h3 >
< input type = "number" v-model = "n_crop" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { n _crop } } < / span >
< / div >
2023-08-19 03:25:36 +02:00
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Number of tokens to generate < / h3 >
< input type = "number" v-model = "n_predicts" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { n _predicts } } < / span >
< / div >
2023-08-19 01:28:40 +02:00
< div class = "slider-container ml-2 mr-2" >
< h3 class = "text-gray-600" > Seed < / h3 >
< input type = "number" v-model = "seed" class="w-full" >
< span class = "slider-value text-gray-500" > Current value : { { seed } } < / span >
< / div >
2023-08-19 19:26:15 +02:00
< / div >
2023-08-19 01:28:40 +02:00
< / div >
< / div >
< Toast ref = "toast" / >
< / template >
< script >
2023-08-19 03:25:36 +02:00
import feather from 'feather-icons'
2023-08-19 01:28:40 +02:00
import axios from "axios" ;
import socket from '@/services/websocket.js'
import Toast from '../components/Toast.vue'
2023-08-19 19:26:15 +02:00
import MarkdownRenderer from '../components/MarkdownRenderer.vue' ;
2023-08-19 01:28:40 +02:00
export default {
name : 'PlayGroundView' ,
data ( ) {
return {
generating : false ,
presets : { } ,
2023-08-20 00:12:08 +02:00
selectedPreset : '' ,
cursorPosition : 0 ,
2023-08-19 01:28:40 +02:00
text : "" ,
2023-08-20 00:12:08 +02:00
pre _text : "" ,
post _text : "" ,
2023-08-19 01:28:40 +02:00
temperature : 0.1 ,
top _k : 50 ,
top _p : 0.9 ,
repeat _penalty : 1.3 ,
repeat _last _n : 50 ,
2023-08-19 14:06:24 +02:00
n _crop : - 1 ,
2023-08-19 03:25:36 +02:00
n _predicts : 2000 ,
2023-08-19 01:28:40 +02:00
seed : - 1 ,
} ;
} ,
components : {
Toast ,
2023-08-19 19:26:15 +02:00
MarkdownRenderer
2023-08-19 01:28:40 +02:00
} ,
2023-08-19 03:25:36 +02:00
mounted ( ) {
2023-08-20 00:12:08 +02:00
const text _element = document . getElementById ( 'text_element' ) ;
2023-08-20 21:31:51 +02:00
text _element . addEventListener ( 'input' , ( ) => {
2023-08-20 22:21:46 +02:00
this . cursorPosition = text _element . selectionStart + 1 ;
2023-08-20 00:12:08 +02:00
} ) ;
text _element . addEventListener ( 'click' , ( ) => {
this . cursorPosition = text _element . selectionStart ;
} ) ;
axios . get ( './presets.json' ) . then ( response => {
2023-08-19 01:28:40 +02:00
console . log ( response . data )
this . presets = response . data
2023-08-19 03:25:36 +02:00
} ) . catch ( ex => {
this . $refs . toast . showToast ( ` Error: ${ ex } ` , 4 , false )
2023-08-19 01:28:40 +02:00
} ) ;
// Event handler for receiving generated text chunks
socket . on ( 'text_chunk' , data => {
this . appendToOutput ( data . chunk ) ;
2023-08-20 00:12:08 +02:00
const text _element = document . getElementById ( 'text_element' ) ;
text _element . scrollTo ( 0 , text _element . scrollHeight ) ;
2023-08-19 01:28:40 +02:00
} ) ;
// Event handler for receiving generated text chunks
socket . on ( 'text_generated' , data => {
// Toggle button visibility
this . generating = false ;
} ) ;
socket . on ( 'generation_error' , data => {
console . log ( 'generation_error:' , data ) ;
this . $refs . toast . showToast ( ` Error: ${ data } ` , 4 , false )
// Toggle button visibility
this . generating = false ;
} ) ;
// Event handler for successful connection
socket . on ( 'connect' , ( ) => {
console . log ( 'Connected to LoLLMs server' ) ;
this . $store . state . isConnected = true ;
this . generating = false
} ) ;
// Event handler for error during text generation
socket . on ( 'buzzy' , error => {
console . error ( 'Server is busy. Wait for your turn' , error ) ;
this . $refs . toast . showToast ( ` Error: ${ error . message } ` , 4 , false )
// Toggle button visibility
this . generating = false
} ) ;
// Event handler for error during text generation
socket . on ( 'generation_canceled' , error => {
// Toggle button visibility
this . generating = false
console . log ( "Generation canceled OK" )
} ) ;
2023-08-20 00:12:08 +02:00
//console.log('chatbox mnt',this.$refs)
this . $nextTick ( ( ) => {
feather . replace ( ) ;
} ) ;
} ,
created ( ) {
2023-08-19 01:28:40 +02:00
} ,
methods : {
2023-08-20 00:12:08 +02:00
getCursorPosition ( ) {
return this . cursorPosition ;
} ,
2023-08-19 01:28:40 +02:00
appendToOutput ( chunk ) {
2023-08-20 00:12:08 +02:00
this . pre _text += chunk
this . text = this . pre _text + this . post _text
2023-08-19 01:28:40 +02:00
} ,
generate ( ) {
2023-08-20 00:12:08 +02:00
console . log ( "Finding cursor position" )
this . pre _text = this . text . substring ( 0 , this . getCursorPosition ( ) )
this . post _text = this . text . substring ( this . getCursorPosition ( ) , this . text . length )
var prompt = this . text . substring ( 0 , this . getCursorPosition ( ) )
2023-08-19 01:28:40 +02:00
console . log ( prompt )
// Trigger the 'generate_text' event with the prompt
2023-08-19 14:06:24 +02:00
socket . emit ( 'generate_text' , { prompt : prompt , personality : - 1 , n _predicts : this . n _predicts , n _crop : this . n _crop ,
2023-08-19 01:28:40 +02:00
parameters : {
temperature : this . temperature ,
top _k : this . top _k ,
top _p : this . top _p ,
repeat _penalty : this . repeat _penalty , // Update with desired repeat penalty value
repeat _last _n : this . repeat _last _n , // Update with desired repeat_last_n value
seed : parseInt ( this . seed )
} } ) ;
// Toggle button visibility
this . generating = true
} ,
stopGeneration ( ) {
// Trigger the 'cancel_generation' event
2023-08-19 14:06:24 +02:00
socket . emit ( 'cancel_text_generation' , { } ) ;
2023-08-19 01:28:40 +02:00
} ,
exportText ( ) {
2023-08-19 03:25:36 +02:00
const textToExport = this . text ;
const element = document . createElement ( 'a' ) ;
const file = new Blob ( [ textToExport ] , { type : 'text/plain' } ) ;
element . href = URL . createObjectURL ( file ) ;
element . download = 'exported_text.txt' ;
document . body . appendChild ( element ) ;
element . click ( ) ;
document . body . removeChild ( element ) ;
2023-08-19 01:28:40 +02:00
} ,
2023-08-21 01:31:05 +02:00
importText ( ) {
const inputFile = document . getElementById ( "import-input" ) ;
if ( ! inputFile ) return ; // If the element doesn't exist, do nothing
inputFile . addEventListener ( "change" , event => {
if ( event . target . files && event . target . files [ 0 ] ) {
const reader = new FileReader ( ) ;
reader . onload = ( ) => {
this . text = reader . result ;
} ;
reader . readAsText ( event . target . files [ 0 ] ) ;
} else {
alert ( "Please select a file." ) ;
}
} ) ;
inputFile . click ( ) ;
} ,
2023-08-19 01:28:40 +02:00
setPreset ( ) {
this . text = this . presets [ this . selectedPreset ] ;
} ,
addPreset ( ) {
let title = prompt ( 'Enter the title of the preset:' ) ;
this . presets [ title ] = this . text
} ,
removePreset ( ) {
if ( this . selectedPreset ) {
delete this . presets [ this . selectedPreset ] ;
}
} ,
savePreset ( ) {
2023-08-19 03:25:36 +02:00
axios . post ( "/save_presets" , this . presets ) . then ( ( response ) => {
2023-08-19 01:28:40 +02:00
console . log ( response ) ;
2023-08-19 03:25:36 +02:00
this . $refs . toast . showToast ( ` Presets saved ` , 4 , true )
2023-08-19 01:28:40 +02:00
} ) ;
2023-08-19 03:25:36 +02:00
} ,
reloadPresets ( ) {
axios . get ( './presets.json' ) . then ( response => {
console . log ( response . data )
this . presets = response . data
} ) . catch ( ex => {
this . $refs . toast . showToast ( ` Error: ${ ex } ` , 4 , false )
} ) ;
} ,
2023-08-19 01:28:40 +02:00
}
} ;
< / script >
< style >
select {
width : 200 px ;
}
body {
background - color : # fafafa ;
font - family : sans - serif ;
}
. container {
margin : 4 px auto ;
width : 800 px ;
}
. settings {
position : fixed ;
top : 0 ;
right : 0 ;
width : 250 px ;
background - color : # fff ;
z - index : 1000 ;
display : none ;
}
. settings - button {
cursor : pointer ;
padding : 10 px ;
border : 1 px solid # ddd ;
border - radius : 5 px ;
color : # 333 ;
font - size : 14 px ;
}
. settings - button : hover {
background - color : # eee ;
}
. settings - button : active {
background - color : # ddd ;
}
. slider - container {
margin - top : 20 px ;
}
. slider - value {
display : inline - block ;
margin - left : 10 px ;
color : # 6 b7280 ;
font - size : 14 px ;
}
. small - button {
padding : 0.5 rem 0.75 rem ;
font - size : 0.875 rem ;
}
< / style >