From 6a4ad04220854fb6b1a549440b700a26b0a8cf40 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 15:07:29 +0100 Subject: [PATCH 01/10] add docker image for molecular transformer. --- .../docker/molecular-transformer/Dockerfile | 11 +++ chemcrow/docker/molecular-transformer/app.py | 75 +++++++++++++++++++ .../molecular-transformer/models/README.md | 1 + 3 files changed, 87 insertions(+) create mode 100644 chemcrow/docker/molecular-transformer/Dockerfile create mode 100644 chemcrow/docker/molecular-transformer/app.py create mode 100644 chemcrow/docker/molecular-transformer/models/README.md diff --git a/chemcrow/docker/molecular-transformer/Dockerfile b/chemcrow/docker/molecular-transformer/Dockerfile new file mode 100644 index 0000000..3832fa6 --- /dev/null +++ b/chemcrow/docker/molecular-transformer/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.10 +WORKDIR /app + +RUN pip install rdkit-pypi==2022.3.1 +RUN pip install OpenNMT-py==2.2.0 "numpy<2.0.0" + +COPY . . +COPY input.txt . +COPY models/ . +CMD ["python", "app.py"] + diff --git a/chemcrow/docker/molecular-transformer/app.py b/chemcrow/docker/molecular-transformer/app.py new file mode 100644 index 0000000..c937d4b --- /dev/null +++ b/chemcrow/docker/molecular-transformer/app.py @@ -0,0 +1,75 @@ +import re +import subprocess +from flask import Flask, request, jsonify +from rdkit import Chem + +app = Flask(__name__) + + +SMI_REGEX_PATTERN = r"(\%\([0-9]{3}\)|\[[^\]]+]|Br?|Cl?|N|O|S|P|F|I|b|c|n|o|s|p|\||\(|\)|\.|=|#|-|\+|\\|\/|:|~|@|\?|>>?|\*|\$|\%[0-9]{2}|[0-9])" + +def canonicalize_smiles(smiles, verbose=False): # will raise an Exception if invalid SMILES + mol = Chem.MolFromSmiles(smiles) + if mol is not None: + return Chem.MolToSmiles(mol) + else: + if verbose: + print(f'{smiles} is invalid.') + return '' + +def smiles_tokenizer(smiles): + """Canonicalize and tokenize input smiles""" + + smiles = canonicalize_smiles(smiles) + smiles_regex = re.compile(SMI_REGEX_PATTERN) + tokens = [token for token in smiles_regex.findall(smiles)] + return ' '.join(tokens) + + +@app.route('/api/v1/run', methods=['POST']) +def f(): + request_data = request.get_json() + input = request_data['smiles'] + + # Write the input to 'inp.txt' + with open('input.txt', 'w') as f: + # Tokenize smiles + smi = smiles_tokenizer(input) + f.write(smi) + + model_path = 'models/USPTO480k_model_step_400000.pt' + + src_path = 'input.txt' + output_path = 'output.txt' + n_best = 5 + beam_size = 10 + max_length = 300 + batch_size = 1 + + try: + # Construct the command to execute + cmd = f"onmt_translate -model {model_path} " \ + f"--src {src_path} " \ + f"--output {output_path} --n_best {n_best} " \ + f"--beam_size {beam_size} --max_length {max_length} " \ + f"--batch_size {batch_size}" + + # Execute the command using subprocess.check_call() + subprocess.check_call(cmd, shell=True) + + # Read produced output + with open('output.txt', 'r') as f: + prods = f.read() + prods = re.sub(' ', '', prods).split('\n') + + + # Return a success message + return jsonify({'status': 'SUCCESS', 'product': prods}) + + except: + return jsonify({'status': 'ERROR', 'product': None}) + +if __name__ == '__main__': + # Run the Flask app + app.run(debug=True, host='0.0.0.0') + diff --git a/chemcrow/docker/molecular-transformer/models/README.md b/chemcrow/docker/molecular-transformer/models/README.md new file mode 100644 index 0000000..715cad2 --- /dev/null +++ b/chemcrow/docker/molecular-transformer/models/README.md @@ -0,0 +1 @@ +# Download model from https://drive.google.com/uc?id=1ywJCJHunoPTB5wr6KdZ8aLv7tMFMBHNy From af101e8a03797944cc61d012772dee892f492d63 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 15:17:30 +0100 Subject: [PATCH 02/10] add readme to download model --- chemcrow/docker/README.md | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 chemcrow/docker/README.md diff --git a/chemcrow/docker/README.md b/chemcrow/docker/README.md new file mode 100644 index 0000000..225d63c --- /dev/null +++ b/chemcrow/docker/README.md @@ -0,0 +1,54 @@ + +# Tools of organic chemistry + +A docker container was prepared for each tool, which exposes an api for requests. + +> docker run -d -p 8082:5000 doncamilom/rxnpred:latest + +Where 5000 is fixed, and 8082 is the port to be exposed. + +A request in curl can look like this + +> curl -X POST -H "Content-Type: application/json" -d '{"smiles": "O=C(OC(C)(C)C)c1ccc(C(=O)Nc2ccc(Cl)cc2)cc1"}' http://localhost:8082/api/v1/run + +Or in Python + +```python + +import json +import requests + +def reaction_predict(reactants): + response = requests.post( + "http://localhost:8082/api/v1/translate", + headers={"Content-Type": "application/json"}, + data=json.dumps({"smiles": reactants}) + ) + return response.json()['product'][0] + +product = reaction_predict('CCOCCCCO.CC(=O)Cl') +``` + +## Tools + +- [ ] Retrosynthesis (AiZynthfinder) +- [ ] Reaction prediction (Molecular Transformer) +- [ ] Reaction fingerprints (RXNFP) + + +## TO-DO (missing tools) + +- [ ] Condition prediction (Coley) +- [ ] LinChemIn (Syngenta) +- [ ] Reaction equilibration (Theo) +- [ ] Literature parsing (Coley, J.Cole, Jasyntho) +- [ ] Descriptors (?) +- [ ] Maybe robotic platform/simulator +- [ ] Other calculation software +- [ ] Multimodal molecule description, generation (GIT-Mol) https://github.com/AI-HPC-Research-Team/GIT-Mol/tree/main +- [ ] Multimodal too, SOTA (BioT5+) (https://huggingface.co/QizhiPei/biot5-base) +- [ ] Text to Mol (https://huggingface.co/spaces/ndhieunguyen/Lang2mol-Diff) -- checkout the app.py +- [ ] text2mol, mol2text https://github.com/QizhiPei/BioT5 (inference code. different FTs for each task? +- [ ] MolGrapher https://github.com/DS4SD/MolGrapher image->smiles. easy as is in huggingface + +saccrow-data/papers From 06e50fe71e1da715a5f5ff503c01966d703de276 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 15:17:44 +0100 Subject: [PATCH 03/10] update readme --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index b62f489..cf80361 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,31 @@ chem_model = ChemCrow(model="gpt-4-0613", temp=0.1, streaming=False) chem_model.run("What is the molecular weight of tylenol?") ``` + +## 🛠️ Self-hosting of some tools. + +By default, ChemCrow relies on the RXN4Chem API for retrosynthetic planning and reaction product prediction. This can however be slow and depends on you having an API key. + +Optionally, you can also self host these tools by running some pre-made docker images. + +Run + +``` +docker run --gpus all -d -p 8051:5000 doncamilom/rxnpred:latest +docker run --gpus all -d -p 8052:5000 doncamilom/retrosynthesis:latest +``` + + +Now ChemCrow can be used like this: + +```python +from chemcrow.agents import ChemCrow + +chem_model = ChemCrow(model="gpt-4-0613", temp=0.1, streaming=False, local_rxn=True) +chem_model.run("What is the product of the reaction between styrene and dibromine?") +``` + + ## ✅ Citation Bran, Andres M., et al. "ChemCrow: Augmenting large-language models with chemistry tools." arXiv preprint arXiv:2304.05376 (2023). From 58352fc8c8133835ab397eec2f4dfe903b8824d8 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 17:15:21 +0100 Subject: [PATCH 04/10] updating tests. they were failing --- tests/test_converters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_converters.py b/tests/test_converters.py index 0ca0b3d..41760f7 100644 --- a/tests/test_converters.py +++ b/tests/test_converters.py @@ -79,7 +79,7 @@ def test_query2smiles_chemspace(singlemol, single_iupac): else: chemspace = ChemSpace(chemspace_api_key=os.getenv("CHEMSPACE_API_KEY")) smiles_from_chemspace = chemspace.convert_mol_rep("caffeine", "smiles") - assert "CN1C=NC2=C1C(=O)N(C)C(=O)N2[13CH3]" in smiles_from_chemspace + assert "CN1C=NC2=C1C(=O)N(C)C(=O)N2C" in smiles_from_chemspace price = chemspace.buy_mol(singlemol) assert "of this molecule cost" in price @@ -91,8 +91,8 @@ def test_query2smiles_chemspace(singlemol, single_iupac): def test_smiles2name(): smiles2name = SMILES2Name() assert ( - smiles2name.run("CN1C=NC2=C1C(=O)N(C)C(=O)N2[13CH3]") - == "1,7-Dimethyl-3-(113C)methylpurine-2,6-dione" + smiles2name.run("CN1C=NC2=C1C(=O)N(C)C(=O)N2C") + == "caffeine" ) assert "acetic acid" in smiles2name.run("CC(=O)O").lower() assert "Error:" in smiles2name.run("nonsense") From 1bb22dd1065e17df246e27fde582dec748419293 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 17:21:03 +0100 Subject: [PATCH 05/10] add optional local_rxn add working tool --- chemcrow/agents/chemcrow.py | 3 +- chemcrow/agents/tools.py | 9 ++++- chemcrow/tools/__init__.py | 1 + chemcrow/tools/reactions.py | 80 +++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 chemcrow/tools/reactions.py diff --git a/chemcrow/agents/chemcrow.py b/chemcrow/agents/chemcrow.py index 4528887..3bcbe8b 100644 --- a/chemcrow/agents/chemcrow.py +++ b/chemcrow/agents/chemcrow.py @@ -46,6 +46,7 @@ def __init__( streaming: bool = True, openai_api_key: Optional[str] = None, api_keys: dict = {}, + local_rxn: bool = False, ): """Initialize ChemCrow agent.""" @@ -58,7 +59,7 @@ def __init__( if tools is None: api_keys["OPENAI_API_KEY"] = openai_api_key tools_llm = _make_llm(tools_model, temp, openai_api_key, streaming) - tools = make_tools(tools_llm, api_keys=api_keys, verbose=verbose) + tools = make_tools(tools_llm, api_keys=api_keys, local_rxn=local_rxn, verbose=verbose) # Initialize agent self.agent_executor = RetryAgentExecutor.from_agent_and_tools( diff --git a/chemcrow/agents/tools.py b/chemcrow/agents/tools.py index 6574cd8..f7bfcdf 100644 --- a/chemcrow/agents/tools.py +++ b/chemcrow/agents/tools.py @@ -6,7 +6,7 @@ from chemcrow.tools import * -def make_tools(llm: BaseLanguageModel, api_keys: dict = {}, verbose=True): +def make_tools(llm: BaseLanguageModel, api_keys: dict = {}, local_rxn: bool=False, verbose=True): serp_api_key = api_keys.get("SERP_API_KEY") or os.getenv("SERP_API_KEY") rxn4chem_api_key = api_keys.get("RXN4CHEM_API_KEY") or os.getenv("RXN4CHEM_API_KEY") openai_api_key = api_keys.get("OPENAI_API_KEY") or os.getenv("OPENAI_API_KEY") @@ -48,10 +48,15 @@ def make_tools(llm: BaseLanguageModel, api_keys: dict = {}, verbose=True): all_tools += [GetMoleculePrice(chemspace_api_key)] if serp_api_key: all_tools += [WebSearch(serp_api_key)] - if rxn4chem_api_key: + if (not local_rxn) and rxn4chem_api_key: all_tools += [ RXNPredict(rxn4chem_api_key), RXNRetrosynthesis(rxn4chem_api_key, openai_api_key), ] + elif local_rxn: + all_tools += [ + RXNPredictLocal(), + RXNRetrosynthesisLocal() + ] return all_tools diff --git a/chemcrow/tools/__init__.py b/chemcrow/tools/__init__.py index c175d4b..9addc8e 100644 --- a/chemcrow/tools/__init__.py +++ b/chemcrow/tools/__init__.py @@ -6,3 +6,4 @@ from .safety import * # noqa from .chemspace import * # noqa from .converters import * # noqa +from .reactions import * # noqa diff --git a/chemcrow/tools/reactions.py b/chemcrow/tools/reactions.py new file mode 100644 index 0000000..48211e3 --- /dev/null +++ b/chemcrow/tools/reactions.py @@ -0,0 +1,80 @@ +"""Self-hosted reaction tools. Retrosynthesis, reaction forward prediction.""" + +import abc +import ast +import re +from time import sleep +from typing import Optional + +import requests + +import json +from langchain.chat_models import ChatOpenAI +from langchain.schema import HumanMessage +from langchain.tools import BaseTool + +from chemcrow.utils import is_smiles + +__all__ = ["RXNPredictLocal", "RXNRetrosynthesisLocal"] + + +class RXNPredictLocal(BaseTool): + """Predict reaction.""" + + name = "ReactionPredict" + description = ( + "Predict the outcome of a chemical reaction. " + "Takes as input the SMILES of the reactants separated by a dot '.', " + "returns SMILES of the products." + ) + + def _run(self, reactants: str) -> str: + """Run reaction prediction.""" + if not is_smiles(reactants): + return "Incorrect input." + + product = self.predict_reaction(reactants) + return product + + def predict_reaction(self, reactants: str) -> str: + """Make api request.""" + try: + response = requests.post( + "http://localhost:8051/api/v1/run", + headers={"Content-Type": "application/json"}, + data=json.dumps({"smiles": reactants}) + ) + return response.json()['product'][0] + except: + return "Error in prediction." + + +class RXNRetrosynthesisLocal(BaseTool): + """Predict retrosynthesis.""" + + name = "ReactionRetrosynthesis" + description = ( + "Obtain the synthetic route to a chemical compound. " + "Takes as input the SMILES of the product, returns recipe." + ) + openai_api_key: str = "" + + def _run(self, reactants: str) -> str: + """Run reaction prediction.""" + # Check that input is smiles + if not is_smiles(reactants): + return "Incorrect input." + + prediction_id = self.predict_reaction(reactants) + results = self.get_results(prediction_id) + product = results["productMolecule"]["smiles"] + return product + + def predict_reaction(self, reactants: str) -> str: + """Make api request.""" + response = requests.post( + "http://localhost:8021/api/v1/run", + headers={"Content-Type": "application/json"}, + data=json.dumps({"smiles": reactants}) + ) + return response.json()['product'][0] From 28740cd69607fe8179432a9cdd40a6c5799d5e95 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 17:42:14 +0100 Subject: [PATCH 06/10] add readme for files --- chemcrow/docker/aizynthfinder/Dockerfile | 9 ++++++ chemcrow/docker/aizynthfinder/app.py | 29 +++++++++++++++++++ chemcrow/docker/aizynthfinder/config.yml | 11 +++++++ chemcrow/docker/aizynthfinder/files/README.md | 11 +++++++ 4 files changed, 60 insertions(+) create mode 100644 chemcrow/docker/aizynthfinder/Dockerfile create mode 100644 chemcrow/docker/aizynthfinder/app.py create mode 100644 chemcrow/docker/aizynthfinder/config.yml create mode 100644 chemcrow/docker/aizynthfinder/files/README.md diff --git a/chemcrow/docker/aizynthfinder/Dockerfile b/chemcrow/docker/aizynthfinder/Dockerfile new file mode 100644 index 0000000..92d9520 --- /dev/null +++ b/chemcrow/docker/aizynthfinder/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.9 +RUN pip install aizynthfinder[all] flask +COPY files/ . +COPY . . + +EXPOSE 5000 +ENTRYPOINT ["python"] + +CMD ["app.py"] diff --git a/chemcrow/docker/aizynthfinder/app.py b/chemcrow/docker/aizynthfinder/app.py new file mode 100644 index 0000000..f8c98f3 --- /dev/null +++ b/chemcrow/docker/aizynthfinder/app.py @@ -0,0 +1,29 @@ +import json +import subprocess + +from flask import Flask, jsonify, request + +app = Flask(__name__) + +@app.route('/api/v1/run', methods=['POST']) +def rxnfp(): + data = request.get_json() + target = data.get("target", []) + + command = ["aizynthcli", "--config", "config.yml", "--smiles", f"{target}"] + + print(command) + result = subprocess.run( + command, check=True, capture_output=True, text=True + ) + print(result) + + # Read output trees.json + with open("trees.json", "r") as f: + tree = json.load(f) + + return tree + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) diff --git a/chemcrow/docker/aizynthfinder/config.yml b/chemcrow/docker/aizynthfinder/config.yml new file mode 100644 index 0000000..1e26ccc --- /dev/null +++ b/chemcrow/docker/aizynthfinder/config.yml @@ -0,0 +1,11 @@ +expansion: + uspto: + - files/uspto_model.onnx + - files/uspto_templates.csv.gz + ringbreaker: + - files/uspto_ringbreaker_model.onnx + - files/uspto_ringbreaker_templates.csv.gz +filter: + uspto: files/uspto_filter_model.onnx +stock: + zinc: files/zinc_stock.hdf5 diff --git a/chemcrow/docker/aizynthfinder/files/README.md b/chemcrow/docker/aizynthfinder/files/README.md new file mode 100644 index 0000000..6cfc2db --- /dev/null +++ b/chemcrow/docker/aizynthfinder/files/README.md @@ -0,0 +1,11 @@ +# Download al lthe important files for runnig aizynthfinder using + +``` +download_public_data . +``` + +Which comes by installing aizynthfinder + +``` +pip install aizynthfinder[all] +``` From 6526f2daa81b6e6b38533d92234d88df7b0ad557 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 17:44:21 +0100 Subject: [PATCH 07/10] ignore model files --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index c7a6e11..6a425fe 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,10 @@ dmypy.json local/ *ipynb query/ + +# Models in docker directory +**/docker/molecular-transformer/*txt +*.pt +*onnx +**/docker/*/files/*csv.gz +**/docker/*/files/*hdf5 \ No newline at end of file From 39dbc84d6bb75a66af5fe1842625b38e234c5e6d Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 18:24:24 +0100 Subject: [PATCH 08/10] fix local retro tool --- chemcrow/tools/reactions.py | 56 ++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/chemcrow/tools/reactions.py b/chemcrow/tools/reactions.py index 48211e3..1fdb6e8 100644 --- a/chemcrow/tools/reactions.py +++ b/chemcrow/tools/reactions.py @@ -65,16 +65,58 @@ def _run(self, reactants: str) -> str: if not is_smiles(reactants): return "Incorrect input." - prediction_id = self.predict_reaction(reactants) - results = self.get_results(prediction_id) - product = results["productMolecule"]["smiles"] - return product + paths = self.retrosynthesis(reactants) + procedure = self.get_action_sequence(paths[0]) + return procedure - def predict_reaction(self, reactants: str) -> str: + def retrosynthesis(self, reactants: str) -> str: """Make api request.""" response = requests.post( - "http://localhost:8021/api/v1/run", + "http://localhost:8052/api/v1/run", headers={"Content-Type": "application/json"}, data=json.dumps({"smiles": reactants}) ) - return response.json()['product'][0] + return response.json() + + def get_action_sequence(self, path): + """Get sequence of actions.""" + actions = path + json_actions = self._preproc_actions(actions) + llm_sum = self._summary_gpt(json_actions) + return llm_sum + + def _preproc_actions(self, path): + """Preprocess actions.""" + def _clean_actions(d): + if 'metadata' in d: + if 'mapped_reaction_smiles' in d['metadata']: + r = d['metadata']['mapped_reaction_smiles'].split(">>") + yield {"reactants": r[1], "products": r[0]} + if 'children' in d: + for c in d['children']: + yield from _clean_actions(c) + + rxns = list(_clean_actions(path)) + return rxns + + def _summary_gpt(self, json: dict) -> str: + """Describe synthesis.""" + llm = ChatOpenAI( # type: ignore + temperature=0.05, + model_name="gpt-3.5-turbo-16k", + request_timeout=2000, + max_tokens=2000, + openai_api_key=self.openai_api_key, + ) + prompt = ( + "Here is a chemical synthesis described as a json.\nYour task is " + "to describe the synthesis, as if you were giving instructions for" + "a recipe. Use only the substances, quantities, temperatures and " + "in general any action mentioned in the json file. This is your " + "only source of information, do not make up anything else. Also, " + "add 15mL of DCM as a solvent in the first step. If you ever need " + 'to refer to the json file, refer to it as "(by) the tool". ' + "However avoid references to it. \nFor this task, give as many " + f"details as possible.\n {str(json)}" + ) + return llm([HumanMessage(content=prompt)]).content From c85b3604b207a4a3d5f223485bb191fe312e505a Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 18:24:53 +0100 Subject: [PATCH 09/10] lint --- chemcrow/tools/rxn4chem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chemcrow/tools/rxn4chem.py b/chemcrow/tools/rxn4chem.py index c7be7e3..de65ec7 100644 --- a/chemcrow/tools/rxn4chem.py +++ b/chemcrow/tools/rxn4chem.py @@ -100,7 +100,7 @@ def _run(self, reactants: str) -> str: product = results["productMolecule"]["smiles"] return product - @RXN4Chem.retry(10, KeyError) + # @RXN4Chem.retry(10, KeyError) def predict_reaction(self, reactants: str) -> str: """Make api request.""" response = self.rxn4chem.predict_reaction(reactants) @@ -109,7 +109,7 @@ def predict_reaction(self, reactants: str) -> str: else: raise KeyError - @RXN4Chem.retry(10, KeyError) + # @RXN4Chem.retry(10, KeyError) def get_results(self, prediction_id: str) -> str: """Make api request.""" results = self.rxn4chem.get_predict_reaction_results(prediction_id) From fc7039c81b3e25fc1a5ce7ff4b371fa79a0eced5 Mon Sep 17 00:00:00 2001 From: Andres M Bran Date: Thu, 19 Dec 2024 18:25:49 +0100 Subject: [PATCH 10/10] add readme for building docker images --- chemcrow/docker/README.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/chemcrow/docker/README.md b/chemcrow/docker/README.md index 225d63c..67d17a8 100644 --- a/chemcrow/docker/README.md +++ b/chemcrow/docker/README.md @@ -3,7 +3,7 @@ A docker container was prepared for each tool, which exposes an api for requests. -> docker run -d -p 8082:5000 doncamilom/rxnpred:latest +> docker run -d -p 8052:5000 doncamilom/rxnpred:latest Where 5000 is fixed, and 8082 is the port to be exposed. @@ -20,7 +20,7 @@ import requests def reaction_predict(reactants): response = requests.post( - "http://localhost:8082/api/v1/translate", + "http://localhost:8052/api/v1/run", headers={"Content-Type": "application/json"}, data=json.dumps({"smiles": reactants}) ) @@ -28,27 +28,3 @@ def reaction_predict(reactants): product = reaction_predict('CCOCCCCO.CC(=O)Cl') ``` - -## Tools - -- [ ] Retrosynthesis (AiZynthfinder) -- [ ] Reaction prediction (Molecular Transformer) -- [ ] Reaction fingerprints (RXNFP) - - -## TO-DO (missing tools) - -- [ ] Condition prediction (Coley) -- [ ] LinChemIn (Syngenta) -- [ ] Reaction equilibration (Theo) -- [ ] Literature parsing (Coley, J.Cole, Jasyntho) -- [ ] Descriptors (?) -- [ ] Maybe robotic platform/simulator -- [ ] Other calculation software -- [ ] Multimodal molecule description, generation (GIT-Mol) https://github.com/AI-HPC-Research-Team/GIT-Mol/tree/main -- [ ] Multimodal too, SOTA (BioT5+) (https://huggingface.co/QizhiPei/biot5-base) -- [ ] Text to Mol (https://huggingface.co/spaces/ndhieunguyen/Lang2mol-Diff) -- checkout the app.py -- [ ] text2mol, mol2text https://github.com/QizhiPei/BioT5 (inference code. different FTs for each task? -- [ ] MolGrapher https://github.com/DS4SD/MolGrapher image->smiles. easy as is in huggingface - -saccrow-data/papers