Add convertion tool

This commit is contained in:
kwaroran
2024-09-09 03:09:36 +09:00
parent e334551976
commit 7c69a46170
5 changed files with 436 additions and 3 deletions

View File

@@ -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')
}

View File

@@ -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
}