FlashPPI: A Practical Guide to Protein Interaction Screening
Screening every pair in a proteome becomes expensive quickly. With 4,000 proteins, there are 7,998,000 distinct unordered pairs before considering self-interactions. FlashPPI narrows that search: retrieve plausible partners using protein embeddings, then spend the more detailed contact-prediction work on the retrieved candidates.
This guide explains the method, checks the released inference code, and provides a small CSV checker. Sources were checked on October 8, 2026. The original study is Cornman and colleagues’ PNAS paper, published in 2026. The model inference recipe below was checked against source code; the GPU model and the paper’s benchmarks were not run for this article.
1. From protein sequences to candidate interactions
FlashPPI initializes its shared encoder from gLM2, a genomic language model. It learns protein-level retrieval representations alongside residue-level contact prediction, using contrastive learning and hard negatives. The paper focuses on microbial protein interactions. See the original study.
For practical use, separate these outputs:
| Output | Purpose | What it does not establish |
|---|---|---|
| Retrieval similarity | Choose candidate partners for detailed scoring | Experimental evidence of binding |
| Contact map | Estimate which residue pairs may contact | A solved three-dimensional complex |
contact_score |
Rank or filter a candidate using its strongest predicted contact | A calibrated probability of a real interaction |
In the released model, the contact score is the maximum predicted contact probability over valid residue pairs. The single-proteome script applies a sigmoid to the maximum valid contact logit, giving the same aggregation. A score near 1 therefore does not mean a 99% experimental confirmation rate.
This is a different task from OmegaTherm’s mutation-stability prediction: FlashPPI asks about potential protein partners and interfaces, rather than a mutation-induced change in ΔΔG or ΔTm.
2. Read the performance claims in context
Figure 2 of the paper reports AUPRC 0.29 for FlashPPI versus 0.07 for PLM-Interact on a held-out E. coli K12 benchmark with a 1:100 positive-to-negative ratio. The runtime comparison uses a single NVIDIA A100. These are the authors’ results, not measurements from this tutorial. See the paper and Figure 2.
Keep the benchmark’s organism, negative sampling, and prevalence in view. AUPRC is not accuracy, and a result on this benchmark does not establish equal performance for arbitrary eukaryotic proteins, antibody–antigen pairs, or a different experimental setting.
For your own assessment, measure whether retrieval keeps known partners as well as whether the final scores rank them well. A pair missed during retrieval never reaches the contact head. Use a held-out evaluation set and inspect precision at the number of candidates you can actually follow up.
3. What “linear-time” means in the released workflow
At fixed retrieval depth k, the expensive contact stage scores roughly N × k directed candidates instead of all protein pairs. That is the useful reduction. Sequence lengths and batching still affect the cost of each candidate.
There is an implementation detail worth making explicit: the checked single-proteome script uses FAISS IndexFlatIP. FAISS documents this as exhaustive inner-product search. Searching N queries against N stored vectors still performs quadratic vector comparisons for fixed embedding dimension. Thus the public script does not make every stage strictly linear; it reduces the much heavier contact-inference workload.
Increasing --stage1_top_k can retain more potential partners, but also increases contact work. The script requests k + 1 neighbors and removes self-hits, so the actual count can differ from exactly N × k. Check the candidate count in the log rather than assuming it.
4. Set up a reproducible local trial
The official repository documents a GPU-based screening workflow. Start with a small protein FASTA and a CUDA-capable machine. The script contains a CPU fallback, but this guide does not validate its performance or compatibility. Flash Attention is optional in the repository instructions; it is not needed for the output checker below.
The inspected code commit is bb75bb1a960b3c8325a643b5cd7d7c11e41b5a0f:
git clone https://github.com/TattaBio/FlashPPI.git
cd FlashPPI
git checkout bb75bb1a960b3c8325a643b5cd7d7c11e41b5a0f
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
python predict_proteome.py --help
Dependencies are specified with minimum versions rather than a complete environment lock. Use a Python and PyTorch build suitable for your GPU and record the versions that work.
The scripts normally resolve tattabio/flashppi from the Hub. To also fix the model revision, save the following as download_model.py in the repository root and run python download_model.py:
from huggingface_hub import snapshot_download
snapshot_download(
repo_id="tattabio/flashppi",
revision="f6238ca5e5814d8a39b7e07822e9c35d5dc00b35",
local_dir="weights/flashppi",
allow_patterns=["*.json", "*.py", "*.safetensors"],
)
The revision was checked against the official model repository. This is a model-weight download, not just a small configuration file. Hugging Face documents the revision, local_dir, and file-filter options in its download guide. The upstream loader uses trust_remote_code=True, so it executes the model implementation from that snapshot.
5. Run single-proteome screening
Put your protein FASTA at my_proteome.fasta in the repository root. Use unique record IDs, nonempty amino-acid sequences, and at least two records. The script uses Biopython’s record IDs in the output; do not rely on descriptive text after whitespace to distinguish records. The site’s FASTA audit tutorial provides a starting check.
Create a fresh output directory and launch:
mkdir flashppi-run-001 && \
python predict_proteome.py \
--fasta my_proteome.fasta \
--model_name weights/flashppi \
--output flashppi-run-001/predictions.csv \
--stage1_top_k 100 \
--threshold 0.5 \
--batch_size 4 \
--max_len 1024 \
> flashppi-run-001/run.log 2>&1
mkdir refuses an existing directory, and && prevents the model command from running in that case. This helps keep an older predictions file from being mistaken for a new result. Read flashppi-run-001/run.log after the process exits.
The important settings are:
| Setting | Effect in the checked script |
|---|---|
--stage1_top_k |
Controls retrieval depth before contact scoring; default 100 |
--threshold |
Keeps scores strictly greater than the threshold; default 0.5 |
--batch_size |
Controls encoding and contact batches; this example uses 4 instead of the default 64 |
--max_len |
Tokenizer maximum length with truncation enabled; default 1024 |
These are software settings, not validated biological cutoffs. Inspect long sequences before running: truncation can remove a relevant region. Reducing batch size may help memory use, but the single-proteome script retains all residue embeddings on the chosen device, so it does not eliminate the proteome-sized cache. See the pinned implementation.
6. Interpret the CSV and missing-output case
Single-proteome output has query_id, match_id, and contact_score. The script removes self-hits during candidate construction, merges reverse-order pairs, retains the maximum score for each unordered pair, and sorts the retained results by score.
If no candidates exceed the threshold, it prints a message and does not write a CSV. An existing file at the requested path would remain untouched. Check the process status and log together; file absence alone cannot distinguish a successful empty result from a failed run. These behaviors are visible in the output code.
The separate cross-proteome script has a different contract: it queries viral proteins against a combined host-plus-viral candidate pool and retains at most one best host hit per query above its threshold. Its default threshold is 0.4, and its columns include viral_id, host_id, and host_is_best_contact. That flag compares the retrieved, contact-scored candidates; it does not establish a global biological best partner. The checker below deliberately targets the single-proteome CSV only.
7. Check the report before using it
Download check_flashppi_output.py. It needs Python 3.10 or newer and no external packages. This demonstration uses invented scores solely to test the report format:
python3 check_flashppi_output.py --help
cat > example_predictions.csv <<'CSV'
query_id,match_id,contact_score
p1,p2,0.91
p2,p3,0.72
CSV
python3 check_flashppi_output.py example_predictions.csv
Expected output:
{
"edges": 2,
"proteins_in_edges": 3,
"min_contact_score": 0.72,
"max_contact_score": 0.91
}
Run this example in a scratch directory because cat > replaces the example file. For a real run, pass the actual predictions.csv path to the checker. proteins_in_edges counts only proteins appearing in retained edges, not the full proteome or isolated nodes.
"""Check a FlashPPI single-proteome CSV; no model inference or biological validation."""
import argparse
import csv
import json
import math
def summarize(path):
pairs = set()
nodes = set()
minimum = maximum = None
with open(path, encoding="utf-8-sig", newline="") as handle:
reader = csv.reader(handle, strict=True)
if next(reader, None) != ["query_id", "match_id", "contact_score"]:
raise ValueError("Expected query_id,match_id,contact_score header in that order")
for number, row in enumerate(reader, start=1):
if len(row) != 3:
raise ValueError(f"Record {number}: expected 3 fields")
query, match, text_score = row
if any(not value or value != value.strip() for value in (query, match)):
raise ValueError(f"Record {number}: empty or padded ID")
if query == match:
raise ValueError(f"Record {number}: self-pair")
score = float(text_score)
if not math.isfinite(score) or not 0 <= score <= 1:
raise ValueError(f"Record {number}: score must be finite and in [0, 1]")
pair = tuple(sorted((query, match)))
if pair in pairs:
raise ValueError(f"Record {number}: duplicate undirected pair")
pairs.add(pair)
nodes.update((query, match))
minimum = score if minimum is None else min(minimum, score)
maximum = score if maximum is None else max(maximum, score)
return {"edges": len(pairs), "proteins_in_edges": len(nodes),
"min_contact_score": minimum, "max_contact_score": maximum}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input", help="single-proteome predictions CSV")
args = parser.parse_args()
try:
result = summarize(args.input)
except (OSError, UnicodeError, ValueError, csv.Error) as exc:
parser.exit(1, f"error: {exc}\n")
print(json.dumps(result, indent=2, allow_nan=False))
if __name__ == "__main__":
main()
The checker rejects malformed rows, nonfinite or out-of-range scores, self-pairs, and repeated unordered pairs. It accepts a header-only report as zero edges, although the upstream no-hit path does not create such a file. It does not verify that IDs belong to your input FASTA, that a file came from the current run, or that the predicted interactions are correct. Its pair and node sets grow with report size.
Six tests passed, including a 10,000-edge report, quoted IDs, reversed duplicates, invalid scores, and CLI error handling. This validates the checker, not FlashPPI’s biological accuracy.
8. Troubleshooting and next steps
| Symptom | Action |
|---|---|
| No predictions file | Check exit status and the log’s no-hit message; use a fresh run directory. |
| CUDA memory error | Reduce batch size, inspect sequence lengths, and account for the retained residue cache. |
| Fewer candidate pairs than expected | Inspect retrieval depth, self-hit removal, and the available protein count. |
| Duplicate-looking protein names | Make the FASTA record IDs unique before inference. |
| High score without experimental support | Review the contact map and validate candidates using an appropriate independent assay. |
| Cross-proteome CSV rejected by the checker | Use an analysis matched to that script’s different schema. |
For interactive exploration, the official model card links to SeqHub, which offers FASTA-based network and contact-map exploration. The local route is useful when you need explicit versioning and reproducible output handling.
9. Summary
FlashPPI uses retrieval to reserve detailed contact prediction for a manageable candidate set. Pin both code and model, inspect the retrieval and truncation settings, and interpret the contact score according to its actual aggregation. Keep candidate screening separate from experimental confirmation, and verify the output contract before building downstream analyses.
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/en/flashppi-protein-interaction-guide.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
相关文章
- OmegaTherm: A Practical Guide to Protein Stability Predictions
- Prevent Data Leakage in Protein Datasets with Grouped Splits
- Audit Protein FASTA Files with Python Before Generating Embeddings
- Protein ML in Python: Build an Amino Acid Composition Baseline
- nanoBERT and VHHBERT: A Practical Guide to Nanobody Language Models