☰
Scientific Agent Skills:科研AI助手技能包搭建指南
2026/10/23 5:35:39 网站建设 项目流程

做科研的人大概都有过这种体验:一个课题做三个月,真正花在“想问题”上的时间可能不到三成,剩下七成全耗在重复动作上——翻文献、对格式、重跑一遍不知道哪里出错的脚本、把同一张图按不同期刊要求导出五个版本。这两年命令行 AI 编程助手火了,Codex、Claude Code 这类工具能读文件、能执行命令、能改代码,很多人第一反应就是“那我是不是可以让它帮我干这些活”。试过之后多数人的结论是:能干一点,但不敢信。它跑得挺欢,结果经不起核对。问题不在模型本身,而在于你丢给它的是一个光秃秃的会话窗口,里面没有任何关于“你们这个领域该怎么干活”的约束。Scientific Agent Skills 想解决的正是这一层——把科研流程里那些固定的动作、规范、检查项,写成 AI 助手能够按需加载的技能包,让 Codex、Claude Code 从“会写代码的聊天机器人”变成“知道规矩的科研助手”。下面这套东西,我在几个数据分析型项目里反复打磨过,从目录怎么摆、技能文件怎么写,到脚本怎么防跑飞、结果怎么验证,都是可以直接抄的结构。适合两类人看:一类是有一定编程基础、想把 AI 真正嵌进研究流程的研究生和博后;另一类是带学生、希望把实验室的隐性规范固化成工具链的导师。

1. 先搞清楚:科研助手缺的到底是能力还是规矩

1.1 从“能聊天”到“能干活”,中间隔着什么

很多人对 AI 助手的失望,来源于一个错误预期:以为它读得懂论文、写得出代码,就该能直接接手科研任务。实际用下来你会发现,它确实读得懂、写得出,但它不知道该按什么顺序读、按什么标准写。举个最常见的场景:你让它处理一批实验数据,它会很自然地写出一段 pandas 代码,跑出均值、标准差、p 值,然后给你一段通顺的解释。看起来很完美,问题在于——它没有做正态性检验就上了 t 检验,没有记录随机种子,没有保存中间结果,也没告诉你它把缺失值悄悄 drop 掉了。这套操作在代码层面完全正确,在科研层面完全不合格。

这就是关键差异。编程助手优化的是“代码能不能跑通”,科研助手要优化的是“结论能不能经得起复核”。前者是能力问题,后者是规矩问题。而规矩这件事,恰恰是通用大模型最缺的,因为它不在训练语料的显眼位置——没人会把“我们实验室处理离群值必须先画箱线图再决定”这种话写进公开文档。

Scientific Agent Skills 的思路,就是把这些规矩从人的脑子里、从实验室的口口相传里抠出来,写成文件,放进项目目录,让 AI 在需要的时候自己去读。它不是什么新框架,本质上就是一套约定:用固定目录结构组织领域知识,用元数据告诉模型“什么时候该用我”,用脚本把易错操作固化下来。Codex 和 Claude Code 这类工具本身支持读取工作目录下的文件、按指令执行命令,这就给了技能包落地的土壤。

我建议你先接受一个前提:不要指望一次对话解决一个课题。把 AI 助手当成一个刚进组的、手很快但不懂规矩的新人,你的任务是给它写一份足够细致的 SOP,而不是指望它天生懂事。

1.2 一个技能包的目录长什么样,为什么这么设计

技能包的组织方式,我试过三种:全塞进一个大提示词、写成单个长 Markdown、拆成目录按需加载。前两种都死在同一个地方——上下文。你把实验室三年的规范全写成两万字提示词,模型每次对话都要吃掉这两万字,真正留给数据的内容所剩无几,而且它对这么长的文本注意力是衰减的,越靠后的规则越容易被忽略。

目录式方案是目前最稳的。一个技能一个目录,结构大致是这样:

skills/ ├── lit-review/ │ ├── SKILL.md │ ├── scripts/ │ │ └── dedupe_refs.py │ └── references/ │ └── screening_rules.md ├── stat-analysis/ │ ├── SKILL.md │ └── scripts/ │ ├── assumption_check.py │ └── report_stats.py └── figure-export/ ├── SKILL.md └── scripts/ └── export_figure.py

