@qvac/sdk 0.2.1 → 0.2.3-dev.1760899404.f30d071
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/README.md +3 -4
- package/dist/examples/llamacpp-multimodal.js +3 -3
- package/dist/examples/rag/rag-hyperdb-workspaces.js +1 -2
- package/dist/models/hyperdrive/models.d.ts +1 -49
- package/dist/models/hyperdrive/models.js +54 -105
- package/dist/schemas/common.d.ts +0 -1
- package/dist/schemas/rag.d.ts +0 -3
- package/dist/schemas/rag.js +1 -3
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +2 -28
- package/dist/server/bare/registry/model-registry.d.ts +0 -1
- package/dist/server/rpc/handlers/completion-stream.js +45 -31
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +19 -0
- package/dist/server/rpc/handlers/load-model/download-manager.js +25 -10
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +80 -121
- package/dist/server/rpc/handlers/load-model/resolve.js +55 -8
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ npm i expo-file-system react-native-bare-kit
|
|
|
79
79
|
```js
|
|
80
80
|
export default {
|
|
81
81
|
expo: {
|
|
82
|
-
plugins: ["
|
|
82
|
+
plugins: ["qvac-sdk/expo-plugin"],
|
|
83
83
|
},
|
|
84
84
|
};
|
|
85
85
|
```
|
|
@@ -141,7 +141,6 @@ const cachedResponse = completion({
|
|
|
141
141
|
|
|
142
142
|
// Unload model to free up system resources
|
|
143
143
|
await unloadModel({ modelId });
|
|
144
|
-
process.exit();
|
|
145
144
|
```
|
|
146
145
|
|
|
147
146
|
**For more on how to use QVAC SDK, see [SDK at QVAC documentation](https://tether-2.gitbook.io/qvac-by-tether-or-reference/y2AsIh94H9DJ1pIBCNj9/sdk)**.
|
|
@@ -162,10 +161,10 @@ bun run build # or `watch` for hotreload
|
|
|
162
161
|
bun run build:pack
|
|
163
162
|
```
|
|
164
163
|
|
|
165
|
-
This outputs a tarball under `dist/qvac-sdk-{version}.tgz` that you can install in your project, e.g.:
|
|
164
|
+
This outputs a tarball under `dist/tetherto-qvac-sdk-{version}.tgz` that you can install in your project, e.g.:
|
|
166
165
|
|
|
167
166
|
```bash
|
|
168
|
-
npm i path/to/qvac-sdk-0.1.
|
|
167
|
+
npm i path/to/tetherto-qvac-sdk-0.0.1.tgz
|
|
169
168
|
```
|
|
170
169
|
|
|
171
170
|
## Examples
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { completion, loadModel,
|
|
1
|
+
import { completion, loadModel, unloadModel } from "@qvac/sdk";
|
|
2
2
|
if (process.argv.length < 3) {
|
|
3
3
|
console.error(`Specify an image file path as the first argument and a second image file path as the second (optional) argument`);
|
|
4
4
|
process.exit(1);
|
|
@@ -8,9 +8,9 @@ try {
|
|
|
8
8
|
const imageFilePath = process.argv[2];
|
|
9
9
|
// Load the main model with projection in a single step
|
|
10
10
|
const modelId = await loadModel({
|
|
11
|
-
modelSrc:
|
|
11
|
+
modelSrc: "https://huggingface.co/ggml-org/SmolVLM2-500M-Video-Instruct-GGUF/resolve/main/SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
|
|
12
12
|
modelType: "llm",
|
|
13
|
-
projectionModelSrc:
|
|
13
|
+
projectionModelSrc: "https://huggingface.co/ggml-org/SmolVLM2-500M-Video-Instruct-GGUF/resolve/main/mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
|
|
14
14
|
modelConfig: {
|
|
15
15
|
ctx_size: 1024,
|
|
16
16
|
},
|
|
@@ -41,10 +41,9 @@ try {
|
|
|
41
41
|
documents: medicalArticle,
|
|
42
42
|
chunk: true,
|
|
43
43
|
chunkOpts: {
|
|
44
|
-
chunkSize:
|
|
44
|
+
chunkSize: 30,
|
|
45
45
|
chunkOverlap: 10,
|
|
46
46
|
chunkStrategy: "paragraph",
|
|
47
|
-
splitStrategy: "token",
|
|
48
47
|
},
|
|
49
48
|
});
|
|
50
49
|
console.log(`✅ Created ${medicalResult.processed.length} chunks from medical article`);
|
|
@@ -62,20 +62,6 @@ export declare const models: readonly [{
|
|
|
62
62
|
readonly addon: "llm";
|
|
63
63
|
readonly expectedSize: 1056782912;
|
|
64
64
|
readonly sha256Checksum: "c876f159707a4e4f70e045106c69db15bfc935a4981706fd4f65c6e7ea1e81c5";
|
|
65
|
-
}, {
|
|
66
|
-
readonly hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31";
|
|
67
|
-
readonly hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0";
|
|
68
|
-
readonly modelId: "Qwen2.5-Omni-3B-Q4_K_M.gguf";
|
|
69
|
-
readonly addon: "llm";
|
|
70
|
-
readonly expectedSize: 2104931648;
|
|
71
|
-
readonly sha256Checksum: "4b0bd358c1e9ec55dd3055ef6d71c958c821533d85916a10cfa89c4552a86e29";
|
|
72
|
-
}, {
|
|
73
|
-
readonly hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31";
|
|
74
|
-
readonly hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0";
|
|
75
|
-
readonly modelId: "mmproj-Qwen2.5-Omni-3B-Q8_0.gguf";
|
|
76
|
-
readonly addon: "llm";
|
|
77
|
-
readonly expectedSize: 1538031328;
|
|
78
|
-
readonly sha256Checksum: "4e6c816cd33f7298d07cb780c136a396631e50e62f6501660271f8c6e302e565";
|
|
79
65
|
}, {
|
|
80
66
|
readonly hyperdriveKey: "d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578";
|
|
81
67
|
readonly hyperbeeKey: "generation:qwen3:instruct::0.6B::1.0.0";
|
|
@@ -111,34 +97,6 @@ export declare const models: readonly [{
|
|
|
111
97
|
readonly addon: "llm";
|
|
112
98
|
readonly expectedSize: 2401075552;
|
|
113
99
|
readonly sha256Checksum: "9cfebb63cd7e6b6d1755ea8ef001fcdadfa17831da1db96eafe3fc554913d5e1";
|
|
114
|
-
}, {
|
|
115
|
-
readonly hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f";
|
|
116
|
-
readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct";
|
|
117
|
-
readonly modelId: "SmolVLM2-500M-Video-Instruct-f16.gguf";
|
|
118
|
-
readonly addon: "llm";
|
|
119
|
-
readonly expectedSize: 820424704;
|
|
120
|
-
readonly sha256Checksum: "80f7e3f04bc2d3324ac1a9f52f5776fe13a69912adf74f8e7edacf773d140d77";
|
|
121
|
-
}, {
|
|
122
|
-
readonly hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f";
|
|
123
|
-
readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct";
|
|
124
|
-
readonly modelId: "mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf";
|
|
125
|
-
readonly addon: "llm";
|
|
126
|
-
readonly expectedSize: 199470624;
|
|
127
|
-
readonly sha256Checksum: "b5dc8ebe7cbeab66a5369693960a52515d7824f13d4063ceca78431f2a6b59b0";
|
|
128
|
-
}, {
|
|
129
|
-
readonly hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576";
|
|
130
|
-
readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct";
|
|
131
|
-
readonly modelId: "SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
|
|
132
|
-
readonly addon: "llm";
|
|
133
|
-
readonly expectedSize: 436808704;
|
|
134
|
-
readonly sha256Checksum: "6f67b8036b2469fcd71728702720c6b51aebd759b78137a8120733b4d66438bc";
|
|
135
|
-
}, {
|
|
136
|
-
readonly hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576";
|
|
137
|
-
readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct";
|
|
138
|
-
readonly modelId: "mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
|
|
139
|
-
readonly addon: "llm";
|
|
140
|
-
readonly expectedSize: 108785184;
|
|
141
|
-
readonly sha256Checksum: "921dc7e259f308e5b027111fa185efcbf33db13f6e35749ddf7f5cdb60ef520b";
|
|
142
100
|
}, {
|
|
143
101
|
readonly hyperdriveKey: "268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7";
|
|
144
102
|
readonly hyperbeeKey: "translation:ggml-indictrans:dist:2:200M:q0f32:1.0.0:en-hi";
|
|
@@ -463,17 +421,11 @@ export declare const GTE_LARGE_FP16: "pear://d1896d9259692818df95bd2480e90c2d057
|
|
|
463
421
|
export declare const LASER_DOLPHIN_2_6_2X7B_INST_Q2_K: "pear://bd40e4bfae48b5bf436d1b0b447ae26e4c384aebe101a5e7df6ae71c919dadf1/dolphin-mixtral-2x7b-dop-Q2_K.gguf";
|
|
464
422
|
export declare const LLAMA_3_2_1B_INST_Q4_0: "pear://afa79ee07c0a138bb9f11bfaee771fb1bdfca8c82d961cff0474e49827bd1de3/Llama-3.2-1B-Instruct-Q4_0.gguf";
|
|
465
423
|
export declare const QWEN_3_1_7B_INST_Q4: "pear://05d3d7ad9cd650f53c28f85e312ef09a645dd487845897958b3be8a19cb3aab9/Qwen3-1.7B-Q4_0.gguf";
|
|
466
|
-
export declare const QWEN2_5_OMNI_3B_MULTIMODAL: "pear://583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31/Qwen2.5-Omni-3B-Q4_K_M.gguf";
|
|
467
|
-
export declare const MMPROJ_QWEN2_5_OMNI_3B_MULTIMODAL: "pear://583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31/mmproj-Qwen2.5-Omni-3B-Q8_0.gguf";
|
|
468
424
|
export declare const QWEN3_0_6B_INST: "pear://d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578/Qwen3-0.6B-UD-IQ1_S.gguf";
|
|
469
425
|
export declare const QWEN3_4B_INST_Q4: "pear://19ffb75463149955ee24d786dfddd84d41fc872ea813cd4465f5f7299d165adc/model.gguf";
|
|
470
426
|
export declare const QWEN3_600M_INST_Q4: "pear://211874c9885f6b88b9926904420e365f5e74e1b6ac47207b7536408539bef4b7/Qwen3-0.6B-Q4_0.gguf";
|
|
471
427
|
export declare const SALAMANDRATA_2B_INST_Q4: "pear://1610d81772a9e7c37660666dbdfdcef915b6b83c522ea1ad31c19cab0075811d/salamandrata_2b_inst_q4.gguf";
|
|
472
428
|
export declare const SALAMANDRATA_2B_INST_Q8: "pear://96860337b0bdffdbb8ef0df4c8b2c3ab5e78568f5f7e15815a0a6b392512c9b5/salamandrata_2b_inst_q8.gguf";
|
|
473
|
-
export declare const SMOLVLM2_2_500M_MULTIMODAL_F16: "pear://b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f/SmolVLM2-500M-Video-Instruct-f16.gguf";
|
|
474
|
-
export declare const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_F16: "pear://b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f/mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf";
|
|
475
|
-
export declare const SMOLVLM2_2_500M_MULTIMODAL_Q8_0: "pear://73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576/SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
|
|
476
|
-
export declare const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0: "pear://73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576/mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
|
|
477
429
|
export declare const MARIAN_EN_HI_INDIC_200M_Q0F32: "pear://268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7/ggml-indictrans2-en-indic-dist-200M.bin";
|
|
478
430
|
export declare const MARIAN_HI_EN_INDIC_200M_Q0F32: "pear://dfea395ffe1cb6d259029e5c81c290f8828981987855e23e7b66fd7c705901eb/ggml-indictrans2-indic-en-dist-200M.bin";
|
|
479
431
|
export declare const MARIAN_HI_HI_INDIC_320M_Q0F32: "pear://9a66da960931c449b41e3315d9aea4d3925f2cda024e8a4c139b64d0a539ed41/ggml-indictrans2-indic-indic-dist-320M.bin";
|
|
@@ -519,5 +471,5 @@ export declare const WHISPER_LARGE_3: "pear://76fb36d7f16a430618962d3e78b0e22e61
|
|
|
519
471
|
export declare const WHISPER_SMALL: "pear://c6a987fbb4ad8fba1526e446501f88ee45dfafbf1685410a7aeadb589fe18608/ggml-small.en-q8_0.bin";
|
|
520
472
|
export declare const WHISPER_TINY: "pear://9281d61503593fdf3eaa9d5e5d44746c271ef930aed3b7f8ee9ce153c76399d6/ggml-tiny.bin";
|
|
521
473
|
export declare const WHISPER_TINY_SILERO: "pear://ebfb94b378276da139554668f1ff737644eadff529c2ea0f2662d7df61fd86ca/ggml-tiny.bin";
|
|
522
|
-
export declare function getModelBySrc(modelId: string, hyperdriveKey
|
|
474
|
+
export declare function getModelBySrc(modelId: string, hyperdriveKey?: string): HyperdriveItem | undefined;
|
|
523
475
|
//# sourceMappingURL=models.d.ts.map
|
|
@@ -65,22 +65,6 @@ export const models = [
|
|
|
65
65
|
expectedSize: 1056782912,
|
|
66
66
|
sha256Checksum: "c876f159707a4e4f70e045106c69db15bfc935a4981706fd4f65c6e7ea1e81c5",
|
|
67
67
|
},
|
|
68
|
-
{
|
|
69
|
-
hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31",
|
|
70
|
-
hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0",
|
|
71
|
-
modelId: "Qwen2.5-Omni-3B-Q4_K_M.gguf",
|
|
72
|
-
addon: "llm",
|
|
73
|
-
expectedSize: 2104931648,
|
|
74
|
-
sha256Checksum: "4b0bd358c1e9ec55dd3055ef6d71c958c821533d85916a10cfa89c4552a86e29",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31",
|
|
78
|
-
hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0",
|
|
79
|
-
modelId: "mmproj-Qwen2.5-Omni-3B-Q8_0.gguf",
|
|
80
|
-
addon: "llm",
|
|
81
|
-
expectedSize: 1538031328,
|
|
82
|
-
sha256Checksum: "4e6c816cd33f7298d07cb780c136a396631e50e62f6501660271f8c6e302e565",
|
|
83
|
-
},
|
|
84
68
|
{
|
|
85
69
|
hyperdriveKey: "d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578",
|
|
86
70
|
hyperbeeKey: "generation:qwen3:instruct::0.6B::1.0.0",
|
|
@@ -121,38 +105,6 @@ export const models = [
|
|
|
121
105
|
expectedSize: 2401075552,
|
|
122
106
|
sha256Checksum: "9cfebb63cd7e6b6d1755ea8ef001fcdadfa17831da1db96eafe3fc554913d5e1",
|
|
123
107
|
},
|
|
124
|
-
{
|
|
125
|
-
hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f",
|
|
126
|
-
hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct",
|
|
127
|
-
modelId: "SmolVLM2-500M-Video-Instruct-f16.gguf",
|
|
128
|
-
addon: "llm",
|
|
129
|
-
expectedSize: 820424704,
|
|
130
|
-
sha256Checksum: "80f7e3f04bc2d3324ac1a9f52f5776fe13a69912adf74f8e7edacf773d140d77",
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f",
|
|
134
|
-
hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct",
|
|
135
|
-
modelId: "mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf",
|
|
136
|
-
addon: "llm",
|
|
137
|
-
expectedSize: 199470624,
|
|
138
|
-
sha256Checksum: "b5dc8ebe7cbeab66a5369693960a52515d7824f13d4063ceca78431f2a6b59b0",
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576",
|
|
142
|
-
hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct",
|
|
143
|
-
modelId: "SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
|
|
144
|
-
addon: "llm",
|
|
145
|
-
expectedSize: 436808704,
|
|
146
|
-
sha256Checksum: "6f67b8036b2469fcd71728702720c6b51aebd759b78137a8120733b4d66438bc",
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576",
|
|
150
|
-
hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct",
|
|
151
|
-
modelId: "mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
|
|
152
|
-
addon: "llm",
|
|
153
|
-
expectedSize: 108785184,
|
|
154
|
-
sha256Checksum: "921dc7e259f308e5b027111fa185efcbf33db13f6e35749ddf7f5cdb60ef520b",
|
|
155
|
-
},
|
|
156
108
|
{
|
|
157
109
|
hyperdriveKey: "268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7",
|
|
158
110
|
hyperbeeKey: "translation:ggml-indictrans:dist:2:200M:q0f32:1.0.0:en-hi",
|
|
@@ -523,63 +475,60 @@ export const GTE_LARGE_FP16 = `pear://${models[4].hyperdriveKey}/${models[4].mod
|
|
|
523
475
|
export const LASER_DOLPHIN_2_6_2X7B_INST_Q2_K = `pear://${models[5].hyperdriveKey}/${models[5].modelId}`;
|
|
524
476
|
export const LLAMA_3_2_1B_INST_Q4_0 = `pear://${models[6].hyperdriveKey}/${models[6].modelId}`;
|
|
525
477
|
export const QWEN_3_1_7B_INST_Q4 = `pear://${models[7].hyperdriveKey}/${models[7].modelId}`;
|
|
526
|
-
export const
|
|
527
|
-
export const
|
|
528
|
-
export const
|
|
529
|
-
export const
|
|
530
|
-
export const
|
|
531
|
-
export const
|
|
532
|
-
export const
|
|
533
|
-
export const
|
|
534
|
-
export const
|
|
535
|
-
export const
|
|
536
|
-
export const
|
|
537
|
-
export const
|
|
538
|
-
export const
|
|
539
|
-
export const
|
|
540
|
-
export const
|
|
541
|
-
export const
|
|
542
|
-
export const
|
|
543
|
-
export const
|
|
544
|
-
export const
|
|
545
|
-
export const
|
|
546
|
-
export const
|
|
547
|
-
export const
|
|
548
|
-
export const
|
|
549
|
-
export const
|
|
550
|
-
export const
|
|
551
|
-
export const
|
|
552
|
-
export const
|
|
553
|
-
export const
|
|
554
|
-
export const
|
|
555
|
-
export const
|
|
556
|
-
export const
|
|
557
|
-
export const
|
|
558
|
-
export const
|
|
559
|
-
export const
|
|
560
|
-
export const
|
|
561
|
-
export const
|
|
562
|
-
export const
|
|
563
|
-
export const
|
|
564
|
-
export const
|
|
565
|
-
export const
|
|
566
|
-
export const
|
|
567
|
-
export const
|
|
568
|
-
export const
|
|
569
|
-
export const
|
|
570
|
-
export const
|
|
571
|
-
export const
|
|
572
|
-
export const
|
|
573
|
-
export const
|
|
574
|
-
export const
|
|
575
|
-
export const
|
|
576
|
-
export const MARIAN_OPUS_JA_EN_Q4F16_1 = `pear://${models[58].hyperdriveKey}/${models[58].modelId}`;
|
|
577
|
-
export const VAD_SILERO_5_1_2 = `pear://${models[59].hyperdriveKey}/${models[59].modelId}`;
|
|
578
|
-
export const WHISPER_LARGE_3 = `pear://${models[60].hyperdriveKey}/${models[60].modelId}`;
|
|
579
|
-
export const WHISPER_SMALL = `pear://${models[61].hyperdriveKey}/${models[61].modelId}`;
|
|
580
|
-
export const WHISPER_TINY = `pear://${models[62].hyperdriveKey}/${models[62].modelId}`;
|
|
581
|
-
export const WHISPER_TINY_SILERO = `pear://${models[63].hyperdriveKey}/${models[63].modelId}`;
|
|
478
|
+
export const QWEN3_0_6B_INST = `pear://${models[8].hyperdriveKey}/${models[8].modelId}`;
|
|
479
|
+
export const QWEN3_4B_INST_Q4 = `pear://${models[9].hyperdriveKey}/${models[9].modelId}`;
|
|
480
|
+
export const QWEN3_600M_INST_Q4 = `pear://${models[10].hyperdriveKey}/${models[10].modelId}`;
|
|
481
|
+
export const SALAMANDRATA_2B_INST_Q4 = `pear://${models[11].hyperdriveKey}/${models[11].modelId}`;
|
|
482
|
+
export const SALAMANDRATA_2B_INST_Q8 = `pear://${models[12].hyperdriveKey}/${models[12].modelId}`;
|
|
483
|
+
export const MARIAN_EN_HI_INDIC_200M_Q0F32 = `pear://${models[13].hyperdriveKey}/${models[13].modelId}`;
|
|
484
|
+
export const MARIAN_HI_EN_INDIC_200M_Q0F32 = `pear://${models[14].hyperdriveKey}/${models[14].modelId}`;
|
|
485
|
+
export const MARIAN_HI_HI_INDIC_320M_Q0F32 = `pear://${models[15].hyperdriveKey}/${models[15].modelId}`;
|
|
486
|
+
export const MARIAN_EN_HI_INDIC_1B_Q0F16 = `pear://${models[16].hyperdriveKey}/${models[16].modelId}`;
|
|
487
|
+
export const MARIAN_HI_EN_INDIC_1B_Q0F16 = `pear://${models[17].hyperdriveKey}/${models[17].modelId}`;
|
|
488
|
+
export const MARIAN_HI_HI_INDIC_1B_Q0F16 = `pear://${models[18].hyperdriveKey}/${models[18].modelId}`;
|
|
489
|
+
export const MARIAN_EN_HI_INDIC_1B_Q0F32 = `pear://${models[19].hyperdriveKey}/${models[19].modelId}`;
|
|
490
|
+
export const MARIAN_HI_EN_INDIC_1B_Q0F32 = `pear://${models[20].hyperdriveKey}/${models[20].modelId}`;
|
|
491
|
+
export const MARIAN_HI_HI_INDIC_1B_Q0F32 = `pear://${models[21].hyperdriveKey}/${models[21].modelId}`;
|
|
492
|
+
export const MARIAN_EN_HI_INDIC_1B_Q4_0 = `pear://${models[22].hyperdriveKey}/${models[22].modelId}`;
|
|
493
|
+
export const MARIAN_HI_EN_INDIC_1B_Q4_0 = `pear://${models[23].hyperdriveKey}/${models[23].modelId}`;
|
|
494
|
+
export const MARIAN_HI_HI_INDIC_1B_Q4_0 = `pear://${models[24].hyperdriveKey}/${models[24].modelId}`;
|
|
495
|
+
export const MARIAN_EN_HI_INDIC_200M_Q0F16 = `pear://${models[25].hyperdriveKey}/${models[25].modelId}`;
|
|
496
|
+
export const MARIAN_HI_EN_INDIC_200M_Q0F16 = `pear://${models[26].hyperdriveKey}/${models[26].modelId}`;
|
|
497
|
+
export const MARIAN_EN_HI_INDIC_200M_Q4_0 = `pear://${models[27].hyperdriveKey}/${models[27].modelId}`;
|
|
498
|
+
export const MARIAN_HI_EN_INDIC_200M_Q4_0 = `pear://${models[28].hyperdriveKey}/${models[28].modelId}`;
|
|
499
|
+
export const MARIAN_HI_HI_INDIC_320M_Q0F16 = `pear://${models[29].hyperdriveKey}/${models[29].modelId}`;
|
|
500
|
+
export const MARIAN_HI_HI_INDIC_320M_Q4_0 = `pear://${models[30].hyperdriveKey}/${models[30].modelId}`;
|
|
501
|
+
export const MARIAN_OPUS_EN_IT = `pear://${models[31].hyperdriveKey}/${models[31].modelId}`;
|
|
502
|
+
export const MARIAN_OPUS_IT_EN = `pear://${models[32].hyperdriveKey}/${models[32].modelId}`;
|
|
503
|
+
export const MARIAN_OPUS_DE_EN_Q0F32 = `pear://${models[33].hyperdriveKey}/${models[33].modelId}`;
|
|
504
|
+
export const MARIAN_OPUS_DE_ES_Q0F32 = `pear://${models[34].hyperdriveKey}/${models[34].modelId}`;
|
|
505
|
+
export const MARIAN_OPUS_DE_IT_Q0F32 = `pear://${models[35].hyperdriveKey}/${models[35].modelId}`;
|
|
506
|
+
export const MARIAN_OPUS_EN_DE_Q0F32 = `pear://${models[36].hyperdriveKey}/${models[36].modelId}`;
|
|
507
|
+
export const MARIAN_OPUS_EN_ES_Q0F32 = `pear://${models[37].hyperdriveKey}/${models[37].modelId}`;
|
|
508
|
+
export const MARIAN_OPUS_EN_IT_Q0F32 = `pear://${models[38].hyperdriveKey}/${models[38].modelId}`;
|
|
509
|
+
export const MARIAN_OPUS_ES_DE_Q0F32 = `pear://${models[39].hyperdriveKey}/${models[39].modelId}`;
|
|
510
|
+
export const MARIAN_OPUS_ES_EN_Q0F32 = `pear://${models[40].hyperdriveKey}/${models[40].modelId}`;
|
|
511
|
+
export const MARIAN_OPUS_ES_IT_Q0F32 = `pear://${models[41].hyperdriveKey}/${models[41].modelId}`;
|
|
512
|
+
export const MARIAN_OPUS_IT_DE_Q0F32 = `pear://${models[42].hyperdriveKey}/${models[42].modelId}`;
|
|
513
|
+
export const MARIAN_OPUS_IT_EN_Q0F32 = `pear://${models[43].hyperdriveKey}/${models[43].modelId}`;
|
|
514
|
+
export const MARIAN_OPUS_IT_ES_Q0F32 = `pear://${models[44].hyperdriveKey}/${models[44].modelId}`;
|
|
515
|
+
export const MARIAN_OPUS_EN_RU_Q0F16 = `pear://${models[45].hyperdriveKey}/${models[45].modelId}`;
|
|
516
|
+
export const MARIAN_OPUS_RU_EN_Q0F16 = `pear://${models[46].hyperdriveKey}/${models[46].modelId}`;
|
|
517
|
+
export const MARIAN_OPUS_EN_RU_Q0F32 = `pear://${models[47].hyperdriveKey}/${models[47].modelId}`;
|
|
518
|
+
export const MARIAN_OPUS_RU_EN_Q0F32 = `pear://${models[48].hyperdriveKey}/${models[48].modelId}`;
|
|
519
|
+
export const MARIAN_OPUS_EN_RU_Q4_0 = `pear://${models[49].hyperdriveKey}/${models[49].modelId}`;
|
|
520
|
+
export const MARIAN_OPUS_RU_EN_Q4_0 = `pear://${models[50].hyperdriveKey}/${models[50].modelId}`;
|
|
521
|
+
export const MARIAN_OPUS_EN_JA_Q4F16_1 = `pear://${models[51].hyperdriveKey}/${models[51].modelId}`;
|
|
522
|
+
export const MARIAN_OPUS_JA_EN_Q4F16_1 = `pear://${models[52].hyperdriveKey}/${models[52].modelId}`;
|
|
523
|
+
export const VAD_SILERO_5_1_2 = `pear://${models[53].hyperdriveKey}/${models[53].modelId}`;
|
|
524
|
+
export const WHISPER_LARGE_3 = `pear://${models[54].hyperdriveKey}/${models[54].modelId}`;
|
|
525
|
+
export const WHISPER_SMALL = `pear://${models[55].hyperdriveKey}/${models[55].modelId}`;
|
|
526
|
+
export const WHISPER_TINY = `pear://${models[56].hyperdriveKey}/${models[56].modelId}`;
|
|
527
|
+
export const WHISPER_TINY_SILERO = `pear://${models[57].hyperdriveKey}/${models[57].modelId}`;
|
|
582
528
|
// Helper function for our curated model list
|
|
583
529
|
export function getModelBySrc(modelId, hyperdriveKey) {
|
|
584
|
-
|
|
530
|
+
if (hyperdriveKey) {
|
|
531
|
+
return models.find((model) => model.modelId === modelId && model.hyperdriveKey === hyperdriveKey);
|
|
532
|
+
}
|
|
533
|
+
return models.find((model) => model.modelId === modelId);
|
|
585
534
|
}
|
package/dist/schemas/common.d.ts
CHANGED
package/dist/schemas/rag.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ declare const ragSaveEmbeddingsParamsSchema: z.ZodObject<{
|
|
|
25
25
|
paragraph: "paragraph";
|
|
26
26
|
}>>;
|
|
27
27
|
splitStrategy: z.ZodOptional<z.ZodEnum<{
|
|
28
|
-
token: "token";
|
|
29
28
|
character: "character";
|
|
30
29
|
word: "word";
|
|
31
30
|
sentence: "sentence";
|
|
@@ -46,7 +45,6 @@ export declare const ragSaveEmbeddingsOperationSchema: z.ZodObject<{
|
|
|
46
45
|
paragraph: "paragraph";
|
|
47
46
|
}>>;
|
|
48
47
|
splitStrategy: z.ZodOptional<z.ZodEnum<{
|
|
49
|
-
token: "token";
|
|
50
48
|
character: "character";
|
|
51
49
|
word: "word";
|
|
52
50
|
sentence: "sentence";
|
|
@@ -97,7 +95,6 @@ export declare const ragRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
97
95
|
paragraph: "paragraph";
|
|
98
96
|
}>>;
|
|
99
97
|
splitStrategy: z.ZodOptional<z.ZodEnum<{
|
|
100
|
-
token: "token";
|
|
101
98
|
character: "character";
|
|
102
99
|
word: "word";
|
|
103
100
|
sentence: "sentence";
|
package/dist/schemas/rag.js
CHANGED
|
@@ -4,9 +4,7 @@ const llmChunkOptsSchema = z.object({
|
|
|
4
4
|
chunkSize: z.number().optional(),
|
|
5
5
|
chunkOverlap: z.number().optional(),
|
|
6
6
|
chunkStrategy: z.enum(["character", "paragraph"]).optional(),
|
|
7
|
-
splitStrategy: z
|
|
8
|
-
.enum(["character", "word", "token", "sentence", "line"])
|
|
9
|
-
.optional(),
|
|
7
|
+
splitStrategy: z.enum(["character", "word", "sentence", "line"]).optional(),
|
|
10
8
|
});
|
|
11
9
|
const ragSaveEmbeddingsResultSchema = z.object({
|
|
12
10
|
status: z.enum(["fulfilled", "rejected"]),
|
|
@@ -54,34 +54,8 @@ function prepareMessagesForCache(cachePathToUse, cacheExists, history) {
|
|
|
54
54
|
}
|
|
55
55
|
async function* processModelResponse(model, messagesToSend, shouldSaveCache) {
|
|
56
56
|
const response = await model.run(messagesToSend);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const errorPromise = new Promise((_, reject) => {
|
|
60
|
-
rejectOnError = reject;
|
|
61
|
-
});
|
|
62
|
-
response.onError((error) => {
|
|
63
|
-
if (rejectOnError) {
|
|
64
|
-
rejectOnError(error);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
const iterator = response.iterate();
|
|
68
|
-
try {
|
|
69
|
-
while (true) {
|
|
70
|
-
// Race between getting the next token and an error occurring
|
|
71
|
-
const result = await Promise.race([iterator.next(), errorPromise]);
|
|
72
|
-
if (result.done) {
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
yield result.value;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
if (error instanceof Error) {
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
throw new Error(String(error));
|
|
84
|
-
}
|
|
57
|
+
for await (const token of response.iterate()) {
|
|
58
|
+
yield token;
|
|
85
59
|
}
|
|
86
60
|
if (shouldSaveCache) {
|
|
87
61
|
await model.run([{ role: "session", content: "save" }]);
|
|
@@ -1,38 +1,52 @@
|
|
|
1
1
|
import { completion } from "../../bare/addons/llamacpp/index.js";
|
|
2
2
|
export async function* handleCompletionStream(request) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}));
|
|
8
|
-
const stream = completion({
|
|
9
|
-
history: filteredHistory,
|
|
10
|
-
modelId: request.modelId,
|
|
11
|
-
kvCache: request.kvCache,
|
|
12
|
-
});
|
|
13
|
-
let stats;
|
|
14
|
-
let done = false;
|
|
15
|
-
let buffer = "";
|
|
16
|
-
while (!done) {
|
|
17
|
-
const result = await stream.next();
|
|
18
|
-
if (result.done) {
|
|
19
|
-
stats = result.value;
|
|
20
|
-
done = true;
|
|
3
|
+
try {
|
|
4
|
+
// Log tools if provided
|
|
5
|
+
if (request.tools) {
|
|
6
|
+
console.log("Tools passed to completionStream:", request.tools);
|
|
21
7
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
8
|
+
const filteredHistory = request.history.map(({ role, content, attachments }) => ({
|
|
9
|
+
role,
|
|
10
|
+
content,
|
|
11
|
+
attachments: attachments ?? [],
|
|
12
|
+
}));
|
|
13
|
+
const stream = completion({
|
|
14
|
+
history: filteredHistory,
|
|
15
|
+
modelId: request.modelId,
|
|
16
|
+
kvCache: request.kvCache,
|
|
17
|
+
});
|
|
18
|
+
let stats;
|
|
19
|
+
let done = false;
|
|
20
|
+
let buffer = "";
|
|
21
|
+
while (!done) {
|
|
22
|
+
const result = await stream.next();
|
|
23
|
+
if (result.done) {
|
|
24
|
+
stats = result.value;
|
|
25
|
+
done = true;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
buffer += result.value;
|
|
29
|
+
if (request.stream) {
|
|
30
|
+
yield {
|
|
31
|
+
type: "completionStream",
|
|
32
|
+
token: result.value,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
29
35
|
}
|
|
30
36
|
}
|
|
37
|
+
yield {
|
|
38
|
+
type: "completionStream",
|
|
39
|
+
token: buffer,
|
|
40
|
+
done: true,
|
|
41
|
+
stats,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error("Error during completion stream:", error);
|
|
46
|
+
yield {
|
|
47
|
+
type: "completionStream",
|
|
48
|
+
token: "",
|
|
49
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
50
|
+
};
|
|
31
51
|
}
|
|
32
|
-
yield {
|
|
33
|
-
type: "completionStream",
|
|
34
|
-
token: buffer,
|
|
35
|
-
done: true,
|
|
36
|
-
stats,
|
|
37
|
-
};
|
|
38
52
|
}
|
|
@@ -4,9 +4,28 @@ export declare const registerDownload: (key: string, entry: DownloadEntry) => vo
|
|
|
4
4
|
export declare const unregisterDownload: (key: string) => void;
|
|
5
5
|
export declare const createHyperdriveDownloadKey: (hyperdriveKey: string, modelFileName: string) => string;
|
|
6
6
|
export declare const createHttpDownloadKey: (url: string) => string;
|
|
7
|
+
export declare const getAllActiveDownloads: () => Map<string, DownloadEntry>;
|
|
7
8
|
export declare const setClearCacheFlag: (downloadKey: string, clearCache: boolean) => void;
|
|
8
9
|
export declare const shouldClearCache: (downloadKey: string) => boolean;
|
|
9
10
|
export declare const clearClearCacheFlag: (downloadKey: string) => void;
|
|
10
11
|
export declare const createCancelFunction: (downloadKey: string, clearCache?: boolean) => () => void;
|
|
11
12
|
export declare const cancelAllDownloads: () => void;
|
|
13
|
+
export declare const getDownloadStats: () => {
|
|
14
|
+
activeCount: number;
|
|
15
|
+
downloads: ({
|
|
16
|
+
hyperdriveKey: string;
|
|
17
|
+
modelFileName: string;
|
|
18
|
+
key: string;
|
|
19
|
+
startTime: number;
|
|
20
|
+
duration: number;
|
|
21
|
+
type: "hyperdrive" | "http";
|
|
22
|
+
} | {
|
|
23
|
+
url: string;
|
|
24
|
+
modelPath: string;
|
|
25
|
+
key: string;
|
|
26
|
+
startTime: number;
|
|
27
|
+
duration: number;
|
|
28
|
+
type: "hyperdrive" | "http";
|
|
29
|
+
})[];
|
|
30
|
+
};
|
|
12
31
|
//# sourceMappingURL=download-manager.d.ts.map
|
|
@@ -12,6 +12,7 @@ export const unregisterDownload = (key) => {
|
|
|
12
12
|
};
|
|
13
13
|
export const createHyperdriveDownloadKey = (hyperdriveKey, modelFileName) => `${hyperdriveKey}:${modelFileName}`;
|
|
14
14
|
export const createHttpDownloadKey = (url) => `http:${url}`;
|
|
15
|
+
export const getAllActiveDownloads = () => new Map(activeDownloads);
|
|
15
16
|
export const setClearCacheFlag = (downloadKey, clearCache) => {
|
|
16
17
|
if (clearCache) {
|
|
17
18
|
clearCacheFlags.set(downloadKey, true);
|
|
@@ -38,6 +39,24 @@ export const cancelAllDownloads = () => {
|
|
|
38
39
|
console.log(`🧹 Cancelling ${activeDownloads.size} active downloads`);
|
|
39
40
|
Array.from(activeDownloads.keys()).forEach((key) => createCancelFunction(key)());
|
|
40
41
|
};
|
|
42
|
+
export const getDownloadStats = () => ({
|
|
43
|
+
activeCount: activeDownloads.size,
|
|
44
|
+
downloads: Array.from(activeDownloads.entries()).map(([key, entry]) => ({
|
|
45
|
+
key,
|
|
46
|
+
startTime: entry.startTime,
|
|
47
|
+
duration: Date.now() - entry.startTime,
|
|
48
|
+
type: entry.type,
|
|
49
|
+
...(entry.type === "hyperdrive"
|
|
50
|
+
? {
|
|
51
|
+
hyperdriveKey: entry.hyperdriveKey,
|
|
52
|
+
modelFileName: entry.modelFileName,
|
|
53
|
+
}
|
|
54
|
+
: {
|
|
55
|
+
url: entry.url,
|
|
56
|
+
modelPath: entry.modelPath,
|
|
57
|
+
}),
|
|
58
|
+
})),
|
|
59
|
+
});
|
|
41
60
|
// Register cleanup handlers for graceful shutdown
|
|
42
61
|
let cleanupRegistered = false;
|
|
43
62
|
let isCleaningUp = false;
|
|
@@ -60,14 +79,10 @@ const registerCleanupHandlers = () => {
|
|
|
60
79
|
console.error("❌ Error during download cleanup:", error);
|
|
61
80
|
}
|
|
62
81
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
process.exit(0);
|
|
70
|
-
};
|
|
71
|
-
process.once("SIGTERM", () => void exitHandler());
|
|
72
|
-
process.once("SIGINT", () => void exitHandler());
|
|
82
|
+
process.on("SIGTERM", () => {
|
|
83
|
+
void cleanup();
|
|
84
|
+
});
|
|
85
|
+
process.on("SIGINT", () => {
|
|
86
|
+
void cleanup();
|
|
87
|
+
});
|
|
73
88
|
};
|
|
@@ -10,49 +10,24 @@ import { getEnv } from "../../../worker.js";
|
|
|
10
10
|
import { getModelsCacheDir, generateShortHash } from "../../../utils/index.js";
|
|
11
11
|
import { getModelBySrc } from "../../../../models/hyperdrive/index.js";
|
|
12
12
|
import { getActiveDownload, registerDownload, unregisterDownload, createHyperdriveDownloadKey, shouldClearCache, clearClearCacheFlag, } from "./download-manager.js";
|
|
13
|
-
function createProgressHandler(blob, progressCallback, downloadKey, initialBytes = 0) {
|
|
14
|
-
let downloadedBytes = initialBytes;
|
|
15
|
-
return (index, bytes) => {
|
|
16
|
-
if (index >= blob.blockOffset &&
|
|
17
|
-
index < blob.blockOffset + blob.blockLength) {
|
|
18
|
-
downloadedBytes += bytes;
|
|
19
|
-
if (progressCallback && downloadKey) {
|
|
20
|
-
progressCallback({
|
|
21
|
-
type: "modelProgress",
|
|
22
|
-
downloaded: downloadedBytes,
|
|
23
|
-
total: blob.byteLength,
|
|
24
|
-
percentage: blob.byteLength > 0 ? (downloadedBytes / blob.byteLength) * 100 : 0,
|
|
25
|
-
downloadKey,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
13
|
async function setupHyperdrive(hyperdriveKey, corestoreDir) {
|
|
32
14
|
const corestore = new Corestore(corestoreDir);
|
|
33
15
|
await corestore.ready();
|
|
34
16
|
const drive = new Hyperdrive(corestore, Buffer.from(hyperdriveKey, "hex"));
|
|
35
17
|
await drive.ready();
|
|
36
18
|
const swarm = new Hyperswarm();
|
|
37
|
-
|
|
19
|
+
swarm.join(drive.discoveryKey, { server: false, client: true });
|
|
38
20
|
swarm.on("connection", (connection) => {
|
|
39
21
|
console.log(`🤝 Connected to peer for hyperdrive download`);
|
|
40
22
|
drive.replicate(connection);
|
|
41
23
|
});
|
|
42
|
-
|
|
43
|
-
swarm.flush()
|
|
24
|
+
const doneFindingPeers = drive.findingPeers();
|
|
25
|
+
await swarm.flush();
|
|
26
|
+
doneFindingPeers();
|
|
44
27
|
return { corestore, drive, swarm, corestoreDir };
|
|
45
28
|
}
|
|
46
29
|
async function cleanupHyperdrive(setup) {
|
|
47
30
|
console.log("🧹 Cleaning up hyperdrive setup");
|
|
48
|
-
if (!setup.swarm.suspended) {
|
|
49
|
-
try {
|
|
50
|
-
await setup.swarm.suspend();
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// If suspend fails, continue with cleanup
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
31
|
await setup.swarm.destroy();
|
|
57
32
|
await setup.drive.close();
|
|
58
33
|
await setup.corestore.close();
|
|
@@ -67,81 +42,43 @@ export async function deleteCorestoreDirectory(corestoreDir) {
|
|
|
67
42
|
}
|
|
68
43
|
}
|
|
69
44
|
async function findFileInHyperdrive(drive, modelFileName) {
|
|
70
|
-
if (drive.core.length === 0) {
|
|
71
|
-
// this method will update the length of the core using the first peer it finds
|
|
72
|
-
// this will ensure that the hyperdrive is usable
|
|
73
|
-
await drive.core.update();
|
|
74
|
-
}
|
|
75
45
|
const paths = [modelFileName, `/${modelFileName}`, `./${modelFileName}`];
|
|
46
|
+
let entry = null;
|
|
47
|
+
let targetPath = modelFileName;
|
|
76
48
|
for (const pathVariation of paths) {
|
|
77
49
|
try {
|
|
78
|
-
|
|
50
|
+
entry = await drive.entry(pathVariation);
|
|
79
51
|
if (entry) {
|
|
80
|
-
|
|
52
|
+
targetPath = pathVariation;
|
|
53
|
+
break;
|
|
81
54
|
}
|
|
82
55
|
}
|
|
83
56
|
catch {
|
|
84
57
|
// Continue trying other paths
|
|
85
58
|
}
|
|
86
59
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
for await (const file of files) {
|
|
60
|
+
if (!entry) {
|
|
61
|
+
// Try listing available files to help debug
|
|
62
|
+
try {
|
|
63
|
+
const rootFiles = drive.list("/", false);
|
|
64
|
+
const availableFiles = [];
|
|
65
|
+
for await (const file of rootFiles) {
|
|
94
66
|
availableFiles.push(file.key);
|
|
95
67
|
}
|
|
96
|
-
if (availableFiles.length
|
|
97
|
-
|
|
68
|
+
if (availableFiles.length === 0) {
|
|
69
|
+
// Try without leading slash
|
|
70
|
+
const noSlashFiles = drive.list("", false);
|
|
71
|
+
for await (const file of noSlashFiles) {
|
|
72
|
+
availableFiles.push(file.key);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`File ${modelFileName} not found in hyperdrive. Available files: ${availableFiles.join(", ")}`);
|
|
98
76
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// Ignore listing errors
|
|
102
|
-
}
|
|
103
|
-
const filesInfo = availableFiles.length > 0
|
|
104
|
-
? `Available files: ${availableFiles.join(", ")}`
|
|
105
|
-
: "Could not list available files";
|
|
106
|
-
throw new Error(`File ${modelFileName} not found in hyperdrive. ${filesInfo}`);
|
|
107
|
-
}
|
|
108
|
-
async function checkFileDownloaded(drive, entry) {
|
|
109
|
-
const blobs = await drive.getBlobs();
|
|
110
|
-
const blob = entry?.value?.blob;
|
|
111
|
-
if (!blob) {
|
|
112
|
-
return {
|
|
113
|
-
blobs,
|
|
114
|
-
blocksDownloaded: 0,
|
|
115
|
-
totalBlocks: 0,
|
|
116
|
-
totalBytes: 0,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
// Check how many blocks are already downloaded
|
|
120
|
-
let blocksDownloaded = 0;
|
|
121
|
-
for (let i = blob.blockOffset; i < blob.blockOffset + blob.blockLength; i++) {
|
|
122
|
-
const hasBlock = await blobs.core.has(i);
|
|
123
|
-
if (hasBlock) {
|
|
124
|
-
blocksDownloaded++;
|
|
77
|
+
catch (listError) {
|
|
78
|
+
throw new Error(`File ${modelFileName} not found in hyperdrive. Could not list available files: ${listError instanceof Error ? listError.message : String(listError)}`);
|
|
125
79
|
}
|
|
126
80
|
}
|
|
127
|
-
return {
|
|
128
|
-
blobs,
|
|
129
|
-
blocksDownloaded,
|
|
130
|
-
totalBlocks: blob.blockLength,
|
|
131
|
-
totalBytes: blob.byteLength,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
async function validateFileExistence(drive, file) {
|
|
135
|
-
const { entry, targetPath } = await findFileInHyperdrive(drive, file);
|
|
136
|
-
const { blobs, blocksDownloaded, totalBlocks, totalBytes } = await checkFileDownloaded(drive, entry);
|
|
137
|
-
return {
|
|
138
|
-
entry,
|
|
139
|
-
blobs,
|
|
140
|
-
targetPath,
|
|
141
|
-
blocksDownloaded,
|
|
142
|
-
totalBlocks,
|
|
143
|
-
totalBytes,
|
|
144
|
-
};
|
|
81
|
+
return { entry, targetPath };
|
|
145
82
|
}
|
|
146
83
|
async function validateFileChecksum(filePath, expectedChecksum) {
|
|
147
84
|
console.log(`🔍 Validating SHA256 checksum...`);
|
|
@@ -216,15 +153,13 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
|
|
|
216
153
|
}
|
|
217
154
|
console.log(`Downloading model from hyperdrive ${hyperdriveKey} to ${modelPath}`);
|
|
218
155
|
const setup = await setupHyperdrive(hyperdriveKey, corestoreDir);
|
|
156
|
+
let downloadedBytes = 0;
|
|
157
|
+
let totalBytes = 0;
|
|
219
158
|
// Set up abort handler
|
|
220
159
|
let readStream;
|
|
221
160
|
let writeStream;
|
|
222
161
|
const cleanup = () => {
|
|
223
162
|
console.log("🛑 Aborting hyperdrive download...");
|
|
224
|
-
setup.swarm.suspended = true;
|
|
225
|
-
setup.swarm.suspend().catch(() => {
|
|
226
|
-
// Ignore errors during emergency suspend
|
|
227
|
-
});
|
|
228
163
|
// Destroy streams if they exist
|
|
229
164
|
if (readStream) {
|
|
230
165
|
readStream.destroy();
|
|
@@ -234,19 +169,48 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
|
|
|
234
169
|
}
|
|
235
170
|
};
|
|
236
171
|
signal?.addEventListener("abort", cleanup);
|
|
237
|
-
let downloadHandler;
|
|
238
172
|
try {
|
|
239
|
-
const
|
|
173
|
+
const result = await findFileInHyperdrive(setup.drive, modelFileName);
|
|
174
|
+
const { entry, targetPath } = result;
|
|
175
|
+
totalBytes = entry?.value?.blob?.byteLength || 0;
|
|
176
|
+
console.log(`📏 Model size: ${totalBytes} bytes (${(totalBytes / 1024 / 1024).toFixed(2)} MB)`);
|
|
177
|
+
// Get blobs and file blob range
|
|
178
|
+
const blobs = await setup.drive.getBlobs();
|
|
240
179
|
const blob = entry?.value?.blob;
|
|
241
180
|
if (!blob) {
|
|
242
181
|
throw new Error(`No blob found for ${modelFileName}`);
|
|
243
182
|
}
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
|
|
183
|
+
// Check what blocks are already downloaded in corestore for this specific file
|
|
184
|
+
let alreadyDownloaded = 0;
|
|
185
|
+
for (let i = blob.blockOffset; i < blob.blockOffset + blob.blockLength; i++) {
|
|
186
|
+
const hasBlock = await blobs.core.has(i);
|
|
187
|
+
if (hasBlock) {
|
|
188
|
+
alreadyDownloaded++;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
downloadedBytes = 0;
|
|
192
|
+
if (alreadyDownloaded > 0) {
|
|
193
|
+
console.log(`📥 Resuming download (${alreadyDownloaded}/${blob.blockLength} blocks already in corestore)`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log(`📥 Starting fresh download`);
|
|
197
|
+
}
|
|
247
198
|
// Track only downloads for blocks within our file's blob range
|
|
248
|
-
|
|
249
|
-
|
|
199
|
+
blobs.core.on("download", (index, bytes) => {
|
|
200
|
+
if (index >= blob.blockOffset &&
|
|
201
|
+
index < blob.blockOffset + blob.blockLength) {
|
|
202
|
+
downloadedBytes += bytes;
|
|
203
|
+
if (progressCallback) {
|
|
204
|
+
progressCallback({
|
|
205
|
+
type: "modelProgress",
|
|
206
|
+
downloaded: downloadedBytes,
|
|
207
|
+
total: totalBytes,
|
|
208
|
+
percentage: totalBytes > 0 ? (downloadedBytes / totalBytes) * 100 : 0,
|
|
209
|
+
downloadKey,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
250
214
|
// Check if aborted before starting streams
|
|
251
215
|
if (signal?.aborted) {
|
|
252
216
|
throw new Error("Download cancelled");
|
|
@@ -259,13 +223,15 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
|
|
|
259
223
|
readStream.pipe(writeStream);
|
|
260
224
|
// Wait for download to complete
|
|
261
225
|
await new Promise((resolve, reject) => {
|
|
262
|
-
writeStream.on("finish", resolve);
|
|
226
|
+
writeStream.on("finish", () => resolve(undefined));
|
|
263
227
|
writeStream.on("error", reject);
|
|
264
228
|
readStream.on("error", reject);
|
|
265
229
|
// Also reject on abort
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
230
|
+
if (signal) {
|
|
231
|
+
signal.addEventListener("abort", () => {
|
|
232
|
+
reject(new Error("Download cancelled"));
|
|
233
|
+
}, { once: true });
|
|
234
|
+
}
|
|
269
235
|
});
|
|
270
236
|
console.log(`✅ Model downloaded successfully to ${modelPath}`);
|
|
271
237
|
// Delete corestore directory after successful download (only when not seeding, to save space)
|
|
@@ -283,29 +249,22 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
|
|
|
283
249
|
}
|
|
284
250
|
finally {
|
|
285
251
|
signal?.removeEventListener("abort", cleanup);
|
|
286
|
-
if (downloadHandler) {
|
|
287
|
-
try {
|
|
288
|
-
const { blobs } = await validateFileExistence(setup.drive, modelFileName);
|
|
289
|
-
blobs.core.off("download", downloadHandler);
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
// If we can't get blobs, setup is already closed
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
252
|
if (!seed) {
|
|
296
253
|
await cleanupHyperdrive(setup);
|
|
297
254
|
}
|
|
298
255
|
// Only delete corestore and partial file if user explicitly requested clearCache
|
|
299
|
-
if (signal?.aborted
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
256
|
+
if (signal?.aborted) {
|
|
257
|
+
if (shouldClearCache(downloadKey)) {
|
|
258
|
+
try {
|
|
259
|
+
await fsPromises.unlink(modelPath);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// no-op
|
|
263
|
+
}
|
|
264
|
+
await deleteCorestoreDirectory(corestoreDir);
|
|
305
265
|
}
|
|
306
|
-
|
|
266
|
+
clearClearCacheFlag(downloadKey);
|
|
307
267
|
}
|
|
308
|
-
clearClearCacheFlag(downloadKey);
|
|
309
268
|
}
|
|
310
269
|
}
|
|
311
270
|
export async function downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, progressCallback, expectedChecksum) {
|
|
@@ -1,10 +1,46 @@
|
|
|
1
|
-
import { models } from "../../../../models/hyperdrive/models.js";
|
|
1
|
+
import { getModelBySrc, models } from "../../../../models/hyperdrive/models.js";
|
|
2
2
|
import { hyperdriveUrlSchema } from "../../../../schemas/index.js";
|
|
3
3
|
import { getModelsCacheDir } from "../../../utils/index.js";
|
|
4
4
|
import { promises as fsPromises } from "bare-fs";
|
|
5
5
|
import path from "bare-path";
|
|
6
6
|
import { downloadModelFromHttp } from "./http.js";
|
|
7
7
|
import { downloadModelFromHyperdrive } from "./hyperdrive.js";
|
|
8
|
+
/**
|
|
9
|
+
* Attempts to resolve a model from cache (without validation)
|
|
10
|
+
* Validation will be handled by the hyperdrive download logic
|
|
11
|
+
*/
|
|
12
|
+
async function tryResolveCachedModel(modelId) {
|
|
13
|
+
const cacheDir = getModelsCacheDir();
|
|
14
|
+
const cachedPath = path.join(cacheDir, modelId);
|
|
15
|
+
try {
|
|
16
|
+
await fsPromises.access(cachedPath);
|
|
17
|
+
// File exists - return null to let hyperdrive validation handle size/checksum
|
|
18
|
+
// This ensures partial downloads are properly resumed instead of being
|
|
19
|
+
// incorrectly validated and deleted
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// File doesn't exist
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolves a known model by ID from hyperdrive, checking cache first
|
|
29
|
+
*/
|
|
30
|
+
async function resolveKnownModel(model, modelIdOrPath, progressCallback, seed) {
|
|
31
|
+
if (!model) {
|
|
32
|
+
throw new Error("Model is null");
|
|
33
|
+
}
|
|
34
|
+
console.log(`Loading model ID '${modelIdOrPath}' from hyperdrive`);
|
|
35
|
+
// Try to resolve from cache first
|
|
36
|
+
const cachedPath = await tryResolveCachedModel(model.modelId);
|
|
37
|
+
if (cachedPath) {
|
|
38
|
+
return cachedPath;
|
|
39
|
+
}
|
|
40
|
+
// Not cached or invalid, download from hyperdrive
|
|
41
|
+
const downloadedPath = await downloadModelFromHyperdrive(model.hyperdriveKey, model.modelId, seed, progressCallback, model.sha256Checksum);
|
|
42
|
+
return downloadedPath;
|
|
43
|
+
}
|
|
8
44
|
/**
|
|
9
45
|
* Resolves a local file path or cached file
|
|
10
46
|
*/
|
|
@@ -48,7 +84,10 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
|
|
|
48
84
|
let actualPath;
|
|
49
85
|
// Validate seeding is only used with hyperdrive models
|
|
50
86
|
if (seed && !hyperdriveKey) {
|
|
51
|
-
|
|
87
|
+
const model = getModelBySrc(actualModelSrc);
|
|
88
|
+
if (!model) {
|
|
89
|
+
throw new Error("Seeding is only supported for hyperdrive models");
|
|
90
|
+
}
|
|
52
91
|
}
|
|
53
92
|
// Check if it's an HTTP/HTTPS URL
|
|
54
93
|
if (actualModelSrc.startsWith("http://") ||
|
|
@@ -62,13 +101,21 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
|
|
|
62
101
|
console.log(`Loading from hyperdrive: ${hyperdriveKey}`);
|
|
63
102
|
actualPath = await downloadModelFromHyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
|
|
64
103
|
}
|
|
65
|
-
else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
|
|
66
|
-
// Handle file paths (absolute or relative with slashes)
|
|
67
|
-
actualPath = actualModelSrc;
|
|
68
|
-
}
|
|
69
104
|
else {
|
|
70
|
-
//
|
|
71
|
-
|
|
105
|
+
// Try to resolve as a known model ID
|
|
106
|
+
const model = getModelBySrc(actualModelSrc);
|
|
107
|
+
if (model) {
|
|
108
|
+
actualPath = await resolveKnownModel(model, actualModelSrc, progressCallback, seed);
|
|
109
|
+
}
|
|
110
|
+
else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
|
|
111
|
+
// Handle file paths (absolute or relative with slashes)
|
|
112
|
+
console.log(`Loading from file: ${actualModelSrc}`);
|
|
113
|
+
actualPath = actualModelSrc;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Handle local files and cached files
|
|
117
|
+
actualPath = await resolveLocalOrCachedFile(actualModelSrc);
|
|
118
|
+
}
|
|
72
119
|
}
|
|
73
120
|
return actualPath;
|
|
74
121
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3-dev.1760899404.f30d071",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"bare:ensureprebuilds:whispercpp": "cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-ia32 && cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm && cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-x64",
|
|
46
46
|
"bare:ensureprebuilds:embeddings": "cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-ia32 && cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-arm && cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-x64",
|
|
47
47
|
"bare:ensureprebuilds": "bun run bare:ensureprebuilds:llamacpp && bun run bare:ensureprebuilds:whispercpp && bun run bare:ensureprebuilds:embeddings",
|
|
48
|
-
"prepare
|
|
48
|
+
"prepare": "bun run husky",
|
|
49
49
|
"bare:example": "./scripts/run-with-bare.sh",
|
|
50
50
|
"docs_api:website": "typedoc --out ./docs/api/website --entryPoints index.ts --entryPointStrategy expand --readme none",
|
|
51
51
|
"docs_api:markdown": "typedoc --plugin typedoc-plugin-markdown --out ./docs/api/markdown --entryPoints index.ts --entryPointStrategy expand --readme none && sed -i '1,4d' ./docs/api/markdown/README.md",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"update-models": "node ./scripts/update-models.js"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@qvac/embed-llamacpp": "^0.3.
|
|
57
|
-
"@qvac/llm-llamacpp": "^0.3.
|
|
56
|
+
"@qvac/embed-llamacpp": "^0.3.0",
|
|
57
|
+
"@qvac/llm-llamacpp": "^0.3.0",
|
|
58
58
|
"@qvac/decoder-audio": "^0.1.0",
|
|
59
59
|
"@qvac/error": "^0.1.0",
|
|
60
60
|
"@qvac/langdetect-text": "^0.1.0",
|
|
61
61
|
"@qvac/logging": "^0.1.0",
|
|
62
|
-
"@qvac/rag": "^0.
|
|
62
|
+
"@qvac/rag": "^0.1.0",
|
|
63
63
|
"@qvac/transcription-whispercpp": "^0.1.4",
|
|
64
64
|
"@qvac/translation-nmtcpp": "^0.1.0",
|
|
65
65
|
"fast-safe-stringify": "2.1.1",
|
|
@@ -126,4 +126,4 @@
|
|
|
126
126
|
"patchedDependencies": {
|
|
127
127
|
"bare-rpc@0.2.11": "patches/bare-rpc@0.2.11.patch"
|
|
128
128
|
}
|
|
129
|
-
}
|
|
129
|
+
}
|