From dc75fb5e55d6296a47e0d122bfed1891c5f545b8 Mon Sep 17 00:00:00 2001 From: RaulFD-creator Date: Thu, 11 Sep 2025 13:42:09 +0100 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=AA=B2=20Simplify=20HPO=20XGBoost?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autopeptideml/data/h_param_search/xgboost_class.yml | 7 ------- autopeptideml/data/h_param_search/xgboost_reg.yml | 7 ------- 2 files changed, 14 deletions(-) diff --git a/autopeptideml/data/h_param_search/xgboost_class.yml b/autopeptideml/data/h_param_search/xgboost_class.yml index 6ca7e98..062f172 100644 --- a/autopeptideml/data/h_param_search/xgboost_class.yml +++ b/autopeptideml/data/h_param_search/xgboost_class.yml @@ -81,13 +81,6 @@ tree_method: - approx - hist -booster: - type: categorical - values: - - gbtree - - dart - - gblinear - grow_policy: type: categorical values: diff --git a/autopeptideml/data/h_param_search/xgboost_reg.yml b/autopeptideml/data/h_param_search/xgboost_reg.yml index cbbb209..5a54eab 100644 --- a/autopeptideml/data/h_param_search/xgboost_reg.yml +++ b/autopeptideml/data/h_param_search/xgboost_reg.yml @@ -81,13 +81,6 @@ tree_method: - approx - hist -booster: - type: categorical - values: - - gbtree - - dart - - gblinear - grow_policy: type: categorical values: From 19b664e316c902bbfc93539c6753d53e148c659e Mon Sep 17 00:00:00 2001 From: RaulFD-creator Date: Thu, 2 Oct 2025 15:57:35 +0100 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20Add=20ChemBERTa-3?= =?UTF-8?q?=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autopeptideml/reps/__init__.py | 2 +- autopeptideml/reps/lms.py | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/autopeptideml/reps/__init__.py b/autopeptideml/reps/__init__.py index df8c589..acc5f8c 100644 --- a/autopeptideml/reps/__init__.py +++ b/autopeptideml/reps/__init__.py @@ -5,5 +5,5 @@ 'esm2-15b', 'esm2-3b', 'esm2-650m', 'esm1b', 'esm2-150m', 'esm2-35m', 'esm2-8m', 'esmc-600m', 'esmc-300m', 'ankh-base', 'ankh-large'] -CLMs = ['molformer-xl', 'chemberta-2', 'peptideclm'] +CLMs = ['molformer-xl', 'chemberta-2', 'chemberta-3', 'peptideclm'] FPs = ['ecfp', 'morgan', 'fcfp', 'pepfunn'] diff --git a/autopeptideml/reps/lms.py b/autopeptideml/reps/lms.py index c61ca42..aa60054 100644 --- a/autopeptideml/reps/lms.py +++ b/autopeptideml/reps/lms.py @@ -32,6 +32,7 @@ 'ankh-large': 1536, 'MoLFormer-XL-both-10pct': 768, 'ChemBERTa-77M-MLM': 384, + 'ChemBERTa-100M-MLM': 768, 'PeptideCLM-23M-all': 768 } @@ -53,8 +54,8 @@ 'ankh-large': 'ankh-large', 'molformer-xl': 'MoLFormer-XL-both-10pct', 'chemberta-2': 'ChemBERTa-77M-MLM', + 'chemberta-3': 'ChemBERTa-100M-MLM', 'peptideclm': 'PeptideCLM-23M-all' - } @@ -149,17 +150,22 @@ def max_len(self) -> int: return 1022 elif self.lab.lower() == 'evolutionaryscale': return 2046 + elif self.lab.lower() == 'deepchem': + return 512 else: return 2046 - def get_num_params(self) -> int: + def get_num_params(self, human_readable: bool = False) -> int: """ Returns the total number of parameters in the model. :rtype: int :return: The number of parameters in the model. """ - return sum(p.numel() for p in self.model.parameters()) + if not human_readable: + return sum(p.numel() for p in self.model.parameters()) + else: + return f"{sum(p.numel() for p in self.model.parameters())/1e6:,.3f}M" def _load_model(self, model: str): """ @@ -239,7 +245,7 @@ def _load_model(self, model: str): self.tokenizer = self.model.tokenizer else: self.tokenizer = AutoTokenizer.from_pretrained( - f'{self.lab}/{model}', trust_remote_code=True + f'{self.lab}/{model}', trust_remote_code=True, ) self.dimension = AVAILABLE_MODELS[model] @@ -277,6 +283,8 @@ def _rep_batch( :rtype: List[np.ndarray] :return: A list of numpy arrays representing the embeddings of each input sequence. """ + batch = [b if len(b) <= self.max_len() else b[:self.max_len()] + for b in batch] inputs = self.tokenizer(batch, add_special_tokens=True, truncation=True, padding="longest", return_tensors="pt") From ab2e341efeedfedd5c1b0fe038884ccc86f388f7 Mon Sep 17 00:00:00 2001 From: RaulFD-creator Date: Tue, 4 Nov 2025 08:46:36 +0000 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=AA=B2=20Minor=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autopeptideml/apml.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/autopeptideml/apml.py b/autopeptideml/apml.py index 7b471b9..b8f85c7 100644 --- a/autopeptideml/apml.py +++ b/autopeptideml/apml.py @@ -148,7 +148,7 @@ def sample_negatives( else: path = target_db if not self.preprocessed: - self._preprocessing_data(n_jobs=n_jobs) + self._preprocessing_data(n_jobs=n_jobs, verbose=verbose) self.metadata['status'] = 'sampling-negatives' self.metadata['negative-sampling-metadata'] = { @@ -245,6 +245,10 @@ def build_models( if task not in ['class', 'reg']: raise ValueError(f"Task: {task} is not valid.", "Choose one: `class, reg`") + if task == 'class': + from .utils.dataset_parsing import _is_string_series + if _is_string_series(self.df[self.label_field]): + raise ValueError("The target column contains textual values, please substitute for '1' for the positive class and '0' for the negative.") if split_strategy == 'good': raise NotImplementedError( @@ -283,6 +287,7 @@ def build_models( random_state=random_state, n_jobs=n_jobs, n_trials=n_trials, + verbose=verbose, model_configs=model_configs ) self._evaluating( @@ -309,19 +314,13 @@ def represent( ): repengine = self.repengines[rep] if rep in PLMs or rep == 'one-hot': - if 'apml-seqs' in self.df: - seqs = self.df['apml-seqs'] - else: - seqs = self._use_pipeline(mols, 'to-sequences', n_jobs=n_jobs, - verbose=verbose) + seqs = self._use_pipeline(mols, 'to-sequences', n_jobs=n_jobs, + verbose=verbose) x = {rep: repengine.compute_reps(seqs, verbose=verbose, batch_size=32)} else: - if 'apml-smiles' in self.df: - mols = self.df['apml-smiles'] - else: - mols = self._use_pipeline(mols, 'to-smiles', n_jobs=n_jobs, - verbose=verbose) + mols = self._use_pipeline(mols, 'to-smiles', n_jobs=n_jobs, + verbose=verbose) x = {rep: repengine.compute_reps(mols, verbose=verbose, batch_size=32)} return x @@ -336,6 +335,7 @@ def _hpo( n_folds: int, n_jobs: int, n_trials: int, + verbose: bool, random_state: int ): if task == 'class': @@ -372,6 +372,7 @@ def _hpo( n_trials=n_trials, patience=n_trials//5, custom_hpspace=model_configs, + verbose=2 if verbose else 0, random_state=random_state, n_jobs=n_jobs, db_file=osp.join(self.meta_dir, 'database.sql'), From 8b7b3e9ea30d763b0a4ff7eae4e1bfd269be6d2d Mon Sep 17 00:00:00 2001 From: RaulFD-creator Date: Tue, 4 Nov 2025 08:47:34 +0000 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20New=20utility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- autopeptideml/utils/dataset_parsing.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/autopeptideml/utils/dataset_parsing.py b/autopeptideml/utils/dataset_parsing.py index 43cf29e..121e0ea 100644 --- a/autopeptideml/utils/dataset_parsing.py +++ b/autopeptideml/utils/dataset_parsing.py @@ -52,3 +52,14 @@ def _read_csv(path: str) -> pd.DataFrame: return pd.read_csv(path, sep=',') elif path.endswith(".tsv"): return pd.read_csv(path, sep='\t') + + +def _is_string_series(s: pd.Series): + if isinstance(s.dtype, pd.StringDtype): + # The series was explicitly created as a string series (Pandas>=1.0.0) + return True + elif s.dtype == 'object': + # Object series, check each value + return all((v is None) or isinstance(v, str) for v in s) + else: + return False From db925a2822b2e0ebe35babd551c74418692cded3 Mon Sep 17 00:00:00 2001 From: RaulFD-creator Date: Tue, 4 Nov 2025 08:47:44 +0000 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=A7=B9=20Minor=20improvement=20notebo?= =?UTF-8?q?ok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/AutoPeptideML2.ipynb | 320 +++++++++++++++++++++++++++++++--- 1 file changed, 299 insertions(+), 21 deletions(-) diff --git a/examples/AutoPeptideML2.ipynb b/examples/AutoPeptideML2.ipynb index 93d5cbb..739e5ce 100644 --- a/examples/AutoPeptideML2.ipynb +++ b/examples/AutoPeptideML2.ipynb @@ -84,10 +84,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "d0bf31ce", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "to-smiles\n", + "-> to-smiles-1\n", + "-> -> to-smiles-1a\n", + "-> -> -> filter-smiles -> keep_smiles: False\n", + "-> -> -> canonical-cleaner -> substitution: G\n", + "-> -> -> sequence-to-smiles\n", + "-> -> \n", + "-> -> to-smiles-1b\n", + "-> -> -> filter-smiles -> keep_smiles: True\n", + "-> -> \n", + "-> aggregate\n", + "-> canonicalize-smiles\n", + "\n" + ] + } + ], "source": [ "from autopeptideml.pipeline import get_pipeline\n", "\n", @@ -97,10 +117,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "304c57fd", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "to-sequences\n", + "-> to-sequences-1\n", + "-> -> to-sequences-1a\n", + "-> -> -> filter-smiles -> keep_smiles: False\n", + "-> -> \n", + "-> -> to-sequences-1b\n", + "-> -> -> filter-smiles -> keep_smiles: True\n", + "-> -> -> smiles-to-sequence\n", + "-> -> \n", + "-> aggregate\n", + "-> canonical-cleaner -> substitution: X\n", + "\n" + ] + } + ], "source": [ "to_sequences = get_pipeline('to-sequences')\n", "print(to_sequences)" @@ -123,7 +162,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "1bec09c5", "metadata": {}, "outputs": [], @@ -132,10 +171,10 @@ "from autopeptideml import AutoPeptideML\n", "\n", "# # Option 1 - Natural peptides\n", - "# df = pd.read_csv('c-antiviral.csv')\n", - "# df = df[df['labels'] == 1].sample(500, random_state=1)\n", - "# db = 'canonical'\n", - "# all_inputs = df['sequence'].tolist()\n", + "df = pd.read_csv('c-antiviral.csv')\n", + "df = df[df['labels'] == 1].sample(500, random_state=1)\n", + "db = 'canonical'\n", + "all_inputs = df['sequence'].tolist()\n", "\n", "# # Option 2 - Modified peptides\n", "# df2 = pd.read_csv('nc-antiviral.csv')\n", @@ -168,10 +207,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "a68c3722", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "label\n", + "1 500\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Check distribution of labels\n", "apml.df.label.value_counts()" @@ -189,10 +241,131 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "774c33f5", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 1 of 2: to-smiles-1\n", + "Executing preprocessing step 1 of 2: to-smiles-1a\n", + "Executing preprocessing step 1 of 3: filter-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 653kit/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 2 of 3: canonical-cleaner\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 788kit/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 3 of 3: sequence-to-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "100%|██████████| 500/500 [00:04<00:00, 116it/s] \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 2 of 2: to-smiles-1b\n", + "Executing preprocessing step 1 of 1: filter-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 912kit/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 2 of 2: canonicalize-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 789kit/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 1 of 2: to-sequences-1\n", + "Executing preprocessing step 1 of 2: to-sequences-1a\n", + "Executing preprocessing step 1 of 1: filter-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 1.03Mit/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 2 of 2: to-sequences-1b\n", + "Executing preprocessing step 1 of 2: filter-smiles\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 1.01Mit/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing preprocessing step 2 of 2: smiles-to-sequence\n", + "Executing preprocessing step 2 of 2: canonical-cleaner\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 500/500 [00:00<00:00, 880kit/s]\n" + ] + } + ], "source": [ "# Sample negatives\n", "apml.sample_negatives(\n", @@ -214,10 +387,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "2652bcb2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "label\n", + "1 500\n", + "0 500\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Check distribution of labels after negative sampling\n", "import seaborn as sns\n", @@ -228,10 +425,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "f97647b2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "apml.df['apml-seqs'].isna().sum()" ] @@ -252,20 +460,90 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "5d4a5811", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known')': /simple/transformers/\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known')': /simple/transformers/\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known')': /simple/transformers/\u001b[0m\u001b[33m\n", + "\u001b[0m\u001b[33mWARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError(': Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known')': /simple/transformers/\u001b[0m\u001b[33m\n", + "\u001b[0m^C\n" + ] + } + ], "source": [ "!pip install transformers --no-cache-dir --quiet -U" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "ea75d0c0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Partitioning...\n", + "Computing ecfp representations...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 8/8 [00:01<00:00, 7.33it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Computing chemberta-2 representations...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 8/8 [00:05<00:00, 1.37it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Computing esm2-8m representations...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 8/8 [00:02<00:00, 3.97it/s]\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b87dc670f0a8473f98af13b74e8fd821", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/50 [00:00 Date: Tue, 4 Nov 2025 08:53:31 +0000 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=93=9D=20Update=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 +++++-------------------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 9b15914..29f7638 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ To use version 1.0, which may be necessary for retrocompatibility with previousl ## Model builder -In order to build a new model, AutoPeptideML (v.2.0), introduces a new utility to automatically prepare an experiment configuration file, to i) improve the reproducibility of the pipeline and ii) to keep a user-friendly interface despite the much increased flexibility. +In order to build a new model, AutoPeptideML (v.2.0) guides you through the process through a series of prompts. ```bash -autopeptideml prepare-config --config-path +autopeptideml build-model ``` This launches an interactive CLI that walks you through: @@ -72,7 +72,6 @@ This launches an interactive CLI that walks you through: - Picking models and representations - Automatically sampling negatives - You’ll be prompted to answer various questions like: ``` @@ -86,13 +85,13 @@ You’ll be prompted to answer various questions like: And so on. The final config is written to: ``` -.yml +/setup-config.yml ``` This config file allows for easy reproducibility of the results, so that anyone can repeat the training processes. You can check the configuration file and make any changes you deem necessary. Finally, you can build the model by simply running: ``` -autopeptideml build-model --outdir --config-path /config.yml +autopeptideml build-model --outdir --config-path /setup-config.yml ``` ## Prediction @@ -120,6 +119,7 @@ Installing in a conda environment is recommended. For creating the environment, ```bash conda create -n autopeptideml python conda activate autopeptideml +conda install quarto -c conda-forge ``` ### 1. Python Package @@ -190,45 +190,6 @@ To use PeptideCLM: pip install smilesPE ``` -## Documentation - -### Configuration file - - -```yaml -datasets: - main: - feat-fields: # Column with peptide sequence/SMILES - label-field: # Column with labels/ "Assume all entries are positives" - path: # Path to dataset - neg-db: - activities-to-exclude: # List of activities to exclude - - activity-1 - - activity-2 - ... - feat-fields: null # Column with peptide sequence/SMILES (only if using custom database) - path: # Path to custom database or choose: canonical, non-canonical, both -device: # Device for computing representations. Choose: cpu, mps, cuda -direction: # Direction of optimization. Choose: maximize or minimize -metric: # Metric for optimization. mse, mae require direction minimize -models: # List of machine learning algorithms to explore. List: - # knn, svm, rf, gradboost, xgboost, lightgbm - - model-1 - - model-2 - ... -n-trials: # Number of optimization steps. Recommended 100-200 -pipeline: to-smiles # Pipeline for preprocessing. Choose: to-smiles, to-sequences -reps: # List of peptide representations to explore. List: - # ecfp, chemberta-2, molformer-xl, peptide-clm, esm2-8m, ... - - rep-1 - - rep-2 - ... - -split-strategy: min # Strategy for splitting train/test. Choose: min, random. -task: class # Machine learning type of problem. Choose: class or reg. -n-jobs: # Number of processes to launch. -1 uses all possible CPU cores. -``` - ### More details about API Please check the [Code reference documentation](https://ibm.github.io/AutoPeptideML/autopeptideml/) From b802a01526b8a9ec9626a3e310798724a12dabb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fern=C3=A1ndez=20D=C3=ADaz?= <78709417+RaulFD-creator@users.noreply.github.com> Date: Tue, 2 Dec 2025 13:48:09 +0000 Subject: [PATCH 7/8] Change import to load_external_modules in mkdocs.yml --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 2286018..a88afb8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,7 +56,7 @@ plugins: - mkdocstrings: handlers: python: - import: + load_external_modules: - https://docs.python.org/3/objects.inv - https://installer.readthedocs.io/en/stable/objects.inv # demonstration purpose in the docs - https://mkdocstrings.github.io/autorefs/objects.inv From d398a2353c240aadfffe754ce62a1aaf7b6d0be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Fern=C3=A1ndez=20D=C3=ADaz?= <78709417+RaulFD-creator@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:11:29 +0000 Subject: [PATCH 8/8] Add workflow_dispatch trigger to publish-pages-doc.yml --- .github/workflows/publish-pages-doc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish-pages-doc.yml b/.github/workflows/publish-pages-doc.yml index 29dcb00..08d8c48 100644 --- a/.github/workflows/publish-pages-doc.yml +++ b/.github/workflows/publish-pages-doc.yml @@ -5,6 +5,8 @@ on: branches: - main - master + workflow_dispatch: + jobs: deploy: runs-on: ubuntu-latest