오픈 파운데이션 통합 구조·친화도 예측 — Boltz-2와 Chai-1로 AlphaFold3의 벽을 넘기
2024년 5월 AlphaFold3의 발표는 구조생물학의 흐름을 다시 한번 바꿨습니다. 그런데 실제 실험실이나 신약 개발 팀이 AlphaFold3를 로컬로 돌리려면 수 테라바이트 유전체 데이터베이스와 학술 전용 라이선스라는 두 개의 벽을 넘어야 했습니다. 그리고 2024년 11월 MIT/Genentech이 Boltz-1을 완전 오픈소스(MIT 라이선스)로 공개했고, 2025년 Boltz-2가 여기에 결합 친화도(binding affinity) 예측까지 통합해 자유에너지 섭동(FEP+) 대비 1000배 빠른 속도로 신약 스크리닝에 실전 투입 가능한 도구가 됐습니다. 이 편은 이 오픈 파운데이션 도구 조합으로 하드코어 신약 파이프라인을 구축합니다.
📚 선수 편 권고 (강력 권고)
이 편은 AI×바이오 하드코어 심화 편의 정점입니다. 진입 전에 DryBench의 다음 편들을 먼저 듣고·보시길 강력히 권고드립니다.
- DryBench ai-native #3 트랜스포머와 임베딩
- DryBench ai-native #12 PyTorch 기초
- DryBench ai-native #14 Claude Code와 Cursor
- DryBench ai-native #15 Bio-AI 통합
선수 편 없이 진입할 경우, 이 편에서 다루는 트랜스포머 아키텍처의 3D 좌표 처리, PyTorch에서 대용량 모델 로딩·GPU 관리, Claude Code로 파이프라인 자동화, Bio-AI의 큰 그림에 대한 재설명 없이 실전 코드부터 진행하므로 따라가기 어렵습니다.
우리 DryBench에서 이거 배웠잖아
DryBench ai-native #3에서 트랜스포머가 시퀀스뿐 아니라 3D 좌표·그래프 같은 임의의 구조화된 데이터에 확장 가능하다는 것을, #12에서 PyTorch가 대용량 모델의 파라미터를 GPU 메모리에 로드하고 mixed precision·flash attention 같은 최적화를 어떻게 활용하는지를, #14에서 Claude Code가 반복적인 파이프라인 스크립팅을 압축해주는 실전 도구라는 것을, #15에서 Bio-AI 융합의 큰 그림 안에서 구조 예측이 어디에 위치하는지를 배웠습니다.
그런데 실제 신약 개발 팀 관점에서 "AlphaFold3가 있으니 됐다"는 자족이 왜 부족한지 살펴봐야 합니다. 구조 예측 하나만으로는 리간드가 얼마나 강하게 붙는지(affinity) 모릅니다. 전통적으로 이 답은 FEP(Free Energy Perturbation) 계산으로 얻었는데 리간드 하나 당 며칠~몇 주가 걸립니다. Boltz-2는 이 두 축(구조 + 친화도)을 하나의 신경망 forward pass로 통합해 밀리초 단위로 산출합니다. 신약 스크리닝의 판이 바뀌는 지점이고, 이 편은 그 실전형입니다.
하드코어 문제 정의
신약 스크리닝의 실전 요구
한 표적 단백질(예: 특정 kinase)에 대해 1000개 이상의 후보 저분자 라이브러리에서 유효 hit을 골라야 합니다. 전통 접근:
- Docking (AutoDock Vina, Glide): 리간드 하나당 초
분. 하지만 pose는 대충 맞아도 affinity 정확도는 낮음 (correlation r ~ 0.40.5). - FEP+ (Schrödinger): 리간드 하나당 며칠. 정확도 높음 (r ~ 0.8+). 대신 상용, 라이선스 매우 비쌈.
- AlphaFold3: 복합체 구조는 뛰어나지만 affinity는 직접 출력 안 함. 별도 scoring 필요.
- Boltz-2: 구조 + affinity(log10 IC50 근사) 통합 출력. FEP+ 근접 정확도. 리간드 하나당 밀리초~초.
이 편에서 다루는 파이프라인 목표:
- 표적 단백질 서열 + 후보 리간드 SMILES 1000개 → 24시간 이내 스크리닝 완료.
- 친화도 상위 20개 후보 자동 랭킹 + PyMOL 시각화 자동 생성.
- 다중 conformation 처리: 리간드 하나에 대해 여러 pose를 샘플링 후 앙상블 스코어링.
- 재현성 강제: 모든 실행이 YAML config 하나로 정의되어 tag 추적.
왜 AlphaFold3가 아니라 Boltz-2 · Chai-1인가
- 라이선스: AlphaFold3는 학술 비상업 승인 필요, 상업 이용 별도 협의. Boltz-1/2 · Chai-1은 오픈 (Boltz는 MIT [1], Chai는 연구 무료 + 상업 별도 [2]).
- 인프라 부담: AlphaFold3는 UniRef·MGnify·PDB 등 수 TB 데이터베이스 로컬 동기화 필요. Boltz-2는 MMseqs2 원격 API로 대체 가능 [1].
- 친화도 통합: AF3는 구조만. Boltz-2는 구조 + affinity 통합 예측 [1].
- 속도: Boltz-2는 FEP+ 대비 1000x 빠름 (논문 근거 [3]).
- 상업 자유: MIT 라이선스는 상업 이용에 제약 없음. Chai-1은 상업 유료 API 제공.
도구 스택과 인프라 요구
| 도구 | 역할 | 라이선스 |
|---|---|---|
Boltz (v2, pip install boltz) | 구조 + 친화도 통합 예측 | MIT |
Chai-1 (chai_lab) | 대안·앙상블 파트너 | 연구 무료, 상업 별도 |
| MMseqs2 원격 API (BioLM 무료 tier) | MSA 구축 (로컬 DB 불필요) | GPL v3 (MMseqs2 자체), API는 BioLM 정책 |
| RDKit | SMILES 파싱·리간드 처리 | BSD-3-Clause |
| PyMOL (오픈 소스판) | 3D 구조 시각화 | LGPL |
| Biopython | PDB 파일 후처리 | Biopython License |
| PyTorch, CUDA | 신경망 백엔드 | BSD |
| PDBbind (벤치) | 결합 친화도 실측 데이터 | 학술 무료 |
인프라 요구:
- 최소 실전: 24GB VRAM 데이터센터 GPU 또는 상급 소비자 GPU (RTX 4090 24GB) 1대. Boltz-2는 fp16 기준 약 15GB VRAM 소모, 큰 복합체는 20GB+.
- CPU 폴백: 매우 느림 (단일 예측 30분 이상), 사실상 실전 불가.
- RAM: 32GB 이상.
- 디스크: Boltz weights 약 2~5GB, Chai-1 weights 약 5GB, MSA 캐시 수 GB.
- 네트워크: MMseqs2 원격 API 호출 시 표적당 수 MB 통신.
학습자 재현 예상 비용: 로컬 GPU 없다면 클라우드 온디맨드 GPU 인스턴스(예: 24GB VRAM 급) 시간당 요금표 참고. 리간드 1000개 스크리닝 약 2~4시간 GPU (Boltz-2 논문 벤치 기준 [3]).
파이프라인 실전 구현
전체 흐름:
Step 1. 표적 단백질 MSA 원격 구축
MMseqs2를 로컬에 설치하고 UniRef 다운로드하는 대신 원격 API를 사용합니다. Boltz는 여러 원격 MSA 서버를 지원합니다 [4].
from pathlib import Pathfrom dataclasses import dataclass
import requests
@dataclassclass MSAResult: """Multiple Sequence Alignment 결과.""" query_id: str a3m_content: str # a3m 포맷 MSA depth: int # MSA 깊이 (동원된 서열 수)
def build_msa_remote( query_sequence: str, query_id: str = "target", api_base: str = "https://api.colabfold.com", max_depth: int = 5000,) -> MSAResult: """ColabFold MSA 서버(MMseqs2 백엔드)로 원격 MSA 구축. Boltz 공식 문서는 ColabFold 또는 BioLM API를 권장 [4]. """ # 실제 API 호출 (예시: ColabFold MMseqs2 API) payload = {"query": f">{query_id}\n{query_sequence}", "mode": "env"} resp = requests.post(f"{api_base}/ticket/msa", data=payload, timeout=600) resp.raise_for_status() ticket = resp.json()["id"] # 폴링해서 완료 대기 import time while True: status = requests.get(f"{api_base}/ticket/{ticket}", timeout=30).json() if status["status"] == "COMPLETE": break elif status["status"] == "ERROR": raise RuntimeError(f"MSA 구축 실패: {status}") time.sleep(5) # a3m 결과 다운로드 a3m_resp = requests.get(f"{api_base}/result/download/{ticket}", timeout=60) a3m_resp.raise_for_status() a3m_content = a3m_resp.text depth = a3m_content.count("\n>") return MSAResult(query_id=query_id, a3m_content=a3m_content, depth=depth)
def save_a3m(msa: MSAResult, output_dir: Path) -> Path: """a3m 파일 저장.""" output_dir.mkdir(parents=True, exist_ok=True) path = output_dir / f"{msa.query_id}.a3m" path.write_text(msa.a3m_content) return pathStep 2. 리간드 라이브러리 정규화
SMILES는 같은 분자를 여러 표기로 쓸 수 있어 canonicalization이 필요합니다. RDKit이 표준입니다.
from rdkit import Chemfrom rdkit.Chem import AllChem, Descriptors, Lipinskiimport pandas as pd
def canonicalize_smiles(smiles: str) -> str | None: """SMILES canonical form 반환. 파싱 실패 시 None.""" mol = Chem.MolFromSmiles(smiles) if mol is None: return None return Chem.MolToSmiles(mol, canonical=True)
def lipinski_filter(smiles: str) -> dict: """Lipinski's Rule of Five 통과 여부 + 물리화학 특성.""" mol = Chem.MolFromSmiles(smiles) if mol is None: return {"valid": False} props = { "MW": Descriptors.MolWt(mol), "LogP": Descriptors.MolLogP(mol), "HBA": Lipinski.NumHAcceptors(mol), "HBD": Lipinski.NumHDonors(mol), "RotB": Lipinski.NumRotatableBonds(mol), } violations = sum([ props["MW"] > 500, props["LogP"] > 5, props["HBA"] > 10, props["HBD"] > 5, ]) props["valid"] = True props["lipinski_violations"] = violations props["lipinski_pass"] = violations <= 1 return props
def prepare_ligand_library(smiles_list: list[str]) -> pd.DataFrame: """리간드 라이브러리 정규화 + 물리화학 필터.""" records = [] for i, raw in enumerate(smiles_list): canon = canonicalize_smiles(raw) if canon is None: continue props = lipinski_filter(canon) records.append({ "ligand_id": f"L{i:04d}", "smiles_raw": raw, "smiles_canonical": canon, **props, }) df = pd.DataFrame(records) return df[df["lipinski_pass"]].reset_index(drop=True)Step 3. Boltz-2 YAML Config 생성
Boltz는 YAML 하나에 protein + ligand + MSA를 지정합니다 [4].
import yaml
def build_boltz_config( protein_sequence: str, protein_msa_path: Path, ligand_smiles: str, ligand_id: str, output_dir: Path,) -> Path: """Boltz YAML config 생성. 하나의 protein-ligand 페어 당 하나.""" config = { "version": 1, "sequences": [ { "protein": { "id": "A", "sequence": protein_sequence, "msa": str(protein_msa_path), } }, { "ligand": { "id": "L", "smiles": ligand_smiles, } }, ], "constraints": [], "properties": [ {"affinity": {"binder": "L"}} # 결합 친화도 예측 켜기 (Boltz-2 신규) ], } output_dir.mkdir(parents=True, exist_ok=True) yaml_path = output_dir / f"{ligand_id}.yaml" with open(yaml_path, "w") as f: yaml.safe_dump(config, f, sort_keys=False) return yaml_pathStep 4. Boltz-2 배치 추론
여러 리간드를 순회하며 예측. GPU 메모리를 감안한 세션 관리.
import subprocessimport json
@dataclassclass BoltzResult: """Boltz-2 예측 결과.""" ligand_id: str pdb_path: Path # 예측된 3D 복합체 구조 plddt_mean: float # 구조 신뢰도 (0~100) iptm: float # 인터페이스 pTM (0~1) affinity_log_ic50: float # log10(IC50 mol/L) 예측치 (음수일수록 강력) inference_time_sec: float
def run_boltz_prediction( yaml_path: Path, output_dir: Path, device: str = "cuda", use_msa_server: bool = False,) -> BoltzResult: """Boltz-2 CLI 실행 (실전에서는 Python API도 가능).""" import time start = time.time() cmd = [ "boltz", "predict", str(yaml_path), "--out_dir", str(output_dir), "--devices", "1", "--accelerator", "gpu" if device == "cuda" else "cpu", ] if use_msa_server: cmd.append("--use_msa_server") result = subprocess.run(cmd, capture_output=True, text=True, check=True) elapsed = time.time() - start # Boltz는 output_dir/{name}/{name}_model_0.pdb + confidence.json 생성 name = yaml_path.stem pdb_path = output_dir / name / f"{name}_model_0.pdb" conf_path = output_dir / name / f"confidence_{name}_model_0.json" with open(conf_path) as f: conf = json.load(f) # affinity는 별도 JSON에서 (Boltz-2 신규 필드) affinity_path = output_dir / name / f"affinity_{name}.json" affinity_data = json.loads(affinity_path.read_text()) if affinity_path.exists() else {} return BoltzResult( ligand_id=name, pdb_path=pdb_path, plddt_mean=float(conf.get("complex_plddt", 0.0)), iptm=float(conf.get("iptm", 0.0)), affinity_log_ic50=float(affinity_data.get("affinity_pred_value", 0.0)), inference_time_sec=elapsed, )Step 5. 배치 스크리닝 오케스트레이션
리간드 라이브러리 전체를 순회 + 실패 처리 + 진행률 표시.
from tqdm import tqdm
def batch_screen( protein_sequence: str, protein_msa: MSAResult, ligand_library: pd.DataFrame, work_dir: Path, device: str = "cuda",) -> pd.DataFrame: """리간드 라이브러리 전체 스크리닝.""" msa_path = save_a3m(protein_msa, work_dir / "msa") results = [] failures = [] for _, row in tqdm(ligand_library.iterrows(), total=len(ligand_library), desc="Screening"): try: yaml_path = build_boltz_config( protein_sequence=protein_sequence, protein_msa_path=msa_path, ligand_smiles=row["smiles_canonical"], ligand_id=row["ligand_id"], output_dir=work_dir / "configs", ) boltz_result = run_boltz_prediction( yaml_path=yaml_path, output_dir=work_dir / "predictions", device=device, use_msa_server=False, ) results.append({ "ligand_id": boltz_result.ligand_id, "smiles": row["smiles_canonical"], "affinity_log_ic50": boltz_result.affinity_log_ic50, "plddt": boltz_result.plddt_mean, "iptm": boltz_result.iptm, "pdb_path": str(boltz_result.pdb_path), "inference_sec": boltz_result.inference_time_sec, "MW": row.get("MW"), "LogP": row.get("LogP"), }) except Exception as e: failures.append({"ligand_id": row["ligand_id"], "error": str(e)}) df_results = pd.DataFrame(results).sort_values("affinity_log_ic50") df_failures = pd.DataFrame(failures) df_failures.to_csv(work_dir / "failures.csv", index=False) return df_resultsStep 6. Top-K PyMOL 시각화
상위 후보의 결합 포즈를 자동으로 렌더링.
def render_pymol( pdb_path: Path, output_png: Path, ray_trace: bool = True,) -> None: """PyMOL 헤드리스 렌더링.""" script = f"""load {pdb_path}, complexhide everythingshow cartoon, complex and polymershow sticks, complex and organiccolor grey70, complex and polymercolor yellow, complex and organicbg_color whitezoom complex and organic, 5{"ray 1200, 900" if ray_trace else ""}png {output_png}, dpi=150quit""" script_path = output_png.parent / "render.pml" script_path.write_text(script) subprocess.run(["pymol", "-cq", str(script_path)], check=True)
def render_top_k(results_df: pd.DataFrame, output_dir: Path, k: int = 20) -> None: output_dir.mkdir(parents=True, exist_ok=True) for _, row in results_df.head(k).iterrows(): render_pymol( pdb_path=Path(row["pdb_path"]), output_png=output_dir / f"{row['ligand_id']}.png", )통합 파이프라인
def full_screening_pipeline( protein_sequence: str, protein_id: str, smiles_library: list[str], work_dir: Path, device: str = "cuda", top_k: int = 20,) -> pd.DataFrame: """FASTA + SMILES 라이브러리 → 랭킹된 결과 DataFrame.""" print(f"[1/6] MSA 구축 원격 요청 (query length={len(protein_sequence)})") msa = build_msa_remote(protein_sequence, query_id=protein_id) print(f" MSA depth={msa.depth}") print(f"[2/6] 리간드 라이브러리 정규화 (raw={len(smiles_library)})") library = prepare_ligand_library(smiles_library) print(f" Lipinski 통과={len(library)}") print(f"[3/6] 배치 스크리닝 시작") results = batch_screen(protein_sequence, msa, library, work_dir, device) results.to_csv(work_dir / "screening_results.csv", index=False) print(f"[4/6] Top-{top_k} PyMOL 렌더링") render_top_k(results, work_dir / "top_k_renders", k=top_k) print(f"[5/6] 완료: work_dir={work_dir}") print(f"[6/6] 상위 5개 리간드 요약:") print(results.head(5)[["ligand_id", "affinity_log_ic50", "plddt", "iptm"]].to_string(index=False)) return resultsChai-1 앙상블 검증 (선택적 강화)
Chai-1은 Boltz와 유사한 SOTA 오픈 파운데이션이라 상위 후보를 Chai-1으로 재검증하면 위양성을 줄일 수 있습니다 [2].
from chai_lab.chai1 import run_inference
def chai_reverification( protein_sequence: str, ligand_smiles: str, output_dir: Path, device: str = "cuda",) -> dict: """Chai-1로 동일 페어 재예측. Boltz 결과와 앙상블 스코어링.""" fasta_str = f">protein|name=A\n{protein_sequence}\n>ligand|name=L\n{ligand_smiles}\n" fasta_path = output_dir / "chai_input.fasta" fasta_path.write_text(fasta_str) output_dir.mkdir(parents=True, exist_ok=True) result = run_inference( fasta_file=fasta_path, output_dir=output_dir, num_trunk_recycles=3, num_diffn_timesteps=200, seed=42, device=device, use_esm_embeddings=True, ) return { "pdb_path": result[0], "iptm": float(result[0].iptm), # 예시 필드, 실제 API 참조 }
def ensemble_ranking( boltz_score: float, chai_score: float, weight: float = 0.5,) -> float: """두 모델의 스코어 가중 평균 (낮을수록 강력).""" return weight * boltz_score + (1 - weight) * chai_score성능·비용·알려진 실패 케이스
성능 참고 (공개 벤치 인용)
| 접근 | 벤치 | Structure RMSD (Å) | Affinity Pearson r | 시간/페어 | 출처 |
|---|---|---|---|---|---|
| Docking (AutoDock Vina) | PDBbind core | 3.5~5.0 | 0.4~0.5 | 초 | Legacy |
| Glide XP | PDBbind core | 2.5~3.5 | 0.55~0.65 | 분 | Schrödinger |
| FEP+ (Schrödinger) | 정선 subset | — | 0.75~0.85 | 며칠 | 상용 |
| AlphaFold3 (구조만) | Recent PDB | 1.5~2.5 | 별도 scoring 필요 | 초~분 | Google DeepMind 2024 |
| Chai-1 | 벤치 subset | ~2.0 | ~0.65 | 초~분 | Chai Discovery 2024 [2] |
| Boltz-1 | Recent PDB | 2.0~3.0 | ~0.6 | 초 | MIT/Genentech 2024 [1] |
| Boltz-2 | PDBbind 등 | ~2.0 | ~0.80 (FEP+ 수준) | 밀리초~초 | Wohlwend et al. 2025 [3] |
학습자 재현 예상 비용
- API 비용 0(로컬 GPU 사용 시). MMseqs2 원격 API 무료 tier 활용.
- GPU 시간: 표적 하나 + 리간드 1000개 스크리닝 약 2~4시간 (24GB VRAM GPU 기준).
- 클라우드 온디맨드 사용 시 시간당 요금표 확인 필요.
- 디스크: Boltz weights 2~5GB, 결과 PDB + 렌더 약 500MB.
알려진 실패 케이스 3건 (커뮤니티·논문 수집형)
-
큰 복합체(> 2000 residues)에서 OOM(Out of Memory)
증상: 24GB VRAM에서도 대형 다중 서브유닛 복합체는 메모리 초과.
원인: Boltz-2의 attention은 residue 수에 O(N²) 메모리.
회피: (a)--use_flash_attention옵션 활성화, (b) fp16 강제, (c) 큰 복합체는 서브유닛별 분할 예측 후 후처리 결합, (d) 48GB+ VRAM GPU 필요.
출처: Boltz GitHub Issues — "OOM for large complexes" 스레드 [5]. -
MSA depth 부족으로 정확도 급락
증상: 신규 orphan 서열이나 metagenomic 서열은 MMseqs2 원격에서 MSA depth < 32로 나오는 경우가 있고 이때 Boltz-2 pLDDT · affinity 신뢰도 급락.
원인: 파운데이션 모델도 co-evolution 신호에 여전히 의존.
회피: (a) MSA depth < 100이면 결과에 경고 플래그, (b)--msa_server옵션으로 여러 서버 시도, (c) single-sequence 모드(no MSA)로 baseline 비교해 신뢰도 판단.
출처: Boltz 공식 documentation "MSA quality" 섹션 [6]. -
리간드 stereochemistry 무시로 잘못된 결합 pose
증상: SMILES에 stereochemistry가 명시되어 있어도 예측이 여러 stereoisomer를 임의로 선택.
원인: SMILES canonicalization 단계에서 chirality tag 유실 or 파운데이션 모델 학습 데이터 편향.
회피: (a)Chem.MolFromSmiles(canonical=False)로 원본 stereochemistry 보존, (b) 3D conformer를 RDKitAllChem.EmbedMolecule로 생성 후 SDF 입력 시도, (c) 예측 결과 pose의 chirality를 사후 검증.
출처: RDKit Discussions + Boltz Issues (stereochemistry 관련 여러 스레드) [7].
확장 아이디어
- Fragment-based drug discovery: 리간드 라이브러리를 fragment(< 300 Da) 위주로 구성 후 Boltz-2로 hit fragment 스크리닝 → linker 설계.
- Target class 벤치: 하나의 kinase family(예: MAPK) 전체 서열에 대해 동일 리간드 라이브러리 반복 스크리닝 → selectivity map.
- Active learning loop: 예측 상위를 실제 실험 assay → 결과 피드백 → 모델 fine-tuning (도메인 특화).
- Protein-Protein complex + ligand: Boltz는 다중 chain 지원. 항체-항원 + 저분자 조합 시나리오 확장.
- MCP tool 노출: 편 14의 MCP Agent가 이 파이프라인을 tool로 호출 → 자율 신약 후보 리서치.
다음 편
- 편 08
docking-hybrid-diffusion: DiffDock-Glide 하이브리드로 이 편의 top-k 후보에 pose 정밀화. - 편 13
protein-design-multimodal: ESM3로 신규 표적 단백질 설계 → Boltz-2로 결합 후보 스크리닝. - 편 14
bio-mcp-agent: 이 파이프라인을 MCP tool로 감싸 자율 신약 리서치 에이전트. - 편 15
bio-mcp-server-suite: PDBbind·ChEMBL 데이터 접근용 커스텀 MCP 서버.
참고 문헌
- Wohlwend J, Corso G, Passaro S, et al. Boltz-1: 오픈 파운데이션 구조 예측. MIT/Genentech 2024. GitHub:
https://github.com/jwohlwend/boltz - Chai Discovery. "Chai-1: Decoding the molecular interactions of life." bioRxiv 2024.
https://www.biorxiv.org/content/10.1101/2024.10.10.615955v2/ GitHub:https://github.com/chaidiscovery/chai-lab - Passaro S, Corso G, Wohlwend J, et al. "Boltz-2: Towards Accurate and Efficient Binding Affinity Prediction." bioRxiv 2025.
https://www.biorxiv.org/content/10.1101/2025.06.14.659707v1 - Boltz 공식 문서 (prediction 사용법):
https://github.com/jwohlwend/boltz/blob/main/docs/prediction.md - Boltz GitHub Issues (OOM, MSA, stereochemistry):
https://github.com/jwohlwend/boltz/issues - Boltz 공식 문서 MSA 섹션:
https://github.com/jwohlwend/boltz/blob/main/docs/msa.md - RDKit Discussions (stereochemistry canonicalization):
https://github.com/rdkit/rdkit/discussions - Abramson J, Adler J, Dunger J, et al. "Accurate structure prediction of biomolecular interactions with AlphaFold 3." Nature 2024.
https://www.nature.com/articles/s41586-024-07487-w - Schrödinger FEP+ (상용):
https://www.schrodinger.com/products/fep - PDBbind:
http://www.pdbbind.org.cn/ - MMseqs2:
https://github.com/soedinglab/MMseqs2 - ColabFold MSA server (오픈 tier):
https://github.com/sokrypton/ColabFold - BioLM API:
https://biolm.ai/models/ - RDKit:
https://www.rdkit.org/ - PyMOL open-source:
https://github.com/schrodinger/pymol-open-source - AutoDock Vina:
https://vina.scripps.edu/ - Recent PDB 벤치 세트:
https://www.rcsb.org/