Skip to content

Commit 82f5abb

Browse files
authored
Gallery improvements (#7267)
* Fix gallery deployment * Improve WebLLM example * Add description
1 parent 203a2be commit 82f5abb

File tree

2 files changed

+71
-21
lines changed

2 files changed

+71
-21
lines changed

examples/gallery/WebLLM.ipynb

+67-18
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"\n",
1414
"from panel.custom import JSComponent, ESMEvent\n",
1515
"\n",
16-
"pn.extension(template='material')"
16+
"pn.extension('mathjax', template='material')"
1717
]
1818
},
1919
{
@@ -31,36 +31,50 @@
3131
"metadata": {},
3232
"outputs": [],
3333
"source": [
34-
"\n",
3534
"MODELS = {\n",
36-
" 'Mistral-7b-Instruct': 'Mistral-7B-Instruct-v0.3-q4f16_1-MLC',\n",
37-
" 'SmolLM': 'SmolLM-360M-Instruct-q4f16_1-MLC',\n",
38-
" 'Gemma-2b': 'gemma-2-2b-it-q4f16_1-MLC',\n",
39-
" 'Llama-3.1-8b-Instruct': 'Llama-3.1-8B-Instruct-q4f32_1-MLC-1k'\n",
35+
" 'SmolLM (130MB)': 'SmolLM-135M-Instruct-q4f16_1-MLC',\n",
36+
" 'TinyLlama-1.1B-Chat (675 MB)': 'TinyLlama-1.1B-Chat-v1.0-q4f16_1-MLC-1k',\n",
37+
" 'Gemma-2b (1895 MB)': 'gemma-2-2b-it-q4f16_1-MLC',\n",
38+
" 'Mistral-7b-Instruct (4570 MB)': 'Mistral-7B-Instruct-v0.3-q4f16_1-MLC',\n",
39+
" 'Llama-3.1-8b-Instruct (4598 MB)': 'Llama-3-8B-Instruct-q4f16_1-MLC-1k',\n",
4040
"}\n",
4141
"\n",
4242
"class WebLLM(JSComponent):\n",
4343
"\n",
4444
" loaded = param.Boolean(default=False, doc=\"\"\"\n",
4545
" Whether the model is loaded.\"\"\")\n",
4646
"\n",
47-
" model = param.Selector(default='SmolLM-360M-Instruct-q4f16_1-MLC', objects=MODELS)\n",
47+
" history = param.Integer(default=3)\n",
4848
"\n",
49-
" temperature = param.Number(default=1, bounds=(0, 2))\n",
49+
" status = param.Dict(default={'text': '', 'progress': 0})\n",
5050
"\n",
5151
" load_model = param.Event()\n",
52+
"\n",
53+
" model = param.Selector(default='SmolLM-135M-Instruct-q4f16_1-MLC', objects=MODELS)\n",
54+
"\n",
55+
" running = param.Boolean(default=False, doc=\"\"\"\n",
56+
" Whether the LLM is currently running.\"\"\")\n",
5257
" \n",
58+
" temperature = param.Number(default=1, bounds=(0, 2), doc=\"\"\"\n",
59+
" Temperature of the model completions.\"\"\")\n",
60+
"\n",
5361
" _esm = \"\"\"\n",
5462
" import * as webllm from \"https://esm.run/@mlc-ai/web-llm\";\n",
5563
"\n",
5664
" const engines = new Map()\n",
5765
"\n",
5866
" export async function render({ model }) {\n",
5967
" model.on(\"msg:custom\", async (event) => {\n",
60-
" console.log(event)\n",
6168
" if (event.type === 'load') {\n",
6269
" if (!engines.has(model.model)) {\n",
63-
" engines.set(model.model, await webllm.CreateMLCEngine(model.model))\n",
70+
" const initProgressCallback = (status) => {\n",
71+
" model.status = status\n",
72+
" }\n",
73+
" const mlc = await webllm.CreateMLCEngine(\n",
74+
" model.model,\n",
75+
" {initProgressCallback}\n",
76+
" )\n",
77+
" engines.set(model.model, mlc)\n",
6478
" }\n",
6579
" model.loaded = true\n",
6680
" } else if (event.type === 'completion') {\n",
@@ -73,7 +87,11 @@
7387
" temperature: model.temperature ,\n",
7488
" stream: true,\n",
7589
" })\n",
90+
" model.running = true\n",
7691
" for await (const chunk of chunks) {\n",
92+
" if (!model.running) {\n",
93+
" break\n",
94+
" }\n",
7795
" model.send_msg(chunk.choices[0])\n",
7896
" }\n",
7997
" }\n",
@@ -83,6 +101,8 @@
83101
"\n",
84102
" def __init__(self, **params):\n",
85103
" super().__init__(**params)\n",
104+
" if pn.state.location:\n",
105+
" pn.state.location.sync(self, {'model': 'model'})\n",
86106
" self._buffer = []\n",
87107
"\n",
88108
" @param.depends('load_model', watch=True)\n",
@@ -93,14 +113,14 @@
93113
" @param.depends('loaded', watch=True)\n",
94114
" def _loaded(self):\n",
95115
" self.loading = False\n",
96-
" self.param.load_model.constant = True\n",
97116
"\n",
98117
" @param.depends('model', watch=True)\n",
99118
" def _update_load_model(self):\n",
100-
" self.param.load_model.constant = False\n",
119+
" self.loaded = False\n",
101120
"\n",
102121
" def _handle_msg(self, msg):\n",
103-
" self._buffer.insert(0, msg)\n",
122+
" if self.running:\n",
123+
" self._buffer.insert(0, msg)\n",
104124
"\n",
105125
" async def create_completion(self, msgs):\n",
106126
" self._send_msg({'type': 'completion', 'messages': msgs})\n",
@@ -119,21 +139,34 @@
119139
"\n",
120140
" async def callback(self, contents: str, user: str):\n",
121141
" if not self.loaded:\n",
122-
" yield f'Model `{self.model}` is loading.' if self.param.load_model.constant else 'Load the model'\n",
142+
" if self.loading:\n",
143+
" yield pn.pane.Markdown(\n",
144+
" f'## `{self.model}`\\n\\n' + self.param.status.rx()['text']\n",
145+
" )\n",
146+
" else:\n",
147+
" yield 'Load the model'\n",
123148
" return\n",
149+
" self.running = False\n",
150+
" self._buffer.clear()\n",
124151
" message = \"\"\n",
125152
" async for chunk in llm.create_completion([{'role': 'user', 'content': contents}]):\n",
126153
" message += chunk['delta'].get('content', '')\n",
127154
" yield message\n",
128155
"\n",
129156
" def menu(self):\n",
157+
" status = self.param.status.rx()\n",
130158
" return pn.Column(\n",
131159
" pn.widgets.Select.from_param(self.param.model, sizing_mode='stretch_width'),\n",
132160
" pn.widgets.FloatSlider.from_param(self.param.temperature, sizing_mode='stretch_width'),\n",
133161
" pn.widgets.Button.from_param(\n",
134162
" self.param.load_model, sizing_mode='stretch_width',\n",
135-
" loading=self.param.loading\n",
136-
" )\n",
163+
" disabled=self.param.loaded.rx().rx.or_(self.param.loading)\n",
164+
" ),\n",
165+
" pn.indicators.Progress(\n",
166+
" value=(status['progress']*100).rx.pipe(int), visible=self.param.loading,\n",
167+
" sizing_mode='stretch_width'\n",
168+
" ),\n",
169+
" pn.pane.Markdown(status['text'], visible=self.param.loading)\n",
137170
" )"
138171
]
139172
},
@@ -154,7 +187,21 @@
154187
"source": [
155188
"llm = WebLLM()\n",
156189
"\n",
157-
"pn.Column(llm.menu(), llm).servable(area='sidebar')"
190+
"intro = pn.pane.Alert(\"\"\"\n",
191+
"`WebLLM` runs large-language models entirely in your browser.\n",
192+
"When visiting the application the first time the model has\n",
193+
"to be downloaded and loaded into memory, which may take \n",
194+
"some time. Models are ordered by size (and capability),\n",
195+
"e.g. SmolLLM is very quick to download but produces poor\n",
196+
"quality output while Mistral-7b will take a while to\n",
197+
"download but produces much higher quality output.\n",
198+
"\"\"\".replace('\\n', ' '))\n",
199+
"\n",
200+
"pn.Column(\n",
201+
" llm.menu(),\n",
202+
" intro,\n",
203+
" llm\n",
204+
").servable(area='sidebar')"
158205
]
159206
},
160207
{
@@ -179,7 +226,9 @@
179226
" respond=False,\n",
180227
")\n",
181228
"\n",
182-
"chat_interface.servable(title='WebLLM')"
229+
"llm.param.watch(lambda e: chat_interface.send(f'Loaded `{e.obj.model}`, start chatting!', user='System', respond=False), 'loaded')\n",
230+
"\n",
231+
"pn.Row(chat_interface).servable(title='WebLLM')"
183232
]
184233
}
185234
],

