mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-17 20:31:47 +02:00
ui : extract discover pipeline tags, memory and serve-command constants
Move remaining magic strings in the discover UI into $lib/constants: - HF modalities: HF_MODALITY_PIPELINE_TAGS (vision/audio/video pipeline_tag groups) and HF_MMPROJ_FILENAME_TOKEN; reuse MODEL_ID.ORG_SEPARATOR for the org split. - Bit-depth row: OTHER_BIT_DEPTH_LABEL, BIT_DEPTH_LABEL_SUFFIX and the existing GIGABYTE_LABEL / OTHER_BIT_DEPTH instead of 'Other', '-bit', 'GB'. - Serve command preview: a SERVE_COMMAND constants object (llama/serve/-hf/ -hfd/--spec-type) plus MODEL_ID.QUANTIZATION_SEPARATOR for the ':' join. Assisted-by: llama-ui:Qwen3.8-Flash-Next
This commit is contained in:
+30
-10
@@ -2,7 +2,13 @@
|
||||
import { quantBitDepth } from './download-options.utils';
|
||||
import { Check, Copy, Plus, X } from '@lucide/svelte';
|
||||
import * as Select from '$lib/components/ui/select';
|
||||
import { DEFAULT_BASE_BIT_DEPTH, type ModelSidecar,SPEC_TYPE } from '$lib/constants';
|
||||
import {
|
||||
DEFAULT_BASE_BIT_DEPTH,
|
||||
MODEL_ID,
|
||||
type ModelSidecar,
|
||||
SERVE_COMMAND,
|
||||
SPEC_TYPE
|
||||
} from '$lib/constants';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { QuantOption } from '$lib/types';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
@@ -91,10 +97,20 @@
|
||||
|
||||
/** The llama serve command, composed from the inline picks. */
|
||||
let command = $derived.by(() => {
|
||||
const parts = ['llama', 'serve', '-hf', mainQuant ? `${modelId}:${mainQuant}` : modelId];
|
||||
const parts = [
|
||||
SERVE_COMMAND.BIN,
|
||||
SERVE_COMMAND.SUBCOMMAND,
|
||||
SERVE_COMMAND.MODEL_FLAG,
|
||||
mainQuant ? `${modelId}${MODEL_ID.QUANTIZATION_SEPARATOR}${mainQuant}` : modelId
|
||||
];
|
||||
|
||||
if (draftOption && draftQuant) {
|
||||
parts.push('-hfd', `${modelId}:${draftQuant}`, '--spec-type', specType ?? '');
|
||||
parts.push(
|
||||
SERVE_COMMAND.DRAFT_FLAG,
|
||||
`${modelId}${MODEL_ID.QUANTIZATION_SEPARATOR}${draftQuant}`,
|
||||
SERVE_COMMAND.SPEC_TYPE_FLAG,
|
||||
specType ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
return parts.join(' ');
|
||||
@@ -124,13 +140,15 @@
|
||||
<div
|
||||
class="flex min-w-0 flex-1 items-center gap-x-2 overflow-x-auto py-0.5 font-mono text-xs whitespace-nowrap text-foreground/90"
|
||||
>
|
||||
<span class="shrink-0">llama</span>
|
||||
<span class="shrink-0">{SERVE_COMMAND.BIN}</span>
|
||||
|
||||
<span class="shrink-0">serve</span>
|
||||
<span class="shrink-0">{SERVE_COMMAND.SUBCOMMAND}</span>
|
||||
|
||||
<span class="shrink-0">-hf</span>
|
||||
<span class="shrink-0">{SERVE_COMMAND.MODEL_FLAG}</span>
|
||||
|
||||
<span class="shrink-0">{modelId}{mainQuant ? ':' : ''}</span>
|
||||
<span class="shrink-0">
|
||||
{modelId}{mainQuant ? MODEL_ID.QUANTIZATION_SEPARATOR : ''}
|
||||
</span>
|
||||
|
||||
<!-- Base quant: always part of the command, the 4-bit file by default. -->
|
||||
{#if baseOption}
|
||||
@@ -172,9 +190,11 @@
|
||||
it only appears while hovering the segment, or directly on touch -->
|
||||
{#if draftOption}
|
||||
<span class="group/draft inline-flex shrink-0 items-center gap-x-2">
|
||||
<span>-hfd</span>
|
||||
<span>{SERVE_COMMAND.DRAFT_FLAG}</span>
|
||||
|
||||
<span class="shrink-0">{modelId}{draftQuant ? ':' : ''}</span>
|
||||
<span class="shrink-0">
|
||||
{modelId}{draftQuant ? MODEL_ID.QUANTIZATION_SEPARATOR : ''}
|
||||
</span>
|
||||
|
||||
<Select.Root
|
||||
onValueChange={(v) => v && (draftPick = v)}
|
||||
@@ -199,7 +219,7 @@
|
||||
</Select.Root>
|
||||
|
||||
{#if draftType}
|
||||
<span>--spec-type</span>
|
||||
<span>{SERVE_COMMAND.SPEC_TYPE_FLAG}</span>
|
||||
|
||||
<!-- the select only earns its chrome when there is a real choice to make -->
|
||||
{#if specTypes.length > 1}
|
||||
|
||||
+12
-4
@@ -1,5 +1,11 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton from './ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
import {
|
||||
BIT_DEPTH_LABEL_SUFFIX,
|
||||
GIGABYTE_LABEL,
|
||||
OTHER_BIT_DEPTH,
|
||||
OTHER_BIT_DEPTH_LABEL
|
||||
} from '$lib/constants';
|
||||
import { SelectableFileKind } from '$lib/enums';
|
||||
import type { DownloadEntryState, SelectableFile } from '$lib/types';
|
||||
import { minMemoryTierGb } from '$lib/utils';
|
||||
@@ -22,15 +28,17 @@
|
||||
|
||||
<div class="grid grid-cols-[5rem_1fr] items-center gap-3 py-3">
|
||||
<div class="pt-1 text-sm tabular-nums text-muted-foreground">
|
||||
{#if bitDepth === 99}
|
||||
Other
|
||||
{#if bitDepth === OTHER_BIT_DEPTH}
|
||||
{OTHER_BIT_DEPTH_LABEL}
|
||||
{:else}
|
||||
{bitDepth}-bit
|
||||
{bitDepth}{BIT_DEPTH_LABEL_SUFFIX}
|
||||
{/if}
|
||||
|
||||
{#if mainMemGb}
|
||||
<span class="block text-[10px] whitespace-nowrap text-muted-foreground/60">
|
||||
needs at least {mainMemGb}GB{draftMemGb ? ` + ${draftMemGb}GB` : ''}+ memory
|
||||
needs at least {mainMemGb}{GIGABYTE_LABEL}{draftMemGb
|
||||
? ` + ${draftMemGb}${GIGABYTE_LABEL}`
|
||||
: ''}+ memory
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
+14
-12
@@ -1,7 +1,13 @@
|
||||
<script lang="ts">
|
||||
import ModelId from '../../ModelId.svelte';
|
||||
import ModelsDiscoverAvatar from '../ModelsDiscoverAvatar.svelte';
|
||||
import { isAuxSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import {
|
||||
HF_MMPROJ_FILENAME_TOKEN,
|
||||
HF_MODALITY_PIPELINE_TAGS,
|
||||
isAuxSidecar,
|
||||
MODEL_ID,
|
||||
type ModelSidecar
|
||||
} from '$lib/constants';
|
||||
import { HuggingFaceService, ModelsService } from '$lib/services';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
import type { ModelsHubSizeRange } from '$lib/stores/models-hub/index.svelte';
|
||||
@@ -20,7 +26,7 @@
|
||||
|
||||
let { active = false, model, onSelect, showBaseModelAvatar = false }: Props = $props();
|
||||
|
||||
let org = $derived(model.id.split('/')[0] ?? model.id);
|
||||
let org = $derived(model.id.split(MODEL_ID.ORG_SEPARATOR)[0] ?? model.id);
|
||||
|
||||
// Org whose avatar is shown: the base model's org when showBaseModelAvatar
|
||||
// (e.g. the Qwen logo for ggml-org/Qwen3.8-27B-GGUF), else the repo's org.
|
||||
@@ -74,16 +80,12 @@
|
||||
let modalities = $derived.by<ModelModalities>(() => {
|
||||
const tag = model.pipeline_tag ?? '';
|
||||
const vision =
|
||||
['image-text-to-text', 'image-to-text', 'text-to-image', 'image-to-video'].includes(tag) ||
|
||||
Boolean(model.siblings?.some((s) => s.rfilename.toLowerCase().includes('mmproj')));
|
||||
const audio = [
|
||||
'audio-classification',
|
||||
'audio-to-audio',
|
||||
'automatic-speech-recognition',
|
||||
'text-to-speech',
|
||||
'voice-activity-detection'
|
||||
].includes(tag);
|
||||
const video = ['text-to-video', 'image-to-video', 'video-to-video'].includes(tag);
|
||||
HF_MODALITY_PIPELINE_TAGS.vision.includes(tag) ||
|
||||
Boolean(
|
||||
model.siblings?.some((s) => s.rfilename.toLowerCase().includes(HF_MMPROJ_FILENAME_TOKEN))
|
||||
);
|
||||
const audio = HF_MODALITY_PIPELINE_TAGS.audio.includes(tag);
|
||||
const video = HF_MODALITY_PIPELINE_TAGS.video.includes(tag);
|
||||
|
||||
return { audio, video, vision };
|
||||
});
|
||||
|
||||
@@ -100,6 +100,28 @@ export const HF_SAFETENSORS_TAG = 'safetensors';
|
||||
|
||||
// Pipeline tasks (logic use only - matching `pipeline_tag` values against tags)
|
||||
|
||||
/**
|
||||
* `pipeline_tag` values grouped by the input/output modality they imply, used
|
||||
* to derive a discover row's modality icons. A tag in more than one group (e.g.
|
||||
* `image-to-video`) lights up each modality it belongs to.
|
||||
*/
|
||||
export const HF_MODALITY_PIPELINE_TAGS: Readonly<
|
||||
Record<'audio' | 'video' | 'vision', readonly string[]>
|
||||
> = {
|
||||
audio: [
|
||||
'audio-classification',
|
||||
'audio-to-audio',
|
||||
'automatic-speech-recognition',
|
||||
'text-to-speech',
|
||||
'voice-activity-detection'
|
||||
],
|
||||
video: ['text-to-video', 'image-to-video', 'video-to-video'],
|
||||
vision: ['image-text-to-text', 'image-to-text', 'text-to-image', 'image-to-video']
|
||||
};
|
||||
|
||||
/** Filename token marking an mmproj sidecar sibling (unlocks vision / audio). */
|
||||
export const HF_MMPROJ_FILENAME_TOKEN = 'mmproj';
|
||||
|
||||
export const HF_TASK_TAGS: readonly string[] = [
|
||||
'audio-classification',
|
||||
'audio-to-audio',
|
||||
|
||||
@@ -27,6 +27,27 @@ export const SPEC_TYPE: Record<ModelSidecar, string> = {
|
||||
/** Bit-depth bucket for files that carry no quant token; rendered as "Other". */
|
||||
export const OTHER_BIT_DEPTH = 99;
|
||||
|
||||
/** Label for the OTHER_BIT_DEPTH bucket. */
|
||||
export const OTHER_BIT_DEPTH_LABEL = 'Other';
|
||||
|
||||
/** Suffix appended after a bit-depth number to label a row, e.g. `4-bit`. */
|
||||
export const BIT_DEPTH_LABEL_SUFFIX = '-bit';
|
||||
|
||||
/**
|
||||
* Fixed tokens of the standalone `llama serve` command preview, so the command
|
||||
* builder and its rendered spans share one source of the CLI spelling.
|
||||
*/
|
||||
export const SERVE_COMMAND = {
|
||||
BIN: 'llama',
|
||||
/** Draft model repo:tag argument (download sidecar / draft weights). */
|
||||
DRAFT_FLAG: '-hfd',
|
||||
/** Main model repo:tag argument. */
|
||||
MODEL_FLAG: '-hf',
|
||||
/** Speculative-decoding type argument for the draft. */
|
||||
SPEC_TYPE_FLAG: '--spec-type',
|
||||
SUBCOMMAND: 'serve'
|
||||
} as const;
|
||||
|
||||
/** Bit depth preferred for the command's default base quant. */
|
||||
export const DEFAULT_BASE_BIT_DEPTH = 4;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user