/experiments/2_7_skills/

2.7 & 2.8 节实验:139 个公开 Skill 四档长度塞入窗口 vs INDEX.md 渐进式披露与描述改写实验(30 道考题)

目录文件列表

文件 / 目录说明大小
📁 ../返回上级目录-
📁 graded/子目录-
📁 raw/子目录-
📄 README.md30.0 KB
📄 baseline.log387 B
📄 build_pool.py5.9 KB
📄 candidates.json222.9 KB
📄 candidates_baseline.json1.8 MB
📄 candidates_raw.json265.4 KB
📄 candidates_summary.json36.2 KB
📄 descriptions_fixed.json11.0 KB
📄 draft.log3.2 KB
📄 exclude.json150 B
📄 fix_descriptions.py3.2 KB
📄 grade.log2.0 KB
📄 grade.py10.3 KB
📄 index_fixed_plan.json1.7 KB
📄 lib.py5.9 KB
📄 make_tasks.py7.2 KB
📄 pool.json76.0 KB
📄 pool_text.json1.4 MB
📄 probe.json5.4 KB
📄 probe.py2.3 KB
📄 results.json18.5 KB
📄 results_before_rubric_fix.json18.6 KB
📄 run.py9.6 KB
📄 run_deepseek-v4.1-flash.log9.1 KB
📄 run_fixed_deepseek-v4.1-flash.log1.2 KB
📄 run_fixed_gpt-5.log1.1 KB
📄 run_fixed_grok-4-fast.log1.5 KB
📄 run_gpt-5.log11.4 KB
📄 run_grok-4-fast.log7.4 KB
📄 run_rep2_deepseek-v4.1-flash.log2.3 KB
📄 run_rep2_gpt-5.log1.8 KB
📄 run_rep2_grok-4-fast.log1.7 KB
📄 selection.json4.2 KB
📄 spotcheck.json59.7 KB
📄 spotcheck_review.json1.3 KB
📄 task_cues.json424 B
📄 tasks.json32.7 KB

README.md

2.7 把所有 skill 塞进窗口,还是只放一张索引

怎么跑

# 1. 建 skill 池(不调 API)
.venv/bin/python experiments/2_7_skills/build_pool.py
# 2. 出题:gpt-5 起草候选题,再用三个模型做“不给 skill”的基线,人工复核后定稿
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/make_tasks.py draft
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/make_tasks.py baseline
.venv/bin/python experiments/2_7_skills/make_tasks.py finalize          # 读 selection.json
# 3. 主实验(每个模型一行)
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/run.py grok-4-fast none index full_1 full_10 full_30 full_all index_rep2
# 4. 判分、汇总
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/grade.py
# 5. 修描述后重跑
.venv/bin/python experiments/2_7_skills/fix_descriptions.py plan
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/fix_descriptions.py rewrite
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/run.py grok-4-fast index_fixed
op run --env-file experiments/aib.env -- .venv/bin/python -u experiments/2_7_skills/grade.py && .venv/bin/python experiments/2_7_skills/grade.py analyze

接口是 AI Builder Space(OpenAI 兼容)。模型:deepseek-v4.1-flash、grok-4-fast、gpt-5。实验日期 2026-10-13。全部花费约 54 美元(网关账单前后差),其中主实验 28.6 美元,大头是 grok 的 full_all(12.1 美元)。

先说网关的三个事实,它们影响怎么读结果

实验设计

