@qvac/harness 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -1
- package/README.md +49 -0
- package/dist-lib/index.d.ts +31 -2
- package/dist-lib/index.js +365 -53
- package/dist-lib/lib/audio-transcode-bare.d.ts +1 -1
- package/dist-lib/lib/audio-transcode-bare.js +22 -25
- package/dist-lib/lib/audio-transcode-node.d.ts +1 -1
- package/dist-lib/lib/audio-transcode-node.js +1 -3
- package/dist-lib/lib/capabilities/audio-resample.d.ts +1 -1
- package/dist-lib/lib/capabilities/audio-resample.js +7 -8
- package/dist-lib/lib/capabilities/completion.d.ts +5 -2
- package/dist-lib/lib/capabilities/completion.js +22 -4
- package/dist-lib/lib/capabilities/download.d.ts +3 -1
- package/dist-lib/lib/capabilities/download.js +1 -1
- package/dist-lib/lib/capabilities/preview-model-source.d.ts +1 -0
- package/dist-lib/lib/capabilities/preview-model-source.js +1 -0
- package/dist-lib/lib/capabilities/usage-breakdown.js +4 -1
- package/dist-lib/lib/capabilities/voice.d.ts +5 -1
- package/dist-lib/lib/capabilities/voice.js +94 -26
- package/dist-lib/lib/connect.d.ts +4 -1
- package/dist-lib/lib/connect.js +14 -1
- package/dist-lib/lib/contract-types.d.ts +10 -0
- package/dist-lib/lib/models/download-gate.d.ts +20 -0
- package/dist-lib/lib/models/download-gate.js +73 -0
- package/dist-lib/lib/models/memory-cap.d.ts +13 -0
- package/dist-lib/lib/models/memory-cap.js +21 -0
- package/dist-lib/lib/models/model-catalog-constants.d.ts +3 -1
- package/dist-lib/lib/models/model-catalog-constants.js +9 -1
- package/dist-lib/lib/models/model-catalog.d.ts +6 -2
- package/dist-lib/lib/models/model-catalog.js +35 -3
- package/dist-lib/lib/models/model-handle.d.ts +8 -1
- package/dist-lib/lib/models/model-handle.js +20 -2
- package/dist-lib/lib/models/model-list.d.ts +8 -1
- package/dist-lib/lib/models/model-list.js +23 -0
- package/dist-lib/lib/models/model-pool.d.ts +33 -5
- package/dist-lib/lib/models/model-pool.js +97 -29
- package/dist-lib/lib/serve.js +18 -2
- package/dist-lib/lib/tools/generate-image.d.ts +4 -2
- package/dist-lib/lib/tools/generate-image.js +5 -2
- package/dist-lib/lib/tools/generate-music.d.ts +4 -2
- package/dist-lib/lib/tools/generate-music.js +5 -2
- package/dist-lib/lib/tools/translate.d.ts +3 -1
- package/dist-lib/lib/tools/translate.js +6 -1
- package/dist-lib/schema/harness.js +41 -3
- package/dist-lib/spec/bind.js +9 -0
- package/dist-lib/spec/calls.js +3 -0
- package/dist-lib/spec/hrpc/hrpc.json +39 -0
- package/dist-lib/spec/hrpc/index.js +39 -3
- package/dist-lib/spec/hrpc/messages.js +93 -10
- package/dist-lib/spec/hyperschema/index.js +93 -10
- package/dist-lib/spec/hyperschema/schema.json +57 -1
- package/dist-lib/spec/hyperschema/types.d.ts +19 -2
- package/package.json +4 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const VictimRank: {
|
|
2
|
+
readonly generator: 0;
|
|
3
|
+
readonly companion: 1;
|
|
4
|
+
readonly requested: 2;
|
|
5
|
+
readonly pinned: 3;
|
|
6
|
+
readonly replying: 4;
|
|
7
|
+
};
|
|
8
|
+
export interface CapVictim {
|
|
9
|
+
readonly rank: number;
|
|
10
|
+
readonly lastUsed: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function nextVictim<T extends CapVictim>(victims: ReadonlyArray<T>): T | undefined;
|
|
13
|
+
export declare function memoryCapBytes(percent: number, availableBytes: number): number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const VictimRank = {
|
|
2
|
+
generator: 0,
|
|
3
|
+
companion: 1,
|
|
4
|
+
requested: 2,
|
|
5
|
+
pinned: 3,
|
|
6
|
+
replying: 4
|
|
7
|
+
};
|
|
8
|
+
export function nextVictim(victims) {
|
|
9
|
+
let best;
|
|
10
|
+
for (const victim of victims) {
|
|
11
|
+
if (best === undefined ||
|
|
12
|
+
victim.rank < best.rank ||
|
|
13
|
+
(victim.rank === best.rank && victim.lastUsed < best.lastUsed)) {
|
|
14
|
+
best = victim;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return best;
|
|
18
|
+
}
|
|
19
|
+
export function memoryCapBytes(percent, availableBytes) {
|
|
20
|
+
return Math.round((Math.min(percent, 100) / 100) * availableBytes);
|
|
21
|
+
}
|
|
@@ -6,6 +6,8 @@ export declare const QWEN_35_9B = "Qwen3.5-9B-Q4_K_M";
|
|
|
6
6
|
export declare const QWEN_36_27B = "Qwen3.6-27B-UD-Q4_K_XL";
|
|
7
7
|
export declare const QWEN_36_35B_A3B = "Qwen3.6-35B-A3B-UD-Q4_K_M";
|
|
8
8
|
export declare const QWEN_38_27B = "Qwen3.8-27B-UD-Q4_K_XL";
|
|
9
|
+
export declare const BONSAI_2_27B_PQ2 = "Ternary-Bonsai-2-27B-PQ2_0";
|
|
10
|
+
export declare const BONSAI_2_27B_PTQ1 = "Ternary-Bonsai-2-27B-PTQ1_0";
|
|
9
11
|
export declare const MEDPSY_1_7B = "medpsy-1.7b-q4_k_m-imat";
|
|
10
12
|
export declare const MEDPSY_4B = "medpsy-4b-q4_k_m-imat";
|
|
11
13
|
export declare function isCapabilityProfile(value: string): value is CapabilityProfile;
|
|
@@ -19,7 +21,7 @@ export interface HostCapability {
|
|
|
19
21
|
export declare function isMobilePlatform(platform: string): boolean;
|
|
20
22
|
export declare function runnableModelName(requested: string, host: HostCapability | null): string;
|
|
21
23
|
export declare function capabilityProfileToModelName(profile: CapabilityProfile): string;
|
|
22
|
-
export declare const AGENT_MODEL_NAMES: readonly ["Qwen3.5-2B-Q4_K_M", "Qwen3.5-4B-Q4_K_M", "Qwen3.5-9B-Q4_K_M", "Qwen3.6-27B-UD-Q4_K_XL", "Qwen3.6-35B-A3B-UD-Q4_K_M", "Qwen3.8-27B-UD-Q4_K_XL", "medpsy-1.7b-q4_k_m-imat", "medpsy-4b-q4_k_m-imat"];
|
|
24
|
+
export declare const AGENT_MODEL_NAMES: readonly ["Qwen3.5-2B-Q4_K_M", "Qwen3.5-4B-Q4_K_M", "Qwen3.5-9B-Q4_K_M", "Qwen3.6-27B-UD-Q4_K_XL", "Qwen3.6-35B-A3B-UD-Q4_K_M", "Qwen3.8-27B-UD-Q4_K_XL", "Ternary-Bonsai-2-27B-PQ2_0", "Ternary-Bonsai-2-27B-PTQ1_0", "medpsy-1.7b-q4_k_m-imat", "medpsy-4b-q4_k_m-imat"];
|
|
23
25
|
export declare function modelDisplayName(modelName: string): string;
|
|
24
26
|
export declare function capabilityProfileModelLabel(profile: CapabilityProfile): string;
|
|
25
27
|
export declare function isMultimodalLlm(modelName: string): boolean;
|
|
@@ -11,6 +11,8 @@ export const QWEN_35_9B = 'Qwen3.5-9B-Q4_K_M';
|
|
|
11
11
|
export const QWEN_36_27B = 'Qwen3.6-27B-UD-Q4_K_XL';
|
|
12
12
|
export const QWEN_36_35B_A3B = 'Qwen3.6-35B-A3B-UD-Q4_K_M';
|
|
13
13
|
export const QWEN_38_27B = 'Qwen3.8-27B-UD-Q4_K_XL';
|
|
14
|
+
export const BONSAI_2_27B_PQ2 = 'Ternary-Bonsai-2-27B-PQ2_0';
|
|
15
|
+
export const BONSAI_2_27B_PTQ1 = 'Ternary-Bonsai-2-27B-PTQ1_0';
|
|
14
16
|
export const MEDPSY_1_7B = 'medpsy-1.7b-q4_k_m-imat';
|
|
15
17
|
export const MEDPSY_4B = 'medpsy-4b-q4_k_m-imat';
|
|
16
18
|
export function isCapabilityProfile(value) {
|
|
@@ -26,6 +28,8 @@ const MODEL_NAME_TO_PROFILE = new Map([
|
|
|
26
28
|
[QWEN_36_27B, 'xhigh'],
|
|
27
29
|
[QWEN_36_35B_A3B, 'xhigh'],
|
|
28
30
|
[QWEN_38_27B, 'xhigh'],
|
|
31
|
+
[BONSAI_2_27B_PQ2, 'high'],
|
|
32
|
+
[BONSAI_2_27B_PTQ1, 'high'],
|
|
29
33
|
[MEDPSY_1_7B, 'low'],
|
|
30
34
|
[MEDPSY_4B, 'mid']
|
|
31
35
|
]);
|
|
@@ -70,6 +74,8 @@ export const AGENT_MODEL_NAMES = [
|
|
|
70
74
|
QWEN_36_27B,
|
|
71
75
|
QWEN_36_35B_A3B,
|
|
72
76
|
QWEN_38_27B,
|
|
77
|
+
BONSAI_2_27B_PQ2,
|
|
78
|
+
BONSAI_2_27B_PTQ1,
|
|
73
79
|
MEDPSY_1_7B,
|
|
74
80
|
MEDPSY_4B
|
|
75
81
|
];
|
|
@@ -87,7 +93,9 @@ const MULTIMODAL_LLMS = new Set([
|
|
|
87
93
|
QWEN_35_9B,
|
|
88
94
|
QWEN_36_27B,
|
|
89
95
|
QWEN_36_35B_A3B,
|
|
90
|
-
QWEN_38_27B
|
|
96
|
+
QWEN_38_27B,
|
|
97
|
+
BONSAI_2_27B_PQ2,
|
|
98
|
+
BONSAI_2_27B_PTQ1
|
|
91
99
|
]);
|
|
92
100
|
export function isMultimodalLlm(modelName) {
|
|
93
101
|
return MULTIMODAL_LLMS.has(modelName);
|
|
@@ -6,8 +6,8 @@ import type { ModelAddon } from './model-source.ts';
|
|
|
6
6
|
export interface SdkModelAsset extends ModelRegistryEntry {
|
|
7
7
|
readonly src: string;
|
|
8
8
|
}
|
|
9
|
-
import { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName, type CapabilityProfile, type HostCapability, type ImageModelChoice, type ImageChoiceEntry } from './model-catalog-constants.ts';
|
|
10
|
-
export { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName };
|
|
9
|
+
import { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, BONSAI_2_27B_PQ2, BONSAI_2_27B_PTQ1, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName, type CapabilityProfile, type HostCapability, type ImageModelChoice, type ImageChoiceEntry } from './model-catalog-constants.ts';
|
|
10
|
+
export { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, BONSAI_2_27B_PQ2, BONSAI_2_27B_PTQ1, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName };
|
|
11
11
|
export type { CapabilityProfile, HostCapability, ImageModelChoice, ImageChoiceEntry };
|
|
12
12
|
export interface LlmCatalogEntry {
|
|
13
13
|
readonly name: string;
|
|
@@ -15,6 +15,7 @@ export interface LlmCatalogEntry {
|
|
|
15
15
|
readonly capabilityProfile: CapabilityProfile;
|
|
16
16
|
readonly projection?: SdkModelAsset;
|
|
17
17
|
readonly textOnly?: true;
|
|
18
|
+
readonly toolDialect?: ToolDialect;
|
|
18
19
|
}
|
|
19
20
|
export declare const LLM_CATALOG: ReadonlyArray<LlmCatalogEntry>;
|
|
20
21
|
export declare function defaultProjectionMap(): Record<string, string>;
|
|
@@ -52,6 +53,7 @@ export interface DiffusionDownloadMetadata {
|
|
|
52
53
|
}
|
|
53
54
|
export declare function diffusionDownloadName(model: string): string | null;
|
|
54
55
|
export declare function diffusionDownloadMetadata(model: string, addon: ModelAddon | undefined): DiffusionDownloadMetadata | undefined;
|
|
56
|
+
export declare function assetBytes(src: string): number | undefined;
|
|
55
57
|
import { DEFAULT_MUSIC_MODEL_CHOICE, isMusicModelChoice, musicModelChoiceFrom, type MusicModelChoice } from './music-catalog.ts';
|
|
56
58
|
export { DEFAULT_MUSIC_MODEL_CHOICE, isMusicModelChoice, musicModelChoiceFrom, type MusicModelChoice };
|
|
57
59
|
export interface AudioGenCatalogEntry {
|
|
@@ -108,6 +110,7 @@ export declare function curatedListables(): CuratedListable[];
|
|
|
108
110
|
export declare function curatedModelAsset(name: string, addon: ModelRegistryEntry['addon']): SdkModelAsset | undefined;
|
|
109
111
|
export declare function modelAddonOf(model: string): ModelRegistryEntry['addon'];
|
|
110
112
|
export declare function residentSrc(model: string, addon: ModelRegistryEntry['addon']): string;
|
|
113
|
+
export declare function catalogModelName(model: string, addon: ModelRegistryEntry['addon']): string;
|
|
111
114
|
export declare const CUSTOM_TASK_TYPES: readonly ['llm'];
|
|
112
115
|
export type CustomTaskType = (typeof CUSTOM_TASK_TYPES)[number];
|
|
113
116
|
export interface CustomModelEntry {
|
|
@@ -123,6 +126,7 @@ export declare function setCustomModels(entries: ReadonlyArray<CustomModelEntry>
|
|
|
123
126
|
export declare function customModels(): ReadonlyArray<CustomModelEntry>;
|
|
124
127
|
export declare function customContextLength(name: string): number | undefined;
|
|
125
128
|
export declare function customModelSrc(name: string, addon: ModelRegistryEntry['addon']): string | undefined;
|
|
129
|
+
export declare function toolDialectFor(name: string): ToolDialect | undefined;
|
|
126
130
|
export declare function customToolDialect(name: string): ToolDialect | undefined;
|
|
127
131
|
export declare function customProjectionMap(): Record<string, string>;
|
|
128
132
|
export declare function companionRegistryPaths(): Map<string, string[]>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AUDIOGEN_ACESTEP_5HZ_LM_0_6B_Q8_0, AUDIOGEN_ACESTEP_V15_SFT_Q8_0, AUDIOGEN_ACESTEP_V15_TURBO_Q4_K_M, AUDIOGEN_ACESTEP_V15_TURBO_Q8_0, AUDIOGEN_QWEN3_EMBEDDING_0_6B_Q8_0, AUDIOGEN_VAE_BF16, EMBEDDINGGEMMA_300M_Q4_0, FLUX_2_KLEIN_4B_Q4_0, FLUX_2_KLEIN_4B_VAE, HEALTHCARE_1_7B_MEDICAL_Q4_K_M, HEALTHCARE_4B_MEDICAL_Q4_K_M, MMPROJ_QWEN3_5_2B_MULTIMODAL_Q8_0, MMPROJ_QWEN3_5_4B_MULTIMODAL_Q8_0, MMPROJ_QWEN3_5_9B_MULTIMODAL_F16, MMPROJ_QWEN3_6_27B_MULTIMODAL_F16, MMPROJ_QWEN3_6_35B_A3B_MULTIMODAL_F16, MMPROJ_QWEN3_8_27B_MULTIMODAL_F16, QWEN3_5_2B_MULTIMODAL_Q4_K_M, QWEN3_5_4B_MULTIMODAL_Q4_K_M, QWEN3_5_9B_MULTIMODAL_Q4_K_M, PARAKEET_TDT_0_6B_V3_Q8_0, QWEN3_4B_Q4_K_M, QWEN3_6_27B_MULTIMODAL_Q4_K_XL, QWEN3_6_35B_A3B_MULTIMODAL_Q4_K_M, QWEN3_8_27B_MULTIMODAL_UD_Q4_K_XL, SD_V2_1_1B_Q8_0, SDXL_BASE_1_0_3B_Q4_0, TTS_MULTILINGUAL_SUPERTONIC3_FP16, TTS_MULTILINGUAL_SUPERTONIC3_Q4_0, TTS_MULTILINGUAL_SUPERTONIC3_Q8_0 } from '@qvac/sdk/models';
|
|
1
|
+
import { AUDIOGEN_ACESTEP_5HZ_LM_0_6B_Q8_0, AUDIOGEN_ACESTEP_V15_SFT_Q8_0, AUDIOGEN_ACESTEP_V15_TURBO_Q4_K_M, AUDIOGEN_ACESTEP_V15_TURBO_Q8_0, AUDIOGEN_QWEN3_EMBEDDING_0_6B_Q8_0, AUDIOGEN_VAE_BF16, EMBEDDINGGEMMA_300M_Q4_0, FLUX_2_KLEIN_4B_Q4_0, FLUX_2_KLEIN_4B_VAE, HEALTHCARE_1_7B_MEDICAL_Q4_K_M, HEALTHCARE_4B_MEDICAL_Q4_K_M, MMPROJ_QWEN3_5_2B_MULTIMODAL_Q8_0, MMPROJ_QWEN3_5_4B_MULTIMODAL_Q8_0, MMPROJ_QWEN3_5_9B_MULTIMODAL_F16, MMPROJ_QWEN3_6_27B_MULTIMODAL_F16, MMPROJ_QWEN3_6_35B_A3B_MULTIMODAL_F16, MMPROJ_QWEN3_8_27B_MULTIMODAL_F16, MMPROJ_TERNARY_BONSAI_2_27B_MULTIMODAL_Q8_0, QWEN3_5_2B_MULTIMODAL_Q4_K_M, QWEN3_5_4B_MULTIMODAL_Q4_K_M, QWEN3_5_9B_MULTIMODAL_Q4_K_M, PARAKEET_TDT_0_6B_V3_Q8_0, QWEN3_4B_Q4_K_M, QWEN3_6_27B_MULTIMODAL_Q4_K_XL, QWEN3_6_35B_A3B_MULTIMODAL_Q4_K_M, QWEN3_8_27B_MULTIMODAL_UD_Q4_K_XL, SD_V2_1_1B_Q8_0, SDXL_BASE_1_0_3B_Q4_0, TERNARY_BONSAI_2_27B_MULTIMODAL_PQ2_0, TERNARY_BONSAI_2_27B_MULTIMODAL_PTQ1_0, TTS_MULTILINGUAL_SUPERTONIC3_FP16, TTS_MULTILINGUAL_SUPERTONIC3_Q4_0, TTS_MULTILINGUAL_SUPERTONIC3_Q8_0 } from '@qvac/sdk/models';
|
|
2
2
|
import { detectToolDialect } from './tool-dialect.js';
|
|
3
3
|
import { defaultTtsModelName } from './tts-model-default.js';
|
|
4
|
-
import { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName } from './model-catalog-constants.js';
|
|
5
|
-
export { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName };
|
|
4
|
+
import { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, BONSAI_2_27B_PQ2, BONSAI_2_27B_PTQ1, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName } from './model-catalog-constants.js';
|
|
5
|
+
export { CAPABILITY_PROFILE_ORDER, QWEN_35_2B, QWEN_35_4B, QWEN_35_9B, QWEN_36_27B, QWEN_36_35B_A3B, QWEN_38_27B, BONSAI_2_27B_PQ2, BONSAI_2_27B_PTQ1, MEDPSY_1_7B, MEDPSY_4B, isCapabilityProfile, meetsMinCapabilityProfile, modelNameToCapabilityProfile, capabilityProfileToModelName, isMultimodalLlm, AGENT_MODEL_NAMES, modelDisplayName, capabilityProfileModelLabel, DEFAULT_IMAGE_MODEL_CHOICE, IMAGE_CHOICE_CATALOG, isMobilePlatform, runnableModelName };
|
|
6
6
|
export const LLM_CATALOG = [
|
|
7
7
|
{
|
|
8
8
|
name: QWEN_35_2B,
|
|
@@ -51,6 +51,20 @@ export const LLM_CATALOG = [
|
|
|
51
51
|
weight: QWEN3_8_27B_MULTIMODAL_UD_Q4_K_XL,
|
|
52
52
|
capabilityProfile: 'xhigh',
|
|
53
53
|
projection: MMPROJ_QWEN3_8_27B_MULTIMODAL_F16
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: BONSAI_2_27B_PQ2,
|
|
57
|
+
weight: TERNARY_BONSAI_2_27B_MULTIMODAL_PQ2_0,
|
|
58
|
+
capabilityProfile: 'high',
|
|
59
|
+
projection: MMPROJ_TERNARY_BONSAI_2_27B_MULTIMODAL_Q8_0,
|
|
60
|
+
toolDialect: 'qwen35'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: BONSAI_2_27B_PTQ1,
|
|
64
|
+
weight: TERNARY_BONSAI_2_27B_MULTIMODAL_PTQ1_0,
|
|
65
|
+
capabilityProfile: 'high',
|
|
66
|
+
projection: MMPROJ_TERNARY_BONSAI_2_27B_MULTIMODAL_Q8_0,
|
|
67
|
+
toolDialect: 'qwen35'
|
|
54
68
|
}
|
|
55
69
|
];
|
|
56
70
|
export function defaultProjectionMap() {
|
|
@@ -181,6 +195,16 @@ export function diffusionDownloadMetadata(model, addon) {
|
|
|
181
195
|
assetSizes
|
|
182
196
|
};
|
|
183
197
|
}
|
|
198
|
+
export function assetBytes(src) {
|
|
199
|
+
const assets = [
|
|
200
|
+
...curatedListables().map((entry) => entry.asset),
|
|
201
|
+
...LLM_CATALOG.flatMap((entry) => (entry.projection ? [entry.projection] : [])),
|
|
202
|
+
...DIFFUSION_CATALOG.flatMap(diffusionAssets),
|
|
203
|
+
...AUDIOGEN_CATALOG.flatMap((entry) => [entry.dit, entry.textEnc, entry.lm, entry.vae])
|
|
204
|
+
];
|
|
205
|
+
const custom = customModels().find((entry) => entry.src === src);
|
|
206
|
+
return assets.find((asset) => asset.src === src)?.expectedSize ?? custom?.expectedSize;
|
|
207
|
+
}
|
|
184
208
|
import { DEFAULT_MUSIC_MODEL_CHOICE, isMusicModelChoice, musicModelChoiceFrom } from './music-catalog.js';
|
|
185
209
|
export { DEFAULT_MUSIC_MODEL_CHOICE, isMusicModelChoice, musicModelChoiceFrom };
|
|
186
210
|
const MUSIC_GENERATION_SKILL = 'music-generation';
|
|
@@ -363,6 +387,11 @@ export function modelAddonOf(model) {
|
|
|
363
387
|
export function residentSrc(model, addon) {
|
|
364
388
|
return curatedModelAsset(model, addon)?.src ?? model;
|
|
365
389
|
}
|
|
390
|
+
export function catalogModelName(model, addon) {
|
|
391
|
+
const known = curatedListables().find((entry) => entry.asset.addon === addon &&
|
|
392
|
+
(entry.name === model || entry.asset.name === model || entry.asset.src === model));
|
|
393
|
+
return known?.name ?? model;
|
|
394
|
+
}
|
|
366
395
|
export const CUSTOM_TASK_TYPES = ['llm'];
|
|
367
396
|
let CUSTOM_MODELS = new Map();
|
|
368
397
|
export function setCustomModels(entries) {
|
|
@@ -378,6 +407,9 @@ export function customModelSrc(name, addon) {
|
|
|
378
407
|
const entry = CUSTOM_MODELS.get(name);
|
|
379
408
|
return entry && (entry.taskType ?? 'llm') === addon ? entry.src : undefined;
|
|
380
409
|
}
|
|
410
|
+
export function toolDialectFor(name) {
|
|
411
|
+
return LLM_CATALOG.find((entry) => entry.name === name)?.toolDialect ?? customToolDialect(name);
|
|
412
|
+
}
|
|
381
413
|
export function customToolDialect(name) {
|
|
382
414
|
const entry = CUSTOM_MODELS.get(name);
|
|
383
415
|
return entry
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { type AbortSignal } from 'bare-abort-controller';
|
|
1
2
|
export interface ModelResource {
|
|
2
3
|
model: string;
|
|
3
4
|
modelId: string;
|
|
4
5
|
ctxSize?: number;
|
|
6
|
+
bytes?: number;
|
|
5
7
|
}
|
|
6
8
|
export interface ModelHandleOptions {
|
|
7
|
-
load(): Promise<ModelResource>;
|
|
9
|
+
load(signal: AbortSignal): Promise<ModelResource>;
|
|
8
10
|
onLoaded?(): void;
|
|
9
11
|
onFailed?(err: unknown): void;
|
|
10
12
|
}
|
|
@@ -15,8 +17,13 @@ export declare class ModelHandle {
|
|
|
15
17
|
private readonly _onFailed;
|
|
16
18
|
private _tracked;
|
|
17
19
|
private _loading;
|
|
20
|
+
private _resource;
|
|
21
|
+
lastUsed: number;
|
|
22
|
+
private _attempt;
|
|
18
23
|
constructor({ load, onLoaded, onFailed }: ModelHandleOptions);
|
|
19
24
|
load(): Promise<ModelResource>;
|
|
20
25
|
get loading(): boolean;
|
|
26
|
+
abandon(): void;
|
|
21
27
|
peek(): Promise<ModelResource> | null;
|
|
28
|
+
get resource(): ModelResource | null;
|
|
22
29
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AbortController } from 'bare-abort-controller';
|
|
2
|
+
import { AbortedError } from '../helpers/race-abort.js';
|
|
1
3
|
import { retryMemo } from '../helpers/retry-memo.js';
|
|
2
4
|
export class ModelHandle {
|
|
3
5
|
_load;
|
|
@@ -6,8 +8,15 @@ export class ModelHandle {
|
|
|
6
8
|
_onFailed;
|
|
7
9
|
_tracked = null;
|
|
8
10
|
_loading = false;
|
|
11
|
+
_resource = null;
|
|
12
|
+
lastUsed = 0;
|
|
13
|
+
_attempt = null;
|
|
9
14
|
constructor({ load, onLoaded, onFailed }) {
|
|
10
|
-
const memo = retryMemo(
|
|
15
|
+
const memo = retryMemo(() => {
|
|
16
|
+
const attempt = new AbortController();
|
|
17
|
+
this._attempt = attempt;
|
|
18
|
+
return load(attempt.signal);
|
|
19
|
+
});
|
|
11
20
|
this._load = memo;
|
|
12
21
|
this._peek = memo.peek;
|
|
13
22
|
this._onLoaded = onLoaded;
|
|
@@ -25,15 +34,24 @@ export class ModelHandle {
|
|
|
25
34
|
report();
|
|
26
35
|
}
|
|
27
36
|
};
|
|
28
|
-
attempt.then(() => settle(() =>
|
|
37
|
+
attempt.then((resource) => settle(() => {
|
|
38
|
+
this._resource = resource;
|
|
39
|
+
this._onLoaded?.();
|
|
40
|
+
}), (err) => settle(() => this._onFailed?.(err)));
|
|
29
41
|
}
|
|
30
42
|
return attempt;
|
|
31
43
|
}
|
|
32
44
|
get loading() {
|
|
33
45
|
return this._loading;
|
|
34
46
|
}
|
|
47
|
+
abandon() {
|
|
48
|
+
this._attempt?.abort(new AbortedError());
|
|
49
|
+
}
|
|
35
50
|
peek() {
|
|
36
51
|
return this._peek();
|
|
37
52
|
}
|
|
53
|
+
get resource() {
|
|
54
|
+
return this._loading ? null : this._resource;
|
|
55
|
+
}
|
|
38
56
|
}
|
|
39
57
|
function noop() { }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as QvacSdk from '@qvac/sdk';
|
|
2
|
-
import type
|
|
2
|
+
import { type ModelAddon, type ModelRegistrySdk } from './model-source.ts';
|
|
3
3
|
import { type ModelTaskType } from './model-task.ts';
|
|
4
4
|
export type ModelType = ModelAddon;
|
|
5
5
|
export interface StaticCatalogEntry {
|
|
@@ -22,6 +22,7 @@ export interface ModelInfo {
|
|
|
22
22
|
actualSize?: number;
|
|
23
23
|
label?: string;
|
|
24
24
|
taskType: ModelTaskType;
|
|
25
|
+
memoryBytes?: number | undefined;
|
|
25
26
|
}
|
|
26
27
|
export type CatalogRow = Omit<ModelInfo, 'isLoading'>;
|
|
27
28
|
export interface ListModelsOptions {
|
|
@@ -54,4 +55,10 @@ export interface CustomModelRowsContext {
|
|
|
54
55
|
}
|
|
55
56
|
export declare function customModelRows({ type, cachedOnly }: ListModelsOptions, { modelsDir, loaded }: CustomModelRowsContext): Promise<CatalogRow[]>;
|
|
56
57
|
export declare function mergeCustomRows(catalog: ReadonlyArray<CatalogRow>, custom: ReadonlyArray<CatalogRow>): CatalogRow[];
|
|
58
|
+
export interface ModelSourceQuery {
|
|
59
|
+
readonly model: string;
|
|
60
|
+
readonly addon: ModelAddon;
|
|
61
|
+
readonly modelsDir: string | undefined;
|
|
62
|
+
}
|
|
63
|
+
export declare function isModelSourceCached(sdk: ModelListSdk, { model, addon, modelsDir }: ModelSourceQuery): Promise<boolean>;
|
|
57
64
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveModelSrc } from './model-source.js';
|
|
1
2
|
import { addonTaskType } from './model-task.js';
|
|
2
3
|
import { isCustomModelCached } from './custom-model-cache.js';
|
|
3
4
|
import { companionRegistryPaths, curatedListables, customModels, musicListables } from './model-catalog.js';
|
|
@@ -153,3 +154,25 @@ export function mergeCustomRows(catalog, custom) {
|
|
|
153
154
|
const shadowed = new Set(custom.map((row) => row.name));
|
|
154
155
|
return [...catalog.filter((row) => !shadowed.has(row.name)), ...custom];
|
|
155
156
|
}
|
|
157
|
+
export async function isModelSourceCached(sdk, { model, addon, modelsDir }) {
|
|
158
|
+
const src = await resolveModelSrc(sdk, model, addon).catch(() => null);
|
|
159
|
+
if (src === null) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const name = registryCatalogName(sdk, src);
|
|
163
|
+
if (name === undefined) {
|
|
164
|
+
return typeof src === 'string' && isCustomModelCached({ name: model, src }, modelsDir);
|
|
165
|
+
}
|
|
166
|
+
const info = await sdk.getModelInfo({ name }).catch(() => null);
|
|
167
|
+
return info?.isCached ?? false;
|
|
168
|
+
}
|
|
169
|
+
function registryCatalogName(sdk, src) {
|
|
170
|
+
if (typeof src !== 'string') {
|
|
171
|
+
return sdk.models.find((entry) => entry.registryPath === src.registryPath)?.name ?? src.name;
|
|
172
|
+
}
|
|
173
|
+
const registryPath = /^registry:\/\/[^/]+\/(.+)$/.exec(src)?.[1];
|
|
174
|
+
if (registryPath === undefined) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
return sdk.models.find((entry) => entry.registryPath === registryPath)?.name;
|
|
178
|
+
}
|
|
@@ -3,14 +3,28 @@ import { ModelHandle } from './model-handle.ts';
|
|
|
3
3
|
import { type ModelSrc } from './context.ts';
|
|
4
4
|
import { type ModelAddon } from './model-source.ts';
|
|
5
5
|
import type { GpuFaultState } from './sdk-faults.ts';
|
|
6
|
+
import type { HoldFn } from './download-gate.ts';
|
|
6
7
|
type SdkModule = typeof import('@qvac/sdk');
|
|
8
|
+
type FitModelType = NonNullable<import('@qvac/sdk').AssessModelFitInput['models'][number]['modelType']>;
|
|
7
9
|
export interface ModelState {
|
|
8
|
-
status: 'loading' | 'downloading' | 'downloaded' | 'ready' | 'error' | 'unloading' | 'unloaded';
|
|
10
|
+
status: 'held' | 'loading' | 'downloading' | 'downloaded' | 'ready' | 'error' | 'unloading' | 'unloaded';
|
|
9
11
|
model: string;
|
|
10
12
|
catalogChanged?: boolean;
|
|
11
13
|
[key: string]: unknown;
|
|
12
14
|
}
|
|
13
15
|
export type NotifyFn = (state: ModelState) => void;
|
|
16
|
+
export interface PendingLoad {
|
|
17
|
+
readonly key: string;
|
|
18
|
+
readonly model: string;
|
|
19
|
+
readonly modelSrc: ModelSrc;
|
|
20
|
+
readonly modelType: FitModelType;
|
|
21
|
+
readonly modelConfig?: Record<string, unknown> | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface Admission {
|
|
24
|
+
readonly bytes: number | undefined;
|
|
25
|
+
release(): void;
|
|
26
|
+
}
|
|
27
|
+
export type BeforeLoad = (load: PendingLoad) => Promise<Admission | undefined>;
|
|
14
28
|
export interface LlmDeviceConfig {
|
|
15
29
|
device?: 'cpu' | 'gpu';
|
|
16
30
|
gpuLayers?: number;
|
|
@@ -80,6 +94,13 @@ export declare function modelOf(key: string): string;
|
|
|
80
94
|
export declare function releaseModel(pool: PoolLike, key: string): void;
|
|
81
95
|
export declare function loadedModels(pool: PoolLike): LoadedModel[];
|
|
82
96
|
export declare function settledModels(pool: PoolLike): string[];
|
|
97
|
+
export interface SettledEntry {
|
|
98
|
+
readonly key: string;
|
|
99
|
+
readonly refs: number;
|
|
100
|
+
readonly bytes: number | undefined;
|
|
101
|
+
readonly lastUsed: number;
|
|
102
|
+
}
|
|
103
|
+
export declare function settledEntries(pool: PoolLike): SettledEntry[];
|
|
83
104
|
export declare function loadingModels(pool: PoolLike): string[];
|
|
84
105
|
export interface ResidentLease {
|
|
85
106
|
model: string;
|
|
@@ -104,6 +125,7 @@ export interface ModelCapacityOptions extends DeadlineOptions {
|
|
|
104
125
|
}
|
|
105
126
|
export declare function awaitModelCapacity(pool: PoolLike, { cap, deadlineMs, tickMs, signal, evictable }: ModelCapacityOptions): Promise<boolean>;
|
|
106
127
|
export declare function evictModelWithin(pool: PoolLike, key: string, options: DeadlineOptions): Promise<boolean>;
|
|
128
|
+
export declare function evictIdleWithin(pool: PoolLike, key: string, { deadlineMs }: DeadlineOptions): Promise<boolean>;
|
|
107
129
|
export declare function evictModel(pool: PoolLike, model: string, options: DeadlineOptions): Promise<boolean>;
|
|
108
130
|
export type LoadSdk = () => Promise<ModelLifecycleSdk>;
|
|
109
131
|
export type EmbedLifecycleSdk = Pick<SdkModule, 'unloadModel' | 'modelRegistrySearch'> & Partial<CancelSdk> & {
|
|
@@ -134,15 +156,19 @@ export declare function loadClockGuard(model: string, sdk: Partial<CancelSdk>, {
|
|
|
134
156
|
export interface ModelPoolOptions {
|
|
135
157
|
deviceConfig?: LlmDeviceConfig;
|
|
136
158
|
loads?: LoadTracker;
|
|
159
|
+
beforeLoad?: BeforeLoad;
|
|
160
|
+
hold?: HoldFn;
|
|
137
161
|
}
|
|
138
|
-
export declare function createModelPool(loadSdk: LoadSdk, notify: NotifyFn, { deviceConfig, loads }?: ModelPoolOptions): ModelPuddle;
|
|
162
|
+
export declare function createModelPool(loadSdk: LoadSdk, notify: NotifyFn, { deviceConfig, loads, beforeLoad, hold }?: ModelPoolOptions): ModelPuddle;
|
|
139
163
|
export interface EmbedPoolOptions {
|
|
140
164
|
faults: GpuFaultState;
|
|
141
165
|
batchSize?: number;
|
|
142
166
|
openclCacheDir?: (() => string | undefined) | undefined;
|
|
143
167
|
loads?: LoadTracker;
|
|
168
|
+
beforeLoad?: BeforeLoad;
|
|
169
|
+
hold?: HoldFn;
|
|
144
170
|
}
|
|
145
|
-
export declare function createEmbedPool(loadSdk: LoadEmbedSdk, notify: NotifyFn, { faults, batchSize, openclCacheDir, loads }: EmbedPoolOptions): ModelPuddle;
|
|
171
|
+
export declare function createEmbedPool(loadSdk: LoadEmbedSdk, notify: NotifyFn, { faults, batchSize, openclCacheDir, loads, beforeLoad, hold }: EmbedPoolOptions): ModelPuddle;
|
|
146
172
|
export type VoiceLifecycleSdk = Pick<SdkModule, 'unloadModel' | 'modelRegistrySearch'> & Partial<CancelSdk> & {
|
|
147
173
|
loadModel(params: {
|
|
148
174
|
modelSrc: ModelSrc;
|
|
@@ -153,12 +179,14 @@ export type VoiceLifecycleSdk = Pick<SdkModule, 'unloadModel' | 'modelRegistrySe
|
|
|
153
179
|
};
|
|
154
180
|
export type LoadVoiceSdk = () => Promise<VoiceLifecycleSdk>;
|
|
155
181
|
export interface VoicePoolOptions {
|
|
156
|
-
modelType:
|
|
182
|
+
modelType: FitModelType;
|
|
157
183
|
addon: ModelAddon;
|
|
158
184
|
modelConfig?: Record<string, unknown> | undefined;
|
|
159
185
|
modelConfigFor?: (modelSrc: ModelSrc) => Readonly<Record<string, unknown>> | undefined;
|
|
160
186
|
openclCacheDir?: (() => string | undefined) | undefined;
|
|
161
187
|
loads?: LoadTracker;
|
|
188
|
+
beforeLoad?: BeforeLoad;
|
|
189
|
+
hold?: HoldFn;
|
|
162
190
|
}
|
|
163
|
-
export declare function createVoicePool(loadSdk: LoadVoiceSdk, notify: NotifyFn, { modelType, addon, modelConfig, modelConfigFor, openclCacheDir, loads }: VoicePoolOptions): ModelPuddle;
|
|
191
|
+
export declare function createVoicePool(loadSdk: LoadVoiceSdk, notify: NotifyFn, { modelType, addon, modelConfig, modelConfigFor, openclCacheDir, loads, beforeLoad, hold }: VoicePoolOptions): ModelPuddle;
|
|
164
192
|
export {};
|