SKILL.md是入口,里面分两部分:文件头的元数据(名称、一句话描述),和正文的详细说明。关键在于加载是分层的——模型一开始只看到所有技能的“名称 + 一句话描述”,判断当前任务需要哪个技能,才会去读那个技能的完整正文;正文里如果提到某个脚本,它再去读脚本。这套机制通常叫渐进式披露,好处很直接:你有二十个技能,日常对话的上下文开销也只相当于二十行描述,而不是二十篇文档。

注意:这套机制能成立的前提,是那句“一句话描述”写得足够准。描述写虚了,模型就路由不到正确的技能,后面的精心设计全部白费。这是整个体系里最容易被低估的一环。

1.3 技能边界怎么划:宁可窄,不要宽

我最早写技能的时候犯过一个典型错误,做了个叫“数据分析”的技能,里面塞了清洗、统计、绘图、导出四块内容。结果模型每次触发这个技能,都会把四块内容全读一遍,然后在清洗阶段就开始考虑图表配色,注意力被严重稀释,输出质量反而不如不加载。

后来改成按动作切分:>--- name: stat-analysis description: 当需要对实验数据进行组间比较、相关性分析或回归建模时使用,包含假设检验流程、效应量计算与结果表输出规范 ---

name用小写加短横线,别用中文和空格;description是最关键的一行,写法后面单独讲。三条横线少一条、缩进错一个空格,都可能解析失败。

第三个坑是编码。路径里有中文、文件用 GBK 保存,都可能让解析器读出一堆乱码,然后静默失败。统一用 UTF-8,路径尽量用英文,这个成本很低,收益很大。

2.3 那句描述到底该怎么写

description不是简介,是路由条件。写成“数据分析相关技能”几乎等于没写,因为模型无法判断什么时候该用它。正确的写法是描述触发场景,包含三要素:动作、对象、产出。

对比一下就明白了:

写法内容效果
差数据统计分析技能几乎不触发,或者乱触发
中用于统计检验触发不稳定,同类任务时灵时不灵
好当需要对两组或多组实验数据进行差异比较、相关性检验或回归建模,并输出含效应量与置信区间的结果表时使用触发准确,且能区分于清洗、绘图技能

好的写法里其实藏着排他信息——“输出含效应量与置信区间的结果表”这句,让模型知道这个技能不是只算个 p 值就完事,它还负责结果表。当任务只是“把数据里的空值处理掉”时,它就不会误触发。

我自己的习惯是,每写一个新技能,先拿三个不同类型的任务去试:一个该触发的、一个不该触发的、一个边界模糊的。三个都判对了,这个描述才算过关。这个过程花不了几分钟,但能省掉后面大量的调试。

3. 六个核心技能的具体拆解

3.1 文献整理技能:把“读过”变成“可检索”

文献这块最容易被做成花架子。让 AI 总结论文,它总结得很漂亮,但你过两周回头看,那些总结既不能支撑论证,也无法定位到原文位置。所以这个技能的核心不是“总结”,而是结构化留存。

我在技能里定的规矩是三条。第一,任何一条来自文献的判断,必须同时记录三样东西:文献标识、原文片段、以及这个片段支撑的是哪个论点。缺一样就不算完成。第二,摘要和结论分开记,不要混在一起,因为这两者的可信度完全不同——摘要里的表述往往是作者的主观概括,结论里的数据才是硬货。第三,建立淘汰记录,被筛掉的文献也要记下筛掉的理由,否则三个月后你会重新读一遍同一篇。

配套脚本做的是去重和格式化。去重不能只按标题字符串比对,A study of X和A Study of X.在字符串层面完全不同,得先归一化:转小写、去标点、压缩空格,再算相似度。相似度阈值我一般设在 0.9,高于这个值判为重复。低于 0.85 的基本是不同文献,中间那段灰色地带交给人工判断,不要自动合并——误合并的代价远高于漏合并。

注意:技能里必须明确写死“不得凭空生成文献信息”。这类助手在补全参考文献格式时,编造作者、年份、卷期页码是很常见的行为,而且编得非常像真的。凡是涉及文献元数据,一律要求从已有文件中提取,提取不到就留空并标注待补,绝不允许“推测填写”。

3.2 数据清洗技能:把所有隐式决定变成显式记录

