GGUF chat only for CPU
This commit is contained in:
parent
46f9be3dd1
commit
c2cd02dc8f
6 changed files with 23 additions and 13 deletions
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
"""Default model lists for inference, split by platform."""
|
"""Default model lists for inference, split by platform."""
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
DEFAULT_MODELS_GGUF = [
|
DEFAULT_MODELS_GGUF = [
|
||||||
"unsloth/Llama-3.2-1B-Instruct-GGUF",
|
"unsloth/Llama-3.2-1B-Instruct-GGUF",
|
||||||
"unsloth/Llama-3.2-3B-Instruct-GGUF",
|
"unsloth/Llama-3.2-3B-Instruct-GGUF",
|
||||||
|
|
@ -25,6 +23,7 @@ DEFAULT_MODELS_STANDARD = [
|
||||||
|
|
||||||
|
|
||||||
def get_default_models() -> list[str]:
|
def get_default_models() -> list[str]:
|
||||||
if sys.platform == "darwin":
|
import utils.hardware.hardware as hw
|
||||||
|
if hw.CHAT_ONLY:
|
||||||
return list(DEFAULT_MODELS_GGUF)
|
return list(DEFAULT_MODELS_GGUF)
|
||||||
return list(DEFAULT_MODELS_STANDARD)
|
return list(DEFAULT_MODELS_STANDARD)
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,14 @@ async def health_check():
|
||||||
platform_map = {"darwin": "mac", "win32": "windows", "linux": "linux"}
|
platform_map = {"darwin": "mac", "win32": "windows", "linux": "linux"}
|
||||||
device_type = platform_map.get(sys.platform, sys.platform)
|
device_type = platform_map.get(sys.platform, sys.platform)
|
||||||
|
|
||||||
|
chat_only = _hw_module.CHAT_ONLY
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "healthy",
|
"status": "healthy",
|
||||||
"timestamp": datetime.now().isoformat(),
|
"timestamp": datetime.now().isoformat(),
|
||||||
"service": "Unsloth UI Backend",
|
"service": "Unsloth UI Backend",
|
||||||
"device_type": device_type,
|
"device_type": device_type,
|
||||||
|
"chat_only": chat_only,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Hardware detection and GPU utilities
|
||||||
from .hardware import (
|
from .hardware import (
|
||||||
DeviceType,
|
DeviceType,
|
||||||
DEVICE,
|
DEVICE,
|
||||||
|
CHAT_ONLY,
|
||||||
detect_hardware,
|
detect_hardware,
|
||||||
get_device,
|
get_device,
|
||||||
is_apple_silicon,
|
is_apple_silicon,
|
||||||
|
|
@ -24,6 +25,7 @@ from .hardware import (
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"DeviceType",
|
"DeviceType",
|
||||||
"DEVICE",
|
"DEVICE",
|
||||||
|
"CHAT_ONLY",
|
||||||
"detect_hardware",
|
"detect_hardware",
|
||||||
"get_device",
|
"get_device",
|
||||||
"is_apple_silicon",
|
"is_apple_silicon",
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ class DeviceType(str, Enum):
|
||||||
# ========== Global State (set once by detect_hardware) ==========
|
# ========== Global State (set once by detect_hardware) ==========
|
||||||
|
|
||||||
DEVICE: Optional[DeviceType] = None
|
DEVICE: Optional[DeviceType] = None
|
||||||
|
CHAT_ONLY: bool = True # No CUDA GPU → GGUF chat only (Mac, CPU-only, etc.)
|
||||||
|
|
||||||
|
|
||||||
# ========== Detection ==========
|
# ========== Detection ==========
|
||||||
|
|
@ -81,7 +82,7 @@ def detect_hardware() -> DeviceType:
|
||||||
2. MLX (Apple Silicon via MLX framework)
|
2. MLX (Apple Silicon via MLX framework)
|
||||||
3. CPU (fallback)
|
3. CPU (fallback)
|
||||||
"""
|
"""
|
||||||
global DEVICE
|
global DEVICE, CHAT_ONLY
|
||||||
|
|
||||||
# --- CUDA: try PyTorch ---
|
# --- CUDA: try PyTorch ---
|
||||||
if _has_torch():
|
if _has_torch():
|
||||||
|
|
@ -89,6 +90,7 @@ def detect_hardware() -> DeviceType:
|
||||||
|
|
||||||
if torch.cuda.is_available():
|
if torch.cuda.is_available():
|
||||||
DEVICE = DeviceType.CUDA
|
DEVICE = DeviceType.CUDA
|
||||||
|
CHAT_ONLY = False
|
||||||
device_name = torch.cuda.get_device_properties(0).name
|
device_name = torch.cuda.get_device_properties(0).name
|
||||||
print(f"Hardware detected: CUDA — {device_name}")
|
print(f"Hardware detected: CUDA — {device_name}")
|
||||||
return DEVICE
|
return DEVICE
|
||||||
|
|
|
||||||
|
|
@ -396,9 +396,12 @@ export function HubModelPicker({
|
||||||
return s;
|
return s;
|
||||||
}, [cachedGguf, cachedModels]);
|
}, [cachedGguf, cachedModels]);
|
||||||
|
|
||||||
|
const chatOnly = usePlatformStore((s) => s.isChatOnly());
|
||||||
|
|
||||||
const recommendedIds = useMemo(() => {
|
const recommendedIds = useMemo(() => {
|
||||||
const all = dedupe([...models.map((model) => model.id), value ?? ""])
|
const all = dedupe([...models.map((model) => model.id), value ?? ""])
|
||||||
.filter((id) => !downloadedSet.has(id.toLowerCase()));
|
.filter((id) => !downloadedSet.has(id.toLowerCase()))
|
||||||
|
.filter((id) => !chatOnly || isGgufRepo(id));
|
||||||
// Cap at 4 GGUFs + 4 non-GGUFs so the list stays manageable
|
// Cap at 4 GGUFs + 4 non-GGUFs so the list stays manageable
|
||||||
const gguf: string[] = [];
|
const gguf: string[] = [];
|
||||||
const hub: string[] = [];
|
const hub: string[] = [];
|
||||||
|
|
@ -407,7 +410,7 @@ export function HubModelPicker({
|
||||||
else if (!isGgufRepo(id) && hub.length < 4) hub.push(id);
|
else if (!isGgufRepo(id) && hub.length < 4) hub.push(id);
|
||||||
}
|
}
|
||||||
return [...gguf, ...hub];
|
return [...gguf, ...hub];
|
||||||
}, [models, value, downloadedSet]);
|
}, [models, value, downloadedSet, chatOnly]);
|
||||||
|
|
||||||
const { paramCountById: recommendedParamCountById } =
|
const { paramCountById: recommendedParamCountById } =
|
||||||
useRecommendedModelVram(recommendedIds);
|
useRecommendedModelVram(recommendedIds);
|
||||||
|
|
@ -415,8 +418,6 @@ export function HubModelPicker({
|
||||||
const showHfSection = debouncedQuery.trim().length > 0;
|
const showHfSection = debouncedQuery.trim().length > 0;
|
||||||
const recommendedSet = useMemo(() => new Set(recommendedIds), [recommendedIds]);
|
const recommendedSet = useMemo(() => new Set(recommendedIds), [recommendedIds]);
|
||||||
|
|
||||||
const chatOnly = usePlatformStore((s) => s.isChatOnly());
|
|
||||||
|
|
||||||
const hfIds = useMemo(() => {
|
const hfIds = useMemo(() => {
|
||||||
if (!showHfSection) return [];
|
if (!showHfSection) return [];
|
||||||
return results
|
return results
|
||||||
|
|
@ -519,7 +520,7 @@ export function HubModelPicker({
|
||||||
<Spinner className="size-3 text-muted-foreground" />
|
<Spinner className="size-3 text-muted-foreground" />
|
||||||
<span className="text-xs text-muted-foreground">Loading models…</span>
|
<span className="text-xs text-muted-foreground">Loading models…</span>
|
||||||
</div>
|
</div>
|
||||||
) : !showHfSection && (cachedGguf.length > 0 || cachedModels.length > 0) ? (
|
) : !showHfSection && (cachedGguf.length > 0 || (!chatOnly && cachedModels.length > 0)) ? (
|
||||||
<>
|
<>
|
||||||
<ListLabel>{"\uD83E\uDDA5"} Downloaded</ListLabel>
|
<ListLabel>{"\uD83E\uDDA5"} Downloaded</ListLabel>
|
||||||
{cachedGguf.map((c) => (
|
{cachedGguf.map((c) => (
|
||||||
|
|
@ -536,7 +537,7 @@ export function HubModelPicker({
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{cachedModels.map((c) => (
|
{!chatOnly && cachedModels.map((c) => (
|
||||||
<ModelRow
|
<ModelRow
|
||||||
key={c.repo_id}
|
key={c.repo_id}
|
||||||
label={c.repo_id}
|
label={c.repo_id}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,16 @@ export type DeviceType = "mac" | "windows" | "linux" | string;
|
||||||
|
|
||||||
interface PlatformState {
|
interface PlatformState {
|
||||||
deviceType: DeviceType;
|
deviceType: DeviceType;
|
||||||
|
chatOnly: boolean;
|
||||||
fetched: boolean;
|
fetched: boolean;
|
||||||
isChatOnly: () => boolean;
|
isChatOnly: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePlatformStore = create<PlatformState>()((_, get) => ({
|
export const usePlatformStore = create<PlatformState>()((_, get) => ({
|
||||||
deviceType: "linux",
|
deviceType: "linux",
|
||||||
|
chatOnly: false,
|
||||||
fetched: false,
|
fetched: false,
|
||||||
isChatOnly: () => get().deviceType === "mac",
|
isChatOnly: () => get().chatOnly,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export async function fetchDeviceType(): Promise<DeviceType> {
|
export async function fetchDeviceType(): Promise<DeviceType> {
|
||||||
|
|
@ -33,9 +35,10 @@ export async function fetchDeviceType(): Promise<DeviceType> {
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/health");
|
const res = await fetch("/api/health");
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = (await res.json()) as { device_type?: string };
|
const data = (await res.json()) as { device_type?: string; chat_only?: boolean };
|
||||||
const deviceType = data.device_type ?? "linux";
|
const deviceType = data.device_type ?? "linux";
|
||||||
usePlatformStore.setState({ deviceType, fetched: true });
|
const chatOnly = data.chat_only ?? deviceType === "mac";
|
||||||
|
usePlatformStore.setState({ deviceType, chatOnly, fetched: true });
|
||||||
return deviceType;
|
return deviceType;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue