From 220c2c091b5cea7860dba2d68a442731d8f0d8cd Mon Sep 17 00:00:00 2001 From: kwaroran Date: Tue, 28 Nov 2023 04:32:27 +0900 Subject: [PATCH] [feat] add llm translation --- src/lang/en.ts | 1 + src/lib/ChatScreens/DefaultChatScreen.svelte | 30 +++++++++- src/lib/Setting/Pages/LanguageSettings.svelte | 7 +++ src/ts/storage/database.ts | 3 +- src/ts/translator/translator.ts | 55 ++++++++++++++++++- 5 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/lang/en.ts b/src/lang/en.ts index bfea2e23..54dad85e 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -457,4 +457,5 @@ export const languageEnglish = { imgGenPrompt: "Image Generation Prompt", imgGenNegatives: "Image Generation Negative Prompt", imgGenInstructions: "Image Generation Instructions", + translationPrompt: "Translation Prompt", } \ No newline at end of file diff --git a/src/lib/ChatScreens/DefaultChatScreen.svelte b/src/lib/ChatScreens/DefaultChatScreen.svelte index 3a2a058c..8e88294f 100644 --- a/src/lib/ChatScreens/DefaultChatScreen.svelte +++ b/src/lib/ChatScreens/DefaultChatScreen.svelte @@ -8,7 +8,7 @@ import { doingChat, sendChat } from "../../ts/process/index"; import { findCharacterbyId, messageForm, sleep } from "../../ts/util"; import { language } from "../../lang"; - import { translate } from "../../ts/translator/translator"; + import { isExpTranslator, translate } from "../../ts/translator/translator"; import { alertError, alertNormal, alertWait } from "../../ts/alert"; import sendSound from '../../etc/send.mp3' import {cloneDeep} from 'lodash' @@ -251,7 +251,33 @@ $: updateInputSizeAll() - function updateInputTransateMessage(reverse: boolean) { + async function updateInputTransateMessage(reverse: boolean) { + if(isExpTranslator()){ + if(!reverse){ + messageInputTranslate = '' + return + } + if(messageInputTranslate === '') { + messageInput = '' + return + } + const lastMessageInputTranslate = messageInputTranslate + await sleep(1500) + if(lastMessageInputTranslate === messageInputTranslate){ + console.log(lastMessageInputTranslate === messageInputTranslate) + console.log(lastMessageInputTranslate, messageInputTranslate) + translate(reverse ? messageInputTranslate : messageInput, reverse).then((translatedMessage) => { + if(translatedMessage){ + if(reverse) + messageInput = translatedMessage + else + messageInputTranslate = translatedMessage + } + }) + } + return + + } if(reverse && messageInputTranslate === '') { messageInput = '' return diff --git a/src/lib/Setting/Pages/LanguageSettings.svelte b/src/lib/Setting/Pages/LanguageSettings.svelte index 5b50227a..6c4b26f8 100644 --- a/src/lib/Setting/Pages/LanguageSettings.svelte +++ b/src/lib/Setting/Pages/LanguageSettings.svelte @@ -10,6 +10,7 @@ import { downloadFile } from "src/ts/storage/globalApi"; import { languageEnglish } from "src/lang/en"; import TextInput from "src/lib/UI/GUI/TextInput.svelte"; + import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte"; let langChanged = false

{language.language}

@@ -56,6 +57,7 @@ Google DeepL + Ax. Model {#if $DataBase.translatorType === 'deepl'} @@ -69,6 +71,11 @@ {/if} + {#if $DataBase.translatorType === 'llm'} + {language.translationPrompt} + + {/if} +
diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts index 7e2e50ba..a094635e 100644 --- a/src/ts/storage/database.ts +++ b/src/ts/storage/database.ts @@ -520,7 +520,7 @@ export interface Database{ mancerHeader:string emotionProcesser:'submodel'|'embedding', showMenuChatList?:boolean, - translatorType:'google'|'deepl'|'none', + translatorType:'google'|'deepl'|'none'|'llm', NAIadventure?:boolean, NAIappendName?:boolean, deeplOptions:{ @@ -541,6 +541,7 @@ export interface Database{ automark?:boolean huggingfaceKey:string allowAllExtentionFiles?:boolean + translatorPrompt:string } export interface customscript{ diff --git a/src/ts/translator/translator.ts b/src/ts/translator/translator.ts index 9b7de9eb..90d6cb7a 100644 --- a/src/ts/translator/translator.ts +++ b/src/ts/translator/translator.ts @@ -3,6 +3,8 @@ import { translatorPlugin } from "../plugins/plugins" import { DataBase } from "../storage/database" import { globalFetch } from "../storage/globalApi" import { alertError } from "../alert" +import { requestChatData } from "../process/request" +import { doingChat } from "../process" let cache={ origin: [''], @@ -98,12 +100,16 @@ export async function runTranslator(text:string, reverse:boolean, from:string,ta async function translateMain(text:string, arg:{from:string, to:string, host:string}){ let db = get(DataBase) - + if(db.translatorType === 'llm'){ + const tr = db.translator || 'en' + return translateLLM(text, {to: tr}) + } if(db.translatorType === 'deepl'){ let url = db.deeplOptions.freeApi ? "https://api-free.deepl.com/v2/translate" : "https://api.deepl.com/v2/translate" const f = await globalFetch(url, { headers: { "Authorization": "DeepL-Auth-Key " + db.deeplOptions.key, + "Content-Type": "application/json" }, body: { text: text, @@ -162,9 +168,23 @@ async function jaTrans(text:string) { return await runTranslator(text, true, 'en','ja') } - +export function isExpTranslator(){ + const db = get(DataBase) + return db.translatorType === 'llm' || db.translatorType === 'deepl' +} export async function translateHTML(html: string, reverse:boolean): Promise { + let db = get(DataBase) + let DoingChat = get(doingChat) + if(DoingChat){ + if(isExpTranslator()){ + return html + } + } + if(db.translatorType === 'llm'){ + const tr = db.translator || 'en' + return translateLLM(html, {to: tr}) + } const dom = new DOMParser().parseFromString(html, 'text/html'); console.log(html) @@ -219,4 +239,35 @@ export async function translateHTML(html: string, reverse:boolean): Promise tags if needed return translatedHTML +} + +let llmCache = new Map() +async function translateLLM(text:string, arg:{to:string}){ + if(llmCache.has(text)){ + return llmCache.get(text) + } + const db = get(DataBase) + let prompt = db.translatorPrompt || `You are a translator. translate the following html or text into {{slot}}. do not output anything other than the translation.` + prompt = prompt.replace('{{slot}}', arg.to) + const rq = await requestChatData({ + formated: [ + { + 'role': 'system', + 'content': prompt + }, + { + 'role': 'user', + 'content': text + } + ], + bias: {}, + useStreaming: false, + }, 'submodel') + + if(rq.type === 'fail' || rq.type === 'streaming' || rq.type === 'multiline'){ + alertError(`${rq.result}`) + return text + } + llmCache.set(text, rq.result) + return rq.result } \ No newline at end of file