清洗环节是科研可复现性最容易崩的地方。一个人处理缺失值,可能顺手就删了、可能均值填补了、可能前向填充了,做完自己都记不清。半年后别人问起来,只能含糊说“处理过了”。

技能文件里我会强制要求输出一份清洗日志,逐条记录:做了什么操作、影响了多少行、为什么这么做。日志不是给人看的备注,是分析流程的一部分,跟结果表一起归档。

缺失值处理的判断链条要写清楚,不能一句“酌情处理”打发过去。我常用的顺序是:先算缺失比例,单列缺失超过三成的直接剔除该列并记录;剩下的看缺失机制,如果是完全随机缺失且比例低,用中位数或众数填补,同时保留一个标记列;如果缺失本身携带信息(比如高收入人群更不愿意填收入),那就不能简单填补,得单独提出来讨论。这套逻辑写进技能,模型就不会无脑dropna()。

离群值同理。技能里明确禁止“直接删除 3 个标准差之外的点”,要求先画分布图,再决定是保留、缩尾还是剔除,并且必须在日志里写明判断依据。这条规矩救过我好几次——有好几个所谓的离群点,其实是稀有但真实的极端案例,删掉就把最有意思的发现删掉了。

3.3 统计检验技能:先检查假设,再谈 p 值

这个技能是整个包里价值最高的一个,也是最需要写细的。原因很简单:统计检验的选择和解读,是 AI 最容易给出“教科书答案但实际错误”的地方。

技能里的执行顺序是固定的。第一步永远是描述性统计加分布检查,输出样本量、均值、中位数、标准差、四分位距,加上正态性检验结果。第二步判断检验方法:两组独立样本且都近似正态、方差齐,走常规 t 检验;方差不齐走校正版本;样本量小于三十且明显偏态,走非参数检验。多组比较先做整体检验,显著了才做事后两两比较,并且必须做多重比较校正。

这里有个参数要算清楚——多重比较的校正阈值。做 k 次比较,如果按 Bonferroni 校正,单次检验的显著性水平就是 0.05/k。k=6 时阈值降到 0.0083,很多原本“显著”的结果会瞬间不显著。这不是保守,这是必要的。我见过太多把六组两两比较全做一遍、然后只报那一个 p=0.04 的做法,这不是分析,这是挑数据。

更推荐用 FDR 校正,它控制的是错误发现率而不是族错误率,在探索性分析里更合理。技能里可以两个都算,输出时并排列出,让人自己判断。

第二块是效应量。技能强制要求每个检验都附带效应量:t 检验给 Cohen's d,方差分析给 η²,非参数给秩相关效应量。理由很实在——p 值只告诉你“有没有差异”,效应量才告诉你“差异有多大、值不值得关心”。一个 p=0.001 但 Cohen's d=0.05 的结果,在实际意义上基本等于没有。

第三块是结果表模板。技能里固定一个输出格式,列包括:比较组、方法、统计量、自由度、p 值、校正后 p 值、效应量、置信区间、样本量。表格直接产出为 CSV,不用人再手工誊抄。这一步看起来琐碎,但它是防错的关键——手工誊抄是转录错误的高发区。

3.4 出图技能:把期刊要求翻译成参数

出图这件事,看着是审美问题,实际全是参数问题。技能要做的,是把“符合期刊要求”这种模糊说法,翻译成具体的数值。

先算尺寸。多数期刊的双栏图宽度要求是 170 毫米左右,单栏 85 毫米左右。按 300 dpi 的印刷要求换算成像素:85 毫米 ÷ 25.4 × 300 ≈ 1004 像素,170 毫米对应约 2008 像素。所以脚本里的 figsize 应该按英寸设,单栏 85/25.4 ≈ 3.35 英寸,双栏约 6.7 英寸,配合 dpi=300 正好对上。字号同理,正文一般要求 7 到 9 磅,标题略大,这个范围在缩放后仍然可读。

再算配色。技能里直接禁用那套经典的红绿对比,改用对色觉障碍友好的方案,并且在技能文件里写清楚“同一张图内的类别不超过六个,超过就换分面”。这条不是审美洁癖,类别一多,颜色区分度必然下降,读者根本分不清谁是谁。

