实测 · 三个学术 Skill 跑一遍真科研
CPS1985 工资回归,端到端走完,看 Skill 到底靠不靠谱
终章说过一句最重要的话:评价 AI 的科研能力,不能只看 idea 多漂亮,要看执行。这一章就把终章介绍的那套学术 Skill 包拉出来,真刀真枪跑一遍——下载真实数据、做真实回归、出图、生成 Word 和 PPT,全程不许 AI"自己写段代码假装是 skill 在干活"。跑完你就知道,这些 Skill 到底是"按一下出论文"的魔法,还是"一位严谨导师的工作清单 + 一箱趁手的脚本"。
一、想让模型干什么#
任务定得很具体:用这三个 Skill 协作,独立完成一个完整的小型实证研究。题目选了劳动经济学里最经典的 Mincer 工资方程——说人话就是回答一个问题:
多读一年书,时薪到底涨百分之几?
围绕这个问题,要求模型走完一条真实科研的全链路:找一个公开的小数据集 → 估计受教育回报 → 出版级配图 → 生成一份可交付的 Word 报告和一套答辩 PPT。三个 Skill 各管一段:
| Skill | 这次负责什么 | 实际触发的子模块 |
|---|---|---|
| scientific-toolkit-skill | 跑数据:EDA、回归、出图、机器学习、查文献 | eda · statistical-analysis · scientific-visualization · scikit-learn · citation-management |
| research-writing-skill | 写正文:中文优先、证据分级、不编造 | Writing Principles · Section Guides |
| office-academic-skill | 出交付物:可编辑 Word / PPT + 交付前质检 | report-structure · slide-quality · Quality Gate |
为了避免"自己重写一遍代码、假装是 skill 干的",这次定了三条硬规矩:
项目长这样
所有产物都写进一个独立的 skill-eval/ 子目录,不碰仓库里其它东西:
skill-eval/
├── data/ # 原始数据集(CPS1985.csv)
├── analysis/ # 分析脚本 + 中间结果(回归、分类、质检)
├── figures/ # 出版级配图(png + svg,300 DPI)
├── deliverables/ # 最终 Word / PPT 交付物
├── papers/ # 文献与 BibTeX
└── logs/ # 检索原始返回
一句话:左边是输入(数据、文献),中间是脚本(调用 skill),右边是产物(图、Word、PPT)。
二、运行了什么、喂了哪些提示词#
环境先探一遍,确认依赖齐全:Python 3.13.11,科学栈 pandas 2.3.3 / numpy 2.2.6 / matplotlib 3.9.2 / scikit-learn 1.8.0 / statsmodels 0.14.6,Office 栈 python-docx 1.2.0 / python-pptx 1.0.2。三个 skill 要用的运行环境都满足。
数据靠 Tavily 选、靠 curl 下(遵守本机全局规则:不用原生 WebSearch,搜索统一走 Tavily)。喂给 Tavily 的提示词:
open source small economics labor wage dataset CSV download CPS1985 Rdatasets
Tavily 确认 CPS 1985(Determinants of Wages,AER/Rdatasets)是公认的小型开源劳动经济学数据集,于是下载:
curl -sSL --retry 2 -o CPS1985.csv \
"https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/master/csv/AER/CPS1985.csv"
拿到 534 行 × 12 列(wage、education、experience、age、gender、union、married、ethnicity、occupation、sector、region)。体量小,正合适。
这里要澄清一个关键点:真正"喂给模型"的提示词,其实就是这几个 Skill 的 description 和规则文件本身——它们既决定 Skill 何时出场,也决定它干活的纪律。下面是这次实际生效的几段核心提示词:
【A · office-academic 的报告结构提示词,驱动 DOCX 标题与证据标签】
文献信息 / 一页式摘要 / 研究背景与问题 / 方法与模型 /
实验·仿真·数据设置 / 结果与图表解读 / 创新点与贡献 /
局限性与边界条件 / 可复现要点 / 汇报讲稿要点 / 原文依据索引表
证据标签:来源: / 推断: / 建议:
【B · office-academic 的幻灯片质量提示词,驱动 PPT 标题写法】
每页一个核心观点;用"行动标题"陈述结论而非话题标签;
图表承载技术论证;保持坐标轴/单位/图例科学准确;
避免文字溢出 / 图片拉伸 / 中文乱码 / 残留占位符。
【C · research-writing 的写作原则提示词,驱动正文风格】
默认中文;保留英文标题/公式/变量/方法名/软件命令/参考文献;
不编造数据/DOI/期刊/实验值;
区分 原文·已有数据 / 用户确认 / 推断 / 建议;
用可测量条件替换"显著/先进/有效"等模糊词。
注意 B 和 C 的味道:它们不是"写得漂亮点"这种空话,而是一串可执行的约束——这正是终章说的"用提示词做纪律"。
三、触发了哪些 Skill、结果如何#
九项测试逐个跑下来,全部端到端通过(过程中暴露 4 处真实摩擦,留到第四节如实交代):
| # | Skill / 子模块 | 测了什么 | 结果 |
|---|---|---|---|
| T1 | exploratory-data-analysis | 用 eda_analyzer.py 跑 EDA 报告 | ✅ 零改动跑通 |
| T2 | statistical-analysis + statsmodels | Mincer OLS + VIF + 残差正态检验 | ✅ 通过(1 处签名修正) |
| T3 | scientific-visualization | 用 style_presets 出 3 张出版级图 | ✅ 通过 |
| T4 | scikit-learn | 用内置 classification_pipeline 做分类 | ✅ 通过 |
| T5 | citation-management | DOI→BibTeX(CrossRef) | ✅ 通过(1 DOI 失效有报错 + 1 编码 bug) |
| T6–T8 | office-academic | 生成 DOCX / PPTX + 质量门禁回读 | ✅ 通过(门禁抓出真实溢出) |
| T9 | research-writing | 中文优先、证据分级的报告正文 | ✅ 通过 |
下面挑最硬的几项,把代码、命令、运行结果原样摆出来。
核心:Mincer 工资回归
这是整个分析的心脏,回答开头那个问题。脚本 analysis/mincer_regression.py 直接 import 了 skill 自带的两个模块(出图样式 + 假设检验),再用 statsmodels 跑一个带稳健标准误的 OLS:
import statsmodels.formula.api as smf
from statsmodels.stats.outliers_influence import variance_inflation_factor
# 关键一步:把 skill 自己的脚本目录加进路径,import 它本身(而不是重写)
sys.path.insert(0, str(SK / "scientific-visualization" / "scripts"))
sys.path.insert(0, str(SK / "statistical-analysis" / "scripts"))
import style_presets # 来自 scientific-visualization
import assumption_checks # 来自 statistical-analysis
# 数据准备:Mincer 方程用 log 工资 + 工龄二次项
df["lwage"] = np.log(df["wage"])
df["exper2"] = df["experience"] ** 2 / 100
# Mincer OLS,HC3 异方差稳健标准误
formula = ("lwage ~ education + experience + exper2 + C(gender) "
"+ C(union) + C(married) + C(ethnicity)")
model = smf.ols(formula, data=df).fit(cov_type="HC3")
print(model.summary())
# 多重共线性(VIF)
Xnum = df[["education", "experience", "exper2"]].assign(const=1.0)
vif = {c: round(float(variance_inflation_factor(Xnum.values, i)), 2)
for i, c in enumerate(Xnum.columns) if c != "const"}
# 残差正态性——调用 skill 自己的模块来检验
resid = model.resid
norm = assumption_checks.check_normality(
resid.values, name="OLS residuals", alpha=0.05, plot=False)
运行命令(MPLBACKEND=Agg 是为了无界面环境不弹窗卡住):
MPLBACKEND=Agg python analysis/mincer_regression.py
真实运行输出(statsmodels 的回归摘要,原样粘贴):
OLS Regression Results
==============================================================================
Dep. Variable: lwage R-squared: 0.325
Model: OLS Adj. R-squared: 0.315
Method: Least Squares F-statistic: 29.34
No. Observations: 534 Prob (F-statistic): 6.93e-38
Df Residuals: 525 Covariance Type: HC3
============================================================================================
coef std err z P>|z| [0.025 0.975]
--------------------------------------------------------------------------------------------
Intercept 0.3851 0.130 2.957 0.003 0.130 0.640
C(gender)[T.male] 0.2316 0.040 5.860 0.000 0.154 0.309
C(union)[T.yes] 0.2091 0.047 4.470 0.000 0.117 0.301
C(married)[T.yes] 0.0362 0.042 0.864 0.387 -0.046 0.118
C(ethnicity)[T.hispanic] -0.0800 0.090 -0.884 0.376 -0.257 0.097
C(ethnicity)[T.other] -0.1224 0.055 -2.234 0.025 -0.230 -0.015
education 0.0887 0.008 10.505 0.000 0.072 0.105
experience 0.0331 0.006 5.356 0.000 0.021 0.045
exper2 -0.0504 0.013 -3.754 0.000 -0.077 -0.024
==============================================================================
把关键数字翻成人话:
| 指标 | 值 | 怎么读 |
|---|---|---|
| 样本量 n | 534 | |
| R² / 调整 R² | 0.325 / 0.315 | 这些变量解释了约 32% 的工资差异 |
| 受教育回报 | 8.87 %/年(p ≈ 8e-26) | 每多读一年书,时薪平均高约 8.9% |
| 男性工资溢价 | +0.232 对数点(≈26%) | 同等条件下男性更高 |
| 工会工资溢价 | +0.209 对数点 | 入会者更高 |
| 工龄二次项 | −0.050(显著) | 工龄收益先升后降,呈凹形 |
| 残差正态(Shapiro,skill 模块) | W=0.986, p≈5e-5 | 残差非正态,已如实写进局限 |
最关键的一行:受教育回报 8.87%/年,正落在权威文献(Card、Heckman 等)给出的 5–10%/年经验区间内——结果可信,不是瞎算。
三张出版级配图
出图脚本 analysis/make_figures.py 直接套用 skill 的出版样式和色盲安全调色板:
import style_presets
style_presets.apply_publication_style("default")
style_presets.set_color_palette("okabe_ito") # 8 色,色盲友好
跑出三张图(每张同时存 png + svg,300 DPI),分别对应回归里三个最重要的结论:

