Tools · Custom Modeling
MPNN Models
On this page
Prices, workflows, and method papersOpen in the app
Run it from the API
Submit with Submit a job and the job_type below. Price it first with Estimate job reservation cost: submitting reserves that amount from your wallet, and the charge settles at the actual runtime.
Saved Model Scoring model-score
- Job type
model-score- Hardware
cpu(default)- Typical runtime
- 5 min on CPU
Payload
Provide at least one of: input_data + input_format, input_table, id_column, vina_poses, gnina_poses, surfdock_poses, diffdock_poses, boltz2_complexes, mm_gbsa_scores, plip_interactions.
| Field | Type | Description |
|---|---|---|
model_idrequired | string | Saved model id (user_models.id). Must be one of your ready models or a public model. Limits: |
score_target | string | Target to score, by name, instead of the model's primary (first) target (#976). The job errors if the model has no such target. Limits: |
score_class | string | integer | For a multiclass target: the class whose probability is the score (#976). Required for a multiclass model; refused for other models. |
input_data[] | (string | artifactRef)[] | Molecules to score: strings in input_format, or closed $artifact refs. Limits: |
input_format | string | Format of every input_data entry; reaction_smiles (atom-mapped reactions) for a reaction model (reaction_mpnn). One of: |
input_table | string | object[] | artifactRef | Table to score instead of input_data: CSV/JSON rows or a closed $artifact ref. Other columns are kept in predictions.csv. |
smiles_column | string | input_table column with SMILES. Default: |
reaction_column | string | input_table column with atom-mapped reaction SMILES, for a reaction model (reaction_mpnn) instead of smiles_column; e.g. reaction-map's mapped_reaction. Limits: |
component_columns | map<string, string> | Reaction models only: the model's condition component name (e.g. ligand) to the input_table column holding its SMILES. A component not listed here or in component_values is read from a column of the same name. |
component_values | map<string, string> | Reaction models only: one condition SMILES per component name used for every reaction ('' for none), e.g. fixed conditions for an enumerated library. |
threshold | object | Molecules whose prediction meets this predicate are written to passers.smi. |
threshold.oprequired | string | One of: |
threshold.valuerequired | number | |
explain | boolean | Add each molecule's signed attributions (MPNN and QSAR models): attribution_base, attribution_scale, top_groups and top_atoms columns in predictions.csv, and groups.csv with every fragment, ring system and functional group value. At most 1000 molecules. Default: |
vina_poses | file_object[] | file_object | Rescorer models: AutoDock Vina poses to score (vina affinity). |
gnina_poses | file_object[] | file_object | Rescorer models: GNINA poses (GNINA affinity and CNN score). |
surfdock_poses | file_object[] | file_object | Rescorer models: SurfDock poses (SurfDock affinity). |
diffdock_poses | file_object[] | file_object | Rescorer models: DiffDock poses (confidence). |
boltz2_complexes | file_object[] | file_object | Rescorer models: Boltz-2 co-folded complexes (affinity and confidence). |
mm_gbsa_scores | file_object[] | file_object | Rescorer models: MM-GBSA scores tables. |
plip_interactions | file_object[] | file_object | Rescorer models: PLIP interaction tables. |
id_column | string | Rescorer models: ligand id column of input_table, matching upstream record ids; marks the payload as rescorer input. Default: |
File fields take {"name": "x.pdb", "content_b64": "…"} or a stored artifact, {"$artifact": {"id": "art-…", "port": "…"}}. Files are up to 25 MiB each.
Example
from cognichem_client import CogniChem
client = CogniChem.from_env() # reads COGNICHEM_API_KEY
payload = {
"model_id": "mdl-01JABCDEFGHJKMNPQRSTVWXYZ0",
"input_data": ["CCO", "c1ccccc1"],
"input_format": "smiles",
"threshold": {"op": "gte", "value": 1},
}
estimate = client.jobs.estimate(job_type="model-score", payload=payload, resource="cpu")
print(f"Reserves ${estimate.cost:.2f}")
job = client.jobs.submit(
job_name="my-model-score-run",
job_type="model-score",
payload=payload,
resource="cpu",
)
status = client.jobs.wait(job.process_id)
if status.status == "completed":
client.jobs.result(job.process_id, save_path=".")curl -X POST "https://api.cognichem.com/api/v1/jobs/submit" \
-H "X-Api-Key: $COGNICHEM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"job_name": "my-model-score-run",
"job_type": "model-score",
"payload": {
"model_id": "mdl-01JABCDEFGHJKMNPQRSTVWXYZ0",
"input_data": [
"CCO",
"c1ccccc1"
],
"input_format": "smiles",
"threshold": {
"op": "gte",
"value": 1
}
},
"resource": "cpu"
}'{
"model_id": "mdl-01JABCDEFGHJKMNPQRSTVWXYZ0",
"input_data": [
"CCO",
"c1ccccc1"
],
"input_format": "smiles",
"threshold": {
"op": "gte",
"value": 1
}
}Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.
Workflow inputs
- Structures (list) · optionalCIF, PDB
- Docked poses (list) · optionalSDF
- Docked poses (list) · optionalSDF
- Table (list) · optionalCSV
- Trained model · optionalOPAQUE
- Molecules (list) · optionalSMILES, INCHI, MOLBLOCK
- Table (list) · optionalCSV
- Docked poses (list) · optionalSDF
- Table (list) · optionalCSV, TSV, JSON
- Docked poses (list) · optionalPDBQT, SDF
Workflow outputs
- ArchiveZIP
- MoleculesSMILES
- TableCSV
- MoleculesSMILES
MPNN Model Training train-mpnn
- Job type
train-mpnn- Hardware
cpu(default)t4l4a10- Typical runtime
- 1 h on CPU
Payload
| Field | Type | Description |
|---|---|---|
model_namerequired | string | Limits: |
input_data[] | string[] | Limits: |
input_format | string | Limits: |
task | string | regression predicts values; binary predicts P(class 1) from 0/1 targets (or values labelled with binary_threshold); multiclass predicts one of 3-10 class labels (#908). Default: |
binary_threshold | number | task binary only: label continuous targets, value >= threshold is class 1. With a censored activity table, a censored bound that is certainly on one side of the threshold is kept even under censored_policy drop. |
targets[] | (number | string | (number | null)[])[] | One value per input_data entry: a number (regression, binary), a class label (multiclass), or a row with one value per target for a multi-target regression or binary model (null where a value is missing). Limits: |
target_names[] | string[] | Names of the targets of a multi-target model, one per targets column (default target_1, target_2, ...). Limits: |
target_units[] | string[] | Units of the targets of a multi-target regression model, one per targets column. Limits: |
splits[] | string[] | Fold label per input_data entry for model_params.split_method 'provided' (#908); 'calibration' rows calibrate the prediction intervals and applicability domain (#975). One of: |
dates[] | (string | integer | number)[] | Measurement date per input_data entry (a year YYYY or a date YYYY-MM-DD) for model_params.split_method 'time' (the default when dates are sent): the oldest molecules train, the newest are the test set (#974). Limits: |
activity_table | string | object[] | artifactRef | Training table instead of input_data + targets: CSV/JSON rows or a closed $artifact ref (#921 B3.1). |
smiles_column | string | activity_table column with SMILES. Default: |
target_column | string | activity_table column with the training target (p_activity is -log10 M). Default: |
target_columns[] | string[] | activity_table columns to learn together (a multi-target model) instead of target_column; empty cells are missing values. Expanded into targets rows and target_names. Limits: |
split_column | string | activity_table column with train / val / test (or calibration) labels; expanded into splits for split_method 'provided' (#908). Limits: |
date_column | string | activity_table column with a year or date per row (e.g. ChEMBL document_year); expanded into dates for split_method 'time', the default when it is set (#974). Limits: |
endpoint | string | Train on rows of this endpoint only (e.g. IC50); required when the table mixes endpoints. Limits: |
censored_policy | string | Rows of an activity table whose censored column is true (relation > or <): drop removes them, as_threshold trains on the bound as if it were exact (named like bioactivity-curate's censored_policy). Default: |
include_censored | boolean | Deprecated: use censored_policy. true is as_threshold, false is drop. Deprecated |
training_data_sources[] | object[] | Set by CogniChem when the activity table carries ChEMBL identifiers (CC BY-SA 3.0), so the model card names ChEMBL as a training-data source. Do not send. Limits: |
training_data_sources.sourcerequired | "chembl" | |
training_data_sources.release | string | null | |
unit | string | Unit of a single regression target (e.g. kcal/mol); returned with every prediction from the trained model. Multi-target models use target_units. |
model_description | string | Free-text description stored with the trained model. |
tags[] | string[] | Labels stored with the trained model. |
model_params | object | Optional architecture and training settings: mp_hidden_dim, mp_depth, n_ffn_layers, ffn_hidden_dim, n_epochs, batch_size, validation_size, test_size, calibration_size, split_method, random_seed, ensemble_size, uncertainty_head, cv_folds, y_randomization, featureset, generate_3d, add_hydrogens, remove_hydrogens and learning_rate. split_method (default random, provided when splits are sent, or time when dates are sent) is random, scaffold (Bemis-Murcko groups), cluster (Butina on Morgan fingerprints at Tanimoto 0.4), provided or time (needs dates or date_column: oldest molecules train, newest test); scaffold and cluster keep related molecules on one side of the split. validation_size (default 0.1) picks the saved checkpoint; test_size (default 0.1; 0 skips the test set) is held out and scored against mean and kNN-Tanimoto baselines in the model card. learning_rate (default 0.001) is the peak of Chemprop's learning-rate schedule: it ramps linearly from learning_rate/10 to learning_rate over the first 5 epochs, then decays exponentially back to learning_rate/10 by the last epoch. Predictions with the trained model reuse its featureset and hydrogen settings. ensemble_size (default 1, up to 10) trains that many members on the same split and serves their mean, with the members' spread as uncertainty; it multiplies training cost. uncertainty_head (regression only; default none) is mve (mean-variance estimation) or evidential (deep evidential regression): each model also predicts a variance per molecule, so a single model gives per-molecule uncertainty at no extra training cost; with an ensemble the members' variances and their spread are combined. cv_folds (default 0, off; or 3 to 10) adds k-fold cross-validation on the non-test molecules for random, scaffold and cluster splits: one model per fold, scored on its held-out part, reported as mean and standard deviation in the model card; the served model is unchanged. y_randomization (default 0, off; up to 10) trains that many single models on shuffled training targets and reports how far a single model trained on the real targets (the first ensemble member) beats them. Each fold and each repeat is one more training run and adds to the cost. Regression models always get 90% split-conformal prediction intervals, wider where the model is less certain when it has an ensemble or an uncertainty_head. They and the applicability-domain threshold are calibrated on the validation fold, which also picks each checkpoint, or, with calibration_size (default 0, off; e.g. 0.1), on a separate calibration fold cut from the training data with the same split_method (in a time split, the period between validation and test). Every prediction reports its max Tanimoto similarity to the training set and whether it is in the applicability domain. A model whose estimated size exceeds the 1 GiB saved-model limit is rejected. |
Example
from cognichem_client import CogniChem
client = CogniChem.from_env() # reads COGNICHEM_API_KEY
payload = {
"model_name": "mr38-tiny",
"input_data": ["CCO", "CCC", "CCN", "c1ccccc1", "CC", "… 3 more"],
"input_format": "smiles",
"targets": [1, 2, 1.5, 0.5, 1.1, "… 3 more"],
"model_params": {
"validation_size": 0.25,
"mp_hidden_dim": 32,
"mp_depth": 1,
"n_ffn_layers": 1,
"ffn_hidden_dim": 32,
"learning_rate": 0.001,
"n_epochs": 6,
"batch_size": 2,
},
}
estimate = client.jobs.estimate(job_type="train-mpnn", payload=payload, resource="cpu")
print(f"Reserves ${estimate.cost:.2f}")
job = client.jobs.submit(
job_name="my-train-mpnn-run",
job_type="train-mpnn",
payload=payload,
resource="cpu",
)
status = client.jobs.wait(job.process_id)
if status.status == "completed":
client.jobs.result(job.process_id, save_path=".")curl -X POST "https://api.cognichem.com/api/v1/jobs/submit" \
-H "X-Api-Key: $COGNICHEM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"job_name": "my-train-mpnn-run",
"job_type": "train-mpnn",
"payload": {
"model_name": "mr38-tiny",
"input_data": [
"CCO",
"CCC",
"CCN",
"c1ccccc1",
"CC",
"… 3 more"
],
"input_format": "smiles",
"targets": [
1,
2,
1.5,
0.5,
1.1,
"… 3 more"
],
"model_params": {
"validation_size": 0.25,
"mp_hidden_dim": 32,
"mp_depth": 1,
"n_ffn_layers": 1,
"ffn_hidden_dim": 32,
"learning_rate": 0.001,
"n_epochs": 6,
"batch_size": 2
}
},
"resource": "cpu"
}'{
"model_name": "mr38-tiny",
"input_data": [
"CCO",
"CCC",
"CCN",
"c1ccccc1",
"CC",
"… 3 more"
],
"input_format": "smiles",
"targets": [
1,
2,
1.5,
0.5,
1.1,
"… 3 more"
],
"model_params": {
"validation_size": 0.25,
"mp_hidden_dim": 32,
"mp_depth": 1,
"n_ffn_layers": 1,
"ffn_hidden_dim": 32,
"learning_rate": 0.001,
"n_epochs": 6,
"batch_size": 2
}
}Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.
Workflow inputs
- Table (list) · optionalCSV, TSV, JSON
- Molecules (list) · optionalSMILES
Workflow outputs
- ArchiveZIP
- Trained modelOPAQUE