字体是最容易翻车的地方。中文字体在很多环境里默认缺失,脚本一跑满屏方块。稳妥做法是在脚本开头做一次字体探测:列出系统里可用的中文字体,取第一个命中的设置进去;一个都没有就明确报错退出,而不是画出一堆方块还继续往下走。报错比沉默的错误输出好一百倍。

导出格式也要定死:矢量图存 PDF 或 SVG 用于排版,位图存 300 dpi 的 PNG 用于预览和投稿系统上传,两个都要出,文件名保持一致。别用 JPEG,压缩伪影在线条图上特别明显。

提示:所有这些参数,与其写在技能正文里让人读,不如直接固化进脚本的默认值。正文只需要说明“什么时候用这个脚本、需要传什么参数”,具体数值让代码去保证。人记不住参数,代码记得住。

3.5 可复现性技能:让每次运行都留下痕迹

这个技能不产出任何研究结果,它只负责记录,但它是整个体系里最该早点做的一个。做法很简单:每次分析运行,自动创建一个带时间戳的目录,里面放五样东西。

  • 输入数据的文件清单和每个文件的哈希值
  • 本次运行的脚本副本(不是引用,是复制)
  • 环境快照,包括语言版本和关键依赖包的版本号
  • 完整运行日志,含起止时间和警告信息
  • 输出文件清单

哈希值这一步很多人会跳过,觉得多余。但当你三个月后发现结果对不上,第一件要确认的事就是“数据文件有没有被改过”。有哈希,一秒钟就能确认;没哈希,你就得靠文件修改时间猜,而修改时间是可以被复制操作覆盖的,完全不可靠。

环境快照同样重要。Python 生态里,同一个包的小版本升级导致数值结果变化的情况并不罕见。技能里可以直接调命令把当前环境的包版本全导出来存成文本文件,几秒钟的事,省掉后面无数的扯皮。

日志这块有个细节值得写进技能:警告信息不能吞掉。很多人写脚本习惯加个忽略警告的设置,图个清爽。但那些警告里经常藏着真问题——除零、类型转换、数据截断,全在那儿。技能里应该要求日志完整保留,并且在结束时统计警告数量,非零就在日志末尾标一行提示。

3.6 写作检查技能:统一口径比润色重要

写作技能最容易写成“帮我改改语法”,价值有限。真正有用的是一致性检查,因为长篇稿件里最要命的错误不是语法,是前后不一致。

技能里我列了几条硬检查。术语一致性:同一个概念全文只能有一种叫法,不能前面叫“处理组”后面叫“实验组”。缩写规范:首次出现给全称加缩写,之后统一用缩写,不能混着来。数字格式:小数点位数、单位空格、百分比写法全文统一。时态:方法用过去时,普遍结论用现在时,这个在中文稿里体现为“本研究中我们采用了”和“结果表明”的区别,要一致。图表引用:正文里提到的每个图号,必须真的存在;反过来每个图,正文里必须至少引用一次。

这些检查用脚本做比用模型做更可靠。写个小脚本扫全文,把疑似不一致的地方列出来,比让模型通读一遍更快也更准。模型的优势在语义层面——判断一句话是不是表述含糊、逻辑是不是断裂、图注是不是没交代清楚关键信息,这些才该交给它。

审稿意见回应这块也可以做成技能。核心规矩只有一条:逐条编号,每条都给出“改了什么、改在哪个位置”。最忌讳的是笼统回复“我们已认真修改”。技能里可以要求输出固定格式的表格,三列:意见原文、应对说明、修改位置。这样既方便审稿人核对,也方便自己复盘。

4. 手把手:从零搭一个能跑的最小技能包

4.1 先跑通一个,再考虑复制

不要一上来就写六个技能。我第一次干这事,花了一整晚写了八个技能文件,第二天一测,六个不触发,两个触发了但跑飞。正确顺序是:挑一个你每周都要做、且流程固定的动作,先把它做成技能,跑通,再复制结构。

选统计检验技能做第一个最合适,因为它有明确输入(数据表)、明确输出(结果表)、明确检查项(假设检验),边界清晰,容易验证对错。

目录建好后,先写入口文件:

