核心问题:发酵DoE为什么需要一个agent技能
发酵工艺优化(fermentation DoE)是生物制造中最昂贵、最不可逆的环节之一。一次2L生物反应器批次可能耗时5-7天,耗材成本数千元,而一次错误的实验设计——比如漏掉了关键交互项、在错误的scale上做优化、或者用了一个无法检测的assay——意味着整周产能被浪费。
传统的DoE工具(JMP、Minitab、Design-Expert)解决了统计设计问题,但它们有三个根本性的盲区:
| 盲区 | 后果 |
|---|---|
| 不检查readiness | 生成了一个漂亮的CCD设计,但assay还没建立、scale bridge没做、historical ledger是空的——设计在数学上正确,在实验上不可执行 |
| 不管理长期状态 | 第一轮batch的结果散落在Excel和ELN里,第二轮设计时agent无法自动读取prior results、无法做sequential augmentation、无法保留negative-result memory |
| 不与agent harness集成 | 无法被Claude Code、Codex CLI这类编码代理直接驱动;无法在CI里跑preflight;无法fan-out到并行sub-agent做文献综述和evidence ingestion |
BioSymphony Ferm DoE的回答是:把整个发酵DoE生命周期建模成一个agent可读写的durable artifact。这个artifact就是 campaign_manifest.json——一个JSON文件,记录了目标、响应、因子、约束、scale context、决策规则、证据、可行性,以及每一轮batch的状态。任何能读文件、跑shell命令的agent harness都能拾起这个技能,驱动战役从intake走到follow-up。
设计哲学:状态活在一个文件里,不在agent的对话上下文里。这意味着会话可以暂停、恢复、在agent之间交接、在agent和人之间交接。同一个 ferm-doe validate 命令在笔记本上、在CI里、在AWS Lambda后面跑出来的结果完全一致。
架构全景:一个manifest,九个门控
整个系统的核心循环可以用README里的那张mermaid图概括:
关键在于:agent不是直接跳到"生成设计"这一步。它必须先通过 validate --summary 这个readiness门控。门控会检查9个独立的gate,每个gate返回一个score和一组issues(blocker或warning):
| Gate | 检查内容 | 失败后果 |
|---|---|---|
contract |
manifest schema完整性、profile声明的required_blocks是否齐全 | blocker |
data_trust |
historical_run_ledger的 provenance、QC标记、异常值 | blocker/warning |
factor |
因子定义完整性、范围合理性、mixture因子是否sum-to-1 | blocker/warning |
response |
响应定义、assay method是否声明、检测限/线性范围 | blocker/warning |
assay |
assay readiness——响应是否真的可测、方法是否验证 | blocker |
assay_power |
统计功效——给定n和噪声,能否检测到声明效应 | warning |
feasibility |
设备产能、试剂库存、时间窗口是否支持设计规模 | blocker/warning |
cost_time |
预算与周期是否在decision_rules声明的边界内 | warning |
mode_transfer |
scale-transfer模式——bridge criteria是否声明、是否qualified | blocker/warning |
这9个gate的score取平均,结合blocker/warning计数,输出三态:
Readiness门控:RED/YELLOW/GREEN三态决策
readiness评分的核心逻辑在 readiness.py 的 score_campaign_readiness 函数里。它不只是一个分数——它是一个决策路由器:
三态的语义是严格的:
- RED:存在blocker。Agent不允许生成设计、不允许进入run packet阶段。必须先修复failed checks,重新跑validate。这是硬约束——
NON_CLAIMS.md明确声明:readiness gate在lab work之前验证measurement readiness、manifest结构、profile fit,但它不验证实际lab测量,除非result rows带着provenance和QC evidence被ingest进来。 - YELLOW:没有blocker但有warning,或者score低于0.82。Agent可以继续,但run packet会标注"planning only"。所有public demo都停留在YELLOW——因为它们是synthetic planning fixture,不是executed lab evidence。这是一个诚实的设计:demo不会假装自己是validated campaign。
- GREEN:所有axis清零,score ≥ 0.82,无warning。这是"值得跑"的状态——agent可以生成设计、分析结果、规划follow-up,run packet不带planning-only caveat。
这个三态系统的价值在于:它把"这个实验设计能不能跑"这个判断从agent的LLM推理里拿出来了,变成了确定性的代码判断。Agent不需要"觉得"一个设计ready了——代码会告诉它。这和ScholarLoop的"LLM只做开放式推理,一切可验证的都由代码执行"是同一个哲学。
Profile注册表:9种发酵战役模板
发酵工艺优化不是一个 homogeneous 的问题。screening一个新菌株的active factors、用RSM找一个optimum、优化media blend、做fed-batch的split-plot、从shake flask scale-up到2L、build一个scale-down model、做confirmation runs、sequential augmentation——每一种都是不同的战役,需要不同的required blocks、advised blocks、DoE家族。
BioSymphony用9个profile把这些战役模板化。每个profile在 profiles.py 的 PROFILE_REGISTRY 里声明:
| Profile | required_blocks | advised_doe_families |
|---|---|---|
screening |
无(permissive) | DSD, PB, fractional factorial |
optimization_rsm |
responses, factors | CCD, Box-Behnken, optimal I |
mixture |
factors(至少一个mixture类型) | Scheffé, extreme-vertices |
split_plot_fed_batch |
responses, factors(需hard-to-change因子) | split-plot |
scale_up_bridge |
scale_context(direction=scale_up) | DSD, CCD, Box-Behnken |
scale_down_qualification |
scale_context + recapitulation_criterion | full factorial, DSD |
confirmation |
无 | custom constrained, full factorial |
sequential_augmentation |
doe(需previous_wave_ref) | sequential augmentation, optimal D/I |
custom |
用户自定义 | 用户自定义 |
关键设计:required_blocks 缺失会触发blocker(RED),advised_blocks 缺失只触发warning(YELLOW)。这意味着profile是composable的——一个scale_up_bridge战役可以同时advised arms(多臂结构)和risk_register,但即使你没有arms,它也不会RED,只会YELLOW提醒你"建议加arms做reference+target对照"。
一个特别值得注意的profile是 split_plot_fed_batch。Fed-batch发酵有hard-to-change setpoints(whole-plot,比如温度设定值,改一次要等整个batch)和easy-to-change media(sub-plot,每次run可以换)。传统DoE工具经常错误地用fully randomized design处理fed-batch,导致伪自由度和错误的F检验。BioSymphony在profile层面就要求 factor_hard_to_change_required: True,从源头防止这个统计错误。
DoE家族选择器:14种设计家族与最小运行数
选对DoE家族是发酵DoE的核心决策。BioSymphony在 doe_families.py 的 FAMILY_REGISTRY 里维护了14种家族,每种都带minimum-runs guidance、是否支持quadratic curvature、是否支持two-factor interactions、typical use case:
| 家族 | min_runs | quadratic | 2FI | 典型用途 |
|---|---|---|---|---|
| definitive_screening | 2k+1 | ✅ | partial | ≤10因子筛选,怀疑曲率 |
| plackett_burman | next_mult_4(k+1) | ❌ | ❌ | 极低资源主效应筛选 |
| fractional_factorial | 2^(k-p) | ❌ | depends(res) | 4-8因子筛选到优化过渡 |
| full_factorial | ∏levels | depends | ✅ | ≤4因子或categorical-heavy |
| central_composite | 2^k+2k+n_c | ✅ | ✅ | 筛选后RSM优化 |
| box_behnken | 2k(k-1)+n_c | ✅ | ✅ | 角点不可行时的RSM |
| optimal_d / optimal_i | model_terms+n_c | model-dep | model-dep | 非标准约束下的计算机生成设计 |
| scheffe_mixture | — | ✅ | ✅ | media/feed blend优化 |
| extreme_vertices_mixture | — | ✅ | ✅ | 带约束的mixture |
| split_plot | — | ✅ | ✅ | fed-batch hard/easy-to-change |
| sequential_augmentation | — | — | — | 基于prior wave结果增补 |
| custom_constrained | — | — | — | 用户自定义约束 |
这个taxonomy的价值不只是参考——它会驱动warning。如果一个campaign声明了 optimization_rsm profile但选了 plackett_burman(不支持quadratic),validator会发出warning:"RSM优化建议CCD或Box-Behnken,PB无法拟合曲率"。同样,如果设计的run数低于家族的 min_runs_formula,会触发minimum-runs shortfall warning。
这里有一个重要的诚实声明:doe_families.py 的docstring写的是 "Conservative; deeper analysis is a statistician's job." BioSymphony不替代统计学家——它提供一个保守的、不会犯低级错误的起点,把需要专业判断的留给人类。
适配器路由:47工具注册表与优雅降级
BioSymphony最工程化的部分是它的适配器层。发酵DoE的backend landscape极其碎片化:BoFire(BASF的Bayesian optimization框架)、BoTorch(Meta的Gaussian process + acquisition)、ENTMOOT(树模型优化)、OMLT(可微分ML优化)、TabPFN(表格foundation model)、pyDOE3(经典设计)、SALib(敏感性分析)、scipy(统计检验)……没有一个工具能cover所有场景。
BioSymphony的解决方案是 docs/TOOL_REGISTRY.md 和 docs/tool-registry.json——一个curated的47工具注册表,每个工具标注claim level和route reason。运行时,adaptive_backend_surface 让BoFire、BayBE、Ax/BoTorch、ENTMOOT、OMLT、TabPFN在同一套design preflight checks后面竞争。
关键设计模式是优雅降级。以BoFire适配器为例:
每个适配器都用 importlib.util.find_spec 检查可选依赖是否存在。如果BoFire没装,is_available() 返回False,系统回退到deterministic local planning(stdlib DoE),并在routing decision里标注"bofire not installed, fell back to stdlib"。这意味着:
- 公共包是stdlib-only的——
pip install biosymphony-ferm-doe不拖任何重依赖,开箱即用 - 可选依赖按需安装——
pip install "biosymphony-ferm-doe[bofire]"才启用BoFire路由 - 降级是显式的——routing decision JSON里会写明
should_route: false, reason: "bofire not installed",agent和人都看得见
路由决策本身是有逻辑的。BoFire适配器的 routing_decision 检查四个route reason:
只有当campaign确实有non-box constraints、多目标响应、或scale fidelity结构时,系统才会建议路由到BoFire。否则stdlib DoE就够了——不需要为了一个简单的screening design拖入整个Bayesian optimization栈。
一个特别值得注意的已知陷阱记录在AGENTS.md里:当BoFire的 SoboStrategy 配合 NChooseK 约束时,上游issue #450会无限stall。BioSymphony的应对是路由到ENTMOOT v2或enforce cardinality post-hoc——这是一个被代码固化下来的运维知识,而不是留给agent去"发现"的坑。
Scale-bridge:kLa、P/V、tip-speed的资格认证
发酵工艺最危险的错误之一是在错误的scale上做优化。shake flask里的最优条件到了2L可能完全失效——因为kLa(体积氧传质系数)、P/V(单位体积功率)、tip speed(叶尖速度)、mixing time、OUR(氧摄取速率)、RQ(呼吸商)、VVM(每分钟通气体积比)这些工程参数随scale非线性变化。
BioSymphony的 scale_context block和 bridge.py 模块解决这个问题。一个scale-bridge战役需要声明:
- from_scale / to_scale 的工程目标值(kLa、P/V、tip speed等)
- bridge_strategy.primary_criterion——以哪个参数为主匹配
- bridge_factors 分三类:
transferable(可直接迁移)、needs_retuning(需重新调参)、not_applicable(目标scale不适用)
compute_bridge_qualification 函数会在 to_arm(目标scale)生成qualification design:把criterion target固定在engineering recipe值,emit center-point replicates(和可选的factor perturbations),让操作员对比recapitulation是否达成。
关键在于claim level的诚实。bridge.py 的 CLAIM_LEVEL = "bridge_qualification_planning",NON_CLAIM 明确声明:
"Bridge qualification is a planned design at the target scale. It does not establish that the small or large scale recapitulates the other until executed runs satisfy the manifest's recapitulation_criterion with provenance."
也就是说:BioSymphony可以规划一个scale-bridge的qualification design,但它不会声称bridge已经qualified——除非你真的跑了那些runs,结果满足manifest里声明的recapitulation criterion,并且带着provenance被ingest回来。这是一个planning→qualification→evidence的三阶段诚实链。
工程数学本身委托给 scale_recipe.compute_scale_recipe,保证 ferm-doe scale-recipe 子命令和bridge qualification用的是同一套criterion-matched setpoint推导。这避免了"CLI算一遍、bridge算一遍、结果不一致"的bug。
成本诚实栈:五个数字,不许只报一个
生物制造的cost modeling是一个充满自我欺骗的领域。一个常见的失败模式是:有人报一个"simulator number"(理论最优条件下的yield × 理论单价),然后假装这就是COGS。BioSymphony用 docs/COST_MODEL_REALISM_CHECK.md 和 templates/cost_stack.template.md 强制一个五层数字栈:
| 层级 | 含义 | 为什么单独不够 |
|---|---|---|
| Simulator number | 理论最优条件下的yield × 理论单价 | 假设100%收率、无批次变异、无下游损失 |
| Bulk reagent number | 大宗试剂成本(培养基、补料、前体) | 不含人工、设备折旧、耗材 |
| Fully-loaded shake-flask COGS | 含人工、耗材、设备分摊的完整shake-flask成本 | shake-flask ≠ 生产scale,不能外推 |
| CMO benchmark | 合同制造组织报价基准 | 反映市场价但可能含/不含不同scope |
| Stated range | 显式声明的不确定区间 | 承认成本本身有分布,不是点估计 |
这个设计的核心信念是:一个数字说不了真话,五个数字才能三角验证。如果simulator number和CMO benchmark差10倍,那中间一定有一个假设是错的——而BioSymphony要求你把五个数字都摆出来,让矛盾可见。
Scientific Swarm与cumulative dossier
对于复杂的campaign,BioSymphony支持 Scientific Swarm 模式——一个per-corpus的swarm plus integrator plus harvester的cumulative dossier pattern。这不是ad-hoc的并行dispatch,而是一个有结构的证据累积工作流。
Swarm模式的核心是 swarm.py 维护的一组dossier文件:
Evidence table的schema是结构化的——每一行证据带 lane_id、source_type、source_ref、source_trust、license、extraction_method、agent_id、review_status、claim_type、entity_type、claim、factor_or_response、suggested_action、suggested_role、phase、effect_direction、severity……这意味着每一条证据都是可溯源的——你知道它从哪来、谁提取的、review状态如何、建议什么action。
关键设计原则在AGENTS.md里写得很清楚:One coherent dossier per campaign(CITATIONS.json、NOTES.md、SOURCES.bib、per-corpus EVIDENCE.csv),不是N个isolated reports。Bounded workers(并行sub-agent、swarm corpora、integrator和harvester角色)通过 task_request contract协调,不是ad-hoc dispatch。
这个pattern的价值在于negative-result memory。传统DoE工具的第一轮结果和第二轮设计之间是断裂的——第二轮的agent不知道第一轮哪些因子被证明无效。BioSymphony的cumulative dossier让每一轮的evidence、assumption attack、observability plan都持久化,下一轮的agent可以直接读取,避免重复验证已知无效的因子。
设计锦标赛:多候选方案的裁决
当readiness通过后,BioSymphony不是直接生成一个设计——它运行一个 design tournament(tournament.py)。run_design_tournament 会:
- 调用
propose_candidate_designs生成多个候选设计(不同DoE家族、不同run budget) - 对每个候选调用
score_candidate评分 - 如果Scientific Swarm启用,先
ensure_swarm_review把swarm的evidence-backed factor roles、assumption safety、observability、control strategy纳入评分 - 如果campaign arms启用,走per-arm tournament(每个arm独立裁决)
- 在accepted候选里选
total_score最高的作为selected design
裁决策略(adjudication_policy)是显式声明的,有四条规则:
- 不把skeptical audit lane选为executable design——audit lane是用来挑刺的,不是用来跑的
- readiness为RED时拒绝所有executable designs——硬约束,不可覆盖
- 优先feasible、assay-ready、mode-aware的设计,而非纯统计score——一个统计score最高但assay没ready的设计不该被选
- Scientific Swarm启用时,优先align with evidence-backed factor roles、assumption safety、observability、control strategy的设计
这个设计的深层逻辑是:统计最优 ≠ 实验最优。一个D-optimal设计可能在数学上最优,但如果它要求的run数超出了试剂库存,或者它的某个因子组合在prior evidence里已被证明无效,那它就不该被选。Tournament把这个多维度tradeoff显式化,而不是留给agent去"感觉"。
声明边界:它不声称什么
BioSymphony最值得尊敬的设计是它的 NON_CLAIMS.md 和贯穿全代码库的claim level标注。在一个充斥着"AI优化发酵工艺""智能实验设计"这类营销话术的领域,BioSymphony明确声明它不做什么:
Claim Boundaries:本仓库在lab work之前验证measurement readiness、manifest结构、profile fit。它不验证实际lab测量,除非result rows带着provenance和QC evidence被ingest进来。
不声称optimized、validated、production-ready、或GxP-ready行为。
每一个适配器都带 CLAIM_LEVEL 和 NON_CLAIM 常量。BoFire适配器声明 CLAIM_LEVEL = "bofire_adapter_planning",并明确:"BoFire-backed candidates are planned model-based suggestions. They do not validate assay readiness, scale transfer, or physical execution." Bridge模块声明 CLAIM_LEVEL = "bridge_qualification_planning"。这些claim level会写进run packet——操作员和reviewer看到的不是"优化设计",而是"planning support, claim level: X"。
这不仅是法律意义上的cover-your-ass。这是一个认识论设计:系统在每一个输出上都标注自己的认知边界,防止下游(agent或人)把planning support误读为validated result。在一个"AI说它优化了"就可能被当成真优化的时代,这种自我标注是稀缺的工程美德。
另一个关键边界是public safety。AGENTS.md列出了一系列"Do not add":private strain details、unpublished sequences、customer batch records、confidential media formulations、API keys、private workstation paths、private issue-tracker IDs、raw private campaign artifacts。所有public demo都是synthetic或public-source的,并显式标注"synthetic"。这意味着这个仓库可以被审计、被fork、被CI测试,而不会泄露任何真实campaign的敏感信息。
对生物制造AI化的启示
BioSymphony Ferm DoE代表了一种我认为被低估的AI-for-science范式:不是用LLM替代领域专家,而是用LLM驱动一个领域专家设计的确定性harness。它的价值不在"AI更聪明",而在:
- 状态持久化:发酵战役跨越数周数月,传统工具的状态活在人的脑子里和散落的Excel里。BioSymphony把状态活在一个可读写的JSON里,agent和人都可读写、可审计、可交接。
- readiness前置:不是在生成设计后才发现assay没ready,而是在生成设计前就用9个gate阻断。这把"设计正确但不可执行"的失败模式从源头消灭。
- claim标注:每一个输出都带claim level,防止planning被误读为validation。在一个AI容易过度声称的时代,这是认识论层面的工程纪律。
- 优雅降级:47工具注册表不是"全装上才好用",而是"stdlib开箱即用,可选依赖按需启用,降级显式可见"。这让公共包轻量、可审计、可CI。
- negative-result memory:cumulative dossier让每一轮的evidence和assumption attack持久化,下一轮不重复验证已知无效的因子。
对比那些"用一个LLM agent跑整个发酵优化"的demo项目,BioSymphony的路径更慢、更重、更不性感——但它更接近真实生物制造R&D的工作方式。真实的发酵DoE不是一个prompt-to-design的魔法,而是一个intake→readiness→design→execute→analyze→follow-up的长期循环,中间有无数的门控、交接、negative result、scale transfer陷阱。BioSymphony把这些都建模了,而不是假装它们不存在。
对于想用AI做生物制造工艺开发的团队,BioSymphony提供了一个可借鉴的架构蓝图:把领域知识固化成profile registry和DoE family taxonomy,把工程约束固化成readiness gate,把工具碎片化解决成adapter registry with graceful degradation,把长期状态固化成durable manifest,把认知边界固化成claim level标注。这套架构不依赖任何特定LLM——任何能读写文件、跑shell的agent harness都能驱动它。
一句话总结:BioSymphony Ferm DoE不是"用AI做发酵DoE"——它是"给发酵DoE的领域知识套上一个agent可驱动的确定性harness"。状态活在一个文件里,readiness由代码判定,claim level自我标注,工具栈优雅降级。这是2026年生物制造AI化应该有的样子:不是更聪明的LLM,而是更诚实的工程边界。
项目信息
仓库:BioSymphony/ferm-doe(MIT License,pre-alpha)
语言:Python 3.10+,运行时stdlib-only,可选extra路由到BoFire/BoTorch/ENTMOOT等
测试:455 tests pass,38 expected skips(可选依赖未装时的优雅降级)
部署:AWS Lambda和Modal scaffold,同一命令跑在笔记本/CI/云endpoint
Agent harness兼容:Symphony with Linear、Claude Code with Linear、Codex CLI、OpenAI Agents SDK、自定义orchestrator
核心artifact:campaign_manifest.json(durable state,pause/resume/handoff)
Profile数:9(screening、optimization_rsm、mixture、split_plot_fed_batch、scale_up_bridge、scale_down_qualification、confirmation、sequential_augmentation、custom)
DoE家族数:14
工具注册表:47个BO/DoE和sidecar工具
Public demo数:12个campaign-shaped demo + adaptive-backend-eval + starter-studies
注:本文基于BioSymphony Ferm DoE仓库的公开代码、README、AGENTS.md、SKILL.md和源码分析撰写。所有引用的代码片段和设计声明均锚定于仓库实际文件。仓库状态为pre-alpha,public demo均为synthetic planning fixture,不构成lab-validation或production-readiness声明。