skill 池(pool.json)。 来源是公开的 context-infrastructure 仓库 rules/skills/*.md,加上 adhoc_jobs/ 下 origin 名字出现在 SKILL_ECOSYSTEM.md 里的公开 skill 仓库的 skills/*.md 和 skills/<dir>/SKILL.md,只取 git 跟踪的文件,不取 references/、templates/ 和 skill 目录里的子文件。去重规则:同名取较长的那份(context-infrastructure 里有 5 个写作类文件只剩“已迁移到 writing-skill”的指针,换成 writing-skill 里的正文)。密钥扫描只命中占位符(example.com、replace-with-your-...),唯一剔除的是 skill_imessage.md,它的例子里有一个具体的美国电话号码,无法确认是虚构的(exclude.json)。最后是 139 个 skill,369,217 个 token(cl100k)。描述取 frontmatter 的 description,没有就取第一个标题加第一句;索引里每条截到 240 字符。全量索引 6,682 token。

题目(tasks.json)。 gpt-5 读每个 skill,各提 2 道候选题,要求题目像真实用户的提问、不提 skill 文件名、不照抄原文,并给出逐字摘录和判分要点;摘录不是原文子串的直接丢掉,剩 236 道。三个模型在“不给任何 skill”的情况下各答一遍,169 道三个模型全错。我们只从这 169 道里选,再人工读摘录筛掉:答案在别的 skill 里也写着的(比如 voice-lora 和 voice-lora-rewrite、ios_development 和 simulator_testing 讲的是同一条),依赖占位值或私有路径的,问题本身含糊的。最后 30 道,30 个不同的目标 skill,8 个来自 context-infrastructure,22 个来自 22 个不同的生态仓库。筛选理由在 selection.json。

条件(每个模型、每道题一次调用,题与题之间没有历史)。

判分。 gpt-5 当判官,看题目、逐字摘录、判分要点和答案,输出 {correct, reason}。

结果

准确率、输入 token、延迟、花费(results.json 的 cells)

模型 none full_1 full_10 full_30 full_all index index_rep2
deepseek-v4.1-flash 2/30 28/30 30/30 30/30 30/30 24/30 24/30
gpt-5 1/30 30/30 28/30 29/30 放不下 22/30 22/30
grok-4-fast 0/30 27/30 27/30 27/30 19/30 13/30 13/30
模型 条件 平均输入 token(接口计费) 平均延迟(秒) 30 题总花费(美元)
deepseek-v4.1-flash full_1 2,977 3.9 0.021
full_10 16,610 4.5 0.083
full_30 64,455 4.7 0.298
full_all 336,205 5.7 1.521
index 30,691 18.5 0.396
gpt-5 full_1 2,552 30.4 0.647
full_10 16,305 31.1 1.210
full_30 65,781 35.9 3.060
full_all 340,111(被拒) 0
index 13,959 36.1 1.264
grok-4-fast full_1 2,615 3.7 0.108
full_10 15,500 4.7 0.597
full_30 61,641 6.9 2.333
full_all 321,925 16.6 12.101
index 10,923 6.7 0.430

index 的 token、延迟、花费是一道题内所有轮次的总和。花费:deepseek 和 grok 取网关 trace 里的 estimated_cost_usd,gpt-5 按 1.25 / 10 美元每百万输入 / 输出 token 估算,都没有扣缓存折扣。full_all 的 30 道题共享很长的前缀,服务端很可能命中了缓存,deepseek full_all 只要 5.7 秒可能和这个有关,但网关不报缓存命中,我们无法确认。

池子在各个 k 下的大小(cl100k,30 道题的最小 / 平均 / 最大):k=1 为 435 / 2,528 / 6,432;k=10 为 15,463 / 17,584 / 21,460;k=30 为 71,010 / 72,852 / 77,007;全部为 369,217。

窗口能不能装下:gpt-5 在网关上的输入上限是 272,000 token,整个池子算出来是 340,111 token,30 道题全部返回 400,是上限的 125%。这一格记作“放不下”,不是答错。deepseek 和 grok 都装下了全池(336,205 和 321,925 token);网关没有公布这两个模型的窗口大小,所以我们不报占比。

假设 1:全塞进去,准确率会不会随 skill 变多而掉

看模型。grok 从 full_1 到 full_30 一直是 27/30,到 full_all 掉到 19/30。逐题看,full_all 相对 full_1 丢了 11 道、多对了 3 道(T02、T08、T30)。丢的那 11 道,目标 skill 在 139 个里的位置是 23、29、31、33、46、51、64、67、74、113、119,没有集中在中间或某一端。读答案,丢分的方式主要是两种:一种是拿了别的 skill 的内容来答(T05 去讲 tavily 的缓存,T01 去讲 semantic-search 的相对路径),一种是没用 skill 里的规则,按常识给了一个差不多的数(T06 说间隔 3 到 5 秒,skill 写的是 2 到 3 秒)。

deepseek 没有掉:full_1 28/30,full_10、full_30、full_all 都是 30/30。full_1 错的两道(T12、T15)在更大的 k 下反而答对了。gpt-5 在它装得下的范围内也没有明显下降(30、28、29),差的这一两道在不同 k 之间换来换去,和 index_rep2 里看到的波动是同一个量级。

所以在 34 万 token 这个量级上,“稀释”是否发生取决于模型:grok 掉了 8 道,deepseek 一道没掉,gpt-5 根本装不下。

假设 2:只给索引,准确率能不能保住、成本能不能降

成本降了。和全塞相比,grok 的输入 token 从 321,925 降到 10,923(约 1/29),30 道题的花费从 12.10 美元降到 0.43 美元,延迟从 16.6 秒降到 6.7 秒。deepseek 的输入从 336,205 降到 30,691(约 1/11),花费从 1.52 降到 0.40 美元,但延迟反而从 5.7 秒涨到 18.5 秒,因为 index 至少要多一轮往返,而它在网关上的每一轮都更慢。gpt-5 和它能装下的最大一格 full_30 比,输入从 65,781 降到 13,959,延迟和花费差不多(每题多一轮推理)。

准确率没有保住。三个模型的 index 都低于对应的 full_1:deepseek 24 对 28,gpt-5 22 对 30,grok 13 对 27。grok 的 index(13)比它最差的 full_all(19)还低。index_rep2 和 index 的总分完全一样(24、22、13),所以这个差距不是一次运气。

假设 3:index 下的错误是不是变成了“没打开 / 打开错”

是的,几乎全是。

模型 index 答错 一个都没打开 只打开了别的 skill 打开了目标但答错
deepseek-v4.1-flash 6 2 4 0
gpt-5 8 3 4 1
grok-4-fast 17 12 4 1

三个模型合计 31 个错误里,29 个是没走到目标 skill,只有 2 个是打开了目标却答错。打开了目标的题,答对率是 deepseek 23/23、gpt-5 21/22、grok 12/13。另有一道 T17(视频生成接口超时后能不能重发)三个模型都没打开目标也答对了,这道题的答案接近常识。

没走到目标有两种不同的原因,要分开看。

第一种是问题本身没有线索。 出题时要求不点名 skill,有 7 道题因此连产品名都没提(T01、T05、T10、T11、T22、T28、T29,标注在 task_cues.json,这是看完失败之后做的人工标注)。比如 T29 问“按最近两天导出收到的邮件为 Markdown,--after/--before 能不能填 ISO 时间”,没说是 Resend,三个模型都去打开了 Outlook 的 skill,而 Outlook 的 skill 里确实也有导出邮件为 Markdown 的命令。在这 7 道上,deepseek 和 gpt-5 都是 2/7,grok 是 1/7。在其余 23 道有线索的题上,deepseek 22/23,gpt-5 20/23,grok 12/23。这说明索引式加载有一个全塞没有的前提:用户的说法要能和某一行描述对上。全塞的时候模型直接看到了内容,不需要这一步。

第二种是 grok 根本不打开。 grok 30 道里有 13 道一个 skill 都没打开(rep2 里是 15 道),其中大部分问题里明明写着 Codex、Koyeb、dataforseo、B 站、Gemini 这样的名字,索引里也有对应的行。它直接按自己的知识作答,而且答得很笃定(T19 说 --tail 100 --follow 可以用;skill 写的是 --tail 是布尔开关)。deepseek 和 gpt-5 只在 3 到 4 道题上没打开。

修描述有没有用(index_fixed)

做法:把 index 里“答错且没打开目标”的题的目标 skill 收集起来(三个模型合计 18 个),让 gpt-5 只看 skill 正文和原描述,重写成一句“什么情况下该打开它”的说明,不给它看题目。我们人工读了一遍,只改了一处:codex_cli 的新描述里写了“web_search 不支持等错误”,正好是 T09 问的症状,删成了“参数、配置、沙箱、审批等问题”(原稿留在 descriptions_fixed.json 的 hand_edits)。其余的新描述也会提到用户场景,比如 resend 的“查看/导出收到的邮件”,这是这类改写本来就该做的事,但它离题目也更近了,这一点读者要知道。

模型 原来没打开而答错 改后答对 同一批题在 index_rep2 里答对 10 道原本答对的抽样,改后仍对 同一抽样在 index_rep2 里仍对
deepseek-v4.1-flash 6 4(T01、T22、T24、T29) 0 10 10
gpt-5 7 4(T10、T23、T24、T29) 1(T24) 10 10
grok-4-fast 16 2(T19、T26) 2(T14、T26) 7 8

deepseek 和 gpt-5 上,修描述把一半多的失败救回来了,修好的题都是改后打开了目标 skill;只靠重跑,同一批题 deepseek 一道都不会变对,gpt-5 只变对一道。被救回的题里包括 T01、T10、T22、T29 这几道“问题里没线索”的题:新描述写清了使用场景,模型就能从“导出收到的邮件”“统计会话库”这样的说法对上去。T05(OpenReview)和 T11(Apple Photos)在所有模型、所有 index 条件下都没救回来,问题里既没有产品名也没有足够独特的场景。

grok 上看不出效果:改后救回 2 道,和单纯重跑救回的 2 道一样多;16 道里仍有 9 道一个 skill 都没打开;原本答对的抽样里还掉了 3 道(T03、T07、T23),而 T03、T07 的描述根本没改,掉分和 rep2 里的波动是同一量级。对一个不愿意去打开文件的模型,描述写得再好也没有用。

修前和修后的描述(修前是索引里实际显示的版本,截到 240 字符):

ai_session_profanity_rate(gpt、grok 没打开)

ai_session_search_archive(deepseek 没打开)

apple_photos(deepseek、gpt、grok 没打开)

asr(grok 没打开)

codex_cli(grok 没打开)

dataforseo(grok 没打开)

eink_diary(grok 没打开)

koyeb(grok 没打开)

openreview(deepseek、gpt、grok 没打开)

skill_image_generation(grok 没打开)

skill_opencode_data(deepseek、grok 没打开)

skill_process_launcher(gpt、grok 没打开)

skill_resend_email(deepseek、gpt、grok 没打开)

skill_typefully_twitter(grok 没打开)

speaker_notes(deepseek、gpt、grok 没打开)

video-scoring-audio(gpt 没打开)

workflow_bilibili_whisper_transcription(grok 没打开)

zun_music(grok 没打开)

可以看到原描述的几种毛病:只写“是什么”不写“什么时候用”(openreview、speaker_notes);描述被截断在半句(typefully 以冒号结尾,后面的列表没进索引);第一句话被提取成了一个默认模型名(bilibili);全英文,而用户用中文提问。改后的描述还有一个没控制住的变量:都换成了中文,平均也更长(全量索引从 6,682 涨到 7,804 token)。我们没法从这次实验里分开“写清使用场景”和“换成中文”各自的贡献。

判分可靠性

我们抽了 24 条判分(12 条判对、12 条判错,固定种子),逐条对照摘录和答案人工判:24 条里 21 条一致(spotcheck.json、spotcheck_review.json)。3 条不一致都是判官太严,而且集中在两道题上:T20 的判分要点要求写出“退出码 20”,但题目没问退出码;T16 的答案说接近当前时刻的时间戳“会被拒绝”,判官认为原文只说“可能被拒绝”。我们改了这两道题的判分要点(原版留在 tasks.json 的 rubric_original),只对这两道题重新判分。改之前的汇总在 results_before_rubric_fix.json:变化是 deepseek full_10 29→30,gpt-5 none 0→1、full_1 29→30、full_10 27→28、full_30 28→29、index 21→22、index_rep2 21→22,grok full_1 / full_10 / full_30 都是 26→27。结论的方向没有变。改后这 3 条都与人工判断一致。剩下的 21 条里没有发现判官放水的情况,判错的多半有实据(给了另一个数、另一个参数,或者拒答)。

none 条件下仍有 3 次答对:deepseek 的 T17 和 T25,gpt-5 的 T20(改判分要点之后,“先回底座再开始”这条可以靠常识猜到)。每道都只有一个模型答对,仍满足“不超过 1/3 的模型答对”的筛题规则。

注意事项

文件

正文怎么用

教材正文移出的细节

2026 年 10 月第三轮改写(v3)时,本实验拆分为两部分写入正文:2.7(ch02_07.md)使用只给对口 1 个 / 给 10 个 / 给 30 个 / 139 个全塞四档展示名义窗口与有效上下文的衰减和成本;2.8(ch02_08.md)使用只给对口 1 个 / 139 个全塞 / 只放索引(按需读)对比渐进式披露、路由错因(29/31 死在没打开对的文件)与改写 18 条描述的效果。下面这些实现细节只保留在本 README: