Merge branch 'main' of https://github.com/kwaroran/RisuAI
This commit is contained in:
9
src/ts/process/generateSeed.ts
Normal file
9
src/ts/process/generateSeed.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export function generateRandomSeed(length) {
|
||||
let result = '';
|
||||
const characters = '0123456789';
|
||||
const charactersLength = characters.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
15
src/ts/process/processzip.ts
Normal file
15
src/ts/process/processzip.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import JSZip from "jszip";
|
||||
|
||||
export async function processZip(dataArray: Uint8Array): Promise<string> {
|
||||
const blob = new Blob([dataArray], { type: "application/zip" });
|
||||
const zip = new JSZip();
|
||||
const zipData = await zip.loadAsync(blob);
|
||||
|
||||
const imageFile = Object.keys(zipData.files).find(fileName => /\.(jpg|jpeg|png)$/.test(fileName));
|
||||
if (imageFile) {
|
||||
const imageData = await zipData.files[imageFile].async("base64");
|
||||
return `data:image/png;base64,${imageData}`;
|
||||
} else {
|
||||
throw new Error("No image found in ZIP file");
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,13 @@ import { get } from "svelte/store"
|
||||
import { DataBase, type character } from "../storage/database"
|
||||
import { requestChatData } from "./request"
|
||||
import { alertError } from "../alert"
|
||||
import { globalFetch } from "../storage/globalApi"
|
||||
import { globalFetch, readImage } from "../storage/globalApi"
|
||||
import { CharEmotion } from "../stores"
|
||||
import type { OpenAIChat } from "."
|
||||
|
||||
|
||||
import { processZip } from "./processzip"
|
||||
import { convertToBase64 } from "./uinttobase64"
|
||||
import type { List } from "lodash"
|
||||
import { generateRandomSeed } from "./generateSeed"
|
||||
export async function stableDiff(currentChar:character,prompt:string){
|
||||
const mainPrompt = "assistant is a chat analyzer.\nuser will input a data of situation with key and values before chat, and a chat of a user and character.\nView the status of the chat and change the data.\nif data's key starts with $, it must change it every time.\nif data value is none, it must change it."
|
||||
let db = get(DataBase)
|
||||
@@ -129,7 +131,7 @@ export async function stableDiff(currentChar:character,prompt:string){
|
||||
"cfg_scale": db.sdCFG,
|
||||
"prompt": prompts.join(','),
|
||||
"negative_prompt": neg,
|
||||
'sampler_name': db.sdConfig.sampler_name,
|
||||
"sampler_name": db.sdConfig.sampler_name,
|
||||
"enable_hr": db.sdConfig.enable_hr,
|
||||
"denoising_strength": db.sdConfig.denoising_strength,
|
||||
"hr_scale": db.sdConfig.hr_scale,
|
||||
@@ -161,6 +163,113 @@ export async function stableDiff(currentChar:character,prompt:string){
|
||||
return false
|
||||
}
|
||||
}
|
||||
if(db.sdProvider === 'novelai'){
|
||||
|
||||
let prompts:string[] = []
|
||||
let neg = ''
|
||||
for(let i=0;i<currentSd.length;i++){
|
||||
if(currentSd[i][0] !== 'negative'){
|
||||
prompts.push(currentSd[i][1])
|
||||
}
|
||||
else{
|
||||
neg = currentSd[i][1]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let reqlist= {}
|
||||
|
||||
if(db.NAII2I){
|
||||
let base64img = ''
|
||||
if(db.NAIImgConfig.image === ''){
|
||||
const charimg = currentChar.image;
|
||||
|
||||
const img = await readImage(charimg)
|
||||
const base64 = await convertToBase64(img);
|
||||
base64img = base64.split('base64,')[1];
|
||||
}else{
|
||||
base64img = db.NAIImgConfig.image.split('base64,')[1];
|
||||
}
|
||||
|
||||
let randomseed = generateRandomSeed(10);
|
||||
let seed = parseInt(randomseed, 10);
|
||||
reqlist = {
|
||||
body: {
|
||||
"action": "img2img",
|
||||
"input": prompts.join(','),
|
||||
"model": db.NAIImgModel,
|
||||
"parameters": {
|
||||
"seed": seed,
|
||||
"extra_noise_seed": seed,
|
||||
"add_original_image": false,
|
||||
"cfg_rescale": 0,
|
||||
"controlnet_strength": 1,
|
||||
"dynamic_threshold": false,
|
||||
"n_samples": 1,
|
||||
"width": db.NAIImgConfig.width,
|
||||
"height": db.NAIImgConfig.height,
|
||||
"sampler": db.NAIImgConfig.sampler,
|
||||
"steps": db.NAIImgConfig.steps,
|
||||
"scale": db.NAIImgConfig.scale,
|
||||
"negative_prompt": neg,
|
||||
"sm": false,
|
||||
"sm_dyn": false,
|
||||
"noise": db.NAIImgConfig.noise,
|
||||
"noise_schedule": "native",
|
||||
"strength": db.NAIImgConfig.strength,
|
||||
"image": base64img,
|
||||
"ucPreset": 2,
|
||||
"uncond_scale": 1
|
||||
}
|
||||
},
|
||||
headers:{
|
||||
"Authorization": "Bearer " + db.NAIApiKey
|
||||
}
|
||||
}
|
||||
}else{
|
||||
reqlist = {
|
||||
body: {
|
||||
"input": prompts.join(','),
|
||||
"model": db.NAIImgModel,
|
||||
"parameters": {
|
||||
"width": db.NAIImgConfig.width,
|
||||
"height": db.NAIImgConfig.height,
|
||||
"sampler": db.NAIImgConfig.sampler,
|
||||
"steps": db.NAIImgConfig.steps,
|
||||
"scale": db.NAIImgConfig.scale,
|
||||
"negative_prompt": neg,
|
||||
"sm": db.NAIImgConfig.sm,
|
||||
"sm_dyn": db.NAIImgConfig.sm_dyn
|
||||
}
|
||||
},
|
||||
headers:{
|
||||
"Authorization": "Bearer " + db.NAIApiKey
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
const da = await globalFetch(db.NAIImgUrl, reqlist)
|
||||
|
||||
if(da){
|
||||
let charemotions = get(CharEmotion)
|
||||
const img = await processZip(da.data);
|
||||
const emos:[string, string,number][] = [[img, img, Date.now()]]
|
||||
charemotions[currentChar.chaId] = emos
|
||||
CharEmotion.set(charemotions)
|
||||
}
|
||||
else{
|
||||
alertError(JSON.stringify(da.data))
|
||||
return false
|
||||
}
|
||||
|
||||
return returnSdData
|
||||
|
||||
|
||||
} catch (error) {
|
||||
alertError(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@@ -139,8 +139,29 @@ export async function sayTTS(character:character,text:string) {
|
||||
}
|
||||
|
||||
}
|
||||
case 'novelai': {
|
||||
const audioContext = new AudioContext();
|
||||
const response = await fetch(`https://api.novelai.net/ai/generate-voice?text=${text}&voice=-1&seed=${character.naittsConfig.voice}&opus=false&version=${character.naittsConfig.version}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Authorization": "Bearer " + db.NAIApiKey,
|
||||
}
|
||||
});
|
||||
|
||||
if (response.status === 200 && response.headers.get('content-type') === 'audio/mpeg') {
|
||||
const audioBuffer = await response.arrayBuffer();
|
||||
audioContext.decodeAudioData(audioBuffer, (decodedData) => {
|
||||
const sourceNode = audioContext.createBufferSource();
|
||||
sourceNode.buffer = decodedData;
|
||||
sourceNode.connect(audioContext.destination);
|
||||
sourceNode.start();
|
||||
});
|
||||
} else {
|
||||
alertError("Error fetching or decoding audio data");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const oaiVoices = [
|
||||
@@ -189,4 +210,29 @@ export async function getVOICEVOXVoices() {
|
||||
})
|
||||
speakersInfo.unshift({ name: "None", list: null})
|
||||
return speakersInfo;
|
||||
}
|
||||
|
||||
export async function getNovelAIVoices(){
|
||||
return [
|
||||
{
|
||||
gender: "UNISEX",
|
||||
voices: ['Anananan']
|
||||
},
|
||||
{
|
||||
gender: "FEMALE",
|
||||
voices: ['Aini', 'Orea', 'Claea', 'Lim', 'Aurae', 'Naia']
|
||||
},
|
||||
{
|
||||
gender: "MALE",
|
||||
voices: ['Aulon', 'Elei', 'Ogma', 'Raid', 'Pega', 'Lam']
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
export async function FixNAITTS(data:character){
|
||||
if (data.naittsConfig === undefined){
|
||||
data.naittsConfig.voice = 'Anananan'
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
17
src/ts/process/uinttobase64.ts
Normal file
17
src/ts/process/uinttobase64.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export async function convertToBase64(data: Uint8Array): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const blob = new Blob([data]);
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onloadend = function() {
|
||||
const base64String = reader.result as string;
|
||||
resolve(base64String);
|
||||
};
|
||||
|
||||
reader.onerror = function(error) {
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
@@ -174,6 +174,18 @@ export function setDatabase(data:Database){
|
||||
if(checkNullish(data.sdCFG)){
|
||||
data.sdCFG = 7
|
||||
}
|
||||
if(checkNullish(data.NAIImgUrl)){
|
||||
data.NAIImgUrl = 'https://api.novelai.net/ai/generate-image'
|
||||
}
|
||||
if(checkNullish(data.NAIApiKey)){
|
||||
data.NAIApiKey = ''
|
||||
}
|
||||
if(checkNullish(data.NAIImgModel)){
|
||||
data.NAIImgModel = 'nai-diffusion-3'
|
||||
}
|
||||
if(checkNullish(data.NAII2I)){
|
||||
data.NAII2I = true
|
||||
}
|
||||
if(checkNullish(data.textTheme)){
|
||||
data.textTheme = "standard"
|
||||
}
|
||||
@@ -231,6 +243,20 @@ export function setDatabase(data:Database){
|
||||
hr_upscaler:"Latent"
|
||||
}
|
||||
}
|
||||
if(checkNullish(data.NAIImgConfig)){
|
||||
data.NAIImgConfig = {
|
||||
width:512,
|
||||
height:768,
|
||||
sampler:"k_dpmpp_sde",
|
||||
steps:28,
|
||||
scale:5,
|
||||
sm:true,
|
||||
sm_dyn:true,
|
||||
noise:0.0,
|
||||
strength:0.3,
|
||||
image:""
|
||||
}
|
||||
}
|
||||
if(checkNullish(data.customTextTheme)){
|
||||
data.customTextTheme = {
|
||||
FontColorStandard: "#f8f8f2",
|
||||
@@ -394,6 +420,11 @@ export interface Database{
|
||||
sdSteps:number
|
||||
sdCFG:number
|
||||
sdConfig:sdConfig
|
||||
NAIImgUrl:string
|
||||
NAIApiKey:string
|
||||
NAIImgModel:string
|
||||
NAII2I:boolean
|
||||
NAIImgConfig:NAIImgConfig
|
||||
runpodKey:string
|
||||
promptPreprocess:boolean
|
||||
bias: [string, number][]
|
||||
@@ -588,6 +619,11 @@ export interface character{
|
||||
INTONATION_SCALE?: number
|
||||
VOLUME_SCALE?: number
|
||||
}
|
||||
naittsConfig?:{
|
||||
customvoice?: boolean
|
||||
voice?: string
|
||||
version?: string
|
||||
}
|
||||
supaMemory?:boolean
|
||||
additionalAssets?:[string, string, string][]
|
||||
ttsReadOnlyQuoted?:boolean
|
||||
@@ -717,6 +753,18 @@ interface sdConfig{
|
||||
hr_upscaler:string
|
||||
}
|
||||
|
||||
interface NAIImgConfig{
|
||||
width:number,
|
||||
height:number,
|
||||
sampler:string,
|
||||
steps:number,
|
||||
scale:number,
|
||||
sm:boolean,
|
||||
sm_dyn:boolean,
|
||||
noise:number,
|
||||
strength:number,
|
||||
image:string
|
||||
}
|
||||
export type FormatingOrderItem = 'main'|'jailbreak'|'chats'|'lorebook'|'globalNote'|'authorNote'|'lastChat'|'description'|'postEverything'|'personaPrompt'
|
||||
|
||||
export interface Chat{
|
||||
|
||||
@@ -661,7 +661,7 @@ export async function globalFetch(url:string, arg:{
|
||||
method: method,
|
||||
signal: arg.abortSignal
|
||||
})
|
||||
|
||||
|
||||
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
|
||||
return {
|
||||
ok: da.ok && da.status >= 200 && da.status < 300,
|
||||
@@ -685,6 +685,16 @@ export async function globalFetch(url:string, arg:{
|
||||
headers: headers,
|
||||
method: method
|
||||
})
|
||||
if(da.headers.get('content-type')?.includes('application/x-zip-compressed')){
|
||||
const daText = await da.blob()
|
||||
|
||||
addFetchLog(daText, da.ok && da.status >= 200 && da.status < 300)
|
||||
return {
|
||||
ok: da.ok && da.status >= 200 && da.status < 300,
|
||||
data: daText,
|
||||
headers: Object.fromEntries(da.headers)
|
||||
}
|
||||
}
|
||||
const daText = await da.text()
|
||||
try {
|
||||
const dat = JSON.parse(daText)
|
||||
|
||||
Reference in New Issue
Block a user