Boltz 详细部署指南
面向零基础用户的 Boltz 蛋白质结构预测实战手册,涵盖环境安装、首次预测、结果查看与常见报错处理,可直接照做复现。
2026-03-14
#你需要安装的软件
必装软件
1. Python 3.12(推荐)
- 官方要求:
>=3.10,<3.13 - 不建议使用 3.14(兼容性差,常见依赖无法正常安装)
2. Git(可选但推荐)
- 用于克隆仓库、后续更新代码
3. ChimeraX(查看 3D 结构)
- 推荐版本:Production Release 1.11.1
- 下载地址:UCSF ChimeraX 官网
可选软件
NVIDIA GPU 驱动 + CUDA 环境
如果你有 NVIDIA 显卡,可显著加速推理;没有也可以运行(CPU 模式)。
#推荐目录结构
建议固定到一个目录,避免路径混乱:
D:\AI\boltz-main\
后续所有命令都在项目根目录执行。
#安装与初始化(首次只做一次)
在 PowerShell 中执行以下步骤:
# 进入项目目录
cd D:\project\example\boltz-main\boltz-main
# 如果没有 Python 3.12,使用 winget 安装(需管理员权限)
winget install Python.Python.3.12 --silent --accept-package-agreements --accept-source-agreements
# 清理旧环境(若之前安装失败过,先删除旧环境)
Remove-Item -Recurse -Force .venv -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force venv312 -ErrorAction SilentlyContinue
# 创建虚拟环境(强制指定 Python 3.12)
py -3.12 -m venv .venv
# 安装项目依赖
.\.venv\Scripts\python.exe -m pip install -e ."为什么不能用 Python 3.14? 目前科学计算库(如 numpy、torch)对最新版 Python 支持有滞后,强制推荐 3.12。
#第一次最稳妥预测(低配置可跑)
使用仓库内置样例(无 MSA,资源占用最小):
# 确保在项目根目录下
.\.venv\Scripts\boltz.exe predict examples\prot_no_msa.yaml --accelerator cpu --override参数说明:
--accelerator cpu— 强制 CPU 运行,避免无 GPU 报错--override— 覆盖旧结果,确保本次重新计算
#输出结果怎么看
默认输出目录:boltz_results_prot_no_msa
关键文件
| 文件 | 说明 |
|---|---|
predictions/prot_no_msa/prot_no_msa_model_0.cif | 三维结构文件,可用 ChimeraX 打开 |
predictions/prot_no_msa/confidence_prot_no_msa_model_0.json | JSON 格式置信度报告 |
置信度解读示例
{
"confidence_score": 0.613,
"ptm": 0.544,
"complex_plddt": 0.630
}| 指标 | 本次结果 | 解读 |
|---|---|---|
confidence_score | 0.613 | 可用,中等置信度 |
ptm | 0.544 | 全局拓扑基本正确 |
complex_plddt | 0.630 | 局部精度中等,低资源模式正常 |
"使用
msa: empty属于低资源模式,分数偏中等是正常的。启用 MSA 服务器可显著提升精度。
#如何用 ChimeraX 查看 3D 结构
- 安装 ChimeraX 1.11.1
- 打开软件,点击
File → Open - 选择
.cif文件:prot_no_msa_model_0.cif
鼠标操作:
| 操作 | 功能 |
|---|---|
| 左键拖动 | 旋转 |
| 右键拖动 | 缩放 |
| 中键拖动 | 平移 |
#常见报错与处理
报错 1:No supported gpu backend found!
原因: 机器没有可用 GPU,但命令默认 gpu 模式。
解决:
.\.venv\Scripts\boltz.exe predict examples\prot_no_msa.yaml --accelerator cpu报错 2:Python 3.14 安装依赖失败
现象: 出现 Building wheel for ... error 或 No matching distribution found。
原因: Python 3.14+ 太新,很多科学计算包(numpy、pytorch)还没发布对应编译版本。
解决:
- 卸载 Python 3.14,安装 Python 3.12
- 创建环境时强制指定:
py -3.12 -m venv .venv
报错 3:pip 找不到
解决: 始终使用虚拟环境里的 python 执行 pip:
.\.venv\Scripts\python.exe -m pip install -e .#30 秒最短复现流程
# 1. 进入项目目录
cd D:\project\example\boltz-main\boltz-main
# 2. 创建环境 (Python 3.12)
py -3.12 -m venv .venv
# 3. 安装依赖
.\.venv\Scripts\python.exe -m pip install -e .
# 4. 运行预测
.\.venv\Scripts\boltz.exe predict examples\prot_no_msa.yaml --accelerator cpu --override输出在:.\boltz_results_prot_no_msa\predictions\prot_no_msa\
#自定义预测(只改一个 YAML)
复制 examples/prot_no_msa.yaml 并修改序列:
version: 1
sequences:
- protein:
id: A
sequence: 你的蛋白质氨基酸序列
msa: empty运行预测:
.\.venv\Scripts\boltz.exe predict 你的文件.yaml --accelerator cpu --override#一键向导脚本(推荐)
项目仓库中提供了引导式 PowerShell 脚本 boltz_predict_wizard.ps1,具备以下能力:
- ✅ 自动环境管理 — 自动检测并使用
.venv,强制 Python 3.12 - ✅ 相对路径 — 脚本可随项目移动,不依赖绝对路径
- ✅ 可视化交互 — 无需记忆复杂命令
- ✅ 系统检测 — 自动识别 CPU/内存/GPU 并推荐预测难度
它会自动完成:
- 检测本机硬件配置
- 推荐预测难度(1/2/3 级)
- 引导输入蛋白质序列
- 自动生成 YAML 输入文件
- 自动运行 Boltz 预测并显示进度
运行方式:
cd D:\project\example\boltz-main\boltz-main
.\boltz_predict_wizard.ps1#完整向导脚本源码
以下是 boltz_predict_wizard.ps1 的完整源码(639 行),可直接复制保存为 .ps1 文件使用:
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$utf8编码 = New-Object System.Text.UTF8Encoding($false)
$OutputEncoding = $utf8编码
try { [Console]::InputEncoding = $utf8编码 } catch {}
try { [Console]::OutputEncoding = $utf8编码 } catch {}
function 读入-默认值 {
param(
[string]$提示语,
[string]$默认值
)
$输入 = Read-Host "$提示语 [$默认值]"
if ([string]::IsNullOrWhiteSpace($输入)) {
return $默认值
}
return $输入.Trim()
}
function 读入-是或否 {
param(
[string]$提示语,
[bool]$默认是 = $true
)
$默认文本 = if ($默认是) { "Y/n" } else { "y/N" }
$输入 = Read-Host "$提示语 ($默认文本)"
if ([string]::IsNullOrWhiteSpace($输入)) {
return $默认是
}
$值 = $输入.Trim().ToLowerInvariant()
if ($值 -in @("y", "yes", "1", "是")) { return $true }
if ($值 -in @("n", "no", "0", "否")) { return $false }
return $默认是
}
function 获取-系统信息 {
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
$os = Get-CimInstance Win32_OperatingSystem
$gpu列表 = Get-CimInstance Win32_VideoController | Where-Object { $_.Name -and $_.Name -notmatch "Microsoft Basic" }
$gpu名称 = @()
foreach ($g in $gpu列表) {
$gpu名称 += $g.Name
}
$有Nvidia = $false
foreach ($名称 in $gpu名称) {
if ($名称 -match "NVIDIA") { $有Nvidia = $true }
}
$内存GB = [math]::Round(([double]$os.TotalVisibleMemorySize / 1MB), 1)
[pscustomobject]@{
CPU = $cpu.Name
内存GB = $内存GB
GPU列表 = $gpu名称
有Nvidia = $有Nvidia
}
}
function 检查-Python312 {
try {
& py -3.12 -c "import sys; print(sys.version)"
if ($LASTEXITCODE -eq 0) { return }
} catch {
}
$立即安装 = 读入-是或否 -提示语 "未检测到 Python 3.12,是否立即安装" -默认是 $true
if (-not $立即安装) {
throw "必须先安装 Python 3.12 才能继续。"
}
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
throw "系统未找到 winget,请手动安装 Python 3.12 后重试。"
}
& winget install Python.Python.3.12 --silent --accept-package-agreements --accept-source-agreements
& py -3.12 -c "import sys; print(sys.version)"
if ($LASTEXITCODE -ne 0) {
throw "Python 3.12 安装后仍不可用,请重启终端后重试。"
}
}
function 重建-虚拟环境 {
param([string]$虚拟环境目录)
$oldEAP = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
try {
cmd /c "rd /s /q `"$虚拟环境目录`"" 2>$null
} catch {
}
$ErrorActionPreference = $oldEAP
if (Test-Path $虚拟环境目录) {
$备份名 = "${虚拟环境目录}_old_" + (Get-Date -Format "HHmmss")
try {
Rename-Item -Path $虚拟环境目录 -NewName $备份名 -ErrorAction SilentlyContinue
} catch {
throw "由于目录被锁定,无法重建虚拟环境。请手动删除 $虚拟环境目录 后重试。"
}
}
Write-Host "正在创建 Python 虚拟环境 (.venv)..." -ForegroundColor Cyan
& py -3.12 -m venv $虚拟环境目录 | Out-Host
if ($LASTEXITCODE -ne 0) { throw "创建虚拟环境失败。请确认已安装 Python 3.12。" }
}
function 安装-Boltz依赖 {
param(
[string]$python路径,
[string]$项目目录
)
Write-Host "正在安装/修复依赖..." -ForegroundColor Cyan
& $python路径 -m pip install -e $项目目录 | Out-Host
if ($LASTEXITCODE -ne 0) { return $false }
return $true
}
function 测试-Boltz环境 {
param(
[string]$python路径,
[string]$boltz路径
)
if (-not (Test-Path $python路径)) {
return [pscustomobject]@{ 可用 = $false; 原因 = "缺少 python.exe" }
}
if (-not (Test-Path $boltz路径)) {
return [pscustomobject]@{ 可用 = $false; 原因 = "缺少 boltz.exe" }
}
try {
$python版本 = & $python路径 --version 2>&1
if ($LASTEXITCODE -ne 0 -or $python版本 -match "No Python at") {
return [pscustomobject]@{ 可用 = $false; 原因 = "Python 解释器不可用" }
}
} catch {
return [pscustomobject]@{ 可用 = $false; 原因 = "Python 执行失败" }
}
try {
& $python路径 -c "import boltz, torch, rdkit" 2>$null
if ($LASTEXITCODE -ne 0) {
return [pscustomobject]@{ 可用 = $false; 原因 = "关键依赖导入失败" }
}
} catch {
return [pscustomobject]@{ 可用 = $false; 原因 = "关键依赖导入异常" }
}
try {
& $boltz路径 --help > $null 2>&1
if ($LASTEXITCODE -ne 0) {
return [pscustomobject]@{ 可用 = $false; 原因 = "boltz 命令不可用" }
}
} catch {
return [pscustomobject]@{ 可用 = $false; 原因 = "boltz 命令执行异常" }
}
return [pscustomobject]@{ 可用 = $true; 原因 = "" }
}
function 检查-Boltz环境 {
param([string]$项目目录)
$虚拟环境目录 = Join-Path $项目目录 ".venv"
$python路径 = Join-Path $虚拟环境目录 "Scripts\python.exe"
$boltz路径 = Join-Path $虚拟环境目录 "Scripts\boltz.exe"
$检测起始时间 = Get-Date
if ((Test-Path $python路径) -and (Test-Path $boltz路径)) {
$检测耗时 = [math]::Round(((Get-Date) - $检测起始时间).TotalMilliseconds)
Write-Host ("检测到现有 .venv,可直接运行(检测耗时 {0}ms)。" -f $检测耗时) -ForegroundColor DarkGray
return [pscustomobject]@{
Python路径 = $python路径
Boltz路径 = $boltz路径
虚拟环境目录 = $虚拟环境目录
}
}
if (-not (Test-Path $python路径)) {
Write-Host "未检测到 .venv python,正在创建环境并安装依赖..." -ForegroundColor Yellow
重建-虚拟环境 -虚拟环境目录 $虚拟环境目录
$修复成功 = 安装-Boltz依赖 -python路径 $python路径 -项目目录 $项目目录
if (-not $修复成功) { throw "安装 Boltz 依赖失败。" }
} elseif (-not (Test-Path $boltz路径)) {
Write-Host "检测到 .venv 但缺少 boltz 命令,正在修复依赖..." -ForegroundColor Yellow
$修复成功 = 安装-Boltz依赖 -python路径 $python路径 -项目目录 $项目目录
if (-not $修复成功) {
Write-Host "依赖修复失败,正在重建虚拟环境..." -ForegroundColor Yellow
重建-虚拟环境 -虚拟环境目录 $虚拟环境目录
$修复成功 = 安装-Boltz依赖 -python路径 $python路径 -项目目录 $项目目录
if (-not $修复成功) { throw "安装 Boltz 依赖失败。" }
}
}
if (-not (Test-Path $boltz路径)) {
throw "环境修复失败:仍未找到 boltz.exe。"
}
$检测耗时 = [math]::Round(((Get-Date) - $检测起始时间).TotalMilliseconds)
Write-Host ("环境已就绪(检测/修复耗时 {0}ms)。" -f $检测耗时) -ForegroundColor DarkGray
return [pscustomobject]@{
Python路径 = $python路径
Boltz路径 = $boltz路径
虚拟环境目录 = $虚拟环境目录
}
}
function 生成-Yaml文本 {
param(
[string]$链ID,
[string]$序列,
[bool]$使用MSA服务器
)
if ($使用MSA服务器) {
@"
version: 1
sequences:
- protein:
id: $链ID
sequence: $序列
"@
} else {
@"
version: 1
sequences:
- protein:
id: $链ID
sequence: $序列
msa: empty
"@
}
}
function 获取-结果目录 {
param(
[string]$输出根目录,
[string]$任务名
)
$首选目录 = Join-Path $输出根目录 ("boltz_results_" + $任务名)
if (Test-Path $首选目录) { return $首选目录 }
$候选 = Get-ChildItem -Path $输出根目录 -Directory -Filter "boltz_results_*" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if ($候选) { return $候选.FullName }
return $首选目录
}
function 查找-ChimeraX路径 {
$候选路径 = @()
if ($env:CHIMERAX_PATH) {
$候选路径 += $env:CHIMERAX_PATH
}
foreach ($命令名 in @("ChimeraX.exe", "chimeraX.exe", "chimerax.exe")) {
$命令 = Get-Command $命令名 -ErrorAction SilentlyContinue | Select-Object -First 1
if ($命令 -and $命令.Source) {
$候选路径 += $命令.Source
}
}
$候选路径 += @(
"C:\Program Files\ChimeraX\bin\ChimeraX.exe",
"C:\Program Files\ChimeraX\ChimeraX.exe",
"$env:LOCALAPPDATA\Programs\ChimeraX\bin\ChimeraX.exe",
"$env:LOCALAPPDATA\Programs\ChimeraX\ChimeraX.exe"
)
$快捷方式目录 = @(
"$env:ProgramData\Microsoft\Windows\Start Menu\Programs",
"$env:APPDATA\Microsoft\Windows\Start Menu\Programs"
)
foreach ($目录 in $快捷方式目录) {
if (-not (Test-Path $目录)) { continue }
$快捷方式 = Get-ChildItem -Path $目录 -Filter "*ChimeraX*.lnk" -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $快捷方式) { continue }
try {
$wsh = New-Object -ComObject WScript.Shell
$lnk = $wsh.CreateShortcut($快捷方式.FullName)
if ($lnk.TargetPath) {
$候选路径 += $lnk.TargetPath
}
} catch {
}
}
foreach ($目录 in @("C:\Program Files", "$env:LOCALAPPDATA\Programs")) {
if (-not (Test-Path $目录)) { continue }
$发现 = Get-ChildItem -Path $目录 -Filter "ChimeraX.exe" -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($发现) {
$候选路径 += $发现.FullName
}
}
foreach ($路径 in ($候选路径 | Select-Object -Unique)) {
if ($路径 -and (Test-Path $路径)) {
return $路径
}
}
return $null
}
function 处理-启动终端切换 {
param([string]$脚本路径)
if ($env:BOLTZ_WIZARD_EXTERNAL_HOSTED -eq "1") {
return
}
Write-Host "提示:按 Enter 可立即切换到 Windows PowerShell 终端;倒计时结束将继续在当前 IDE 终端运行。" -ForegroundColor Yellow
$是否切换 = $false
$可读按键 = $false
try {
$null = $Host.UI.RawUI.KeyAvailable
$可读按键 = $true
} catch {
}
for ($剩余秒 = 3; $剩余秒 -ge 1 -and -not $是否切换; $剩余秒--) {
Write-Host -NoNewline ("`r将在 {0} 秒后继续当前终端,按 Enter 立即切换..." -f $剩余秒)
if ($可读按键) {
for ($i = 0; $i -lt 10; $i++) {
if ($Host.UI.RawUI.KeyAvailable) {
$按键 = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
if ($按键.VirtualKeyCode -eq 13) {
$是否切换 = $true
break
}
}
Start-Sleep -Milliseconds 100
}
} else {
Start-Sleep -Seconds 1
}
}
Write-Host ""
if ($是否切换) {
$转义路径 = $脚本路径.Replace("'", "''")
$命令文本 = "$env:BOLTZ_WIZARD_EXTERNAL_HOSTED='1'; & '$转义路径'"
Start-Process -FilePath "powershell.exe" -ArgumentList @("-NoExit", "-ExecutionPolicy", "Bypass", "-Command", $命令文本) | Out-Null
Write-Host "已切换到 Windows PowerShell 终端,新终端将直接开始执行。" -ForegroundColor Cyan
exit
}
Write-Host "继续在当前 IDE 终端运行。" -ForegroundColor DarkGray
Write-Host ""
}
处理-启动终端切换 -脚本路径 $MyInvocation.MyCommand.Path
Write-Host ""
Write-Host "==============================================="
$bannerLines = @(
" ██╗ ██████╗ ██████╗ ███████╗ ███████╗ ██████╗ ██╗ ██████╗ "
"███║██╔═████╗╚════██╗╚════██║ ██╔════╝██╔═══██╗██║ ██╔═══██╗"
"╚██║██║██╔██║ █████╔╝ ██╔╝ ███████╗██║ ██║██║ ██║ ██║"
" ██║████╔╝██║ ╚═══██╗ ██╔╝ ╚════██║██║ ██║██║ ██║ ██║"
" ██║╚██████╔╝██████╔╝ ██║ ███████║╚██████╔╝███████╗╚██████╔╝"
" ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝ "
)
$colors = @("Red", "Magenta", "Cyan", "Green", "Yellow", "White")
$colorIndex = 0
foreach ($line in $bannerLines) {
Write-Host $line -ForegroundColor $colors[$colorIndex % $colors.Count]
$colorIndex++
}
Write-Host "==============================================="
Write-Host "Boltz 蛋白质结构预测向导"
Write-Host "By·1037SOLO" -ForegroundColor Cyan
Write-Host "==============================================="
Write-Host ""
$系统 = 获取-系统信息
Write-Host "本机信息:"
Write-Host ("CPU: " + $系统.CPU)
Write-Host ("内存(GB): " + $系统.内存GB)
if ($系统.GPU列表.Count -gt 0) {
Write-Host ("GPU: " + ($系统.GPU列表 -join " | "))
} else {
Write-Host "GPU: 未检测到独立显卡"
}
Write-Host ""
if ($系统.有Nvidia -and $系统.内存GB -ge 32) {
Write-Host "推荐难度:3(高质量,优先 GPU)"
} elseif ($系统.有Nvidia -or $系统.内存GB -ge 16) {
Write-Host "推荐难度:2(标准模式)"
} else {
Write-Host "推荐难度:1(入门低资源)"
}
Write-Host ""
$项目目录 = Split-Path -Parent $MyInvocation.MyCommand.Path
Push-Location $项目目录
try {
检查-Python312
$环境 = 检查-Boltz环境 -项目目录 $项目目录
$默认任务名 = "protein_" + (Get-Date -Format "yyyyMMdd_HHmmss")
$任务名 = 读入-默认值 -提示语 "请输入任务名(英文/数字)" -默认值 $默认任务名
$任务名 = ($任务名 -replace "[^a-zA-Z0-9_\-]", "_")
$链ID = 读入-默认值 -提示语 "请输入链ID" -默认值 "A"
$蛋白序列 = ""
while ($true) {
$原始序列 = Read-Host "请输入蛋白质序列(只允许字母,使用 Shift+Insert 粘贴,Ctrl+C 退出,脚本会自动去空格)"
$清洗序列 = ($原始序列.ToUpperInvariant() -replace "\s", "")
if ($清洗序列.Length -lt 20) {
Write-Host "序列过短,建议至少 20 个氨基酸。" -ForegroundColor Yellow
continue
}
if ($清洗序列 -notmatch "^[A-Z]+$") {
Write-Host "序列含非法字符,请仅输入字母。" -ForegroundColor Yellow
continue
}
$蛋白序列 = $清洗序列
break
}
Write-Host ""
Write-Host "难度选项:"
Write-Host "1) 入门:CPU + 单序列,最快"
Write-Host "2) 标准:CPU,采样更充分"
Write-Host "3) 高质量:优先 GPU,可选 MSA 服务器"
$难度 = 读入-默认值 -提示语 "请选择难度" -默认值 "1"
if ($难度 -notin @("1","2","3")) { $难度 = "1" }
$加速器 = "cpu"
$循环步数 = 1
$采样步数 = 50
$使用MSA服务器 = $false
if ($难度 -eq "2") {
$加速器 = "cpu"
$循环步数 = 3
$采样步数 = 150
}
if ($难度 -eq "3") {
$加速器 = if ($系统.有Nvidia) { "gpu" } else { "cpu" }
$循环步数 = 3
$采样步数 = 200
$使用MSA服务器 = 读入-是或否 -提示语 "是否启用 MSA 服务器(更准但更慢,需要联网)" -默认是 $true
if (-not $系统.有Nvidia) {
Write-Host "未检测到 NVIDIA GPU,已自动切换为 CPU。" -ForegroundColor Yellow
}
}
if ($难度 -in @("1","2")) {
$使用MSA服务器 = $false
}
$输入目录 = Join-Path $项目目录 "generated_inputs"
$输出目录 = Join-Path $项目目录 "generated_outputs"
New-Item -ItemType Directory -Path $输入目录 -Force | Out-Null
New-Item -ItemType Directory -Path $输出目录 -Force | Out-Null
$yaml路径 = Join-Path $输入目录 ($任务名 + ".yaml")
$yaml文本 = 生成-Yaml文本 -链ID $链ID -序列 $蛋白序列 -使用MSA服务器 $使用MSA服务器
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::WriteAllText($yaml路径, $yaml文本, $utf8Bom)
Write-Host ""
Write-Host "开始预测..."
Write-Host ("输入文件: " + $yaml路径)
Write-Host ("输出根目录: " + $输出目录)
Write-Host ("加速器: " + $加速器)
Write-Host ("recycling_steps: " + $循环步数)
Write-Host ("sampling_steps: " + $采样步数)
Write-Host ("use_msa_server: " + $使用MSA服务器)
Write-Host ""
$参数 = @(
"predict",
$yaml路径,
"--out_dir", $输出目录,
"--accelerator", $加速器,
"--recycling_steps", $循环步数.ToString(),
"--sampling_steps", $采样步数.ToString(),
"--diffusion_samples", "1",
"--override"
)
if ($使用MSA服务器) {
$参数 += "--use_msa_server"
}
$执行单次预测 = {
param(
[string]$boltz路径,
[string[]]$命令参数,
[string]$输出根目录,
[string]$当前任务名
)
$标准输出日志 = [System.IO.Path]::GetTempFileName()
$错误输出日志 = [System.IO.Path]::GetTempFileName()
try {
$进程 = Start-Process -FilePath $boltz路径 -ArgumentList $命令参数 -RedirectStandardOutput $标准输出日志 -RedirectStandardError $错误输出日志 -PassThru -NoNewWindow
$动画字符 = @("-", "\", "|", "/")
$索引 = 0
$当前状态 = "正在初始化..."
$阶段已显示 = @{}
$更新阶段 = {
param(
[string]$阶段键,
[string]$阶段文本,
[string]$颜色 = "Cyan"
)
if (-not $阶段已显示.ContainsKey($阶段键)) {
$阶段已显示[$阶段键] = $true
Write-Host ""
Write-Host ("[阶段] " + $阶段文本) -ForegroundColor $颜色
}
$script:当前状态 = $阶段文本
}
Write-Host "执行阶段:"
Write-Host " 1/8 输入检查"
Write-Host " 2/8 预处理与记录构建"
Write-Host " 3/8 MSA 获取/解析"
Write-Host " 4/8 特征构建(Tokenize/Featurize)"
Write-Host " 5/8 模型与参数加载"
Write-Host " 6/8 结构预测"
Write-Host " 7/8 扩散采样"
Write-Host " 8/8 写入预测结果"
Write-Host " 附加阶段:亲和力预测(仅在输入包含 affinity 时执行)"
Write-Host ""
Write-Host "正在启动 Boltz 引擎..." -NoNewline
while (-not $进程.HasExited) {
$日志内容 = @()
$标准输出内容 = Get-Content $标准输出日志 -Tail 80 -ErrorAction SilentlyContinue
$错误输出内容 = Get-Content $错误输出日志 -Tail 80 -ErrorAction SilentlyContinue
if ($标准输出内容) { $日志内容 += $标准输出内容 }
if ($错误输出内容) { $日志内容 += $错误输出内容 }
if ($日志内容) {
$日志文本 = $日志内容 -join "`n"
if ($日志文本 -match "Checking input data") { & $更新阶段 "1" "1/8 输入检查" "DarkCyan" }
if ($日志文本 -match "Processing \d+ inputs with") { & $更新阶段 "2" "2/8 预处理与记录构建" "DarkCyan" }
if ($日志文本 -match "Generating MSA|Calling MSA server|MSA server") { & $更新阶段 "3" "3/8 MSA 获取/解析" "DarkCyan" }
if ($日志文本 -match "Tokenizing|Featurizer|Processing .* protein entities") { & $更新阶段 "4" "4/8 特征构建(Tokenize/Featurize)" "DarkCyan" }
if ($日志文本 -match "Downloading|Loading") { & $更新阶段 "5" "5/8 模型与参数加载" "DarkCyan" }
if ($日志文本 -match "Running structure prediction|Predicting") { & $更新阶段 "6" "6/8 结构预测" "Cyan" }
if ($日志文本 -match "Sampling") { & $更新阶段 "7" "7/8 扩散采样" "Yellow" }
if ($日志文本 -match "Writing|predictions|confidence_|plddt_|pae_|pde_") { & $更新阶段 "8" "8/8 写入预测结果" "Green" }
if ($日志文本 -match "Predicting property: affinity|Running affinity prediction") { & $更新阶段 "A" "附加阶段:亲和力预测" "Magenta" }
$最后一行 = $日志内容 | Select-Object -Last 1
if ($最后一行 -match "Loading") { $当前状态 = "正在加载模型参数..." }
elseif ($最后一行 -match "Predicting") { $当前状态 = "正在进行结构预测..." }
elseif ($最后一行 -match "Sampling") { $当前状态 = "正在采样 (这是最耗时的步骤)..." }
elseif ($最后一行 -match "Writing") { $当前状态 = "正在写入结果文件..." }
elseif ($最后一行 -match "Tokenizing") { $当前状态 = "正在处理序列特征..." }
}
Write-Host -NoNewline ("`r[" + $动画字符[$索引 % 4] + "] " + $当前状态 + " ")
$索引++
Start-Sleep -Milliseconds 200
}
Write-Host ""
if ($进程.ExitCode -ne 0) {
$结果目录 = 获取-结果目录 -输出根目录 $输出根目录 -任务名 $当前任务名
$置信度文件 = Get-ChildItem -Path $结果目录 -Recurse -Filter "confidence_*.json" -ErrorAction SilentlyContinue | Select-Object -First 1
$结构文件 = Get-ChildItem -Path $结果目录 -Recurse -Filter "*.cif" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($置信度文件 -and $结构文件) {
Write-Host "提示:Boltz 引擎返回了非零退出码,但检测到已成功生成预测结果,将继续运行。" -ForegroundColor Yellow
return
}
Write-Host "预测过程中出现错误!日志如下:" -ForegroundColor Red
Write-Host "----- 标准输出 -----" -ForegroundColor Yellow
Get-Content $标准输出日志 -ErrorAction SilentlyContinue | Write-Host
Write-Host "----- 标准错误 -----" -ForegroundColor Yellow
Get-Content $错误输出日志 -ErrorAction SilentlyContinue | Write-Host
throw ("预测失败,Boltz 退出码: {0}" -f $进程.ExitCode)
}
} finally {
foreach ($日志路径 in @($标准输出日志, $错误输出日志)) {
if ($日志路径) {
Microsoft.PowerShell.Management\Remove-Item -LiteralPath $日志路径 -ErrorAction SilentlyContinue
}
}
}
}
$已重试修复 = $false
while ($true) {
try {
& $执行单次预测 -boltz路径 $环境.Boltz路径 -命令参数 $参数 -输出根目录 $输出目录 -当前任务名 $任务名
break
} catch {
if (-not $已重试修复) {
Write-Host "检测到运行报错,正在立即重装依赖并自动重试一次..." -ForegroundColor Yellow
$修复成功 = 安装-Boltz依赖 -python路径 $环境.Python路径 -项目目录 $项目目录
if (-not $修复成功) {
throw "自动重装依赖失败,无法继续。"
}
$环境 = 检查-Boltz环境 -项目目录 $项目目录
$已重试修复 = $true
continue
}
throw
}
}
$结果目录 = 获取-结果目录 -输出根目录 $输出目录 -任务名 $任务名
$置信度文件 = Get-ChildItem -Path $结果目录 -Recurse -Filter "confidence_*.json" -ErrorAction SilentlyContinue | Select-Object -First 1
$结构文件 = Get-ChildItem -Path $结果目录 -Recurse -Filter "*.cif" -ErrorAction SilentlyContinue | Select-Object -First 1
Write-Host ""
Write-Host "预测完成!" -ForegroundColor Green
Write-Host ("结果目录: " + $结果目录)
if ($置信度文件) {
Write-Host ("置信度文件: " + $置信度文件.FullName)
try {
$json = Get-Content $置信度文件.FullName -Raw | ConvertFrom-Json
if ($json.confidence_score) {
$分数 = [math]::Round($json.confidence_score * 100, 2)
Write-Host "预测评分 (Confidence Score): $分数 / 100" -ForegroundColor Cyan
}
} catch {
Write-Host "无法读取评分文件。" -ForegroundColor Yellow
}
}
if ($结构文件) { Write-Host ("结构文件: " + $结构文件.FullName) }
Write-Host ""
$打开目录 = 读入-是或否 -提示语 "是否立即打开结果目录" -默认是 $true
if ($打开目录) {
Start-Process -FilePath $结果目录
}
$打开Chimera = 读入-是或否 -提示语 "是否自动打开 ChimeraX 并加载该文件" -默认是 $false
if ($打开Chimera -and $结构文件) {
$chimera路径 = 查找-ChimeraX路径
if ($chimera路径) {
Start-Process -FilePath $chimera路径 -ArgumentList @($结构文件.FullName)
} else {
Write-Host "未找到 ChimeraX 可执行文件(已尝试环境变量、PATH、开始菜单快捷方式和常见安装目录),请手动打开 .cif 文件。" -ForegroundColor Yellow
}
}
Write-Host ""
Write-Host "更详细指南可以参考 https://1037solo/wiki/teach/MedTools/Protein" -ForegroundColor Green
Write-Host "感谢使用本脚本,祝一切顺利!" -ForegroundColor Green
Write-Host ""
}
finally {
Pop-Location
}"此脚本包含自动化环境检测与修复、ChimeraX 自动检测与打开、实时进度动画、多难度模式选择等完整功能。点击右上角「下载」按钮可直接保存为
.ps1文件使用。