add AutoSuggest Component

add fetch abort control parameter
This commit is contained in:
LL
2023-05-30 22:43:48 +09:00
parent bdf00126cc
commit fc0c50c331
9 changed files with 252 additions and 34 deletions

View File

@@ -1,10 +1,11 @@
<script lang="ts">
import { DatabaseIcon, DicesIcon, LanguagesIcon, MenuIcon, MicOffIcon, RefreshCcwIcon, Send } from "lucide-svelte";
import Suggestion from './Suggestion.svelte';
import { DatabaseIcon, DicesIcon, LanguagesIcon, MenuIcon, MicOffIcon, PowerIcon, RefreshCcwIcon, ReplyIcon, Send } from "lucide-svelte";
import { selectedCharID } from "../../ts/stores";
import Chat from "./Chat.svelte";
import { DataBase, appVer, type Message } from "../../ts/storage/database";
import { DataBase, appVer, type Message, type character } from "../../ts/storage/database";
import { getCharImage } from "../../ts/characters";
import { doingChat, sendChat } from "../../ts/process/index";
import { doingChat, sendChat, type OpenAIChat } from "../../ts/process/index";
import { findCharacterbyId, messageForm, sleep } from "../../ts/util";
import { language } from "../../lang";
import { translate } from "../../ts/translator/translator";
@@ -24,7 +25,7 @@
let rerolls:Message[][] = []
let rerollid = -1
let lastCharId = -1
let doingChatInputTranslate = false
async function send() {
let selectedChar = $selectedCharID
console.log('send')
@@ -179,7 +180,6 @@
}
$: updateInputSize()
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="w-full h-full" style={customStyle} on:click={() => {
@@ -220,7 +220,7 @@
/>
{#if $doingChat}
{#if $doingChat || doingChatInputTranslate}
<div
class="mr-2 bg-selected flex justify-center items-center text-white w-12 h-12 rounded-md hover:bg-green-500 transition-colors">
<div class="loadmove" class:autoload={autoMode}>
@@ -231,13 +231,16 @@
class="mr-2 bg-gray-500 flex justify-center items-center text-white w-12 h-12 rounded-md hover:bg-green-500 transition-colors"><Send />
</div>
{/if}
<div on:click={(e) => {
openMenu = !openMenu
e.stopPropagation()
}}
class="mr-2 bg-gray-500 flex justify-center items-center text-white w-12 h-12 rounded-md hover:bg-green-500 transition-colors"><MenuIcon />
</div>
<div on:click={(e) => {
openMenu = !openMenu
e.stopPropagation()
}}
class="mr-2 bg-gray-500 flex justify-center items-center text-white w-12 h-12 rounded-md hover:bg-green-500 transition-colors"><MenuIcon />
</div>
</div>
{#if $DataBase.useAutoSuggestions}
<Suggestion messageInput={(msg)=>messageInput=msg} {send}/>
{/if}
{#each messageForm($DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
{#if chat.role === 'char'}
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
@@ -356,14 +359,20 @@
</div>
{#if $DataBase.translator !== ''}
<div class="flex items-center cursor-pointer hover:text-green-500 transition-colors" on:click={async () => {
$doingChat = true
doingChatInputTranslate = true
messageInput = (await translate(messageInput, true))
$doingChat = false
doingChatInputTranslate = false
}}>
<LanguagesIcon />
<span class="ml-2">{language.translateInput}</span>
</div>
{/if}
<div class={"flex items-center cursor-pointer "+ ($DataBase.useAutoSuggestions ? 'text-green-500':'lg:hover:text-green-500')} on:click={async () => {
$DataBase.useAutoSuggestions = !$DataBase.useAutoSuggestions
}}>
<ReplyIcon />
<span class="ml-2">자동 제안</span>
</div>
<div class="flex items-center cursor-pointer hover:text-green-500 transition-colors" on:click={reroll}>
<RefreshCcwIcon />
<span class="ml-2">{language.reroll}</span>

View File

@@ -0,0 +1,167 @@
<script lang="ts">
import { requestChatData } from "src/ts/process/request";
import { doingChat, type OpenAIChat } from "../../ts/process/index";
import { DataBase, type character } from "../../ts/storage/database";
import { selectedCharID } from "../../ts/stores";
import { translate } from "src/ts/translator/translator";
import { CopyIcon, LanguagesIcon, RefreshCcwIcon } from "lucide-svelte";
import { alertConfirm } from "src/ts/alert";
import { language } from "src/lang";
export let send;
export let messageInput;
let suggestMessages = $DataBase.characters[$selectedCharID]?.chats[$DataBase.characters[$selectedCharID].chatPage]?.suggestMessages
let suggestMessagesTranslated
let toggleTranslate = $DataBase.autoTranslate
let progress;
let progressChatPage=-1;
let abortController;
let chatPage
$: {
$selectedCharID
//FIXME add selectedChatPage for optimize render
chatPage = $DataBase.characters[$selectedCharID].chatPage
updateSuggestions()
}
const updateSuggestions = () => {
if($selectedCharID > -1 && !$doingChat) {
if(progressChatPage > 0 && progressChatPage != chatPage){
progress=false
abortController?.abort()
}
let currentChar = $DataBase.characters[$selectedCharID];
suggestMessages = currentChar?.chats[currentChar.chatPage].suggestMessages
}
}
doingChat.subscribe((v) => {
if(v) {
progress=false
abortController?.abort()
suggestMessages = []
}
if(!v && $selectedCharID > -1 && (!suggestMessages || suggestMessages.length === 0) && !progress){
let currentChar = $DataBase.characters[$selectedCharID] as character;
let messages = currentChar.chats[currentChar.chatPage].message;
let lastMessages = messages.slice(Math.max(messages.length - 10, 0));
if(lastMessages.length === 0)
return
const promptbody:OpenAIChat[] = [
{
role:'system',
content: $DataBase.autoSuggestPrompt
}
,
{
role: 'user',
content: lastMessages.map(b=>b.role+":"+b.data).reduce((a,b)=>a+','+b)
}
]
progress = true
progressChatPage = chatPage
abortController = new AbortController()
requestChatData({
formated: promptbody,
bias: {},
currentChar
}, 'submodel', abortController.signal).then(rq2=>{
if(rq2.type !== 'fail' && rq2.type !== 'streaming' && progress){
var suggestMessagesNew = rq2.result.split('\n').filter(msg => msg.startsWith('-')).map(msg => msg.replace('-','').trim())
currentChar.chats[currentChar.chatPage].suggestMessages = suggestMessagesNew
suggestMessages = suggestMessagesNew
}
progress = false
})
}
})
const translateSuggest = async (toggle, messages)=>{
if(toggle && messages && messages.length > 0) {
suggestMessagesTranslated = []
for(let i = 0; i < suggestMessages.length; i++){
let msg = suggestMessages[i]
let translated = await translate(msg, false)
suggestMessagesTranslated[i] = translated
}
}
}
$: {translateSuggest(toggleTranslate, suggestMessages)}
</script>
<div class="ml-4 flex flex-wrap">
{#if progress}
<div class="flex bg-gray-500 p-2 rounded-lg items-center">
<div class="loadmove mx-2"/>
<div>응답 제안 작성 중...</div>
</div>
{:else if !$doingChat}
<div class="flex mr-2 mb-2">
<button class={"bg-gray-500 hover:bg-gray-700 font-bold py-2 px-4 rounded " + (toggleTranslate ? 'text-green-500' : 'text-white')}
on:click={() => {
toggleTranslate = !toggleTranslate
// translateSuggest(toggleTranslate, suggestMessages)
}}
>
<LanguagesIcon/>
</button>
</div>
<div class="flex mr-2 mb-2">
<button class="bg-gray-500 hover:bg-gray-700 font-bold py-2 px-4 rounded text-white"
on:click={() => {
alertConfirm(language.askReRollAutoSuggestions).then((result) => {
if(result) {
suggestMessages = []
doingChat.set(true)
doingChat.set(false)
}
})
}}
>
<RefreshCcwIcon/>
</button>
</div>
{#each suggestMessages??[] as suggest, i}
<div class="flex mr-2 mb-2">
<button class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded" on:click={() => {
suggestMessages = []
messageInput(suggest)
send()
}}>
{#if toggleTranslate && suggestMessagesTranslated && suggestMessagesTranslated.length > 0}
{suggestMessagesTranslated[i]??suggest}
{:else}
{suggest}
{/if}
</button>
<button class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded ml-1" on:click={() => {
messageInput(suggest)
}}>
<CopyIcon/>
</button>
</div>
{/each}
{/if}
</div>
<style>
.loadmove {
animation: spin 1s linear infinite;
border-radius: 50%;
border: 0.4rem solid rgba(0,0,0,0);
width: 1rem;
height: 1rem;
border-top: 0.4rem solid white;
border-left: 0.4rem solid white;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

View File

@@ -13,13 +13,15 @@
let tokens = {
mainPrompt: 0,
jailbreak: 0,
globalNote: 0
globalNote: 0,
autoSuggest: 0
}
let lasttokens = {
mainPrompt: '',
jailbreak: '',
globalNote: ''
globalNote: '',
autoSuggest: ''
}
export let openPresetList =false
@@ -31,6 +33,7 @@
tokens.mainPrompt = await tokenize($DataBase.mainPrompt)
tokens.jailbreak = await tokenize($DataBase.jailbreak)
tokens.globalNote = await tokenize($DataBase.globalNote)
tokens.autoSuggest = await tokenize($DataBase.autoSuggestPrompt)
}
let advancedBotSettings = false
@@ -143,8 +146,11 @@
<span class="text-gray-400 mb-6 text-sm">{tokens.jailbreak} {language.tokens}</span>
<span class="text-neutral-200">{language.globalNote} <Help key="globalNote"/></span>
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 min-h-20 focus:bg-selected text-xs w-full" autocomplete="off" bind:value={$DataBase.globalNote}></textarea>
<span class="text-gray-400 mb-6 text-sm">{tokens.globalNote} {language.tokens}</span>
<span class="text-neutral-200">{language.autoSuggest} <Help key="autoSuggest"/></span>
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 min-h-20 focus:bg-selected text-xs w-full" autocomplete="off" bind:value={$DataBase.autoSuggestPrompt}></textarea>
<span class="text-gray-400 mb-6 text-sm">{tokens.autoSuggest} {language.tokens}</span>
<span class="text-neutral-200">{language.maxContextSize}</span>
{#if $DataBase.aiModel === 'gpt35'}
<input class="text-neutral-200 mb-4 text-sm p-2 bg-transparent input-text focus:bg-selected" type="number" min={0} max="4000" bind:value={$DataBase.maxContext}>