diff --git a/docs/tutorials/design-with-safe.ipynb b/docs/tutorials/design-with-safe.ipynb
index f5bb36c..f99e7d3 100644
--- a/docs/tutorials/design-with-safe.ipynb
+++ b/docs/tutorials/design-with-safe.ipynb
@@ -3,7 +3,11 @@
{
"cell_type": "code",
"execution_count": 1,
- "metadata": {},
+ "metadata": {
+ "tags": [
+ "remove_cell"
+ ]
+ },
"outputs": [],
"source": [
"%load_ext autoreload\n",
@@ -12,7 +16,7 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -27,56 +31,77 @@
]
},
{
- "cell_type": "code",
- "execution_count": 2,
+ "cell_type": "markdown",
"metadata": {},
- "outputs": [
- {
- "ename": "HFValidationError",
- "evalue": "Repo id must be in the form 'repo_name' or 'namespace/repo_name': '/home/hadim/.cache/safe/default_model'. Use `repo_type` argument if needed.",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mHFValidationError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m/home/hadim/Code/valence/Libs/safe/docs/tutorials/design-with-safe.ipynb Cell 3\u001b[0m line \u001b[0;36m1\n\u001b[0;32m----> 1\u001b[0m designer \u001b[39m=\u001b[39m sf\u001b[39m.\u001b[39;49mSAFEDesign\u001b[39m.\u001b[39;49mload_default(verbose\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m)\n",
- "File \u001b[0;32m~/Code/valence/Libs/safe/safe/sample.py:89\u001b[0m, in \u001b[0;36mSAFEDesign.load_default\u001b[0;34m(cls, verbose, model_dir, device)\u001b[0m\n\u001b[1;32m 87\u001b[0m \u001b[39mif\u001b[39;00m model_dir \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m \u001b[39mor\u001b[39;00m \u001b[39mnot\u001b[39;00m model_dir:\n\u001b[1;32m 88\u001b[0m model_dir \u001b[39m=\u001b[39m \u001b[39mcls\u001b[39m\u001b[39m.\u001b[39m_DEFAULT_MODEL_PATH\n\u001b[0;32m---> 89\u001b[0m model \u001b[39m=\u001b[39m SAFEDoubleHeadsModel\u001b[39m.\u001b[39;49mfrom_pretrained(model_dir)\n\u001b[1;32m 90\u001b[0m tokenizer \u001b[39m=\u001b[39m SAFETokenizer\u001b[39m.\u001b[39mload(os\u001b[39m.\u001b[39mpath\u001b[39m.\u001b[39mjoin(model_dir, \u001b[39m\"\u001b[39m\u001b[39mtokenizer.json\u001b[39m\u001b[39m\"\u001b[39m))\n\u001b[1;32m 91\u001b[0m gen_config \u001b[39m=\u001b[39m GenerationConfig\u001b[39m.\u001b[39mfrom_pretrained(model_dir)\n",
- "File \u001b[0;32m~/local/micromamba/envs/safe/lib/python3.11/site-packages/transformers/modeling_utils.py:2507\u001b[0m, in \u001b[0;36mPreTrainedModel.from_pretrained\u001b[0;34m(cls, pretrained_model_name_or_path, config, cache_dir, ignore_mismatched_sizes, force_download, local_files_only, token, revision, use_safetensors, *model_args, **kwargs)\u001b[0m\n\u001b[1;32m 2504\u001b[0m \u001b[39mif\u001b[39;00m commit_hash \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 2505\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39misinstance\u001b[39m(config, PretrainedConfig):\n\u001b[1;32m 2506\u001b[0m \u001b[39m# We make a call to the config file first (which may be absent) to get the commit hash as soon as possible\u001b[39;00m\n\u001b[0;32m-> 2507\u001b[0m resolved_config_file \u001b[39m=\u001b[39m cached_file(\n\u001b[1;32m 2508\u001b[0m pretrained_model_name_or_path,\n\u001b[1;32m 2509\u001b[0m CONFIG_NAME,\n\u001b[1;32m 2510\u001b[0m cache_dir\u001b[39m=\u001b[39;49mcache_dir,\n\u001b[1;32m 2511\u001b[0m force_download\u001b[39m=\u001b[39;49mforce_download,\n\u001b[1;32m 2512\u001b[0m resume_download\u001b[39m=\u001b[39;49mresume_download,\n\u001b[1;32m 2513\u001b[0m proxies\u001b[39m=\u001b[39;49mproxies,\n\u001b[1;32m 2514\u001b[0m local_files_only\u001b[39m=\u001b[39;49mlocal_files_only,\n\u001b[1;32m 2515\u001b[0m token\u001b[39m=\u001b[39;49mtoken,\n\u001b[1;32m 2516\u001b[0m revision\u001b[39m=\u001b[39;49mrevision,\n\u001b[1;32m 2517\u001b[0m subfolder\u001b[39m=\u001b[39;49msubfolder,\n\u001b[1;32m 2518\u001b[0m _raise_exceptions_for_missing_entries\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 2519\u001b[0m _raise_exceptions_for_connection_errors\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m,\n\u001b[1;32m 2520\u001b[0m )\n\u001b[1;32m 2521\u001b[0m commit_hash \u001b[39m=\u001b[39m extract_commit_hash(resolved_config_file, commit_hash)\n\u001b[1;32m 2522\u001b[0m \u001b[39melse\u001b[39;00m:\n",
- "File \u001b[0;32m~/local/micromamba/envs/safe/lib/python3.11/site-packages/transformers/utils/hub.py:429\u001b[0m, in \u001b[0;36mcached_file\u001b[0;34m(path_or_repo_id, filename, cache_dir, force_download, resume_download, proxies, token, revision, local_files_only, subfolder, repo_type, user_agent, _raise_exceptions_for_missing_entries, _raise_exceptions_for_connection_errors, _commit_hash, **deprecated_kwargs)\u001b[0m\n\u001b[1;32m 426\u001b[0m user_agent \u001b[39m=\u001b[39m http_user_agent(user_agent)\n\u001b[1;32m 427\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[1;32m 428\u001b[0m \u001b[39m# Load from URL or cache if already cached\u001b[39;00m\n\u001b[0;32m--> 429\u001b[0m resolved_file \u001b[39m=\u001b[39m hf_hub_download(\n\u001b[1;32m 430\u001b[0m path_or_repo_id,\n\u001b[1;32m 431\u001b[0m filename,\n\u001b[1;32m 432\u001b[0m subfolder\u001b[39m=\u001b[39;49m\u001b[39mNone\u001b[39;49;00m \u001b[39mif\u001b[39;49;00m \u001b[39mlen\u001b[39;49m(subfolder) \u001b[39m==\u001b[39;49m \u001b[39m0\u001b[39;49m \u001b[39melse\u001b[39;49;00m subfolder,\n\u001b[1;32m 433\u001b[0m repo_type\u001b[39m=\u001b[39;49mrepo_type,\n\u001b[1;32m 434\u001b[0m revision\u001b[39m=\u001b[39;49mrevision,\n\u001b[1;32m 435\u001b[0m cache_dir\u001b[39m=\u001b[39;49mcache_dir,\n\u001b[1;32m 436\u001b[0m user_agent\u001b[39m=\u001b[39;49muser_agent,\n\u001b[1;32m 437\u001b[0m force_download\u001b[39m=\u001b[39;49mforce_download,\n\u001b[1;32m 438\u001b[0m proxies\u001b[39m=\u001b[39;49mproxies,\n\u001b[1;32m 439\u001b[0m resume_download\u001b[39m=\u001b[39;49mresume_download,\n\u001b[1;32m 440\u001b[0m token\u001b[39m=\u001b[39;49mtoken,\n\u001b[1;32m 441\u001b[0m local_files_only\u001b[39m=\u001b[39;49mlocal_files_only,\n\u001b[1;32m 442\u001b[0m )\n\u001b[1;32m 443\u001b[0m \u001b[39mexcept\u001b[39;00m GatedRepoError \u001b[39mas\u001b[39;00m e:\n\u001b[1;32m 444\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mEnvironmentError\u001b[39;00m(\n\u001b[1;32m 445\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mYou are trying to access a gated repo.\u001b[39m\u001b[39m\\n\u001b[39;00m\u001b[39mMake sure to request access at \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 446\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mhttps://huggingface.co/\u001b[39m\u001b[39m{\u001b[39;00mpath_or_repo_id\u001b[39m}\u001b[39;00m\u001b[39m and pass a token having permission to this repo either \u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 447\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mby logging in with `huggingface-cli login` or by passing `token=`.\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 448\u001b[0m ) \u001b[39mfrom\u001b[39;00m \u001b[39me\u001b[39;00m\n",
- "File \u001b[0;32m~/local/micromamba/envs/safe/lib/python3.11/site-packages/huggingface_hub/utils/_validators.py:110\u001b[0m, in \u001b[0;36mvalidate_hf_hub_args.._inner_fn\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[39mfor\u001b[39;00m arg_name, arg_value \u001b[39min\u001b[39;00m chain(\n\u001b[1;32m 106\u001b[0m \u001b[39mzip\u001b[39m(signature\u001b[39m.\u001b[39mparameters, args), \u001b[39m# Args values\u001b[39;00m\n\u001b[1;32m 107\u001b[0m kwargs\u001b[39m.\u001b[39mitems(), \u001b[39m# Kwargs values\u001b[39;00m\n\u001b[1;32m 108\u001b[0m ):\n\u001b[1;32m 109\u001b[0m \u001b[39mif\u001b[39;00m arg_name \u001b[39min\u001b[39;00m [\u001b[39m\"\u001b[39m\u001b[39mrepo_id\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mfrom_id\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39m\"\u001b[39m\u001b[39mto_id\u001b[39m\u001b[39m\"\u001b[39m]:\n\u001b[0;32m--> 110\u001b[0m validate_repo_id(arg_value)\n\u001b[1;32m 112\u001b[0m \u001b[39melif\u001b[39;00m arg_name \u001b[39m==\u001b[39m \u001b[39m\"\u001b[39m\u001b[39mtoken\u001b[39m\u001b[39m\"\u001b[39m \u001b[39mand\u001b[39;00m arg_value \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 113\u001b[0m has_token \u001b[39m=\u001b[39m \u001b[39mTrue\u001b[39;00m\n",
- "File \u001b[0;32m~/local/micromamba/envs/safe/lib/python3.11/site-packages/huggingface_hub/utils/_validators.py:158\u001b[0m, in \u001b[0;36mvalidate_repo_id\u001b[0;34m(repo_id)\u001b[0m\n\u001b[1;32m 155\u001b[0m \u001b[39mraise\u001b[39;00m HFValidationError(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mRepo id must be a string, not \u001b[39m\u001b[39m{\u001b[39;00m\u001b[39mtype\u001b[39m(repo_id)\u001b[39m}\u001b[39;00m\u001b[39m: \u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00mrepo_id\u001b[39m}\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m 157\u001b[0m \u001b[39mif\u001b[39;00m repo_id\u001b[39m.\u001b[39mcount(\u001b[39m\"\u001b[39m\u001b[39m/\u001b[39m\u001b[39m\"\u001b[39m) \u001b[39m>\u001b[39m \u001b[39m1\u001b[39m:\n\u001b[0;32m--> 158\u001b[0m \u001b[39mraise\u001b[39;00m HFValidationError(\n\u001b[1;32m 159\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mRepo id must be in the form \u001b[39m\u001b[39m'\u001b[39m\u001b[39mrepo_name\u001b[39m\u001b[39m'\u001b[39m\u001b[39m or \u001b[39m\u001b[39m'\u001b[39m\u001b[39mnamespace/repo_name\u001b[39m\u001b[39m'\u001b[39m\u001b[39m:\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 160\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m \u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00mrepo_id\u001b[39m}\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m. Use `repo_type` argument if needed.\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 161\u001b[0m )\n\u001b[1;32m 163\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m REPO_ID_REGEX\u001b[39m.\u001b[39mmatch(repo_id):\n\u001b[1;32m 164\u001b[0m \u001b[39mraise\u001b[39;00m HFValidationError(\n\u001b[1;32m 165\u001b[0m \u001b[39m\"\u001b[39m\u001b[39mRepo id must use alphanumeric chars or \u001b[39m\u001b[39m'\u001b[39m\u001b[39m-\u001b[39m\u001b[39m'\u001b[39m\u001b[39m, \u001b[39m\u001b[39m'\u001b[39m\u001b[39m_\u001b[39m\u001b[39m'\u001b[39m\u001b[39m, \u001b[39m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m'\u001b[39m\u001b[39m, \u001b[39m\u001b[39m'\u001b[39m\u001b[39m--\u001b[39m\u001b[39m'\u001b[39m\u001b[39m and \u001b[39m\u001b[39m'\u001b[39m\u001b[39m..\u001b[39m\u001b[39m'\u001b[39m\u001b[39m are\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 166\u001b[0m \u001b[39m\"\u001b[39m\u001b[39m forbidden, \u001b[39m\u001b[39m'\u001b[39m\u001b[39m-\u001b[39m\u001b[39m'\u001b[39m\u001b[39m and \u001b[39m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m'\u001b[39m\u001b[39m cannot start or end the name, max length is 96:\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 167\u001b[0m \u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m \u001b[39m\u001b[39m'\u001b[39m\u001b[39m{\u001b[39;00mrepo_id\u001b[39m}\u001b[39;00m\u001b[39m'\u001b[39m\u001b[39m.\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 168\u001b[0m )\n",
- "\u001b[0;31mHFValidationError\u001b[0m: Repo id must be in the form 'repo_name' or 'namespace/repo_name': '/home/hadim/.cache/safe/default_model'. Use `repo_type` argument if needed."
- ]
- }
- ],
"source": [
- "# designer = sf.SAFEDesign.load_default(verbose=True)\n"
+ "Load the default pretrained Safe model.\n",
+ "\n",
+ "We will use this unique model for all the downstream molecular design tasks.\n"
]
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 3,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "SAFEDoubleHeadsModel(\n",
+ " (transformer): GPT2Model(\n",
+ " (wte): Embedding(1880, 768)\n",
+ " (wpe): Embedding(1024, 768)\n",
+ " (drop): Dropout(p=0.1, inplace=False)\n",
+ " (h): ModuleList(\n",
+ " (0-11): 12 x GPT2Block(\n",
+ " (ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True)\n",
+ " (attn): GPT2Attention(\n",
+ " (c_attn): Conv1D()\n",
+ " (c_proj): Conv1D()\n",
+ " (attn_dropout): Dropout(p=0.1, inplace=False)\n",
+ " (resid_dropout): Dropout(p=0.1, inplace=False)\n",
+ " )\n",
+ " (ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True)\n",
+ " (mlp): GPT2MLP(\n",
+ " (c_fc): Conv1D()\n",
+ " (c_proj): Conv1D()\n",
+ " (act): NewGELUActivation()\n",
+ " (dropout): Dropout(p=0.1, inplace=False)\n",
+ " )\n",
+ " )\n",
+ " )\n",
+ " (ln_f): LayerNorm((768,), eps=1e-05, elementwise_affine=True)\n",
+ " )\n",
+ " (lm_head): Linear(in_features=768, out_features=1880, bias=False)\n",
+ " (multiple_choice_head): PropertyHead(\n",
+ " (summary): Linear(in_features=768, out_features=64, bias=True)\n",
+ " (activation): ReLU()\n",
+ " (out): Linear(in_features=64, out_features=1, bias=True)\n",
+ " )\n",
+ ")"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# candidate_mol = \"O=C(C#CCN1CCCCC1)Nc1ccc2ncnc(Nc3cccc(Br)c3)c2c1\"\n",
+ "designer = sf.SAFEDesign.load_default(verbose=True)\n",
"\n",
- "# scaffold = \"[*]N-c1ccc2ncnc(-N[*])c2c1\" # this is for scaffold decoration\n",
- "# superstructure = \"c1ccc2ncncc2c1\"\n",
- "# side_chains = '[1*]C(=O)C#CCN1CCCCC1.[2*]c1cccc(Br)c1' # this is for scaffold morphing\n",
- "# motif = \"[*]-N1CCCCC1\" # this is for motif extension\n",
- "# linker_generation = [\"[*]-N1CCCCC1\", \"Brc1cccc(Nc2ncnc3ccc(-[*])cc23)c1\"] # this is for linker generation\n"
+ "designer.model\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
- "We start with the image shown in the README of the SAFE GitHub Repository to assess the performance on the various tasks SAFE should in theory be good at. "
+ "Let's start with the below molecule.\n"
]
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -85,115 +110,131 @@
""
],
"text/plain": [
""
]
},
- "execution_count": 31,
+ "execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "# dm.to_image(dm.to_mol(candidate_mol))\n"
+ "candidate_smiles = \"O=C(C#CCN1CCCCC1)Nc1ccc2ncnc(Nc3cccc(Br)c3)c2c1\"\n",
+ "candidate_mol = dm.to_mol(candidate_smiles)\n",
+ "\n",
+ "dm.to_image(candidate_mol)\n"
]
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
- "# N_SAMPLES = 100\n"
+ "\n",
+ "\n",
+ "\n",
+ "# # this is for substructure\n",
+ "#\n",
+ "\n",
+ "# # this is for scaffold morphing\n",
+ "#\n",
+ "\n",
+ "# # this is for motif extension\n",
+ "# motif = \"[*]-N1CCCCC1\"\n",
+ "\n",
+ "# # this is for linker generation\n",
+ "#\n"
]
},
{
@@ -202,1438 +243,995 @@
"source": [
"## De novo generation\n",
"\n",
- "Generation of novel molecules without any constraints."
+ "Generation of novel molecules without any constraints.\n"
]
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 6,
"metadata": {},
"outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "32fd666ff8c047f5b5b52b2511add797",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ " 0%| | 0/1 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
{
"name": "stderr",
"output_type": "stream",
"text": [
- "\u001b[32m2023-08-29 16:58:21.338\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36msafe.sample\u001b[0m:\u001b[36mde_novo_generation\u001b[0m:\u001b[36m559\u001b[0m - \u001b[1mAfter sanitization, 83 / 100 (83.00 %) generated molecules are valid !\u001b[0m\n"
+ "/home/hadim/local/micromamba/envs/safe/lib/python3.11/site-packages/transformers/generation/configuration_utils.py:399: UserWarning: `num_beams` is set to 1. However, `early_stopping` is set to `True` -- this flag is only used in beam-based generation modes. You should set `num_beams>1` or unset `early_stopping`.\n",
+ " warnings.warn(\n",
+ "\u001b[32m2023-10-28 11:37:25.393\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36msafe.sample\u001b[0m:\u001b[36mde_novo_generation\u001b[0m:\u001b[36m581\u001b[0m - \u001b[1mAfter sanitization, 82 / 100 (82.00 %) generated molecules are valid !\u001b[0m\n"
]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "['CCCCOc1c(Br)cc(C)cc1-c1nc(C2(CC)CCN(C(C)C)CC2)cn2nc(C)nc12',\n",
+ " 'CC(C)(C)OC(=O)Nc1ccc(C[NH+]2CC[C@@H]3OCCC[C@H]3C2)cn1',\n",
+ " 'Cc1ccc(Br)c(NCCC(C)C(C)C)c1',\n",
+ " 'CCOC(=O)C1=C(C)N=c2s/c(=C/c3c(C)[nH]c4ccccc34)c(=O)n2[C@@H]1c1ccc(OC)cc1',\n",
+ " 'CCc1ccccc1-n1cc(O)c(C(=O)Nc2ccc(Cl)c(F)c2)n1']"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "# generated = designer.de_novo_generation(sanitize=True, n_samples_per_trial=N_SAMPLES)\n"
+ "generated_smiles = designer.de_novo_generation(sanitize=True, n_samples_per_trial=12)\n",
+ "\n",
+ "generated_smiles[:5]\n"
]
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
- "