edgeflowjs 0.1.0 → 0.3.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/README.md +200 -66
- package/dist/backends/index.d.ts +9 -2
- package/dist/backends/index.d.ts.map +1 -1
- package/dist/backends/index.js +13 -13
- package/dist/backends/index.js.map +1 -1
- package/dist/backends/onnx.d.ts +49 -4
- package/dist/backends/onnx.d.ts.map +1 -1
- package/dist/backends/onnx.js +165 -76
- package/dist/backends/onnx.js.map +1 -1
- package/dist/backends/transformers-adapter.d.ts +99 -0
- package/dist/backends/transformers-adapter.d.ts.map +1 -0
- package/dist/backends/transformers-adapter.js +171 -0
- package/dist/backends/transformers-adapter.js.map +1 -0
- package/dist/backends/webgpu.d.ts +7 -5
- package/dist/backends/webgpu.d.ts.map +1 -1
- package/dist/backends/webgpu.js +7 -5
- package/dist/backends/webgpu.js.map +1 -1
- package/dist/backends/webnn.d.ts +6 -5
- package/dist/backends/webnn.d.ts.map +1 -1
- package/dist/backends/webnn.js +6 -5
- package/dist/backends/webnn.js.map +1 -1
- package/dist/core/composer.d.ts +118 -0
- package/dist/core/composer.d.ts.map +1 -0
- package/dist/core/composer.js +163 -0
- package/dist/core/composer.js.map +1 -0
- package/dist/core/device-profiler.d.ts +75 -0
- package/dist/core/device-profiler.d.ts.map +1 -0
- package/dist/core/device-profiler.js +131 -0
- package/dist/core/device-profiler.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/memory.d.ts +22 -2
- package/dist/core/memory.d.ts.map +1 -1
- package/dist/core/memory.js +49 -13
- package/dist/core/memory.js.map +1 -1
- package/dist/core/plugin.d.ts +100 -0
- package/dist/core/plugin.d.ts.map +1 -0
- package/dist/core/plugin.js +106 -0
- package/dist/core/plugin.js.map +1 -0
- package/dist/core/runtime.d.ts +4 -0
- package/dist/core/runtime.d.ts.map +1 -1
- package/dist/core/runtime.js +18 -0
- package/dist/core/runtime.js.map +1 -1
- package/dist/core/scheduler.d.ts +17 -0
- package/dist/core/scheduler.d.ts.map +1 -1
- package/dist/core/scheduler.js +101 -3
- package/dist/core/scheduler.js.map +1 -1
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker.d.ts +202 -0
- package/dist/core/worker.d.ts.map +1 -0
- package/dist/core/worker.js +477 -0
- package/dist/core/worker.js.map +1 -0
- package/dist/edgeflow.browser.js +9789 -4379
- package/dist/edgeflow.browser.js.map +4 -4
- package/dist/edgeflow.browser.min.js +435 -5
- package/dist/edgeflow.browser.min.js.map +4 -4
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -12
- package/dist/index.js.map +1 -1
- package/dist/pipelines/automatic-speech-recognition.d.ts +63 -0
- package/dist/pipelines/automatic-speech-recognition.d.ts.map +1 -0
- package/dist/pipelines/automatic-speech-recognition.js +269 -0
- package/dist/pipelines/automatic-speech-recognition.js.map +1 -0
- package/dist/pipelines/base.d.ts +6 -1
- package/dist/pipelines/base.d.ts.map +1 -1
- package/dist/pipelines/base.js +12 -2
- package/dist/pipelines/base.js.map +1 -1
- package/dist/pipelines/feature-extraction.d.ts +5 -40
- package/dist/pipelines/feature-extraction.d.ts.map +1 -1
- package/dist/pipelines/feature-extraction.js +44 -63
- package/dist/pipelines/feature-extraction.js.map +1 -1
- package/dist/pipelines/image-classification.d.ts +4 -36
- package/dist/pipelines/image-classification.d.ts.map +1 -1
- package/dist/pipelines/image-classification.js +22 -60
- package/dist/pipelines/image-classification.js.map +1 -1
- package/dist/pipelines/image-segmentation.d.ts +221 -0
- package/dist/pipelines/image-segmentation.d.ts.map +1 -0
- package/dist/pipelines/image-segmentation.js +535 -0
- package/dist/pipelines/image-segmentation.js.map +1 -0
- package/dist/pipelines/index.d.ts +18 -0
- package/dist/pipelines/index.d.ts.map +1 -1
- package/dist/pipelines/index.js +51 -2
- package/dist/pipelines/index.js.map +1 -1
- package/dist/pipelines/object-detection.d.ts +44 -0
- package/dist/pipelines/object-detection.d.ts.map +1 -0
- package/dist/pipelines/object-detection.js +218 -0
- package/dist/pipelines/object-detection.js.map +1 -0
- package/dist/pipelines/question-answering.d.ts +41 -0
- package/dist/pipelines/question-answering.d.ts.map +1 -0
- package/dist/pipelines/question-answering.js +164 -0
- package/dist/pipelines/question-answering.js.map +1 -0
- package/dist/pipelines/text-classification.d.ts +3 -39
- package/dist/pipelines/text-classification.d.ts.map +1 -1
- package/dist/pipelines/text-classification.js +29 -67
- package/dist/pipelines/text-classification.js.map +1 -1
- package/dist/pipelines/text-generation.d.ts +281 -0
- package/dist/pipelines/text-generation.d.ts.map +1 -0
- package/dist/pipelines/text-generation.js +766 -0
- package/dist/pipelines/text-generation.js.map +1 -0
- package/dist/pipelines/zero-shot-classification.d.ts +45 -0
- package/dist/pipelines/zero-shot-classification.d.ts.map +1 -0
- package/dist/pipelines/zero-shot-classification.js +140 -0
- package/dist/pipelines/zero-shot-classification.js.map +1 -0
- package/dist/tools/benchmark.d.ts +92 -0
- package/dist/tools/benchmark.d.ts.map +1 -0
- package/dist/tools/benchmark.js +213 -0
- package/dist/tools/benchmark.js.map +1 -0
- package/dist/tools/debugger.d.ts +258 -0
- package/dist/tools/debugger.d.ts.map +1 -0
- package/dist/tools/debugger.js +624 -0
- package/dist/tools/debugger.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/monitor.d.ts +284 -0
- package/dist/tools/monitor.d.ts.map +1 -0
- package/dist/tools/monitor.js +921 -0
- package/dist/tools/monitor.js.map +1 -0
- package/dist/tools/quantization.d.ts +235 -0
- package/dist/tools/quantization.d.ts.map +1 -0
- package/dist/tools/quantization.js +830 -0
- package/dist/tools/quantization.js.map +1 -0
- package/dist/utils/hub.d.ts +162 -0
- package/dist/utils/hub.d.ts.map +1 -0
- package/dist/utils/hub.js +311 -0
- package/dist/utils/hub.js.map +1 -0
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +5 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/model-loader.d.ts.map +1 -1
- package/dist/utils/model-loader.js +106 -30
- package/dist/utils/model-loader.js.map +1 -1
- package/dist/utils/offline.d.ts +147 -0
- package/dist/utils/offline.d.ts.map +1 -0
- package/dist/utils/offline.js +405 -0
- package/dist/utils/offline.js.map +1 -0
- package/dist/utils/preprocessor.d.ts +82 -6
- package/dist/utils/preprocessor.d.ts.map +1 -1
- package/dist/utils/preprocessor.js +278 -21
- package/dist/utils/preprocessor.js.map +1 -1
- package/dist/utils/tokenizer.d.ts +197 -72
- package/dist/utils/tokenizer.d.ts.map +1 -1
- package/dist/utils/tokenizer.js +558 -274
- package/dist/utils/tokenizer.js.map +1 -1
- package/package.json +26 -11
package/README.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Browser ML inference framework with task scheduling and smart caching.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/edgeflowjs)
|
|
8
|
-
[](https://packagephobia.com/result?p=edgeflowjs)
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
|
|
11
11
|
[Documentation](https://edgeflow.js.org) · [Examples](examples/) · [API Reference](https://edgeflow.js.org/api) · [English](README.md) | [中文](README_CN.md)
|
|
@@ -16,30 +16,34 @@
|
|
|
16
16
|
|
|
17
17
|
## ✨ Features
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
19
|
+
- 📋 **Task Scheduler** - Priority queue, concurrency control, task cancellation
|
|
20
|
+
- 🔄 **Batch Processing** - Efficient batch inference out of the box
|
|
21
|
+
- 💾 **Memory Management** - Automatic memory tracking and cleanup with scopes
|
|
22
|
+
- 📥 **Smart Model Loading** - Preloading, sharding, resume download support
|
|
23
|
+
- 💿 **Offline Caching** - IndexedDB-based model caching for offline use
|
|
24
|
+
- ⚡ **Multi-Backend** - ONNX Runtime with WebGPU/WASM execution providers, automatic fallback
|
|
25
|
+
- 🤗 **HuggingFace Hub** - Direct model download with one line
|
|
26
|
+
- 🔤 **Real Tokenizers** - BPE & WordPiece tokenizers, load tokenizer.json directly
|
|
27
|
+
- 👷 **Web Worker Support** - Run inference in background threads
|
|
28
|
+
- 📦 **Batteries Included** - ONNX Runtime bundled, zero configuration needed
|
|
29
|
+
- 🎯 **TypeScript First** - Full type support with intuitive APIs
|
|
28
30
|
|
|
29
31
|
## 📦 Installation
|
|
30
32
|
|
|
31
33
|
```bash
|
|
32
|
-
npm install
|
|
34
|
+
npm install edgeflowjs
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
yarn add
|
|
38
|
+
yarn add edgeflowjs
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
```bash
|
|
40
|
-
pnpm add
|
|
42
|
+
pnpm add edgeflowjs
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
> **Note**: ONNX Runtime is included as a dependency. No additional setup required.
|
|
46
|
+
|
|
43
47
|
## 🚀 Quick Start
|
|
44
48
|
|
|
45
49
|
### Try the Demo
|
|
@@ -67,14 +71,14 @@ Open **http://localhost:3000** in your browser:
|
|
|
67
71
|
- 🧮 **Tensor Operations** - Test tensor creation, math ops, softmax, relu
|
|
68
72
|
- 📝 **Text Classification** - Run sentiment analysis on text
|
|
69
73
|
- 🔍 **Feature Extraction** - Extract embeddings from text
|
|
70
|
-
- ⚡ **
|
|
74
|
+
- ⚡ **Task Scheduling** - Test priority-based scheduling
|
|
71
75
|
- 📋 **Task Scheduler** - Test priority-based task scheduling
|
|
72
76
|
- 💾 **Memory Management** - Test allocation and cleanup
|
|
73
77
|
|
|
74
78
|
### Basic Usage
|
|
75
79
|
|
|
76
80
|
```typescript
|
|
77
|
-
import { pipeline } from '
|
|
81
|
+
import { pipeline } from 'edgeflowjs';
|
|
78
82
|
|
|
79
83
|
// Create a sentiment analysis pipeline
|
|
80
84
|
const sentiment = await pipeline('sentiment-analysis');
|
|
@@ -103,16 +107,16 @@ console.log(results);
|
|
|
103
107
|
// ]
|
|
104
108
|
```
|
|
105
109
|
|
|
106
|
-
###
|
|
110
|
+
### Multiple Pipelines
|
|
107
111
|
|
|
108
112
|
```typescript
|
|
109
|
-
import { pipeline } from '
|
|
113
|
+
import { pipeline } from 'edgeflowjs';
|
|
110
114
|
|
|
111
115
|
// Create multiple pipelines
|
|
112
116
|
const classifier = await pipeline('text-classification');
|
|
113
117
|
const extractor = await pipeline('feature-extraction');
|
|
114
118
|
|
|
115
|
-
// Run
|
|
119
|
+
// Run in parallel with Promise.all
|
|
116
120
|
const [classification, features] = await Promise.all([
|
|
117
121
|
classifier.run('Sample text'),
|
|
118
122
|
extractor.run('Sample text')
|
|
@@ -122,7 +126,7 @@ const [classification, features] = await Promise.all([
|
|
|
122
126
|
### Image Classification
|
|
123
127
|
|
|
124
128
|
```typescript
|
|
125
|
-
import { pipeline } from '
|
|
129
|
+
import { pipeline } from 'edgeflowjs';
|
|
126
130
|
|
|
127
131
|
const classifier = await pipeline('image-classification');
|
|
128
132
|
|
|
@@ -137,48 +141,159 @@ const result = await classifier.run(img);
|
|
|
137
141
|
const results = await classifier.run([img1, img2, img3]);
|
|
138
142
|
```
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
### Text Generation (Streaming)
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
```typescript
|
|
147
|
+
import { pipeline } from 'edgeflowjs';
|
|
148
|
+
|
|
149
|
+
const generator = await pipeline('text-generation');
|
|
150
|
+
|
|
151
|
+
// Simple generation
|
|
152
|
+
const result = await generator.run('Once upon a time', {
|
|
153
|
+
maxNewTokens: 50,
|
|
154
|
+
temperature: 0.8,
|
|
155
|
+
});
|
|
156
|
+
console.log(result.generatedText);
|
|
157
|
+
|
|
158
|
+
// Streaming output
|
|
159
|
+
for await (const event of generator.stream('Hello, ')) {
|
|
160
|
+
process.stdout.write(event.token);
|
|
161
|
+
if (event.done) break;
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Zero-shot Classification
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { pipeline } from 'edgeflowjs';
|
|
151
169
|
|
|
152
|
-
|
|
170
|
+
const classifier = await pipeline('zero-shot-classification');
|
|
153
171
|
|
|
154
|
-
|
|
172
|
+
const result = await classifier.classify(
|
|
173
|
+
'I love playing soccer on weekends',
|
|
174
|
+
['sports', 'politics', 'technology', 'entertainment']
|
|
175
|
+
);
|
|
155
176
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
| Batch Processing | ⚠️ Partial | ✅ Native |
|
|
160
|
-
| Memory Management | ⚠️ Basic | ✅ Complete |
|
|
161
|
-
| Bundle Size | ~2-5MB | <500KB |
|
|
162
|
-
| Dependencies | ONNX Runtime | Optional |
|
|
177
|
+
console.log(result.labels[0], result.scores[0]);
|
|
178
|
+
// 'sports', 0.92
|
|
179
|
+
```
|
|
163
180
|
|
|
164
|
-
###
|
|
181
|
+
### Question Answering
|
|
165
182
|
|
|
183
|
+
```typescript
|
|
184
|
+
import { pipeline } from 'edgeflowjs';
|
|
185
|
+
|
|
186
|
+
const qa = await pipeline('question-answering');
|
|
187
|
+
|
|
188
|
+
const result = await qa.run({
|
|
189
|
+
question: 'What is the capital of France?',
|
|
190
|
+
context: 'Paris is the capital and largest city of France.'
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
console.log(result.answer); // 'Paris'
|
|
166
194
|
```
|
|
167
|
-
Text Classification (BERT-base):
|
|
168
|
-
- transformers.js: 45ms (serial)
|
|
169
|
-
- edgeFlow.js: 42ms (parallel capable)
|
|
170
195
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
196
|
+
### Load from HuggingFace Hub
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { fromHub, fromTask } from 'edgeflowjs';
|
|
200
|
+
|
|
201
|
+
// Load by model ID (auto-downloads model, tokenizer, config)
|
|
202
|
+
const bundle = await fromHub('Xenova/distilbert-base-uncased-finetuned-sst-2-english');
|
|
203
|
+
console.log(bundle.tokenizer); // Tokenizer instance
|
|
204
|
+
console.log(bundle.config); // Model config
|
|
205
|
+
|
|
206
|
+
// Load by task name (uses recommended model)
|
|
207
|
+
const sentimentBundle = await fromTask('sentiment-analysis');
|
|
174
208
|
```
|
|
175
209
|
|
|
210
|
+
### Web Workers (Background Inference)
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
import { runInWorker, WorkerPool, isWorkerSupported } from 'edgeflowjs';
|
|
214
|
+
|
|
215
|
+
// Simple: run inference in background thread
|
|
216
|
+
if (isWorkerSupported()) {
|
|
217
|
+
const outputs = await runInWorker(modelUrl, inputs);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Advanced: use worker pool for parallel processing
|
|
221
|
+
const pool = new WorkerPool({ numWorkers: 4 });
|
|
222
|
+
await pool.init();
|
|
223
|
+
|
|
224
|
+
const modelId = await pool.loadModel(modelUrl);
|
|
225
|
+
const results = await pool.runBatch(modelId, batchInputs);
|
|
226
|
+
|
|
227
|
+
pool.terminate();
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 🎯 Supported Tasks
|
|
231
|
+
|
|
232
|
+
| Task | Pipeline | Status |
|
|
233
|
+
|------|----------|--------|
|
|
234
|
+
| Text Generation | `text-generation` | ✅ Production (TinyLlama, streaming, KV cache) |
|
|
235
|
+
| Image Segmentation | `image-segmentation` | ✅ Production (SlimSAM, interactive prompts) |
|
|
236
|
+
| Text Classification | `text-classification` | ⚠️ Experimental (heuristic, provide own model) |
|
|
237
|
+
| Sentiment Analysis | `sentiment-analysis` | ⚠️ Experimental (heuristic, provide own model) |
|
|
238
|
+
| Feature Extraction | `feature-extraction` | ⚠️ Experimental (mock embeddings, provide own model) |
|
|
239
|
+
| Image Classification | `image-classification` | ⚠️ Experimental (heuristic, provide own model) |
|
|
240
|
+
| Object Detection | `object-detection` | ⚠️ Experimental (real NMS/IoU, needs own model) |
|
|
241
|
+
| Speech Recognition | `automatic-speech-recognition` | ⚠️ Experimental (preprocessing only, needs model) |
|
|
242
|
+
| Zero-shot Classification | `zero-shot-classification` | ⚠️ Experimental (random scoring, needs NLI model) |
|
|
243
|
+
| Question Answering | `question-answering` | ⚠️ Experimental (word overlap heuristic, needs model) |
|
|
244
|
+
|
|
245
|
+
> **Note:** Experimental pipelines work for demos and testing the API surface. For production accuracy, provide a real ONNX model via `options.model` or use the **transformers.js adapter backend** to leverage HuggingFace's model ecosystem.
|
|
246
|
+
|
|
247
|
+
## ⚡ Key Differentiators
|
|
248
|
+
|
|
249
|
+
edgeFlow.js is not a replacement for transformers.js — it is a **production orchestration layer** that can wrap any inference engine (including transformers.js) and add the features real apps need.
|
|
250
|
+
|
|
251
|
+
### What edgeFlow.js adds on top of inference engines
|
|
252
|
+
|
|
253
|
+
| Feature | Inference engines alone | With edgeFlow.js |
|
|
254
|
+
|---------|------------------------|------------------|
|
|
255
|
+
| Task Scheduling | None — run and hope | Priority queue with concurrency limits |
|
|
256
|
+
| Task Cancellation | Not possible | Cancel pending/queued tasks |
|
|
257
|
+
| Batch Processing | Manual | Built-in batching with configurable size |
|
|
258
|
+
| Memory Management | Manual cleanup | Automatic scopes, leak detection, GC hints |
|
|
259
|
+
| Model Preloading | Manual | Background preloading with priority queue |
|
|
260
|
+
| Resume Download | Start over on failure | Chunked download with automatic resume |
|
|
261
|
+
| Model Caching | Basic or none | IndexedDB cache with stats and eviction |
|
|
262
|
+
| Pipeline Composition | Not available | Chain multiple models (ASR → translate → TTS) |
|
|
263
|
+
| Device Adaptation | Manual model selection | Auto-select model variant by device capability |
|
|
264
|
+
| Performance Monitoring | External tooling needed | Built-in dashboard and alerting |
|
|
265
|
+
|
|
266
|
+
## 🔌 transformers.js Adapter (Recommended)
|
|
267
|
+
|
|
268
|
+
Use edgeFlow.js as an orchestration layer on top of [transformers.js](https://huggingface.co/docs/transformers.js) to get access to 1000+ HuggingFace models with scheduling, caching, and memory management:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { pipeline as tfPipeline } from '@xenova/transformers';
|
|
272
|
+
import { useTransformersBackend, pipeline } from 'edgeflowjs';
|
|
273
|
+
|
|
274
|
+
// Register transformers.js as the inference backend
|
|
275
|
+
useTransformersBackend({
|
|
276
|
+
pipelineFactory: tfPipeline,
|
|
277
|
+
device: 'webgpu', // GPU acceleration
|
|
278
|
+
dtype: 'fp16', // Half precision
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Use edgeFlow.js API — scheduling, caching, memory management included
|
|
282
|
+
const classifier = await pipeline('text-classification', {
|
|
283
|
+
model: 'Xenova/distilbert-base-uncased-finetuned-sst-2-english',
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const result = await classifier.run('I love this product!');
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> **Why?** transformers.js is excellent at loading and running single models. edgeFlow.js adds the production features you need when running multiple models, managing memory on constrained devices, caching for offline use, and scheduling concurrent inference.
|
|
290
|
+
|
|
176
291
|
## 🔧 Configuration
|
|
177
292
|
|
|
178
293
|
### Runtime Selection
|
|
179
294
|
|
|
180
295
|
```typescript
|
|
181
|
-
import { pipeline } from '
|
|
296
|
+
import { pipeline } from 'edgeflowjs';
|
|
182
297
|
|
|
183
298
|
// Automatic (recommended)
|
|
184
299
|
const model = await pipeline('text-classification');
|
|
@@ -192,7 +307,7 @@ const model = await pipeline('text-classification', {
|
|
|
192
307
|
### Memory Management
|
|
193
308
|
|
|
194
309
|
```typescript
|
|
195
|
-
import { pipeline, getMemoryStats, gc } from '
|
|
310
|
+
import { pipeline, getMemoryStats, gc } from 'edgeflowjs';
|
|
196
311
|
|
|
197
312
|
const model = await pipeline('text-classification');
|
|
198
313
|
|
|
@@ -213,7 +328,7 @@ gc();
|
|
|
213
328
|
### Scheduler Configuration
|
|
214
329
|
|
|
215
330
|
```typescript
|
|
216
|
-
import { configureScheduler } from '
|
|
331
|
+
import { configureScheduler } from 'edgeflowjs';
|
|
217
332
|
|
|
218
333
|
configureScheduler({
|
|
219
334
|
maxConcurrentTasks: 4,
|
|
@@ -227,7 +342,7 @@ configureScheduler({
|
|
|
227
342
|
### Caching
|
|
228
343
|
|
|
229
344
|
```typescript
|
|
230
|
-
import { pipeline, Cache } from '
|
|
345
|
+
import { pipeline, Cache } from 'edgeflowjs';
|
|
231
346
|
|
|
232
347
|
// Create a cache
|
|
233
348
|
const cache = new Cache({
|
|
@@ -246,7 +361,7 @@ const model = await pipeline('text-classification', {
|
|
|
246
361
|
### Custom Model Loading
|
|
247
362
|
|
|
248
363
|
```typescript
|
|
249
|
-
import { loadModel, runInference } from '
|
|
364
|
+
import { loadModel, runInference } from 'edgeflowjs';
|
|
250
365
|
|
|
251
366
|
// Load from URL with caching, sharding, and resume support
|
|
252
367
|
const model = await loadModel('https://example.com/model.bin', {
|
|
@@ -268,7 +383,7 @@ model.dispose();
|
|
|
268
383
|
### Preloading Models
|
|
269
384
|
|
|
270
385
|
```typescript
|
|
271
|
-
import { preloadModel, preloadModels, getPreloadStatus } from '
|
|
386
|
+
import { preloadModel, preloadModels, getPreloadStatus } from 'edgeflowjs';
|
|
272
387
|
|
|
273
388
|
// Preload a single model in background (with priority)
|
|
274
389
|
preloadModel('https://example.com/model1.onnx', { priority: 10 });
|
|
@@ -293,7 +408,7 @@ import {
|
|
|
293
408
|
deleteCachedModel,
|
|
294
409
|
clearModelCache,
|
|
295
410
|
getModelCacheStats
|
|
296
|
-
} from '
|
|
411
|
+
} from 'edgeflowjs';
|
|
297
412
|
|
|
298
413
|
// Check if model is cached
|
|
299
414
|
if (await isModelCached('https://example.com/model.onnx')) {
|
|
@@ -319,7 +434,7 @@ console.log(`${stats.models} models cached, ${stats.totalSize} bytes total`);
|
|
|
319
434
|
Large model downloads automatically support resuming from where they left off:
|
|
320
435
|
|
|
321
436
|
```typescript
|
|
322
|
-
import { loadModelData } from '
|
|
437
|
+
import { loadModelData } from 'edgeflowjs';
|
|
323
438
|
|
|
324
439
|
// Download with progress and resume support
|
|
325
440
|
const modelData = await loadModelData('https://example.com/large-model.onnx', {
|
|
@@ -338,7 +453,7 @@ const modelData = await loadModelData('https://example.com/large-model.onnx', {
|
|
|
338
453
|
### Model Quantization
|
|
339
454
|
|
|
340
455
|
```typescript
|
|
341
|
-
import { quantize } from '
|
|
456
|
+
import { quantize } from 'edgeflowjs/tools';
|
|
342
457
|
|
|
343
458
|
const quantized = await quantize(model, {
|
|
344
459
|
method: 'int8',
|
|
@@ -352,7 +467,7 @@ console.log(`Compression: ${quantized.compressionRatio}x`);
|
|
|
352
467
|
### Benchmarking
|
|
353
468
|
|
|
354
469
|
```typescript
|
|
355
|
-
import { benchmark } from '
|
|
470
|
+
import { benchmark } from 'edgeflowjs/tools';
|
|
356
471
|
|
|
357
472
|
const result = await benchmark(
|
|
358
473
|
() => model.run('sample text'),
|
|
@@ -371,7 +486,7 @@ console.log(result);
|
|
|
371
486
|
### Memory Scope
|
|
372
487
|
|
|
373
488
|
```typescript
|
|
374
|
-
import { withMemoryScope, tensor } from '
|
|
489
|
+
import { withMemoryScope, tensor } from 'edgeflowjs';
|
|
375
490
|
|
|
376
491
|
const result = await withMemoryScope(async (scope) => {
|
|
377
492
|
// Tensors tracked in scope
|
|
@@ -390,7 +505,7 @@ const result = await withMemoryScope(async (scope) => {
|
|
|
390
505
|
## 🔌 Tensor Operations
|
|
391
506
|
|
|
392
507
|
```typescript
|
|
393
|
-
import { tensor, zeros, ones, matmul, softmax, relu } from '
|
|
508
|
+
import { tensor, zeros, ones, matmul, softmax, relu } from 'edgeflowjs';
|
|
394
509
|
|
|
395
510
|
// Create tensors
|
|
396
511
|
const a = tensor([[1, 2], [3, 4]]);
|
|
@@ -417,6 +532,10 @@ c.dispose();
|
|
|
417
532
|
| Firefox 118+ | ⚠️ Flag | ❌ | ✅ |
|
|
418
533
|
| Safari 17+ | ⚠️ Preview | ❌ | ✅ |
|
|
419
534
|
|
|
535
|
+
## Star History
|
|
536
|
+
|
|
537
|
+
[](https://www.star-history.com/?repos=s-zx%2FedgeFlow.js&type=date&legend=top-left)
|
|
538
|
+
|
|
420
539
|
## 📖 API Reference
|
|
421
540
|
|
|
422
541
|
### Core
|
|
@@ -426,20 +545,35 @@ c.dispose();
|
|
|
426
545
|
- `runInference(model, inputs)` - Run model inference
|
|
427
546
|
- `getScheduler()` - Get the global scheduler
|
|
428
547
|
- `getMemoryManager()` - Get the memory manager
|
|
548
|
+
- `runInWorker(url, inputs)` - Run inference in a Web Worker
|
|
549
|
+
- `WorkerPool` - Manage multiple workers for parallel inference
|
|
429
550
|
|
|
430
551
|
### Pipelines
|
|
431
552
|
|
|
432
|
-
- `TextClassificationPipeline`
|
|
433
|
-
- `SentimentAnalysisPipeline`
|
|
434
|
-
- `FeatureExtractionPipeline`
|
|
435
|
-
- `ImageClassificationPipeline`
|
|
553
|
+
- `TextClassificationPipeline` - Text/sentiment classification
|
|
554
|
+
- `SentimentAnalysisPipeline` - Sentiment analysis
|
|
555
|
+
- `FeatureExtractionPipeline` - Text embeddings
|
|
556
|
+
- `ImageClassificationPipeline` - Image classification
|
|
557
|
+
- `TextGenerationPipeline` - Text generation with streaming
|
|
558
|
+
- `ObjectDetectionPipeline` - Object detection with bounding boxes
|
|
559
|
+
- `AutomaticSpeechRecognitionPipeline` - Speech to text
|
|
560
|
+
- `ZeroShotClassificationPipeline` - Classify without training
|
|
561
|
+
- `QuestionAnsweringPipeline` - Extractive QA
|
|
562
|
+
|
|
563
|
+
### HuggingFace Hub
|
|
564
|
+
|
|
565
|
+
- `fromHub(modelId, options?)` - Load model bundle from HuggingFace
|
|
566
|
+
- `fromTask(task, options?)` - Load recommended model for task
|
|
567
|
+
- `downloadTokenizer(modelId)` - Download tokenizer only
|
|
568
|
+
- `downloadConfig(modelId)` - Download config only
|
|
569
|
+
- `POPULAR_MODELS` - Registry of popular models by task
|
|
436
570
|
|
|
437
571
|
### Utilities
|
|
438
572
|
|
|
439
|
-
- `Tokenizer` -
|
|
440
|
-
- `ImagePreprocessor` - Image preprocessing
|
|
441
|
-
- `AudioPreprocessor` - Audio preprocessing
|
|
442
|
-
- `Cache` -
|
|
573
|
+
- `Tokenizer` - BPE/WordPiece tokenization with HuggingFace support
|
|
574
|
+
- `ImagePreprocessor` - Image preprocessing with HuggingFace config support
|
|
575
|
+
- `AudioPreprocessor` - Audio preprocessing for Whisper/wav2vec
|
|
576
|
+
- `Cache` - LRU caching utilities
|
|
443
577
|
|
|
444
578
|
### Tools
|
|
445
579
|
|
package/dist/backends/index.d.ts
CHANGED
|
@@ -4,10 +4,17 @@
|
|
|
4
4
|
export { WebGPURuntime, createWebGPURuntime } from './webgpu.js';
|
|
5
5
|
export { WebNNRuntime, createWebNNRuntime } from './webnn.js';
|
|
6
6
|
export { WASMRuntime, createWASMRuntime } from './wasm.js';
|
|
7
|
-
export { ONNXRuntime, createONNXRuntime } from './onnx.js';
|
|
7
|
+
export { ONNXRuntime, createONNXRuntime, isOnnxAvailable, setOnnxModule, configureOnnxAssets, type OnnxAssetPaths, } from './onnx.js';
|
|
8
|
+
export { TransformersAdapterRuntime, useTransformersBackend, getTransformersAdapter, type TransformersAdapterOptions, type TransformersPipelineFactory, } from './transformers-adapter.js';
|
|
8
9
|
export type { Runtime, RuntimeType, RuntimeCapabilities } from '../core/types.js';
|
|
9
10
|
/**
|
|
10
|
-
* Register all available backends
|
|
11
|
+
* Register all available backends.
|
|
12
|
+
*
|
|
13
|
+
* Always registers the ONNX Runtime factory synchronously so there is no
|
|
14
|
+
* async race between registration and the first pipeline() call.
|
|
15
|
+
* `ONNXRuntime.isAvailable()` is called lazily by RuntimeManager when it
|
|
16
|
+
* selects a backend, so if onnxruntime-web is not installed the runtime is
|
|
17
|
+
* simply skipped at that point.
|
|
11
18
|
*/
|
|
12
19
|
export declare function registerAllBackends(): void;
|
|
13
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3D,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,2BAA2B,CAAC;AAGnC,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAKlF;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
package/dist/backends/index.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* edgeFlow.js - Backend Exports
|
|
3
3
|
*/
|
|
4
|
-
// WebGPU Backend
|
|
4
|
+
// WebGPU Backend (planned - skeleton only)
|
|
5
5
|
export { WebGPURuntime, createWebGPURuntime } from './webgpu.js';
|
|
6
|
-
// WebNN Backend
|
|
6
|
+
// WebNN Backend (planned - skeleton only)
|
|
7
7
|
export { WebNNRuntime, createWebNNRuntime } from './webnn.js';
|
|
8
8
|
// WASM Backend (basic tensor ops)
|
|
9
9
|
export { WASMRuntime, createWASMRuntime } from './wasm.js';
|
|
10
10
|
// ONNX Runtime Backend (real model inference)
|
|
11
|
-
export { ONNXRuntime, createONNXRuntime } from './onnx.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
11
|
+
export { ONNXRuntime, createONNXRuntime, isOnnxAvailable, setOnnxModule, configureOnnxAssets, } from './onnx.js';
|
|
12
|
+
// transformers.js Adapter Backend
|
|
13
|
+
export { TransformersAdapterRuntime, useTransformersBackend, getTransformersAdapter, } from './transformers-adapter.js';
|
|
15
14
|
import { registerRuntime } from '../core/runtime.js';
|
|
16
|
-
import { createWebGPURuntime } from './webgpu.js';
|
|
17
|
-
import { createWebNNRuntime } from './webnn.js';
|
|
18
15
|
import { createONNXRuntime } from './onnx.js';
|
|
19
16
|
/**
|
|
20
|
-
* Register all available backends
|
|
17
|
+
* Register all available backends.
|
|
18
|
+
*
|
|
19
|
+
* Always registers the ONNX Runtime factory synchronously so there is no
|
|
20
|
+
* async race between registration and the first pipeline() call.
|
|
21
|
+
* `ONNXRuntime.isAvailable()` is called lazily by RuntimeManager when it
|
|
22
|
+
* selects a backend, so if onnxruntime-web is not installed the runtime is
|
|
23
|
+
* simply skipped at that point.
|
|
21
24
|
*/
|
|
22
25
|
export function registerAllBackends() {
|
|
23
|
-
registerRuntime('webgpu', createWebGPURuntime);
|
|
24
|
-
registerRuntime('webnn', createWebNNRuntime);
|
|
25
|
-
// Use ONNX Runtime as the WASM backend for real model inference
|
|
26
26
|
registerRuntime('wasm', createONNXRuntime);
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* Auto-register backends on module load
|
|
29
|
+
* Auto-register backends on module load (synchronous — no race condition).
|
|
30
30
|
*/
|
|
31
31
|
registerAllBackends();
|
|
32
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2CAA2C;AAC3C,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEjE,0CAA0C;AAC1C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9D,kCAAkC;AAClC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE3D,8CAA8C;AAC9C,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,mBAAmB,GAEpB,MAAM,WAAW,CAAC;AAEnB,kCAAkC;AAClC,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,GAGvB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB;IACjC,eAAe,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,mBAAmB,EAAE,CAAC"}
|
package/dist/backends/onnx.d.ts
CHANGED
|
@@ -2,12 +2,53 @@
|
|
|
2
2
|
* edgeFlow.js - ONNX Runtime Backend
|
|
3
3
|
*
|
|
4
4
|
* Uses onnxruntime-web for real ONNX model inference.
|
|
5
|
-
*
|
|
5
|
+
* onnxruntime-web is an optional peer dependency loaded dynamically.
|
|
6
6
|
*/
|
|
7
7
|
import { Runtime, RuntimeType, RuntimeCapabilities, LoadedModel, ModelLoadOptions, Tensor } from '../core/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Override paths for the onnxruntime-web WASM assets, mirroring ORT's
|
|
10
|
+
* `env.wasm.wasmPaths` object form. Set via {@link configureOnnxAssets}
|
|
11
|
+
* when the consumer's bundler emits content-hashed asset URLs (a bare
|
|
12
|
+
* directory prefix can't address those).
|
|
13
|
+
*/
|
|
14
|
+
export interface OnnxAssetPaths {
|
|
15
|
+
/** URL/path for the main `.wasm` binary. */
|
|
16
|
+
wasm?: string;
|
|
17
|
+
/** URL/path for the loader `.mjs` glue. */
|
|
18
|
+
mjs?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Inject a pre-imported onnxruntime-web module — the recommended
|
|
22
|
+
* integration path for Web Workers and custom bundler setups, where the
|
|
23
|
+
* internal dynamic `import('onnxruntime-web/wasm')` may be dropped.
|
|
24
|
+
*
|
|
25
|
+
* ONNX Runtime is an optional peer dependency that the consumer owns:
|
|
26
|
+
* once you inject a module, **you** own its configuration. Configure it
|
|
27
|
+
* first (`ort.env.wasm.wasmPaths`, `numThreads`, execution providers,
|
|
28
|
+
* ...) and the backend will use it as-is without overriding anything.
|
|
29
|
+
*
|
|
30
|
+
* import * as ort from "onnxruntime-web/wasm";
|
|
31
|
+
* ort.env.wasm.wasmPaths = { wasm: wasmUrl, mjs: mjsUrl };
|
|
32
|
+
* ort.env.wasm.numThreads = 1;
|
|
33
|
+
* setOnnxModule(ort);
|
|
34
|
+
*/
|
|
35
|
+
export declare function setOnnxModule(module: any): void;
|
|
36
|
+
/**
|
|
37
|
+
* Configure the onnxruntime-web WASM asset locations (sets
|
|
38
|
+
* `env.wasm.wasmPaths` during init). Primarily for the auto-load path —
|
|
39
|
+
* when you let the backend import ORT itself but your bundler content-
|
|
40
|
+
* hashes the `.wasm` / `.mjs` files (e.g. Vite `?url` imports), so the
|
|
41
|
+
* default `/ort/` prefix can't resolve them. If you inject your own
|
|
42
|
+
* module via {@link setOnnxModule}, prefer configuring it directly.
|
|
43
|
+
* An explicit call here is still honored even for an injected module.
|
|
44
|
+
*/
|
|
45
|
+
export declare function configureOnnxAssets(paths: OnnxAssetPaths): void;
|
|
46
|
+
/**
|
|
47
|
+
* Check whether onnxruntime-web is importable.
|
|
48
|
+
*/
|
|
49
|
+
export declare function isOnnxAvailable(): Promise<boolean>;
|
|
8
50
|
/**
|
|
9
51
|
* ONNXRuntime - Real ONNX model inference using onnxruntime-web
|
|
10
|
-
* Automatically loads ONNX Runtime from CDN when first used.
|
|
11
52
|
*/
|
|
12
53
|
export declare class ONNXRuntime implements Runtime {
|
|
13
54
|
readonly name: RuntimeType;
|
|
@@ -15,11 +56,11 @@ export declare class ONNXRuntime implements Runtime {
|
|
|
15
56
|
private executionProvider;
|
|
16
57
|
get capabilities(): RuntimeCapabilities;
|
|
17
58
|
/**
|
|
18
|
-
* Check if ONNX Runtime is available (
|
|
59
|
+
* Check if ONNX Runtime is available (peer dependency installed)
|
|
19
60
|
*/
|
|
20
61
|
isAvailable(): Promise<boolean>;
|
|
21
62
|
/**
|
|
22
|
-
* Initialize the ONNX runtime
|
|
63
|
+
* Initialize the ONNX runtime
|
|
23
64
|
*/
|
|
24
65
|
initialize(): Promise<void>;
|
|
25
66
|
/**
|
|
@@ -30,6 +71,10 @@ export declare class ONNXRuntime implements Runtime {
|
|
|
30
71
|
* Run inference
|
|
31
72
|
*/
|
|
32
73
|
run(model: LoadedModel, inputs: Tensor[]): Promise<Tensor[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Run inference with named inputs
|
|
76
|
+
*/
|
|
77
|
+
runNamed(model: LoadedModel, namedInputs: Map<string, Tensor>): Promise<Tensor[]>;
|
|
33
78
|
/**
|
|
34
79
|
* Unload a model
|
|
35
80
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onnx.d.ts","sourceRoot":"","sources":["../../src/backends/onnx.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAEhB,MAAM,EAIP,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"onnx.d.ts","sourceRoot":"","sources":["../../src/backends/onnx.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAEhB,MAAM,EAIP,MAAM,kBAAkB,CAAC;AAkB1B;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;;;;;;;;GAcG;AAEH,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAE/D;AAkBD;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAExD;AAkBD;;GAEG;AACH,qBAAa,WAAY,YAAW,OAAO;IACzC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAU;IAEpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,iBAAiB,CAA6B;IAEtD,IAAI,YAAY,IAAI,mBAAmB,CAStC;IAED;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDjC;;OAEG;IACG,SAAS,CACb,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,CAAC;IA+EvB;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA+DlE;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA2DvF;;OAEG;YACW,WAAW;IAQzB;;OAEG;IACH,OAAO,IAAI,IAAI;CAKhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C"}
|