Add fal.ai support
This commit is contained in:
@@ -134,7 +134,7 @@ export const languageEnglish = {
|
||||
legacyTranslation: "If enabled, it will use the old translation method, which preprocess markdown and quotes before translations instead of postprocessing after translations.",
|
||||
luaHelp: "You can use Lua scripts as a trigger script. you can define onInput, onOutput, onStart functions. onInput is called when user sends a message, onOutput is called when character sends a message, onStart is called when the chat starts. for more information, see the documentation.",
|
||||
claudeCachingExperimental: "Caching in Claude is experimental feature that can reduce the cost of the model, but it can also increase the cost if you use it without reroll. since this is a experimental feature, it can be unstable and behavior can be changed in the future.",
|
||||
|
||||
urllora: "You can use direct download link of the model file. you can make direct url from google drive like website like https://sites.google.com/site/gdocs2direct/ , or use civitai URL, copy the the AIR (looks like `urn:air:flux1:lora:civitai:180891@776656` or just `civitai:180891@776656`) and paste it.",
|
||||
},
|
||||
setup: {
|
||||
chooseProvider: "Choose AI Provider",
|
||||
@@ -688,4 +688,5 @@ export const languageEnglish = {
|
||||
hideApiKeys: "Hide API Keys",
|
||||
unformatQuotes: "Disable Quote Formatting",
|
||||
enableDevTools: "Enable Dev Tools",
|
||||
selectFile: "Select File"
|
||||
}
|
||||
@@ -76,6 +76,7 @@
|
||||
<OptionInput value="dalle" >Dall-E</OptionInput>
|
||||
<OptionInput value="stability" >Stability API</OptionInput>
|
||||
<OptionInput value="comfy" >ComfyUI</OptionInput>
|
||||
<OptionInput value="fal" >Fal.ai</OptionInput>
|
||||
</SelectInput>
|
||||
|
||||
{#if $DataBase.sdProvider === 'webui'}
|
||||
@@ -295,6 +296,34 @@
|
||||
<span class="text-textcolor">Timeout (sec)</span>
|
||||
<NumberInput size="sm" marginBottom bind:value={$DataBase.comfyConfig.timeout} min={1} max={120} />
|
||||
{/if}
|
||||
|
||||
{#if $DataBase.sdProvider === 'fal'}
|
||||
<span class="text-textcolor">Fal.ai API Key</span>
|
||||
<TextInput size="sm" marginBottom placeholder="..." bind:value={$DataBase.falToken}/>
|
||||
|
||||
<span class="text-textcolor mt-4">Width</span>
|
||||
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={$DataBase.sdConfig.width}/>
|
||||
<span class="text-textcolor mt-4">Height</span>
|
||||
<NumberInput size="sm" marginBottom min={0} max={2048} bind:value={$DataBase.sdConfig.height}/>
|
||||
|
||||
<span class="text-textcolor mt-4">Model</span>
|
||||
<SelectInput className="mt-2" bind:value={$DataBase.falModel}>
|
||||
<OptionInput value="fal-ai/flux/dev" >Flux[Dev]</OptionInput>
|
||||
<OptionInput value="fal-ai/flux-lora" >Flux[Dev] with Lora</OptionInput>
|
||||
<OptionInput value="fal-ai/flux-pro" >Flux[Pro]</OptionInput>
|
||||
<OptionInput value="fal-ai/flux/schnell" >Flux[Schnell]</OptionInput>
|
||||
</SelectInput>
|
||||
|
||||
{#if $DataBase.falModel === 'fal-ai/flux-lora'}
|
||||
<span class="text-textcolor mt-4">Lora Model URL <Help key="urllora" /></span>
|
||||
<TextInput size="sm" marginBottom bind:value={$DataBase.falLora}/>
|
||||
|
||||
<span class="text-textcolor mt-4">Lora Weight</span>
|
||||
<SliderInput fixed={2} min={0} max={2} step={0.01} bind:value={$DataBase.falLoraScale}/>
|
||||
{/if}
|
||||
|
||||
|
||||
{/if}
|
||||
</Arcodion>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -877,7 +877,7 @@
|
||||
className="h-10">
|
||||
|
||||
{#if currentChar.data.gptSoVitsConfig.ref_audio_data.assetId === '' || currentChar.data.gptSoVitsConfig.ref_audio_data.assetId === undefined}
|
||||
Select File
|
||||
{language.selectFile}
|
||||
{:else}
|
||||
{currentChar.data.gptSoVitsConfig.ref_audio_data.fileName}
|
||||
{/if}
|
||||
|
||||
@@ -523,5 +523,68 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
|
||||
return returnSdData
|
||||
|
||||
}
|
||||
if(db.sdProvider === 'fal'){
|
||||
const model = db.falModel
|
||||
const token = db.falToken
|
||||
|
||||
let body:{[key:string]:any} = {
|
||||
prompt: genPrompt,
|
||||
enable_safety_checker: false,
|
||||
sync_mode: true,
|
||||
image_size: {
|
||||
"width": db.sdConfig.width,
|
||||
"height": db.sdConfig.height,
|
||||
}
|
||||
}
|
||||
|
||||
if(db.falModel === 'fal-ai/flux-lora'){
|
||||
let loraPath = db.falLora
|
||||
if(loraPath.startsWith('urn:') || loraPath.startsWith('civitai:')){
|
||||
const id = loraPath.split('@').pop()
|
||||
loraPath = `https://civitai.com/api/download/models/${id}?type=Model&format=SafeTensor`
|
||||
}
|
||||
body.loras = [{
|
||||
"path": loraPath,
|
||||
"scale": db.falLoraScale
|
||||
}]
|
||||
}
|
||||
|
||||
if(db.falModel === 'fal-ai/flux-pro'){
|
||||
delete body.enable_safety_checker
|
||||
}
|
||||
console.log(body)
|
||||
|
||||
const res = await globalFetch('https://fal.run/' + model, {
|
||||
headers: {
|
||||
"Authorization": "Key " + token,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
method: 'POST',
|
||||
body: body
|
||||
})
|
||||
|
||||
console.log(res)
|
||||
|
||||
if(!res.ok){
|
||||
alertError(JSON.stringify(res.data))
|
||||
return false
|
||||
}
|
||||
|
||||
let image = res.data?.images?.[0]?.url
|
||||
if(!image){
|
||||
alertError(JSON.stringify(res.data))
|
||||
return false
|
||||
}
|
||||
|
||||
if(returnSdData === 'inlay'){
|
||||
return image
|
||||
}
|
||||
else{
|
||||
let charemotions = get(CharEmotion)
|
||||
const emos:[string, string,number][] = [[image, image, Date.now()]]
|
||||
charemotions[currentChar.chaId] = emos
|
||||
CharEmotion.set(charemotions)
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ export async function sayTTS(character:character,text:string) {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
rawResponse: false,
|
||||
|
||||
plainFetchDeforce: true,
|
||||
})
|
||||
console.log(path)
|
||||
if(path.ok){
|
||||
|
||||
@@ -432,6 +432,8 @@ export function setDatabase(data:Database){
|
||||
data.unformatQuotes ??= false
|
||||
data.ttsAutoSpeech ??= false
|
||||
data.translatorInputLanguage ??= 'auto'
|
||||
data.falModel ??= 'fal-ai/flux/dev'
|
||||
data.falLoraScale ??= 1
|
||||
changeLanguage(data.language)
|
||||
DataBase.set(data)
|
||||
}
|
||||
@@ -718,6 +720,11 @@ export interface Database{
|
||||
hideApiKey: boolean
|
||||
unformatQuotes: boolean
|
||||
enableDevTools: boolean
|
||||
falToken: string
|
||||
falModel: string
|
||||
falLora: string
|
||||
falLoraName: string
|
||||
falLoraScale: number
|
||||
}
|
||||
|
||||
export interface customscript{
|
||||
|
||||
@@ -577,6 +577,7 @@ const knownHostes = ["localhost","127.0.0.1","0.0.0.0"]
|
||||
|
||||
interface GlobalFetchArgs {
|
||||
plainFetchForce?: boolean;
|
||||
plainFetchDeforce?: boolean;
|
||||
body?: any;
|
||||
headers?: { [key: string]: string };
|
||||
rawResponse?: boolean;
|
||||
@@ -625,7 +626,7 @@ export async function globalFetch(url: string, arg: GlobalFetchArgs = {}): Promi
|
||||
if (arg.abortSignal?.aborted) { return { ok: false, data: 'aborted', headers: {} }}
|
||||
|
||||
const urlHost = new URL(url).hostname
|
||||
const forcePlainFetch = (knownHostes.includes(urlHost) && !isTauri) || db.usePlainFetch || arg.plainFetchForce
|
||||
const forcePlainFetch = ((knownHostes.includes(urlHost) && !isTauri) || db.usePlainFetch || arg.plainFetchForce) && !arg.plainFetchDeforce
|
||||
|
||||
if (knownHostes.includes(urlHost) && !isTauri && !isNodeServer){
|
||||
return { ok: false, headers: {}, data: 'You are trying local request on web version. This is not allowed due to browser security policy. Use the desktop version instead, or use a tunneling service like ngrok and set the CORS to allow all.' }
|
||||
|
||||
Reference in New Issue
Block a user