@qvac/sdk 0.9.1 → 0.10.0
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/NOTICE +15 -68
- package/dist/client/api/cancel.d.ts +1 -1
- package/dist/client/api/cancel.js +1 -1
- package/dist/client/api/completion-stream.d.ts +51 -12
- package/dist/client/api/completion-stream.js +129 -56
- package/dist/client/api/delete-cache.d.ts +1 -0
- package/dist/client/api/delete-cache.js +1 -0
- package/dist/client/api/diffusion.d.ts +17 -2
- package/dist/client/api/diffusion.js +21 -4
- package/dist/client/api/embed.d.ts +4 -0
- package/dist/client/api/finetune.d.ts +21 -0
- package/dist/client/api/get-loaded-model-info.d.ts +25 -0
- package/dist/client/api/get-loaded-model-info.js +36 -0
- package/dist/client/api/get-model-info.d.ts +9 -1
- package/dist/client/api/get-model-info.js +8 -0
- package/dist/client/api/heartbeat.d.ts +2 -2
- package/dist/client/api/heartbeat.js +2 -2
- package/dist/client/api/index.d.ts +3 -1
- package/dist/client/api/index.js +3 -1
- package/dist/client/api/invoke-plugin.d.ts +16 -0
- package/dist/client/api/invoke-plugin.js +16 -0
- package/dist/client/api/load-model.d.ts +36 -3
- package/dist/client/api/load-model.js +31 -10
- package/dist/client/api/provide.d.ts +11 -5
- package/dist/client/api/provide.js +11 -6
- package/dist/client/api/rag.d.ts +9 -0
- package/dist/client/api/rag.js +9 -0
- package/dist/client/api/registry.d.ts +26 -0
- package/dist/client/api/registry.js +26 -0
- package/dist/client/api/resume.d.ts +20 -4
- package/dist/client/api/resume.js +20 -4
- package/dist/client/api/state.d.ts +23 -0
- package/dist/client/api/state.js +29 -0
- package/dist/client/api/stop-provider.d.ts +11 -5
- package/dist/client/api/stop-provider.js +11 -5
- package/dist/client/api/suspend.d.ts +21 -3
- package/dist/client/api/suspend.js +21 -3
- package/dist/client/api/text-to-speech.d.ts +64 -6
- package/dist/client/api/text-to-speech.js +423 -47
- package/dist/client/api/transcribe.d.ts +29 -4
- package/dist/client/api/transcribe.js +86 -28
- package/dist/client/api/translate.d.ts +1 -0
- package/dist/client/api/translate.js +1 -0
- package/dist/client/rpc/bare-client.js +22 -1
- package/dist/client/rpc/expo-rpc-client.d.ts +1 -1
- package/dist/client/rpc/expo-rpc-client.js +96 -4
- package/dist/client/rpc/node-rpc-client.js +36 -0
- package/dist/examples/audio/mic-input.d.ts +9 -0
- package/dist/examples/audio/mic-input.js +111 -0
- package/dist/examples/completion-events.d.ts +18 -0
- package/dist/examples/completion-events.js +79 -0
- package/dist/examples/delegated-inference/composite.js +12 -18
- package/dist/examples/delegated-inference/consumer-profiled.js +4 -11
- package/dist/examples/delegated-inference/consumer.js +8 -13
- package/dist/examples/delegated-inference/provider.js +11 -16
- package/dist/examples/diffusion-flux2-klein-img2img.d.ts +2 -0
- package/dist/examples/diffusion-flux2-klein-img2img.js +60 -0
- package/dist/examples/diffusion-flux2-klein.js +1 -0
- package/dist/examples/diffusion-img2img.d.ts +2 -0
- package/dist/examples/diffusion-img2img.js +49 -0
- package/dist/examples/diffusion-txt2img.js +2 -1
- package/dist/examples/kv-cache-example.js +11 -12
- package/dist/examples/llamacpp-cache.d.ts +2 -0
- package/dist/examples/llamacpp-cache.js +107 -0
- package/dist/examples/llamacpp-dynamic-tools.d.ts +2 -0
- package/dist/examples/llamacpp-dynamic-tools.js +144 -0
- package/dist/examples/llamacpp-native-tools.js +2 -8
- package/dist/examples/llamacpp-structured-output.d.ts +2 -0
- package/dist/examples/llamacpp-structured-output.js +106 -0
- package/dist/examples/llamacpp-tools-pythonic.d.ts +2 -0
- package/dist/examples/llamacpp-tools-pythonic.js +69 -0
- package/dist/examples/plugins.js +4 -4
- package/dist/examples/suspend-resume.js +21 -4
- package/dist/examples/transcription/parakeet-microphone-record.js +6 -33
- package/dist/examples/transcription/whispercpp-filesystem-streaming.js +7 -5
- package/dist/examples/transcription/whispercpp-filesystem.js +12 -3
- package/dist/examples/transcription/whispercpp-microphone-record.js +6 -29
- package/dist/examples/translation/translation-stream.js +5 -5
- package/dist/examples/tts/llm-to-tts-streaming.d.ts +16 -0
- package/dist/examples/tts/llm-to-tts-streaming.js +143 -0
- package/dist/examples/tts/supertonic-multilingual.js +3 -3
- package/dist/examples/tts/supertonic.js +3 -3
- package/dist/examples/tts/utils.d.ts +11 -1
- package/dist/examples/tts/utils.js +70 -17
- package/dist/examples/voice-assistant/voice-assistant.d.ts +2 -0
- package/dist/examples/voice-assistant/voice-assistant.js +207 -0
- package/dist/expo/plugins/withMobileBundle.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/logging/logger.d.ts +11 -0
- package/dist/logging/logger.js +11 -0
- package/dist/logging/types.d.ts +18 -0
- package/dist/models/registry/models.d.ts +6620 -6185
- package/dist/models/registry/models.js +6296 -5318
- package/dist/models/update-models/codegen.js +84 -23
- package/dist/models/update-models/companions.d.ts +18 -0
- package/dist/models/update-models/companions.js +175 -0
- package/dist/models/update-models/naming.js +0 -25
- package/dist/models/update-models/registry.js +4 -2
- package/dist/models/update-models/types.d.ts +37 -9
- package/dist/profiling/index.d.ts +49 -0
- package/dist/profiling/index.js +49 -0
- package/dist/schemas/cancel.d.ts +6 -2
- package/dist/schemas/cancel.js +14 -7
- package/dist/schemas/common.d.ts +361 -279
- package/dist/schemas/common.js +26 -5
- package/dist/schemas/completion-event.d.ts +225 -0
- package/dist/schemas/completion-event.js +79 -0
- package/dist/schemas/completion-stream.d.ts +122 -31
- package/dist/schemas/completion-stream.js +137 -36
- package/dist/schemas/delegate.d.ts +0 -2
- package/dist/schemas/delegate.js +25 -6
- package/dist/schemas/download-asset.d.ts +5 -5
- package/dist/schemas/embed.js +21 -9
- package/dist/schemas/engine-addon-map.d.ts +11 -1
- package/dist/schemas/engine-addon-map.js +2 -2
- package/dist/schemas/finetune.d.ts +16 -16
- package/dist/schemas/finetune.js +8 -8
- package/dist/schemas/get-loaded-model-info.d.ts +52 -0
- package/dist/schemas/get-loaded-model-info.js +44 -0
- package/dist/schemas/get-model-info.d.ts +2 -2
- package/dist/schemas/get-model-info.js +103 -32
- package/dist/schemas/heartbeat.d.ts +0 -1
- package/dist/schemas/index.d.ts +4 -1
- package/dist/schemas/index.js +4 -1
- package/dist/schemas/llamacpp-config.d.ts +14 -4
- package/dist/schemas/llamacpp-config.js +5 -0
- package/dist/schemas/load-model.d.ts +3233 -1260
- package/dist/schemas/load-model.js +23 -16
- package/dist/schemas/model-src-utils.d.ts +7 -6
- package/dist/schemas/model-src-utils.js +27 -1
- package/dist/schemas/model-types.d.ts +4 -4
- package/dist/schemas/ocr.d.ts +1 -1
- package/dist/schemas/plugin.d.ts +27 -3
- package/dist/schemas/plugin.js +27 -2
- package/dist/schemas/profiling.js +11 -3
- package/dist/schemas/provide.d.ts +1 -3
- package/dist/schemas/provide.js +0 -3
- package/dist/schemas/rag.d.ts +4 -4
- package/dist/schemas/registry.d.ts +10 -10
- package/dist/schemas/registry.js +36 -14
- package/dist/schemas/reload-config.d.ts +73 -7
- package/dist/schemas/sdcpp-config.d.ts +16 -8
- package/dist/schemas/sdcpp-config.js +118 -25
- package/dist/schemas/sdk-config.d.ts +116 -90
- package/dist/schemas/sdk-config.js +16 -0
- package/dist/schemas/sdk-errors-client.d.ts +3 -0
- package/dist/schemas/sdk-errors-client.js +16 -1
- package/dist/schemas/sdk-errors-server.d.ts +3 -0
- package/dist/schemas/sdk-errors-server.js +23 -0
- package/dist/schemas/state.d.ts +23 -0
- package/dist/schemas/state.js +14 -0
- package/dist/schemas/stop-provide.d.ts +0 -5
- package/dist/schemas/stop-provide.js +2 -6
- package/dist/schemas/text-to-speech.d.ts +93 -27
- package/dist/schemas/text-to-speech.js +27 -0
- package/dist/schemas/tools.d.ts +16 -0
- package/dist/schemas/tools.js +15 -0
- package/dist/schemas/transcription-config.d.ts +8 -8
- package/dist/schemas/transcription.d.ts +33 -0
- package/dist/schemas/transcription.js +9 -0
- package/dist/schemas/translate.js +59 -19
- package/dist/schemas/translation-config.d.ts +157 -133
- package/dist/schemas/translation-config.js +34 -11
- package/dist/server/bare/delegate-rpc-client.d.ts +1 -1
- package/dist/server/bare/delegate-rpc-client.js +131 -122
- package/dist/server/bare/hyperswarm.d.ts +2 -2
- package/dist/server/bare/hyperswarm.js +12 -7
- package/dist/server/bare/ops/cancel.js +7 -0
- package/dist/server/bare/ops/kv-cache-utils.d.ts +7 -10
- package/dist/server/bare/ops/kv-cache-utils.js +31 -40
- package/dist/server/bare/ops/load-model.js +0 -1
- package/dist/server/bare/ops/transcribe.d.ts +11 -4
- package/dist/server/bare/ops/transcribe.js +25 -4
- package/dist/server/bare/ops/translate.js +42 -4
- package/dist/server/bare/ops/unload-model.js +21 -19
- package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +1 -2
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +13 -8
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +257 -85
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +101 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +135 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +83 -26
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +57 -32
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -16
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +69 -44
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +113 -94
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +1 -1
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +1 -2
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.d.ts +7 -0
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.js +116 -0
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +2 -3
- package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +71 -9
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +41 -13
- package/dist/server/bare/plugins/onnx-tts/plugin.js +48 -3
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +15 -7
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +5 -6
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +6 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +8 -5
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +13 -13
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +17 -1
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +40 -17
- package/dist/server/bare/registry/config-registry.js +14 -3
- package/dist/server/bare/registry/model-registry.d.ts +8 -10
- package/dist/server/bare/registry/model-registry.js +17 -12
- package/dist/server/bare/registry/registry-client.js +79 -19
- package/dist/server/bare/runtime-lifecycle.d.ts +2 -1
- package/dist/server/bare/runtime-lifecycle.js +13 -2
- package/dist/server/bare/types/addon-responses.d.ts +8 -3
- package/dist/server/bare/utils/transcribe-metadata.d.ts +21 -0
- package/dist/server/bare/utils/transcribe-metadata.js +28 -0
- package/dist/server/bare/utils/tts-stats.d.ts +22 -0
- package/dist/server/bare/utils/tts-stats.js +10 -0
- package/dist/server/rpc/create-server.d.ts +4 -1
- package/dist/server/rpc/create-server.js +5 -1
- package/dist/server/rpc/delegate-transport.js +36 -29
- package/dist/server/rpc/handle-request.js +28 -3
- package/dist/server/rpc/handler-registry.js +7 -1
- package/dist/server/rpc/handler-utils.d.ts +5 -0
- package/dist/server/rpc/handler-utils.js +22 -0
- package/dist/server/rpc/handlers/cancel-delegated.js +3 -5
- package/dist/server/rpc/handlers/cancelHandler.js +4 -5
- package/dist/server/rpc/handlers/completion-stream-delegated.js +14 -5
- package/dist/server/rpc/handlers/delete-cache.js +8 -3
- package/dist/server/rpc/handlers/download-asset.js +3 -24
- package/dist/server/rpc/handlers/get-loaded-model-info.d.ts +3 -0
- package/dist/server/rpc/handlers/get-loaded-model-info.js +39 -0
- package/dist/server/rpc/handlers/get-model-info.js +93 -84
- package/dist/server/rpc/handlers/heartbeat-delegated.js +2 -2
- package/dist/server/rpc/handlers/index.d.ts +6 -0
- package/dist/server/rpc/handlers/index.js +6 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +35 -9
- package/dist/server/rpc/handlers/load-model/download-manager.js +142 -38
- package/dist/server/rpc/handlers/load-model/download-stats.d.ts +5 -4
- package/dist/server/rpc/handlers/load-model/download-stats.js +49 -8
- package/dist/server/rpc/handlers/load-model/handler.js +31 -50
- package/dist/server/rpc/handlers/load-model/http.d.ts +2 -2
- package/dist/server/rpc/handlers/load-model/http.js +97 -142
- package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -2
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +55 -74
- package/dist/server/rpc/handlers/load-model/index.d.ts +0 -1
- package/dist/server/rpc/handlers/load-model/index.js +0 -1
- package/dist/server/rpc/handlers/load-model/registry-client-options.d.ts +27 -0
- package/dist/server/rpc/handlers/load-model/registry-client-options.js +19 -0
- package/dist/server/rpc/handlers/load-model/registry-companion-set.d.ts +22 -0
- package/dist/server/rpc/handlers/load-model/registry-companion-set.js +208 -0
- package/dist/server/rpc/handlers/load-model/registry-download-utils.d.ts +24 -0
- package/dist/server/rpc/handlers/load-model/registry-download-utils.js +114 -0
- package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -20
- package/dist/server/rpc/handlers/load-model/registry.js +109 -381
- package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +15 -0
- package/dist/server/rpc/handlers/load-model/resolve-session.js +61 -0
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -3
- package/dist/server/rpc/handlers/load-model/resolve.js +14 -23
- package/dist/server/rpc/handlers/load-model/types.d.ts +11 -4
- package/dist/server/rpc/handlers/load-model/types.js +28 -1
- package/dist/server/rpc/handlers/load-model-delegated.js +2 -4
- package/dist/server/rpc/handlers/plugin-dispatch.js +9 -5
- package/dist/server/rpc/handlers/plugin-invoke.js +1 -1
- package/dist/server/rpc/handlers/provideHandler/connection.js +13 -2
- package/dist/server/rpc/handlers/provideHandler/handler.js +42 -29
- package/dist/server/rpc/handlers/state.d.ts +3 -0
- package/dist/server/rpc/handlers/state.js +7 -0
- package/dist/server/rpc/handlers/stopProvideHandler.d.ts +2 -2
- package/dist/server/rpc/handlers/stopProvideHandler.js +12 -7
- package/dist/server/rpc/handlers/text-to-speech-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/text-to-speech-stream.js +4 -0
- package/dist/server/rpc/handlers/unload-model-delegated.js +3 -3
- package/dist/server/rpc/profiling/operation-metrics.js +20 -0
- package/dist/server/rpc/rpc-utils.js +1 -1
- package/dist/server/rpc/transport-selector.d.ts +3 -0
- package/dist/server/rpc/transport-selector.js +18 -0
- package/dist/server/utils/cache/auto-history.d.ts +4 -0
- package/dist/server/utils/cache/auto-history.js +22 -0
- package/dist/server/utils/{cache.d.ts → cache/paths.d.ts} +22 -5
- package/dist/server/utils/{cache.js → cache/paths.js} +36 -20
- package/dist/server/utils/cache/types.d.ts +8 -0
- package/dist/server/utils/cache/types.js +1 -0
- package/dist/server/utils/checksum.d.ts +2 -2
- package/dist/server/utils/checksum.js +1 -1
- package/dist/server/utils/clear-storage.d.ts +5 -0
- package/dist/server/utils/clear-storage.js +17 -0
- package/dist/server/utils/completion-normalizer.d.ts +17 -0
- package/dist/server/utils/completion-normalizer.js +301 -0
- package/dist/server/utils/expand-gguf-shards.d.ts +3 -0
- package/dist/server/utils/expand-gguf-shards.js +22 -0
- package/dist/server/utils/formatting.js +1 -1
- package/dist/server/utils/index.d.ts +4 -2
- package/dist/server/utils/index.js +4 -2
- package/dist/server/utils/qvac-paths.d.ts +2 -0
- package/dist/server/utils/qvac-paths.js +5 -0
- package/dist/server/utils/response-format.d.ts +3 -0
- package/dist/server/utils/response-format.js +20 -0
- package/dist/server/utils/tool-integration.d.ts +15 -4
- package/dist/server/utils/tool-integration.js +21 -41
- package/dist/server/utils/tools/dialect.d.ts +8 -0
- package/dist/server/utils/tools/dialect.js +12 -0
- package/dist/server/utils/tools/index.d.ts +3 -0
- package/dist/server/utils/tools/index.js +2 -0
- package/dist/server/utils/tools/parser.d.ts +6 -0
- package/dist/server/utils/tools/parser.js +40 -0
- package/dist/server/utils/tools/parsers/hermes.d.ts +4 -0
- package/dist/server/utils/tools/parsers/hermes.js +100 -0
- package/dist/server/utils/tools/parsers/json.d.ts +6 -0
- package/dist/server/utils/tools/parsers/json.js +115 -0
- package/dist/server/utils/tools/parsers/pythonic.d.ts +4 -0
- package/dist/server/utils/tools/parsers/pythonic.js +267 -0
- package/dist/server/utils/tools/shared.d.ts +18 -0
- package/dist/server/utils/tools/shared.js +54 -0
- package/dist/server/utils/worker-lock.d.ts +3 -0
- package/dist/server/utils/worker-lock.js +67 -0
- package/dist/server/worker-core.d.ts +16 -1
- package/dist/server/worker-core.js +114 -14
- package/dist/utils/aggregate-events.d.ts +16 -0
- package/dist/utils/aggregate-events.js +52 -0
- package/dist/utils/cache-normalize.d.ts +10 -0
- package/dist/utils/cache-normalize.js +23 -0
- package/dist/utils/encoding.d.ts +8 -0
- package/dist/utils/encoding.js +13 -0
- package/dist/utils/errors-client.d.ts +12 -0
- package/dist/utils/errors-client.js +20 -0
- package/dist/utils/errors-server.d.ts +14 -0
- package/dist/utils/errors-server.js +31 -0
- package/dist/utils/load-model-validation.d.ts +7 -0
- package/dist/utils/load-model-validation.js +18 -0
- package/expo/plugins/patches/android-link.mjs +1 -1
- package/expo/plugins/patches/ios-link.mjs +1 -1
- package/package.json +15 -19
- package/dist/examples/translation/translation-opus.d.ts +0 -2
- package/dist/examples/translation/translation-opus.js +0 -33
- package/dist/server/bare/utils/loader-adapter.d.ts +0 -7
- package/dist/server/bare/utils/loader-adapter.js +0 -9
- package/dist/server/utils/model-path.d.ts +0 -5
- package/dist/server/utils/model-path.js +0 -7
- package/dist/server/utils/tool-parser.d.ts +0 -7
- package/dist/server/utils/tool-parser.js +0 -248
|
@@ -2,16 +2,14 @@ import { spawn } from "child_process";
|
|
|
2
2
|
import { join, dirname } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { completion, loadModel, close, LLAMA_3_2_1B_INST_Q4_0, } from "@qvac/sdk";
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
const
|
|
9
|
-
const PROVIDER_STARTUP_TIMEOUT_MS = 30_000;
|
|
5
|
+
// The consumer connects to the provider directly via its public key over the
|
|
6
|
+
// DHT (`dht.connect(publicKey)`). No topic or discovery step is involved —
|
|
7
|
+
// the provider just needs its DHT server listening on its keyPair.
|
|
8
|
+
const PROVIDER_STARTUP_TIMEOUT_MS = 60_000;
|
|
10
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
10
|
const providerScript = join(__dirname, "provider.ts");
|
|
12
|
-
// ── Provider lifecycle ──────────────────────────────────────────────
|
|
13
11
|
function spawnProviderProcess() {
|
|
14
|
-
const child = spawn("bun", ["run", providerScript
|
|
12
|
+
const child = spawn("bun", ["run", providerScript], {
|
|
15
13
|
stdio: ["pipe", "pipe", "pipe"],
|
|
16
14
|
});
|
|
17
15
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -25,9 +23,9 @@ function terminateProvider(provider) {
|
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
25
|
// The provider's Hyperswarm identity (and therefore its public key) is
|
|
28
|
-
// generated at startup — it can't be known ahead of time. We parse it
|
|
29
|
-
//
|
|
30
|
-
// "🆔 Provider Public Key
|
|
26
|
+
// generated at startup — it can't be known ahead of time. We parse it from
|
|
27
|
+
// the provider's stdout where it prints:
|
|
28
|
+
// "🆔 Provider Public Key: <hex>"
|
|
31
29
|
function waitForProviderPublicKey(provider) {
|
|
32
30
|
return new Promise((resolve, reject) => {
|
|
33
31
|
let output = "";
|
|
@@ -38,7 +36,7 @@ function waitForProviderPublicKey(provider) {
|
|
|
38
36
|
const str = chunk.toString();
|
|
39
37
|
output += str;
|
|
40
38
|
process.stdout.write(str);
|
|
41
|
-
const match = output.match(/Provider Public Key
|
|
39
|
+
const match = output.match(/Provider Public Key: ([a-f0-9]+)/i);
|
|
42
40
|
if (match) {
|
|
43
41
|
clearTimeout(timeout);
|
|
44
42
|
resolve(match[1]);
|
|
@@ -54,14 +52,12 @@ function waitForProviderPublicKey(provider) {
|
|
|
54
52
|
});
|
|
55
53
|
});
|
|
56
54
|
}
|
|
57
|
-
|
|
58
|
-
async function runDelegatedCompletion(topic, providerPublicKey) {
|
|
55
|
+
async function runDelegatedCompletion(providerPublicKey) {
|
|
59
56
|
console.log("→ Loading model via delegation...");
|
|
60
57
|
const modelId = await loadModel({
|
|
61
58
|
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
62
59
|
modelType: "llm",
|
|
63
60
|
delegate: {
|
|
64
|
-
topic,
|
|
65
61
|
providerPublicKey,
|
|
66
62
|
timeout: 30_000,
|
|
67
63
|
},
|
|
@@ -83,14 +79,12 @@ async function runDelegatedCompletion(topic, providerPublicKey) {
|
|
|
83
79
|
const stats = await response.stats;
|
|
84
80
|
console.log(`\n📊 Stats: ${JSON.stringify(stats)}`);
|
|
85
81
|
}
|
|
86
|
-
// ── Main ────────────────────────────────────────────────────────────
|
|
87
82
|
const provider = spawnProviderProcess();
|
|
88
83
|
try {
|
|
89
84
|
console.log("🔧 Waiting for provider to start and announce its key...\n");
|
|
90
85
|
const publicKey = await waitForProviderPublicKey(provider);
|
|
91
|
-
console.log(`\n📡 Provider ready — key: ${publicKey}`);
|
|
92
|
-
|
|
93
|
-
await runDelegatedCompletion(TOPIC, publicKey);
|
|
86
|
+
console.log(`\n📡 Provider ready — key: ${publicKey}\n`);
|
|
87
|
+
await runDelegatedCompletion(publicKey);
|
|
94
88
|
void close();
|
|
95
89
|
}
|
|
96
90
|
finally {
|
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { close, completion, LLAMA_3_2_1B_INST_Q4_0, loadModel, profiler, } from "@qvac/sdk";
|
|
2
|
-
const
|
|
3
|
-
if (!topicHex) {
|
|
4
|
-
console.error("❌ Usage: bun run consumer-profiled.ts <topic> <publicKey>");
|
|
5
|
-
process.exit(1);
|
|
6
|
-
}
|
|
7
|
-
const providerPublicKey = process.argv[3];
|
|
2
|
+
const providerPublicKey = process.argv[2];
|
|
8
3
|
if (!providerPublicKey) {
|
|
9
|
-
console.error("❌ Usage: bun run consumer-profiled.ts <
|
|
4
|
+
console.error("❌ Usage: bun run consumer-profiled.ts <providerPublicKey>");
|
|
10
5
|
process.exit(1);
|
|
11
6
|
}
|
|
12
7
|
try {
|
|
13
8
|
profiler.enable({ mode: "verbose", includeServerBreakdown: true });
|
|
14
9
|
console.log("✓ Profiler enabled");
|
|
15
|
-
console.log(`\n
|
|
16
|
-
console.log(`🔑 Provider: ${providerPublicKey}\n`);
|
|
10
|
+
console.log(`\n🔑 Provider: ${providerPublicKey}\n`);
|
|
17
11
|
console.log("→ Loading model (delegated, unary)...");
|
|
18
12
|
const modelId = await loadModel({
|
|
19
13
|
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
20
14
|
modelType: "llm",
|
|
21
15
|
delegate: {
|
|
22
|
-
topic: topicHex,
|
|
23
16
|
providerPublicKey,
|
|
24
|
-
timeout:
|
|
17
|
+
timeout: 60_000,
|
|
25
18
|
},
|
|
26
19
|
});
|
|
27
20
|
console.log(`✓ Model loaded: ${modelId}\n`);
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { completion, LLAMA_3_2_1B_INST_Q4_0, loadModel, close, } from "@qvac/sdk";
|
|
2
|
-
|
|
3
|
-
const topicHex = process.argv[2];
|
|
4
|
-
if (!topicHex) {
|
|
5
|
-
console.error("❌ Topic hex is required. Usage: node consumer.ts <topic-hex> <provider-public-key> [consumer-seed]");
|
|
6
|
-
process.exit(1);
|
|
7
|
-
}
|
|
8
|
-
// Provider public key (required)
|
|
9
|
-
const providerPublicKey = process.argv[3];
|
|
2
|
+
const providerPublicKey = process.argv[2];
|
|
10
3
|
if (!providerPublicKey) {
|
|
11
|
-
console.error("❌ Provider public key is required. Usage: node consumer.ts <
|
|
4
|
+
console.error("❌ Provider public key is required. Usage: node consumer.ts <provider-public-key> [consumer-seed]");
|
|
12
5
|
process.exit(1);
|
|
13
6
|
}
|
|
14
7
|
try {
|
|
15
8
|
// Optional: Consumer seed for deterministic consumer identity (for firewall testing)
|
|
16
|
-
const consumerSeed = process.argv[
|
|
9
|
+
const consumerSeed = process.argv[3];
|
|
17
10
|
process.env["QVAC_HYPERSWARM_SEED"] = consumerSeed;
|
|
18
11
|
console.log(`🚀 Testing delegated inference`);
|
|
19
|
-
console.log(`📡 Topic: ${topicHex}`);
|
|
20
12
|
console.log(`🔑 Provider: ${providerPublicKey}`);
|
|
21
13
|
if (consumerSeed) {
|
|
22
14
|
console.log(`🔑 Consumer seed: ${consumerSeed.substring(0, 16)}... (deterministic identity)`);
|
|
@@ -28,9 +20,12 @@ try {
|
|
|
28
20
|
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
29
21
|
modelType: "llm",
|
|
30
22
|
delegate: {
|
|
31
|
-
topic: topicHex,
|
|
32
23
|
providerPublicKey,
|
|
33
|
-
timeout
|
|
24
|
+
// Generous timeout for the first call on a cold DHT: bootstrapping
|
|
25
|
+
// hyperdht and looking up the provider's key can take 15–45s on the
|
|
26
|
+
// very first run. Subsequent connections in the same process are
|
|
27
|
+
// sub-second because the DHT is already warm.
|
|
28
|
+
timeout: 60_000,
|
|
34
29
|
fallbackToLocal: true, // Optional: Fall back to local inference if delegation fails
|
|
35
30
|
// forceNewConnection: true, // Optional: Force a new connection instead of reusing cached one
|
|
36
31
|
},
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { startQVACProvider } from "@qvac/sdk";
|
|
2
|
-
// Random topic if not provided
|
|
3
|
-
const topic = process.argv[2] ||
|
|
4
|
-
"66646f696865726f6569686a726530776a66646f696865726f6569686a726530";
|
|
5
2
|
// Optional: Seed for deterministic provider identity (64-character hex string)
|
|
6
|
-
const seed = process.argv[
|
|
7
|
-
|
|
3
|
+
const seed = process.argv[2];
|
|
4
|
+
if (seed) {
|
|
5
|
+
process.env["QVAC_HYPERSWARM_SEED"] = seed;
|
|
6
|
+
}
|
|
8
7
|
// Optional: Consumer public key for firewall (allow only this consumer)
|
|
9
|
-
const allowedConsumerPublicKey = process.argv[
|
|
10
|
-
console.log(`🚀 Starting provider service
|
|
8
|
+
const allowedConsumerPublicKey = process.argv[3];
|
|
9
|
+
console.log(`🚀 Starting provider service...`);
|
|
11
10
|
try {
|
|
12
11
|
if (allowedConsumerPublicKey) {
|
|
13
12
|
console.log(`🔒 Firewall enabled: only allowing consumer ${allowedConsumerPublicKey}`);
|
|
14
13
|
}
|
|
15
|
-
// Start the provider service with optional firewall and seed
|
|
16
14
|
const response = await startQVACProvider({
|
|
17
|
-
topic,
|
|
18
15
|
firewall: allowedConsumerPublicKey
|
|
19
16
|
? {
|
|
20
17
|
mode: "allow",
|
|
@@ -26,14 +23,13 @@ try {
|
|
|
26
23
|
console.log("🔗 Provider is now available for delegated inference requests");
|
|
27
24
|
console.log("");
|
|
28
25
|
console.log("📋 Connection Details:");
|
|
29
|
-
console.log(`
|
|
30
|
-
console.log(` 🆔 Provider Public Key (unique): ${response.publicKey}`);
|
|
26
|
+
console.log(` 🆔 Provider Public Key: ${response.publicKey}`);
|
|
31
27
|
console.log("");
|
|
32
28
|
console.log("💡 Consumer command:");
|
|
33
|
-
console.log(` node consumer.ts ${
|
|
29
|
+
console.log(` node consumer.ts ${response.publicKey}`);
|
|
34
30
|
console.log("");
|
|
35
31
|
console.log("💡 To reproduce this provider identity:");
|
|
36
|
-
console.log(` node provider.ts ${
|
|
32
|
+
console.log(` node provider.ts ${seed || "<random-seed>"}`);
|
|
37
33
|
if (!seed) {
|
|
38
34
|
console.log(" (Note: seed was random this time, set one for reproducible identity)");
|
|
39
35
|
}
|
|
@@ -41,9 +37,8 @@ try {
|
|
|
41
37
|
console.log("🔒 For firewall testing:");
|
|
42
38
|
console.log(" 1. Generate a consumer seed (64-char hex)");
|
|
43
39
|
console.log(" 2. Get consumer public key: getConsumerPublicKey(consumerSeed)");
|
|
44
|
-
console.log(" 3. Restart provider with consumer public key as
|
|
45
|
-
console.log(` 4. Run consumer with: node consumer.ts ${
|
|
46
|
-
// Keep the process running
|
|
40
|
+
console.log(" 3. Restart provider with consumer public key as 2nd argument");
|
|
41
|
+
console.log(` 4. Run consumer with: node consumer.ts ${response.publicKey} <consumer-seed>`);
|
|
47
42
|
console.log("📡 Provider is running... Press Ctrl+C to stop");
|
|
48
43
|
process.on("SIGINT", () => {
|
|
49
44
|
console.log("\n🛑 Provider service stopped");
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { loadModel, unloadModel, diffusion, FLUX_2_KLEIN_4B_Q4_0, FLUX_2_KLEIN_4B_VAE, QWEN3_4B_Q4_K_M, } from "@qvac/sdk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
// img2img with FLUX.2 [klein] split-layout — uses in-context conditioning ("flux2_flow").
|
|
5
|
+
const inputPath = process.argv[2];
|
|
6
|
+
const prompt = process.argv[3] || "oil painting style, vibrant colors";
|
|
7
|
+
const outputDir = process.argv[4] || ".";
|
|
8
|
+
const diffusionModelSrc = process.argv[5] || FLUX_2_KLEIN_4B_Q4_0;
|
|
9
|
+
const llmModelSrc = process.argv[6] || QWEN3_4B_Q4_K_M;
|
|
10
|
+
const vaeModelSrc = process.argv[7] || FLUX_2_KLEIN_4B_VAE;
|
|
11
|
+
if (!inputPath) {
|
|
12
|
+
console.error("❌ Error: input image path is required");
|
|
13
|
+
console.error("Usage: bun run bare:example dist/examples/diffusion-flux2-klein-img2img.js <inputImage> [prompt] [outputDir] [diffusionModelSrc] [llmModelSrc] [vaeModelSrc]");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
console.log("Loading FLUX.2 [klein] split-layout model...");
|
|
18
|
+
const modelId = await loadModel({
|
|
19
|
+
modelSrc: diffusionModelSrc,
|
|
20
|
+
modelType: "diffusion",
|
|
21
|
+
modelConfig: {
|
|
22
|
+
device: "gpu",
|
|
23
|
+
threads: 4,
|
|
24
|
+
llmModelSrc,
|
|
25
|
+
vaeModelSrc,
|
|
26
|
+
prediction: "flux2_flow",
|
|
27
|
+
},
|
|
28
|
+
onProgress: (p) => console.log(`Loading: ${p.percentage.toFixed(1)}%`),
|
|
29
|
+
});
|
|
30
|
+
console.log(`Model loaded: ${modelId}`);
|
|
31
|
+
const init_image = new Uint8Array(fs.readFileSync(inputPath));
|
|
32
|
+
console.log(`\nTransforming "${inputPath}" with prompt: "${prompt}"`);
|
|
33
|
+
const { progressStream, outputs, stats } = diffusion({
|
|
34
|
+
modelId,
|
|
35
|
+
prompt,
|
|
36
|
+
init_image,
|
|
37
|
+
steps: 20,
|
|
38
|
+
guidance: 3.5,
|
|
39
|
+
cfg_scale: 1,
|
|
40
|
+
seed: -1,
|
|
41
|
+
});
|
|
42
|
+
for await (const { step, totalSteps } of progressStream) {
|
|
43
|
+
process.stdout.write(`\rStep ${step}/${totalSteps}`);
|
|
44
|
+
}
|
|
45
|
+
console.log();
|
|
46
|
+
const buffers = await outputs;
|
|
47
|
+
for (let i = 0; i < buffers.length; i++) {
|
|
48
|
+
const outputPath = path.join(outputDir, `flux2_img2img_${i}.png`);
|
|
49
|
+
fs.writeFileSync(outputPath, buffers[i]);
|
|
50
|
+
console.log(`Saved: ${outputPath}`);
|
|
51
|
+
}
|
|
52
|
+
console.log("\nStats:", await stats);
|
|
53
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
54
|
+
console.log("Done.");
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error("❌ Error:", error);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { loadModel, unloadModel, diffusion, SD_V2_1_1B_Q8_0 } from "@qvac/sdk";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
// img2img example — transforms an input image guided by a text prompt.
|
|
5
|
+
const inputPath = process.argv[2];
|
|
6
|
+
const prompt = process.argv[3] || "oil painting style, vibrant colors";
|
|
7
|
+
const outputDir = process.argv[4] || ".";
|
|
8
|
+
const modelSrc = process.argv[5] || SD_V2_1_1B_Q8_0;
|
|
9
|
+
if (!inputPath) {
|
|
10
|
+
console.error("❌ Error: input image path is required");
|
|
11
|
+
console.error("Usage: bun run bare:example dist/examples/diffusion-img2img.js <inputImage> [prompt] [outputDir] [modelSrc]");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
console.log("Loading diffusion model...");
|
|
16
|
+
const modelId = await loadModel({
|
|
17
|
+
modelSrc,
|
|
18
|
+
modelType: "diffusion",
|
|
19
|
+
});
|
|
20
|
+
console.log(`Model loaded: ${modelId}`);
|
|
21
|
+
const init_image = new Uint8Array(fs.readFileSync(inputPath));
|
|
22
|
+
console.log(`\nTransforming "${inputPath}" with prompt: "${prompt}"`);
|
|
23
|
+
const { progressStream, outputs, stats } = diffusion({
|
|
24
|
+
modelId,
|
|
25
|
+
prompt,
|
|
26
|
+
init_image,
|
|
27
|
+
strength: 0.5,
|
|
28
|
+
steps: 30,
|
|
29
|
+
seed: -1,
|
|
30
|
+
});
|
|
31
|
+
for await (const { step, totalSteps } of progressStream) {
|
|
32
|
+
process.stdout.write(`\rStep ${step}/${totalSteps}`);
|
|
33
|
+
}
|
|
34
|
+
console.log();
|
|
35
|
+
const buffers = await outputs;
|
|
36
|
+
for (let i = 0; i < buffers.length; i++) {
|
|
37
|
+
const outputPath = path.join(outputDir, `img2img_${i}.png`);
|
|
38
|
+
fs.writeFileSync(outputPath, buffers[i]);
|
|
39
|
+
console.log(`Saved: ${outputPath}`);
|
|
40
|
+
}
|
|
41
|
+
console.log("\nStats:", await stats);
|
|
42
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
43
|
+
console.log("Done.");
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error("❌ Error:", error);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
@@ -11,8 +11,8 @@ try {
|
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
13
|
console.log("🧠 Testing KV Cache functionality...\n");
|
|
14
|
-
// First conversation with cache enabled
|
|
15
|
-
console.log("📝 First conversation (building cache):");
|
|
14
|
+
// First conversation with auto-keyed cache enabled
|
|
15
|
+
console.log("📝 First conversation (building cache for the next turn):");
|
|
16
16
|
const history1 = [
|
|
17
17
|
{ role: "user", content: "What is the capital of France?" },
|
|
18
18
|
];
|
|
@@ -22,24 +22,23 @@ try {
|
|
|
22
22
|
stream: true,
|
|
23
23
|
kvCache: true,
|
|
24
24
|
}); // kvCache = true
|
|
25
|
-
let response1 = "";
|
|
26
25
|
for await (const token of result1.tokenStream) {
|
|
27
|
-
response1 += token;
|
|
28
26
|
process.stdout.write(token);
|
|
29
27
|
}
|
|
30
|
-
const
|
|
28
|
+
const final1 = await result1.final;
|
|
29
|
+
const stats1 = final1.stats;
|
|
31
30
|
console.log(`\n⏱️ First completion stats: ${JSON.stringify(stats1)}\n`);
|
|
32
|
-
// Continue conversation (should reuse
|
|
33
|
-
console.log("🔄 Continuing conversation (reusing cache):");
|
|
31
|
+
// Continue conversation (should reuse the completed first-turn cache).
|
|
32
|
+
console.log("🔄 Continuing conversation (reusing previous turn cache):");
|
|
34
33
|
const history2 = [
|
|
35
34
|
{ role: "user", content: "What is the capital of France?" },
|
|
36
|
-
{ role: "assistant", content:
|
|
35
|
+
{ role: "assistant", content: final1.cacheableAssistantContent ?? final1.contentText },
|
|
37
36
|
{ role: "user", content: "What about Germany?" },
|
|
38
37
|
];
|
|
39
|
-
//
|
|
40
|
-
// 1. Find
|
|
41
|
-
// 2. Load that cache and process the new "What about Germany?"
|
|
42
|
-
// 3. Save the updated cache and rename it to include
|
|
38
|
+
// Auto-keyed caching should:
|
|
39
|
+
// 1. Find the cache saved after turn 1 under [user, assistant]
|
|
40
|
+
// 2. Load that cache and process only the new "What about Germany?" user turn
|
|
41
|
+
// 3. Save the updated cache and rename it to include the new assistant response
|
|
43
42
|
const result2 = completion({
|
|
44
43
|
modelId,
|
|
45
44
|
history: history2,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { completion, deleteCache, LLAMA_3_2_1B_INST_Q4_0, loadModel, unloadModel, VERBOSITY, } from "@qvac/sdk";
|
|
2
|
+
const sharedCacheKey = "llamacpp-cache-demo-shared";
|
|
3
|
+
const isolatedCacheKey = "llamacpp-cache-demo-isolated";
|
|
4
|
+
const systemPrompt = {
|
|
5
|
+
role: "system",
|
|
6
|
+
content: "You are a concise travel assistant. Keep track of the user's preferences across turns.",
|
|
7
|
+
};
|
|
8
|
+
function printStats(stats) {
|
|
9
|
+
console.log("\nPerformance Stats:", {
|
|
10
|
+
timeToFirstToken: stats?.timeToFirstToken,
|
|
11
|
+
tokensPerSecond: stats?.tokensPerSecond,
|
|
12
|
+
cacheTokens: stats?.cacheTokens,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function runCachedCompletion(params) {
|
|
16
|
+
console.log(`\n=== ${params.label} ===`);
|
|
17
|
+
console.log(`Cache key: ${params.kvCache || "disabled"}`);
|
|
18
|
+
console.log("AI Response:");
|
|
19
|
+
const result = completion({
|
|
20
|
+
modelId: params.modelId,
|
|
21
|
+
history: params.history,
|
|
22
|
+
stream: true,
|
|
23
|
+
kvCache: params.kvCache,
|
|
24
|
+
});
|
|
25
|
+
let text = "";
|
|
26
|
+
for await (const token of result.tokenStream) {
|
|
27
|
+
text += token;
|
|
28
|
+
process.stdout.write(token);
|
|
29
|
+
}
|
|
30
|
+
const stats = await result.stats;
|
|
31
|
+
printStats(stats);
|
|
32
|
+
return { text, stats };
|
|
33
|
+
}
|
|
34
|
+
let modelId;
|
|
35
|
+
try {
|
|
36
|
+
console.log("Loading llama.cpp model with cache support...");
|
|
37
|
+
modelId = await loadModel({
|
|
38
|
+
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
39
|
+
modelType: "llm",
|
|
40
|
+
modelConfig: {
|
|
41
|
+
ctx_size: 4096,
|
|
42
|
+
verbosity: VERBOSITY.ERROR,
|
|
43
|
+
},
|
|
44
|
+
onProgress: (progress) => {
|
|
45
|
+
console.log(`Loading: ${progress.percentage.toFixed(1)}%`);
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
console.log(`Model loaded successfully. Model ID: ${modelId}`);
|
|
49
|
+
await deleteCache({ kvCacheKey: sharedCacheKey });
|
|
50
|
+
await deleteCache({ kvCacheKey: isolatedCacheKey });
|
|
51
|
+
const firstUserMessage = {
|
|
52
|
+
role: "user",
|
|
53
|
+
content: "I am planning a weekend in Lisbon. I prefer museums, seafood, and walking routes. Suggest a day plan in 3 bullets.",
|
|
54
|
+
};
|
|
55
|
+
const firstTurn = await runCachedCompletion({
|
|
56
|
+
label: "Turn 1: create a named cache",
|
|
57
|
+
modelId,
|
|
58
|
+
kvCache: sharedCacheKey,
|
|
59
|
+
history: [systemPrompt, firstUserMessage],
|
|
60
|
+
});
|
|
61
|
+
await runCachedCompletion({
|
|
62
|
+
label: "Turn 2: reuse the same cache key",
|
|
63
|
+
modelId,
|
|
64
|
+
kvCache: sharedCacheKey,
|
|
65
|
+
history: [
|
|
66
|
+
systemPrompt,
|
|
67
|
+
firstUserMessage,
|
|
68
|
+
{ role: "assistant", content: firstTurn.text.trim() },
|
|
69
|
+
{
|
|
70
|
+
role: "user",
|
|
71
|
+
content: "Now revise the plan for a rainy day, but keep the same preferences.",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
await runCachedCompletion({
|
|
76
|
+
label: "Turn 3: use a different cache key for an isolated session",
|
|
77
|
+
modelId,
|
|
78
|
+
kvCache: isolatedCacheKey,
|
|
79
|
+
history: [
|
|
80
|
+
systemPrompt,
|
|
81
|
+
{
|
|
82
|
+
role: "user",
|
|
83
|
+
content: "I am planning a weekend in Berlin. I prefer nightlife and late starts. Suggest a day plan in 3 bullets.",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
console.log("\nSummary:");
|
|
88
|
+
console.log(`- Reusing "${sharedCacheKey}" keeps conversation context across turns.`);
|
|
89
|
+
console.log(`- Switching to "${isolatedCacheKey}" starts a separate cache session.`);
|
|
90
|
+
console.log('- Use deleteCache({ kvCacheKey: "your-session" }) to clear a saved session.');
|
|
91
|
+
await deleteCache({ kvCacheKey: sharedCacheKey });
|
|
92
|
+
await deleteCache({ kvCacheKey: isolatedCacheKey });
|
|
93
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (modelId) {
|
|
98
|
+
try {
|
|
99
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
100
|
+
}
|
|
101
|
+
catch (cleanupError) {
|
|
102
|
+
console.warn("⚠️ cleanup failed:", cleanupError);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
console.error("❌ Error:", error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic-tools mode example.
|
|
3
|
+
*
|
|
4
|
+
* In `dynamic` mode each user prompt can carry its own tool set: the addon
|
|
5
|
+
* anchors tools after the last user message, runs the tool-call chain, then
|
|
6
|
+
* trims the tools + chain output from the kv-cache so a later turn can ship
|
|
7
|
+
* a different tool list without poisoning the cache. Compare with
|
|
8
|
+
* `llamacpp-native-tools.ts`, which uses the default `static` mode where
|
|
9
|
+
* one shared tool set lives at the top of the session.
|
|
10
|
+
*
|
|
11
|
+
* Run with:
|
|
12
|
+
* bun run build
|
|
13
|
+
* bun run bare:example dist/examples/llamacpp-dynamic-tools.js
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { completion, loadModel, unloadModel, QWEN3_1_7B_INST_Q4, } from "@qvac/sdk";
|
|
17
|
+
const weatherSchema = z.object({
|
|
18
|
+
city: z.string().describe("City name"),
|
|
19
|
+
});
|
|
20
|
+
const horoscopeSchema = z.object({
|
|
21
|
+
sign: z.string().describe("An astrological sign, e.g. Taurus or Aquarius"),
|
|
22
|
+
});
|
|
23
|
+
const dateSchema = z.object({});
|
|
24
|
+
const toolSchemas = {
|
|
25
|
+
get_weather: weatherSchema,
|
|
26
|
+
get_horoscope: horoscopeSchema,
|
|
27
|
+
get_date: dateSchema,
|
|
28
|
+
};
|
|
29
|
+
const weatherTools = [
|
|
30
|
+
{
|
|
31
|
+
name: "get_weather",
|
|
32
|
+
description: "Get current weather for a city",
|
|
33
|
+
parameters: weatherSchema,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
const horoscopeTools = [
|
|
37
|
+
{
|
|
38
|
+
name: "get_horoscope",
|
|
39
|
+
description: "Get today's horoscope for an astrological sign",
|
|
40
|
+
parameters: horoscopeSchema,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
const dateTools = [
|
|
44
|
+
{
|
|
45
|
+
name: "get_date",
|
|
46
|
+
description: "Get today's date",
|
|
47
|
+
parameters: dateSchema,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
function executeToolCall(call) {
|
|
51
|
+
if (call.name === "get_weather") {
|
|
52
|
+
const args = call.arguments;
|
|
53
|
+
return `The weather in ${args.city} is rainy, 8°C with heavy clouds.`;
|
|
54
|
+
}
|
|
55
|
+
if (call.name === "get_horoscope") {
|
|
56
|
+
const args = call.arguments;
|
|
57
|
+
return `Horoscope for ${args.sign}: a great day for new beginnings.`;
|
|
58
|
+
}
|
|
59
|
+
if (call.name === "get_date") {
|
|
60
|
+
return new Date().toISOString().slice(0, 10);
|
|
61
|
+
}
|
|
62
|
+
return `Unknown tool: ${call.name}`;
|
|
63
|
+
}
|
|
64
|
+
async function chatTurn({ modelId, kvCache, history, tools }) {
|
|
65
|
+
const result = completion({
|
|
66
|
+
modelId,
|
|
67
|
+
history,
|
|
68
|
+
tools,
|
|
69
|
+
kvCache,
|
|
70
|
+
stream: true,
|
|
71
|
+
});
|
|
72
|
+
const tokensTask = (async () => {
|
|
73
|
+
for await (const token of result.tokenStream) {
|
|
74
|
+
process.stdout.write(token);
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
const toolEventsTask = (async () => {
|
|
78
|
+
for await (const evt of result.toolCallStream) {
|
|
79
|
+
console.log(`\n→ tool call: ${evt.call.name}(${JSON.stringify(evt.call.arguments)})`);
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
await Promise.all([tokensTask, toolEventsTask]);
|
|
83
|
+
const text = await result.text;
|
|
84
|
+
const toolCalls = await result.toolCalls;
|
|
85
|
+
if (toolCalls.length === 0) {
|
|
86
|
+
history.push({ role: "assistant", content: text });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
for (const call of toolCalls) {
|
|
90
|
+
const schema = toolSchemas[call.name];
|
|
91
|
+
if (schema) {
|
|
92
|
+
const parsed = schema.safeParse(call.arguments);
|
|
93
|
+
if (!parsed.success) {
|
|
94
|
+
console.warn(` ✗ validation failed for ${call.name}:`, parsed.error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
history.push({ role: "assistant", content: text });
|
|
99
|
+
for (const call of toolCalls) {
|
|
100
|
+
history.push({ role: "tool", content: executeToolCall(call) });
|
|
101
|
+
}
|
|
102
|
+
// Follow-up turn so the model can incorporate the tool results.
|
|
103
|
+
await chatTurn({ modelId, kvCache, history, tools });
|
|
104
|
+
}
|
|
105
|
+
async function main() {
|
|
106
|
+
const modelId = await loadModel({
|
|
107
|
+
modelSrc: QWEN3_1_7B_INST_Q4,
|
|
108
|
+
modelType: "llm",
|
|
109
|
+
modelConfig: {
|
|
110
|
+
ctx_size: 4096,
|
|
111
|
+
tools: true,
|
|
112
|
+
toolsMode: "dynamic",
|
|
113
|
+
},
|
|
114
|
+
onProgress: (progress) => console.log(`Loading: ${progress.percentage.toFixed(1)}%`),
|
|
115
|
+
});
|
|
116
|
+
console.log(`✅ Model loaded: ${modelId}`);
|
|
117
|
+
const kvCache = `dynamic-tools-${Date.now()}`;
|
|
118
|
+
const history = [
|
|
119
|
+
{
|
|
120
|
+
role: "system",
|
|
121
|
+
content: "You are a helpful assistant that uses tools when they are available. " +
|
|
122
|
+
"User's cat is named Windy and dog is named Butch.",
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
// Turn 1 — only weather tools available.
|
|
126
|
+
history.push({ role: "user", content: "What's the weather in Tokyo?" });
|
|
127
|
+
console.log("\n🤖 Turn 1 (tools=weather):\n");
|
|
128
|
+
await chatTurn({ modelId, kvCache, history, tools: weatherTools });
|
|
129
|
+
// Turn 2 — same session, swap to horoscope tools. Dynamic mode lets the
|
|
130
|
+
// model see a different tool set without invalidating the kv-cache.
|
|
131
|
+
history.push({ role: "user", content: "Now check my horoscope for Aquarius." });
|
|
132
|
+
console.log("\n\n🤖 Turn 2 (tools=horoscope):\n");
|
|
133
|
+
await chatTurn({ modelId, kvCache, history, tools: horoscopeTools });
|
|
134
|
+
// Turn 3 — swap to a parameterless tool to confirm empty-arg flows work.
|
|
135
|
+
history.push({ role: "user", content: "What's today's date?" });
|
|
136
|
+
console.log("\n\n🤖 Turn 3 (tools=date):\n");
|
|
137
|
+
await chatTurn({ modelId, kvCache, history, tools: dateTools });
|
|
138
|
+
console.log("\n\n🎉 Done.");
|
|
139
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
140
|
+
}
|
|
141
|
+
main().catch((err) => {
|
|
142
|
+
console.error("❌ Error:", err);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
});
|