examples/gallery/anaconda-project.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ description: An environment to serve all Panel gallery examples
44
commands:
55
prod:
66
description: Serve the prod Panel gallery
7-
unix: bokeh sampledata && sleep 60 && panel serve *.ipynb --static-dirs thumbnails=thumbnails --reuse-sessions --global-loading-spinner --liveness --num-procs 8
7+
unix: panel serve *.ipynb --static-dirs thumbnails=thumbnails --reuse-sessions --global-loading-spinner --liveness --num-procs 8
88
supports_http_options: true
99
env_spec: prod
1010
dev:
1111
description: Serve the dev Panel gallery
12-
unix: bokeh sampledata && sleep 60 && panel serve *.ipynb --static-dirs thumbnails=thumbnails --reuse-sessions --global-loading-spinner --liveness --num-procs 2
12+
unix: panel serve *.ipynb --static-dirs thumbnails=thumbnails --reuse-sessions --global-loading-spinner --liveness --num-procs 2
1313
supports_http_options: true
1414
env_spec: dev
1515

@@ -22,7 +22,8 @@ variables:
2222

2323
packages: &pkgs
2424
- python >=3.10.13
25-
- panel >=1.3.8
25+
- panel >=1.5.0rc2
26+
- bokeh_sampledata
2627
- holoviews >=1.18.2
2728
- nbconvert
2829
- pandas >=2.2.0

0 commit comments

Comments
 (0)