--- name: stat-analysis description: 当需要对两组或多组实验数据进行组间差异比较、相关性检验或回归建模,并输出含效应量与置信区间的结果表时使用 --- # 统计分析 ## 何时使用 用户提供了数据表,并要求比较组间差异、检验相关性或建立回归模型时使用。 仅做数据清洗或仅做绘图时不要使用本技能。 ## 执行顺序 1. 先跑 scripts/assumption_check.py,得到描述统计与分布检查结果 2. 根据检查结果选择检验方法,选择依据见 references/method_choice.md 3. 跑 scripts/report_stats.py 生成结果表 4. 检查结果表是否包含效应量与置信区间,缺失则重跑 ## 硬性约束 - 不得跳过假设检查直接选检验 - 多组比较必须做多重比较校正,校正方法与原始 p 值并列输出 - 结果表必须包含样本量列 - 所有输出写入 outputs/ 目录,不得写入 data/raw/

这份文件里,description负责路由,正文的“何时使用”负责二次确认,“硬性约束”负责兜底。三层的分工要清楚,不要把约束写进描述里,那会把路由条件搞乱。

references/method_choice.md单独放方法选择的判断树,因为它内容长、且不是每次都需要读全。这样拆开,日常调用只加载技能正文,只有真正需要选方法时才去读那一篇。

4.2 脚本层:把易错操作焊死

脚本的作用不是替模型思考,是把那些“每次都要记得做、但每次都容易忘”的动作变成默认行为。以假设检查脚本为例,核心逻辑大概是这样:

import pandas as pd from scipy import stats def check_assumptions(df, group_col, value_col, alpha=0.05): groups = [g[value_col].dropna().values for _, g in df.groupby(group_col)] report = {"n_groups": len(groups), "sizes": [len(g) for g in groups]} # 正态性:样本量小于 5000 用 Shapiro,否则用偏度峰度判断 normality = [] for g in groups: if len(g) < 3: normality.append(None) elif len(g) < 5000: normality.append(stats.shapiro(g).pvalue) else: normality.append(stats.normaltest(g).pvalue) report["normality_p"] = normality # 方差齐性:两组用 Levene,多组同样用 Levene(对偏态更稳健) if len(groups) >= 2: report["levene_p"] = stats.levene(*groups).pvalue # 给出建议,但不替人做决定 all_normal = all(p is not None and p > alpha for p in normality) homo = report.get("levene_p", 1.0) > alpha report["suggestion"] = ( "参数检验" if all_normal and homo else "非参数检验或校正版本" ) return report

注意最后那段suggestion的措辞——给建议,不给结论。这是我在实际使用中调整出来的:早期版本直接返回“用 t 检验”,模型拿到就照做,人也不再核对。改成给建议之后,人会被迫看一眼依据,误判率明显下降。

方差齐性检验这里用了 Levene 而不是 Bartlett,理由是 Bartlett 对非正态数据非常敏感,稍微偏一点就报方差不齐,实践中误报率偏高。Levene 基于绝对偏差,稳健性好得多。这个选择本身就该写进技能的参考文档里,让读的人知道为什么。

结果表脚本里有个参数值得算一下:置信区间的计算方式。两组均值差的置信区间,用 Welch 方法时自由度不再是简单的 n1+n2-2,而是按方差和样本量加权算出来的近似值。脚本里直接调库函数就行,但技能文档里要说明“输出的是 Welch 区间而非等方差区间”,否则读表的人会按错误的自由度去理解。

4.3 联调:怎么判断技能真的生效了

写完不等于能用,得有一套验证动作。我的验证清单是四步。

第一步,问它“你能看到哪些技能”,确认清单正确。第二步,给一个明确该触发的任务,比如“比较 A 组和 B 组的测量值差异”,观察它是否调用了统计技能、是否先跑了假设检查。第三步,给一个不该触发的任务,比如“把这份数据的列名改成英文”,看它会不会错误地调用统计技能。第四步,给一个边界任务,比如“看看这两组数据分布有没有差别”,这句话既可以是描述统计也可以是检验,看它怎么判断——这一步最能暴露描述写得含糊的地方。

四步里有任何一步不对,先改description,别急着改脚本。九成的触发问题都出在描述上。

跑通之后还有一件事要做:记录一次完整对话。把从提问到出结果的整个过程存下来,包括它调了哪些脚本、中间报了什么错、你怎么纠正的。这份记录后面会成为你优化技能的第一手材料,比凭记忆改有效得多。

