Add ChatML and Rework display

This commit is contained in:
kwaroran
2024-12-01 17:05:50 +09:00
parent 5ebb934d3b
commit 8a6cfedcda
4 changed files with 234 additions and 86 deletions

View File

@@ -10,6 +10,7 @@
import TextInput from "./GUI/TextInput.svelte";
import { DBState } from 'src/ts/stores.svelte';
let opened = $state(false)
interface Props {
promptItem: PromptItem;
onRemove?: () => void;
@@ -36,101 +37,227 @@
promptItem = currentprompt
}
</script>
function getName(promptItem:PromptItem){
<div class="flex flex-col first:mt-0 mt-2 border border-selected p-4 rounded-md bg-darkbg">
<span class="mb-2">
<button class="float-right" onclick={onRemove}><XIcon /></button>
<button class="float-right" onclick={moveDown}><ArrowDown /></button>
<button class="float-right" onclick={moveUp}><ArrowUp /></button>
</span>
<span>{language.type}
</span>
<SelectInput bind:value={promptItem.type} onchange={() => {
if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
promptItem.text = ""
promptItem.role = "system"
if(promptItem.name){
return promptItem.name
}
if(promptItem.type === 'plain'){
return language.formating.plain
}
if(promptItem.type === 'jailbreak'){
return language.formating.jailbreak
}
if(promptItem.type === 'chat'){
promptItem.rangeStart = -1000
promptItem.rangeEnd = 'end'
return language.Chat
}
}} >
<OptionInput value="plain">{language.formating.plain}</OptionInput>
<OptionInput value="jailbreak">{language.formating.jailbreak}</OptionInput>
<OptionInput value="chat">{language.Chat}</OptionInput>
<OptionInput value="persona">{language.formating.personaPrompt}</OptionInput>
<OptionInput value="description">{language.formating.description}</OptionInput>
<OptionInput value="authornote">{language.formating.authorNote}</OptionInput>
<OptionInput value="lorebook">{language.formating.lorebook}</OptionInput>
<OptionInput value="memory">{language.formating.memory}</OptionInput>
<OptionInput value="postEverything">{language.formating.postEverything}</OptionInput>
{#if DBState.db.promptSettings.customChainOfThought}
<OptionInput value="cot">{language.cot}</OptionInput>
{/if}
</SelectInput>
if(promptItem.type === 'persona'){
return language.formating.personaPrompt
}
if(promptItem.type === 'description'){
return language.formating.description
}
if(promptItem.type === 'authornote'){
return language.formating.authorNote
}
if(promptItem.type === 'lorebook'){
return language.formating.lorebook
}
if(promptItem.type === 'memory'){
return language.formating.memory
}
if(promptItem.type === 'postEverything'){
return language.formating.postEverything
}
if(promptItem.type === 'cot'){
return language.cot
}
if(promptItem.type === 'chatML'){
return 'ChatML'
}
return ""
}
{#if promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'}
<span>{language.specialType}</span>
<SelectInput bind:value={promptItem.type2}>
<OptionInput value="normal">{language.noSpecialType}</OptionInput>
<OptionInput value="main">{language.mainPrompt}</OptionInput>
<OptionInput value="globalNote">{language.globalNote}</OptionInput>
function replacePrompt(prompt:PromptItem){
if(JSON.stringify(promptItem) === JSON.stringify(prompt)){
return
}
const ind = DBState.db.promptTemplate.findIndex((item, index) => {
return JSON.stringify(item) === JSON.stringify(prompt)
})
if(ind !== -1){
DBState.db.promptTemplate[ind] = promptItem
promptItem = prompt
}
else{
const myInd = DBState.db.promptTemplate.findIndex((item, index) => {
return JSON.stringify(item) === JSON.stringify(promptItem)
})
DBState.db.promptTemplate.splice(myInd, 0, prompt)
}
}
</script>
<div class="first:mt-0 w-full h-2" role="doc-pagebreak" ondrop={(e) => {
e.preventDefault()
e.stopPropagation()
const data = e.dataTransfer.getData('text')
if(data === 'prompt'){
const prompt = JSON.parse(e.dataTransfer.getData('prompt'))
replacePrompt(prompt)
}
}} ondragover={(e) => {
e.preventDefault()
}} draggable="true" ondragstart={(e) => {
e.dataTransfer.setData('text', 'prompt')
e.dataTransfer.setData('prompt', JSON.stringify(promptItem))
}}>
</div>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="flex flex-col border border-selected p-4 rounded-md bg-darkbg"
ondragover={(e) => {
e.preventDefault()
}}
ondrop={(e) => {
e.preventDefault()
const data = e.dataTransfer.getData('text')
if(data === 'prompt'){
const prompt = JSON.parse(e.dataTransfer.getData('prompt'))
replacePrompt(prompt)
}
}}
draggable={opened ? false : true}
ondragstart={(e) => {
e.dataTransfer.setData('text', 'prompt')
e.dataTransfer.setData('prompt', JSON.stringify(promptItem))
}}
>
<!-- svelte-ignore a11y_click_events_have_key_events -->
<div class="flex items-center w-full" onclick={() => {
opened = !opened
}}>
<span>{getName(promptItem)}</span>
<div class="flex flex-1 justify-end">
<button onclick={(e) => {
e.stopPropagation()
onRemove()
}}><XIcon /></button>
<button onclick={(e) => {
e.stopPropagation()
moveDown()
}}><ArrowDown /></button>
<button onclick={(e) => {
e.stopPropagation()
moveUp()
}}><ArrowUp /></button>
</div>
</div>
{#if opened}
<span class="mt-6">{language.name}</span>
<TextInput bind:value={promptItem.name} />
<span class="mt-2">{language.type} </span>
<SelectInput bind:value={promptItem.type} onchange={() => {
if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
promptItem.text = ""
promptItem.role = "system"
}
if(promptItem.type === 'chat'){
promptItem.rangeStart = -1000
promptItem.rangeEnd = 'end'
}
}} >
<OptionInput value="plain">{language.formating.plain}</OptionInput>
<OptionInput value="jailbreak">{language.formating.jailbreak}</OptionInput>
<OptionInput value="chat">{language.Chat}</OptionInput>
<OptionInput value="persona">{language.formating.personaPrompt}</OptionInput>
<OptionInput value="description">{language.formating.description}</OptionInput>
<OptionInput value="authornote">{language.formating.authorNote}</OptionInput>
<OptionInput value="lorebook">{language.formating.lorebook}</OptionInput>
<OptionInput value="memory">{language.formating.memory}</OptionInput>
<OptionInput value="postEverything">{language.formating.postEverything}</OptionInput>
<OptionInput value="chatML">{"chatML"}</OptionInput>
{#if DBState.db.promptSettings.customChainOfThought}
<OptionInput value="cot">{language.cot}</OptionInput>
{/if}
</SelectInput>
<span>{language.prompt}</span>
<TextAreaInput highlight bind:value={promptItem.text} />
<span>{language.role}</span>
<SelectInput bind:value={promptItem.role}>
<OptionInput value="user">{language.user}</OptionInput>
<OptionInput value="bot">{language.character}</OptionInput>
<OptionInput value="system">{language.systemPrompt}</OptionInput>
</SelectInput>
{/if}
{#if promptItem.type === 'chat'}
{#if promptItem.rangeStart !== -1000}
<span>{language.rangeStart}</span>
<NumberInput bind:value={promptItem.rangeStart} />
<span>{language.rangeEnd}</span>
{#if promptItem.rangeEnd === 'end'}
<NumberInput value={0} marginBottom disabled/>
<CheckInput name={language.untilChatEnd} check={true} onChange={() => {
if(promptItem.type === 'chat'){
promptItem.rangeEnd = 0
{#if promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'}
<span>{language.specialType}</span>
<SelectInput bind:value={promptItem.type2}>
<OptionInput value="normal">{language.noSpecialType}</OptionInput>
<OptionInput value="main">{language.mainPrompt}</OptionInput>
<OptionInput value="globalNote">{language.globalNote}</OptionInput>
</SelectInput>
<span>{language.prompt}</span>
<TextAreaInput highlight bind:value={promptItem.text} />
<span>{language.role}</span>
<SelectInput bind:value={promptItem.role}>
<OptionInput value="user">{language.user}</OptionInput>
<OptionInput value="bot">{language.character}</OptionInput>
<OptionInput value="system">{language.systemPrompt}</OptionInput>
</SelectInput>
{/if}
{#if promptItem.type === 'chatML'}
<span>{language.prompt}</span>
<TextAreaInput highlight bind:value={promptItem.text} />
{/if}
{#if promptItem.type === 'chat'}
{#if promptItem.rangeStart !== -1000}
<span>{language.rangeStart}</span>
<NumberInput bind:value={promptItem.rangeStart} />
<span>{language.rangeEnd}</span>
{#if promptItem.rangeEnd === 'end'}
<NumberInput value={0} marginBottom disabled/>
<CheckInput name={language.untilChatEnd} check={true} onChange={() => {
if(promptItem.type === 'chat'){
promptItem.rangeEnd = 0
}
}} />
{:else}
<NumberInput bind:value={promptItem.rangeEnd} marginBottom />
<CheckInput name={language.untilChatEnd} check={false} onChange={() => {
if(promptItem.type === 'chat'){
promptItem.rangeEnd = 'end'
}
}} />
{/if}
{#if DBState.db.promptSettings.sendChatAsSystem}
<CheckInput name={language.chatAsOriginalOnSystem} bind:check={promptItem.chatAsOriginalOnSystem}/>
{/if}
{/if}
<CheckInput name={language.advanced} check={promptItem.rangeStart !== -1000} onChange={chatPromptChange} className="my-2"/>
{/if}
{#if promptItem.type === 'authornote'}
<span>{language.defaultPrompt}</span>
<TextInput bind:value={promptItem.defaultText} />
{/if}
{#if promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'}
{#if !promptItem.innerFormat}
<CheckInput name={language.customInnerFormat} check={false} className="mt-2" onChange={() => {
if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
promptItem.innerFormat = "{{slot}}"
}
}} />
{:else}
<NumberInput bind:value={promptItem.rangeEnd} marginBottom />
<CheckInput name={language.untilChatEnd} check={false} onChange={() => {
if(promptItem.type === 'chat'){
promptItem.rangeEnd = 'end'
<span>{language.innerFormat}</span>
<TextAreaInput highlight bind:value={promptItem.innerFormat}/>
<CheckInput name={language.customInnerFormat} check={true} className="mt-2" onChange={() => {
if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
promptItem.innerFormat = null
}
}} />
{/if}
{#if DBState.db.promptSettings.sendChatAsSystem}
<CheckInput name={language.chatAsOriginalOnSystem} bind:check={promptItem.chatAsOriginalOnSystem}/>
{/if}
{/if}
<CheckInput name={language.advanced} check={promptItem.rangeStart !== -1000} onChange={chatPromptChange} className="my-2"/>
{/if}
{#if promptItem.type === 'authornote'}
<span>{language.defaultPrompt}</span>
<TextInput bind:value={promptItem.defaultText} />
{/if}
{#if promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'}
{#if !promptItem.innerFormat}
<CheckInput name={language.customInnerFormat} check={false} className="mt-2" onChange={() => {
if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
promptItem.innerFormat = "{{slot}}"
}
}} />
{:else}
<span>{language.innerFormat}</span>
<TextAreaInput highlight bind:value={promptItem.innerFormat}/>
<CheckInput name={language.customInnerFormat} check={true} className="mt-2" onChange={() => {
if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
promptItem.innerFormat = null
}
}} />
{/if}
{/if}
</div>

View File

@@ -2280,7 +2280,7 @@ export function parseChatML(data:string):OpenAIChat[]|null{
return {
role: role,
content: v
content: risuChatParser(v)
}
})
}

View File

@@ -28,6 +28,7 @@ import { runImageEmbedding } from "./transformers";
import { hanuraiMemory } from "./memory/hanuraiMemory";
import { hypaMemoryV2 } from "./memory/hypav2";
import { runLuaEditTrigger } from "./lua";
import { parseChatML } from "../parser.svelte";
export interface OpenAIChat{
role: 'system'|'user'|'assistant'|'function'
@@ -548,6 +549,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
await tokenizeChatArray([prompt])
break
}
case 'chatML':{
let prompts = parseChatML(card.text)
await tokenizeChatArray(prompts)
break
}
case 'chat':{
let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd
@@ -1007,6 +1013,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
pushPrompts([prompt])
break
}
case 'chatML':{
let prompts = parseChatML(card.text)
pushPrompts(prompts)
break
}
case 'chat':{
let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd

View File

@@ -4,7 +4,7 @@ import { getDatabase, presetTemplate, setDatabase, type Database } from "../stor
import { alertError, alertNormal } from "../alert";
import type { OobaChatCompletionRequestParams } from "../model/ooba";
export type PromptItem = PromptItemPlain|PromptItemTyped|PromptItemChat|PromptItemAuthorNote;
export type PromptItem = PromptItemPlain|PromptItemTyped|PromptItemChat|PromptItemAuthorNote|PromptItemChatML
export type PromptType = PromptItem['type'];
export type PromptSettings = {
assistantPrefill: string
@@ -21,17 +21,26 @@ export interface PromptItemPlain {
type2: 'normal'|'globalNote'|'main'
text: string;
role: 'user'|'bot'|'system';
name?: string
}
export interface PromptItemChatML {
type: 'chatML'
text: string
name?: string
}
export interface PromptItemTyped {
type: 'persona'|'description'|'lorebook'|'postEverything'|'memory'
innerFormat?: string
innerFormat?: string,
name?: string
}
export interface PromptItemAuthorNote {
type : 'authornote'
innerFormat?: string
defaultText?: string
name?: string
}
@@ -40,6 +49,7 @@ export interface PromptItemChat {
rangeStart: number;
rangeEnd: number|'end';
chatAsOriginalOnSystem?: boolean;
name?: string
}
export async function tokenizePreset(prompts:PromptItem[], consti:boolean = false){