(false);
const {
@@ -73,7 +70,14 @@ export const LaunchScreen = ({
onLaunchModeChange,
});
- const combinedWarnings = useWarnings({ modelPath, sdmodel, warnings });
+ const { warnings: combinedWarnings } = useWarnings({
+ modelPath,
+ sdmodel,
+ backend,
+ noavx2,
+ failsafe,
+ configLoaded,
+ });
const setHappyDefaults = useCallback(async () => {
try {
@@ -302,7 +306,7 @@ export const LaunchScreen = ({
-
+
diff --git a/src/hooks/useWarnings.ts b/src/hooks/useWarnings.ts
index 2a6382e..059b178 100644
--- a/src/hooks/useWarnings.ts
+++ b/src/hooks/useWarnings.ts
@@ -1,41 +1,300 @@
-import { useMemo } from 'react';
+import { useMemo, useEffect, useState, useCallback } from 'react';
+
+export interface Warning {
+ type: 'warning' | 'info';
+ message: string;
+}
interface UseWarningsProps {
modelPath: string;
sdmodel: string;
- warnings: Array<{ type: 'warning' | 'info'; message: string }>;
+ backend?: string;
+ noavx2?: boolean;
+ failsafe?: boolean;
+ configLoaded?: boolean;
}
+const checkModelWarnings = (
+ modelPath: string,
+ sdmodel: string,
+ configLoaded: boolean
+): Warning[] => {
+ const hasTextModel = modelPath?.trim() !== '';
+ const hasImageModel = sdmodel.trim() !== '';
+ const showModelPriorityWarning = hasTextModel && hasImageModel;
+ const showNoModelWarning = !hasTextModel && !hasImageModel && configLoaded;
+
+ const warnings: Warning[] = [];
+
+ if (showModelPriorityWarning) {
+ warnings.push({
+ type: 'warning',
+ message:
+ 'Both text and image generation models are selected. The image generation model will take priority and be used for launch.',
+ });
+ }
+
+ if (showNoModelWarning) {
+ warnings.push({
+ type: 'info',
+ message:
+ 'Select a model in the General or Image Generation tab to enable launch.',
+ });
+ }
+
+ return warnings;
+};
+
+interface BackendSupport {
+ cuda: boolean;
+ rocm: boolean;
+}
+
+interface GpuCapabilities {
+ cuda: { supported: boolean };
+ rocm: { supported: boolean };
+}
+
+interface GpuInfo {
+ hasNVIDIA: boolean;
+ hasAMD: boolean;
+}
+
+const checkGpuWarnings = async (
+ backendSupport: BackendSupport,
+ gpuCapabilities: GpuCapabilities,
+ gpuInfo: GpuInfo
+): Promise => {
+ const warnings: Warning[] = [];
+
+ if (
+ backendSupport.cuda &&
+ !gpuCapabilities.cuda.supported &&
+ gpuInfo.hasNVIDIA
+ ) {
+ warnings.push({
+ type: 'warning',
+ message:
+ 'Your KoboldCpp binary supports CUDA and you have an NVIDIA GPU, but CUDA runtime is not detected on your system.',
+ });
+ }
+
+ if (
+ backendSupport.rocm &&
+ !gpuCapabilities.rocm.supported &&
+ gpuInfo.hasAMD
+ ) {
+ warnings.push({
+ type: 'warning',
+ message:
+ 'Your KoboldCpp binary supports ROCm and you have an AMD GPU, but ROCm runtime is not detected on your system.',
+ });
+ }
+
+ return warnings;
+};
+
+const checkVramWarnings = async (backend: string): Promise => {
+ const warnings: Warning[] = [];
+ const isGpuBackend = ['cuda', 'rocm', 'vulkan', 'clblast'].includes(backend);
+
+ if (isGpuBackend) {
+ try {
+ const gpuMemoryInfo = await window.electronAPI.kobold.detectGPUMemory();
+ const lowVramGpus = gpuMemoryInfo.filter(
+ (gpu) =>
+ typeof gpu.totalMemoryMB === 'number' && gpu.totalMemoryMB < 8192
+ );
+
+ if (lowVramGpus.length > 0) {
+ warnings.push({
+ type: 'warning',
+ message: `Low VRAM detected (${lowVramGpus
+ .map(
+ (gpu) =>
+ `${gpu.deviceName}: ${(gpu.totalMemoryMB! / 1024).toFixed(1)}GB`
+ )
+ .join(
+ ', '
+ )}). Consider using smaller models, reducing GPU layers, or enabling the "Low VRAM" option on the Advanced tab.`,
+ });
+ }
+ } catch (error) {
+ window.electronAPI.logs.logError(
+ 'Failed to detect GPU memory:',
+ error as Error
+ );
+ }
+ }
+
+ return warnings;
+};
+
+const checkCpuWarnings = (
+ backend: string,
+ cpuCapabilities: { avx: boolean; avx2: boolean },
+ noavx2: boolean,
+ failsafe: boolean,
+ availableBackends: Array<{ value: string; label: string; devices?: string[] }>
+): Warning[] => {
+ const warnings: Warning[] = [];
+
+ if (backend !== 'cpu') {
+ return warnings;
+ }
+
+ if (!cpuCapabilities.avx2 && !noavx2) {
+ warnings.push({
+ type: 'warning',
+ message:
+ 'Your CPU does not support AVX2. Enable the "Disable AVX2" option on the Advanced tab to avoid crashes.',
+ });
+ }
+
+ if (!cpuCapabilities.avx && !cpuCapabilities.avx2 && !failsafe) {
+ warnings.push({
+ type: 'warning',
+ message:
+ 'Your CPU does not support AVX or AVX2. Enable the "Failsafe" option on the Advanced tab to avoid crashes.',
+ });
+ }
+
+ if (
+ availableBackends.length > 0 &&
+ availableBackends.some((b) => b.value === 'cpu')
+ ) {
+ warnings.push({
+ type: 'info',
+ message:
+ "LLMs run significantly faster on GPU-accelerated systems. Consider using NVIDIA's CUDA, AMD's ROCm or Vulkan backends for optimal performance.",
+ });
+ }
+
+ return warnings;
+};
+
+const checkBackendWarnings = async (params?: {
+ backend: string;
+ cpuCapabilities: {
+ avx: boolean;
+ avx2: boolean;
+ } | null;
+ noavx2: boolean;
+ failsafe: boolean;
+ availableBackends: Array<{
+ value: string;
+ label: string;
+ devices?: string[];
+ }>;
+}): Promise => {
+ const warnings: Warning[] = [];
+
+ try {
+ const [backendSupport, gpuCapabilities, gpuInfo] = await Promise.all([
+ window.electronAPI.kobold.detectBackendSupport(),
+ window.electronAPI.kobold.detectGPUCapabilities(),
+ window.electronAPI.kobold.detectGPU(),
+ ]);
+
+ if (!backendSupport) {
+ return warnings;
+ }
+
+ const gpuWarnings = await checkGpuWarnings(
+ backendSupport,
+ gpuCapabilities,
+ gpuInfo
+ );
+ warnings.push(...gpuWarnings);
+
+ if (params) {
+ const { backend, cpuCapabilities, noavx2, failsafe, availableBackends } =
+ params;
+
+ const vramWarnings = await checkVramWarnings(backend);
+ warnings.push(...vramWarnings);
+
+ if (cpuCapabilities) {
+ const cpuWarnings = checkCpuWarnings(
+ backend,
+ cpuCapabilities,
+ noavx2,
+ failsafe,
+ availableBackends
+ );
+ warnings.push(...cpuWarnings);
+ }
+ }
+
+ return warnings;
+ } catch (error) {
+ window.electronAPI.logs.logError(
+ 'Failed to check backend warnings:',
+ error as Error
+ );
+ return warnings;
+ }
+};
+
export const useWarnings = ({
modelPath,
sdmodel,
- warnings,
-}: UseWarningsProps) =>
- useMemo(() => {
- const hasTextModel = modelPath?.trim() !== '';
- const hasImageModel = sdmodel.trim() !== '';
- const showModelPriorityWarning = hasTextModel && hasImageModel;
- const showNoModelWarning = !hasTextModel && !hasImageModel;
+ backend,
+ noavx2 = false,
+ failsafe = false,
+ configLoaded = false,
+}: UseWarningsProps) => {
+ const [backendWarnings, setBackendWarnings] = useState([]);
- return [
- ...warnings,
- ...(showModelPriorityWarning
- ? [
- {
- type: 'warning' as const,
- message:
- 'Both text and image generation models are selected. The image generation model will take priority and be used for launch.',
- },
- ]
- : []),
- ...(showNoModelWarning
- ? [
- {
- type: 'info' as const,
- message:
- 'Select a model in the General or Image Generation tab to enable launch.',
- },
- ]
- : []),
- ];
- }, [modelPath, sdmodel, warnings]);
+ const modelWarnings = useMemo(
+ () => checkModelWarnings(modelPath, sdmodel, configLoaded),
+ [modelPath, sdmodel, configLoaded]
+ );
+
+ const updateBackendWarnings = useCallback(async () => {
+ if (!backend) {
+ setBackendWarnings([]);
+ return;
+ }
+
+ try {
+ const [cpuCapabilitiesResult, availableBackends] = await Promise.all([
+ window.electronAPI.kobold.detectCPU(),
+ window.electronAPI.kobold.getAvailableBackends(),
+ ]);
+
+ const cpuCapabilities = {
+ avx: cpuCapabilitiesResult.avx,
+ avx2: cpuCapabilitiesResult.avx2,
+ };
+
+ const warnings = await checkBackendWarnings({
+ backend,
+ cpuCapabilities,
+ noavx2,
+ failsafe,
+ availableBackends,
+ });
+ setBackendWarnings(warnings);
+ } catch (error) {
+ window.electronAPI.logs.logError(
+ 'Failed to check backend warnings:',
+ error as Error
+ );
+ setBackendWarnings([]);
+ }
+ }, [backend, noavx2, failsafe]);
+
+ useEffect(() => {
+ updateBackendWarnings();
+ }, [updateBackendWarnings]);
+
+ const allWarnings = useMemo(
+ () => [...modelWarnings, ...backendWarnings],
+ [modelWarnings, backendWarnings]
+ );
+
+ return {
+ warnings: allWarnings,
+ };
+};
diff --git a/src/utils/backendWarnings.ts b/src/utils/backendWarnings.ts
deleted file mode 100644
index 0ee1875..0000000
--- a/src/utils/backendWarnings.ts
+++ /dev/null
@@ -1,138 +0,0 @@
-export interface BackendWarning {
- type: 'warning' | 'info';
- message: string;
-}
-
-interface WarningParams {
- backend: string;
- cpuCapabilities: {
- avx: boolean;
- avx2: boolean;
- } | null;
- noavx2: boolean;
- failsafe: boolean;
- availableBackends: Array<{
- value: string;
- label: string;
- devices?: string[];
- }>;
-}
-
-export const checkBackendWarnings = async (
- params?: WarningParams
- // eslint-disable-next-line sonarjs/cognitive-complexity
-): Promise => {
- const warnings: BackendWarning[] = [];
-
- try {
- const [backendSupport, gpuCapabilities, gpuInfo] = await Promise.all([
- window.electronAPI.kobold.detectBackendSupport(),
- window.electronAPI.kobold.detectGPUCapabilities(),
- window.electronAPI.kobold.detectGPU(),
- ]);
-
- if (!backendSupport) {
- return warnings;
- }
-
- if (
- backendSupport.cuda &&
- !gpuCapabilities.cuda.supported &&
- gpuInfo.hasNVIDIA
- ) {
- warnings.push({
- type: 'warning',
- message:
- 'Your KoboldCpp binary supports CUDA and you have an NVIDIA GPU, but CUDA runtime is not detected on your system.',
- });
- }
-
- if (
- backendSupport.rocm &&
- !gpuCapabilities.rocm.supported &&
- gpuInfo.hasAMD
- ) {
- warnings.push({
- type: 'warning',
- message:
- 'Your KoboldCpp binary supports ROCm and you have an AMD GPU, but ROCm runtime is not detected on your system.',
- });
- }
-
- if (params) {
- const { backend, cpuCapabilities, noavx2, failsafe, availableBackends } =
- params;
-
- const isGpuBackend = ['cuda', 'rocm', 'vulkan', 'clblast'].includes(
- backend
- );
-
- if (isGpuBackend) {
- try {
- const gpuMemoryInfo =
- await window.electronAPI.kobold.detectGPUMemory();
- const lowVramGpus = gpuMemoryInfo.filter(
- (gpu) =>
- typeof gpu.totalMemoryMB === 'number' && gpu.totalMemoryMB < 8192
- );
-
- if (lowVramGpus.length > 0) {
- warnings.push({
- type: 'warning',
- message: `Low VRAM detected (${lowVramGpus
- .map(
- (gpu) =>
- `${gpu.deviceName}: ${(gpu.totalMemoryMB! / 1024).toFixed(1)}GB`
- )
- .join(
- ', '
- )}). Consider using smaller models, reducing GPU layers, or enabling the "Low VRAM" option on the Advanced tab.`,
- });
- }
- } catch (error) {
- window.electronAPI.logs.logError(
- 'Failed to detect GPU memory:',
- error as Error
- );
- }
- }
-
- if (backend === 'cpu' && cpuCapabilities) {
- if (!cpuCapabilities.avx2 && !noavx2) {
- warnings.push({
- type: 'warning',
- message:
- 'Your CPU does not support AVX2. Enable the "Disable AVX2" option on the Advanced tab to avoid crashes.',
- });
- }
-
- if (!cpuCapabilities.avx && !cpuCapabilities.avx2 && !failsafe) {
- warnings.push({
- type: 'warning',
- message:
- 'Your CPU does not support AVX or AVX2. Enable the "Failsafe" option on the Advanced tab to avoid crashes.',
- });
- }
-
- if (
- availableBackends.length > 0 &&
- availableBackends.some((b) => b.value === 'cpu')
- ) {
- warnings.push({
- type: 'info',
- message:
- "LLMs run significantly faster on GPU-accelerated systems. Consider using NVIDIA's CUDA, AMD's ROCm or Vulkan backends for optimal performance.",
- });
- }
- }
- }
-
- return warnings;
- } catch (error) {
- window.electronAPI.logs.logError(
- 'Failed to check backend warnings:',
- error as Error
- );
- return warnings;
- }
-};