@fugood/bricks-project 2.24.0-beta.15 → 2.24.0-beta.16
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/compile/action-name-map.ts +14 -0
- package/compile/index.ts +4 -0
- package/package.json +2 -2
- package/skills/bricks-project/rules/buttress.md +9 -6
- package/tools/mcp-tools/huggingface.ts +112 -3
- package/types/bricks/Camera.ts +1 -1
- package/types/bricks/Image.ts +1 -1
- package/types/bricks/Lottie.ts +1 -1
- package/types/bricks/Maps.ts +1 -1
- package/types/bricks/QrCode.ts +1 -1
- package/types/bricks/Rect.ts +1 -1
- package/types/bricks/Slideshow.ts +1 -1
- package/types/bricks/Text.ts +1 -1
- package/types/bricks/TextInput.ts +1 -1
- package/types/bricks/Video.ts +1 -1
- package/types/bricks/WebView.ts +1 -1
- package/types/generators/Assistant.ts +1 -1
- package/types/generators/LlmMlx.ts +210 -0
- package/types/generators/index.ts +1 -0
- package/utils/event-props.ts +16 -0
|
@@ -772,6 +772,20 @@ export const templateActionNameMap = {
|
|
|
772
772
|
documents: 'GENERATOR_RERANKER_DOCUMENTS',
|
|
773
773
|
},
|
|
774
774
|
},
|
|
775
|
+
GENERATOR_MLX_LLM: {
|
|
776
|
+
GENERATOR_MLX_LLM_LOAD_MODEL: {
|
|
777
|
+
modelId: 'GENERATOR_MLX_LLM_MODEL_ID',
|
|
778
|
+
vlm: 'GENERATOR_MLX_LLM_VLM',
|
|
779
|
+
},
|
|
780
|
+
GENERATOR_MLX_LLM_COMPLETION: {
|
|
781
|
+
messages: 'GENERATOR_MLX_LLM_MESSAGES',
|
|
782
|
+
tools: 'GENERATOR_MLX_LLM_TOOLS',
|
|
783
|
+
maxTokens: 'GENERATOR_MLX_LLM_MAX_TOKENS',
|
|
784
|
+
temperature: 'GENERATOR_MLX_LLM_TEMPERATURE',
|
|
785
|
+
topP: 'GENERATOR_MLX_LLM_TOP_P',
|
|
786
|
+
repetitionPenalty: 'GENERATOR_MLX_LLM_REPETITION_PENALTY',
|
|
787
|
+
},
|
|
788
|
+
},
|
|
775
789
|
GENERATOR_QNN_LLM: {
|
|
776
790
|
GENERATOR_QNN_LLM_PROCESS: {
|
|
777
791
|
prompt: 'GENERATOR_QNN_LLM_PROMPT',
|
package/compile/index.ts
CHANGED
|
@@ -670,6 +670,8 @@ export const compile = async (app: Application) => {
|
|
|
670
670
|
buildList(item, index, 'brickList'),
|
|
671
671
|
)
|
|
672
672
|
property.brickList = brickList
|
|
673
|
+
} else if (!brickItems.brickList) {
|
|
674
|
+
property.brickList = []
|
|
673
675
|
} else {
|
|
674
676
|
// Not supported Data for brickList
|
|
675
677
|
throw new TypeError('Not supported Data for brickList directly')
|
|
@@ -679,6 +681,8 @@ export const compile = async (app: Application) => {
|
|
|
679
681
|
buildList(item, index, 'brickDetails'),
|
|
680
682
|
)
|
|
681
683
|
property.brickDetails = brickDetails
|
|
684
|
+
} else if (!brickItems.brickDetails) {
|
|
685
|
+
property.brickDetails = []
|
|
682
686
|
} else {
|
|
683
687
|
// Not supported Data for brickList
|
|
684
688
|
throw new TypeError('Not supported Data for brickList directly')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-project",
|
|
3
|
-
"version": "2.24.0-beta.
|
|
3
|
+
"version": "2.24.0-beta.16",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
@@ -24,5 +24,5 @@
|
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"oxfmt": "^0.36.0"
|
|
26
26
|
},
|
|
27
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "b024e1980b2c25797ae26e9b973497e3ee724265"
|
|
28
28
|
}
|
|
@@ -14,8 +14,9 @@ When mobile devices or embedded systems lack hardware for local AI inference (LL
|
|
|
14
14
|
|
|
15
15
|
## Supported Generators
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
17
|
+
- LLM (GGML) (LlmMlx.ts) - Local Large Language Model inference with GGML
|
|
18
|
+
- LLM (MLX) (LlmGgml.ts) - Local Large Language Model inference with MLX
|
|
19
|
+
- Speech-to-Text (GGML) (SpeechToTextGgml.ts) - Local Speech-to-Text inference with GGML
|
|
19
20
|
|
|
20
21
|
## Client Configuration
|
|
21
22
|
|
|
@@ -50,10 +51,12 @@ const llmGenerator: GeneratorLLM = {
|
|
|
50
51
|
property: {
|
|
51
52
|
modelUrl: 'https://huggingface.co/ggml-org/gemma-3-12b-it-qat-GGUF/resolve/main/gemma-3-12b-it-qat-q4_0.gguf',
|
|
52
53
|
contextSize: 8192,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
buttressConnectionSettings: {
|
|
55
|
+
enabled: true,
|
|
56
|
+
url: 'http://192.168.1.100:2080',
|
|
57
|
+
fallbackType: 'use-local',
|
|
58
|
+
strategy: 'prefer-best',
|
|
59
|
+
},
|
|
57
60
|
},
|
|
58
61
|
events: {},
|
|
59
62
|
switches: [],
|
|
@@ -102,6 +102,7 @@ type HFSibling = {
|
|
|
102
102
|
rfilename: string
|
|
103
103
|
size?: number
|
|
104
104
|
lfs?: { sha256?: string }
|
|
105
|
+
blobId?: string
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
type HFModel = {
|
|
@@ -132,8 +133,9 @@ type GeneratorType =
|
|
|
132
133
|
| 'GeneratorOnnxLLM'
|
|
133
134
|
| 'GeneratorOnnxSTT'
|
|
134
135
|
| 'GeneratorTTS'
|
|
136
|
+
| 'GeneratorMlxLLM'
|
|
135
137
|
|
|
136
|
-
type ModelKind = 'gguf' | 'onnx'
|
|
138
|
+
type ModelKind = 'gguf' | 'onnx' | 'mlx'
|
|
137
139
|
|
|
138
140
|
interface GeneratorConfig {
|
|
139
141
|
modelKind: ModelKind
|
|
@@ -219,6 +221,11 @@ const generatorConfigs: Record<GeneratorType, GeneratorConfig> = {
|
|
|
219
221
|
filter: 'onnx,text-to-speech',
|
|
220
222
|
hasValidStructure: hasValidOnnxStructure,
|
|
221
223
|
},
|
|
224
|
+
GeneratorMlxLLM: {
|
|
225
|
+
modelKind: 'mlx',
|
|
226
|
+
filter: 'mlx',
|
|
227
|
+
taskFilter: supportedLlmTasks,
|
|
228
|
+
},
|
|
222
229
|
}
|
|
223
230
|
|
|
224
231
|
const searchHFModels = async (filter: string, search?: string, limit = 50): Promise<HFModel[]> => {
|
|
@@ -276,6 +283,7 @@ export function register(server: McpServer) {
|
|
|
276
283
|
'GeneratorOnnxLLM',
|
|
277
284
|
'GeneratorOnnxSTT',
|
|
278
285
|
'GeneratorTTS',
|
|
286
|
+
'GeneratorMlxLLM',
|
|
279
287
|
])
|
|
280
288
|
.describe('Generator type to search models for')
|
|
281
289
|
.default('GeneratorLLM'),
|
|
@@ -407,6 +415,7 @@ export function register(server: McpServer) {
|
|
|
407
415
|
'GeneratorOnnxLLM',
|
|
408
416
|
'GeneratorOnnxSTT',
|
|
409
417
|
'GeneratorTTS',
|
|
418
|
+
'GeneratorMlxLLM',
|
|
410
419
|
])
|
|
411
420
|
.describe('Generator type for model selection')
|
|
412
421
|
.default('GeneratorLLM'),
|
|
@@ -489,7 +498,107 @@ export function register(server: McpServer) {
|
|
|
489
498
|
|
|
490
499
|
// Return JSON for huggingface_select to allow direct parsing by consumers
|
|
491
500
|
return {
|
|
492
|
-
content: [
|
|
501
|
+
content: [
|
|
502
|
+
{
|
|
503
|
+
type: 'text',
|
|
504
|
+
text: `${JSON5.stringify(result, null, 2)} // Please use _hfRepoInfo undocumented field with @ts-ignore`,
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Handle MLX models (repo-level, like ONNX)
|
|
511
|
+
if (config.modelKind === 'mlx') {
|
|
512
|
+
// Fetch config.json for model architecture metadata
|
|
513
|
+
const headers: Record<string, string> = {}
|
|
514
|
+
if (HF_TOKEN) headers['Authorization'] = `Bearer ${HF_TOKEN}`
|
|
515
|
+
let mlxModelConfig: Record<string, any> | null = null
|
|
516
|
+
try {
|
|
517
|
+
const configRes = await fetch(
|
|
518
|
+
`https://huggingface.co/${modelId}/resolve/main/config.json`,
|
|
519
|
+
{ headers },
|
|
520
|
+
)
|
|
521
|
+
if (configRes.ok) mlxModelConfig = await configRes.json()
|
|
522
|
+
} catch {
|
|
523
|
+
// Non-critical
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const modelType =
|
|
527
|
+
mlxModelConfig?.model_type || details.config?.model_type || details.cardData?.model_type
|
|
528
|
+
|
|
529
|
+
// Build MLX model metadata from config.json (for hardware guardrails)
|
|
530
|
+
const cfg = mlxModelConfig || ({} as Record<string, any>)
|
|
531
|
+
const textCfg = cfg.text_config || cfg
|
|
532
|
+
const numHeads = textCfg.num_attention_heads || textCfg.n_heads || 0
|
|
533
|
+
const hiddenSize = textCfg.hidden_size || textCfg.dim || 0
|
|
534
|
+
const kvLoraRank = textCfg.kv_lora_rank || 0
|
|
535
|
+
const quant = cfg.quantization || cfg.quantization_config || null
|
|
536
|
+
|
|
537
|
+
// Sum safetensors/npz file sizes for model weight bytes
|
|
538
|
+
const modelBytes = siblings
|
|
539
|
+
.filter((f) => /\.(safetensors|npz)$/.test(f.rfilename))
|
|
540
|
+
.reduce((sum, f) => sum + (f.size ?? 0), 0)
|
|
541
|
+
|
|
542
|
+
// Build _mlxDownloadFiles list (safetensors, json, jinja, tokenizer.model)
|
|
543
|
+
const mlxDownloadFiles = siblings
|
|
544
|
+
.filter(
|
|
545
|
+
(f) =>
|
|
546
|
+
f.rfilename.endsWith('.safetensors') ||
|
|
547
|
+
f.rfilename.endsWith('.json') ||
|
|
548
|
+
f.rfilename.endsWith('.jinja') ||
|
|
549
|
+
f.rfilename === 'tokenizer.model',
|
|
550
|
+
)
|
|
551
|
+
.map((f) => ({
|
|
552
|
+
url: `https://huggingface.co/${modelId}/resolve/main/${f.rfilename}?download=true`,
|
|
553
|
+
filename: `${modelId.replace('/', '-')}/${f.rfilename}`,
|
|
554
|
+
hash_type: f.lfs ? 'sha256' : f.blobId ? 'sha1' : undefined,
|
|
555
|
+
sha256: f.lfs?.sha256,
|
|
556
|
+
sha1: f.lfs ? undefined : f.blobId,
|
|
557
|
+
}))
|
|
558
|
+
|
|
559
|
+
const result = {
|
|
560
|
+
modelId,
|
|
561
|
+
modelType,
|
|
562
|
+
_mlxDownloadFiles: mlxDownloadFiles,
|
|
563
|
+
_hfRepoInfo: {
|
|
564
|
+
repo: modelId,
|
|
565
|
+
model: {
|
|
566
|
+
id: details.id,
|
|
567
|
+
downloads: details.downloads,
|
|
568
|
+
likes: details.likes,
|
|
569
|
+
author: details.author,
|
|
570
|
+
},
|
|
571
|
+
generatorType,
|
|
572
|
+
modelType,
|
|
573
|
+
...(modelBytes > 0 && { size: modelBytes }),
|
|
574
|
+
...(mlxModelConfig && {
|
|
575
|
+
mlxModelMetadata: {
|
|
576
|
+
hiddenSize,
|
|
577
|
+
numLayers: textCfg.num_hidden_layers || textCfg.n_layers || 0,
|
|
578
|
+
numHeads,
|
|
579
|
+
numKvHeads: textCfg.num_key_value_heads ?? numHeads,
|
|
580
|
+
headDim:
|
|
581
|
+
textCfg.head_dim ||
|
|
582
|
+
textCfg.v_head_dim ||
|
|
583
|
+
(numHeads > 0 && hiddenSize > 0 ? hiddenSize / numHeads : 0),
|
|
584
|
+
maxCtx: textCfg.max_position_embeddings || 0,
|
|
585
|
+
kvLoraRank,
|
|
586
|
+
qkRopeHeadDim: textCfg.qk_rope_head_dim || 0,
|
|
587
|
+
isMLA: kvLoraRank > 0,
|
|
588
|
+
quantBits: quant?.bits || null,
|
|
589
|
+
quantGroupSize: quant?.group_size || null,
|
|
590
|
+
},
|
|
591
|
+
}),
|
|
592
|
+
},
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return {
|
|
596
|
+
content: [
|
|
597
|
+
{
|
|
598
|
+
type: 'text',
|
|
599
|
+
text: `${JSON5.stringify(result, null, 2)} // IMPORTANT: Use _mlxDownloadFiles / _hfRepoInfo undocumented fields with @ts-ignore`,
|
|
600
|
+
},
|
|
601
|
+
],
|
|
493
602
|
}
|
|
494
603
|
}
|
|
495
604
|
|
|
@@ -638,7 +747,7 @@ export function register(server: McpServer) {
|
|
|
638
747
|
content: [
|
|
639
748
|
{
|
|
640
749
|
type: 'text',
|
|
641
|
-
text: `${JSON5.stringify(result, null, 2)} //
|
|
750
|
+
text: `${JSON5.stringify(result, null, 2)} // IMPORTANT: Use _hfRepoInfo undocumented field with @ts-ignore`,
|
|
642
751
|
},
|
|
643
752
|
],
|
|
644
753
|
}
|
package/types/bricks/Camera.ts
CHANGED
|
@@ -188,7 +188,7 @@ Default property:
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
/* Camera view brick
|
|
191
|
+
/* Camera view brick */
|
|
192
192
|
export type BrickCamera = Brick &
|
|
193
193
|
BrickCameraDef & {
|
|
194
194
|
templateKey: 'BRICK_CAMERA'
|
package/types/bricks/Image.ts
CHANGED
package/types/bricks/Lottie.ts
CHANGED
|
@@ -137,7 +137,7 @@ Default property:
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
/* Lottie Adobe After Effects animations brick
|
|
140
|
+
/* Lottie Adobe After Effects animations brick */
|
|
141
141
|
export type BrickLottie = Brick &
|
|
142
142
|
BrickLottieDef & {
|
|
143
143
|
templateKey: 'BRICK_LOTTIE'
|
package/types/bricks/Maps.ts
CHANGED
package/types/bricks/QrCode.ts
CHANGED
package/types/bricks/Rect.ts
CHANGED
|
@@ -168,7 +168,7 @@ Default property:
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
/* Slideshow brick
|
|
171
|
+
/* Slideshow brick */
|
|
172
172
|
export type BrickSlideshow = Brick &
|
|
173
173
|
BrickSlideshowDef & {
|
|
174
174
|
templateKey: 'BRICK_SLIDESHOW'
|
package/types/bricks/Text.ts
CHANGED
|
@@ -209,7 +209,7 @@ Default property:
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
/* Text Input brick
|
|
212
|
+
/* Text Input brick */
|
|
213
213
|
export type BrickTextInput = Brick &
|
|
214
214
|
BrickTextInputDef & {
|
|
215
215
|
templateKey: 'BRICK_TEXT_INPUT'
|
package/types/bricks/Video.ts
CHANGED
package/types/bricks/WebView.ts
CHANGED
|
@@ -141,7 +141,7 @@ Default property:
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
/* WebView brick
|
|
144
|
+
/* WebView brick */
|
|
145
145
|
export type BrickWebView = Brick &
|
|
146
146
|
BrickWebViewDef & {
|
|
147
147
|
templateKey: 'BRICK_WEBVIEW'
|
|
@@ -434,7 +434,7 @@ Default property:
|
|
|
434
434
|
| DataLink
|
|
435
435
|
/* Whether to cache messages */
|
|
436
436
|
cacheMessages?: boolean | DataLink
|
|
437
|
-
/* LLM Generator (Supports `LLM (GGML)` and `OpenAI LLM` generators) */
|
|
437
|
+
/* LLM Generator (Supports `LLM (GGML)`, `LLM (MLX)`, and `OpenAI LLM` generators) */
|
|
438
438
|
llmGeneratorId?: string | DataLink | (() => Generator)
|
|
439
439
|
/* LLM Live Policy. If the policy is `only-in-use`, the LLM context will be released when the assistant is not in use.
|
|
440
440
|
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/* Auto generated by build script */
|
|
2
|
+
import type { SwitchCondInnerStateCurrentCanvas, SwitchCondData, SwitchDef } from '../switch'
|
|
3
|
+
import type { Data, DataLink } from '../data'
|
|
4
|
+
import type {
|
|
5
|
+
Brick,
|
|
6
|
+
Generator,
|
|
7
|
+
EventAction,
|
|
8
|
+
ActionWithDataParams,
|
|
9
|
+
ActionWithParams,
|
|
10
|
+
Action,
|
|
11
|
+
EventProperty,
|
|
12
|
+
} from '../common'
|
|
13
|
+
|
|
14
|
+
/* Load model */
|
|
15
|
+
export type GeneratorMlxLLMActionLoadModel = ActionWithParams & {
|
|
16
|
+
__actionName: 'GENERATOR_MLX_LLM_LOAD_MODEL'
|
|
17
|
+
params?: Array<
|
|
18
|
+
| {
|
|
19
|
+
input: 'modelId'
|
|
20
|
+
value?: string | DataLink | EventProperty
|
|
21
|
+
mapping?: string
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
input: 'vlm'
|
|
25
|
+
value?: boolean | DataLink | EventProperty
|
|
26
|
+
mapping?: string
|
|
27
|
+
}
|
|
28
|
+
>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Run text completion */
|
|
32
|
+
export type GeneratorMlxLLMActionCompletion = ActionWithParams & {
|
|
33
|
+
__actionName: 'GENERATOR_MLX_LLM_COMPLETION'
|
|
34
|
+
params?: Array<
|
|
35
|
+
| {
|
|
36
|
+
input: 'messages'
|
|
37
|
+
value?: Array<any> | DataLink | EventProperty
|
|
38
|
+
mapping?: string
|
|
39
|
+
}
|
|
40
|
+
| {
|
|
41
|
+
input: 'tools'
|
|
42
|
+
value?: Array<any> | DataLink | EventProperty
|
|
43
|
+
mapping?: string
|
|
44
|
+
}
|
|
45
|
+
| {
|
|
46
|
+
input: 'maxTokens'
|
|
47
|
+
value?: number | DataLink | EventProperty
|
|
48
|
+
mapping?: string
|
|
49
|
+
}
|
|
50
|
+
| {
|
|
51
|
+
input: 'temperature'
|
|
52
|
+
value?: number | DataLink | EventProperty
|
|
53
|
+
mapping?: string
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
input: 'topP'
|
|
57
|
+
value?: number | DataLink | EventProperty
|
|
58
|
+
mapping?: string
|
|
59
|
+
}
|
|
60
|
+
| {
|
|
61
|
+
input: 'repetitionPenalty'
|
|
62
|
+
value?: number | DataLink | EventProperty
|
|
63
|
+
mapping?: string
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Stop text completion */
|
|
69
|
+
export type GeneratorMlxLLMActionStopCompletion = Action & {
|
|
70
|
+
__actionName: 'GENERATOR_MLX_LLM_STOP_COMPLETION'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Release model context */
|
|
74
|
+
export type GeneratorMlxLLMActionReleaseContext = Action & {
|
|
75
|
+
__actionName: 'GENERATOR_MLX_LLM_RELEASE_CONTEXT'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface GeneratorMlxLLMDef {
|
|
79
|
+
/*
|
|
80
|
+
Default property:
|
|
81
|
+
{
|
|
82
|
+
"init": false,
|
|
83
|
+
"modelId": "mlx-community/Qwen3-4B-4bit",
|
|
84
|
+
"vlm": false,
|
|
85
|
+
"completionMessages": [
|
|
86
|
+
{
|
|
87
|
+
"role": "system",
|
|
88
|
+
"content": "You are a helpful assistant."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"role": "user",
|
|
92
|
+
"content": "Hello"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"completionMaxTokens": 1024,
|
|
96
|
+
"completionTemperature": 0.6,
|
|
97
|
+
"completionTopP": 1,
|
|
98
|
+
"completionRepetitionContextSize": 20
|
|
99
|
+
}
|
|
100
|
+
*/
|
|
101
|
+
property?: {
|
|
102
|
+
/* Initialize model on generator init */
|
|
103
|
+
init?: boolean | DataLink
|
|
104
|
+
/* HuggingFace model ID or local path to model directory
|
|
105
|
+
e.g. "mlx-community/Qwen3-4B-4bit" */
|
|
106
|
+
modelId?: string | DataLink
|
|
107
|
+
/* Enable Vision Language Model (VLM) mode */
|
|
108
|
+
vlm?: boolean | DataLink
|
|
109
|
+
/* Chat messages (if first message has role 'system', it will be used as system prompt) */
|
|
110
|
+
completionMessages?:
|
|
111
|
+
| Array<
|
|
112
|
+
| DataLink
|
|
113
|
+
| {
|
|
114
|
+
role?: string | DataLink
|
|
115
|
+
content?: string | DataLink
|
|
116
|
+
}
|
|
117
|
+
>
|
|
118
|
+
| DataLink
|
|
119
|
+
/* Maximum tokens to generate */
|
|
120
|
+
completionMaxTokens?: number | DataLink
|
|
121
|
+
/* Temperature (0.0 to 2.0) */
|
|
122
|
+
completionTemperature?: number | DataLink
|
|
123
|
+
/* Top P sampling */
|
|
124
|
+
completionTopP?: number | DataLink
|
|
125
|
+
/* Repetition penalty factor */
|
|
126
|
+
completionRepetitionPenalty?: number | DataLink
|
|
127
|
+
/* Number of tokens to consider for repetition penalty */
|
|
128
|
+
completionRepetitionContextSize?: number | DataLink
|
|
129
|
+
/* Maximum KV cache size (context window). Uses rotating cache to limit memory.
|
|
130
|
+
Smaller values (e.g. 512) use less memory but lower quality.
|
|
131
|
+
Larger values (e.g. 4096) use more memory but better quality.
|
|
132
|
+
Leave empty for unlimited (model default). */
|
|
133
|
+
contextSize?: number | DataLink
|
|
134
|
+
/* Enable thinking mode (model-dependent, e.g. Qwen3).
|
|
135
|
+
When enabled, passes enable_thinking=true to the chat template.
|
|
136
|
+
The model may output reasoning in <think> tags which will be extracted as reasoning_content. */
|
|
137
|
+
completionEnableThinking?: boolean | DataLink
|
|
138
|
+
/* Additional keyword arguments for chat template (object) */
|
|
139
|
+
completionChatTemplateKwargs?: {} | DataLink
|
|
140
|
+
/* Tools for chat mode using OpenAI-compatible function calling format
|
|
141
|
+
Format: Array of objects with {type, function: {name, description, parameters}} structure
|
|
142
|
+
See: https://platform.openai.com/docs/guides/function-calling */
|
|
143
|
+
completionTools?: Array<{} | DataLink> | DataLink
|
|
144
|
+
/* Buttress connection settings for remote inference */
|
|
145
|
+
buttressConnectionSettings?:
|
|
146
|
+
| DataLink
|
|
147
|
+
| {
|
|
148
|
+
enabled?: boolean | DataLink
|
|
149
|
+
url?: string | DataLink
|
|
150
|
+
fallbackType?: 'use-local' | 'no-op' | DataLink
|
|
151
|
+
strategy?: 'prefer-local' | 'prefer-buttress' | 'prefer-best' | DataLink
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
events?: {
|
|
155
|
+
/* Event triggered when context state changes */
|
|
156
|
+
onContextStateChange?: Array<EventAction>
|
|
157
|
+
/* Error event */
|
|
158
|
+
onError?: Array<EventAction>
|
|
159
|
+
/* Completion streaming event (emitted for each token) */
|
|
160
|
+
onCompletion?: Array<EventAction>
|
|
161
|
+
/* Completion finished event */
|
|
162
|
+
onCompletionFinished?: Array<EventAction>
|
|
163
|
+
}
|
|
164
|
+
outlets?: {
|
|
165
|
+
/* Context state */
|
|
166
|
+
contextState?: () => Data
|
|
167
|
+
/* Model load progress (0-1) */
|
|
168
|
+
loadProgress?: () => Data
|
|
169
|
+
/* Whether the model is evaluating */
|
|
170
|
+
isEvaluating?: () => Data
|
|
171
|
+
/* Completion result */
|
|
172
|
+
completionResult?: () => Data
|
|
173
|
+
/* Last token */
|
|
174
|
+
completionLastToken?: () => Data
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* On-device LLM inference using Apple MLX framework on iOS/tvOS
|
|
179
|
+
|
|
180
|
+
## Features
|
|
181
|
+
- Powered by MLX (Apple's ML framework optimized for Apple Silicon)
|
|
182
|
+
- Download models directly from HuggingFace Hub
|
|
183
|
+
- Streaming token generation
|
|
184
|
+
- Supports LLM and VLM (Vision Language Models)
|
|
185
|
+
- Requires iOS 17+ or tvOS 17+ */
|
|
186
|
+
export type GeneratorMlxLLM = Generator &
|
|
187
|
+
GeneratorMlxLLMDef & {
|
|
188
|
+
templateKey: 'GENERATOR_MLX_LLM'
|
|
189
|
+
switches?: Array<
|
|
190
|
+
SwitchDef &
|
|
191
|
+
GeneratorMlxLLMDef & {
|
|
192
|
+
conds?: Array<{
|
|
193
|
+
method: '==' | '!=' | '>' | '<' | '>=' | '<='
|
|
194
|
+
cond:
|
|
195
|
+
| SwitchCondInnerStateCurrentCanvas
|
|
196
|
+
| SwitchCondData
|
|
197
|
+
| {
|
|
198
|
+
__typename: 'SwitchCondInnerStateOutlet'
|
|
199
|
+
outlet:
|
|
200
|
+
| 'contextState'
|
|
201
|
+
| 'loadProgress'
|
|
202
|
+
| 'isEvaluating'
|
|
203
|
+
| 'completionResult'
|
|
204
|
+
| 'completionLastToken'
|
|
205
|
+
value: any
|
|
206
|
+
}
|
|
207
|
+
}>
|
|
208
|
+
}
|
|
209
|
+
>
|
|
210
|
+
}
|
|
@@ -44,6 +44,7 @@ export * from './RealtimeTranscription'
|
|
|
44
44
|
export * from './LlmGgml'
|
|
45
45
|
export * from './TextToSpeechGgml'
|
|
46
46
|
export * from './RerankerGgml'
|
|
47
|
+
export * from './LlmMlx'
|
|
47
48
|
export * from './LlmQualcommAiEngine'
|
|
48
49
|
export * from './LlmOpenAiCompat'
|
|
49
50
|
export * from './TextToSpeechOpenAiLike'
|
package/utils/event-props.ts
CHANGED
|
@@ -905,6 +905,22 @@ export const templateEventPropsMap = {
|
|
|
905
905
|
'GENERATOR_RERANKER_ERROR', // type: string
|
|
906
906
|
],
|
|
907
907
|
},
|
|
908
|
+
GENERATOR_MLX_LLM: {
|
|
909
|
+
onContextStateChange: [
|
|
910
|
+
'GENERATOR_MLX_LLM_CONTEXT_STATE', // type: string
|
|
911
|
+
],
|
|
912
|
+
onError: [
|
|
913
|
+
'GENERATOR_MLX_LLM_ERROR', // type: string
|
|
914
|
+
],
|
|
915
|
+
onCompletion: [
|
|
916
|
+
'GENERATOR_MLX_LLM_COMPLETION_TOKEN', // type: string
|
|
917
|
+
'GENERATOR_MLX_LLM_COMPLETION_RESULT', // type: string
|
|
918
|
+
],
|
|
919
|
+
onCompletionFinished: [
|
|
920
|
+
'GENERATOR_MLX_LLM_COMPLETION_RESULT', // type: string
|
|
921
|
+
'GENERATOR_MLX_LLM_COMPLETION_RESULT_DETAILS', // type: object
|
|
922
|
+
],
|
|
923
|
+
},
|
|
908
924
|
GENERATOR_QNN_LLM: {
|
|
909
925
|
onContextStateChange: [
|
|
910
926
|
'GENERATOR_QNN_LLM_CONTEXT_STATE', // type: string
|