mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
refactoring out duplicate code
This commit is contained in:
parent
2d34cf7a8d
commit
a0d1599b9d
7 changed files with 290 additions and 309 deletions
|
|
@ -1,44 +1,40 @@
|
||||||
AMDGPU
|
AMDGPU
|
||||||
APPIMAGE
|
APPIMAGE
|
||||||
BLAS
|
|
||||||
CUDA
|
|
||||||
GGUF
|
|
||||||
KOBOLDAI
|
|
||||||
KOBOLDCPP
|
|
||||||
OLDPC
|
|
||||||
ROCM
|
|
||||||
SDXL
|
|
||||||
SPACEBAR
|
|
||||||
Consolas
|
|
||||||
Cooldown
|
|
||||||
Dolfino
|
|
||||||
Flashattention
|
|
||||||
KoboldCpp
|
|
||||||
Lowvram
|
|
||||||
Segoe
|
|
||||||
Tauri
|
|
||||||
asar
|
asar
|
||||||
|
Autoencoder
|
||||||
|
BLAS
|
||||||
clblast
|
clblast
|
||||||
clinfo
|
clinfo
|
||||||
|
Consolas
|
||||||
contextsize
|
contextsize
|
||||||
|
Cooldown
|
||||||
cublas
|
cublas
|
||||||
cuda
|
cuda
|
||||||
|
CUDA
|
||||||
|
Dolfino
|
||||||
finetuned
|
finetuned
|
||||||
flashattention
|
flashattention
|
||||||
|
Flashattention
|
||||||
friendlykobold
|
friendlykobold
|
||||||
geforce
|
geforce
|
||||||
ggml
|
ggml
|
||||||
gguf
|
gguf
|
||||||
|
GGUF
|
||||||
gpulayers
|
gpulayers
|
||||||
hipblas
|
hipblas
|
||||||
kcpps
|
kcpps
|
||||||
kcppt
|
kcppt
|
||||||
koboldai
|
koboldai
|
||||||
|
KOBOLDAI
|
||||||
koboldcpp
|
koboldcpp
|
||||||
|
KoboldCpp
|
||||||
|
KOBOLDCPP
|
||||||
lora
|
lora
|
||||||
lowvram
|
lowvram
|
||||||
|
Lowvram
|
||||||
maximizable
|
maximizable
|
||||||
minimizable
|
minimizable
|
||||||
|
MMAP
|
||||||
mmproj
|
mmproj
|
||||||
mmq
|
mmq
|
||||||
multiuser
|
multiuser
|
||||||
|
|
@ -51,12 +47,14 @@ noshift
|
||||||
nsis
|
nsis
|
||||||
nvidia
|
nvidia
|
||||||
oldpc
|
oldpc
|
||||||
|
OLDPC
|
||||||
opencl
|
opencl
|
||||||
pkexec
|
pkexec
|
||||||
quantmatmul
|
quantmatmul
|
||||||
radeon
|
radeon
|
||||||
remotetunnel
|
remotetunnel
|
||||||
rocm
|
rocm
|
||||||
|
ROCM
|
||||||
rocminfo
|
rocminfo
|
||||||
safetensors
|
safetensors
|
||||||
sdclipg
|
sdclipg
|
||||||
|
|
@ -66,8 +64,12 @@ sdmodel
|
||||||
sdphotomaker
|
sdphotomaker
|
||||||
sdui
|
sdui
|
||||||
sdvae
|
sdvae
|
||||||
|
SDXL
|
||||||
|
Segoe
|
||||||
sonarjs
|
sonarjs
|
||||||
|
SPACEBAR
|
||||||
taskkill
|
taskkill
|
||||||
|
Tauri
|
||||||
togglefullscreen
|
togglefullscreen
|
||||||
treemap
|
treemap
|
||||||
trycloudflare
|
trycloudflare
|
||||||
|
|
@ -81,4 +83,3 @@ vulkan
|
||||||
vulkaninfo
|
vulkaninfo
|
||||||
wayland
|
wayland
|
||||||
websearch
|
websearch
|
||||||
MMAP
|
|
||||||
|
|
|
||||||
31
src/components/CheckboxWithTooltip.tsx
Normal file
31
src/components/CheckboxWithTooltip.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { Checkbox, Group } from '@mantine/core';
|
||||||
|
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
|
import styles from '@/styles/layout.module.css';
|
||||||
|
|
||||||
|
interface CheckboxWithTooltipProps {
|
||||||
|
checked: boolean;
|
||||||
|
onChange: (checked: boolean) => void;
|
||||||
|
label: string;
|
||||||
|
tooltip: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CheckboxWithTooltip = ({
|
||||||
|
checked,
|
||||||
|
onChange,
|
||||||
|
label,
|
||||||
|
tooltip,
|
||||||
|
disabled = false,
|
||||||
|
}: CheckboxWithTooltipProps) => (
|
||||||
|
<div className={styles.minWidth200}>
|
||||||
|
<Group gap="xs" align="center">
|
||||||
|
<Checkbox
|
||||||
|
checked={checked}
|
||||||
|
onChange={(event) => onChange(event.currentTarget.checked)}
|
||||||
|
label={label}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<InfoTooltip label={tooltip} />
|
||||||
|
</Group>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
90
src/components/ModelFileField.tsx
Normal file
90
src/components/ModelFileField.tsx
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { Group, TextInput, Button } from '@mantine/core';
|
||||||
|
import { File, Search } from 'lucide-react';
|
||||||
|
import { SectionHeader } from '@/components/SectionHeader';
|
||||||
|
import { getInputValidationState } from '@/utils';
|
||||||
|
import styles from '@/styles/layout.module.css';
|
||||||
|
|
||||||
|
interface ModelFileFieldProps {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
placeholder: string;
|
||||||
|
tooltip?: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
onSelectFile: () => void;
|
||||||
|
showSearchHF?: boolean;
|
||||||
|
searchUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModelFileField = ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
placeholder,
|
||||||
|
tooltip,
|
||||||
|
onChange,
|
||||||
|
onSelectFile,
|
||||||
|
showSearchHF = false,
|
||||||
|
searchUrl = 'https://huggingface.co/models?pipeline_tag=text-to-image&library=gguf&sort=trending',
|
||||||
|
}: ModelFileFieldProps) => {
|
||||||
|
const validationState = getInputValidationState(value);
|
||||||
|
|
||||||
|
const getInputColor = () => {
|
||||||
|
switch (validationState) {
|
||||||
|
case 'valid':
|
||||||
|
return 'green';
|
||||||
|
case 'invalid':
|
||||||
|
return 'red';
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHelperText = () => {
|
||||||
|
if (!value.trim()) return undefined;
|
||||||
|
|
||||||
|
if (validationState === 'invalid') {
|
||||||
|
return 'Enter a valid URL or file path';
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SectionHeader
|
||||||
|
title={label}
|
||||||
|
tooltip={tooltip}
|
||||||
|
fontWeight={500}
|
||||||
|
marginBottom="xs"
|
||||||
|
/>
|
||||||
|
<Group gap="xs" align="flex-start">
|
||||||
|
<div className={styles.flex1}>
|
||||||
|
<TextInput
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
onChange={(event) => onChange(event.currentTarget.value)}
|
||||||
|
color={getInputColor()}
|
||||||
|
error={validationState === 'invalid' ? getHelperText() : undefined}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={onSelectFile}
|
||||||
|
variant="light"
|
||||||
|
leftSection={<File size={16} />}
|
||||||
|
>
|
||||||
|
Browse
|
||||||
|
</Button>
|
||||||
|
{showSearchHF && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
window.electronAPI.app.openExternal(searchUrl);
|
||||||
|
}}
|
||||||
|
variant="outline"
|
||||||
|
leftSection={<Search size={16} />}
|
||||||
|
>
|
||||||
|
Search HF
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
23
src/components/SectionHeader.tsx
Normal file
23
src/components/SectionHeader.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Group, Text } from '@mantine/core';
|
||||||
|
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
|
|
||||||
|
interface SectionHeaderProps {
|
||||||
|
title: string;
|
||||||
|
tooltip?: string;
|
||||||
|
fontWeight?: number;
|
||||||
|
marginBottom?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SectionHeader = ({
|
||||||
|
title,
|
||||||
|
tooltip,
|
||||||
|
fontWeight = 600,
|
||||||
|
marginBottom = 'md',
|
||||||
|
}: SectionHeaderProps) => (
|
||||||
|
<Group gap="xs" align="center" mb={marginBottom}>
|
||||||
|
<Text size="sm" fw={fontWeight}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
{tooltip && <InfoTooltip label={tooltip} />}
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Stack, Checkbox, Group, Text, TextInput } from '@mantine/core';
|
import { Stack, Group, Text, TextInput } from '@mantine/core';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { InfoTooltip } from '@/components/InfoTooltip';
|
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
|
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import styles from '@/styles/layout.module.css';
|
|
||||||
|
|
||||||
export const AdvancedTab = () => {
|
export const AdvancedTab = () => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -68,102 +68,62 @@ export const AdvancedTab = () => {
|
||||||
</Group>
|
</Group>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={!noshift}
|
checked={!noshift}
|
||||||
onChange={(event) =>
|
onChange={(checked) => handleNoshiftChange(!checked)}
|
||||||
handleNoshiftChange(!event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Context Shift"
|
label="Context Shift"
|
||||||
|
tooltip="Use Context Shifting to reduce reprocessing."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Use Context Shifting to reduce reprocessing." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={noshift}
|
checked={noshift}
|
||||||
onChange={(event) =>
|
onChange={handleNoshiftChange}
|
||||||
handleNoshiftChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="No Shift"
|
label="No Shift"
|
||||||
|
tooltip="Don't use GPU layer shifting for incomplete offloads, which may reduce model performance."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Don't use GPU layer shifting for incomplete offloads, which may reduce model performance." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={flashattention}
|
checked={flashattention}
|
||||||
onChange={(event) =>
|
onChange={handleFlashattentionChange}
|
||||||
handleFlashattentionChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Flash Attention"
|
label="Flash Attention"
|
||||||
|
tooltip="Enable flash attention to reduce memory usage. May produce incorrect answers for some prompts, but improves performance."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Enable flash attention to reduce memory usage. May produce incorrect answers for some prompts, but improves performance." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
checked={usemmap}
|
||||||
<Checkbox
|
onChange={handleUsemmapChange}
|
||||||
checked={lowvram}
|
label="MMAP"
|
||||||
onChange={(event) =>
|
tooltip="Use MMAP to load models when enabled."
|
||||||
handleLowvramChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Low VRAM"
|
|
||||||
disabled={backend !== 'cuda' && backend !== 'rocm'}
|
|
||||||
/>
|
/>
|
||||||
<InfoTooltip
|
|
||||||
label={
|
<CheckboxWithTooltip
|
||||||
|
checked={lowvram}
|
||||||
|
onChange={handleLowvramChange}
|
||||||
|
label="Low VRAM"
|
||||||
|
tooltip={
|
||||||
backend !== 'cuda' && backend !== 'rocm'
|
backend !== 'cuda' && backend !== 'rocm'
|
||||||
? 'Low VRAM mode is only available for CUDA and ROCm backends.'
|
? 'Low VRAM mode is only available for CUDA and ROCm backends.'
|
||||||
: 'Avoid offloading KV Cache or scratch buffers to VRAM. Allows more layers to fit, but may result in a speed loss.'
|
: 'Avoid offloading KV Cache or scratch buffers to VRAM. Allows more layers to fit, but may result in a speed loss.'
|
||||||
}
|
}
|
||||||
|
disabled={backend !== 'cuda' && backend !== 'rocm'}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
|
||||||
</Group>
|
|
||||||
|
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={quantmatmul}
|
checked={quantmatmul}
|
||||||
onChange={(event) =>
|
onChange={handleQuantmatmulChange}
|
||||||
handleQuantmatmulChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="QuantMatMul"
|
label="QuantMatMul"
|
||||||
disabled={backend !== 'cuda' && backend !== 'rocm'}
|
tooltip={
|
||||||
/>
|
|
||||||
<InfoTooltip
|
|
||||||
label={
|
|
||||||
backend !== 'cuda' && backend !== 'rocm'
|
backend !== 'cuda' && backend !== 'rocm'
|
||||||
? 'QuantMatMul is only available for CUDA and ROCm backends.'
|
? 'QuantMatMul is only available for CUDA and ROCm backends.'
|
||||||
: 'Enable MMQ mode to use finetuned kernels instead of default CuBLAS/HipBLAS for prompt processing.'
|
: 'Enable MMQ mode to use finetuned kernels instead of default CuBLAS/HipBLAS for prompt processing.'
|
||||||
}
|
}
|
||||||
|
disabled={backend !== 'cuda' && backend !== 'rocm'}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={usemmap}
|
|
||||||
onChange={(event) =>
|
|
||||||
handleUsemmapChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="MMAP"
|
|
||||||
/>
|
|
||||||
<InfoTooltip label="Use MMAP to load models when enabled." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -175,46 +135,30 @@ export const AdvancedTab = () => {
|
||||||
</Group>
|
</Group>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={noavx2}
|
checked={noavx2}
|
||||||
onChange={(event) =>
|
onChange={handleNoavx2Change}
|
||||||
handleNoavx2Change(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Disable AVX2"
|
label="Disable AVX2"
|
||||||
disabled={isLoading || !backendSupport?.noavx2}
|
tooltip={
|
||||||
/>
|
|
||||||
<InfoTooltip
|
|
||||||
label={
|
|
||||||
!backendSupport?.noavx2 && !isLoading
|
!backendSupport?.noavx2 && !isLoading
|
||||||
? 'This binary does not support the no-AVX2 mode.'
|
? 'This binary does not support the no-AVX2 mode.'
|
||||||
: 'Do not use AVX2 instructions, a slower compatibility mode for older devices.'
|
: 'Do not use AVX2 instructions, a slower compatibility mode for older devices.'
|
||||||
}
|
}
|
||||||
|
disabled={isLoading || !backendSupport?.noavx2}
|
||||||
/>
|
/>
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={failsafe}
|
checked={failsafe}
|
||||||
onChange={(event) =>
|
onChange={handleFailsafeChange}
|
||||||
handleFailsafeChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Failsafe"
|
label="Failsafe"
|
||||||
disabled={isLoading || !backendSupport?.failsafe}
|
tooltip={
|
||||||
/>
|
|
||||||
<InfoTooltip
|
|
||||||
label={
|
|
||||||
!backendSupport?.failsafe && !isLoading
|
!backendSupport?.failsafe && !isLoading
|
||||||
? 'This binary does not support failsafe mode.'
|
? 'This binary does not support failsafe mode.'
|
||||||
: 'Use failsafe mode, extremely slow CPU only compatibility mode that should work on all devices. Can be combined with useclblast if your device supports OpenCL.'
|
: 'Use failsafe mode, extremely slow CPU only compatibility mode that should work on all devices. Can be combined with useclblast if your device supports OpenCL.'
|
||||||
}
|
}
|
||||||
|
disabled={isLoading || !backendSupport?.failsafe}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import { Stack, Text, Group, TextInput, Button, Select } from '@mantine/core';
|
import { Stack, Select } from '@mantine/core';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { File, Search } from 'lucide-react';
|
import { SectionHeader } from '@/components/SectionHeader';
|
||||||
import { InfoTooltip } from '@/components/InfoTooltip';
|
import { ModelFileField } from '@/components/ModelFileField';
|
||||||
import { getInputValidationState, IMAGE_MODEL_PRESETS } from '@/utils';
|
import { IMAGE_MODEL_PRESETS } from '@/utils';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import styles from '@/styles/layout.module.css';
|
|
||||||
|
|
||||||
export const ImageGenerationTab = () => {
|
export const ImageGenerationTab = () => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -34,100 +33,15 @@ export const ImageGenerationTab = () => {
|
||||||
|
|
||||||
const [selectedPreset, setSelectedPreset] = useState<string | null>(null);
|
const [selectedPreset, setSelectedPreset] = useState<string | null>(null);
|
||||||
|
|
||||||
const ModelField = ({
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
placeholder,
|
|
||||||
tooltip,
|
|
||||||
onChange,
|
|
||||||
onSelectFile,
|
|
||||||
showSearchHF = false,
|
|
||||||
}: {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
placeholder: string;
|
|
||||||
tooltip?: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
onSelectFile: () => void;
|
|
||||||
showSearchHF?: boolean;
|
|
||||||
}) => {
|
|
||||||
const validationState = getInputValidationState(value);
|
|
||||||
|
|
||||||
const getInputColor = () => {
|
|
||||||
switch (validationState) {
|
|
||||||
case 'valid':
|
|
||||||
return 'green';
|
|
||||||
case 'invalid':
|
|
||||||
return 'red';
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHelperText = () => {
|
|
||||||
if (!value.trim()) return undefined;
|
|
||||||
|
|
||||||
if (validationState === 'invalid') {
|
|
||||||
return 'Enter a valid URL or file path';
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Group gap="xs" align="center" mb="xs">
|
|
||||||
<Text size="sm" fw={500}>
|
|
||||||
{label}
|
|
||||||
</Text>
|
|
||||||
{tooltip && <InfoTooltip label={tooltip} />}
|
|
||||||
</Group>
|
|
||||||
<Group gap="xs" align="flex-start">
|
|
||||||
<div className={styles.flex1}>
|
|
||||||
<TextInput
|
|
||||||
placeholder={placeholder}
|
|
||||||
value={value}
|
|
||||||
onChange={(event) => onChange(event.currentTarget.value)}
|
|
||||||
color={getInputColor()}
|
|
||||||
error={
|
|
||||||
validationState === 'invalid' ? getHelperText() : undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
onClick={onSelectFile}
|
|
||||||
variant="light"
|
|
||||||
leftSection={<File size={16} />}
|
|
||||||
>
|
|
||||||
Browse
|
|
||||||
</Button>
|
|
||||||
{showSearchHF && (
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
window.electronAPI.app.openExternal(
|
|
||||||
'https://huggingface.co/models?pipeline_tag=text-to-image&library=gguf&sort=trending'
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
variant="outline"
|
|
||||||
leftSection={<Search size={16} />}
|
|
||||||
>
|
|
||||||
Search HF
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<div>
|
<div>
|
||||||
<Group gap="xs" align="center" mb="xs">
|
<SectionHeader
|
||||||
<Text size="sm" fw={500}>
|
title="Model Preset"
|
||||||
Model Preset
|
tooltip="Quick presets for popular image generation models with pre-configured encoders."
|
||||||
</Text>
|
fontWeight={500}
|
||||||
<InfoTooltip label="Quick presets for popular image generation models with pre-configured encoders." />
|
marginBottom="xs"
|
||||||
</Group>
|
/>
|
||||||
<Select
|
<Select
|
||||||
placeholder="Choose a preset..."
|
placeholder="Choose a preset..."
|
||||||
data={IMAGE_MODEL_PRESETS.map((preset) => ({
|
data={IMAGE_MODEL_PRESETS.map((preset) => ({
|
||||||
|
|
@ -145,40 +59,45 @@ export const ImageGenerationTab = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="Image Gen. Model File"
|
label="Image Gen. Model File"
|
||||||
value={sdmodel}
|
value={sdmodel}
|
||||||
placeholder="Select a model file or enter a direct URL"
|
placeholder="Select a model file or enter a direct URL"
|
||||||
|
tooltip="The primary image generation model. This is the main model that will generate images."
|
||||||
onChange={handleSdmodelChange}
|
onChange={handleSdmodelChange}
|
||||||
onSelectFile={handleSelectSdmodelFile}
|
onSelectFile={handleSelectSdmodelFile}
|
||||||
showSearchHF
|
showSearchHF
|
||||||
|
searchUrl="https://huggingface.co/models?pipeline_tag=text-to-image&library=gguf&sort=trending"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="T5-XXL File"
|
label="T5-XXL File"
|
||||||
value={sdt5xxl}
|
value={sdt5xxl}
|
||||||
placeholder="Select a T5-XXL file or enter a direct URL"
|
placeholder="Select a T5-XXL file or enter a direct URL"
|
||||||
|
tooltip="T5-XXL text encoder model for enhanced text understanding."
|
||||||
onChange={handleSdt5xxlChange}
|
onChange={handleSdt5xxlChange}
|
||||||
onSelectFile={handleSelectSdt5xxlFile}
|
onSelectFile={handleSelectSdt5xxlFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="Clip-L File"
|
label="Clip-L File"
|
||||||
value={sdclipl}
|
value={sdclipl}
|
||||||
placeholder="Select a Clip-L file or enter a direct URL"
|
placeholder="Select a Clip-L file or enter a direct URL"
|
||||||
|
tooltip="CLIP-L text encoder model for text-image understanding."
|
||||||
onChange={handleSdcliplChange}
|
onChange={handleSdcliplChange}
|
||||||
onSelectFile={handleSelectSdcliplFile}
|
onSelectFile={handleSelectSdcliplFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="Clip-G File"
|
label="Clip-G File"
|
||||||
value={sdclipg}
|
value={sdclipg}
|
||||||
placeholder="Select a Clip-G file or enter a direct URL"
|
placeholder="Select a Clip-G file or enter a direct URL"
|
||||||
|
tooltip="CLIP-G text encoder model for enhanced text-image understanding."
|
||||||
onChange={handleSdclipgChange}
|
onChange={handleSdclipgChange}
|
||||||
onSelectFile={handleSelectSdclipgFile}
|
onSelectFile={handleSelectSdclipgFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="PhotoMaker"
|
label="PhotoMaker"
|
||||||
value={sdphotomaker}
|
value={sdphotomaker}
|
||||||
placeholder="Select a PhotoMaker file or enter a direct URL"
|
placeholder="Select a PhotoMaker file or enter a direct URL"
|
||||||
|
|
@ -187,15 +106,16 @@ export const ImageGenerationTab = () => {
|
||||||
onSelectFile={handleSelectSdphotomakerFile}
|
onSelectFile={handleSelectSdphotomakerFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="Image VAE"
|
label="Image VAE"
|
||||||
value={sdvae}
|
value={sdvae}
|
||||||
placeholder="Select a VAE file or enter a direct URL"
|
placeholder="Select a VAE file or enter a direct URL"
|
||||||
|
tooltip="Variational Autoencoder model for improved image quality."
|
||||||
onChange={handleSdvaeChange}
|
onChange={handleSdvaeChange}
|
||||||
onSelectFile={handleSelectSdvaeFile}
|
onSelectFile={handleSelectSdvaeFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModelField
|
<ModelFileField
|
||||||
label="Image LoRa"
|
label="Image LoRa"
|
||||||
value={sdlora}
|
value={sdlora}
|
||||||
placeholder="Select a LoRa file or enter a direct URL"
|
placeholder="Select a LoRa file or enter a direct URL"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Stack, Text, TextInput, Group, Checkbox } from '@mantine/core';
|
import { Stack, Text, TextInput, Group } from '@mantine/core';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { InfoTooltip } from '@/components/InfoTooltip';
|
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
|
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
||||||
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
import styles from '@/styles/layout.module.css';
|
|
||||||
|
|
||||||
export const NetworkTab = () => {
|
export const NetworkTab = () => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -85,71 +85,43 @@ export const NetworkTab = () => {
|
||||||
<div>
|
<div>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={multiuser}
|
checked={multiuser}
|
||||||
onChange={(event) =>
|
onChange={handleMultiuserChange}
|
||||||
handleMultiuserChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Multiuser Mode"
|
label="Multiuser Mode"
|
||||||
|
tooltip="Allows requests by multiple different clients to be queued and handled in sequence."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Allows requests by multiple different clients to be queued and handled in sequence." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={multiplayer}
|
checked={multiplayer}
|
||||||
onChange={(event) =>
|
onChange={handleMultiplayerChange}
|
||||||
handleMultiplayerChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Shared Multiplayer"
|
label="Shared Multiplayer"
|
||||||
|
tooltip="Hosts a shared multiplayer session"
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Hosts a shared multiplayer session" />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="lg" align="flex-start" wrap="nowrap">
|
<Group gap="lg" align="flex-start" wrap="nowrap">
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={remotetunnel}
|
checked={remotetunnel}
|
||||||
onChange={(event) =>
|
onChange={handleRemotetunnelChange}
|
||||||
handleRemotetunnelChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Remote Tunnel"
|
label="Remote Tunnel"
|
||||||
|
tooltip="Creates a trycloudflare tunnel. Allows you to access koboldcpp from other devices over an internet URL."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Creates a trycloudflare tunnel. Allows you to access koboldcpp from other devices over an internet URL." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.minWidth200}>
|
<CheckboxWithTooltip
|
||||||
<Group gap="xs" align="center">
|
|
||||||
<Checkbox
|
|
||||||
checked={nocertify}
|
checked={nocertify}
|
||||||
onChange={(event) =>
|
onChange={handleNocertifyChange}
|
||||||
handleNocertifyChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="No Certify Mode (Insecure)"
|
label="No Certify Mode (Insecure)"
|
||||||
|
tooltip="Allows insecure SSL connections. Use this if you have SSL cert errors and need to bypass certificate restrictions."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Allows insecure SSL connections. Use this if you have SSL cert errors and need to bypass certificate restrictions." />
|
|
||||||
</Group>
|
|
||||||
</div>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="xs" align="center">
|
<CheckboxWithTooltip
|
||||||
<Checkbox
|
|
||||||
checked={websearch}
|
checked={websearch}
|
||||||
onChange={(event) =>
|
onChange={handleWebsearchChange}
|
||||||
handleWebsearchChange(event.currentTarget.checked)
|
|
||||||
}
|
|
||||||
label="Enable WebSearch"
|
label="Enable WebSearch"
|
||||||
|
tooltip="Enable the local search engine proxy so Web Searches can be done."
|
||||||
/>
|
/>
|
||||||
<InfoTooltip label="Enable the local search engine proxy so Web Searches can be done." />
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue