mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-19 01:04:55 +02:00
ui : move discover download types, enums and constants to lib
Extract the download-options shared symbols out of the component-local download-options.utils.ts into their lib-scoped folders: QuantOption, DownloadEntryState, BitDepthRow and SelectableFile into $lib/types; a new SelectableFileKind enum (replacing the 'main'/'draft'/'aux' string union) into $lib/enums; SPEC_TYPE, the bit-depth buckets and the draft label into a new models-discover-download.constants.ts. The util keeps only its dedicated functions, with named constants for its magic values. Assisted-by: llama-ui:Qwen3.8-Flash-Next
This commit is contained in:
+3
-3
@@ -3,9 +3,10 @@
|
||||
import ModelsDiscoverDetailsHeader from './ModelsDiscoverDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsReadme from './ModelsDiscoverDetailsReadme.svelte';
|
||||
import ModelsDiscoverDetailsSkeleton from './ModelsDiscoverDetailsSkeleton.svelte';
|
||||
import { OTHER_BIT_DEPTH } from '$lib/constants';
|
||||
import { ModelAuxSidecar } from '$lib/enums';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { HfModelDetailInfo, HfModelSibling } from '$lib/types/huggingface';
|
||||
import type { BitDepthRow, HfModelDetailInfo, HfModelSibling } from '$lib/types';
|
||||
import { detectThinkingSupport, detectToolUseSupport } from '$lib/utils';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
|
||||
@@ -48,7 +49,6 @@
|
||||
// Draft sidecars (mtp, dflash, dspark, eagle3) present in the repo, e.g.
|
||||
// speculative-decoding drafts. mmproj is excluded: it is vision.
|
||||
|
||||
type BitDepthRow = { bitDepth: number; files: HfModelSibling[] };
|
||||
let bitDepthRows = $derived.by<BitDepthRow[]>(() => {
|
||||
const rows = new SvelteMap<number, HfModelSibling[]>();
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
if (meta?.sidecar === ModelAuxSidecar.MMPROJ) continue;
|
||||
|
||||
const depth = meta?.quant ? HuggingFaceService.getBitDepth(meta.quant) : null;
|
||||
const bucket = depth ?? 99;
|
||||
const bucket = depth ?? OTHER_BIT_DEPTH;
|
||||
const list = rows.get(bucket) ?? [];
|
||||
|
||||
list.push(file);
|
||||
|
||||
+7
-10
@@ -1,16 +1,11 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
type BitDepthRow,
|
||||
classify,
|
||||
type DownloadEntryState,
|
||||
labelFor,
|
||||
type QuantOption,
|
||||
type SelectableFile
|
||||
} from './download-options.utils';
|
||||
import { classify, labelFor } from './download-options.utils';
|
||||
import ModelsDiscoverDetailsDownloadOptionsDownloadCommand from './ModelsDiscoverDetailsDownloadOptionsDownloadCommand.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptionsRow from './ModelsDiscoverDetailsDownloadOptionsRow.svelte';
|
||||
import { SelectableFileKind } from '$lib/enums';
|
||||
import { HuggingFaceService, ModelsService } from '$lib/services';
|
||||
import { modelsStore } from '$lib/stores';
|
||||
import type { BitDepthRow, DownloadEntryState, QuantOption, SelectableFile } from '$lib/types';
|
||||
|
||||
interface Props {
|
||||
/** Full HuggingFace repo id, e.g. `ggml-org/gemma-3-4b-it-GGUF`. */
|
||||
@@ -98,7 +93,9 @@
|
||||
}
|
||||
|
||||
/** Non-draft quants for the command's base select, in row order. */
|
||||
let mainOptions = $derived(selectableFiles.filter((f) => f.kind === 'main').map(optionFor));
|
||||
let mainOptions = $derived(
|
||||
selectableFiles.filter((f) => f.kind === SelectableFileKind.MAIN).map(optionFor)
|
||||
);
|
||||
|
||||
/**
|
||||
* Draft options for the command's draft select, with their sidecar type
|
||||
@@ -106,7 +103,7 @@
|
||||
*/
|
||||
let draftOptions = $derived(
|
||||
selectableFiles
|
||||
.filter((f) => f.kind === 'draft')
|
||||
.filter((f) => f.kind === SelectableFileKind.DRAFT)
|
||||
.map((f) => ({
|
||||
...optionFor(f),
|
||||
badge: HuggingFaceService.extractQuantMeta(f.path)?.sidecar ?? null
|
||||
|
||||
+3
-5
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { quantBitDepth, type QuantOption, SPEC_TYPE } from './download-options.utils';
|
||||
import { quantBitDepth } from './download-options.utils';
|
||||
import { Check, Copy, Plus, X } from '@lucide/svelte';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import { type ModelSidecar } from '$lib/constants';
|
||||
import { DEFAULT_BASE_BIT_DEPTH, type ModelSidecar,SPEC_TYPE } from '$lib/constants';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { QuantOption } from '$lib/types';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
|
||||
interface Props {
|
||||
@@ -22,9 +23,6 @@
|
||||
let draftTypePick = $state<ModelSidecar | null>(null);
|
||||
let withDraft = $state(false);
|
||||
|
||||
/** Bit depth to prefer in the default base quant; the closest one wins. */
|
||||
const DEFAULT_BASE_BIT_DEPTH = 4;
|
||||
|
||||
function bitDepthOf(path: string): number {
|
||||
return quantBitDepth(HuggingFaceService.extractQuantMeta(path)?.quant ?? null);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import DownloadProgressBar from '../../DownloadProgressBar.svelte';
|
||||
import { type DownloadEntryState, labelFor } from './download-options.utils';
|
||||
import { labelFor } from './download-options.utils';
|
||||
import { Check, Download, Loader2, Pause, Play, RotateCw, X } from '@lucide/svelte';
|
||||
import DialogConfirmation from '$lib/components/app/dialogs/DialogConfirmation.svelte';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import { modelsStore } from '$lib/stores';
|
||||
import type { HfModelSibling } from '$lib/types';
|
||||
import type { DownloadEntryState, HfModelSibling } from '$lib/types';
|
||||
|
||||
interface Props {
|
||||
/** GGUF file the chip stands for. */
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { DownloadEntryState, SelectableFile } from './download-options.utils';
|
||||
import ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton from './ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
import { SelectableFileKind } from '$lib/enums';
|
||||
import type { DownloadEntryState, SelectableFile } from '$lib/types';
|
||||
import { minMemoryTierGb } from '$lib/utils';
|
||||
|
||||
interface Props {
|
||||
@@ -12,8 +13,8 @@
|
||||
|
||||
let { bitDepth, files }: Props = $props();
|
||||
|
||||
let mainFile = $derived(files.find((f) => f.kind === 'main') ?? null);
|
||||
let draftFile = $derived(files.find((f) => f.kind === 'draft') ?? null);
|
||||
let mainFile = $derived(files.find((f) => f.kind === SelectableFileKind.MAIN) ?? null);
|
||||
let draftFile = $derived(files.find((f) => f.kind === SelectableFileKind.DRAFT) ?? null);
|
||||
|
||||
let mainMemGb = $derived(mainFile ? minMemoryTierGb(mainFile.size ?? 0) : null);
|
||||
let draftMemGb = $derived(draftFile ? minMemoryTierGb(draftFile.size ?? 0) : null);
|
||||
|
||||
+22
-52
@@ -1,44 +1,24 @@
|
||||
import { isAuxSidecar, isDraftSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import { ModelAuxSidecar, ModelDraftSidecar } from '$lib/enums';
|
||||
import { DRAFT_FILE_LABEL, isAuxSidecar, isDraftSidecar, OTHER_BIT_DEPTH } from '$lib/constants';
|
||||
import { SelectableFileKind } from '$lib/enums';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { HfModelSibling } from '$lib/types/huggingface';
|
||||
|
||||
/**
|
||||
* Option of a quant `<select>`; the picks only compose the serve command and
|
||||
* are not bound to the quant chips.
|
||||
*/
|
||||
export interface QuantOption {
|
||||
/** Quant token, or the file name when the file carries no quant (e.g. BF16). */
|
||||
label: string;
|
||||
/** Repo-relative file path the option stands for. */
|
||||
path: string;
|
||||
}
|
||||
|
||||
/** Download state of a single repo entry, injected by the integration layer. */
|
||||
export interface DownloadEntryState {
|
||||
/** Server identifier the entry's actions (pause / resume / cancel / retry) target. */
|
||||
repoWithTag: string;
|
||||
isDownloading: boolean;
|
||||
progress: ModelDownloadProgress | null;
|
||||
isDownloaded: boolean;
|
||||
isPaused: boolean;
|
||||
isFailed: boolean;
|
||||
}
|
||||
|
||||
/** Download state of a single repo entry, injected by the integration layer. */
|
||||
|
||||
export type BitDepthRow = { bitDepth: number; files: HfModelSibling[] };
|
||||
|
||||
/** A selectable GGUF, tagged with its kind: main weights, draft, or aux (mmproj). */
|
||||
export type SelectableFile = HfModelSibling & { kind: 'main' | 'draft' | 'aux' };
|
||||
/** Leading `UD-` (Unsloth Dynamic) quant prefix and its length. */
|
||||
const UD_QUANT_PREFIX = 'UD-';
|
||||
const UD_QUANT_PREFIX_REGEX = /^UD-(?=.)/i;
|
||||
/** Captures the bit-depth digits of a quant token, e.g. `Q4_K_M` -> `4`. */
|
||||
const QUANT_BIT_DEPTH_REGEX = /(?:I?Q|F)(\d+)/i;
|
||||
/** Trailing weight extension, stripped from a quantless file's label. */
|
||||
const WEIGHT_EXTENSION_LABEL_REGEX = /\.gguf$/i;
|
||||
/** Path separator between path segments. */
|
||||
const PATH_SEPARATOR = '/';
|
||||
|
||||
/** Kind of a file path: the main weights, a draft sidecar, or an aux sidecar (mmproj). */
|
||||
export function classify(path: string): 'main' | 'draft' | 'aux' {
|
||||
export function classify(path: string): SelectableFileKind {
|
||||
const sidecar = HuggingFaceService.extractQuantMeta(path)?.sidecar;
|
||||
|
||||
if (!sidecar) return 'main';
|
||||
if (!sidecar) return SelectableFileKind.MAIN;
|
||||
|
||||
return isAuxSidecar(sidecar) ? 'aux' : 'draft';
|
||||
return isAuxSidecar(sidecar) ? SelectableFileKind.AUX : SelectableFileKind.DRAFT;
|
||||
}
|
||||
|
||||
/** Display label of a file: its quant, else the file name without the extension. */
|
||||
@@ -49,32 +29,22 @@ export function labelFor(path: string): string {
|
||||
|
||||
// Quantless sidecar files: the chip badge already carries the sidecar type,
|
||||
// so the label only marks draft files; aux sidecars badge alone.
|
||||
if (meta?.sidecar) return isDraftSidecar(meta.sidecar) ? 'draft' : '';
|
||||
if (meta?.sidecar) return isDraftSidecar(meta.sidecar) ? DRAFT_FILE_LABEL : '';
|
||||
|
||||
const basename = path.split('/').pop() ?? path;
|
||||
const basename = path.split(PATH_SEPARATOR).pop() ?? path;
|
||||
|
||||
return basename.replace(/\.gguf$/i, '');
|
||||
return basename.replace(WEIGHT_EXTENSION_LABEL_REGEX, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit depth of a quant token; `99` (Other) when it carries none. The `UD-`
|
||||
* Bit depth of a quant token; `OTHER_BIT_DEPTH` when it carries none. The `UD-`
|
||||
* unsloth prefix is stripped before matching.
|
||||
*/
|
||||
export function quantBitDepth(quant: string | null): number {
|
||||
if (!quant) return 99;
|
||||
if (!quant) return OTHER_BIT_DEPTH;
|
||||
|
||||
const stripped = quant.match(/^UD-(?=.)/i) ? quant.slice(3) : quant;
|
||||
const bit = stripped.match(/(?:I?Q|F)(\d+)/i)?.[1];
|
||||
const stripped = UD_QUANT_PREFIX_REGEX.test(quant) ? quant.slice(UD_QUANT_PREFIX.length) : quant;
|
||||
const bit = stripped.match(QUANT_BIT_DEPTH_REGEX)?.[1];
|
||||
|
||||
return bit ? Number(bit) : 99;
|
||||
return bit ? Number(bit) : OTHER_BIT_DEPTH;
|
||||
}
|
||||
|
||||
// LLAMA-APP-REUSE: --spec-type value for each draft sidecar; aux sidecars stay empty
|
||||
export const SPEC_TYPE: Record<ModelSidecar, string> = {
|
||||
[ModelAuxSidecar.IMATRIX]: '',
|
||||
[ModelAuxSidecar.MMPROJ]: '',
|
||||
[ModelDraftSidecar.DFLASH]: 'draft-dflash',
|
||||
[ModelDraftSidecar.DSPARK]: 'draft-dspark',
|
||||
[ModelDraftSidecar.EAGLE3]: 'eagle3',
|
||||
[ModelDraftSidecar.MTP]: 'draft-mtp'
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ export * from './path-display.constants';
|
||||
export * from './model-id.constants';
|
||||
export * from './model-loading.constants';
|
||||
export * from './models-discover.constants';
|
||||
export * from './models-discover-download.constants';
|
||||
export * from './huggingface.constants';
|
||||
export * from './precision.constants';
|
||||
export * from './pwa.constants';
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Models Discover — download options constants.
|
||||
*
|
||||
* Shared values backing the download-options area of the details pane: the
|
||||
* serve `--spec-type` mapping, the bit-depth buckets, and the standalone
|
||||
* command builder. Kept here (not component-local) so they sit with the rest
|
||||
* of the discover domain constants.
|
||||
*/
|
||||
|
||||
import type { ModelSidecar } from '$lib/constants';
|
||||
import { ModelAuxSidecar, ModelDraftSidecar } from '$lib/enums';
|
||||
|
||||
/**
|
||||
* `--spec-type` value for each draft sidecar; aux sidecars (mmproj, imatrix)
|
||||
* carry none and stay empty.
|
||||
*/
|
||||
// LLAMA-APP-REUSE: --spec-type value for each draft sidecar; aux sidecars stay empty
|
||||
export const SPEC_TYPE: Record<ModelSidecar, string> = {
|
||||
[ModelAuxSidecar.IMATRIX]: '',
|
||||
[ModelAuxSidecar.MMPROJ]: '',
|
||||
[ModelDraftSidecar.DFLASH]: 'draft-dflash',
|
||||
[ModelDraftSidecar.DSPARK]: 'draft-dspark',
|
||||
[ModelDraftSidecar.EAGLE3]: 'eagle3',
|
||||
[ModelDraftSidecar.MTP]: 'draft-mtp'
|
||||
};
|
||||
|
||||
/** Bit-depth bucket for files that carry no quant token; rendered as "Other". */
|
||||
export const OTHER_BIT_DEPTH = 99;
|
||||
|
||||
/** Bit depth preferred for the command's default base quant. */
|
||||
export const DEFAULT_BASE_BIT_DEPTH = 4;
|
||||
|
||||
/** Label shown for a draft-sidecar chip whose quant is unknown. */
|
||||
export const DRAFT_FILE_LABEL = 'draft';
|
||||
@@ -69,7 +69,13 @@ export {
|
||||
JsonSchemaType
|
||||
} from './mcp.enums';
|
||||
|
||||
export { ModelAuxSidecar, ModelCapability, ModelDraftSidecar, ModelModality } from './model.enums';
|
||||
export {
|
||||
ModelAuxSidecar,
|
||||
ModelCapability,
|
||||
ModelDraftSidecar,
|
||||
ModelModality,
|
||||
SelectableFileKind
|
||||
} from './model.enums';
|
||||
|
||||
export { ServerRole, ServerModelStatus, ServerModelsSseEventType } from './server.enums';
|
||||
|
||||
|
||||
@@ -31,8 +31,18 @@ export enum ModelDraftSidecar {
|
||||
* accompanying the main model weights.
|
||||
*/
|
||||
export enum ModelAuxSidecar {
|
||||
/** Multimodal projector: unlocks vision and/or audio input modalities. */
|
||||
MMPROJ = 'mmproj',
|
||||
/** Importance-matrix data used to build imatrix quants; not loaded at serve time. */
|
||||
IMATRIX = 'imatrix'
|
||||
IMATRIX = 'imatrix',
|
||||
/** Multimodal projector: unlocks vision and/or audio input modalities. */
|
||||
MMPROJ = 'mmproj'
|
||||
}
|
||||
|
||||
/**
|
||||
* Role of a selectable GGUF in the download options: the main weights, a
|
||||
* speculative-decoding draft sidecar, or an auxiliary sidecar (mmproj).
|
||||
*/
|
||||
export enum SelectableFileKind {
|
||||
AUX = 'aux',
|
||||
DRAFT = 'draft',
|
||||
MAIN = 'main'
|
||||
}
|
||||
|
||||
@@ -115,6 +115,14 @@ export type {
|
||||
ModalityCapabilities
|
||||
} from './models';
|
||||
|
||||
// Models discover types
|
||||
export type {
|
||||
BitDepthRow,
|
||||
DownloadEntryState,
|
||||
QuantOption,
|
||||
SelectableFile
|
||||
} from './models-discover';
|
||||
|
||||
// Settings types
|
||||
export type {
|
||||
SettingsConfigValue,
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import type { SelectableFileKind } from '$lib/enums';
|
||||
import type { HfModelSibling } from '$lib/types/huggingface';
|
||||
|
||||
/**
|
||||
* Option of a quant `<select>` in the download-options command builder; the
|
||||
* picks only compose the serve command and are not bound to the quant chips.
|
||||
*/
|
||||
export interface QuantOption {
|
||||
/** Quant token, or the file name when the file carries no quant (e.g. BF16). */
|
||||
label: string;
|
||||
/** Repo-relative file path the option stands for. */
|
||||
path: string;
|
||||
}
|
||||
|
||||
/** Download state of a single repo entry, injected by the integration layer. */
|
||||
export interface DownloadEntryState {
|
||||
/** Server identifier the entry's actions (pause / resume / cancel / retry) target. */
|
||||
repoWithTag: string;
|
||||
isDownloading: boolean;
|
||||
progress: ModelDownloadProgress | null;
|
||||
isDownloaded: boolean;
|
||||
isPaused: boolean;
|
||||
isFailed: boolean;
|
||||
}
|
||||
|
||||
/** A group of GGUF files sharing one bit-depth bucket. */
|
||||
export type BitDepthRow = { bitDepth: number; files: HfModelSibling[] };
|
||||
|
||||
/** A selectable GGUF, tagged with its role: main weights, draft, or aux (mmproj). */
|
||||
export type SelectableFile = HfModelSibling & { kind: SelectableFileKind };
|
||||
Reference in New Issue
Block a user