mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
windows fixes of linux fixes of windows fixes
This commit is contained in:
parent
c0f1b4790c
commit
982d6e4951
8 changed files with 159 additions and 128 deletions
|
|
@ -40,11 +40,9 @@ export const BackendSelector = ({
|
|||
useEffect(() => {
|
||||
const loadBackends = async () => {
|
||||
try {
|
||||
const [currentBinaryInfo, cpuCapabilitiesResult, gpuCapabilities] =
|
||||
await Promise.all([
|
||||
window.electronAPI.kobold.getCurrentBinaryInfo(),
|
||||
const [cpuCapabilitiesResult, backends] = await Promise.all([
|
||||
window.electronAPI.kobold.detectCPU(),
|
||||
window.electronAPI.kobold.detectGPUCapabilities(),
|
||||
window.electronAPI.kobold.getAvailableBackends(),
|
||||
]);
|
||||
|
||||
setCpuCapabilities({
|
||||
|
|
@ -52,23 +50,10 @@ export const BackendSelector = ({
|
|||
avx2: cpuCapabilitiesResult.avx2,
|
||||
});
|
||||
|
||||
let backends: Array<{
|
||||
value: string;
|
||||
label: string;
|
||||
devices?: string[];
|
||||
}> = [];
|
||||
|
||||
if (currentBinaryInfo?.path) {
|
||||
backends = await window.electronAPI.kobold.getAvailableBackends(
|
||||
currentBinaryInfo.path,
|
||||
gpuCapabilities
|
||||
);
|
||||
|
||||
const cpuBackend = backends.find((b) => b.value === 'cpu');
|
||||
if (cpuBackend) {
|
||||
cpuBackend.devices = cpuCapabilitiesResult.devices;
|
||||
}
|
||||
}
|
||||
|
||||
setAvailableBackends(backends);
|
||||
hasInitialized.current = true;
|
||||
|
|
@ -231,7 +216,7 @@ export const BackendSelector = ({
|
|||
step={1}
|
||||
size="sm"
|
||||
w={80}
|
||||
disabled={autoGpuLayers}
|
||||
disabled={autoGpuLayers || backend === 'cpu'}
|
||||
/>
|
||||
<Group gap="xs" align="center">
|
||||
<Checkbox
|
||||
|
|
@ -241,6 +226,7 @@ export const BackendSelector = ({
|
|||
handleAutoGpuLayersChange(event.currentTarget.checked)
|
||||
}
|
||||
size="sm"
|
||||
disabled={backend === 'cpu'}
|
||||
/>
|
||||
<InfoTooltip label="Automatically try to allocate the GPU layers based on available VRAM." />
|
||||
</Group>
|
||||
|
|
|
|||
|
|
@ -76,10 +76,7 @@ export const LaunchScreen = ({
|
|||
|
||||
const setHappyDefaults = useCallback(async () => {
|
||||
try {
|
||||
const backends = await window.electronAPI.kobold.getAvailableBackends(
|
||||
(await window.electronAPI.kobold.getCurrentBinaryInfo())?.path || '',
|
||||
await window.electronAPI.kobold.detectGPUCapabilities()
|
||||
);
|
||||
const backends = await window.electronAPI.kobold.getAvailableBackends();
|
||||
|
||||
if (!backend && backends.length > 0) {
|
||||
handleBackendChange(backends[0].value);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ class FriendlyKoboldApp {
|
|||
this.windowManager = new WindowManager();
|
||||
this.githubService = new GitHubService(this.logManager);
|
||||
this.hardwareService = new HardwareService();
|
||||
this.binaryService = new BinaryService(this.logManager);
|
||||
|
||||
this.koboldManager = new KoboldCppManager(
|
||||
this.configManager,
|
||||
|
|
@ -44,6 +43,12 @@ class FriendlyKoboldApp {
|
|||
this.logManager
|
||||
);
|
||||
|
||||
this.binaryService = new BinaryService(
|
||||
this.logManager,
|
||||
this.koboldManager,
|
||||
this.hardwareService
|
||||
);
|
||||
|
||||
this.ipcHandlers = new IPCHandlers(
|
||||
this.koboldManager,
|
||||
this.configManager,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { existsSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { LogManager } from '@/main/managers/LogManager';
|
||||
import type { KoboldCppManager } from '@/main/managers/KoboldCppManager';
|
||||
import type { HardwareService } from '@/main/services/HardwareService';
|
||||
|
||||
export interface BackendSupport {
|
||||
rocm: boolean;
|
||||
|
|
@ -18,9 +20,17 @@ export class BinaryService {
|
|||
Array<{ value: string; label: string; devices?: string[] }>
|
||||
>();
|
||||
private logManager: LogManager;
|
||||
private koboldManager: KoboldCppManager;
|
||||
private hardwareService: HardwareService;
|
||||
|
||||
constructor(logManager: LogManager) {
|
||||
constructor(
|
||||
logManager: LogManager,
|
||||
koboldManager: KoboldCppManager,
|
||||
hardwareService: HardwareService
|
||||
) {
|
||||
this.logManager = logManager;
|
||||
this.koboldManager = koboldManager;
|
||||
this.hardwareService = hardwareService;
|
||||
}
|
||||
|
||||
detectBackendSupport(koboldBinaryPath: string): BackendSupport {
|
||||
|
|
@ -46,7 +56,18 @@ export class BinaryService {
|
|||
|
||||
const hasKoboldCppLib = (name: string) => {
|
||||
const filename = `${name}${libExtension}`;
|
||||
return existsSync(join(internalDir, filename));
|
||||
|
||||
if (platform === 'win32') {
|
||||
return (
|
||||
existsSync(join(binaryDir, filename)) ||
|
||||
existsSync(join(internalDir, filename))
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
existsSync(join(internalDir, filename)) ||
|
||||
existsSync(join(binaryDir, filename))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
support.rocm = hasKoboldCppLib('koboldcpp_hipblas');
|
||||
|
|
@ -66,29 +87,33 @@ export class BinaryService {
|
|||
return support;
|
||||
}
|
||||
|
||||
getAvailableBackends(
|
||||
koboldBinaryPath: string,
|
||||
hardwareCapabilities?: {
|
||||
cuda: { supported: boolean; devices: string[] };
|
||||
rocm: { supported: boolean; devices: string[] };
|
||||
vulkan: { supported: boolean; devices: string[] };
|
||||
clblast: { supported: boolean; devices: string[] };
|
||||
async getAvailableBackends(): Promise<
|
||||
Array<{ value: string; label: string; devices?: string[] }>
|
||||
> {
|
||||
try {
|
||||
const [currentBinaryInfo, hardwareCapabilities] = await Promise.all([
|
||||
this.koboldManager.getCurrentBinaryInfo(),
|
||||
this.hardwareService.detectGPUCapabilities(),
|
||||
]);
|
||||
|
||||
if (!currentBinaryInfo?.path) {
|
||||
return [{ value: 'cpu', label: 'CPU' }];
|
||||
}
|
||||
): Array<{ value: string; label: string; devices?: string[] }> {
|
||||
const cacheKey = `${koboldBinaryPath}:${JSON.stringify(hardwareCapabilities)}`;
|
||||
|
||||
const cacheKey = `${currentBinaryInfo.path}:${JSON.stringify(hardwareCapabilities)}`;
|
||||
|
||||
if (this.availableBackendsCache.has(cacheKey)) {
|
||||
return this.availableBackendsCache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
const backendSupport = this.detectBackendSupport(koboldBinaryPath);
|
||||
const backendSupport = this.detectBackendSupport(currentBinaryInfo.path);
|
||||
const backends: Array<{
|
||||
value: string;
|
||||
label: string;
|
||||
devices?: string[];
|
||||
}> = [];
|
||||
|
||||
if (backendSupport.cuda && hardwareCapabilities?.cuda.supported) {
|
||||
if (backendSupport.cuda && hardwareCapabilities.cuda.supported) {
|
||||
backends.push({
|
||||
value: 'cuda',
|
||||
label: 'CUDA',
|
||||
|
|
@ -96,7 +121,7 @@ export class BinaryService {
|
|||
});
|
||||
}
|
||||
|
||||
if (backendSupport.rocm && hardwareCapabilities?.rocm.supported) {
|
||||
if (backendSupport.rocm && hardwareCapabilities.rocm.supported) {
|
||||
backends.push({
|
||||
value: 'rocm',
|
||||
label: 'ROCm',
|
||||
|
|
@ -104,7 +129,7 @@ export class BinaryService {
|
|||
});
|
||||
}
|
||||
|
||||
if (backendSupport.vulkan && hardwareCapabilities?.vulkan.supported) {
|
||||
if (backendSupport.vulkan && hardwareCapabilities.vulkan.supported) {
|
||||
backends.push({
|
||||
value: 'vulkan',
|
||||
label: 'Vulkan',
|
||||
|
|
@ -112,7 +137,7 @@ export class BinaryService {
|
|||
});
|
||||
}
|
||||
|
||||
if (backendSupport.clblast && hardwareCapabilities?.clblast.supported) {
|
||||
if (backendSupport.clblast && hardwareCapabilities.clblast.supported) {
|
||||
backends.push({
|
||||
value: 'clblast',
|
||||
label: 'CLBlast',
|
||||
|
|
@ -127,6 +152,13 @@ export class BinaryService {
|
|||
|
||||
this.availableBackendsCache.set(cacheKey, backends);
|
||||
return backends;
|
||||
} catch (error) {
|
||||
this.logManager.logError(
|
||||
'Failed to get available backends:',
|
||||
error as Error
|
||||
);
|
||||
return [{ value: 'cpu', label: 'CPU' }];
|
||||
}
|
||||
}
|
||||
|
||||
clearCache(): void {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export class HardwareService {
|
|||
]);
|
||||
|
||||
this.gpuCapabilitiesCache = { cuda, rocm, vulkan, clblast };
|
||||
|
||||
return this.gpuCapabilitiesCache;
|
||||
}
|
||||
|
||||
|
|
@ -303,13 +304,17 @@ export class HardwareService {
|
|||
const lines = output.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.includes('deviceName')) {
|
||||
const name = line.split('=')[1]?.trim();
|
||||
// Handle both formats: "deviceName = AMD Radeon RX 7900 GRE" and other potential formats
|
||||
if (line.includes('deviceName') && line.includes('=')) {
|
||||
const parts = line.split('=');
|
||||
if (parts.length >= 2) {
|
||||
const name = parts[1]?.trim();
|
||||
if (name) {
|
||||
devices.push(shortenDeviceName(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolve({
|
||||
supported: devices.length > 0,
|
||||
|
|
@ -343,29 +348,23 @@ export class HardwareService {
|
|||
const lines = output.split('\n');
|
||||
|
||||
let currentPlatform = '';
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
// Extract platform name
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
|
||||
// Extract platform name - this appears early in the output
|
||||
if (line.includes('Platform Name:')) {
|
||||
currentPlatform = line.split('Platform Name:')[1]?.trim() || '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract device names for GPU devices
|
||||
if (line.includes('Device Name:')) {
|
||||
const deviceName = line.split('Device Name:')[1]?.trim();
|
||||
if (deviceName) {
|
||||
// Look ahead to check if this is a GPU device
|
||||
for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
|
||||
if (lines[j].includes('Device Type:') && lines[j].includes('GPU')) {
|
||||
const deviceLabel = currentPlatform
|
||||
? `${shortenDeviceName(deviceName)} (${currentPlatform})`
|
||||
: shortenDeviceName(deviceName);
|
||||
// When we find a GPU device type, look for device name
|
||||
if (line.includes('Device Type:') && line.includes('GPU')) {
|
||||
const deviceName = this.findDeviceNameInClInfo(lines, i);
|
||||
|
||||
if (deviceName && currentPlatform) {
|
||||
const deviceLabel = `${shortenDeviceName(deviceName)} (${currentPlatform})`;
|
||||
devices.push(deviceLabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,6 +372,34 @@ export class HardwareService {
|
|||
return devices;
|
||||
}
|
||||
|
||||
private findDeviceNameInClInfo(lines: string[], startIndex: number): string {
|
||||
// Look for Board name first (appears closer to Device Type and is more descriptive)
|
||||
for (
|
||||
let j = startIndex + 1;
|
||||
j < Math.min(startIndex + 50, lines.length);
|
||||
j++
|
||||
) {
|
||||
const nextLine = lines[j].trim();
|
||||
if (nextLine.includes('Board name:')) {
|
||||
return nextLine.split('Board name:')[1]?.trim() || '';
|
||||
}
|
||||
}
|
||||
|
||||
// If no Board name found, look for Name: field (appears much later)
|
||||
for (
|
||||
let j = startIndex + 1;
|
||||
j < Math.min(startIndex + 100, lines.length);
|
||||
j++
|
||||
) {
|
||||
const nextLine = lines[j].trim();
|
||||
if (nextLine.startsWith('Name:')) {
|
||||
return nextLine.split('Name:')[1]?.trim() || '';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private async detectCLBlast(): Promise<{
|
||||
supported: boolean;
|
||||
devices: string[];
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { LogManager } from '@/main/managers/LogManager';
|
|||
import { GitHubService } from '@/main/services/GitHubService';
|
||||
import { HardwareService } from '@/main/services/HardwareService';
|
||||
import { BinaryService } from '@/main/services/BinaryService';
|
||||
import type { GPUCapabilities } from '@/types/hardware';
|
||||
|
||||
export class IPCHandlers {
|
||||
private koboldManager: KoboldCppManager;
|
||||
|
|
@ -125,13 +124,8 @@ export class IPCHandlers {
|
|||
this.binaryService.detectBackendSupport(binaryPath)
|
||||
);
|
||||
|
||||
ipcMain.handle(
|
||||
'kobold:getAvailableBackends',
|
||||
(_, binaryPath: string, hardwareCapabilities: GPUCapabilities) =>
|
||||
this.binaryService.getAvailableBackends(
|
||||
binaryPath,
|
||||
hardwareCapabilities
|
||||
)
|
||||
ipcMain.handle('kobold:getAvailableBackends', () =>
|
||||
this.binaryService.getAvailableBackends()
|
||||
);
|
||||
|
||||
ipcMain.handle('kobold:getPlatform', () => ({
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import type {
|
|||
LogsAPI,
|
||||
UpdateInfo,
|
||||
} from '@/types/electron';
|
||||
import type { GPUCapabilities } from '@/types/hardware';
|
||||
|
||||
const koboldAPI: KoboldAPI = {
|
||||
getInstalledVersion: () => ipcRenderer.invoke('kobold:getInstalledVersion'),
|
||||
|
|
@ -32,15 +31,7 @@ const koboldAPI: KoboldAPI = {
|
|||
ipcRenderer.invoke('kobold:detectAllCapabilities'),
|
||||
detectBackendSupport: (binaryPath: string) =>
|
||||
ipcRenderer.invoke('kobold:detectBackendSupport', binaryPath),
|
||||
getAvailableBackends: (
|
||||
binaryPath: string,
|
||||
hardwareCapabilities: GPUCapabilities
|
||||
) =>
|
||||
ipcRenderer.invoke(
|
||||
'kobold:getAvailableBackends',
|
||||
binaryPath,
|
||||
hardwareCapabilities
|
||||
),
|
||||
getAvailableBackends: () => ipcRenderer.invoke('kobold:getAvailableBackends'),
|
||||
getCurrentInstallDir: () => ipcRenderer.invoke('kobold:getCurrentInstallDir'),
|
||||
selectInstallDirectory: () =>
|
||||
ipcRenderer.invoke('kobold:selectInstallDirectory'),
|
||||
|
|
|
|||
7
src/types/electron.d.ts
vendored
7
src/types/electron.d.ts
vendored
|
|
@ -81,10 +81,9 @@ export interface KoboldAPI {
|
|||
failsafe: boolean;
|
||||
cuda: boolean;
|
||||
}>;
|
||||
getAvailableBackends: (
|
||||
binaryPath: string,
|
||||
hardwareCapabilities: GPUCapabilities
|
||||
) => Promise<Array<{ value: string; label: string; devices?: string[] }>>;
|
||||
getAvailableBackends: () => Promise<
|
||||
Array<{ value: string; label: string; devices?: string[] }>
|
||||
>;
|
||||
getCurrentInstallDir: () => Promise<string>;
|
||||
selectInstallDirectory: () => Promise<string | null>;
|
||||
downloadRelease: (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue