Add convertion tool
This commit is contained in:
@@ -700,4 +700,7 @@ export const languageEnglish = {
|
||||
namespace: "Namespace",
|
||||
moduleIntergration: "Module Integration",
|
||||
previewInfo: "This preview shows prompt before model-specific processing.",
|
||||
miscTools: "Misc Tools",
|
||||
promptConvertion: "Prompt Convertion",
|
||||
convertionStep1: "Select all file related to the prompt (Context, Instruct and Sampler JSON is supported)",
|
||||
}
|
||||
@@ -10,8 +10,11 @@
|
||||
import { characterFormatUpdate, createBlankChar } from "src/ts/characters";
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase, setDatabase, type character } from "src/ts/storage/database";
|
||||
import PlaygroundImageGen from "./PlaygroundImageGen.svelte";
|
||||
import PlaygroundParser from "./PlaygroundParser.svelte";
|
||||
import PlaygroundImageGen from "./PlaygroundImageGen.svelte";
|
||||
import PlaygroundParser from "./PlaygroundParser.svelte";
|
||||
import ToolConvertion from "./ToolConvertion.svelte";
|
||||
|
||||
let easterEggTouch = 0
|
||||
|
||||
const playgroundChat = () => {
|
||||
let db = get(DataBase)
|
||||
@@ -81,6 +84,24 @@
|
||||
}}>
|
||||
<h1 class="text-2xl font-bold text-start">Parser</h1>
|
||||
</button>
|
||||
<button class="bg-darkbg rounded-md p-6 flex flex-col transition-shadow hover:ring-1" on:click={() => {
|
||||
PlaygroundStore.set(101)
|
||||
}}>
|
||||
<h1 class="text-2xl font-bold text-start">{language.promptConvertion}</h1>
|
||||
</button>
|
||||
<button class="bg-darkbg rounded-md p-6 flex flex-col transition-shadow hover:ring-1" on:click={() => {
|
||||
easterEggTouch += 1
|
||||
}}>
|
||||
<h1 class="text-2xl font-bold text-start">
|
||||
{#if easterEggTouch <= 10}
|
||||
🤗 Coming soon
|
||||
{:else if easterEggTouch <= 30}
|
||||
🤗 Still coming soon
|
||||
{:else if easterEggTouch <= 50}
|
||||
😇 Really soon
|
||||
{/if}
|
||||
</h1>
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
{#if $SizeStore.w < 1024}
|
||||
@@ -114,6 +135,9 @@
|
||||
{#if $PlaygroundStore === 8}
|
||||
<PlaygroundParser/>
|
||||
{/if}
|
||||
{#if $PlaygroundStore === 101}
|
||||
<ToolConvertion/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
49
src/lib/Playground/ToolConvertion.svelte
Normal file
49
src/lib/Playground/ToolConvertion.svelte
Normal file
@@ -0,0 +1,49 @@
|
||||
<script lang="ts">
|
||||
import { language } from "src/lang";
|
||||
import Button from "../UI/GUI/Button.svelte";
|
||||
import { selectMultipleFile } from "src/ts/util";
|
||||
import { detectPromptJSONType, promptConvertion } from "src/ts/process/prompt";
|
||||
|
||||
let files: { name: string, content: string, type:string }[] = []
|
||||
|
||||
const addFile = async () => {
|
||||
const selFiles = await selectMultipleFile(['json'])
|
||||
|
||||
for(let i = 0; i < selFiles.length; i++) {
|
||||
const file = selFiles[i]
|
||||
const text = new TextDecoder().decode(file.data)
|
||||
files.push({
|
||||
name: file.name,
|
||||
content: text,
|
||||
type: detectPromptJSONType(text),
|
||||
})
|
||||
}
|
||||
|
||||
console.log(files)
|
||||
files = files
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<h2 class="text-4xl text-textcolor my-6 font-black relative">{language.promptConvertion}</h2>
|
||||
<span class="text-textcolor2">{language.convertionStep1}</span>
|
||||
|
||||
<div class="border border-darkborderc flex flex-col rounded-md p-4 gap-2">
|
||||
{#each files as file, i}
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-start">
|
||||
{#if file.type !== 'NOTSUPPORTED'}
|
||||
<span class="bg-blue-500 rounded-md text-white mr-2 font-bold px-2 py-1">{file.type}</span>
|
||||
{:else}
|
||||
<span class="bg-red-500 rounded-md text-white mr-2 font-bold px-2 py-1">NOTSUPPORTED</span>
|
||||
{/if}
|
||||
<span>{file.name}</span>
|
||||
</div>
|
||||
<Button>Delete</Button>
|
||||
</div>
|
||||
{/each}
|
||||
<Button on:click={addFile}>Add</Button>
|
||||
</div>
|
||||
<Button className="mt-6" on:click={() => {
|
||||
promptConvertion(files)
|
||||
}}>Run</Button>
|
||||
@@ -1,6 +1,7 @@
|
||||
import { get } from "svelte/store";
|
||||
import { tokenizeAccurate } from "../tokenizer";
|
||||
import type { Database } from "../storage/database";
|
||||
import { DataBase, presetTemplate, setDatabase, type Database } from "../storage/database";
|
||||
import { alertError, alertNormal } from "../alert";
|
||||
|
||||
export type PromptItem = PromptItemPlain|PromptItemTyped|PromptItemChat|PromptItemAuthorNote;
|
||||
export type PromptType = PromptItem['type'];
|
||||
@@ -64,3 +65,350 @@ export async function tokenizePreset(prompts:PromptItem[], consti:boolean = fals
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
export function detectPromptJSONType(text:string){
|
||||
|
||||
function notNull<T>(x:T|null):x is T{
|
||||
return x !== null && x !== undefined
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(text)
|
||||
if(notNull(parsed.chat_completion_source) && Array.isArray(parsed.prompts)&& Array.isArray(parsed.prompt_order)){
|
||||
return "STCHAT"
|
||||
}
|
||||
else if(notNull(parsed.temp) && notNull(parsed.rep_pen) && notNull(parsed.min_length)){
|
||||
return "PARAMETERS"
|
||||
}
|
||||
else if(notNull(parsed.story_string) && notNull(parsed.chat_start)){
|
||||
return "STCONTEXT"
|
||||
}
|
||||
else if(notNull(parsed.input_sequence) && notNull(parsed.output_sequence)){
|
||||
return "STINST"
|
||||
}
|
||||
} catch (e) {}
|
||||
return 'NOTSUPPORTED'
|
||||
}
|
||||
|
||||
const typePriority = [
|
||||
'STINST',
|
||||
'PARAMETERS',
|
||||
'STCONTEXT',
|
||||
'STCHAT',
|
||||
]
|
||||
|
||||
|
||||
type InstData = {
|
||||
"system_prompt": string,
|
||||
"input_sequence": string,
|
||||
"output_sequence": string,
|
||||
"last_output_sequence": string,
|
||||
"system_sequence": string,
|
||||
"stop_sequence": string,
|
||||
"system_sequence_prefix": string,
|
||||
"system_sequence_suffix": string,
|
||||
"first_output_sequence": string,
|
||||
"output_suffix": string,
|
||||
"input_suffix": string,
|
||||
"system_suffix": string,
|
||||
"user_alignment_message": string,
|
||||
"system_same_as_user": boolean,
|
||||
"last_system_sequence": string,
|
||||
"first_input_sequence": string,
|
||||
"last_input_sequence": string,
|
||||
"name": string
|
||||
}
|
||||
|
||||
export function stChatConvert(pre:any){
|
||||
//ST preset
|
||||
let promptTemplate = []
|
||||
|
||||
function findPrompt(identifier:number){
|
||||
return pre.prompts.find((p:any) => p.identifier === identifier)
|
||||
}
|
||||
|
||||
for(const prompt of pre?.prompt_order?.[0]?.order){
|
||||
if(!prompt?.enabled){
|
||||
continue
|
||||
}
|
||||
const p = findPrompt(prompt?.identifier ?? '')
|
||||
if(p){
|
||||
switch(p.identifier){
|
||||
case 'main':{
|
||||
promptTemplate.push({
|
||||
type: 'plain',
|
||||
type2: 'main',
|
||||
text: p.content ?? "",
|
||||
role: p.role ?? "system"
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'jailbreak':
|
||||
case 'nsfw':{
|
||||
promptTemplate.push({
|
||||
type: 'jailbreak',
|
||||
type2: 'normal',
|
||||
text: p.content ?? "",
|
||||
role: p.role ?? "system"
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'dialogueExamples':
|
||||
case 'charPersonality':
|
||||
case 'scenario':{
|
||||
break //ignore
|
||||
}
|
||||
case 'chatHistory':{
|
||||
promptTemplate.push({
|
||||
type: 'chat',
|
||||
rangeEnd: 'end',
|
||||
rangeStart: 0
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'worldInfoBefore':{
|
||||
promptTemplate.push({
|
||||
type: 'lorebook'
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'worldInfoAfter':{
|
||||
break
|
||||
}
|
||||
case 'charDescription':{
|
||||
promptTemplate.push({
|
||||
type: 'description'
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'personaDescription':{
|
||||
promptTemplate.push({
|
||||
type: 'persona'
|
||||
})
|
||||
break
|
||||
}
|
||||
default:{
|
||||
console.log(p)
|
||||
promptTemplate.push({
|
||||
type: 'plain',
|
||||
type2: 'normal',
|
||||
text: p.content ?? "",
|
||||
role: p.role ?? "system"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
console.log("Prompt not found", prompt)
|
||||
|
||||
}
|
||||
}
|
||||
if(pre?.assistant_prefill){
|
||||
promptTemplate.push({
|
||||
type: 'postEverything'
|
||||
})
|
||||
promptTemplate.push({
|
||||
type: 'plain',
|
||||
type2: 'main',
|
||||
text: `{{#if {{prefill_supported}}}}${pre?.assistant_prefill}{{/if}}`,
|
||||
role: 'bot'
|
||||
})
|
||||
}
|
||||
|
||||
return promptTemplate
|
||||
}
|
||||
|
||||
export function promptConvertion(files:{ name: string, content: string, type:string }[]){
|
||||
let preset = structuredClone(presetTemplate)
|
||||
let instData = {
|
||||
"system_prompt": "",
|
||||
"input_sequence": "",
|
||||
"output_sequence": "",
|
||||
"last_output_sequence": "",
|
||||
"system_sequence": "",
|
||||
"stop_sequence": "",
|
||||
"system_sequence_prefix": "",
|
||||
"system_sequence_suffix": "",
|
||||
"first_output_sequence": "",
|
||||
"output_suffix": "",
|
||||
"input_suffix": "",
|
||||
"system_suffix": "",
|
||||
"user_alignment_message": "",
|
||||
"system_same_as_user": false,
|
||||
"last_system_sequence": "",
|
||||
"first_input_sequence": "",
|
||||
"last_input_sequence": "",
|
||||
"name": ""
|
||||
}
|
||||
let story_string = ''
|
||||
let chat_start = ''
|
||||
preset.name = ''
|
||||
|
||||
let type = ''
|
||||
|
||||
files = files.filter(x=>x.type !== 'NOTSUPPORTED').sort((a,b)=>{
|
||||
return typePriority.indexOf(a.type) - typePriority.indexOf(b.type)
|
||||
})
|
||||
|
||||
|
||||
if(files.findIndex(x=>x.type === 'STINST') !== -1){
|
||||
type = 'STINST'
|
||||
}
|
||||
if(files.findIndex(x=>x.type === 'STCHAT') !== -1){
|
||||
if(type !== ''){
|
||||
alertError(`Both ${type} and STCHAT are not supported together.`)
|
||||
return
|
||||
}
|
||||
type = 'STCHAT'
|
||||
}
|
||||
|
||||
let samplers:string[] = []
|
||||
const getParam = (setname:keyof(typeof preset), getname:string = '', arg:{
|
||||
multiplier?: number
|
||||
}={}) => {
|
||||
if(getname === ''){
|
||||
getname = setname
|
||||
}
|
||||
let multiplier = arg.multiplier ?? 1
|
||||
if(samplers.includes(getname)){
|
||||
// @ts-ignore
|
||||
preset[setname] = data[getname] * multiplier
|
||||
}
|
||||
else{
|
||||
// @ts-ignore
|
||||
preset[setname] = -1000
|
||||
}
|
||||
}
|
||||
|
||||
for(let i=0;i<files.length;i++){
|
||||
const file = files[i]
|
||||
const data = JSON.parse(file.content)
|
||||
preset.name ||= instData.name ?? ''
|
||||
switch(file.type){
|
||||
case 'STINST':{
|
||||
instData = data as InstData
|
||||
if(data.system_same_as_user){
|
||||
instData.system_sequence = ''
|
||||
instData.system_sequence_prefix = instData.input_sequence
|
||||
instData.system_sequence_suffix = instData.output_sequence
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'PARAMETERS':{
|
||||
samplers = data.samplers
|
||||
getParam('temperature', 'temp', {multiplier: 100})
|
||||
getParam('top_p')
|
||||
getParam('top_k')
|
||||
getParam('top_a')
|
||||
getParam('min_p')
|
||||
getParam('repetition_penalty', 'rep_pen')
|
||||
getParam('frequencyPenalty', 'freq_pen', {multiplier: 100})
|
||||
getParam('PresensePenalty', 'presence_penalty', {multiplier: 100})
|
||||
break
|
||||
}
|
||||
case 'STCONTEXT':{
|
||||
story_string = data.story_string
|
||||
chat_start = data.chat_start
|
||||
break
|
||||
}
|
||||
case 'STCHAT':{
|
||||
samplers = []
|
||||
getParam('temperature', 'temperature', {multiplier: 100})
|
||||
getParam('top_p')
|
||||
getParam('top_k')
|
||||
getParam('top_a')
|
||||
getParam('min_p')
|
||||
getParam('repetition_penalty', 'repetition_penalty')
|
||||
getParam('frequencyPenalty', 'frequency_penalty', {multiplier: 100})
|
||||
getParam('PresensePenalty', 'presence_penalty', {multiplier: 100})
|
||||
const prompts = stChatConvert(data)
|
||||
preset.promptTemplate = prompts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(type === 'STCHAT'){
|
||||
preset.aiModel = 'openrouter'
|
||||
preset.subModel = 'openrouter'
|
||||
const db = get(DataBase)
|
||||
db.botPresets.push(preset)
|
||||
setDatabase(db)
|
||||
|
||||
alertNormal('Preset converted successfully. You can find it in bot setting presets')
|
||||
return
|
||||
}
|
||||
|
||||
preset.promptTemplate = [{
|
||||
type: 'plain',
|
||||
type2: 'main',
|
||||
text: '',
|
||||
role: 'system'
|
||||
},{
|
||||
type: 'description',
|
||||
},{
|
||||
type: 'persona',
|
||||
},{
|
||||
type: 'lorebook',
|
||||
},{
|
||||
type: 'chat',
|
||||
rangeStart: 0,
|
||||
rangeEnd: 'end',
|
||||
}, {
|
||||
type: 'authornote',
|
||||
}, {
|
||||
type: 'plain',
|
||||
type2: 'globalNote',
|
||||
text: '',
|
||||
role: 'system'
|
||||
}]
|
||||
|
||||
|
||||
|
||||
//build a jinja template from the instData
|
||||
let jinja = ''
|
||||
|
||||
jinja += story_string
|
||||
.replace(/{{user}}/gi, '{{risu_user}}')
|
||||
.replace(/{{user}}/gi, '{{risu_user}}')
|
||||
.replace(/{{system_prompt}}/gi, instData.system_prompt)
|
||||
.replace(/{{system}}/gi, instData.system_prompt)
|
||||
.replace(/{{#if (.+?){{\/if}}/gis, '')
|
||||
.replace(/{{(.+?)}}/gi, '')
|
||||
.replace(/\n\n+/g, '\n\n')
|
||||
jinja += chat_start
|
||||
jinja += `{% for message in messages %}`
|
||||
jinja += `{% if message.role == 'user' %}`
|
||||
jinja += instData.input_sequence
|
||||
jinja += `{{ message.content }}`
|
||||
jinja += instData.input_suffix
|
||||
jinja += `{% endif %}`
|
||||
jinja += `{% if message.role == 'assistant' %}`
|
||||
jinja += instData.output_sequence
|
||||
jinja += `{{ message.content }}`
|
||||
jinja += instData.output_suffix
|
||||
jinja += `{% endif %}`
|
||||
jinja += `{% if message.role == 'system' %}`
|
||||
jinja += instData.system_sequence
|
||||
jinja += instData.system_sequence_prefix
|
||||
jinja += `{{ message.content }}`
|
||||
jinja += instData.system_sequence_suffix
|
||||
jinja += instData.system_suffix
|
||||
jinja += `{% endif %}`
|
||||
jinja += `{% endfor %}`
|
||||
jinja += instData.output_sequence
|
||||
|
||||
preset.instructChatTemplate = "jinja"
|
||||
preset.JinjaTemplate = jinja
|
||||
preset.aiModel = 'openrouter'
|
||||
preset.subModel = 'openrouter'
|
||||
preset.useInstructPrompt = true
|
||||
|
||||
preset.name ||= 'Converted from JSON'
|
||||
|
||||
|
||||
const db = get(DataBase)
|
||||
db.botPresets.push(preset)
|
||||
setDatabase(db)
|
||||
|
||||
alertNormal('Preset converted successfully. You can find it in bot setting presets')
|
||||
}
|
||||
@@ -977,6 +977,9 @@ export interface botPreset{
|
||||
customPromptTemplateToggle?:string
|
||||
templateDefaultVariables?:string
|
||||
moduleIntergration?:string
|
||||
top_k?:number
|
||||
instructChatTemplate?:string
|
||||
JinjaTemplate?:string
|
||||
}
|
||||
|
||||
|
||||
@@ -1257,6 +1260,9 @@ export function saveCurrentPreset(){
|
||||
customPromptTemplateToggle: db.customPromptTemplateToggle ?? "",
|
||||
templateDefaultVariables: db.templateDefaultVariables ?? "",
|
||||
moduleIntergration: db.moduleIntergration ?? "",
|
||||
top_k: db.top_k,
|
||||
instructChatTemplate: db.instructChatTemplate,
|
||||
JinjaTemplate: db.JinjaTemplate ?? ''
|
||||
}
|
||||
db.botPresets = pres
|
||||
setDatabase(db)
|
||||
@@ -1342,6 +1348,9 @@ export function setPreset(db:Database, newPres: botPreset){
|
||||
db.customPromptTemplateToggle = newPres.customPromptTemplateToggle ?? ''
|
||||
db.templateDefaultVariables = newPres.templateDefaultVariables ?? ''
|
||||
db.moduleIntergration = newPres.moduleIntergration ?? ''
|
||||
db.top_k = newPres.top_k ?? db.top_k
|
||||
db.instructChatTemplate = newPres.instructChatTemplate ?? db.instructChatTemplate
|
||||
db.JinjaTemplate = newPres.JinjaTemplate ?? db.JinjaTemplate
|
||||
return db
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user