一个生物信息项目从“数据下载完成”到“真正可以访问”,中间隔着很长一段工程距离。
原始数据需要清洗、映射、索引、校验;查询逻辑需要从命令行走向可复用服务;服务器部署需要处理路径、权限和安全边界;Web UI 需要在不暴露原始数据库和序列文件的前提下,把复杂数据变成可以浏览、搜索和理解的信息页面。
Human_Genes_Functions 的 Stage 1,就是这样一个从数据工程到在线查询系统的初始闭环。它不是最终豪华版平台,但已经完成了一个很重要的阶段:从本地人类基因功能数据库,推进到可通过浏览器访问的 Web UI,并且通过了功能、安全、截图和文档归档验收。
一、项目目标:不是一个网页,而是一套人类基因知识底座
Human_Genes_Functions 的目标不是简单做一个基因搜索框,也不是把几个文件放到服务器上供下载。它更接近一个长期演进的人类基因功能信息系统。
Stage 1 的目标可以拆成两层。
第一层是数据底座:
- 整理人类基因、转录本、外显子、CDS 等结构信息;
- 整合代表转录本和代表蛋白;
- 建立基因别名、外部 ID 和功能注释;
- 汇总 GO、UniProt、NCBI / RefSeq 等来源的信息;
- 构建可搜索的 SQLite 数据库;
- 支持命令行查询和 FASTA 导出;
- 形成可发布、可校验、可迁移的 server release。
第二层是 Web 入口:
- 提供首页和搜索入口;
- 支持 gene symbol、alias、ENSG、关键词搜索;
- 展示搜索结果;
- 展示基因详情;
- 通过后端生成 FASTA 输出;
- 不让浏览器直接下载 SQLite、FASTA、脚本、manifest 和内部报告。
这两个层次的关系非常重要:
数据库和 FASTA 是系统底座,Web UI 只是受控查询层。
浏览器看到的是查询结果,不是原始数据文件。
二、数据基线:以 GRCh38.p14 与 GENCODE Release 50 为核心
项目的数据基线采用 GRCh38.p14 和 GENCODE Release 50。这个选择决定了后续所有基因、转录本、外显子、CDS、蛋白关系和坐标体系的基础。
GENCODE 层提供的是整个系统的主骨架:
- gene;
- transcript;
- exon;
- CDS;
- gene type;
- transcript type;
- chromosome / seqname;
- start / end;
- strand;
- gene version;
- transcript version;
- protein ID;
- tag;
- HAVANA 信息;
- transcript support level;
- attributes JSON。
这些信息进入 SQLite 后,构成最基础的结构表:
genestranscriptsexonscds
从数量上看,这不是一个玩具数据库。系统中整理了约 78,733 个基因、644,292 条转录本、5,078,384 条外显子记录和 3,210,731 条 CDS 记录。这个规模决定了项目必须认真处理索引、查询入口和发布方式,而不能只靠几个静态文本文件。
在这一层,数据处理的重点不是“展示”,而是把庞大的原始注释转化成结构稳定、可查询、可验证的本地数据库。
三、代表转录本与代表蛋白:让一个基因有可用的默认入口
对普通查询来说,一个基因可能对应多个转录本、多个蛋白和多个外部数据库映射。如果页面只把全部结果堆出来,信息会非常混乱。因此,项目中专门构建了代表转录本和代表蛋白层。
相关表包括:
gene_representative_transcriptsofficial_mane_transcriptsofficial_refseq_select_transcriptsrepresentative_reconciliationrepresentative_sourcesofficial_representative_sourcestranscript_representative_flags
这一层的意义是为每个基因提供一个更适合作为默认展示和 FASTA 导出的入口。它不是简单随机选一个转录本,而是综合官方来源、MANE、RefSeq Select、protein ID 和 fallback 规则进行整理。
这使得 Web UI 可以做到:
- 在 TP53 页面展示代表转录本;
- 在有蛋白编码的基因上提供代表蛋白 FASTA;
- 在 XIST 这类 lncRNA 上清楚显示 protein unavailable;
- 避免用户每次都要手动理解一个基因下几十个转录本的差异。
代表层是从“原始注释数据库”走向“可用知识系统”的关键一步。
四、别名、外部 ID 与跨库映射:让搜索不只依赖标准基因名
真实使用中,用户不会永远输入标准 gene symbol。一个基因可能通过别名、HGNC ID、Ensembl ID、NCBI Gene ID、RefSeq accession、UniProt ID 等方式被提到。
因此项目建立了多个映射层:
gene_aliasesgene_function_annotationsgene_ncbi_mappingsrefseq_transcript_mappingsrefseq_protein_mappingsncbi_genesuniprot_proteins
其中 gene_aliases 覆盖了 HGNC IDs、alias symbols、alias names、Ensembl gene IDs、来源和证据文本。NCBI / RefSeq 映射层则支持 NCBI Gene ID、RefSeq RNA accession、RefSeq protein accession 与基因层摘要之间的关联。
这些映射的价值在 Web UI 阶段变得非常明显。搜索框不能只接受 TP53 这种标准 symbol,也应该逐步支持:
- gene symbol;
- alias;
- ENSG;
- ENST;
- ENSP;
- RefSeq;
- NCBI Gene;
- UniProt;
- 功能关键词。
Stage 1 只实现了第一批入口,但底层结构已经为后续扩展留出了空间。
五、功能注释层:GO、UniProt、NCBI Summary 的整合
项目并不满足于只存储基因结构,还整理了功能信息。关键数据层包括:
- GO annotations;
- UniProt function summary;
- UniProt comments;
- UniProt subcellular locations;
- UniProt keywords;
- UniProt EC numbers;
- NCBI gene summaries。
对应的表包括:
gene_go_annotationsgo_termsgo_annotation_summaryuniprot_function_summaryuniprot_function_commentsuniprot_subcellular_locationsuniprot_keywordsuniprot_ec_numbersncbi_gene_summariesncbi_gene_summary_status
这一层让基因详情页不只是显示坐标和 ID,而能展示更接近“知识”的内容,例如:
- 这个基因参与什么生物过程;
- 对应蛋白有什么功能描述;
- UniProt 是否有功能说明;
- 是否有亚细胞定位;
- 是否有催化活性或 EC number;
- NCBI Gene 中是否有基因层摘要;
- GO 注释属于 biological process、molecular function 还是 cellular component。
例如 TP53 和 MT-ND1 这类 protein-coding gene 可以展示代表蛋白、GO、UniProt、NCBI summary 等丰富内容;而 XIST 是 lncRNA,很多蛋白相关层自然不存在。Stage 1 Web UI 对 XIST 的处理不是报错,而是显示清晰的 unavailable 状态,这反映了底层数据模型对不同 gene type 的兼容。
六、搜索索引:从精确查询走向关键词检索
除了精确查找基因名,系统还构建了搜索文档和全文索引:
gene_search_documentsgene_search_termsgene_search_ftsgene_search_audit
其中 FTS5 表使用 gene_symbol、gene_name 和 search_text 作为搜索字段。它让系统可以从“查 TP53”扩展到“查 DNA repair”这样的功能关键词检索。
这一步非常关键,因为它改变了系统的使用方式。没有全文索引时,用户必须知道基因名;有了搜索索引之后,用户可以从功能概念进入系统。
例如 DNA repair 搜索可以返回数百个匹配结果,并出现 RAD52、XPA、XRCC1、DCLRE1A、XRCC2 等相关基因。这样的搜索入口,才更接近未来“人类基因功能知识平台”的方向。
七、FASTA 资产与后端导出:不能让浏览器直接下载原始文件
项目同时整理了 FASTA 资产,例如代表蛋白和转录本序列相关文件。FASTA 是非常重要的数据资产,但它不应该作为静态文件直接暴露给浏览器。
原因有两个。
第一,原始 FASTA 文件体积较大,不应该被随意直链下载。
第二,用户真正需要的通常不是整个 FASTA 文件,而是某个 gene、transcript 或 protein 对应的片段。
因此 Stage 1 的设计原则是:
FASTA 由后端根据 gene / transcript / protein ID 生成输出,浏览器不能直接浏览原始 FASTA 文件。
这意味着 Web UI 的 FASTA 页面不是一个静态下载目录,而是一个受控导出入口。它需要:
- 验证参数;
- 只允许合法 type;
- 根据基因或转录本解析对应序列;
- 对不可用情况返回清晰提示;
- 限制输出规模;
- 不暴露服务器上的真实 FASTA 路径。
这也是后续安全设计中反复强调 fasta_assets/ 必须 403 的原因。
八、SQLite 数据库:一个可运行的本地知识库
所有处理结果最终汇入 SQLite 数据库。这个数据库大约 8.65GB,是 Web UI 和 CLI 查询系统共同依赖的运行时核心。
它不是简单的表格堆叠,而是一个面向查询组织过的本地知识库。它包含:
- 基因结构层;
- 转录本结构层;
- exon / CDS 层;
- gene summary;
- aliases;
- GO annotations;
- representative transcript;
- NCBI / RefSeq mapping;
- UniProt function;
- search documents;
- FTS5 全文索引。
从 Web UI 的角度看,这个数据库已经具备第一阶段页面所需的查询入口:
- 通过 gene_name 精确查找;
- 通过 gene_id 精确查找;
- 通过 alias 查找;
- 通过代表转录本表读取默认转录本;
- 通过 GO 表读取功能注释;
- 通过 UniProt 表读取功能摘要;
- 通过 NCBI summary 表读取基因描述;
- 通过 FTS5 做全局关键词搜索。
这也是为什么 Stage 1 可以采用 PHP + SQLite 的原因:数据层已经相当完整,Web UI 不需要重建数据,只需要安全、稳定地读取它。
九、CLI 查询系统:Web UI 之前的可验证运行层
在 Web UI 出现之前,项目已经通过 CLI smoke test 验证了核心能力。这些测试包括:
- 搜索
DNA repair; - 查询
TP53; - 查询
MT-ND1; - 导出 TP53 representative transcript FASTA;
- 导出 TP53 representative protein FASTA。
CLI 查询层的重要性在于,它证明数据处理结果不是“生成了一堆文件”,而是已经可以被程序稳定调用。
在后续 Web UI 设计中,CLI 逻辑也成为了概念基础:
- 输入标准化;
- gene lookup;
- representative transcript / protein selection;
- ID version stripping;
- FASTA resolution;
- GO / UniProt / NCBI summary selection;
- 查询结果格式化。
虽然 Stage 1 的 PHP Web UI 并不是简单调用 CLI 脚本,但它复用了 CLI 阶段验证过的查询规则和数据理解方式。
十、发布包:数据系统进入可部署状态
数据处理和 CLI 验证完成后,项目形成了 server release。这个发布包包含:
- SQLite 数据库;
- FASTA 资产;
- scripts;
- manifests;
- reports;
- docs;
- README;
- VERSION;
- placeholder 页面;
- 发布记录和校验材料。
发布包的意义是把本地工程结果冻结成一个可以部署的系统版本。它不是开发目录,也不是临时输出,而是可以同步到服务器、可以做 smoke test、可以归档和回滚的工程产物。
在部署过程中,manifest 和报告文件非常重要。它们让后续排查可以确认:
- 哪些文件属于发布包;
- 大文件是否完整;
- 关键 SQLite / FASTA 文件大小是否一致;
- CLI smoke test 是否通过;
- 发布版本是否可追踪。
这也是项目从“实验性数据处理”转入“工程发布”的标志。
十一、第一次服务器部署:从本地发布包到 HTTPS 入口
服务器部署阶段,最初的目标是把本地 server release 同步到服务器目录,并通过 HTTPS 提供一个 placeholder 页面。
部署时使用了预检、rsync dry-run、正式 rsync、服务器文件检查、CLI smoke test 和 HTTPS 暴露检查等步骤。
正式同步后,服务器端确认:
- 发布包内容已存在;
- CLI smoke test 通过;
- 首页 placeholder 可访问;
- data、scripts、fasta_assets、manifests、reports、docs 等目录访问返回 403。
乍看之下,这似乎已经安全。但进一步检查发现一个关键问题:
目录访问 403,不代表具体文件直链也被禁止。
虽然 /data/ 目录不能列出,但已知路径下的 SQLite 文件仍然可能 200;虽然 /fasta_assets/ 目录不能列出,但具体 FASTA 文件也可能 200;脚本、manifest、report 文件也存在类似风险。
这个问题非常重要。它说明 Web 安全不能只检查“目录列表是否关闭”,还必须检查具体敏感文件路径和 Range 请求。
十二、安全边界:从 .htaccess 误区到 Apache 目录级配置
最初尝试过通过 .htaccess 白名单规则限制访问,只允许首页,其他请求全部拒绝。但服务器 Apache 配置中 AllowOverride None,这意味着 .htaccess 并不是可靠的安全边界。
最终采用 Apache 目录级配置作为真正边界。
安全策略变成:
- 允许
/和 Web UI 必要入口; - 禁止 SQLite / DB 文件;
- 禁止 FASTA 原始文件;
- 禁止 scripts;
- 禁止 manifests;
- 禁止 reports;
- 禁止 docs;
- 禁止 app 目录直接访问;
- 禁止 README / VERSION 等内部文件;
- Range 请求也必须被拦截。
这个阶段的经验非常明确:
.htaccess可以作为辅助,但不能作为核心安全边界。
真正的边界应由服务器配置明确控制。
最终安全验收中,敏感路径全部返回 403,Range 探测也返回 403,CLI smoke test 仍然通过。这说明浏览器访问被限制,但服务器本地读取能力没有被破坏。
十三、Web UI Stage 1 规划:从 placeholder 到真实查询页面
在 CLI 部署安全闭环完成后,项目进入 Web UI Stage 1。
长期愿景是一个界面漂亮、功能丰富、可扩展的人类基因 / 功能 / 疾病 / 性状综合信息系统。但 Stage 1 的目标比较克制:
- 首页;
- 搜索页面;
- 基因详情页;
- FASTA 输出页;
- PHP + SQLite;
- 不引入重型前端框架;
- 不增加登录系统;
- 不做疾病、性状、变异浏览器;
- 不暴露原始 SQLite / FASTA / scripts。
Stage 1 的技术路线选择 PHP + SQLite,原因很实际:
- 服务器已经使用 Apache;
- SQLite 已经是本地运行时数据库;
- PHP 部署简单;
- 不需要额外 daemon;
- 查询层可以做成只读;
- 初始版本更容易审计和回滚。
设计上,Stage 1 虽然是页面优先,但代码结构仍然按未来 API 化方向组织:
SearchServiceGeneServiceFastaExportServiceDatabaseGatewayResultFormatter
页面入口包括:
index.phpsearch.phpgene.phpfasta.php
未来可以扩展出:
api/search.phpapi/gene.phpapi/fasta.php
这使得 Stage 1 不只是一个临时页面,而是后续平台化的第一层。
十四、Web UI 原型:从能查到能看
第一版 Web UI 原型完成后,已经可以:
- 搜索 TP53;
- 搜索 DNA repair;
- 查看 TP53、MT-ND1、XIST 基因详情;
- 输出 TP53 protein FASTA;
- 输出 TP53 transcript FASTA;
- 对 XIST protein unavailable 做提示。
但早期原型仍然带有明显工程痕迹。例如:
- 页面文案还出现 prototype / CLI fallback;
- 搜索结果中
<mark>高亮标签被原样显示; - TP53 详情页布局被长文本拉高;
- XIST 没有 UniProt / protein 时显示不够干净;
- FASTA 页面像临时输出;
- favicon 和子路径静态资源也需要处理。
之后进行了多轮小修:
- 修正文案;
- 修复搜索高亮转义;
- 优化 Gene detail 布局;
- 清理 XIST empty state;
- 改善 FASTA export 面板;
- 控制 unavailable 状态;
- 增加 favicon 支持;
- 重新截图验证。
这个过程说明 Web UI 的价值不仅在于功能跑通,还在于让复杂数据有一个可理解的展示层。
十五、部署策略:完整包还是 overlay
Web UI 准备上线时,出现了一个重要策略问题:本机 Web UI stage 只是一个小发布包,只包含:
index.phpsearch.phpgene.phpfasta.phpapp/assets/favicon.ico
它不包含:
data/fasta_assets/scripts/manifests/reports/docs/- SQLite;
- FASTA。
而服务器正式目录中已经有完整数据资产。如果直接把 Web UI 小包当成完整源目录,并对服务器正式目录执行裸 rsync --delete,就有误删数据目录的风险。
因此部署前必须区分两个概念:
- 完整数据发布包;
- Web UI overlay 小包。
最终选择 overlay 方式:
服务器上的数据资产作为稳定底座保留;
Web UI 小包只覆盖页面、app、assets 等 Web 层文件;
不重传 SQLite 和 FASTA;
不对整个正式目录裸--delete。
这个选择更高效,也更符合管理实际。完整包适合迁移、归档或全新部署;而在服务器数据已经完整且校验一致时,overlay 更适合 Web UI 更新。
十六、上线故障一:路径混淆导致 500
Web UI overlay 后,首页可以访问,但 search、gene、fasta 页面返回 500。
排查发现线上 app/config.php 仍然指向本机或旧发布路径,而不是服务器正式目录。PHP 在服务器上运行时,尝试读取一个服务器上不存在的本机工作区路径,因此报 Database file not found。
修复方式是将 HGF_RELEASE_ROOT 改为服务器正式目录。
这次故障暴露了 AI 协作部署中的一个典型风险:
本机 staging 路径、旧完整发布包路径、服务器正式目录、服务器临时目录必须严格区分。
一旦路径角色混用,Web UI 可能部署成功但运行失败。
路径修正后,PHP 能够找到服务器上的 SQLite 和 FASTA 文件,第一层 500 被解决。
十七、上线故障二:SQLite readonly 错误
路径修正后,search、gene、fasta 页面仍然 500,但错误变成:
attempt to write a readonly database
这说明 PHP 已经找到数据库,但 PDO SQLite 默认连接方式仍然可能尝试写入 journal、WAL 或临时状态。由于数据库和目录是只读的,查询在 PDO->prepare() 阶段就失败了。
这个问题不能通过 chmod 777 或放宽数据目录写权限解决。系统的设计原则就是只读查询,应该让数据库连接方式适应只读部署,而不是让数据目录变得可写。
最终修复方式是使用 SQLite immutable readonly URI:
sqlite:file:<path>?immutable=1
并保留 PDO 的只读打开标记。
这次修复后:
- search.php 不再 500;
- gene.php 不再 500;
- fasta.php 不再 500;
- TP53 / DNA repair / XIST / FASTA smoke test 通过;
- 敏感路径仍然 403;
- 没有 chmod;
- 没有修改数据库;
- 没有修改 Apache;
- 没有重新 overlay;
- 没有重新 rsync 整个 Web UI。
这是整个项目中非常有价值的一次运行时修复。它说明只读数据库部署不是简单地“文件权限设成只读”就结束,还需要数据库驱动层也以真正只读、不可变的方式打开文件。
十八、最终验收:功能、安全、截图和文档
修复完成后进行了最终验收。
功能方面,正常页面全部返回 200:
- 首页;
- index.php;
- TP53 搜索;
- DNA repair 搜索;
- TP53 gene detail;
- MT-ND1 gene detail;
- XIST gene detail;
- TP53 protein FASTA;
- TP53 transcript FASTA;
- XIST protein unavailable 页面。
安全方面,敏感路径全部返回 403:
- SQLite;
- FASTA 原始文件;
- scripts;
- manifests;
- reports;
- docs;
- app;
- README;
- VERSION。
Range 探测也全部返回 403。
此外还生成了线上截图,并用 stat / file 验证截图真实存在。最终生成了:
- 部署结果文档;
- 部署摘要文档;
- 运行时修复文档;
- favicon 修复文档;
- 线上截图目录。
最终状态确认:
Stage 1 Web UI deployed and verified.
这代表项目从数据处理、CLI 查询、服务器部署、安全边界、Web UI、运行时修复到最终验收,已经完成了第一阶段闭环。
十九、favicon 小修:子路径部署中的静态资源细节
最终验收后,还处理了 favicon 不显示的问题。
项目部署在子路径下,因此 favicon link 如果写成 /favicon.ico,浏览器会请求站点根目录,而不是项目目录下的图标。修复方向是:
- 补齐项目目录下的 favicon 文件;
- HTML 中使用相对路径;
- 加上版本参数避免浏览器缓存;
- 同步修复回本机 Web UI stage;
- 不修改 Apache;
- 不 reload;
- 不修改数据库;
- 不重新 overlay 整个 Web UI。
这个问题虽小,但体现了子路径部署中的一个基本原则:
静态资源不要默认项目部署在站点根目录。
相对路径比根路径更适合子路径项目。
二十、AI 协作中的角色分工和边界
这个项目的推进并不是单人手动完成,而是通过用户、ChatGPT 和本机 AI 代理三者协作完成。
ChatGPT 主要承担:
- 架构判断;
- 风险识别;
- 部署策略拆解;
- 自然语言任务组织;
- 根据日志定位错误;
- 在路径混淆时纠偏;
- 在部署失败时收敛排查范围。
AI 代理主要承担:
- 本机和服务器执行;
- 文件同步;
- 代码小修;
- 截图生成;
- 文档生成;
- 执行结果反馈。
用户承担最终控制权:
- 决定服务器路径;
- 纠正不合理的目录设计;
- 判断是否采用 overlay;
- 在 AI 代理无 shell 能力时手动执行取证命令;
- 手动修复关键路径;
- 决定何时停止继续修改,进入归档状态。
这个过程也留下了几个很重要的协作原则:
- AI 代理没有 shell 时,不能假装执行。
- 截图必须用
stat/file验证。 - 本机路径和服务器路径必须写清楚。
- Web UI 小包不能当完整发布包使用。
- 涉及
rsync --delete必须先确认源目录性质。 - 目录 403 不代表文件直链安全。
.htaccess不是可靠安全边界。- 数据库只读错误不能靠 chmod 解决。
- 出现 500 时必须看 error log,不应继续猜。
- 最终状态必须通过功能、安全、Range、截图、文档同时验收。
二十一、这次 Stage 1 真正完成了什么
这次 Stage 1 完成的不是单纯“上线一个网页”,而是一个完整的生物信息工程初始闭环。
它完成了:
- 人类基因结构数据整理;
- 转录本、外显子、CDS 入库;
- 代表转录本和代表蛋白层构建;
- NCBI / RefSeq / UniProt / GO 功能层整合;
- gene alias 与外部 ID 映射;
- FTS5 全文搜索;
- FASTA 后端导出逻辑;
- SQLite 运行时数据库;
- CLI 查询系统;
- server release;
- manifest、reports、docs;
- 服务器同步;
- HTTPS placeholder;
- 敏感直链暴露修复;
- Apache 目录级访问控制;
- Web UI Stage 1;
- overlay 部署;
- config 路径修复;
- SQLite immutable readonly 修复;
- favicon 修复;
- 最终验收和截图归档。
从工程意义上看,这标志着项目已经从“本地数据处理成果”变成“可访问、可验证、可继续扩展的在线系统”。
二十二、下一阶段:从基因查询走向生物医学知识平台
Stage 1 之后,不适合立刻继续频繁改服务器。更合理的方式是先冻结当前成功状态,再规划 Stage 2。
Stage 2 可以考虑:
- 更好的搜索排序;
- 疾病模块;
- 性状模块;
- 变异信息;
- 文献引用;
- 通路信息;
- 多基因比较;
- gene dashboard;
- JSON API;
- 高级筛选;
- 后端缓存;
- 更完整的版本发布流程;
- 更稳定的测试与回归脚本。
但这些都应该建立在 Stage 1 当前稳定状态之上。
Stage 1 的价值在于,它证明了这条路线是可行的:
大规模本地人类基因数据库
可以通过只读、安全、受控的方式
转化成一个可访问的 Web 信息系统。
结语
Human_Genes_Functions Stage 1 的完成,不只是一次部署成功,也不只是一个网页上线。它是一条从数据处理到服务上线的完整工程链路:
原始注释进入结构化数据库;
跨库功能信息被整合;
搜索索引被建立;
CLI 查询证明数据可用;
发布包让系统可迁移;
服务器部署让系统可访问;
Apache 边界保护敏感资产;
Web UI 让数据进入浏览器;
运行时修复让系统稳定;
最终验收让阶段状态冻结。
这就是一个数据项目从“有数据”走向“有系统”的过程。
最终状态:
Human_Genes_Functions Web UI Stage 1 deployed and verified.