图 1 把"受教育回报"画了出来:两条拟合线都向上,且男性(蓝)整体高于女性(黄)——对应回归里的 education 系数和 gender 溢价。

图 2 是 Mincer 方程的招牌形状——凹形:工龄早期收益快,后期变平甚至下降,对应回归里显著为负的 exper2 二次项。

图 3 把工会溢价可视化:入会一组(右)的中位数和均值都更高,对应回归里 +0.209 的 union 系数。
顺手做了个分类(scikit-learn)
为了测 scikit-learn 子技能,又让它的内置管线做了个二分类:预测某人时薪是否高于中位数。脚本只是把数据喂给 skill 的 train_and_evaluate_model,预处理、三模型五折交叉验证、网格调参、评估全由管线自动完成:
import classification_pipeline as cp # skill 自己的管线
y = (df["wage"] > df["wage"].median()).astype(int) # 1 = 高于中位数
res = cp.train_and_evaluate_model(
X, y, numeric_features=numeric, categorical_features=categorical,
test_size=0.25, random_state=42)
运行结果(管线自动选出最优模型为逻辑回归):
Random Forest : 0.7025 (+/- 0.0843)
Gradient Boosting : 0.7175 (+/- 0.1091)
Best model: Logistic Regression (Best CV score: 0.7350)
Best parameters: {'classifier__C': 0.1, 'classifier__penalty': 'l2'}
Test: Accuracy=0.627 F1=0.626 ROC AUC=0.699
整套管线零改动跑通。准确率 0.627 不算高——这恰恰诚实:单看人口学特征预测个体工资本就难,结果没被粉饰。
把结果变成 Word 和 PPT,再回读质检
最后由 office-academic-skill 把分析变成交付物:一份 DOCX 报告(401 KB,内嵌 3 张图、2 张表、7 处 来源: 证据标签,中文微软雅黑 + 英文 Times New Roman)和一套 8 页 16:9 答辩 PPT(每页一个观点、行动标题陈述结论、配演讲者备注)。
真正体现工程严谨的是最后一步——Quality Gate(质量门禁):它把生成好的文件重新解包回读,不信任生成过程,专查缺文、乱码、图片溢出、残留占位符。第一次跑就抓出真问题:
slides overflowing bounds : [3, 4]
第 3、4 页的图按 8.5 英寸插入后高度超出了画布下边界——这正是 skill 文档里点名要防的"图片溢出"。把这两页图宽改窄后重新生成,复检全绿:
slide count : 8
slides overflowing bounds : none
slides missing notes : none
embedded media (images) : 3
stale 'Click to add' text : False
'{{' template leftover : False
DOCX 复检同样干净:31 段正文、2 表、3 图、CJK 正常、mojibake 嫌疑 0 处、关键数字 8.87 确实出现在正文里。
四、四处真实摩擦(实测,不是宣传)#
跑通不等于完美。如实记下过程中撞到的 4 个坑:
- 网络会抽风。 下载数据第一次
curl报Recv failure: Connection was reset,重试第 2 次才成功。检索和下载都遇到过连接 reset,得靠--retry。 - 脚本有真实小 bug。 引文工具
doi_to_bibtex.py把 CrossRef 返回的 en-dash 写成了乱码1801–1863(响应未显式设编码导致双重编码)。生产前需要清洗。 - reference 文档不给函数签名。 调用
check_normality时按直觉传test=参数直接报TypeError,读源码才知道真实签名是check_normality(data, name=, alpha=, plot=),而且plot默认True,无界面环境会plt.show()卡住,必须显式plot=False。 - PPT 图片溢出(见上一节)——好在被 Quality Gate 自己逮住了。
还有一处值得表扬的"优雅失败":验证 DOI 时 10.1257/jep.20.4.69 失效,脚本明确报 Error: DOI not found 并给出 Converted 1/2 DOIs (50.0%),不静默吞错。
五、结论:魔法,还是工作清单?#
把九项测试、四处摩擦放一起,结论很清楚:
站得住的地方 ✅
- 三技能协作链路真能端到端跑通:分析 → 写正文 → 出 Word/PPT 完整走了一遍,交付 1 份 DOCX + 1 份 PPT。
- 内置脚本是真资产不是摆设:EDA、假设检验、出版样式、ML 管线、DOI→BibTeX 五个模块全部被实际调用并产出正确结果,多数零改动。
- "证据分级 + 不编造"落地有效:受教育回报 8.87%/年与权威文献吻合,所有定量主张都挂了
来源:标签。 - Quality Gate 名副其实:它真的抓出了一个 PPT 溢出缺陷并驱动修复。
打折扣的地方 ⚠️
- reference 是"概念性指南"不是"API 文档",调内置脚本前最好先
Read一眼源码确认签名。 - 脚本存在真实小 bug(en-dash 编码),headless 默认值也不友好。
- Office 产物本质是标准 python-docx/pptx 生成,价值在"结构模板 + 证据标签 + 质量门禁"这套方法论,而非独家引擎。
这恰好回应了终章那盆冷水——"理念惊艳、执行褪色"。这次执行之所以没有褪色,是因为全程都有终章强调的那几样东西兜底:真实数据、可溯源的证据分级、以及交付前那道把关的 Quality Gate。说到底,让 AI 科研靠谱的从来不是某段惊艳的提示词,而是有没有验证机制。