diff --git a/src/lang/en.ts b/src/lang/en.ts
index 1a82b1d2..cb866e62 100644
--- a/src/lang/en.ts
+++ b/src/lang/en.ts
@@ -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)",
}
\ No newline at end of file
diff --git a/src/lib/Playground/PlaygroundMenu.svelte b/src/lib/Playground/PlaygroundMenu.svelte
index 84f9a699..9359c1fb 100644
--- a/src/lib/Playground/PlaygroundMenu.svelte
+++ b/src/lib/Playground/PlaygroundMenu.svelte
@@ -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 @@
}}>
Parser
+
+
{:else}
{#if $SizeStore.w < 1024}
@@ -114,6 +135,9 @@
{#if $PlaygroundStore === 8}
{/if}
+ {#if $PlaygroundStore === 101}
+
+ {/if}
{/if}
\ No newline at end of file
diff --git a/src/lib/Playground/ToolConvertion.svelte b/src/lib/Playground/ToolConvertion.svelte
new file mode 100644
index 00000000..58f46d2f
--- /dev/null
+++ b/src/lib/Playground/ToolConvertion.svelte
@@ -0,0 +1,49 @@
+
+
+{language.promptConvertion}
+{language.convertionStep1}
+
+
+ {#each files as file, i}
+
+
+ {#if file.type !== 'NOTSUPPORTED'}
+ {file.type}
+ {:else}
+ NOTSUPPORTED
+ {/if}
+ {file.name}
+
+
+
+ {/each}
+
+
+
\ No newline at end of file
diff --git a/src/ts/process/prompt.ts b/src/ts/process/prompt.ts
index 1b5b1aea..7a73a109 100644
--- a/src/ts/process/prompt.ts
+++ b/src/ts/process/prompt.ts
@@ -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(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