5. 踩过的坑和排查速查表

5.1 那些让人抓狂的典型故障

技能完全不触发。这是最高频的问题。排查顺序:先确认文件路径和文件名,再确认元数据格式,最后看描述。前两个是硬错误,一眼能看出来;描述问题最隐蔽,典型表现是“问它有什么技能它能列出来,但干活时就是不用”。这种情况八成是描述里全是“支持”“相关”“辅助”这类无信息量的词。改法是把动作和产出写具体。

技能触发了但脚本跑不动。多数是路径问题。脚本里用了相对路径,但执行时的工作目录不是项目根目录,data/raw/x.csv就找不到了。解决办法是在技能里明确要求“所有脚本以项目根目录为工作目录执行”,或者在脚本内部自己做路径解析,基于脚本自身位置推算根目录,不依赖调用方的工作目录。

中文路径或中文列名报编码错误。这类问题在跨平台时特别常见。根治办法是数据文件和列名统一用英文,中文只出现在最终报告里。如果确实绕不开,读写时显式指定编码,并且不要指望系统默认值。

画图出来全是方块。中文字体缺失,前面说过。补充一点:即使系统装了字体,绘图库的字体缓存也可能没更新,需要清一次缓存再重试。技能里可以直接写一条“先跑字体探测脚本,探测失败就中止”。

长表格被截断。数据行数一多,输出到对话里就会被截。技能里应该规定:超过一定行数的表格一律写文件,对话里只报“已写入某路径,共 N 行”,需要看细节时再单独读。这条规矩能省掉大量“咦怎么少了几行”的困惑。

模型自作主张改了原始数据。这是最危险的一类。除了前面说的只读权限,技能里还应该加一条:任何写操作前必须先打印将要修改的文件路径和目标路径,等确认后再执行。多这一句,能挡住绝大多数误操作。

5.2 速查表

现象最可能的原因处理动作
列不出技能路径层级不对或文件名不符确认入口文件在技能目录第一层且命名正确
列得出但不触发描述信息量不足改写描述,加入动作、对象、产出三要素
误触发到别的技能两个技能描述重叠收窄边界,在描述里加排他说明
脚本报文件不存在工作目录不一致脚本内基于自身位置解析路径
中文显示为方块字体缺失或缓存未更新字体探测加缓存清理
表格行数不全对话输出截断改为写文件,对话只报路径和行数
原始数据被改动缺少写保护目录只读加技能内写前确认
结果无法复现未记录环境与种子强制生成运行目录与环境快照

5.3 长期维护:技能包是会烂的

这一点很少有人提,但很实际。技能包写完不是一劳永逸,它会随三件事慢慢失效:工具本身升级导致加载机制变化、依赖库升级导致脚本报错、你的分析流程变化导致技能不再匹配。

我的做法是给技能包建一个自己的版本记录,每次改动写一行:改了什么、为什么改。同时每隔一段时间做一次“冷启动测试”——换一台干净的机器,或者清空环境重装,从零跑一遍核心流程。这个测试能暴露出一堆隐藏依赖,比如某个包其实是你手动装过但没写进依赖清单的,换个环境就崩。我吃过这个亏,本地跑得好好的,换台机器重装环境,脚本直接报缺包,查了半天才发现是三年前手动装的一个小库。

另一个经验是:技能文件里的示例要定期更新。很多技能会附带一个“输入输出示例”,用来告诉模型期望的格式。这些示例如果用真实数据写,时间一长就会和当前数据结构脱节,模型照着旧格式输出,你还以为是它理解错了。示例要么用完全虚构的结构,要么定期同步。用虚构结构更省事,反正模型看的是格式不是内容。

最后说一个心态上的体会。这套东西的价值不在于让 AI 替你做科研,而在于逼你把“自己到底是怎么做科研的”这件事说清楚。我写完第一版技能包的收获,不是多了个助手,而是发现自己原来有那么多操作是凭直觉做的、根本说不出来由。把这个过程显式化之后,即使不用 AI,分析质量也会上去一大截。后面想扩展的话,最值得先做的是把审稿意见回应也固化成技能——那部分格式最固定、重复度最高,收益最直接。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询