Felladrin commited on
Commit
4723216
0 Parent(s):

Initial commit

Browse files
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ node_modules
2
+ .parcel-cache
README.md ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: "Web-LLM: Mistral 7B OpenOrca"
3
+ emoji: 🌊
4
+ colorFrom: pink
5
+ colorTo: purple
6
+ sdk: static
7
+ app_file: dist/index.html
8
+ pinned: false
9
+ license: apache-2.0
10
+ models:
11
+ - Felladrin/mlc-chat-Mistral-7B-OpenOrca-q4f32_1
12
+ - Open-Orca/Mistral-7B-OpenOrca
13
+ ---
14
+
15
+ # Web-LLM: Mistral 7B OpenOrca
16
+
17
+ Demo Space for [Felladrin/mlc-chat-Mistral-7B-OpenOrca-q4f32_1](https://huggingface.co/Felladrin/mlc-chat-Mistral-7B-OpenOrca-q4f32_1) model.
18
+
19
+ ## Contributing
20
+
21
+ Before start developing or building, run `npm ci` to install the dependencies.
22
+
23
+ To run the app locally for development, run `npm start`.
24
+
25
+ To build the app to `dist` folder, run `npm run build`.
dist/index.9744ff88.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .chatui{border:2px solid #ddd;border-radius:5px;flex-flow:column wrap;justify-content:space-between;width:100%;max-width:867px;height:600px;margin:25px 10px;display:flex;box-shadow:0 15px 15px -5px #0003}s .chatui-header{color:#666;background:#eee;border-bottom:2px solid #ddd;justify-content:space-between;padding:10px;display:flex}.chatui-chat{flex:1;padding:10px;overflow-y:auto}.chatui-chat::-webkit-scrollbar{width:6px}.chatui-chat::-webkit-scrollbar-track{background:#ddd}.chatui-chat::-webkit-scrollbar-thumb{background:#bdbdbd}.msg{align-items:flex-end;margin-bottom:10px;display:flex}.msg:last-of-type{margin:0}.msg-bubble{background:#ececec;border-radius:15px;max-width:450px;padding:15px}.left-msg .msg-bubble{border-bottom-left-radius:0}.error-msg .msg-bubble{color:#f15959;border-bottom-left-radius:0}.init-msg .msg-bubble{border-bottom-left-radius:0}.right-msg{flex-direction:row-reverse}.right-msg .msg-bubble{color:#fff;background:#579ffb;border-bottom-right-radius:0}.chatui-inputarea{background:#eee;border-top:2px solid #ddd;padding:10px;display:flex}.chatui-inputarea *{border:none;border-radius:3px;padding:10px;font-size:1em}.chatui-input{background:#ddd;flex:1}.chatui-reset-btn{cursor:pointer;background:#ececec;border-radius:8px;width:200px;margin-left:10px;font-weight:700}.chatui-reset-btn:hover{background:#dcdada}.chatui-send-btn{color:#fff;cursor:pointer;background:#579ffb;margin-left:10px;font-weight:700}.chatui-send-btn:hover{background:#577bfb}.chatui-chat{background-color:#fcfcfe}
dist/index.bd4d70df.js ADDED
The diff for this file is too large to render. See raw diff
 
dist/index.html ADDED
@@ -0,0 +1 @@
 
 
1
+ <script type="module" src="index.runtime.2846421e.js"></script><select id="chatui-select" style="display:none"></select><link href="index.9744ff88.css" rel="stylesheet" type="text/css"><div class="chatui"> <div class="chatui-chat" id="chatui-chat" height="100"></div> <div class="chatui-inputarea"> <input id="chatui-input" type="text" class="chatui-input" placeholder="Enter your message..."> <button id="chatui-send-btn" class="chatui-send-btn">Send</button> </div> </div><div class="chatui-extra-control"> <button id="chatui-reset-btn" class="chatui-reset-btn">Reset</button> <label id="chatui-info-label"></label> </div><script type="module" src="index.bd4d70df.js"></script>
dist/index.runtime.2846421e.js ADDED
@@ -0,0 +1 @@
 
 
1
+ var e=globalThis,r={},t={},a=e.parcelRequireba71;null==a&&((a=function(e){if(e in r)return r[e].exports;if(e in t){var a=t[e];delete t[e];var n={id:e,exports:{}};return r[e]=n,a.call(n.exports,n,n.exports),n.exports}var o=Error("Cannot find module '"+e+"'");throw o.code="MODULE_NOT_FOUND",o}).register=function(e,r){t[e]=r},e.parcelRequireba71=a),(0,a.register)("dRo73",function(e,r){Object.defineProperty(e.exports,"register",{get:()=>t,set:e=>t=e,enumerable:!0,configurable:!0});var t,a=new Map;t=function(e,r){for(var t=0;t<r.length-1;t+=2)a.set(r[t],{baseUrl:e,path:r[t+1]})}}),a("dRo73").register(new URL("",import.meta.url).toString(),JSON.parse('["lvtVP","index.bd4d70df.js","ayGjr","worker.6af90c76.js"]'));
dist/worker.6af90c76.js ADDED
The diff for this file is too large to render. See raw diff
 
package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
package.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "simple-chat",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "start": "parcel src/index.html",
7
+ "build": "parcel build src/index.html --public-url ./ --no-source-maps"
8
+ },
9
+ "devDependencies": {
10
+ "buffer": "^6.0.3",
11
+ "parcel": "^2.8.3",
12
+ "process": "^0.11.10",
13
+ "typescript": "^5.2.2",
14
+ "url": "^0.11.3"
15
+ },
16
+ "dependencies": {
17
+ "@mlc-ai/web-llm": "^0.2.8"
18
+ }
19
+ }
src/index.css ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .chatui {
2
+ display: flex;
3
+ flex-flow: column wrap;
4
+ justify-content: space-between;
5
+ width: 100%;
6
+ max-width: 867px;
7
+ margin: 25px 10px;
8
+ height: 600px;
9
+ border: 2px solid #ddd;
10
+ border-radius: 5px;
11
+ box-shadow: 0 15px 15px -5px rgba(0, 0, 0, 0.2);
12
+ }
13
+
14
+ s .chatui-header {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ padding: 10px;
18
+ border-bottom: 2px solid #ddd;
19
+ background: #eee;
20
+ color: #666;
21
+ }
22
+
23
+ .chatui-chat {
24
+ flex: 1;
25
+ overflow-y: auto;
26
+ padding: 10px;
27
+ }
28
+
29
+ .chatui-chat::-webkit-scrollbar {
30
+ width: 6px;
31
+ }
32
+
33
+ .chatui-chat::-webkit-scrollbar-track {
34
+ background: #ddd;
35
+ }
36
+
37
+ .chatui-chat::-webkit-scrollbar-thumb {
38
+ background: #bdbdbd;
39
+ }
40
+
41
+ .msg {
42
+ display: flex;
43
+ align-items: flex-end;
44
+ margin-bottom: 10px;
45
+ }
46
+
47
+ .msg:last-of-type {
48
+ margin: 0;
49
+ }
50
+
51
+ .msg-bubble {
52
+ max-width: 450px;
53
+ padding: 15px;
54
+ border-radius: 15px;
55
+ background: #ececec;
56
+ }
57
+
58
+ .left-msg .msg-bubble {
59
+ border-bottom-left-radius: 0;
60
+ }
61
+
62
+ .error-msg .msg-bubble {
63
+ border-bottom-left-radius: 0;
64
+ color: #f15959;
65
+ }
66
+
67
+ .init-msg .msg-bubble {
68
+ border-bottom-left-radius: 0;
69
+ }
70
+
71
+ .right-msg {
72
+ flex-direction: row-reverse;
73
+ }
74
+
75
+ .right-msg .msg-bubble {
76
+ background: #579ffb;
77
+ color: #fff;
78
+ border-bottom-right-radius: 0;
79
+ }
80
+
81
+ .chatui-inputarea {
82
+ display: flex;
83
+ padding: 10px;
84
+ border-top: 2px solid #ddd;
85
+ background: #eee;
86
+ }
87
+
88
+ .chatui-inputarea * {
89
+ padding: 10px;
90
+ border: none;
91
+ border-radius: 3px;
92
+ font-size: 1em;
93
+ }
94
+
95
+ .chatui-input {
96
+ flex: 1;
97
+ background: #ddd;
98
+ }
99
+
100
+ .chatui-reset-btn {
101
+ margin-left: 10px;
102
+ background: #ececec;
103
+ font-weight: bold;
104
+ border-radius: 8px;
105
+ width: 200px;
106
+ cursor: pointer;
107
+ }
108
+
109
+ .chatui-reset-btn:hover {
110
+ background: #dcdada;
111
+ }
112
+
113
+ .chatui-send-btn {
114
+ margin-left: 10px;
115
+ background: #579ffb;
116
+ color: #fff;
117
+ font-weight: bold;
118
+ cursor: pointer;
119
+ }
120
+
121
+ .chatui-send-btn:hover {
122
+ background: #577bfb;
123
+ }
124
+
125
+ .chatui-chat {
126
+ background-color: #fcfcfe;
127
+ }
src/index.html ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <select id="chatui-select" style="display: none"></select>
2
+
3
+ <link href="./index.css" rel="stylesheet" type="text/css" />
4
+
5
+ <div class="chatui">
6
+ <div class="chatui-chat" id="chatui-chat" height="100"></div>
7
+
8
+ <div class="chatui-inputarea">
9
+ <input
10
+ id="chatui-input"
11
+ type="text"
12
+ class="chatui-input"
13
+ placeholder="Enter your message..."
14
+ />
15
+ <button id="chatui-send-btn" class="chatui-send-btn">Send</button>
16
+ </div>
17
+ </div>
18
+
19
+ <div class="chatui-extra-control">
20
+ <button id="chatui-reset-btn" class="chatui-reset-btn">Reset</button>
21
+ <label id="chatui-info-label"></label>
22
+ </div>
23
+ <!--- Place script after ui to make sure ui loads first -->
24
+ <script type="module" src="./index.ts"></script>
src/index.ts ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ ChatInterface,
3
+ ChatModule,
4
+ ChatRestModule,
5
+ ChatWorkerClient,
6
+ } from "@mlc-ai/web-llm";
7
+
8
+ function getElementAndCheck(id: string): HTMLElement {
9
+ const element = document.getElementById(id);
10
+ if (element == null) {
11
+ throw Error("Cannot find element " + id);
12
+ }
13
+ return element;
14
+ }
15
+
16
+ const appConfig = {
17
+ model_list: [
18
+ {
19
+ model_url:
20
+ "https://huggingface.co/Felladrin/mlc-chat-Mistral-7B-OpenOrca-q4f32_1/resolve/main/params/",
21
+ local_id: "Mistral-7B-OpenOrca-q4f32_1",
22
+ },
23
+ ],
24
+ model_lib_map: {
25
+ "Mistral-7B-OpenOrca-q4f32_1":
26
+ "https://huggingface.co/Felladrin/mlc-chat-Mistral-7B-OpenOrca-q4f32_1/resolve/main/Mistral-7B-OpenOrca-q4f32_1-webgpu.wasm",
27
+ },
28
+ use_web_worker: true,
29
+ };
30
+
31
+ class ChatUI {
32
+ private uiChat: HTMLElement;
33
+ private uiChatInput: HTMLInputElement;
34
+ private uiChatInfoLabel: HTMLLabelElement;
35
+ private chat: ChatInterface;
36
+ private localChat: ChatInterface;
37
+ private config = appConfig;
38
+ private selectedModel: string;
39
+ private chatLoaded = false;
40
+ private requestInProgress = false;
41
+ // We use a request chain to ensure that
42
+ // all requests send to chat are sequentialized
43
+ private chatRequestChain: Promise<void> = Promise.resolve();
44
+
45
+ constructor(chat: ChatInterface, localChat: ChatInterface) {
46
+ // use web worker to run chat generation in background
47
+ this.chat = chat;
48
+ this.localChat = localChat;
49
+ // get the elements
50
+ this.uiChat = getElementAndCheck("chatui-chat");
51
+ this.uiChatInput = getElementAndCheck("chatui-input") as HTMLInputElement;
52
+ this.uiChatInfoLabel = getElementAndCheck(
53
+ "chatui-info-label"
54
+ ) as HTMLLabelElement;
55
+ // register event handlers
56
+ getElementAndCheck("chatui-reset-btn").onclick = () => {
57
+ this.onReset();
58
+ };
59
+ getElementAndCheck("chatui-send-btn").onclick = () => {
60
+ this.onGenerate();
61
+ };
62
+ // TODO: find other alternative triggers
63
+ getElementAndCheck("chatui-input").onkeypress = (event) => {
64
+ if (event.keyCode === 13) {
65
+ this.onGenerate();
66
+ }
67
+ };
68
+
69
+ const modelSelector = getElementAndCheck(
70
+ "chatui-select"
71
+ ) as HTMLSelectElement;
72
+ for (let i = 0; i < this.config.model_list.length; ++i) {
73
+ const item = this.config.model_list[i];
74
+ const opt = document.createElement("option");
75
+ opt.value = item.local_id;
76
+ opt.innerHTML = item.local_id;
77
+ opt.selected = i == 0;
78
+ modelSelector.appendChild(opt);
79
+ }
80
+ // Append local server option to the model selector
81
+ const localServerOpt = document.createElement("option");
82
+ localServerOpt.value = "Local Server";
83
+ localServerOpt.innerHTML = "Local Server";
84
+ modelSelector.append(localServerOpt);
85
+ this.selectedModel = modelSelector.value;
86
+ modelSelector.onchange = () => {
87
+ this.onSelectChange(modelSelector);
88
+ };
89
+ }
90
+ /**
91
+ * Push a task to the execution queue.
92
+ *
93
+ * @param task The task to be executed;
94
+ */
95
+ private pushTask(task: () => Promise<void>) {
96
+ const lastEvent = this.chatRequestChain;
97
+ this.chatRequestChain = lastEvent.then(task);
98
+ }
99
+ // Event handlers
100
+ // all event handler pushes the tasks to a queue
101
+ // that get executed sequentially
102
+ // the tasks previous tasks, which causes them to early stop
103
+ // can be interrupted by chat.interruptGenerate
104
+ private async onGenerate() {
105
+ if (this.requestInProgress) {
106
+ return;
107
+ }
108
+ this.pushTask(async () => {
109
+ await this.asyncGenerate();
110
+ });
111
+ }
112
+
113
+ private async onSelectChange(modelSelector: HTMLSelectElement) {
114
+ if (this.requestInProgress) {
115
+ // interrupt previous generation if any
116
+ this.chat.interruptGenerate();
117
+ }
118
+ // try reset after previous requests finishes
119
+ this.pushTask(async () => {
120
+ await this.chat.resetChat();
121
+ this.resetChatHistory();
122
+ await this.unloadChat();
123
+ this.selectedModel = modelSelector.value;
124
+ await this.asyncInitChat();
125
+ });
126
+ }
127
+
128
+ private async onReset() {
129
+ if (this.requestInProgress) {
130
+ // interrupt previous generation if any
131
+ this.chat.interruptGenerate();
132
+ }
133
+ // try reset after previous requests finishes
134
+ this.pushTask(async () => {
135
+ await this.chat.resetChat();
136
+ this.resetChatHistory();
137
+ });
138
+ }
139
+
140
+ // Internal helper functions
141
+ private appendMessage(kind, text) {
142
+ if (kind == "init") {
143
+ text = "[System Initalize] " + text;
144
+ }
145
+ if (this.uiChat === undefined) {
146
+ throw Error("cannot find ui chat");
147
+ }
148
+ const msg = `
149
+ <div class="msg ${kind}-msg">
150
+ <div class="msg-bubble">
151
+ <div class="msg-text">${text}</div>
152
+ </div>
153
+ </div>
154
+ `;
155
+ this.uiChat.insertAdjacentHTML("beforeend", msg);
156
+ this.uiChat.scrollTo(0, this.uiChat.scrollHeight);
157
+ }
158
+
159
+ private updateLastMessage(kind, text) {
160
+ if (kind == "init") {
161
+ text = "[System Initalize] " + text;
162
+ }
163
+ if (this.uiChat === undefined) {
164
+ throw Error("cannot find ui chat");
165
+ }
166
+ const matches = this.uiChat.getElementsByClassName(`msg ${kind}-msg`);
167
+ if (matches.length == 0) throw Error(`${kind} message do not exist`);
168
+ const msg = matches[matches.length - 1];
169
+ const msgText = msg.getElementsByClassName("msg-text");
170
+ if (msgText.length != 1) throw Error("Expect msg-text");
171
+ if (msgText[0].innerHTML == text) return;
172
+ const list = text.split("\n").map((t) => {
173
+ const item = document.createElement("div");
174
+ item.textContent = t;
175
+ return item;
176
+ });
177
+ msgText[0].innerHTML = "";
178
+ list.forEach((item) => msgText[0].append(item));
179
+ this.uiChat.scrollTo(0, this.uiChat.scrollHeight);
180
+ }
181
+
182
+ private resetChatHistory() {
183
+ const clearTags = ["left", "right", "init", "error"];
184
+ for (const tag of clearTags) {
185
+ // need to unpack to list so the iterator don't get affected by mutation
186
+ const matches = [...this.uiChat.getElementsByClassName(`msg ${tag}-msg`)];
187
+ for (const item of matches) {
188
+ this.uiChat.removeChild(item);
189
+ }
190
+ }
191
+ if (this.uiChatInfoLabel !== undefined) {
192
+ this.uiChatInfoLabel.innerHTML = "";
193
+ }
194
+ }
195
+
196
+ private async asyncInitChat() {
197
+ if (this.chatLoaded) return;
198
+ this.requestInProgress = true;
199
+ this.appendMessage("init", "");
200
+ const initProgressCallback = (report) => {
201
+ this.updateLastMessage("init", report.text);
202
+ };
203
+ this.chat.setInitProgressCallback(initProgressCallback);
204
+
205
+ try {
206
+ if (this.selectedModel != "Local Server") {
207
+ await this.chat.reload(this.selectedModel, undefined, this.config);
208
+ }
209
+ } catch (err) {
210
+ this.appendMessage("error", "Init error, " + err.toString());
211
+ console.log(err.stack);
212
+ this.unloadChat();
213
+ this.requestInProgress = false;
214
+ return;
215
+ }
216
+ this.requestInProgress = false;
217
+ this.chatLoaded = true;
218
+ }
219
+
220
+ private async unloadChat() {
221
+ await this.chat.unload();
222
+ this.chatLoaded = false;
223
+ }
224
+
225
+ /**
226
+ * Run generate
227
+ */
228
+ private async asyncGenerate() {
229
+ await this.asyncInitChat();
230
+ this.requestInProgress = true;
231
+ const prompt = this.uiChatInput.value;
232
+ if (prompt == "") {
233
+ this.requestInProgress = false;
234
+ return;
235
+ }
236
+
237
+ this.appendMessage("right", prompt);
238
+ this.uiChatInput.value = "";
239
+ this.uiChatInput.setAttribute("placeholder", "Generating...");
240
+
241
+ this.appendMessage("left", "");
242
+ const callbackUpdateResponse = (step, msg) => {
243
+ if (msg.length === 0) return this.chat.interruptGenerate();
244
+ this.updateLastMessage("left", msg);
245
+ };
246
+
247
+ try {
248
+ if (this.selectedModel == "Local Server") {
249
+ await this.localChat.generate(prompt, callbackUpdateResponse);
250
+ this.uiChatInfoLabel.innerHTML =
251
+ await this.localChat.runtimeStatsText();
252
+ } else {
253
+ await this.chat.generate(prompt, callbackUpdateResponse);
254
+ this.uiChatInfoLabel.innerHTML = await this.chat.runtimeStatsText();
255
+ }
256
+ } catch (err) {
257
+ this.appendMessage("error", "Generate error, " + err.toString());
258
+ console.log(err.stack);
259
+ await this.unloadChat();
260
+ }
261
+ this.uiChatInput.setAttribute("placeholder", "Enter your message...");
262
+ this.requestInProgress = false;
263
+ }
264
+ }
265
+
266
+ const useWebWorker = appConfig.use_web_worker;
267
+ let chat: ChatInterface;
268
+ let localChat: ChatInterface;
269
+
270
+ if (useWebWorker) {
271
+ chat = new ChatWorkerClient(
272
+ new Worker(new URL("./worker.ts", import.meta.url), { type: "module" })
273
+ );
274
+ localChat = new ChatRestModule();
275
+ } else {
276
+ chat = new ChatModule();
277
+ localChat = new ChatRestModule();
278
+ }
279
+ new ChatUI(chat, localChat);
src/worker.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ // Serve the chat workload through web worker
2
+ import { ChatWorkerHandler, ChatModule } from "@mlc-ai/web-llm";
3
+
4
+ const chat = new ChatModule();
5
+ const handler = new ChatWorkerHandler(chat);
6
+ self.onmessage = (msg: MessageEvent) => {
7
+ handler.onmessage(msg);
8
+ };