chembfn-webui 1.2.3__tar.gz → 2.1.3__tar.gz
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.
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/PKG-INFO +19 -6
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/README.md +18 -6
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/bin/app.py +131 -54
- chembfn_webui-2.1.3/chembfn_webui/bin/favicon.png +0 -0
- chembfn_webui-2.1.3/chembfn_webui/cache/results.csv +1 -0
- chembfn_webui-2.1.3/chembfn_webui/lib/utilities.py +419 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/lib/version.py +1 -1
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui.egg-info/PKG-INFO +19 -6
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui.egg-info/SOURCES.txt +3 -1
- chembfn_webui-2.1.3/chembfn_webui.egg-info/requires.txt +5 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/setup.py +35 -12
- chembfn_webui-2.1.3/test/test_prompt_parsing.py +82 -0
- chembfn_webui-2.1.3/test/test_user_expression_validator.py +138 -0
- chembfn_webui-1.2.3/chembfn_webui/bin/favicon.png +0 -0
- chembfn_webui-1.2.3/chembfn_webui/cache/results.csv +0 -1
- chembfn_webui-1.2.3/chembfn_webui/lib/utilities.py +0 -237
- chembfn_webui-1.2.3/chembfn_webui.egg-info/requires.txt +0 -5
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/LICENSE +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/__init__.py +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/cache/cache_file_here.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/model/base_model/place_base_model_here.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/model/lora/place_lora_folder_here.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/model/standalone_model/place_standalone_model_folder_here.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui/model/vocab/place_vocabulary_file_here.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui.egg-info/dependency_links.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui.egg-info/entry_points.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/chembfn_webui.egg-info/top_level.txt +0 -0
- {chembfn_webui-1.2.3 → chembfn_webui-2.1.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chembfn_webui
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 2.1.3
|
|
4
4
|
Summary: WebUI for ChemBFN
|
|
5
5
|
Home-page: https://github.com/Augus1999/ChemBFN-WebUI
|
|
6
6
|
Author: Nianze A. Tao
|
|
@@ -15,15 +15,16 @@ Classifier: Programming Language :: Python :: 3
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
19
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
19
20
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
21
|
Requires-Python: >=3.11
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
License-File: LICENSE
|
|
23
|
-
Requires-Dist: bayesianflow_for_chem>=2.
|
|
24
|
-
Requires-Dist: mol2chemfigPy3>=1.5.
|
|
25
|
-
Requires-Dist: gradio
|
|
26
|
-
Requires-Dist: torch>=2.
|
|
24
|
+
Requires-Dist: bayesianflow_for_chem>=2.4.0
|
|
25
|
+
Requires-Dist: mol2chemfigPy3>=1.5.12
|
|
26
|
+
Requires-Dist: gradio<7.0.0,>=6.0.0
|
|
27
|
+
Requires-Dist: torch>=2.9.0
|
|
27
28
|
Requires-Dist: selfies>=2.2.0
|
|
28
29
|
Dynamic: author
|
|
29
30
|
Dynamic: author-email
|
|
@@ -39,10 +40,20 @@ Dynamic: requires-dist
|
|
|
39
40
|
Dynamic: requires-python
|
|
40
41
|
Dynamic: summary
|
|
41
42
|
|
|
42
|
-
##
|
|
43
|
+
## Web-based UI visualisation tool for ChemBFN method
|
|
43
44
|
|
|
45
|
+
[](https://pypi.org/project/chembfn-webui/)
|
|
46
|
+

|
|
47
|
+

|
|
48
|
+
[](https://stand-with-ukraine.pp.ua)
|
|
44
49
|
|
|
45
50
|
|
|
51
|
+
|
|
52
|
+
> Important:
|
|
53
|
+
>
|
|
54
|
+
> For the security concerning, it is not recommended to use this application as a public service.
|
|
55
|
+
> When deploying on a local host as a shared application, it is better to install this application in a container or VM, to prevent this application from accessing the Internet, and to limit the premissions of read, create, and delete loacal files and directories.
|
|
56
|
+
|
|
46
57
|
### 1. Install
|
|
47
58
|
|
|
48
59
|
```bash
|
|
@@ -97,6 +108,7 @@ For example,
|
|
|
97
108
|
> > "name": JOB_NAME
|
|
98
109
|
> >}
|
|
99
110
|
> >```
|
|
111
|
+
> >The configureation file for base models can be downloaded [here](https://huggingface.co/suenoomozawa/ChemBFN/resolve/main/config.json).
|
|
100
112
|
|
|
101
113
|
If placed correctly, all these files can be seen in the "model explorer" tab.
|
|
102
114
|
|
|
@@ -146,6 +158,7 @@ Under "advanced control" tab
|
|
|
146
158
|
|
|
147
159
|
* You can control semi-autoregressive behaviours by key in `F` for switching off SAR, `T` for switching on SAR, and prompt like `F,F,T,...` to individually control the SAR in an ensemble model.
|
|
148
160
|
* You can add unwanted tokens, e.g., `[Cu],p,[Si]`.
|
|
161
|
+
* You can customise the result preprocessing function, e.g., the model output a reaction SMILES "CCI.C[O-]>>COCC" which couldn't be recognised by RDKit; you can pass `lambda x: x.split(">>")[-1]` to force the program only looking at the products.
|
|
149
162
|
|
|
150
163
|
### 6. Generate molecules
|
|
151
164
|
|
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Web-based UI visualisation tool for ChemBFN method
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/chembfn-webui/)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
[](https://stand-with-ukraine.pp.ua)
|
|
2
7
|
|
|
3
8
|
<p align="left">
|
|
4
|
-
<img src="image/screenshot_0.jpeg" alt="screenshot 0" width="
|
|
5
|
-
<img src="image/screenshot_1.jpeg" alt="screenshot 1" width="
|
|
6
|
-
<img src="image/screenshot_2.jpeg" alt="screenshot 2" width="
|
|
7
|
-
<img src="image/screenshot_3.jpeg" alt="screenshot 3" width="
|
|
8
|
-
<img src="image/screenshot_4.jpeg" alt="screenshot 4" width="
|
|
9
|
+
<img src="image/screenshot_0.jpeg" alt="screenshot 0" width="360" height="auto">
|
|
10
|
+
<img src="image/screenshot_1.jpeg" alt="screenshot 1" width="360" height="auto">
|
|
11
|
+
<img src="image/screenshot_2.jpeg" alt="screenshot 2" width="360" height="auto">
|
|
12
|
+
<img src="image/screenshot_3.jpeg" alt="screenshot 3" width="360" height="auto">
|
|
13
|
+
<img src="image/screenshot_4.jpeg" alt="screenshot 4" width="360" height="auto">
|
|
9
14
|
</p>
|
|
10
15
|
|
|
16
|
+
> [!IMPORTANT]
|
|
17
|
+
>
|
|
18
|
+
> For the security concerning, it is not recommended to use this application as a public service.
|
|
19
|
+
> When deploying on a local host as a shared application, it is better to install this application in a container or VM, to prevent this application from accessing the Internet, and to limit the premissions of read, create, and delete loacal files and directories.
|
|
20
|
+
|
|
11
21
|
### 1. Install
|
|
12
22
|
|
|
13
23
|
```bash
|
|
@@ -62,6 +72,7 @@ For example,
|
|
|
62
72
|
> > "name": JOB_NAME
|
|
63
73
|
> >}
|
|
64
74
|
> >```
|
|
75
|
+
> >The configureation file for base models can be downloaded [here](https://huggingface.co/suenoomozawa/ChemBFN/resolve/main/config.json).
|
|
65
76
|
|
|
66
77
|
If placed correctly, all these files can be seen in the "model explorer" tab.
|
|
67
78
|
|
|
@@ -111,6 +122,7 @@ Under "advanced control" tab
|
|
|
111
122
|
|
|
112
123
|
* You can control semi-autoregressive behaviours by key in `F` for switching off SAR, `T` for switching on SAR, and prompt like `F,F,T,...` to individually control the SAR in an ensemble model.
|
|
113
124
|
* You can add unwanted tokens, e.g., `[Cu],p,[Si]`.
|
|
125
|
+
* You can customise the result preprocessing function, e.g., the model output a reaction SMILES "CCI.C[O-]>>COCC" which couldn't be recognised by RDKit; you can pass `lambda x: x.split(">>")[-1]` to force the program only looking at the products.
|
|
114
126
|
|
|
115
127
|
### 6. Generate molecules
|
|
116
128
|
|
|
@@ -6,8 +6,9 @@ Define application behaviours.
|
|
|
6
6
|
import sys
|
|
7
7
|
import argparse
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from copy import deepcopy
|
|
9
10
|
from functools import partial
|
|
10
|
-
from typing import Tuple, List, Dict, Union, Literal
|
|
11
|
+
from typing import Tuple, List, Dict, Optional, Union, Literal
|
|
11
12
|
|
|
12
13
|
sys.path.append(str(Path(__file__).parent.parent))
|
|
13
14
|
from rdkit.Chem import Draw, MolFromSmiles # type: ignore
|
|
@@ -38,6 +39,7 @@ from lib.utilities import (
|
|
|
38
39
|
parse_prompt,
|
|
39
40
|
parse_exclude_token,
|
|
40
41
|
parse_sar_control,
|
|
42
|
+
build_result_prep_fn,
|
|
41
43
|
)
|
|
42
44
|
from lib.version import __version__
|
|
43
45
|
|
|
@@ -45,7 +47,7 @@ vocabs = find_vocab()
|
|
|
45
47
|
models = find_model()
|
|
46
48
|
cache_dir = Path(__file__).parent.parent / "cache"
|
|
47
49
|
favicon_dir = Path(__file__).parent / "favicon.png"
|
|
48
|
-
|
|
50
|
+
_RESULT_COUNT = 0
|
|
49
51
|
|
|
50
52
|
HTML_STYLE = gr.InputHTMLAttributes(
|
|
51
53
|
autocapitalize="off",
|
|
@@ -76,7 +78,7 @@ def selfies2vec(sel: str, vocab_dict: Dict[str, int]) -> List[int]:
|
|
|
76
78
|
return [vocab_dict.get(i, unknown_id) for i in s]
|
|
77
79
|
|
|
78
80
|
|
|
79
|
-
def
|
|
81
|
+
def _refresh(
|
|
80
82
|
model_selected: str, vocab_selected: str, tokeniser_selected: str
|
|
81
83
|
) -> Tuple[
|
|
82
84
|
List[str], List[str], List[List[str]], List[List[str]], gr.Dropdown, gr.Dropdown
|
|
@@ -121,7 +123,7 @@ def refresh(
|
|
|
121
123
|
return a, b, c, d, e, f
|
|
122
124
|
|
|
123
125
|
|
|
124
|
-
def
|
|
126
|
+
def _select_lora(evt: gr.SelectData, prompt: str) -> str:
|
|
125
127
|
"""
|
|
126
128
|
Select LoRA model name from Dataframe object.
|
|
127
129
|
|
|
@@ -141,7 +143,7 @@ def select_lora(evt: gr.SelectData, prompt: str) -> str:
|
|
|
141
143
|
return f"{prompt};\n<{selected_lora}:1>"
|
|
142
144
|
|
|
143
145
|
|
|
144
|
-
def
|
|
146
|
+
def _token_name_change_evt(
|
|
145
147
|
token_name: str, vocab_fn: str
|
|
146
148
|
) -> Tuple[gr.Dropdown, gr.Tab, gr.Tab]:
|
|
147
149
|
"""
|
|
@@ -178,14 +180,15 @@ def run(
|
|
|
178
180
|
guidance_strength: float,
|
|
179
181
|
method: Literal["BFN", "ODE"],
|
|
180
182
|
temperature: float,
|
|
181
|
-
prompt: str,
|
|
182
|
-
scaffold: str,
|
|
183
|
-
template: str,
|
|
184
|
-
sar_control: str,
|
|
185
|
-
exclude_token: str,
|
|
183
|
+
prompt: Optional[str],
|
|
184
|
+
scaffold: Optional[str],
|
|
185
|
+
template: Optional[str],
|
|
186
|
+
sar_control: Optional[str],
|
|
187
|
+
exclude_token: Optional[str],
|
|
186
188
|
quantise: Literal["on", "off"],
|
|
187
189
|
jited: Literal["on", "off"],
|
|
188
190
|
sorted_: Literal["on", "off"],
|
|
191
|
+
result_prep_fn: Optional[str],
|
|
189
192
|
) -> Tuple[Union[List, None], List[str], str, gr.TextArea, str]:
|
|
190
193
|
"""
|
|
191
194
|
Run generation or inpainting.
|
|
@@ -207,6 +210,7 @@ def run(
|
|
|
207
210
|
:param quantise: `"on"` or `"off"`
|
|
208
211
|
:param jited: `"on"` or `"off"`
|
|
209
212
|
:param sorted\\_: whether to sort the reulst; `"on"` or `"off"`
|
|
213
|
+
:param result_prep_fn: a string form result preprocessing function
|
|
210
214
|
:type model_name: str
|
|
211
215
|
:type token_name: str
|
|
212
216
|
:type vocab_fn: str
|
|
@@ -216,14 +220,15 @@ def run(
|
|
|
216
220
|
:type guidance_strength: float
|
|
217
221
|
:type method: str
|
|
218
222
|
:type temperature: float
|
|
219
|
-
:type prompt: str
|
|
220
|
-
:type scaffold: str
|
|
221
|
-
:type template: str
|
|
222
|
-
:type sar_control: str
|
|
223
|
-
:type exclude_token: str
|
|
223
|
+
:type prompt: str | None
|
|
224
|
+
:type scaffold: str | None
|
|
225
|
+
:type template: str | None
|
|
226
|
+
:type sar_control: str | None
|
|
227
|
+
:type exclude_token: str | None
|
|
224
228
|
:type quantise: str
|
|
225
229
|
:type jited: str
|
|
226
230
|
:type sorted\\_: str
|
|
231
|
+
:type result_prep_fn: str | None
|
|
227
232
|
:return: list of images \n
|
|
228
233
|
list of generated molecules \n
|
|
229
234
|
Chemfig code \n
|
|
@@ -239,6 +244,8 @@ def run(
|
|
|
239
244
|
lora_label_dict = dict([[i[0], i[2] != []] for i in models["lora"]])
|
|
240
245
|
standalone_lmax_dict = dict([[i[0], i[3]] for i in models["standalone"]])
|
|
241
246
|
lora_lmax_dict = dict([[i[0], i[3]] for i in models["lora"]])
|
|
247
|
+
# ------- build result preprocessing function -------
|
|
248
|
+
_result_prep_fn = build_result_prep_fn(result_prep_fn)
|
|
242
249
|
# ------- build tokeniser -------
|
|
243
250
|
if token_name == "SMILES & SAFE":
|
|
244
251
|
vocab_keys = VOCAB_KEYS
|
|
@@ -246,13 +253,13 @@ def run(
|
|
|
246
253
|
trans_fn = lambda x: [i for i in x if (MolFromSmiles(i) and i)]
|
|
247
254
|
img_fn = lambda x: [Draw.MolToImage(MolFromSmiles(i), (500, 500)) for i in x]
|
|
248
255
|
chemfig_fn = lambda x: [mol2chemfig(i, "-r", inline=True) for i in x]
|
|
249
|
-
|
|
256
|
+
elif token_name == "FASTA":
|
|
250
257
|
vocab_keys = FASTA_VOCAB_KEYS
|
|
251
258
|
tokeniser = fasta2vec
|
|
252
259
|
trans_fn = lambda x: [i for i in x if i]
|
|
253
260
|
img_fn = lambda _: None # senseless to provide dumb 2D images
|
|
254
261
|
chemfig_fn = lambda _: [""] # senseless to provide very long Chemfig code
|
|
255
|
-
|
|
262
|
+
elif token_name == "SELFIES":
|
|
256
263
|
vocab_data = load_vocab(vocabs[vocab_fn])
|
|
257
264
|
vocab_keys = vocab_data["vocab_keys"]
|
|
258
265
|
vocab_dict = vocab_data["vocab_dict"]
|
|
@@ -262,11 +269,15 @@ def run(
|
|
|
262
269
|
Draw.MolToImage(MolFromSmiles(decoder(i)), (500, 500)) for i in x
|
|
263
270
|
]
|
|
264
271
|
chemfig_fn = lambda x: [mol2chemfig(decoder(i), "-r", inline=True) for i in x]
|
|
272
|
+
else:
|
|
273
|
+
raise RuntimeError("Oops, maybe something wrong with Gradio.")
|
|
265
274
|
_method = "bfn" if method == "BFN" else f"ode:{temperature}"
|
|
266
275
|
# ------- build model -------
|
|
267
276
|
prompt_info = parse_prompt(prompt)
|
|
268
277
|
sar_flag = parse_sar_control(sar_control)
|
|
269
|
-
|
|
278
|
+
_info = deepcopy(prompt_info)
|
|
279
|
+
_info["semi-autoregression"] = deepcopy(sar_flag)
|
|
280
|
+
print("Prompt summary:", _info) # prompt
|
|
270
281
|
if not prompt_info["lora"]:
|
|
271
282
|
if model_name in base_model_dict:
|
|
272
283
|
lmax = sequence_size
|
|
@@ -287,7 +298,7 @@ def run(
|
|
|
287
298
|
mlp = MLP.from_checkpoint(
|
|
288
299
|
standalone_model_dict[model_name] / "mlp.pt"
|
|
289
300
|
)
|
|
290
|
-
y = torch.tensor([prompt_info["objective"]], dtype=torch.float32)
|
|
301
|
+
y = torch.tensor([prompt_info["objective"][0]], dtype=torch.float32)
|
|
291
302
|
y = mlp.forward(y)
|
|
292
303
|
else:
|
|
293
304
|
y = None
|
|
@@ -317,7 +328,7 @@ def run(
|
|
|
317
328
|
mlp = MLP.from_checkpoint(
|
|
318
329
|
lora_model_dict[prompt_info["lora"][0]] / "mlp.pt"
|
|
319
330
|
)
|
|
320
|
-
y = torch.tensor([prompt_info["objective"]], dtype=torch.float32)
|
|
331
|
+
y = torch.tensor([prompt_info["objective"][0]], dtype=torch.float32)
|
|
321
332
|
y = mlp.forward(y)
|
|
322
333
|
else:
|
|
323
334
|
y = None
|
|
@@ -330,7 +341,7 @@ def run(
|
|
|
330
341
|
if jited == "on":
|
|
331
342
|
bfn.compile()
|
|
332
343
|
else:
|
|
333
|
-
lmax = max(
|
|
344
|
+
lmax = max(lora_lmax_dict[i] for i in prompt_info["lora"])
|
|
334
345
|
if model_name in base_model_dict:
|
|
335
346
|
base_model_dir = base_model_dict[model_name]
|
|
336
347
|
else:
|
|
@@ -355,10 +366,15 @@ def run(
|
|
|
355
366
|
if jited == "on":
|
|
356
367
|
bfn.compile()
|
|
357
368
|
_message.append(f"Sequence length set to {lmax} from model metadata.")
|
|
369
|
+
result_prep_fn_ = lambda x: [_result_prep_fn(i) for i in x]
|
|
358
370
|
# ------- inference -------
|
|
359
371
|
allowed_tokens = parse_exclude_token(exclude_token, vocab_keys)
|
|
360
372
|
if not allowed_tokens:
|
|
361
373
|
allowed_tokens = "all"
|
|
374
|
+
if scaffold is None:
|
|
375
|
+
scaffold = ""
|
|
376
|
+
if template is None:
|
|
377
|
+
template = ""
|
|
362
378
|
scaffold = scaffold.strip()
|
|
363
379
|
template = template.strip()
|
|
364
380
|
if scaffold:
|
|
@@ -376,7 +392,7 @@ def run(
|
|
|
376
392
|
allowed_tokens=allowed_tokens,
|
|
377
393
|
sort=sorted_ == "on",
|
|
378
394
|
)
|
|
379
|
-
mols = trans_fn(mols)
|
|
395
|
+
mols = trans_fn(result_prep_fn_(mols))
|
|
380
396
|
imgs = img_fn(mols)
|
|
381
397
|
chemfigs = chemfig_fn(mols)
|
|
382
398
|
if template:
|
|
@@ -396,7 +412,7 @@ def run(
|
|
|
396
412
|
allowed_tokens=allowed_tokens,
|
|
397
413
|
sort=sorted_ == "on",
|
|
398
414
|
)
|
|
399
|
-
mols = trans_fn(mols)
|
|
415
|
+
mols = trans_fn(result_prep_fn_(mols))
|
|
400
416
|
imgs = img_fn(mols)
|
|
401
417
|
chemfigs = chemfig_fn(mols)
|
|
402
418
|
else:
|
|
@@ -412,17 +428,17 @@ def run(
|
|
|
412
428
|
allowed_tokens=allowed_tokens,
|
|
413
429
|
sort=sorted_ == "on",
|
|
414
430
|
)
|
|
415
|
-
mols = trans_fn(mols)
|
|
431
|
+
mols = trans_fn(result_prep_fn_(mols))
|
|
416
432
|
imgs = img_fn(mols)
|
|
417
433
|
chemfigs = chemfig_fn(mols)
|
|
418
|
-
n_mol = len(mols)
|
|
419
434
|
with open(cache_dir / "results.csv", "w", encoding="utf-8", newline="") as rf:
|
|
420
435
|
rf.write("\n".join(mols))
|
|
421
436
|
_message.append(
|
|
422
|
-
f"{n_mol}
|
|
437
|
+
f"{(n_mol := len(mols))} {'smaple' if n_mol in (0, 1) else 'samples'} "
|
|
438
|
+
"generated and saved to cache that can be downloaded."
|
|
423
439
|
)
|
|
424
|
-
global
|
|
425
|
-
|
|
440
|
+
global _RESULT_COUNT
|
|
441
|
+
_RESULT_COUNT = n_mol
|
|
426
442
|
return (
|
|
427
443
|
imgs,
|
|
428
444
|
mols,
|
|
@@ -432,14 +448,11 @@ def run(
|
|
|
432
448
|
)
|
|
433
449
|
|
|
434
450
|
|
|
435
|
-
with gr.Blocks(
|
|
436
|
-
title="ChemBFN WebUI",
|
|
437
|
-
css="footer {display: none !important} .custom_footer {text-align:center;bottom:0;}",
|
|
438
|
-
analytics_enabled=False,
|
|
439
|
-
) as app:
|
|
451
|
+
with gr.Blocks(title="ChemBFN WebUI", analytics_enabled=False) as app:
|
|
440
452
|
with gr.Row():
|
|
441
453
|
with gr.Column(scale=1):
|
|
442
454
|
btn = gr.Button("RUN", variant="primary")
|
|
455
|
+
stop = gr.Button("\u23f9", variant="stop", visible=False)
|
|
443
456
|
model_name = gr.Dropdown(
|
|
444
457
|
[i[0] for i in models["base"]] + [i[0] for i in models["standalone"]],
|
|
445
458
|
label="model",
|
|
@@ -484,14 +497,15 @@ with gr.Blocks(
|
|
|
484
497
|
message = gr.TextArea(label="message", lines=2)
|
|
485
498
|
with gr.Tab(label="result viewer"):
|
|
486
499
|
with gr.Tab(label="result"):
|
|
487
|
-
btn_download = gr.File(
|
|
500
|
+
btn_download = gr.File(
|
|
501
|
+
str(cache_dir / "results.csv"), label="download", visible=False
|
|
502
|
+
)
|
|
488
503
|
result = gr.Dataframe(
|
|
489
504
|
headers=["molecule"],
|
|
490
|
-
|
|
505
|
+
column_count=(1, "fixed"),
|
|
491
506
|
label="",
|
|
492
|
-
|
|
507
|
+
interactive=False,
|
|
493
508
|
show_row_numbers=True,
|
|
494
|
-
show_copy_button=True,
|
|
495
509
|
)
|
|
496
510
|
with gr.Tab(
|
|
497
511
|
label="LATEX Chemfig", visible=token_name.value != "FASTA"
|
|
@@ -509,7 +523,7 @@ with gr.Blocks(
|
|
|
509
523
|
vocab_table = gr.Dataframe(
|
|
510
524
|
list(vocabs.keys()),
|
|
511
525
|
headers=["name"],
|
|
512
|
-
|
|
526
|
+
column_count=(1, "fixed"),
|
|
513
527
|
label="",
|
|
514
528
|
interactive=False,
|
|
515
529
|
show_row_numbers=True,
|
|
@@ -518,7 +532,7 @@ with gr.Blocks(
|
|
|
518
532
|
base_table = gr.Dataframe(
|
|
519
533
|
[i[0] for i in models["base"]],
|
|
520
534
|
headers=["name"],
|
|
521
|
-
|
|
535
|
+
column_count=(1, "fixed"),
|
|
522
536
|
label="",
|
|
523
537
|
interactive=False,
|
|
524
538
|
show_row_numbers=True,
|
|
@@ -527,7 +541,7 @@ with gr.Blocks(
|
|
|
527
541
|
standalone_table = gr.Dataframe(
|
|
528
542
|
[[i[0], i[2]] for i in models["standalone"]],
|
|
529
543
|
headers=["name", "objective"],
|
|
530
|
-
|
|
544
|
+
column_count=(2, "fixed"),
|
|
531
545
|
label="",
|
|
532
546
|
interactive=False,
|
|
533
547
|
show_row_numbers=True,
|
|
@@ -536,7 +550,7 @@ with gr.Blocks(
|
|
|
536
550
|
lora_tabel = gr.Dataframe(
|
|
537
551
|
[[i[0], i[2]] for i in models["lora"]],
|
|
538
552
|
headers=["name", "objective"],
|
|
539
|
-
|
|
553
|
+
column_count=(2, "fixed"),
|
|
540
554
|
label="",
|
|
541
555
|
interactive=False,
|
|
542
556
|
show_row_numbers=True,
|
|
@@ -553,17 +567,33 @@ with gr.Blocks(
|
|
|
553
567
|
placeholder="key in unwanted tokens separated by comma.",
|
|
554
568
|
html_attributes=HTML_STYLE,
|
|
555
569
|
)
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
label="sort result",
|
|
562
|
-
info="sorting based on entropy",
|
|
570
|
+
result_prep_fn = gr.Textbox(
|
|
571
|
+
"lambda x: x",
|
|
572
|
+
label="result preprocessing function",
|
|
573
|
+
placeholder="lambda x: x",
|
|
574
|
+
html_attributes=HTML_STYLE,
|
|
563
575
|
)
|
|
576
|
+
with gr.Row(scale=1):
|
|
577
|
+
quantise = gr.Radio(
|
|
578
|
+
["on", "off"], value="off", label="quantisation"
|
|
579
|
+
)
|
|
580
|
+
jited = gr.Radio(["on", "off"], value="off", label="JIT")
|
|
581
|
+
sorted_ = gr.Radio(
|
|
582
|
+
["on", "off"], value="off", label="sort result based on entropy"
|
|
583
|
+
)
|
|
564
584
|
gr.HTML(sys_info(), elem_classes="custom_footer", elem_id="footer")
|
|
565
585
|
# ------ user interaction events -------
|
|
566
|
-
btn.click(
|
|
586
|
+
gen = btn.click(
|
|
587
|
+
fn=lambda: (
|
|
588
|
+
gr.Button("RUN", variant="primary", visible=False),
|
|
589
|
+
gr.Button("\u23f9", variant="stop", visible=True),
|
|
590
|
+
),
|
|
591
|
+
inputs=None,
|
|
592
|
+
outputs=[btn, stop],
|
|
593
|
+
api_name="switch_to_stop_mode",
|
|
594
|
+
api_description="Switch to STOP.",
|
|
595
|
+
api_visibility="private",
|
|
596
|
+
).then(
|
|
567
597
|
fn=run,
|
|
568
598
|
inputs=[
|
|
569
599
|
model_name,
|
|
@@ -583,11 +613,36 @@ with gr.Blocks(
|
|
|
583
613
|
quantise,
|
|
584
614
|
jited,
|
|
585
615
|
sorted_,
|
|
616
|
+
result_prep_fn,
|
|
586
617
|
],
|
|
587
618
|
outputs=[img, result, chemfig, message, btn_download],
|
|
619
|
+
api_name="run",
|
|
620
|
+
api_description="Run ChemBFN model.",
|
|
621
|
+
)
|
|
622
|
+
gen.then(
|
|
623
|
+
fn=lambda: (
|
|
624
|
+
gr.Button("RUN", variant="primary", visible=True),
|
|
625
|
+
gr.Button("\u23f9", variant="stop", visible=False),
|
|
626
|
+
),
|
|
627
|
+
inputs=None,
|
|
628
|
+
outputs=[btn, stop],
|
|
629
|
+
api_name="switch_back_to_run_mode",
|
|
630
|
+
api_description="Swtch back to RUN.",
|
|
631
|
+
api_visibility="private",
|
|
632
|
+
)
|
|
633
|
+
stop.click(
|
|
634
|
+
fn=lambda: (
|
|
635
|
+
gr.Button("RUN", variant="primary", visible=True),
|
|
636
|
+
gr.Button("\u23f9", variant="stop", visible=False),
|
|
637
|
+
),
|
|
638
|
+
inputs=None,
|
|
639
|
+
outputs=[btn, stop],
|
|
640
|
+
cancels=[gen],
|
|
641
|
+
api_name="stop",
|
|
642
|
+
api_description="Stop the model.",
|
|
588
643
|
)
|
|
589
644
|
btn_refresh.click(
|
|
590
|
-
fn=
|
|
645
|
+
fn=_refresh,
|
|
591
646
|
inputs=[model_name, vocab_fn, token_name],
|
|
592
647
|
outputs=[
|
|
593
648
|
vocab_table,
|
|
@@ -597,11 +652,14 @@ with gr.Blocks(
|
|
|
597
652
|
model_name,
|
|
598
653
|
vocab_fn,
|
|
599
654
|
],
|
|
655
|
+
api_name="refresh_model_list",
|
|
656
|
+
api_description="Refresh the model list.",
|
|
600
657
|
)
|
|
601
658
|
token_name.input(
|
|
602
|
-
fn=
|
|
659
|
+
fn=_token_name_change_evt,
|
|
603
660
|
inputs=[token_name, vocab_fn],
|
|
604
661
|
outputs=[vocab_fn, code, gallery],
|
|
662
|
+
api_visibility="private",
|
|
605
663
|
)
|
|
606
664
|
method.input(
|
|
607
665
|
fn=lambda x, y: gr.Slider(
|
|
@@ -614,12 +672,25 @@ with gr.Blocks(
|
|
|
614
672
|
),
|
|
615
673
|
inputs=[method, temperature],
|
|
616
674
|
outputs=temperature,
|
|
675
|
+
api_name="select_sampling_method",
|
|
676
|
+
api_description="Select sampling method between 'BFN' and 'ODE'.",
|
|
677
|
+
api_visibility="private",
|
|
678
|
+
)
|
|
679
|
+
lora_tabel.select(
|
|
680
|
+
fn=_select_lora,
|
|
681
|
+
inputs=prompt,
|
|
682
|
+
outputs=prompt,
|
|
683
|
+
api_name="select_lora",
|
|
684
|
+
api_description="Select LoRA model from the model list.",
|
|
685
|
+
api_visibility="private",
|
|
617
686
|
)
|
|
618
|
-
lora_tabel.select(fn=select_lora, inputs=prompt, outputs=prompt)
|
|
619
687
|
result.change(
|
|
620
|
-
fn=lambda x: gr.File(x, label="download", visible=
|
|
688
|
+
fn=lambda x: gr.File(x, label="download", visible=_RESULT_COUNT > 0),
|
|
621
689
|
inputs=btn_download,
|
|
622
690
|
outputs=btn_download,
|
|
691
|
+
api_name="change_download_state",
|
|
692
|
+
api_description="Hide or show the file downloading item.",
|
|
693
|
+
api_visibility="private",
|
|
623
694
|
)
|
|
624
695
|
|
|
625
696
|
|
|
@@ -630,9 +701,13 @@ def main() -> None:
|
|
|
630
701
|
:return:
|
|
631
702
|
:rtype: None
|
|
632
703
|
"""
|
|
704
|
+
from rdkit import RDLogger
|
|
705
|
+
|
|
706
|
+
RDLogger.DisableLog("rdApp.*") # type: ignore
|
|
633
707
|
parser = argparse.ArgumentParser(
|
|
634
708
|
description="A web-based visualisation tool for ChemBFN method.",
|
|
635
|
-
epilog=f"ChemBFN WebUI {__version__},
|
|
709
|
+
epilog=f"ChemBFN WebUI {__version__}, "
|
|
710
|
+
"developed in Hiroshima University by chemists for chemists. "
|
|
636
711
|
"Visit https://augus1999.github.io/bayesian-flow-network-for-chemistry/ for more details.",
|
|
637
712
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
638
713
|
)
|
|
@@ -644,8 +719,10 @@ def main() -> None:
|
|
|
644
719
|
print(f"This is ChemBFN WebUI version {__version__}")
|
|
645
720
|
app.launch(
|
|
646
721
|
share=args.public,
|
|
722
|
+
footer_links=["api"],
|
|
647
723
|
allowed_paths=[cache_dir.absolute().__str__()],
|
|
648
724
|
favicon_path=favicon_dir.absolute().__str__(),
|
|
725
|
+
css=".custom_footer {text-align:center;bottom:0;}",
|
|
649
726
|
)
|
|
650
727
|
|
|
651
728
|
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c1ccccc1
|