@qvac/sdk 0.1.1 → 0.2.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/dist/client/api/completion-stream.d.ts +19 -4
- package/dist/client/api/completion-stream.js +19 -4
- package/dist/client/api/delete-cache.d.ts +29 -0
- package/dist/client/api/delete-cache.js +47 -0
- package/dist/client/api/index.d.ts +1 -0
- package/dist/client/api/index.js +1 -0
- package/dist/client/rpc/bare-client.d.ts +5 -0
- package/dist/client/rpc/bare-client.js +37 -1
- package/dist/examples/download-with-cancel.js +3 -3
- package/dist/examples/kv-cache-cleanup.d.ts +2 -0
- package/dist/examples/kv-cache-cleanup.js +88 -0
- package/dist/examples/kv-cache-custom-key.d.ts +2 -0
- package/dist/examples/kv-cache-custom-key.js +87 -0
- package/dist/examples/llamacpp-multimodal.js +3 -3
- package/dist/examples/rag/rag-hyperdb-workspaces.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/models/hyperdrive/models.d.ts +49 -1
- package/dist/models/hyperdrive/models.js +105 -54
- package/dist/schemas/common.d.ts +22 -6
- package/dist/schemas/common.js +3 -0
- package/dist/schemas/completion-stream.d.ts +5 -3
- package/dist/schemas/completion-stream.js +3 -2
- package/dist/schemas/delete-cache.d.ts +17 -0
- package/dist/schemas/delete-cache.js +17 -0
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/llamacpp-config.d.ts +2 -1
- package/dist/schemas/llamacpp-config.js +5 -2
- package/dist/schemas/load-model.d.ts +16 -6
- package/dist/schemas/rag.d.ts +3 -0
- package/dist/schemas/rag.js +3 -1
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +135 -53
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +13 -4
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +70 -7
- package/dist/server/bare/addons/load-model.js +1 -1
- package/dist/server/bare/registry/model-registry.d.ts +8 -1
- package/dist/server/bare/registry/model-registry.js +9 -0
- package/dist/server/rpc/handle-request.js +11 -0
- package/dist/server/rpc/handlers/completion-stream.js +31 -45
- package/dist/server/rpc/handlers/delete-cache.d.ts +3 -0
- package/dist/server/rpc/handlers/delete-cache.js +29 -0
- package/dist/server/rpc/handlers/index.d.ts +4 -0
- package/dist/server/rpc/handlers/index.js +4 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +0 -19
- package/dist/server/rpc/handlers/load-model/download-manager.js +10 -25
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +121 -80
- package/dist/server/rpc/handlers/load-model/resolve.js +8 -55
- package/package.json +6 -6
|
@@ -7,25 +7,40 @@ import { type CompletionStats, type CompletionClientParams } from "../../schemas
|
|
|
7
7
|
* @param params.history - Array of conversation messages with role, content, and optional attachments
|
|
8
8
|
* @param params.stream - Whether to stream tokens (true) or return complete response (false). Defaults to true
|
|
9
9
|
* @param params.tools - Optional array of tools that can be used by the model
|
|
10
|
-
* @param params.kvCache - Optional
|
|
10
|
+
* @param params.kvCache - Optional KV cache configuration. Cache files are organized hierarchically:
|
|
11
|
+
* - Structure: `{kvCacheKey}/{modelId}/{configHash}.bin`
|
|
12
|
+
* - The configHash includes model config + system prompt to ensure cache isolation
|
|
13
|
+
* - `true`: Auto-generate cache key based on conversation history
|
|
14
|
+
* - `"custom-key"`: Use provided string as cache key for manual session management
|
|
15
|
+
* - `false` or `undefined`: No caching
|
|
16
|
+
* - ⚡ Performance: When cache exists, only the last message is sent to the model (includes multimodal attachments)
|
|
17
|
+
* - 🗑️ Cleanup: Use `deleteCache({ kvCacheKey })` to remove cached sessions
|
|
11
18
|
* @returns Object with tokenStream generator, text promise, and stats promise
|
|
12
19
|
* @example
|
|
13
20
|
* ```typescript
|
|
14
|
-
* // Streaming mode
|
|
21
|
+
* // Streaming mode with auto-generated cache
|
|
15
22
|
* const result = completion({
|
|
16
23
|
* modelId: "llama-2",
|
|
17
24
|
* history: [
|
|
18
25
|
* { role: "user", content: "Hello, how are you?" }
|
|
19
26
|
* ],
|
|
20
27
|
* stream: true,
|
|
28
|
+
* kvCache: true, // Auto-generate cache key
|
|
21
29
|
* });
|
|
22
30
|
*
|
|
23
31
|
* for await (const token of result.tokenStream) {
|
|
24
32
|
* console.log(token);
|
|
25
33
|
* }
|
|
26
34
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
35
|
+
* // Custom session management with cache key
|
|
36
|
+
* const sessionResult = completion({
|
|
37
|
+
* modelId: "llama-2",
|
|
38
|
+
* history: [
|
|
39
|
+
* { role: "user", content: "Continue our conversation" }
|
|
40
|
+
* ],
|
|
41
|
+
* stream: true,
|
|
42
|
+
* kvCache: "user-session-123", // Custom cache key
|
|
43
|
+
* });
|
|
29
44
|
*
|
|
30
45
|
* // Non-streaming mode
|
|
31
46
|
* const response = completion({
|
|
@@ -8,25 +8,40 @@ import { stream as streamRpc } from "../rpc/rpc-client.js";
|
|
|
8
8
|
* @param params.history - Array of conversation messages with role, content, and optional attachments
|
|
9
9
|
* @param params.stream - Whether to stream tokens (true) or return complete response (false). Defaults to true
|
|
10
10
|
* @param params.tools - Optional array of tools that can be used by the model
|
|
11
|
-
* @param params.kvCache - Optional
|
|
11
|
+
* @param params.kvCache - Optional KV cache configuration. Cache files are organized hierarchically:
|
|
12
|
+
* - Structure: `{kvCacheKey}/{modelId}/{configHash}.bin`
|
|
13
|
+
* - The configHash includes model config + system prompt to ensure cache isolation
|
|
14
|
+
* - `true`: Auto-generate cache key based on conversation history
|
|
15
|
+
* - `"custom-key"`: Use provided string as cache key for manual session management
|
|
16
|
+
* - `false` or `undefined`: No caching
|
|
17
|
+
* - ⚡ Performance: When cache exists, only the last message is sent to the model (includes multimodal attachments)
|
|
18
|
+
* - 🗑️ Cleanup: Use `deleteCache({ kvCacheKey })` to remove cached sessions
|
|
12
19
|
* @returns Object with tokenStream generator, text promise, and stats promise
|
|
13
20
|
* @example
|
|
14
21
|
* ```typescript
|
|
15
|
-
* // Streaming mode
|
|
22
|
+
* // Streaming mode with auto-generated cache
|
|
16
23
|
* const result = completion({
|
|
17
24
|
* modelId: "llama-2",
|
|
18
25
|
* history: [
|
|
19
26
|
* { role: "user", content: "Hello, how are you?" }
|
|
20
27
|
* ],
|
|
21
28
|
* stream: true,
|
|
29
|
+
* kvCache: true, // Auto-generate cache key
|
|
22
30
|
* });
|
|
23
31
|
*
|
|
24
32
|
* for await (const token of result.tokenStream) {
|
|
25
33
|
* console.log(token);
|
|
26
34
|
* }
|
|
27
35
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
36
|
+
* // Custom session management with cache key
|
|
37
|
+
* const sessionResult = completion({
|
|
38
|
+
* modelId: "llama-2",
|
|
39
|
+
* history: [
|
|
40
|
+
* { role: "user", content: "Continue our conversation" }
|
|
41
|
+
* ],
|
|
42
|
+
* stream: true,
|
|
43
|
+
* kvCache: "user-session-123", // Custom cache key
|
|
44
|
+
* });
|
|
30
45
|
*
|
|
31
46
|
* // Non-streaming mode
|
|
32
47
|
* const response = completion({
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deletes KV cache files.
|
|
3
|
+
*
|
|
4
|
+
* @param params - The delete cache parameters
|
|
5
|
+
* @param params.all - If true, deletes all cache files
|
|
6
|
+
* @param params.kvCacheKey - The cache key to delete
|
|
7
|
+
* @param params.modelId - Optional: specific model ID to delete within the cache key. If not provided, deletes entire cache key.
|
|
8
|
+
* @returns Promise resolving to success status
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Delete all caches
|
|
12
|
+
* await deleteCache({ all: true });
|
|
13
|
+
*
|
|
14
|
+
* // Delete entire cache key (all models)
|
|
15
|
+
* await deleteCache({ kvCacheKey: "my-session" });
|
|
16
|
+
*
|
|
17
|
+
* // Delete only specific model within cache key
|
|
18
|
+
* await deleteCache({ kvCacheKey: "my-session", modelId: "model-abc123" });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function deleteCache(params: {
|
|
22
|
+
all: true;
|
|
23
|
+
} | {
|
|
24
|
+
kvCacheKey: string;
|
|
25
|
+
modelId?: string;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
success: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=delete-cache.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { send } from "../rpc/rpc-client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Deletes KV cache files.
|
|
4
|
+
*
|
|
5
|
+
* @param params - The delete cache parameters
|
|
6
|
+
* @param params.all - If true, deletes all cache files
|
|
7
|
+
* @param params.kvCacheKey - The cache key to delete
|
|
8
|
+
* @param params.modelId - Optional: specific model ID to delete within the cache key. If not provided, deletes entire cache key.
|
|
9
|
+
* @returns Promise resolving to success status
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Delete all caches
|
|
13
|
+
* await deleteCache({ all: true });
|
|
14
|
+
*
|
|
15
|
+
* // Delete entire cache key (all models)
|
|
16
|
+
* await deleteCache({ kvCacheKey: "my-session" });
|
|
17
|
+
*
|
|
18
|
+
* // Delete only specific model within cache key
|
|
19
|
+
* await deleteCache({ kvCacheKey: "my-session", modelId: "model-abc123" });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export async function deleteCache(params) {
|
|
23
|
+
let req;
|
|
24
|
+
if ("all" in params && params.all) {
|
|
25
|
+
req = {
|
|
26
|
+
type: "deleteCache",
|
|
27
|
+
all: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else if ("kvCacheKey" in params) {
|
|
31
|
+
req = {
|
|
32
|
+
type: "deleteCache",
|
|
33
|
+
kvCacheKey: params.kvCacheKey,
|
|
34
|
+
modelId: params.modelId,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error("Invalid deleteCache parameters");
|
|
39
|
+
}
|
|
40
|
+
const response = (await send(req));
|
|
41
|
+
if (!response.success && response.error) {
|
|
42
|
+
throw new Error(response.error);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
success: response.success,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { loadModel } from "./load-model";
|
|
2
2
|
export { downloadAsset } from "./download-asset";
|
|
3
3
|
export { completion } from "./completion-stream";
|
|
4
|
+
export { deleteCache } from "./delete-cache";
|
|
4
5
|
export { unloadModel } from "./unload-model";
|
|
5
6
|
export { loggingStream } from "./logging-stream";
|
|
6
7
|
export { ping } from "./ping";
|
package/dist/client/api/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { loadModel } from "./load-model.js";
|
|
2
2
|
export { downloadAsset } from "./download-asset.js";
|
|
3
3
|
export { completion } from "./completion-stream.js";
|
|
4
|
+
export { deleteCache } from "./delete-cache.js";
|
|
4
5
|
export { unloadModel } from "./unload-model.js";
|
|
5
6
|
export { loggingStream } from "./logging-stream.js";
|
|
6
7
|
export { ping } from "./ping.js";
|
|
@@ -11,8 +11,13 @@ export declare function stream<T extends Request>(request: T): AsyncGenerator<{
|
|
|
11
11
|
stats?: {
|
|
12
12
|
timeToFirstToken: number;
|
|
13
13
|
tokensPerSecond: number;
|
|
14
|
+
cacheTokens: number;
|
|
14
15
|
} | undefined;
|
|
15
16
|
error?: string | undefined;
|
|
17
|
+
} | {
|
|
18
|
+
type: "deleteCache";
|
|
19
|
+
success: boolean;
|
|
20
|
+
error?: string | undefined;
|
|
16
21
|
} | {
|
|
17
22
|
type: "modelProgress";
|
|
18
23
|
downloaded: number;
|
|
@@ -45,8 +45,44 @@ export async function* stream(request) {
|
|
|
45
45
|
}
|
|
46
46
|
yield* streamWithProgress();
|
|
47
47
|
}
|
|
48
|
+
else if (request.type === "downloadAsset" &&
|
|
49
|
+
"withProgress" in request &&
|
|
50
|
+
request.withProgress) {
|
|
51
|
+
async function* streamWithProgress() {
|
|
52
|
+
const queue = [];
|
|
53
|
+
let done = false;
|
|
54
|
+
const downloadAssetHandler = handler;
|
|
55
|
+
downloadAssetHandler(request, (update) => queue.push(update))
|
|
56
|
+
.then((final) => {
|
|
57
|
+
queue.push(final);
|
|
58
|
+
done = true;
|
|
59
|
+
})
|
|
60
|
+
.catch((error) => {
|
|
61
|
+
done = true;
|
|
62
|
+
throw error;
|
|
63
|
+
});
|
|
64
|
+
while (!done || queue.length > 0) {
|
|
65
|
+
if (queue.length > 0) {
|
|
66
|
+
yield queue.shift();
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
yield* streamWithProgress();
|
|
74
|
+
}
|
|
48
75
|
else {
|
|
49
|
-
|
|
76
|
+
const result = handler(request);
|
|
77
|
+
// Check if the handler returns a Promise or AsyncGenerator
|
|
78
|
+
if (Symbol.asyncIterator in result) {
|
|
79
|
+
// It's an AsyncGenerator
|
|
80
|
+
yield* result;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// It's a Promise, await and yield the single result
|
|
84
|
+
yield await result;
|
|
85
|
+
}
|
|
50
86
|
}
|
|
51
87
|
}
|
|
52
88
|
const createMockRPCRequest = () => {
|
|
@@ -12,9 +12,9 @@ try {
|
|
|
12
12
|
const totalMB = (progress.total / 1024 / 1024).toFixed(2);
|
|
13
13
|
const percentage = progress.percentage.toFixed(1);
|
|
14
14
|
console.log(`📊 Progress: ${percentage}% (${downloadedMB}MB / ${totalMB}MB)`);
|
|
15
|
-
// Example: Stops at
|
|
16
|
-
if (parseFloat(percentage) >=
|
|
17
|
-
console.log("\n🚫 Auto-cancelling at
|
|
15
|
+
// Example: Stops at 10% (or use Ctrl+C for manual stop)
|
|
16
|
+
if (parseFloat(percentage) >= 10 && !cancelled) {
|
|
17
|
+
console.log("\n🚫 Auto-cancelling at 10% for demo purposes...,");
|
|
18
18
|
console.log(`📊 Progress: ${percentage}% (${downloadedMB}MB / ${totalMB}MB)`);
|
|
19
19
|
console.log(progress);
|
|
20
20
|
cancelled = true;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { completion, deleteCache, LLAMA_3_2_1B_INST_Q4_0, loadModel, unloadModel, VERBOSITY, } from "@qvac/sdk";
|
|
2
|
+
try {
|
|
3
|
+
console.log("🧹 KV Cache Cleanup Demo\n");
|
|
4
|
+
console.log("Cache structure: {kvCacheKey}/{modelId}/{configHash}.bin\n");
|
|
5
|
+
console.log("=".repeat(70) + "\n");
|
|
6
|
+
const modelId = await loadModel({
|
|
7
|
+
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
8
|
+
modelType: "llm",
|
|
9
|
+
modelConfig: {
|
|
10
|
+
device: "gpu",
|
|
11
|
+
ctx_size: 2048,
|
|
12
|
+
verbosity: VERBOSITY.SILENT,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
// Create some cached sessions
|
|
16
|
+
const cacheKey1 = "user-alice-session";
|
|
17
|
+
const cacheKey2 = "user-bob-session";
|
|
18
|
+
console.log(`📝 Creating cache for key: "${cacheKey1}"`);
|
|
19
|
+
const result1 = completion({
|
|
20
|
+
modelId,
|
|
21
|
+
history: [{ role: "user", content: "Hello, I'm Alice!" }],
|
|
22
|
+
stream: true,
|
|
23
|
+
kvCache: cacheKey1,
|
|
24
|
+
});
|
|
25
|
+
for await (const token of result1.tokenStream) {
|
|
26
|
+
process.stdout.write(token);
|
|
27
|
+
}
|
|
28
|
+
console.log("\n✅ Cache created\n");
|
|
29
|
+
console.log(`📝 Creating cache for key: "${cacheKey2}"`);
|
|
30
|
+
const result2 = completion({
|
|
31
|
+
modelId,
|
|
32
|
+
history: [{ role: "user", content: "Hello, I'm Bob!" }],
|
|
33
|
+
stream: true,
|
|
34
|
+
kvCache: cacheKey2,
|
|
35
|
+
});
|
|
36
|
+
for await (const token of result2.tokenStream) {
|
|
37
|
+
process.stdout.write(token);
|
|
38
|
+
}
|
|
39
|
+
console.log("\n✅ Cache created\n");
|
|
40
|
+
// Now cleanup specific cache key
|
|
41
|
+
console.log("=".repeat(70));
|
|
42
|
+
console.log(`\n🗑️ Deleting cache key: "${cacheKey1}"`);
|
|
43
|
+
const deleteResult1 = await deleteCache({ kvCacheKey: cacheKey1 });
|
|
44
|
+
if (deleteResult1.success) {
|
|
45
|
+
console.log(`✅ Deleted all caches for key "${cacheKey1}"`);
|
|
46
|
+
console.log(` (Removed: ${cacheKey1}/{modelId}/{configHash}.bin)`);
|
|
47
|
+
}
|
|
48
|
+
// Delete specific model within a cache key
|
|
49
|
+
console.log(`\n🗑️ Deleting specific model in cache key: "${cacheKey2}"`);
|
|
50
|
+
const deleteResult2 = await deleteCache({
|
|
51
|
+
kvCacheKey: cacheKey2,
|
|
52
|
+
modelId: modelId,
|
|
53
|
+
});
|
|
54
|
+
if (deleteResult2.success) {
|
|
55
|
+
console.log(`✅ Deleted model "${modelId}" from cache key "${cacheKey2}"`);
|
|
56
|
+
console.log(` (Removed: ${cacheKey2}/${modelId}/)`);
|
|
57
|
+
}
|
|
58
|
+
// Try to delete non-existent cache key (should succeed silently)
|
|
59
|
+
console.log(`\n🗑️ Deleting non-existent cache key: "non-existent"`);
|
|
60
|
+
const deleteResult3 = await deleteCache({ kvCacheKey: "non-existent" });
|
|
61
|
+
if (deleteResult3.success) {
|
|
62
|
+
console.log("✅ Delete succeeded (cache key didn't exist)");
|
|
63
|
+
}
|
|
64
|
+
console.log("\n" + "=".repeat(70));
|
|
65
|
+
console.log("\n✅ CLEANUP OPTIONS:");
|
|
66
|
+
console.log("-".repeat(70));
|
|
67
|
+
console.log("\n1️⃣ Delete entire cache key (all models):");
|
|
68
|
+
console.log(' await deleteCache({ kvCacheKey: "my-session" })');
|
|
69
|
+
console.log(" └─ Removes: my-session/ (entire directory)");
|
|
70
|
+
console.log("\n2️⃣ Delete specific model within cache key:");
|
|
71
|
+
console.log(' await deleteCache({ kvCacheKey: "my-session", modelId: "model-abc" })');
|
|
72
|
+
console.log(" └─ Removes: my-session/model-abc/ (specific model directory)");
|
|
73
|
+
console.log("\n3️⃣ Delete ALL caches (entire cache folder):");
|
|
74
|
+
console.log(" await deleteCache({ all: true })");
|
|
75
|
+
console.log(" └─ Removes: ALL cache files from all sessions and models");
|
|
76
|
+
console.log("\n💡 Use Cases:");
|
|
77
|
+
console.log(" - User logout → Delete user's cache key");
|
|
78
|
+
console.log(" - Model updated → Delete old model caches");
|
|
79
|
+
console.log(" - Disk space cleanup → Delete old cache keys or all caches");
|
|
80
|
+
console.log(" - Privacy → Clear conversation history");
|
|
81
|
+
console.log(" - App reset → Delete all caches with { all: true }");
|
|
82
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error("❌ Error:", error);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { completion, deleteCache, LLAMA_3_2_1B_INST_Q4_0, loadModel, unloadModel, VERBOSITY, } from "@qvac/sdk";
|
|
2
|
+
const systemPromptMessage = {
|
|
3
|
+
role: "system",
|
|
4
|
+
content: `You are a helpful mathematician assistant.
|
|
5
|
+
But because you are in the army you have to follow these rules:
|
|
6
|
+
- If anyone ask you to do an operation you have to answer with "Sir Yes Sir!" and then give the result
|
|
7
|
+
`,
|
|
8
|
+
};
|
|
9
|
+
try {
|
|
10
|
+
console.log("🧪 Simple KV Cache Demo: Same vs Different Cache Keys\n");
|
|
11
|
+
const modelId = await loadModel({
|
|
12
|
+
modelSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
13
|
+
modelType: "llm",
|
|
14
|
+
modelConfig: {
|
|
15
|
+
device: "gpu",
|
|
16
|
+
ctx_size: 2048,
|
|
17
|
+
verbosity: VERBOSITY.SILENT,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
// Prompt 1 with cache key "session-a" (first time - no cache exists)
|
|
21
|
+
console.log('📝 Prompt 1: "What is 2+2?" with cache key "session-a"');
|
|
22
|
+
console.log(" Status: Creating NEW cache (first time)\n");
|
|
23
|
+
const result1 = completion({
|
|
24
|
+
modelId,
|
|
25
|
+
history: [systemPromptMessage, { role: "user", content: "What is 2+2?" }],
|
|
26
|
+
stream: true,
|
|
27
|
+
kvCache: "session-a",
|
|
28
|
+
});
|
|
29
|
+
console.log(" Response: ");
|
|
30
|
+
let response1 = "";
|
|
31
|
+
for await (const token of result1.tokenStream) {
|
|
32
|
+
response1 += token;
|
|
33
|
+
process.stdout.write(token);
|
|
34
|
+
}
|
|
35
|
+
const stats1 = await result1.stats;
|
|
36
|
+
console.log(`\n Stats: TTFT=${stats1?.timeToFirstToken}ms, CacheTokens=${stats1?.cacheTokens}\n`);
|
|
37
|
+
// Prompt 2 with SAME cache key "session-a" (cache exists - optimized!)
|
|
38
|
+
// This continues the conversation - asking about the previous answer
|
|
39
|
+
console.log('\n📝 Prompt 2: "Now multiply that result by 3" with cache key "session-a" (SAME)');
|
|
40
|
+
console.log(" Status: REUSING existing cache (only last message sent, but context remembered!)\n");
|
|
41
|
+
const result2 = completion({
|
|
42
|
+
modelId,
|
|
43
|
+
history: [
|
|
44
|
+
systemPromptMessage,
|
|
45
|
+
{ role: "user", content: "What is 2+2?" },
|
|
46
|
+
{ role: "assistant", content: response1 },
|
|
47
|
+
{ role: "user", content: "Now multiply that result by 3" }, // Refers to previous answer!
|
|
48
|
+
],
|
|
49
|
+
stream: true,
|
|
50
|
+
kvCache: "session-a", // Same cache key!
|
|
51
|
+
});
|
|
52
|
+
console.log(" Response: ");
|
|
53
|
+
for await (const token of result2.tokenStream) {
|
|
54
|
+
process.stdout.write(token);
|
|
55
|
+
}
|
|
56
|
+
const stats2 = await result2.stats;
|
|
57
|
+
console.log(`\n Stats: TTFT=${stats2?.timeToFirstToken}ms, CacheTokens=${stats2?.cacheTokens}\n`);
|
|
58
|
+
// Prompt 3 with DIFFERENT cache key "session-b" (new cache)
|
|
59
|
+
console.log('\n📝 Prompt 3: "What is 10+10?" with cache key "session-b" (DIFFERENT)');
|
|
60
|
+
console.log(" Status: Creating NEW cache (different key = isolated cache)\n");
|
|
61
|
+
const result3 = completion({
|
|
62
|
+
modelId,
|
|
63
|
+
history: [systemPromptMessage, { role: "user", content: "What is 10+10?" }],
|
|
64
|
+
stream: true,
|
|
65
|
+
kvCache: "session-b", // Different cache key!
|
|
66
|
+
});
|
|
67
|
+
console.log(" Response: ");
|
|
68
|
+
for await (const token of result3.tokenStream) {
|
|
69
|
+
process.stdout.write(token);
|
|
70
|
+
}
|
|
71
|
+
const stats3 = await result3.stats;
|
|
72
|
+
console.log(`\n Stats: TTFT=${stats3?.timeToFirstToken}ms, CacheTokens=${stats3?.cacheTokens}\n`);
|
|
73
|
+
// Summary
|
|
74
|
+
console.log("\n✅ Summary:");
|
|
75
|
+
console.log(' - Prompts 1 & 2 share cache key "session-a" → same cache file');
|
|
76
|
+
console.log(" - Prompt 2 built on Prompt 1's context (model remembered the answer!)");
|
|
77
|
+
console.log(" - Only the last message was sent, but full conversation context maintained");
|
|
78
|
+
console.log(' - Prompt 3 uses cache key "session-b" → separate cache file (isolated)');
|
|
79
|
+
console.log(" - Different cache keys provide complete isolation between sessions");
|
|
80
|
+
await deleteCache({ all: true });
|
|
81
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error("❌ Error:", error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { completion, loadModel, unloadModel } from "@qvac/sdk";
|
|
1
|
+
import { completion, loadModel, SMOLVLM2_2_500M_MULTIMODAL_Q8_0, MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0, 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: SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
|
|
12
12
|
modelType: "llm",
|
|
13
|
-
projectionModelSrc:
|
|
13
|
+
projectionModelSrc: MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
|
|
14
14
|
modelConfig: {
|
|
15
15
|
ctx_size: 1024,
|
|
16
16
|
},
|
|
@@ -41,9 +41,10 @@ try {
|
|
|
41
41
|
documents: medicalArticle,
|
|
42
42
|
chunk: true,
|
|
43
43
|
chunkOpts: {
|
|
44
|
-
chunkSize:
|
|
44
|
+
chunkSize: 100,
|
|
45
45
|
chunkOverlap: 10,
|
|
46
46
|
chunkStrategy: "paragraph",
|
|
47
|
+
splitStrategy: "token",
|
|
47
48
|
},
|
|
48
49
|
});
|
|
49
50
|
console.log(`✅ Created ${medicalResult.processed.length} chunks from medical article`);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { completion, loadModel, downloadAsset, ping, startQVACProvider, unloadModel, transcribe, transcribeStream, embed, translate, cancel, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, } from "./client/api/index";
|
|
1
|
+
export { completion, deleteCache, loadModel, downloadAsset, ping, startQVACProvider, unloadModel, transcribe, transcribeStream, embed, translate, cancel, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, } from "./client/api/index";
|
|
2
2
|
export { type ModelProgressUpdate, type LoadModelOptions, type DownloadAssetOptions, type Tool, VERBOSITY, type Attachment, type CompletionParams, type RagSearchResult, type RagSaveEmbeddingsResult, } from "./schemas/index";
|
|
3
3
|
export * from "./models/hyperdrive/index";
|
|
4
4
|
export { SUPPORTED_AUDIO_FORMATS } from "./constants/audio";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Public API exports only
|
|
2
|
-
export { completion, loadModel, downloadAsset, ping, startQVACProvider, unloadModel, transcribe, transcribeStream, embed, translate, cancel, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, } from "./client/api/index.js";
|
|
2
|
+
export { completion, deleteCache, loadModel, downloadAsset, ping, startQVACProvider, unloadModel, transcribe, transcribeStream, embed, translate, cancel, ragSaveEmbeddings, ragSearch, ragDeleteEmbeddings, } from "./client/api/index.js";
|
|
3
3
|
export { VERBOSITY, } from "./schemas/index.js";
|
|
4
4
|
// Hyperdrive model constants
|
|
5
5
|
export * from "./models/hyperdrive/index.js";
|
|
@@ -62,6 +62,20 @@ 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";
|
|
65
79
|
}, {
|
|
66
80
|
readonly hyperdriveKey: "d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578";
|
|
67
81
|
readonly hyperbeeKey: "generation:qwen3:instruct::0.6B::1.0.0";
|
|
@@ -97,6 +111,34 @@ export declare const models: readonly [{
|
|
|
97
111
|
readonly addon: "llm";
|
|
98
112
|
readonly expectedSize: 2401075552;
|
|
99
113
|
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";
|
|
100
142
|
}, {
|
|
101
143
|
readonly hyperdriveKey: "268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7";
|
|
102
144
|
readonly hyperbeeKey: "translation:ggml-indictrans:dist:2:200M:q0f32:1.0.0:en-hi";
|
|
@@ -421,11 +463,17 @@ export declare const GTE_LARGE_FP16: "pear://d1896d9259692818df95bd2480e90c2d057
|
|
|
421
463
|
export declare const LASER_DOLPHIN_2_6_2X7B_INST_Q2_K: "pear://bd40e4bfae48b5bf436d1b0b447ae26e4c384aebe101a5e7df6ae71c919dadf1/dolphin-mixtral-2x7b-dop-Q2_K.gguf";
|
|
422
464
|
export declare const LLAMA_3_2_1B_INST_Q4_0: "pear://afa79ee07c0a138bb9f11bfaee771fb1bdfca8c82d961cff0474e49827bd1de3/Llama-3.2-1B-Instruct-Q4_0.gguf";
|
|
423
465
|
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";
|
|
424
468
|
export declare const QWEN3_0_6B_INST: "pear://d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578/Qwen3-0.6B-UD-IQ1_S.gguf";
|
|
425
469
|
export declare const QWEN3_4B_INST_Q4: "pear://19ffb75463149955ee24d786dfddd84d41fc872ea813cd4465f5f7299d165adc/model.gguf";
|
|
426
470
|
export declare const QWEN3_600M_INST_Q4: "pear://211874c9885f6b88b9926904420e365f5e74e1b6ac47207b7536408539bef4b7/Qwen3-0.6B-Q4_0.gguf";
|
|
427
471
|
export declare const SALAMANDRATA_2B_INST_Q4: "pear://1610d81772a9e7c37660666dbdfdcef915b6b83c522ea1ad31c19cab0075811d/salamandrata_2b_inst_q4.gguf";
|
|
428
472
|
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";
|
|
429
477
|
export declare const MARIAN_EN_HI_INDIC_200M_Q0F32: "pear://268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7/ggml-indictrans2-en-indic-dist-200M.bin";
|
|
430
478
|
export declare const MARIAN_HI_EN_INDIC_200M_Q0F32: "pear://dfea395ffe1cb6d259029e5c81c290f8828981987855e23e7b66fd7c705901eb/ggml-indictrans2-indic-en-dist-200M.bin";
|
|
431
479
|
export declare const MARIAN_HI_HI_INDIC_320M_Q0F32: "pear://9a66da960931c449b41e3315d9aea4d3925f2cda024e8a4c139b64d0a539ed41/ggml-indictrans2-indic-indic-dist-320M.bin";
|
|
@@ -471,5 +519,5 @@ export declare const WHISPER_LARGE_3: "pear://76fb36d7f16a430618962d3e78b0e22e61
|
|
|
471
519
|
export declare const WHISPER_SMALL: "pear://c6a987fbb4ad8fba1526e446501f88ee45dfafbf1685410a7aeadb589fe18608/ggml-small.en-q8_0.bin";
|
|
472
520
|
export declare const WHISPER_TINY: "pear://9281d61503593fdf3eaa9d5e5d44746c271ef930aed3b7f8ee9ce153c76399d6/ggml-tiny.bin";
|
|
473
521
|
export declare const WHISPER_TINY_SILERO: "pear://ebfb94b378276da139554668f1ff737644eadff529c2ea0f2662d7df61fd86ca/ggml-tiny.bin";
|
|
474
|
-
export declare function getModelBySrc(modelId: string, hyperdriveKey
|
|
522
|
+
export declare function getModelBySrc(modelId: string, hyperdriveKey: string): HyperdriveItem | undefined;
|
|
475
523
|
//# sourceMappingURL=models.d.ts.map
|