@qvac/sdk 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/client/api/cancel.d.ts +1 -1
- package/dist/client/api/cancel.js +4 -3
- package/dist/client/api/completion-stream.d.ts +24 -32
- package/dist/client/api/completion-stream.js +142 -50
- package/dist/client/api/delete-cache.js +3 -2
- package/dist/client/api/download-asset.d.ts +3 -3
- package/dist/client/api/download-asset.js +12 -17
- package/dist/client/api/embed.d.ts +1 -1
- package/dist/client/api/embed.js +4 -3
- package/dist/client/api/get-model-info.d.ts +29 -0
- package/dist/client/api/get-model-info.js +14 -0
- package/dist/client/api/index.d.ts +3 -0
- package/dist/client/api/index.js +3 -0
- package/dist/client/api/load-model.d.ts +3 -3
- package/dist/client/api/load-model.js +13 -22
- package/dist/client/api/logging-stream.d.ts +1 -1
- package/dist/client/api/logging-stream.js +3 -2
- package/dist/client/api/ping.d.ts +1 -1
- package/dist/client/api/ping.js +3 -2
- package/dist/client/api/provide.d.ts +1 -1
- package/dist/client/api/provide.js +4 -3
- package/dist/client/api/rag.d.ts +3 -3
- package/dist/client/api/rag.js +13 -12
- package/dist/client/api/set-config.d.ts +7 -0
- package/dist/client/api/set-config.js +20 -0
- package/dist/client/api/stop-provider.d.ts +1 -1
- package/dist/client/api/stop-provider.js +4 -3
- package/dist/client/api/text-to-speech.d.ts +7 -0
- package/dist/client/api/text-to-speech.js +58 -0
- package/dist/client/api/transcribe.d.ts +4 -2
- package/dist/client/api/transcribe.js +9 -5
- package/dist/client/api/translate.d.ts +1 -1
- package/dist/client/api/translate.js +3 -2
- package/dist/client/api/unload-model.d.ts +5 -1
- package/dist/client/api/unload-model.js +14 -4
- package/dist/client/config-manager.d.ts +4 -0
- package/dist/client/config-manager.js +8 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/init-hooks.d.ts +6 -0
- package/dist/client/init-hooks.js +37 -0
- package/dist/client/rpc/bare-client.d.ts +69 -0
- package/dist/client/rpc/bare-client.js +5 -4
- package/dist/client/rpc/bare-rpc-client.js +7 -3
- package/dist/client/rpc/expo-rpc-client.d.ts +1 -0
- package/dist/client/rpc/expo-rpc-client.js +9 -1
- package/dist/client/rpc/node-rpc-client.d.ts +1 -1
- package/dist/client/rpc/node-rpc-client.js +22 -9
- package/dist/client/rpc/rpc-client.d.ts +1 -0
- package/dist/client/rpc/rpc-client.js +20 -1
- package/dist/constants/audio.d.ts +1 -2
- package/dist/constants/audio.js +1 -17
- package/dist/examples/cache-management.d.ts +2 -0
- package/dist/examples/cache-management.js +97 -0
- package/dist/examples/delegated-inference/consumer.js +2 -2
- package/dist/examples/download-with-blind-relays.d.ts +2 -0
- package/dist/examples/download-with-blind-relays.js +48 -0
- package/dist/examples/download-with-cancel.js +3 -4
- package/dist/examples/embed-hyperdrive.js +0 -1
- package/dist/examples/kv-cache-cleanup.js +0 -1
- package/dist/examples/kv-cache-custom-key.js +0 -1
- package/dist/examples/kv-cache-example.js +0 -1
- package/dist/examples/llamacpp-file-logging.js +0 -1
- package/dist/examples/llamacpp-filesystem.js +2 -2
- package/dist/examples/llamacpp-http.js +0 -1
- package/dist/examples/llamacpp-hyperdrive.js +0 -1
- package/dist/examples/llamacpp-multimodal.js +0 -1
- package/dist/examples/llamacpp-native-tools.js +118 -36
- package/dist/examples/llamacpp-sharded.d.ts +2 -0
- package/dist/examples/llamacpp-sharded.js +44 -0
- package/dist/examples/multi-model-demo.js +0 -1
- package/dist/examples/parallel-download.js +2 -2
- package/dist/examples/rag/rag-chromadb.js +0 -1
- package/dist/examples/rag/rag-hyperdb-workspaces.js +0 -1
- package/dist/examples/rag/rag-hyperdb.js +0 -1
- package/dist/examples/rag/rag-lancedb.js +0 -1
- package/dist/examples/rag/rag-sqlite.js +0 -1
- package/dist/examples/text-to-speech.d.ts +3 -0
- package/dist/examples/text-to-speech.js +137 -0
- package/dist/examples/translation/translation-indic.js +3 -1
- package/dist/examples/translation/translation-llm-context.js +0 -1
- package/dist/examples/translation/translation-llm.js +2 -2
- package/dist/examples/translation/translation-opus.js +3 -1
- package/dist/examples/translation/translation-stream.js +0 -1
- package/dist/examples/whispercpp-filesystem.js +32 -5
- package/dist/examples/whispercpp-microphone-record.js +9 -9
- package/dist/examples/whispercpp-prompt.d.ts +2 -0
- package/dist/examples/whispercpp-prompt.js +68 -0
- package/dist/expo/plugins/withMobileBundle.js +9 -3
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/models/hyperdrive/models.d.ts +1916 -100
- package/dist/models/hyperdrive/models.js +2042 -102
- package/dist/schemas/common.d.ts +413 -58
- package/dist/schemas/common.js +9 -0
- package/dist/schemas/completion-stream.d.ts +26 -22
- package/dist/schemas/completion-stream.js +9 -23
- package/dist/schemas/download-asset.d.ts +77 -2
- package/dist/schemas/download-asset.js +15 -4
- package/dist/schemas/get-model-info.d.ts +100 -0
- package/dist/schemas/get-model-info.js +40 -0
- package/dist/schemas/index.d.ts +7 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/llamacpp-config.d.ts +2 -1
- package/dist/schemas/llamacpp-config.js +3 -4
- package/dist/schemas/load-model.d.ts +2316 -266
- package/dist/schemas/load-model.js +157 -10
- package/dist/schemas/model-src-utils.d.ts +98 -0
- package/dist/schemas/model-src-utils.js +31 -0
- package/dist/schemas/sdk-errors-client.d.ts +25 -0
- package/dist/schemas/sdk-errors-client.js +111 -0
- package/dist/schemas/sdk-errors-server.d.ts +55 -0
- package/dist/schemas/sdk-errors-server.js +271 -0
- package/dist/schemas/set-config.d.ts +21 -0
- package/dist/schemas/set-config.js +14 -0
- package/dist/schemas/text-to-speech.d.ts +34 -0
- package/dist/schemas/text-to-speech.js +25 -0
- package/dist/schemas/tools.d.ts +62 -0
- package/dist/schemas/tools.js +43 -0
- package/dist/schemas/transcription.d.ts +25 -2
- package/dist/schemas/transcription.js +12 -1
- package/dist/schemas/translation-config.d.ts +33 -5
- package/dist/schemas/translation-config.js +18 -1
- package/dist/schemas/unload-model.d.ts +2 -0
- package/dist/schemas/unload-model.js +2 -0
- package/dist/schemas/whispercpp-config.d.ts +55 -18
- package/dist/schemas/whispercpp-config.js +63 -15
- package/dist/server/bare/addons/cancel.js +2 -1
- package/dist/server/bare/addons/llamacpp/create-model.d.ts +9 -2
- package/dist/server/bare/addons/llamacpp/create-model.js +23 -23
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.d.ts +10 -2
- package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +62 -43
- package/dist/server/bare/addons/llamacpp/handlers/embed.js +3 -2
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +1 -1
- package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +6 -2
- package/dist/server/bare/addons/load-model.js +59 -28
- package/dist/server/bare/addons/translation/create-model.d.ts +5 -1
- package/dist/server/bare/addons/translation/create-model.js +17 -25
- package/dist/server/bare/addons/translation/handlers/translate.js +10 -1
- package/dist/server/bare/addons/tts/create-model.d.ts +10 -0
- package/dist/server/bare/addons/tts/create-model.js +25 -0
- package/dist/server/bare/addons/tts/handlers/text-to-speech.d.ts +3 -0
- package/dist/server/bare/addons/tts/handlers/text-to-speech.js +87 -0
- package/dist/server/bare/addons/tts/index.d.ts +3 -0
- package/dist/server/bare/addons/tts/index.js +2 -0
- package/dist/server/bare/addons/unload-model.js +21 -3
- package/dist/server/bare/addons/whispercpp/create-model.d.ts +5 -1
- package/dist/server/bare/addons/whispercpp/create-model.js +13 -32
- package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +41 -20
- package/dist/server/bare/delegate-rpc-client.js +3 -2
- package/dist/server/bare/hyperswarm.d.ts +3 -0
- package/dist/server/bare/hyperswarm.js +22 -1
- package/dist/server/bare/rag-hyperdb/rag-manager.js +2 -3
- package/dist/server/bare/registry/config-registry.d.ts +5 -0
- package/dist/server/bare/registry/config-registry.js +39 -0
- package/dist/server/bare/registry/model-registry.d.ts +13 -0
- package/dist/server/bare/registry/model-registry.js +24 -7
- package/dist/server/rpc/handle-request.js +42 -3
- package/dist/server/rpc/handlers/completion-stream-delegated.js +2 -1
- package/dist/server/rpc/handlers/completion-stream.js +11 -4
- package/dist/server/rpc/handlers/download-asset.js +2 -3
- package/dist/server/rpc/handlers/get-model-info.d.ts +3 -0
- package/dist/server/rpc/handlers/get-model-info.js +148 -0
- package/dist/server/rpc/handlers/index.d.ts +4 -0
- package/dist/server/rpc/handlers/index.js +6 -0
- package/dist/server/rpc/handlers/load-model/http.js +51 -10
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +336 -156
- package/dist/server/rpc/handlers/load-model/index.js +1 -1
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +1 -1
- package/dist/server/rpc/handlers/load-model/resolve.js +10 -6
- package/dist/server/rpc/handlers/load-model-delegated.js +7 -4
- package/dist/server/rpc/handlers/load-model.js +19 -1
- package/dist/server/rpc/handlers/provideHandler/handler.js +2 -1
- package/dist/server/rpc/handlers/rag.js +0 -3
- package/dist/server/rpc/handlers/set-config.d.ts +3 -0
- package/dist/server/rpc/handlers/set-config.js +18 -0
- package/dist/server/rpc/handlers/stopProvideHandler.js +3 -1
- package/dist/server/rpc/handlers/text-to-speech.d.ts +3 -0
- package/dist/server/rpc/handlers/text-to-speech.js +7 -0
- package/dist/server/rpc/handlers/transcribe-stream.js +6 -2
- package/dist/server/rpc/handlers/unload-model.js +7 -0
- package/dist/server/utils/audio/decoder.js +1 -1
- package/dist/server/utils/cache.d.ts +13 -8
- package/dist/server/utils/cache.js +69 -14
- package/dist/server/utils/checksum.d.ts +2 -0
- package/dist/server/utils/checksum.js +24 -0
- package/dist/server/utils/index.d.ts +2 -0
- package/dist/server/utils/index.js +2 -0
- package/dist/server/utils/shard-utils.d.ts +22 -0
- package/dist/server/utils/shard-utils.js +37 -0
- package/dist/server/utils/tool-integration.d.ts +13 -0
- package/dist/server/utils/tool-integration.js +43 -0
- package/dist/server/utils/tool-parser.d.ts +7 -0
- package/dist/server/utils/tool-parser.js +244 -0
- package/dist/utils/errors-base.d.ts +3 -0
- package/dist/utils/errors-base.js +13 -0
- package/dist/utils/errors-client.d.ts +107 -0
- package/dist/utils/errors-client.js +186 -0
- package/dist/utils/errors-server.d.ts +146 -0
- package/dist/utils/errors-server.js +253 -0
- package/dist/utils/tool-helpers.d.ts +17 -0
- package/dist/utils/tool-helpers.js +99 -0
- package/package.json +14 -10
- package/dist/examples/llamacpp-tools-routing.d.ts +0 -2
- package/dist/examples/llamacpp-tools-routing.js +0 -364
- package/dist/examples/llamacpp-tools.d.ts +0 -2
- package/dist/examples/llamacpp-tools.js +0 -81
- package/dist/server/http-server.d.ts +0 -2
- package/dist/server/http-server.js +0 -189
|
@@ -1,62 +1,144 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { completion, loadModel, unloadModel, QWEN_3_1_7B_INST_Q4, } from "../index.js";
|
|
3
|
+
// Define Zod schemas for tool parameters
|
|
4
|
+
const weatherSchema = z.object({
|
|
5
|
+
city: z.string().describe("City name"),
|
|
6
|
+
country: z.string().describe("Country code").optional(),
|
|
7
|
+
});
|
|
8
|
+
const horoscopeSchema = z.object({
|
|
9
|
+
sign: z.string().describe("An astrological sign like Taurus or Aquarius"),
|
|
10
|
+
});
|
|
11
|
+
// Map tool names to their schemas for runtime validation
|
|
12
|
+
const toolSchemas = {
|
|
13
|
+
get_weather: weatherSchema,
|
|
14
|
+
get_horoscope: horoscopeSchema,
|
|
15
|
+
};
|
|
16
|
+
// Simple tool definitions - just name, description, and Zod schema!
|
|
10
17
|
const tools = [
|
|
11
18
|
{
|
|
12
|
-
|
|
19
|
+
name: "get_weather",
|
|
20
|
+
description: "Get current weather for a city",
|
|
21
|
+
parameters: weatherSchema,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
13
24
|
name: "get_horoscope",
|
|
14
|
-
description: "Get today's horoscope for an astrological sign
|
|
15
|
-
parameters:
|
|
16
|
-
type: "object",
|
|
17
|
-
properties: {
|
|
18
|
-
sign: {
|
|
19
|
-
type: "string",
|
|
20
|
-
description: "An astrological sign like Taurus or Aquarius",
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
required: ["sign"],
|
|
24
|
-
},
|
|
25
|
+
description: "Get today's horoscope for an astrological sign",
|
|
26
|
+
parameters: horoscopeSchema,
|
|
25
27
|
},
|
|
26
28
|
];
|
|
27
|
-
// @ts-expect-error - Function will be used in future implementation
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
29
|
-
function getHoroscope(sign) {
|
|
30
|
-
return sign + " Next Tuesday you will befriend a baby otter.";
|
|
31
|
-
}
|
|
32
|
-
console.log(`🚀 Loading GGUF model from: ${ggufPath}`);
|
|
33
29
|
try {
|
|
34
|
-
// Load model from provided file path
|
|
30
|
+
// Load model from provided file path with tools support enabled
|
|
35
31
|
const modelId = await loadModel({
|
|
36
|
-
modelSrc:
|
|
32
|
+
modelSrc: QWEN_3_1_7B_INST_Q4,
|
|
37
33
|
modelType: "llm",
|
|
38
34
|
modelConfig: {
|
|
39
35
|
ctx_size: 4096,
|
|
36
|
+
tools: true, // Enable tools support
|
|
40
37
|
},
|
|
41
38
|
onProgress: (progress) => console.log(`Loading: ${progress.percentage.toFixed(1)}%`),
|
|
42
39
|
});
|
|
43
40
|
console.log(`✅ Model loaded successfully! Model ID: ${modelId}`);
|
|
44
41
|
// Create conversation history
|
|
45
42
|
const history = [
|
|
46
|
-
{
|
|
43
|
+
{
|
|
44
|
+
role: "system",
|
|
45
|
+
content: "You are a helpful assistant that can use tools to get the weather and horoscope.",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
role: "user",
|
|
49
|
+
content: "What's the weather in Tokyo and my horoscope for Aquarius?",
|
|
50
|
+
},
|
|
47
51
|
];
|
|
48
52
|
console.log("\n🤖 AI Response:");
|
|
49
|
-
|
|
50
|
-
// Stream completion
|
|
53
|
+
console.log("(Streaming with tool definitions in prompt)\n");
|
|
51
54
|
const result = completion({ modelId, history, stream: true, tools });
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
// Consume token stream
|
|
56
|
+
const tokensTask = (async () => {
|
|
57
|
+
for await (const token of result.tokenStream) {
|
|
58
|
+
process.stdout.write(token);
|
|
59
|
+
}
|
|
60
|
+
})();
|
|
61
|
+
// Consume tool call events
|
|
62
|
+
const toolsTask = (async () => {
|
|
63
|
+
for await (const evt of result.toolCallStream) {
|
|
64
|
+
if (evt.type === "toolCall") {
|
|
65
|
+
console.log(`\n\n→ Tool Call Detected: ${evt.call.name}(${JSON.stringify(evt.call.arguments)})`);
|
|
66
|
+
console.log(` ID: ${evt.call.id}`);
|
|
67
|
+
}
|
|
68
|
+
else if (evt.type === "toolCallError") {
|
|
69
|
+
console.warn(`\n⚠️ Tool Error: ${evt.error.message}`);
|
|
70
|
+
console.warn(` Code: ${evt.error.code}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
await Promise.all([tokensTask, toolsTask]);
|
|
55
75
|
const stats = await result.stats;
|
|
76
|
+
const toolCalls = await result.toolCalls;
|
|
77
|
+
console.log("\n\n📋 Parsed Tool Calls:");
|
|
78
|
+
if (toolCalls.length > 0) {
|
|
79
|
+
for (const call of toolCalls) {
|
|
80
|
+
console.log(` - ${call.name}(${JSON.stringify(call.arguments)})`);
|
|
81
|
+
const schema = toolSchemas[call.name];
|
|
82
|
+
if (schema) {
|
|
83
|
+
const validated = schema.safeParse(call.arguments);
|
|
84
|
+
if (validated.success) {
|
|
85
|
+
console.log(` ✓ Arguments validated with Zod`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.log(` ✗ Validation failed:`, validated.error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(" No tool calls detected in response");
|
|
95
|
+
}
|
|
56
96
|
console.log("\n📊 Performance Stats:", stats);
|
|
97
|
+
// Execute tool calls and send results back to the model
|
|
98
|
+
if (toolCalls.length > 0) {
|
|
99
|
+
console.log("\n\n🔧 Simulating Tool Execution...");
|
|
100
|
+
// Simulate tool execution (in a real app, you'd call actual APIs)
|
|
101
|
+
const toolResults = toolCalls.map((call) => {
|
|
102
|
+
let result = "";
|
|
103
|
+
if (call.name === "get_weather") {
|
|
104
|
+
const args = call.arguments;
|
|
105
|
+
result = `The weather in ${args.city} is sunny, 22°C with light clouds.`;
|
|
106
|
+
}
|
|
107
|
+
else if (call.name === "get_horoscope") {
|
|
108
|
+
const args = call.arguments;
|
|
109
|
+
result = `Horoscope for ${args.sign}: Today is a great day for new beginnings and creative endeavors!`;
|
|
110
|
+
}
|
|
111
|
+
console.log(` ✓ ${call.name}: ${result}`);
|
|
112
|
+
return { toolCallId: call.id, result };
|
|
113
|
+
});
|
|
114
|
+
// Add tool results to conversation history
|
|
115
|
+
history.push({
|
|
116
|
+
role: "assistant",
|
|
117
|
+
content: await result.text,
|
|
118
|
+
});
|
|
119
|
+
// Add tool results as tool messages
|
|
120
|
+
for (const toolResult of toolResults) {
|
|
121
|
+
history.push({
|
|
122
|
+
role: "tool",
|
|
123
|
+
content: toolResult.result,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// Send follow-up question with tool results
|
|
127
|
+
console.log("\n\n🤖 Follow-up Response with Tool Results:");
|
|
128
|
+
const followUpResult = completion({
|
|
129
|
+
modelId,
|
|
130
|
+
history,
|
|
131
|
+
stream: true,
|
|
132
|
+
tools,
|
|
133
|
+
});
|
|
134
|
+
for await (const token of followUpResult.tokenStream) {
|
|
135
|
+
process.stdout.write(token);
|
|
136
|
+
}
|
|
137
|
+
const followUpStats = await followUpResult.stats;
|
|
138
|
+
console.log("\n\n📊 Follow-up Stats:", followUpStats);
|
|
139
|
+
}
|
|
57
140
|
console.log("\n\n🎉 Completed!");
|
|
58
141
|
await unloadModel({ modelId, clearStorage: false });
|
|
59
|
-
process.exit(0);
|
|
60
142
|
}
|
|
61
143
|
catch (error) {
|
|
62
144
|
console.error("❌ Error:", error);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { completion, loadModel, unloadModel, VERBOSITY, LLAMA_3_2_1B_INST_Q4_0_SHARD, } from "@qvac/sdk";
|
|
2
|
+
try {
|
|
3
|
+
const modelId = await loadModel({
|
|
4
|
+
modelSrc: LLAMA_3_2_1B_INST_Q4_0_SHARD,
|
|
5
|
+
modelType: "llm",
|
|
6
|
+
modelConfig: {
|
|
7
|
+
device: "gpu",
|
|
8
|
+
ctx_size: 2048,
|
|
9
|
+
verbosity: VERBOSITY.SILENT,
|
|
10
|
+
},
|
|
11
|
+
onProgress: (progress) => {
|
|
12
|
+
if (progress.shardInfo) {
|
|
13
|
+
const { shardInfo } = progress;
|
|
14
|
+
console.log(`📥 Downloading ${shardInfo.shardName} (${shardInfo.currentShard}/${shardInfo.totalShards})\n` +
|
|
15
|
+
` File: ${progress.percentage.toFixed(1)}% (${(progress.downloaded / 1024 / 1024).toFixed(2)}MB / ${(progress.total / 1024 / 1024).toFixed(2)}MB)\n` +
|
|
16
|
+
` Overall: ${shardInfo.overallPercentage.toFixed(1)}% (${(shardInfo.overallDownloaded / 1024 / 1024).toFixed(2)}MB / ${(shardInfo.overallTotal / 1024 / 1024).toFixed(2)}MB)`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
// Fallback for non-sharded models
|
|
20
|
+
console.log(`📥 Progress: ${progress.percentage.toFixed(1)}% ` +
|
|
21
|
+
`(${(progress.downloaded / 1024 / 1024).toFixed(2)}MB / ${(progress.total / 1024 / 1024).toFixed(2)}MB)`);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const history = [
|
|
26
|
+
{
|
|
27
|
+
role: "user",
|
|
28
|
+
content: "What are the benefits of sharding large language models? Use emojis in your response.",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
const result = completion({ modelId, history, stream: true });
|
|
32
|
+
console.log("\n🤖 Model response:");
|
|
33
|
+
for await (const token of result.tokenStream) {
|
|
34
|
+
process.stdout.write(token);
|
|
35
|
+
}
|
|
36
|
+
const stats = await result.stats;
|
|
37
|
+
console.log("\n\n📊 Performance Stats:", stats);
|
|
38
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error("❌ Error:", error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
@@ -67,7 +67,6 @@ try {
|
|
|
67
67
|
console.log("📊 Bob Stats: ", await bobResponse2.stats);
|
|
68
68
|
await unloadModel({ modelId: alice, clearStorage: false });
|
|
69
69
|
await unloadModel({ modelId: bob, clearStorage: false });
|
|
70
|
-
process.exit(0);
|
|
71
70
|
}
|
|
72
71
|
catch (error) {
|
|
73
72
|
console.error("❌ Error:", error);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LLAMA_3_2_1B_INST_Q4_0, downloadAsset, WHISPER_LARGE_3, } from "@qvac/sdk";
|
|
1
|
+
import { LLAMA_3_2_1B_INST_Q4_0, downloadAsset, WHISPER_LARGE_3, close, } from "@qvac/sdk";
|
|
2
2
|
try {
|
|
3
3
|
const llamaDownloadPromise = downloadAsset({
|
|
4
4
|
assetSrc: LLAMA_3_2_1B_INST_Q4_0,
|
|
@@ -13,7 +13,7 @@ try {
|
|
|
13
13
|
},
|
|
14
14
|
});
|
|
15
15
|
await Promise.all([llamaDownloadPromise, whisperDownloadPromise]);
|
|
16
|
-
|
|
16
|
+
void close();
|
|
17
17
|
}
|
|
18
18
|
catch (error) {
|
|
19
19
|
console.error("❌ Error:", error);
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_PIPER_NORMAN_EN_US_ONNX_MEDIUM, TTS_PIPER_NORMAN_EN_US_ONNX_MEDIUM_CONFIG, } from "@qvac/sdk";
|
|
2
|
+
import { writeFileSync, unlinkSync } from "fs";
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
|
+
import { platform } from "os";
|
|
5
|
+
// Get eSpeakDataPath from command line arguments or use default
|
|
6
|
+
const eSpeakDataPath = process.argv[2];
|
|
7
|
+
console.log(`Using eSpeak data path: ${eSpeakDataPath}`);
|
|
8
|
+
if (!eSpeakDataPath) {
|
|
9
|
+
console.error("eSpeakDataPath is required");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const modelId = await loadModel({
|
|
14
|
+
modelSrc: TTS_PIPER_NORMAN_EN_US_ONNX_MEDIUM,
|
|
15
|
+
modelType: "tts",
|
|
16
|
+
configSrc: TTS_PIPER_NORMAN_EN_US_ONNX_MEDIUM_CONFIG,
|
|
17
|
+
eSpeakDataPath,
|
|
18
|
+
modelConfig: {
|
|
19
|
+
language: "en",
|
|
20
|
+
},
|
|
21
|
+
onProgress: (progress) => {
|
|
22
|
+
console.log(progress);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
console.log(`Model loaded: ${modelId}`);
|
|
26
|
+
// Test TTS
|
|
27
|
+
console.log("🎵 Testing Text-to-Speech...");
|
|
28
|
+
const result = textToSpeech({
|
|
29
|
+
modelId,
|
|
30
|
+
text: `QVAC SDK is the canonical entry point to QVAC. Written in TypeScript, it provides all QVAC capabilities through a unified interface while also abstracting away the complexity of running your application in a JS environment other than Bare. Supported JS environments include Bare, Node.js, Expo and Bun.`,
|
|
31
|
+
inputType: "text",
|
|
32
|
+
stream: false,
|
|
33
|
+
});
|
|
34
|
+
const audioBuffer = await result.buffer;
|
|
35
|
+
console.log(`TTS complete. Total bytes: ${audioBuffer.length}`);
|
|
36
|
+
// Save and play audio
|
|
37
|
+
console.log("💾 Saving audio to file...");
|
|
38
|
+
createWav(audioBuffer, 22050, "tts-output.wav");
|
|
39
|
+
console.log("✅ Audio saved to tts-output.wav");
|
|
40
|
+
console.log("🔊 Playing audio...");
|
|
41
|
+
const audioData = int16ArrayToBuffer(audioBuffer);
|
|
42
|
+
const wavBuffer = Buffer.concat([
|
|
43
|
+
createWavHeader(audioData.length),
|
|
44
|
+
audioData,
|
|
45
|
+
]);
|
|
46
|
+
playAudio(wavBuffer);
|
|
47
|
+
console.log("✅ Audio playback complete");
|
|
48
|
+
// Unload the model
|
|
49
|
+
await unloadModel({ modelId });
|
|
50
|
+
console.log("Model unloaded");
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error("❌ Error:", error);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
// Function to create WAV header for 16-bit PCM audio
|
|
57
|
+
function createWavHeader(dataLength, sampleRate = 22050) {
|
|
58
|
+
const header = Buffer.alloc(44);
|
|
59
|
+
// RIFF header
|
|
60
|
+
header.write("RIFF", 0);
|
|
61
|
+
header.writeUInt32LE(36 + dataLength, 4);
|
|
62
|
+
header.write("WAVE", 8);
|
|
63
|
+
// fmt chunk
|
|
64
|
+
header.write("fmt ", 12);
|
|
65
|
+
header.writeUInt32LE(16, 16); // fmt chunk size
|
|
66
|
+
header.writeUInt16LE(1, 20); // PCM format
|
|
67
|
+
header.writeUInt16LE(1, 22); // mono
|
|
68
|
+
header.writeUInt32LE(sampleRate, 24);
|
|
69
|
+
header.writeUInt32LE(sampleRate * 2, 28); // byte rate
|
|
70
|
+
header.writeUInt16LE(2, 32); // block align
|
|
71
|
+
header.writeUInt16LE(16, 34); // bits per sample
|
|
72
|
+
// data chunk
|
|
73
|
+
header.write("data", 36);
|
|
74
|
+
header.writeUInt32LE(dataLength, 40);
|
|
75
|
+
return header;
|
|
76
|
+
}
|
|
77
|
+
// Function to convert Int16Array to Buffer
|
|
78
|
+
function int16ArrayToBuffer(int16Array) {
|
|
79
|
+
const buffer = Buffer.alloc(int16Array.length * 2);
|
|
80
|
+
for (let i = 0; i < int16Array.length; i++) {
|
|
81
|
+
const value = int16Array[i] ?? 0;
|
|
82
|
+
buffer.writeInt16LE(value, i * 2);
|
|
83
|
+
}
|
|
84
|
+
return buffer;
|
|
85
|
+
}
|
|
86
|
+
// Function to create and save WAV file (similar to reference implementation)
|
|
87
|
+
export function createWav(audioBuffer, sampleRate = 22050, filename = "output.wav") {
|
|
88
|
+
const audioData = int16ArrayToBuffer(audioBuffer);
|
|
89
|
+
const wavHeader = createWavHeader(audioData.length, sampleRate);
|
|
90
|
+
const wavFile = Buffer.concat([wavHeader, audioData]);
|
|
91
|
+
writeFileSync(filename, wavFile);
|
|
92
|
+
console.log(`WAV file saved as: ${filename}`);
|
|
93
|
+
}
|
|
94
|
+
// Function to play audio using system audio players
|
|
95
|
+
export function playAudio(audioBuffer) {
|
|
96
|
+
const currentPlatform = platform();
|
|
97
|
+
const tempFile = `/tmp/audio-${Date.now()}.wav`;
|
|
98
|
+
// Write audio buffer to temporary file
|
|
99
|
+
writeFileSync(tempFile, audioBuffer);
|
|
100
|
+
let audioPlayer;
|
|
101
|
+
let args;
|
|
102
|
+
switch (currentPlatform) {
|
|
103
|
+
case "darwin":
|
|
104
|
+
audioPlayer = "afplay";
|
|
105
|
+
args = [tempFile];
|
|
106
|
+
break;
|
|
107
|
+
case "linux":
|
|
108
|
+
audioPlayer = "aplay";
|
|
109
|
+
args = [tempFile];
|
|
110
|
+
break;
|
|
111
|
+
case "win32":
|
|
112
|
+
audioPlayer = "powershell";
|
|
113
|
+
args = [
|
|
114
|
+
"-Command",
|
|
115
|
+
`Add-Type -AssemblyName presentationCore; (New-Object Media.SoundPlayer).LoadStream([System.IO.File]::ReadAllBytes('${tempFile}')).PlaySync()`,
|
|
116
|
+
];
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
audioPlayer = "aplay";
|
|
120
|
+
args = [tempFile];
|
|
121
|
+
}
|
|
122
|
+
const result = spawnSync(audioPlayer, args, {
|
|
123
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
124
|
+
});
|
|
125
|
+
try {
|
|
126
|
+
unlinkSync(tempFile);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Ignore cleanup errors
|
|
130
|
+
}
|
|
131
|
+
if (result.error) {
|
|
132
|
+
throw new Error(`Audio player failed: ${result.error.message}`);
|
|
133
|
+
}
|
|
134
|
+
if (result.status !== 0) {
|
|
135
|
+
throw new Error(`Audio player exited with code ${result.status}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { loadModel, translate, unloadModel, MARIAN_EN_HI_INDIC_1B_Q4_0, } from "@qvac/sdk";
|
|
2
|
+
// NOTE: @qvac/translation-nmtcpp version 0.1.6 does not work well with IndicTrans models
|
|
3
|
+
// This example is expected to fail
|
|
4
|
+
// A fix is in progress for future releases
|
|
2
5
|
try {
|
|
3
6
|
const modelId = await loadModel({
|
|
4
7
|
modelSrc: MARIAN_EN_HI_INDIC_1B_Q4_0,
|
|
@@ -22,7 +25,6 @@ try {
|
|
|
22
25
|
const translatedText = await result.text;
|
|
23
26
|
console.log(`Translated text EN -> HI: ${text} -> "${translatedText}"`);
|
|
24
27
|
await unloadModel({ modelId });
|
|
25
|
-
process.exit(0);
|
|
26
28
|
}
|
|
27
29
|
catch (error) {
|
|
28
30
|
console.error("❌ Error:", error);
|
|
@@ -22,7 +22,6 @@ try {
|
|
|
22
22
|
const translatedTextExplicit = await resultExplicit.text;
|
|
23
23
|
console.log(`${engText} -> "${translatedTextExplicit}"`); // "banco" (not "orilla")
|
|
24
24
|
await unloadModel({ modelId, clearStorage: false });
|
|
25
|
-
process.exit(0);
|
|
26
25
|
}
|
|
27
26
|
catch (error) {
|
|
28
27
|
console.error("❌ Error:", error);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { translate, loadModel, SALAMANDRATA_2B_INST_Q4 } from "@qvac/sdk";
|
|
1
|
+
import { translate, loadModel, unloadModel, SALAMANDRATA_2B_INST_Q4, } from "@qvac/sdk";
|
|
2
2
|
try {
|
|
3
3
|
const modelId = await loadModel({
|
|
4
4
|
modelSrc: SALAMANDRATA_2B_INST_Q4,
|
|
@@ -30,7 +30,7 @@ try {
|
|
|
30
30
|
const translatedTextAutodetect = await resultAutodetect.text;
|
|
31
31
|
console.log(`Explicit source: ${engText} -> "${translatedTextExplicit}"`);
|
|
32
32
|
console.log(`Autodetected source: ${espText} -> "${translatedTextAutodetect}"`);
|
|
33
|
-
|
|
33
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
34
34
|
}
|
|
35
35
|
catch (error) {
|
|
36
36
|
console.error("❌ Error:", error);
|
|
@@ -6,6 +6,9 @@ try {
|
|
|
6
6
|
modelConfig: {
|
|
7
7
|
from: "en",
|
|
8
8
|
to: "it",
|
|
9
|
+
temperature: 0.2,
|
|
10
|
+
norepeatngramsize: 3,
|
|
11
|
+
lengthpenalty: 1.2,
|
|
9
12
|
},
|
|
10
13
|
onProgress: (progress) => {
|
|
11
14
|
console.log(progress);
|
|
@@ -22,7 +25,6 @@ try {
|
|
|
22
25
|
const translatedText = await result.text;
|
|
23
26
|
console.log(`Translated text EN -> IT: ${text} -> "${translatedText}"`);
|
|
24
27
|
await unloadModel({ modelId });
|
|
25
|
-
process.exit(0);
|
|
26
28
|
}
|
|
27
29
|
catch (error) {
|
|
28
30
|
console.error("❌ Error:", error);
|
|
@@ -15,11 +15,39 @@ try {
|
|
|
15
15
|
modelType: "whisper",
|
|
16
16
|
vadModelSrc: VAD_SILERO_5_1_2,
|
|
17
17
|
modelConfig: {
|
|
18
|
-
mode: "caption",
|
|
19
|
-
output_format: "plaintext",
|
|
20
|
-
min_seconds: 2,
|
|
21
|
-
max_seconds: 6,
|
|
22
18
|
audio_format: "f32le",
|
|
19
|
+
// Sampling strategy
|
|
20
|
+
strategy: "greedy",
|
|
21
|
+
n_threads: 4,
|
|
22
|
+
// Transcription options
|
|
23
|
+
language: "en",
|
|
24
|
+
translate: false,
|
|
25
|
+
no_timestamps: false,
|
|
26
|
+
single_segment: false,
|
|
27
|
+
print_timestamps: true,
|
|
28
|
+
token_timestamps: true,
|
|
29
|
+
// Quality settings
|
|
30
|
+
temperature: 0.0,
|
|
31
|
+
suppress_blank: true,
|
|
32
|
+
suppress_nst: true,
|
|
33
|
+
// Advanced tuning
|
|
34
|
+
entropy_thold: 2.4,
|
|
35
|
+
logprob_thold: -1.0,
|
|
36
|
+
// VAD configuration
|
|
37
|
+
vad_params: {
|
|
38
|
+
threshold: 0.35,
|
|
39
|
+
min_speech_duration_ms: 200,
|
|
40
|
+
min_silence_duration_ms: 150,
|
|
41
|
+
max_speech_duration_s: 30.0,
|
|
42
|
+
speech_pad_ms: 600,
|
|
43
|
+
samples_overlap: 0.3,
|
|
44
|
+
},
|
|
45
|
+
// Context parameters for GPU
|
|
46
|
+
contextParams: {
|
|
47
|
+
use_gpu: true,
|
|
48
|
+
flash_attn: true,
|
|
49
|
+
gpu_device: 0,
|
|
50
|
+
},
|
|
23
51
|
},
|
|
24
52
|
onProgress: (progress) => {
|
|
25
53
|
console.log(progress);
|
|
@@ -35,7 +63,6 @@ try {
|
|
|
35
63
|
console.log("🧹 Unloading Whisper model...");
|
|
36
64
|
await unloadModel({ modelId });
|
|
37
65
|
console.log("✅ Whisper model unloaded successfully");
|
|
38
|
-
process.exit(0);
|
|
39
66
|
}
|
|
40
67
|
catch (error) {
|
|
41
68
|
console.error("❌ Error:", error);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loadModel,
|
|
1
|
+
import { loadModel, unloadModel, transcribe, transcribeStream, WHISPER_TINY, VAD_SILERO_5_1_2, } from "@qvac/sdk";
|
|
2
2
|
import { spawn, spawnSync } from "child_process";
|
|
3
3
|
import * as readline from "readline";
|
|
4
4
|
import { platform } from "os";
|
|
@@ -239,7 +239,6 @@ function startInteractiveSession(rl, modelId) {
|
|
|
239
239
|
if (ffmpeg) {
|
|
240
240
|
ffmpeg.kill();
|
|
241
241
|
}
|
|
242
|
-
process.exit(0);
|
|
243
242
|
});
|
|
244
243
|
rl.prompt();
|
|
245
244
|
}
|
|
@@ -266,18 +265,20 @@ async function main() {
|
|
|
266
265
|
console.log(" - FFmpeg installed");
|
|
267
266
|
// Check FFmpeg availability
|
|
268
267
|
checkFFmpegAvailable();
|
|
269
|
-
// Download VAD model (asset download only - doesn't load into memory)
|
|
270
|
-
console.log("\n📥 Ensuring VAD model is available...");
|
|
271
|
-
await downloadAsset({ assetSrc: VAD_SILERO_5_1_2 });
|
|
272
268
|
// Load the Whisper model with VAD
|
|
273
|
-
console.log("\n📥 Loading Whisper model...");
|
|
269
|
+
console.log("\n📥 Loading Whisper model with VAD...");
|
|
274
270
|
modelId = await loadModel({
|
|
275
271
|
modelSrc: WHISPER_TINY,
|
|
276
272
|
modelType: "whisper",
|
|
273
|
+
vadModelSrc: VAD_SILERO_5_1_2,
|
|
277
274
|
modelConfig: {
|
|
278
|
-
mode: "caption",
|
|
279
|
-
update_frequency: "on_end",
|
|
280
275
|
audio_format: "f32le",
|
|
276
|
+
vad_params: {
|
|
277
|
+
threshold: 0.6,
|
|
278
|
+
min_speech_duration_ms: 250,
|
|
279
|
+
min_silence_duration_ms: 2000,
|
|
280
|
+
max_speech_duration_s: 30.0,
|
|
281
|
+
},
|
|
281
282
|
},
|
|
282
283
|
onProgress: (progress) => {
|
|
283
284
|
console.log(progress);
|
|
@@ -305,7 +306,6 @@ async function main() {
|
|
|
305
306
|
// Handle graceful shutdown
|
|
306
307
|
process.on("SIGINT", () => {
|
|
307
308
|
console.log("\n🛑 Stopping microphone transcription...");
|
|
308
|
-
process.exit(0);
|
|
309
309
|
});
|
|
310
310
|
// Start the application
|
|
311
311
|
main().catch(console.error);
|