mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-20 01:31:31 +02:00
ui : replace magic strings in hf service and model status store
Extract remaining magic values into named constants/enums: - HF service: reuse PATH_SEPARATOR for the '/' split, new HF_SHARED_DRAFT_TOKEN and HF_SIZE_STRING_REGEX constants. - Model status store: reuse MODEL_ID.QUANTIZATION_SEPARATOR for ':' and PATH_SEPARATOR for the sidecar cache key; new CLI_FLAGS entries for --model-draft / -md / --mmproj; a new DownloadStopRequest enum replacing the 'pause' | 'cancel' string union. - Reuse the shared PATH_SEPARATOR in download-options.utils. Assisted-by: llama-ui:Qwen3.8-Flash-Next
This commit is contained in:
+7
-3
@@ -1,4 +1,10 @@
|
||||
import { DRAFT_FILE_LABEL, isAuxSidecar, isDraftSidecar, OTHER_BIT_DEPTH } from '$lib/constants';
|
||||
import {
|
||||
DRAFT_FILE_LABEL,
|
||||
isAuxSidecar,
|
||||
isDraftSidecar,
|
||||
OTHER_BIT_DEPTH,
|
||||
PATH_SEPARATOR
|
||||
} from '$lib/constants';
|
||||
import { SelectableFileKind } from '$lib/enums';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
|
||||
@@ -9,8 +15,6 @@ const UD_QUANT_PREFIX_REGEX = /^UD-(?=.)/i;
|
||||
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): SelectableFileKind {
|
||||
|
||||
@@ -2,6 +2,12 @@ export const CLI_FLAGS = {
|
||||
AGENT: '--agent',
|
||||
API_KEY: '--api-key',
|
||||
MCP_PROXY: '--ui-mcp-proxy',
|
||||
/** Multimodal projector path; unlocks vision/audio for the model. */
|
||||
MMPROJ: '--mmproj',
|
||||
/** Draft model weights path (long form); the router records it per model. */
|
||||
MODEL_DRAFT: '--model-draft',
|
||||
/** Draft model weights path (short form). */
|
||||
MODEL_DRAFT_SHORT: '-md',
|
||||
SLOTS: '--slots',
|
||||
TOOLS: '--tools'
|
||||
} as const;
|
||||
|
||||
@@ -78,6 +78,11 @@ export const HF_SHARD_PAD_WIDTH = 5;
|
||||
/** `UD-` (Unsloth Dynamic) custom quantization prefix, e.g. `UD-Q4_K_XL`. */
|
||||
export const HF_UD_QUANT_PREFIX = 'UD';
|
||||
export const HF_UD_QUANT_PREFIX_REGEX = /^UD-/i;
|
||||
/**
|
||||
* Segment marking an Unsloth `shared-` draft head that borrows the target
|
||||
* model's embedding/output weights, e.g. `...-shared-Q4_K_M.gguf`.
|
||||
*/
|
||||
export const HF_SHARED_DRAFT_TOKEN = 'shared';
|
||||
/**
|
||||
* Extracts the leading precision digits from a quant token, e.g.
|
||||
* `Q4_K_XL` -> 4, `IQ2_XXS` -> 2, `TQ1_0` -> 1, `BF16` -> 16.
|
||||
@@ -136,6 +141,13 @@ export const MEGABYTE = 1_000_000;
|
||||
export const GIGABYTE = 1_000_000_000;
|
||||
export const TERABYTE = 1_000_000_000_000;
|
||||
|
||||
/**
|
||||
* Matches a human size string (`177GB`, `1.2 TB`, `500MB`), capturing the
|
||||
* numeric value and its unit suffix. Used by `parseSizeBytes`.
|
||||
*/
|
||||
// LLAMA-APP-REUSE: catalog size string parsing
|
||||
export const HF_SIZE_STRING_REGEX = /^\s*([\d.]+)\s*([a-z]+)\s*$/i;
|
||||
|
||||
/**
|
||||
* Byte multiplier for a size suffix (`k` kilobyte, `m` megabyte, ...) as used by
|
||||
* the llama.app catalog `size` strings, whose suffix is lowercase.
|
||||
|
||||
@@ -77,6 +77,8 @@ export {
|
||||
SelectableFileKind
|
||||
} from './model.enums';
|
||||
|
||||
export { DownloadStopRequest } from './model.enums';
|
||||
|
||||
export { ServerRole, ServerModelStatus, ServerModelsSseEventType } from './server.enums';
|
||||
|
||||
export { ParameterSource, SyncableParameterType, SettingsFieldType } from './settings.enums';
|
||||
|
||||
@@ -46,3 +46,13 @@ export enum SelectableFileKind {
|
||||
DRAFT = 'draft',
|
||||
MAIN = 'main'
|
||||
}
|
||||
|
||||
/**
|
||||
* Why an in-flight download is being stopped, so the terminal `download_failed`
|
||||
* feed event can be attributed: a user pause (resumable) or a user cancel
|
||||
* (discard). Distinguishes these from a genuine download failure.
|
||||
*/
|
||||
export enum DownloadStopRequest {
|
||||
CANCEL = 'cancel',
|
||||
PAUSE = 'pause'
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import {
|
||||
HF_SAFETENSORS_TAG,
|
||||
HF_SHARD_PAD_WIDTH,
|
||||
HF_SHARD_REGEX,
|
||||
HF_SHARED_DRAFT_TOKEN,
|
||||
HF_SIZE_STRING_REGEX,
|
||||
HF_SIZE_SUFFIX_BYTES,
|
||||
HF_TASK_TAGS,
|
||||
HF_TREE_PATH,
|
||||
@@ -191,7 +193,7 @@ export class HuggingFaceService {
|
||||
|
||||
// HF repos may nest sidecars in a folder (e.g. `MTP/mtp-Model-Q4_0.gguf`);
|
||||
// parse the file name only, the folder adds no quant information.
|
||||
let source = (filename.split('/').pop() ?? filename).replace(
|
||||
let source = (filename.split(PATH_SEPARATOR).pop() ?? filename).replace(
|
||||
MODEL_ID.WEIGHT_EXTENSION_REGEX,
|
||||
''
|
||||
);
|
||||
@@ -233,7 +235,7 @@ export class HuggingFaceService {
|
||||
const quantIdx = segments.findIndex((seg) => MODEL_ID.QUANTIZATION_SEGMENT_REGEX.test(seg));
|
||||
// Unsloth ships draft heads in two layouts: `shared-` files borrow the
|
||||
// embedding/output weights from the target model, others are self-contained.
|
||||
const shared = segments.some((seg) => seg.toLowerCase() === 'shared');
|
||||
const shared = segments.some((seg) => seg.toLowerCase() === HF_SHARED_DRAFT_TOKEN);
|
||||
|
||||
let quant = quantIdx >= 0 ? segments[quantIdx].toUpperCase() : null;
|
||||
|
||||
@@ -623,9 +625,8 @@ export class HuggingFaceService {
|
||||
* null when it carries no number or no known suffix, so callers can fall
|
||||
* back to another source instead of showing a wrong size.
|
||||
*/
|
||||
// LLAMA-APP-REUSE: catalog size string parsing
|
||||
static parseSizeBytes(size: string): number | null {
|
||||
const match = /^\s*([\d.]+)\s*([a-z]+)\s*$/i.exec(size);
|
||||
const match = HF_SIZE_STRING_REGEX.exec(size);
|
||||
|
||||
if (!match) return null;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
* modelsStore; the host owns the router model rows the feed updates.
|
||||
*/
|
||||
|
||||
import { HF_UD_QUANT_PREFIX_REGEX } from '$lib/constants';
|
||||
import { ServerModelsSseEventType, ServerModelStatus } from '$lib/enums';
|
||||
import { CLI_FLAGS, HF_UD_QUANT_PREFIX_REGEX, MODEL_ID, PATH_SEPARATOR } from '$lib/constants';
|
||||
import { DownloadStopRequest, ServerModelsSseEventType, ServerModelStatus } from '$lib/enums';
|
||||
import { HuggingFaceService } from '$lib/services/huggingface.service';
|
||||
import { ModelsService } from '$lib/services/models.service';
|
||||
import type { ModelPropsManager } from '$lib/stores/models/props.svelte';
|
||||
@@ -41,7 +41,7 @@ export interface ModelStatusHost {
|
||||
* must compare equal.
|
||||
*/
|
||||
function downloadIdKey(repoWithTag: string): string {
|
||||
const idx = repoWithTag.indexOf(':');
|
||||
const idx = repoWithTag.indexOf(MODEL_ID.QUANTIZATION_SEPARATOR);
|
||||
const repo = idx === -1 ? repoWithTag : repoWithTag.slice(0, idx);
|
||||
const tag = idx === -1 ? '' : repoWithTag.slice(idx + 1);
|
||||
|
||||
@@ -64,13 +64,17 @@ export class ModelStatusManager {
|
||||
if (!args) continue;
|
||||
|
||||
for (let i = 0; i < args.length - 1; i++) {
|
||||
if (args[i] !== '--model-draft' && args[i] !== '-md' && args[i] !== '--mmproj') {
|
||||
if (
|
||||
args[i] !== CLI_FLAGS.MODEL_DRAFT &&
|
||||
args[i] !== CLI_FLAGS.MODEL_DRAFT_SHORT &&
|
||||
args[i] !== CLI_FLAGS.MMPROJ
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const parsed = HuggingFaceService.parseCachePath(args[i + 1]);
|
||||
|
||||
if (parsed) result.add(`${parsed.repo}/${parsed.file}`);
|
||||
if (parsed) result.add(`${parsed.repo}${PATH_SEPARATOR}${parsed.file}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +95,7 @@ export class ModelStatusManager {
|
||||
{ target: ServerModelStatus; resolve: () => void; reject: (e: Error) => void }
|
||||
>();
|
||||
/** Tags the user asked to stop (pause or cancel); the download_failed the stop triggers is intentional, not a failure. */
|
||||
private stopRequests = new SvelteMap<string, 'pause' | 'cancel'>();
|
||||
private stopRequests = new SvelteMap<string, DownloadStopRequest>();
|
||||
|
||||
/**
|
||||
* Cancel an in-flight download or remove a previously downloaded/failed model
|
||||
@@ -110,7 +114,7 @@ export class ModelStatusManager {
|
||||
// in-flight: the kill triggers download_failed over the feed; mark it as a
|
||||
// user cancel so it settles silently instead of toasting a failure
|
||||
if (this.downloadProgress.has(repoWithTag)) {
|
||||
this.stopRequests.set(repoWithTag, 'cancel');
|
||||
this.stopRequests.set(repoWithTag, DownloadStopRequest.CANCEL);
|
||||
}
|
||||
|
||||
// a downloaded model registers under the name the router derived from the
|
||||
@@ -342,7 +346,7 @@ export class ModelStatusManager {
|
||||
|
||||
this.subscribe();
|
||||
|
||||
this.stopRequests.set(repoWithTag, 'pause');
|
||||
this.stopRequests.set(repoWithTag, DownloadStopRequest.PAUSE);
|
||||
|
||||
try {
|
||||
await ModelsService.unload(repoWithTag);
|
||||
@@ -416,7 +420,7 @@ export class ModelStatusManager {
|
||||
* delete-and-retry path.
|
||||
*/
|
||||
private applyDownloadFinished(event: ApiModelsSseEvent): void {
|
||||
let request: 'pause' | 'cancel' | undefined;
|
||||
let request: DownloadStopRequest | undefined;
|
||||
|
||||
if (event.event === ServerModelsSseEventType.DOWNLOAD_FAILED) {
|
||||
request = this.stopRequests.get(event.model);
|
||||
@@ -427,7 +431,7 @@ export class ModelStatusManager {
|
||||
|
||||
this.downloadProgress.delete(event.model);
|
||||
|
||||
if (request === 'cancel') {
|
||||
if (request === DownloadStopRequest.CANCEL) {
|
||||
// user cancel: settle silently, the feed's model_remove cleans up the entry
|
||||
this.failedDownloads.delete(event.model);
|
||||
this.pausedDownloads.delete(event.model);
|
||||
@@ -435,7 +439,7 @@ export class ModelStatusManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (request === 'pause') {
|
||||
if (request === DownloadStopRequest.PAUSE) {
|
||||
this.pausedDownloads.set(event.model, progress);
|
||||
this.failedDownloads.delete(event.model);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user