乐于分享
好东西不私藏

如何用 AI 对话创制一个基因组坐标转换 Skill 并发布到 GitHub

如何用 AI 对话创制一个基因组坐标转换 Skill 并发布到 GitHub

       玉米基因组研究中有两个主要参考基因组版本——B73 RefGen v4 和 NAM 5.0。我们手头有一批标记位点的坐标是 v4 版本的,但下游分析和数据整合需要 v5 坐标。也就是说,我需要把若干SNP 位点从一个参考基因组"搬"到另一个上。

这个需求在生物信息学中叫做 liftOver,通常的做法是下载 UCSC 的 liftOver 工具,写命令行,折腾半天。但这次我想试一种完全不同的路径:用 AI 对话完成从需求到工具的全过程

整个过程不需要我写一行代码。我只需要用自然语言告诉 WorkBuddy 我要什么。

第一步:从文件到文件,一个直接的需求

我手上有一个叫 提取位点_v4.txt 的文件,内容长这样:

3_1982836743_1982863305_218715633...

同时我告诉 WorkBuddy chain 文件在哪里。chain 文件是 UCSC 格式的基因组比对文件,记录了 v4 和 v5 之间的坐标对应关系。

我的第一句话就是:

把 提取位点_v4.txt 中的位点转换为 v5 版本

WorkBuddy 做了几件事:

  • 自动读了 chain 文件的格式,理解了它的结构(头部记录染色体、起止位置、方向,后面的数据行是对齐块的大小和偏移量)
  • 写了一个 Python 脚本,解析 chain 文件,对每个位点遍历对齐块,找到对应坐标
  • 运行脚本,16 个位点全部成功转换

整个过程不到两分钟。

转换原理:chain 文件到底在干什么

chain 文件本质上是一个坐标映射表。它的每一段对齐块告诉你:v4 基因组上从位置 A 到位置 A+size 这一段,对应 v5 基因组上从位置 B 到位置 B+size 这一段。两段之间如果有 gap(插入或缺失),文件里会记录 dt 和 dq 两个值,分别表示 v4 和 v5 上的跳跃量。

脚本做的事情就是:拿到一个 v4 位置 → 找到它落在哪个对齐块里 → 算出相对偏移 → 映射到 v5 的对应位置。如果这个位置恰好落在两个对齐块之间的 gap 里,就标记为 UNMAPPED。

这里有一个容易出错的细节:chain 文件可能有多条 chain 覆盖同一个区域。如果一个位置在第一条 chain 里落在 gap 中,应该继续尝试第二条 chain,而不是直接返回失败。这是我们后面调试时发现的一个潜在 bug。

第二步:从脚本到 Skill,让 AI 记住一切

转换做完了,但我不想下次再重复这个过程。我希望这个能力变成一个可复用的"技能"——下次只需要一句话就能触发。

于是我跟 WorkBuddy 说:

把基因组位置转换过程写成一个 skill

WorkBuddy 按照 Skill Creator 的标准流程,自动完成了:

  • 创建了 maize-genome-liftover 目录结构
  • 把刚才写的两个转换脚本放进了 scripts/ 目录
  • 把 chain 文件放进了 assets/ 目录(这样 skill 是自包含的,换个电脑也能用)
  • 写了 SKILL.md,定义了触发词("liftover"、"v4 to v5"、"坐标转换"等)

这个 Skill 建好之后,双向转换只需要一句话:

v4 to v5

或者反过来:

v5 to v4

第三步:调试——让 AI 自己找 bug

第一次跑 v5→v4 时,16 个位点里有两个失败了,标记为 UNMAPPED。

我当时直接问:

为什么两个位点无法映射?

WorkBuddy 的调试过程是这样的:

首先检查 chain 文件里染色体 7 的覆盖范围,发现确实有一条 chain 覆盖了这个区域。但进一步追踪发现,这个位置落在 chain 内部一个 27Mb 的大 gap 里——这是一个真实存在的组装差异,v5 的这部分序列在 v4 中没有对应区域。

但接着 WorkBuddy 又发现了一个更严重的问题:chain 文件里有第二条 chain 也覆盖了这个位置,而且没有 gap!为什么脚本没用第二条 chain?

一查代码,发现了 bug:函数在第一条 chain 失败后直接返回 None,不会尝试后续的 chain。这是一个典型的"只取第一条"的过早返回问题。

AI 自己定位了 bug、解释了原因、修复了代码、重新测试,两个位点成功映射。

整个过程我只需要问一句"为什么没映射",AI 自己完成了从诊断到修复的全流程。

第四步:打磨细节,让工具更合理

修完 bug 后,我又提了改进需求:

chr 前缀保持一致

输入文件可能带 chr 前缀(chr3_198283674),也可能不带(3_198283674)。输出应该和输入保持同一风格。两个脚本都加上了这个逻辑。

每一次修改都只需一句话。

第五步:发布到 GitHub

Skill 改好后,我想把它开源:

把这个 skill 同步到我的 GitHub 仓库

WorkBuddy 自动找到了我的 GitHub 账号,创建了新仓库 maize-genome-liftover,初始化了 git,commit 了所有文件。

推送时网络有点问题,我授权后它就重试成功了。

然后我又说:

写好说明文件,licence 选择 GNU General Public License v3.0

它写了中文 README(包括安装方法、WorkBuddy 对话使用示例、文件结构),添加了 GPL v3.0 许可证,推送到 GitHub。

我再提了一句:

说明文件中的使用方法不要写 bash,写在 WorkBuddy 中的对话示例

它立刻把 README 中的命令行改成了自然语言对话示例。这才是这个工具真正的使用方式——不需要记命令,说话就行。

总结:AI 对话创制工具的几个关键经验

回顾整个过程,有几个值得记录的经验:

一、从具体需求出发,不要一开始就想"做工具"

我没有说"帮我写一个通用的 liftOver 工具",而是说"把我这个文件里的位点转成 v5 版本"。先解决眼前的问题,工具在解决问题的过程中自然长出来。等脚本跑通了再说"把它变成一个 skill"。

二、让 AI 自己调试

当结果不对时,不要自己去翻代码,直接问"为什么这个不对"。AI 能从数据里反向追踪原因,定位代码 bug。在 chain 文件的 gap 问题上,它甚至发现了两个独立的 bug(正则表达式错误和过早返回),一次性修完。

三、从脚本到 Skill 的价值在于"自包含"

把 chain 文件打包进 assets/,让 skill 不依赖外部路径。换个项目、换台电脑,skill 拿过去就能用。这是"一次性投入,长期收益"的关键一步。

四、发布时注意文档的受众

README 里写 bash 命令给程序员看没问题,但如果是skill,真正的用户是在对话框里说话的人。所以要把使用说明写成对话示例——"把 v4 位点转 v5"——而不是 python scripts/liftover_v4tov5.py --input xx


从需求提出到 GitHub 发布,这其中我写过的代码:零行。我做过的事:用中文对话,描述需求,确认结果,提修改意见。

想使用这个skill的同学请直接自取,仓库地址

https://github.com/JustineJiao/maize-genome-liftover/