Merge branch 'kwaroran:main' into main

This commit is contained in:
HyperBlaze
2024-12-01 05:35:23 -08:00
committed by GitHub
9 changed files with 307 additions and 140 deletions

View File

@@ -29,7 +29,7 @@
}, },
"productName": "RisuAI", "productName": "RisuAI",
"mainBinaryName": "RisuAI", "mainBinaryName": "RisuAI",
"version": "140.1.0", "version": "141.0.0",
"identifier": "co.aiclient.risu", "identifier": "co.aiclient.risu",
"plugins": { "plugins": {
"updater": { "updater": {

View File

@@ -2,7 +2,7 @@
import { ArrowLeft, Sparkles, ArrowRight, PencilIcon, LanguagesIcon, RefreshCcwIcon, TrashIcon, CopyIcon, Volume2Icon, BotIcon, ArrowLeftRightIcon, UserIcon } from "lucide-svelte"; import { ArrowLeft, Sparkles, ArrowRight, PencilIcon, LanguagesIcon, RefreshCcwIcon, TrashIcon, CopyIcon, Volume2Icon, BotIcon, ArrowLeftRightIcon, UserIcon } from "lucide-svelte";
import { type CbsConditions, ParseMarkdown, postTranslationParse, type simpleCharacterArgument } from "../../ts/parser.svelte"; import { type CbsConditions, ParseMarkdown, postTranslationParse, type simpleCharacterArgument } from "../../ts/parser.svelte";
import AutoresizeArea from "../UI/GUI/TextAreaResizable.svelte"; import AutoresizeArea from "../UI/GUI/TextAreaResizable.svelte";
import { alertConfirm, alertError, alertNormal, alertRequestData, alertWait } from "../../ts/alert"; import { alertClear, alertConfirm, alertError, alertNormal, alertRequestData, alertWait } from "../../ts/alert";
import { language } from "../../lang"; import { language } from "../../lang";
import { type MessageGenerationInfo } from "../../ts/storage/database.svelte"; import { type MessageGenerationInfo } from "../../ts/storage/database.svelte";
import { alertStore, DBState } from 'src/ts/stores.svelte'; import { alertStore, DBState } from 'src/ts/stores.svelte';
@@ -140,11 +140,12 @@
translateText = false translateText = false
try { try {
if(DBState.db.autoTranslate){ if(DBState.db.autoTranslate){
if(DBState.db.autoTranslateCachedOnly && DBState.db.translatorType === "llm"){ if(DBState.db.autoTranslateCachedOnly && DBState.db.translatorType === 'llm'){
const cache = await getLLMCache(data) const cache = DBState.db.translateBeforeHTMLFormatting
if(cache !== null){ ? await getLLMCache(data)
translateText = true : await getLLMCache(await ParseMarkdown(data, charArg, 'pretranslate', chatID, getCbsCondition()))
}
translateText = cache !== null
} }
else{ else{
translateText = true translateText = true
@@ -430,7 +431,10 @@
return return
} }
catch (e) { catch (e) {
alertError(`Error, please try again: ${e.message}`) alertClear()
window.navigator.clipboard.writeText(msgDisplay).then(() => {
setStatusMessage(language.copied)
})
} }
} }
window.navigator.clipboard.writeText(msgDisplay).then(() => { window.navigator.clipboard.writeText(msgDisplay).then(() => {

View File

@@ -10,6 +10,7 @@
import TextInput from "./GUI/TextInput.svelte"; import TextInput from "./GUI/TextInput.svelte";
import { DBState } from 'src/ts/stores.svelte'; import { DBState } from 'src/ts/stores.svelte';
let opened = $state(false)
interface Props { interface Props {
promptItem: PromptItem; promptItem: PromptItem;
onRemove?: () => void; onRemove?: () => void;
@@ -36,101 +37,224 @@
promptItem = currentprompt 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"> if(promptItem.name){
<span class="mb-2"> return promptItem.name
<button class="float-right" onclick={onRemove}><XIcon /></button> }
<button class="float-right" onclick={moveDown}><ArrowDown /></button>
<button class="float-right" onclick={moveUp}><ArrowUp /></button> if(promptItem.type === 'plain'){
</span> return language.formating.plain
<span>{language.type} }
</span> if(promptItem.type === 'jailbreak'){
<SelectInput bind:value={promptItem.type} onchange={() => { return language.formating.jailbreak
if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
promptItem.text = ""
promptItem.role = "system"
} }
if(promptItem.type === 'chat'){ if(promptItem.type === 'chat'){
promptItem.rangeStart = -1000 return language.Chat
promptItem.rangeEnd = 'end'
} }
}} > if(promptItem.type === 'persona'){
<OptionInput value="plain">{language.formating.plain}</OptionInput> return language.formating.personaPrompt
<OptionInput value="jailbreak">{language.formating.jailbreak}</OptionInput> }
<OptionInput value="chat">{language.Chat}</OptionInput> if(promptItem.type === 'description'){
<OptionInput value="persona">{language.formating.personaPrompt}</OptionInput> return language.formating.description
<OptionInput value="description">{language.formating.description}</OptionInput> }
<OptionInput value="authornote">{language.formating.authorNote}</OptionInput> if(promptItem.type === 'authornote'){
<OptionInput value="lorebook">{language.formating.lorebook}</OptionInput> return language.formating.authorNote
<OptionInput value="memory">{language.formating.memory}</OptionInput> }
<OptionInput value="postEverything">{language.formating.postEverything}</OptionInput> if(promptItem.type === 'lorebook'){
{#if DBState.db.promptSettings.customChainOfThought} return language.formating.lorebook
<OptionInput value="cot">{language.cot}</OptionInput> }
{/if} if(promptItem.type === 'memory'){
</SelectInput> 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'} function replacePrompt(prompt:PromptItem){
<span>{language.specialType}</span> if(JSON.stringify(promptItem) === JSON.stringify(prompt)){
<SelectInput bind:value={promptItem.type2}> return
<OptionInput value="normal">{language.noSpecialType}</OptionInput> }
<OptionInput value="main">{language.mainPrompt}</OptionInput>
<OptionInput value="globalNote">{language.globalNote}</OptionInput> const ind = DBState.db.promptTemplate.findIndex((item, index) => {
return JSON.stringify(item) === JSON.stringify(prompt)
})
if(ind !== -1){
DBState.db.promptTemplate.splice(ind, 1)
}
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> </SelectInput>
<span>{language.prompt}</span>
<TextAreaInput highlight bind:value={promptItem.text} /> {#if promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'}
<span>{language.role}</span> <span>{language.specialType}</span>
<SelectInput bind:value={promptItem.role}> <SelectInput bind:value={promptItem.type2}>
<OptionInput value="user">{language.user}</OptionInput> <OptionInput value="normal">{language.noSpecialType}</OptionInput>
<OptionInput value="bot">{language.character}</OptionInput> <OptionInput value="main">{language.mainPrompt}</OptionInput>
<OptionInput value="system">{language.systemPrompt}</OptionInput> <OptionInput value="globalNote">{language.globalNote}</OptionInput>
</SelectInput> </SelectInput>
{/if} <span>{language.prompt}</span>
{#if promptItem.type === 'chat'} <TextAreaInput highlight bind:value={promptItem.text} />
{#if promptItem.rangeStart !== -1000} <span>{language.role}</span>
<span>{language.rangeStart}</span> <SelectInput bind:value={promptItem.role}>
<NumberInput bind:value={promptItem.rangeStart} /> <OptionInput value="user">{language.user}</OptionInput>
<span>{language.rangeEnd}</span> <OptionInput value="bot">{language.character}</OptionInput>
{#if promptItem.rangeEnd === 'end'} <OptionInput value="system">{language.systemPrompt}</OptionInput>
<NumberInput value={0} marginBottom disabled/> </SelectInput>
<CheckInput name={language.untilChatEnd} check={true} onChange={() => { {/if}
if(promptItem.type === 'chat'){ {#if promptItem.type === 'chatML'}
promptItem.rangeEnd = 0 <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} {:else}
<NumberInput bind:value={promptItem.rangeEnd} marginBottom /> <span>{language.innerFormat}</span>
<CheckInput name={language.untilChatEnd} check={false} onChange={() => { <TextAreaInput highlight bind:value={promptItem.innerFormat}/>
if(promptItem.type === 'chat'){ <CheckInput name={language.customInnerFormat} check={true} className="mt-2" onChange={() => {
promptItem.rangeEnd = 'end' if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
promptItem.innerFormat = null
} }
}} /> }} />
{/if} {/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}
{/if} {/if}
</div> </div>

View File

@@ -411,7 +411,7 @@ export async function ParseMarkdown(
if(firstParsed !== data && char && char.type !== 'group'){ if(firstParsed !== data && char && char.type !== 'group'){
data = await parseAdditionalAssets(data, char, additionalAssetMode, 'post') data = await parseAdditionalAssets(data, char, additionalAssetMode, 'post')
} }
data = await parseInlayImages(data) data = await parseInlayImages(data ?? '')
data = encodeStyle(data) data = encodeStyle(data)
if(mode === 'normal'){ if(mode === 'normal'){
@@ -720,7 +720,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){ if(achara.type === 'group'){
return "" return ""
} }
return achara.personality return risuChatParser(achara.personality, matcherArg)
} }
case 'description': case 'description':
case 'char_desc':{ case 'char_desc':{
@@ -729,7 +729,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){ if(achara.type === 'group'){
return "" return ""
} }
return achara.desc return risuChatParser(achara.desc, matcherArg)
} }
case 'scenario':{ case 'scenario':{
const argChara = chara const argChara = chara
@@ -737,7 +737,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){ if(achara.type === 'group'){
return "" return ""
} }
return achara.scenario return risuChatParser(achara.scenario, matcherArg)
} }
case 'example_dialogue': case 'example_dialogue':
case 'example_message':{ case 'example_message':{
@@ -746,15 +746,15 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){ if(achara.type === 'group'){
return "" return ""
} }
return achara.exampleMessage return risuChatParser(achara.exampleMessage, matcherArg)
} }
case 'persona': case 'persona':
case 'user_persona':{ case 'user_persona':{
return getPersonaPrompt() return risuChatParser(getPersonaPrompt(), matcherArg)
} }
case 'main_prompt': case 'main_prompt':
case 'system_prompt':{ case 'system_prompt':{
return db.mainPrompt return risuChatParser(db.mainPrompt, matcherArg)
} }
case 'lorebook': case 'lorebook':
case 'world_info':{ case 'world_info':{
@@ -765,49 +765,56 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
const characterLore = (achara.type === 'group') ? [] : (achara.globalLore ?? []) const characterLore = (achara.type === 'group') ? [] : (achara.globalLore ?? [])
const chatLore = chat.localLore ?? [] const chatLore = chat.localLore ?? []
const fullLore = characterLore.concat(chatLore.concat(getModuleLorebooks())) const fullLore = characterLore.concat(chatLore.concat(getModuleLorebooks()))
return fullLore.map((f) => { return makeArray(fullLore.map((v) => {
return JSON.stringify(f) return JSON.stringify(v)
}).join("§\n") }))
} }
case 'history': case 'history':
case 'messages':{ case 'messages':{
const selchar = db.characters[get(selectedCharID)] const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage] const chat = selchar.chats[selchar.chatPage]
return chat.message.map((f) => { return makeArray([{
return f.role + ': ' + f.data role: 'char',
}).join("§\n") data: chat.fmIndex === -1 ? selchar.firstMessage : selchar.alternateGreetings[chat.fmIndex]
}].concat(chat.message).map((v) => {
v = safeStructuredClone(v)
v.data = risuChatParser(v.data, matcherArg)
return JSON.stringify(v)
}))
} }
case 'user_history': case 'user_history':
case 'user_messages':{ case 'user_messages':{
const selchar = db.characters[get(selectedCharID)] const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage] const chat = selchar.chats[selchar.chatPage]
return chat.message.map((f) => { return makeArray(chat.message.filter((v) => {
if(f.role === 'user'){ return v.role === 'user'
return f.data }).map((v) => {
} v = safeStructuredClone(v)
return '' v.data = risuChatParser(v.data, matcherArg)
}).filter((f) => { return JSON.stringify(v)
return f !== '' }))
}).join("§\n")
} }
case 'char_history': case 'char_history':
case 'char_messages':{ case 'char_messages':{
const selchar = db.characters[get(selectedCharID)] const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage] const chat = selchar.chats[selchar.chatPage]
return chat.message.map((f) => { return makeArray(chat.message.filter((v) => {
if(f.role === 'char'){ return v.role === 'char'
return f.data }).map((v) => {
} v = safeStructuredClone(v)
return '' v.data = risuChatParser(v.data, matcherArg)
}).filter((f) => { return JSON.stringify(v)
return f !== '' }))
}).join("§\n") }
case 'jb':
case 'jailbreak':{
return risuChatParser(db.jailbreak, matcherArg)
} }
case 'ujb': case 'ujb':
case 'global_note': case 'global_note':
case 'system_note':{ case 'system_note':{
return db.globalNote return risuChatParser(db.globalNote, matcherArg)
} }
case 'chat_index':{ case 'chat_index':{
return chatID.toString() return chatID.toString()
@@ -1038,9 +1045,9 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(!selchar || selchar.type === 'group'){ if(!selchar || selchar.type === 'group'){
return '' return ''
} }
return selchar.additionalAssets?.map((f) => { return makeArray(selchar.additionalAssets?.map((f) => {
return f[0] return f[0]
})?.join('§') ?? '' }))
} }
case 'prefill_supported':{ case 'prefill_supported':{
return db.aiModel.startsWith('claude') ? '1' : '0' return db.aiModel.startsWith('claude') ? '1' : '0'
@@ -1286,7 +1293,9 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
} }
case 'arraypush': case 'arraypush':
case 'array_push':{ case 'array_push':{
return arra[1] + '§' + arra[2] const arr = parseArray(arra[1])
arr.push(arra[2])
return makeArray(arr)
} }
case 'arraysplice': case 'arraysplice':
case 'array_splice':{ case 'array_splice':{
@@ -1351,14 +1360,13 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
const start = arr.length > 1 ? Number(arr[0]) : 0 const start = arr.length > 1 ? Number(arr[0]) : 0
const end = arr.length > 1 ? Number(arr[1]) : Number(arr[0]) const end = arr.length > 1 ? Number(arr[1]) : Number(arr[0])
const step = arr.length > 2 ? Number(arr[2]) : 1 const step = arr.length > 2 ? Number(arr[2]) : 1
let out = '' let out:string[] = []
for(let i=start;i<end;i+=step){ for(let i=start;i<end;i+=step){
out += i.toString() out.push(i.toString())
if(i + step < end){
out += '§'
}
} }
return out
return makeArray(out)
} }
case 'date': case 'date':
case 'time': case 'time':
@@ -1727,7 +1735,11 @@ function blockStartMatcher(p1:string,matcherArg:matcherArg):{type:blockMatch,typ
return {type:'pure-display'} return {type:'pure-display'}
} }
if(p1.startsWith('#each')){ if(p1.startsWith('#each')){
return {type:'each',type2:p1.substring(5).trim()} let t2 = p1.substring(5).trim()
if(t2.startsWith('as ')){
t2 = t2.substring(3).trim()
}
return {type:'each',type2:t2}
} }
if(p1.startsWith('#func')){ if(p1.startsWith('#func')){
const statement = p1.split(' ') const statement = p1.split(' ')
@@ -1831,6 +1843,12 @@ export function risuChatParser(da:string, arg:{
arg:string[] arg:string[]
}> = arg.functions ?? (new Map()) }> = arg.functions ?? (new Map())
arg.callStack = (arg.callStack ?? 0) + 1
if(arg.callStack > 20){
return 'ERROR: Call stack limit reached'
}
const matcherObj = { const matcherObj = {
chatID: chatID, chatID: chatID,
chara: chara, chara: chara,
@@ -1842,7 +1860,8 @@ export function risuChatParser(da:string, arg:{
role: arg.role, role: arg.role,
runVar: arg.runVar ?? false, runVar: arg.runVar ?? false,
consistantChar: arg.consistantChar ?? false, consistantChar: arg.consistantChar ?? false,
cbsConditions: arg.cbsConditions ?? {} cbsConditions: arg.cbsConditions ?? {},
callStack: arg.callStack,
} }
@@ -1971,7 +1990,7 @@ export function risuChatParser(da:string, arg:{
} }
} }
if(dat.startsWith('call::')){ if(dat.startsWith('call::')){
if(arg.callStack && arg.callStack > 10){ if(arg.callStack && arg.callStack > 20){
nested[0] += `ERROR: Call stack limit reached` nested[0] += `ERROR: Call stack limit reached`
break break
} }
@@ -1985,7 +2004,6 @@ export function risuChatParser(da:string, arg:{
data = data.replaceAll(`{{arg::${i}}}`, argData[i]) data = data.replaceAll(`{{arg::${i}}}`, argData[i])
} }
arg.functions = functions arg.functions = functions
arg.callStack = (arg.callStack ?? 0) + 1
nested[0] += risuChatParser(data, arg) nested[0] += risuChatParser(data, arg)
break break
} }
@@ -2280,7 +2298,7 @@ export function parseChatML(data:string):OpenAIChat[]|null{
return { return {
role: role, role: role,
content: v content: risuChatParser(v)
} }
}) })
} }

View File

@@ -28,6 +28,7 @@ import { runImageEmbedding } from "./transformers";
import { hanuraiMemory } from "./memory/hanuraiMemory"; import { hanuraiMemory } from "./memory/hanuraiMemory";
import { hypaMemoryV2 } from "./memory/hypav2"; import { hypaMemoryV2 } from "./memory/hypav2";
import { runLuaEditTrigger } from "./lua"; import { runLuaEditTrigger } from "./lua";
import { parseChatML } from "../parser.svelte";
export interface OpenAIChat{ export interface OpenAIChat{
role: 'system'|'user'|'assistant'|'function' role: 'system'|'user'|'assistant'|'function'
@@ -548,6 +549,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
await tokenizeChatArray([prompt]) await tokenizeChatArray([prompt])
break break
} }
case 'chatML':{
let prompts = parseChatML(card.text)
await tokenizeChatArray(prompts)
break
}
case 'chat':{ case 'chat':{
let start = card.rangeStart let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd
@@ -1007,6 +1013,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
pushPrompts([prompt]) pushPrompts([prompt])
break break
} }
case 'chatML':{
let prompts = parseChatML(card.text)
pushPrompts(prompts)
break
}
case 'chat':{ case 'chat':{
let start = card.rangeStart let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd 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 { alertError, alertNormal } from "../alert";
import type { OobaChatCompletionRequestParams } from "../model/ooba"; 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 PromptType = PromptItem['type'];
export type PromptSettings = { export type PromptSettings = {
assistantPrefill: string assistantPrefill: string
@@ -21,17 +21,26 @@ export interface PromptItemPlain {
type2: 'normal'|'globalNote'|'main' type2: 'normal'|'globalNote'|'main'
text: string; text: string;
role: 'user'|'bot'|'system'; role: 'user'|'bot'|'system';
name?: string
}
export interface PromptItemChatML {
type: 'chatML'
text: string
name?: string
} }
export interface PromptItemTyped { export interface PromptItemTyped {
type: 'persona'|'description'|'lorebook'|'postEverything'|'memory' type: 'persona'|'description'|'lorebook'|'postEverything'|'memory'
innerFormat?: string innerFormat?: string,
name?: string
} }
export interface PromptItemAuthorNote { export interface PromptItemAuthorNote {
type : 'authornote' type : 'authornote'
innerFormat?: string innerFormat?: string
defaultText?: string defaultText?: string
name?: string
} }
@@ -40,6 +49,7 @@ export interface PromptItemChat {
rangeStart: number; rangeStart: number;
rangeEnd: number|'end'; rangeEnd: number|'end';
chatAsOriginalOnSystem?: boolean; chatAsOriginalOnSystem?: boolean;
name?: string
} }
export async function tokenizePreset(prompts:PromptItem[], consti:boolean = false){ export async function tokenizePreset(prompts:PromptItem[], consti:boolean = false){

View File

@@ -12,7 +12,7 @@ import { defaultColorScheme, type ColorScheme } from '../gui/colorscheme';
import type { PromptItem, PromptSettings } from '../process/prompt'; import type { PromptItem, PromptSettings } from '../process/prompt';
import type { OobaChatCompletionRequestParams } from '../model/ooba'; import type { OobaChatCompletionRequestParams } from '../model/ooba';
export let appVer = "140.1.0" export let appVer = "141.0.0"
export let webAppSubVer = '' export let webAppSubVer = ''

View File

@@ -111,7 +111,7 @@ export async function runTranslator(text:string, reverse:boolean, from:string,ta
async function translateMain(text:string, arg:{from:string, to:string, host:string}){ async function translateMain(text:string, arg:{from:string, to:string, host:string}){
let db = getDatabase() let db = getDatabase()
if(db.translatorType === 'llm'){ if(db.translatorType === 'llm'){
const tr = db.translator || 'en' const tr = arg.to || 'en'
return translateLLM(text, {to: tr}) return translateLLM(text, {to: tr})
} }
if(db.translatorType === 'deepl'){ if(db.translatorType === 'deepl'){

View File

@@ -1 +1 @@
{"version":"140.1.0"} {"version":"141.0.0"}