@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
package/dist/schemas/rag.js
CHANGED
|
@@ -4,7 +4,9 @@ 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
|
|
7
|
+
splitStrategy: z
|
|
8
|
+
.enum(["character", "word", "token", "sentence", "line"])
|
|
9
|
+
.optional(),
|
|
8
10
|
});
|
|
9
11
|
const ragSaveEmbeddingsResultSchema = z.object({
|
|
10
12
|
status: z.enum(["fulfilled", "rejected"]),
|
|
@@ -1,65 +1,147 @@
|
|
|
1
1
|
import { completionParamsSchema, } from "../../../../../schemas/index.js";
|
|
2
|
-
import { getModel } from "../../../registry/model-registry.js";
|
|
3
|
-
import { findMatchingCache, getCurrentCacheInfo, renameCacheFile, } from "../kv-cache-utils";
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type: "media",
|
|
14
|
-
});
|
|
15
|
-
}
|
|
2
|
+
import { getModel, getModelConfig, } from "../../../registry/model-registry.js";
|
|
3
|
+
import { findMatchingCache, getCurrentCacheInfo, renameCacheFile, getCacheFilePath, extractSystemPrompt, generateConfigHash, customCacheExists, } from "../kv-cache-utils";
|
|
4
|
+
function transformMessage(message) {
|
|
5
|
+
const transformed = [];
|
|
6
|
+
if (message.attachments && message.attachments.length > 0) {
|
|
7
|
+
for (const attachment of message.attachments) {
|
|
8
|
+
transformed.push({
|
|
9
|
+
role: message.role,
|
|
10
|
+
content: attachment.path,
|
|
11
|
+
type: "media",
|
|
12
|
+
});
|
|
16
13
|
}
|
|
17
|
-
transformedHistory.push({
|
|
18
|
-
role: message.role,
|
|
19
|
-
content: message.content,
|
|
20
|
-
});
|
|
21
14
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
15
|
+
transformed.push({
|
|
16
|
+
role: message.role,
|
|
17
|
+
content: message.content,
|
|
18
|
+
});
|
|
19
|
+
return transformed;
|
|
20
|
+
}
|
|
21
|
+
function transformMessages(messages) {
|
|
22
|
+
const transformed = [];
|
|
23
|
+
for (const message of messages) {
|
|
24
|
+
transformed.push(...transformMessage(message));
|
|
25
|
+
}
|
|
26
|
+
return transformed;
|
|
27
|
+
}
|
|
28
|
+
async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse) {
|
|
29
|
+
const primeMessages = [
|
|
30
|
+
{ role: "session", content: cachePathToUse },
|
|
31
|
+
{ role: "system", content: systemPromptToUse },
|
|
32
|
+
];
|
|
33
|
+
const primeResponse = await model.run(primeMessages);
|
|
34
|
+
primeResponse.once("output", () => {
|
|
35
|
+
void primeResponse.cancel();
|
|
36
|
+
});
|
|
37
|
+
await primeResponse.await();
|
|
38
|
+
}
|
|
39
|
+
function prepareMessagesForCache(cachePathToUse, cacheExists, history) {
|
|
40
|
+
if (cacheExists && history.length > 0) {
|
|
41
|
+
const lastMessage = history[history.length - 1];
|
|
42
|
+
const lastTransformedMessages = transformMessage(lastMessage);
|
|
43
|
+
return [
|
|
35
44
|
{ role: "session", content: cachePathToUse },
|
|
36
|
-
...
|
|
45
|
+
...lastTransformedMessages,
|
|
37
46
|
];
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
}
|
|
48
|
+
const historyWithoutSystem = history.filter((msg) => msg.role !== "system");
|
|
49
|
+
const transformedHistoryWithoutSystem = transformMessages(historyWithoutSystem);
|
|
50
|
+
return [
|
|
51
|
+
{ role: "session", content: cachePathToUse },
|
|
52
|
+
...transformedHistoryWithoutSystem,
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
async function* processModelResponse(model, messagesToSend, shouldSaveCache) {
|
|
56
|
+
const response = await model.run(messagesToSend);
|
|
57
|
+
// Create a promise that rejects when onError is triggered
|
|
58
|
+
let rejectOnError = null;
|
|
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));
|
|
41
84
|
}
|
|
85
|
+
}
|
|
86
|
+
if (shouldSaveCache) {
|
|
42
87
|
await model.run([{ role: "session", content: "save" }]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
88
|
+
}
|
|
89
|
+
const responseWithStats = response;
|
|
90
|
+
return {
|
|
91
|
+
timeToFirstToken: responseWithStats.stats?.TTFT ?? 0,
|
|
92
|
+
tokensPerSecond: responseWithStats.stats?.TPS ?? 0,
|
|
93
|
+
cacheTokens: responseWithStats.stats?.CacheTokens ?? 0,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export async function* completion(params) {
|
|
97
|
+
const { history, modelId, kvCache } = completionParamsSchema.parse(params);
|
|
98
|
+
const transformedHistory = transformMessages(history);
|
|
99
|
+
const model = getModel(modelId);
|
|
100
|
+
if (kvCache) {
|
|
101
|
+
const modelConfig = getModelConfig(modelId);
|
|
102
|
+
const systemPromptFromHistory = extractSystemPrompt(history);
|
|
103
|
+
const configHash = generateConfigHash(modelConfig, systemPromptFromHistory);
|
|
104
|
+
const systemPromptToUse = systemPromptFromHistory ||
|
|
105
|
+
modelConfig.system_prompt ||
|
|
106
|
+
"You are a helpful assistant.";
|
|
107
|
+
let cachePathToUse;
|
|
108
|
+
if (typeof kvCache === "string") {
|
|
109
|
+
cachePathToUse = await getCacheFilePath(modelId, configHash, kvCache);
|
|
110
|
+
const cacheExists = await customCacheExists(modelId, configHash, kvCache);
|
|
111
|
+
if (!cacheExists) {
|
|
112
|
+
await initSystemPromptCache(model, cachePathToUse, systemPromptToUse);
|
|
113
|
+
}
|
|
114
|
+
const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
|
|
115
|
+
return yield* processModelResponse(model, messagesToSend, true);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Auto-generate cache key based on conversation history
|
|
119
|
+
const cacheMessages = history.map((msg) => ({
|
|
120
|
+
role: msg.role,
|
|
121
|
+
content: msg.content,
|
|
122
|
+
attachments: msg.attachments ?? undefined,
|
|
123
|
+
}));
|
|
124
|
+
const existingCache = await findMatchingCache(modelId, configHash, cacheMessages);
|
|
125
|
+
const currentCacheInfo = await getCurrentCacheInfo(modelId, configHash, cacheMessages);
|
|
126
|
+
cachePathToUse =
|
|
127
|
+
existingCache !== null
|
|
128
|
+
? existingCache.cachePath
|
|
129
|
+
: currentCacheInfo.cachePath;
|
|
130
|
+
const cacheExists = existingCache !== null;
|
|
131
|
+
if (!cacheExists) {
|
|
132
|
+
await initSystemPromptCache(model, cachePathToUse, systemPromptToUse);
|
|
133
|
+
}
|
|
134
|
+
const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history);
|
|
135
|
+
const result = yield* processModelResponse(model, messagesToSend, true);
|
|
136
|
+
//If there was an existing cache, we rename it with new hash that includes the current message
|
|
137
|
+
if (existingCache !== null &&
|
|
138
|
+
existingCache.cachePath !== currentCacheInfo.cachePath) {
|
|
139
|
+
await renameCacheFile(existingCache.cachePath, currentCacheInfo.cachePath);
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
47
142
|
}
|
|
48
|
-
const responseWithStats = response;
|
|
49
|
-
return {
|
|
50
|
-
timeToFirstToken: responseWithStats.stats?.TTFT ?? 0,
|
|
51
|
-
tokensPerSecond: responseWithStats.stats?.TPS ?? 0,
|
|
52
|
-
};
|
|
53
143
|
}
|
|
54
144
|
else {
|
|
55
|
-
|
|
56
|
-
for await (const token of response.iterate()) {
|
|
57
|
-
yield token;
|
|
58
|
-
}
|
|
59
|
-
const responseWithStats = response;
|
|
60
|
-
return {
|
|
61
|
-
timeToFirstToken: responseWithStats.stats?.TTFT ?? 0,
|
|
62
|
-
tokensPerSecond: responseWithStats.stats?.TPS ?? 0,
|
|
63
|
-
};
|
|
145
|
+
return yield* processModelResponse(model, transformedHistory, false);
|
|
64
146
|
}
|
|
65
147
|
}
|
|
@@ -5,15 +5,24 @@ export interface CacheMessage {
|
|
|
5
5
|
path: string;
|
|
6
6
|
}[] | undefined;
|
|
7
7
|
}
|
|
8
|
+
export declare function extractSystemPrompt(messages: CacheMessage[]): string | null;
|
|
9
|
+
export declare function generateConfigHash(modelConfig: unknown, systemPrompt: string | null): string;
|
|
8
10
|
export declare function generateCacheKey(messages: CacheMessage[]): string;
|
|
9
|
-
export declare function getCacheFilePath(cacheKey: string): string
|
|
10
|
-
export declare function findMatchingCache(currentHistory: CacheMessage[]): Promise<{
|
|
11
|
+
export declare function getCacheFilePath(modelId: string, configHash: string, cacheKey: string): Promise<string>;
|
|
12
|
+
export declare function findMatchingCache(modelId: string, configHash: string, currentHistory: CacheMessage[]): Promise<{
|
|
11
13
|
cacheKey: string;
|
|
12
14
|
cachePath: string;
|
|
13
15
|
} | null>;
|
|
14
|
-
export declare function getCurrentCacheInfo(currentHistory: CacheMessage[]): {
|
|
16
|
+
export declare function getCurrentCacheInfo(modelId: string, configHash: string, currentHistory: CacheMessage[]): Promise<{
|
|
15
17
|
cacheKey: string;
|
|
16
18
|
cachePath: string;
|
|
17
|
-
}
|
|
19
|
+
}>;
|
|
18
20
|
export declare function renameCacheFile(oldPath: string, newPath: string): Promise<void>;
|
|
21
|
+
export declare function customCacheExists(modelId: string, configHash: string, cacheKey: string): Promise<boolean>;
|
|
22
|
+
export declare function deleteCache(options: {
|
|
23
|
+
all: true;
|
|
24
|
+
} | {
|
|
25
|
+
kvCacheKey: string;
|
|
26
|
+
modelId?: string;
|
|
27
|
+
}): Promise<void>;
|
|
19
28
|
//# sourceMappingURL=kv-cache-utils.d.ts.map
|
|
@@ -2,6 +2,18 @@ import crypto from "bare-crypto";
|
|
|
2
2
|
import { promises as fsPromises } from "bare-fs";
|
|
3
3
|
import path from "bare-path";
|
|
4
4
|
import { getKVCacheDir } from "../../../utils/index.js";
|
|
5
|
+
export function extractSystemPrompt(messages) {
|
|
6
|
+
const systemMessage = messages.find((msg) => msg.role === "system");
|
|
7
|
+
return systemMessage ? systemMessage.content : null;
|
|
8
|
+
}
|
|
9
|
+
export function generateConfigHash(modelConfig, systemPrompt) {
|
|
10
|
+
const hash = crypto.createHash("sha256");
|
|
11
|
+
const configStr = JSON.stringify({ config: modelConfig, systemPrompt });
|
|
12
|
+
const configBuffer = Buffer.from(configStr, "utf8");
|
|
13
|
+
hash.update(configBuffer);
|
|
14
|
+
const hashString = hash.digest("hex");
|
|
15
|
+
return hashString.substring(0, 16);
|
|
16
|
+
}
|
|
5
17
|
export function generateCacheKey(messages) {
|
|
6
18
|
const hash = crypto.createHash("sha256");
|
|
7
19
|
const historyString = JSON.stringify(messages);
|
|
@@ -10,18 +22,28 @@ export function generateCacheKey(messages) {
|
|
|
10
22
|
const hashString = hash.digest("hex");
|
|
11
23
|
return hashString.substring(0, 16);
|
|
12
24
|
}
|
|
13
|
-
export function getCacheFilePath(cacheKey) {
|
|
25
|
+
export async function getCacheFilePath(modelId, configHash, cacheKey) {
|
|
14
26
|
const cacheDir = getKVCacheDir();
|
|
15
|
-
|
|
27
|
+
const sessionCacheDir = path.join(cacheDir, cacheKey);
|
|
28
|
+
const modelCacheDir = path.join(sessionCacheDir, modelId);
|
|
29
|
+
try {
|
|
30
|
+
await fsPromises.mkdir(sessionCacheDir, { recursive: true });
|
|
31
|
+
await fsPromises.mkdir(modelCacheDir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Ignore if directories already exist
|
|
35
|
+
}
|
|
36
|
+
return path.join(modelCacheDir, `${configHash}.bin`);
|
|
16
37
|
}
|
|
17
|
-
|
|
38
|
+
// Used for auto-generated cache key
|
|
39
|
+
export async function findMatchingCache(modelId, configHash, currentHistory) {
|
|
18
40
|
if (currentHistory.length <= 1) {
|
|
19
41
|
return null;
|
|
20
42
|
}
|
|
21
43
|
// Generate cache key for history minus the last message
|
|
22
44
|
const previousHistory = currentHistory.slice(0, -1);
|
|
23
45
|
const cacheKey = generateCacheKey(previousHistory);
|
|
24
|
-
const cachePath = getCacheFilePath(cacheKey);
|
|
46
|
+
const cachePath = await getCacheFilePath(modelId, configHash, cacheKey);
|
|
25
47
|
try {
|
|
26
48
|
await fsPromises.access(cachePath);
|
|
27
49
|
return { cacheKey, cachePath };
|
|
@@ -30,10 +52,9 @@ export async function findMatchingCache(currentHistory) {
|
|
|
30
52
|
return null;
|
|
31
53
|
}
|
|
32
54
|
}
|
|
33
|
-
export function getCurrentCacheInfo(currentHistory) {
|
|
34
|
-
// Generate cache path for the current conversation state
|
|
55
|
+
export async function getCurrentCacheInfo(modelId, configHash, currentHistory) {
|
|
35
56
|
const cacheKey = generateCacheKey(currentHistory);
|
|
36
|
-
const cachePath = getCacheFilePath(cacheKey);
|
|
57
|
+
const cachePath = await getCacheFilePath(modelId, configHash, cacheKey);
|
|
37
58
|
return { cacheKey, cachePath };
|
|
38
59
|
}
|
|
39
60
|
export async function renameCacheFile(oldPath, newPath) {
|
|
@@ -44,3 +65,45 @@ export async function renameCacheFile(oldPath, newPath) {
|
|
|
44
65
|
console.error("Error renaming cache file:", error instanceof Error ? error.message : String(error));
|
|
45
66
|
}
|
|
46
67
|
}
|
|
68
|
+
export async function customCacheExists(modelId, configHash, cacheKey) {
|
|
69
|
+
const cachePath = await getCacheFilePath(modelId, configHash, cacheKey);
|
|
70
|
+
try {
|
|
71
|
+
await fsPromises.access(cachePath);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export async function deleteCache(options) {
|
|
79
|
+
const cacheDir = getKVCacheDir();
|
|
80
|
+
if ("all" in options && options.all) {
|
|
81
|
+
try {
|
|
82
|
+
await fsPromises.rm(cacheDir, { recursive: true });
|
|
83
|
+
await fsPromises.mkdir(cacheDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error("Error deleting all caches:", error instanceof Error ? error.message : String(error));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if ("kvCacheKey" in options) {
|
|
90
|
+
const kvCacheDir = path.join(cacheDir, options.kvCacheKey);
|
|
91
|
+
if (options.modelId) {
|
|
92
|
+
const modelCacheDir = path.join(kvCacheDir, options.modelId);
|
|
93
|
+
try {
|
|
94
|
+
await fsPromises.rm(modelCacheDir, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error(`Error deleting model cache ${options.kvCacheKey}/${options.modelId}:`, error instanceof Error ? error.message : String(error));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
try {
|
|
102
|
+
await fsPromises.rm(kvCacheDir, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error(`Error deleting cache ${options.kvCacheKey}:`, error instanceof Error ? error.message : String(error));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -51,5 +51,5 @@ export async function loadModel(params) {
|
|
|
51
51
|
console.log(`${modelType}: Loading model ${modelId}...`);
|
|
52
52
|
await model.load(false);
|
|
53
53
|
console.log(`${modelType} model ${modelId} loaded`);
|
|
54
|
-
registerModel(modelId, { model, path: modelPath });
|
|
54
|
+
registerModel(modelId, { model, path: modelPath, config: modelConfig });
|
|
55
55
|
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
import type EventEmitter from "events";
|
|
1
2
|
interface AddonInterface {
|
|
2
3
|
cancel(jobId?: string): Promise<void>;
|
|
3
4
|
}
|
|
4
5
|
export interface AnyModel {
|
|
5
6
|
load(...args: unknown[]): Promise<void>;
|
|
6
|
-
run(input: unknown): Promise<{
|
|
7
|
+
run(input: unknown): Promise<EventEmitter & {
|
|
7
8
|
onUpdate(callback: (data: string) => void): {
|
|
8
9
|
await: () => Promise<void>;
|
|
9
10
|
};
|
|
11
|
+
onError(callback: (error: Error) => void): void;
|
|
10
12
|
onUpdate(callback: (data: Array<{
|
|
11
13
|
text: string;
|
|
12
14
|
}>) => void): {
|
|
13
15
|
await: () => Promise<void>;
|
|
14
16
|
};
|
|
17
|
+
cancel(): Promise<void>;
|
|
15
18
|
iterate(): AsyncIterableIterator<string | Array<{
|
|
16
19
|
text: string;
|
|
17
20
|
}>>;
|
|
@@ -29,6 +32,7 @@ interface LocalOptions {
|
|
|
29
32
|
model: AnyModel;
|
|
30
33
|
path: string;
|
|
31
34
|
loadedAt: Date;
|
|
35
|
+
config: unknown;
|
|
32
36
|
}
|
|
33
37
|
export interface ModelEntry {
|
|
34
38
|
id: string;
|
|
@@ -39,6 +43,7 @@ export interface ModelEntry {
|
|
|
39
43
|
export declare function registerModel(id: string, options: {
|
|
40
44
|
model: AnyModel;
|
|
41
45
|
path: string;
|
|
46
|
+
config: unknown;
|
|
42
47
|
} | {
|
|
43
48
|
topic: string;
|
|
44
49
|
providerPublicKey: string;
|
|
@@ -53,7 +58,9 @@ export declare function getModelInfo(id: string): {
|
|
|
53
58
|
id: string;
|
|
54
59
|
path: string;
|
|
55
60
|
loadedAt: Date;
|
|
61
|
+
config: unknown;
|
|
56
62
|
} | null;
|
|
63
|
+
export declare function getModelConfig(id: string): unknown;
|
|
57
64
|
export declare function clearRegistry(): void;
|
|
58
65
|
export declare function getRegistryStats(): {
|
|
59
66
|
totalModels: number;
|
|
@@ -26,6 +26,7 @@ export function registerModel(id, options) {
|
|
|
26
26
|
model: options.model,
|
|
27
27
|
path: options.path,
|
|
28
28
|
loadedAt: new Date(),
|
|
29
|
+
config: options.config,
|
|
29
30
|
},
|
|
30
31
|
});
|
|
31
32
|
console.log(`Local model registered: ${id} -> ${options.path}`);
|
|
@@ -69,8 +70,16 @@ export function getModelInfo(id) {
|
|
|
69
70
|
id: entry.id,
|
|
70
71
|
path: entry.local.path,
|
|
71
72
|
loadedAt: entry.local.loadedAt,
|
|
73
|
+
config: entry.local.config,
|
|
72
74
|
};
|
|
73
75
|
}
|
|
76
|
+
export function getModelConfig(id) {
|
|
77
|
+
const entry = modelRegistry.get(id);
|
|
78
|
+
if (!entry || !entry.local) {
|
|
79
|
+
throw new Error(`Model with ID "${id}" not found or is delegated`);
|
|
80
|
+
}
|
|
81
|
+
return entry.local.config;
|
|
82
|
+
}
|
|
74
83
|
export function clearRegistry() {
|
|
75
84
|
modelRegistry.clear();
|
|
76
85
|
console.log("Model registry cleared");
|
|
@@ -13,6 +13,7 @@ import { handleLoggingStream } from "./handlers/logging-stream.js";
|
|
|
13
13
|
import { cancelHandler } from "./handlers/cancelHandler.js";
|
|
14
14
|
import { provideHandler } from "./handlers/provideHandler.js";
|
|
15
15
|
import { handleRag } from "./handlers/rag.js";
|
|
16
|
+
import { handleDeleteCache } from "./handlers/delete-cache.js";
|
|
16
17
|
import { sendErrorResponse, sendStreamErrorResponse } from "../error-handlers";
|
|
17
18
|
export async function handleRequest(req) {
|
|
18
19
|
try {
|
|
@@ -209,6 +210,16 @@ export async function handleRequest(req) {
|
|
|
209
210
|
}
|
|
210
211
|
break;
|
|
211
212
|
}
|
|
213
|
+
case "deleteCache": {
|
|
214
|
+
try {
|
|
215
|
+
const response = await handleDeleteCache(request);
|
|
216
|
+
req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
sendErrorResponse(req, error);
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
212
223
|
default: {
|
|
213
224
|
throw new Error(`Unknown request type`);
|
|
214
225
|
}
|
|
@@ -1,52 +1,38 @@
|
|
|
1
1
|
import { completion } from "../../bare/addons/llamacpp/index.js";
|
|
2
2
|
export async function* handleCompletionStream(request) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const filteredHistory = request.history.map(({ role, content, attachments }) => ({
|
|
4
|
+
role,
|
|
5
|
+
content,
|
|
6
|
+
attachments: attachments ?? [],
|
|
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;
|
|
7
21
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
}
|
|
22
|
+
else {
|
|
23
|
+
buffer += result.value;
|
|
24
|
+
if (request.stream) {
|
|
25
|
+
yield {
|
|
26
|
+
type: "completionStream",
|
|
27
|
+
token: result.value,
|
|
28
|
+
};
|
|
35
29
|
}
|
|
36
30
|
}
|
|
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
|
-
};
|
|
51
31
|
}
|
|
32
|
+
yield {
|
|
33
|
+
type: "completionStream",
|
|
34
|
+
token: buffer,
|
|
35
|
+
done: true,
|
|
36
|
+
stats,
|
|
37
|
+
};
|
|
52
38
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { deleteCache as deleteCacheUtil } from "../../bare/addons/llamacpp/kv-cache-utils.js";
|
|
2
|
+
export async function handleDeleteCache(request) {
|
|
3
|
+
try {
|
|
4
|
+
if ("all" in request && request.all) {
|
|
5
|
+
await deleteCacheUtil({ all: true });
|
|
6
|
+
}
|
|
7
|
+
else if ("kvCacheKey" in request) {
|
|
8
|
+
const params = {
|
|
9
|
+
kvCacheKey: request.kvCacheKey,
|
|
10
|
+
};
|
|
11
|
+
if (request.modelId !== undefined) {
|
|
12
|
+
params.modelId = request.modelId;
|
|
13
|
+
}
|
|
14
|
+
await deleteCacheUtil(params);
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
type: "deleteCache",
|
|
18
|
+
success: true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error("Error deleting cache:", error);
|
|
23
|
+
return {
|
|
24
|
+
type: "deleteCache",
|
|
25
|
+
success: false,
|
|
26
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -8,9 +8,12 @@ import { provideHandler } from "./provideHandler";
|
|
|
8
8
|
import { handleTranslate } from "./translate";
|
|
9
9
|
import { handleLoggingStream } from "./logging-stream";
|
|
10
10
|
import { handleRag } from "./rag";
|
|
11
|
+
import { cancelHandler } from "./cancelHandler";
|
|
12
|
+
import { handleDeleteCache } from "./delete-cache";
|
|
11
13
|
export declare const handlers: {
|
|
12
14
|
completionStream: typeof handleCompletionStream;
|
|
13
15
|
downloadAsset: typeof handleDownloadAsset;
|
|
16
|
+
deleteCache: typeof handleDeleteCache;
|
|
14
17
|
loadModel: typeof handleLoadModel;
|
|
15
18
|
unloadModel: typeof handleUnloadModel;
|
|
16
19
|
embed: typeof handleEmbed;
|
|
@@ -19,5 +22,6 @@ export declare const handlers: {
|
|
|
19
22
|
translate: typeof handleTranslate;
|
|
20
23
|
loggingStream: typeof handleLoggingStream;
|
|
21
24
|
rag: typeof handleRag;
|
|
25
|
+
cancel: typeof cancelHandler;
|
|
22
26
|
};
|
|
23
27
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -8,9 +8,12 @@ import { provideHandler } from "./provideHandler.js";
|
|
|
8
8
|
import { handleTranslate } from "./translate.js";
|
|
9
9
|
import { handleLoggingStream } from "./logging-stream.js";
|
|
10
10
|
import { handleRag } from "./rag.js";
|
|
11
|
+
import { cancelHandler } from "./cancelHandler.js";
|
|
12
|
+
import { handleDeleteCache } from "./delete-cache.js";
|
|
11
13
|
export const handlers = {
|
|
12
14
|
completionStream: handleCompletionStream,
|
|
13
15
|
downloadAsset: handleDownloadAsset,
|
|
16
|
+
deleteCache: handleDeleteCache,
|
|
14
17
|
loadModel: handleLoadModel,
|
|
15
18
|
unloadModel: handleUnloadModel,
|
|
16
19
|
embed: handleEmbed,
|
|
@@ -19,4 +22,5 @@ export const handlers = {
|
|
|
19
22
|
translate: handleTranslate,
|
|
20
23
|
loggingStream: handleLoggingStream,
|
|
21
24
|
rag: handleRag,
|
|
25
|
+
cancel: cancelHandler,
|
|
22
26
|
};
|
|
@@ -4,28 +4,9 @@ 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>;
|
|
8
7
|
export declare const setClearCacheFlag: (downloadKey: string, clearCache: boolean) => void;
|
|
9
8
|
export declare const shouldClearCache: (downloadKey: string) => boolean;
|
|
10
9
|
export declare const clearClearCacheFlag: (downloadKey: string) => void;
|
|
11
10
|
export declare const createCancelFunction: (downloadKey: string, clearCache?: boolean) => () => void;
|
|
12
11
|
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
|
-
};
|
|
31
12
|
//# sourceMappingURL=download-manager.d.ts.map
|