你有没有遇到过这种情况:给 AI 塞了一大堆资料,它回答出来的内容却好像根本没读到你最想让它注意的那段?
你怀疑是自己写的 prompt 有问题,反复改措辞。但其实问题可能更根本:你给它的资料,排列方式错了。
这不是什么玄学。AI 模型在处理长文本时有一个有据可查的现象——研究者称之为「lost in the middle」效应。简单说,放在上下文中间的信息,模型的注意力会显著衰减;放在开头和结尾的,才是模型真正「看进去」的内容。
这个 Skill 解决的就是这类问题。它叫 Context Optimization,属于 h4vzz/awesome-ai-agent-skills 仓库中 context-engineering 分类下的一个 Agent Skill,设计目标是:让喂给模型的每一个 token,都真正挣到它的位置。
背景:上下文的「垃圾进垃圾出」
RAG 管道(检索增强生成)理论上很美好:先检索,再生成,输出有来源的答案。但工程上有一个常见的隐患:检索回来的内容,直接扔进去就用了。
这个隐患会带来三个问题:
第一,重复内容大量涌入。 在做文档切片(chunking)时,为了保证语义连贯,通常会用「重叠切片」——相邻两个 chunk 会共享若干行。结果就是同一段话以两三种略微不同的形式出现在上下文里,占掉宝贵的 token,却没有带来任何额外信息。
第二,低价值内容混入。 版权声明、导航栏文字、重复的页面头部、package.json 里的依赖列表——这些东西跑进来完全没有意义,但如果没有主动过滤,它们就在那里。
第三,重要信息被埋在中间。 就算检索到的内容是对的,如果把最关键的那段放在整个上下文的第 5 位,而前面有 3 段一般般的内容,模型的注意力分配就已经偏了。
Context Optimization 这个 Skill 要做的,是在内容进入提示词之前,对它进行一轮「精修」。
工作流:6 步,但顺序是有讲究的
原始 context(chunks + 分数 + 元数据) ↓① 审计:清点总 token,计算压缩空间 ↓② 去重:语义相似度 / n-gram 检测,保留最完整版本 ↓③ 评分:相关性 × 信息密度 = 复合效用分 ↓④ 过滤:去掉效用分低的,保留 top 60-70% ↓⑤ 重排:最高分放首,次高分放尾,中间放其余 ↓⑥ 验证:检查每个子问题是否还有 chunk 覆盖 ↓优化后的 context(精炼、有序、全覆盖)六步,但第一个设计决策藏在步骤顺序里。
设计决策一:去重必须发生在过滤之前
这条规则看起来平淡无奇,但它的理由让人印象深刻。
直觉上,你可能会先过滤(把不相关的扔掉),再去重(把重复的合并)。但 Skill 的设计是反过来的:先去重,再过滤。
为什么?因为「相关性分数」是在切片粒度上算的,而切片是有重叠的。假设你的问题是「退货政策是什么」,检索回来两个 chunk:一个来自政策文档(相关性 0.95),另一个来自 FAQ(相关性 0.88),但这两个 chunk 说的几乎是同一件事。
如果先过滤:两个都留下(分数都高),结果上下文里出现了两次差不多的内容。 如果先去重:识别出重复,保留分数更高的那个,然后再决定要不要过滤其他内容——这时你看到的是「不含重复的真实信息量」,过滤决策会更准确。
Skill 的 Best Practices 里原话是:「先去重才能看清到底有多少独特信息,这样过滤决策才有根基。」(Deduplicate before filtering — removing redundant passages first gives you a clearer picture of the unique information available. — h4vzz/awesome-ai-agent-skills,截至 2026 年 5 月)
去重的技术实现有两种:
语义相似度检测:cosine distance > 0.92 的两个 chunk,视为近似重复 n-gram 重叠检测:直接比较文本字符串级别的重叠比例
两种方法各有擅长。代码切片建议用 n-gram(代码有严格的字符意义);文档切片建议用语义相似度(同一段话可能换了说法)。
设计决策二:相关性 × 信息密度,复合分才是真分
这是整个 Skill 里我觉得最有设计感的一个决策。
大多数 RAG 系统在决定「留哪些 chunk」时,用的是检索分数——余弦相似度,或者重排序模型给出的相关性分。但 Skill 在这里引入了第二个维度:信息密度(information density)。
什么是信息密度?Skill 的定义是:单位 token 内包含的有用信息量。衡量方式是统计命名实体、代码标识符、数值数据、关键词的数量,除以 chunk 的 token 总数。
然后把两个分数相乘:复合效用分 = 相关性分 × 信息密度分。
打个比方。假设你在让 AI 帮你重构一段认证模块的代码,两个 chunk:
Chunk A: src/auth/login.js:1-45,相关性 0.93,高密度(有完整的函数逻辑、变量名、DB 调用)Chunk B: README.md:100-130,相关性 0.45,低密度(项目介绍、安装说明,没有代码)
单看相关性,A 远高于 B,你可能直接过滤掉 B。但如果还有另一个 Chunk C:相关性 0.50,但密度极高(一个关键的 token refresh 逻辑,7 行就说清楚了),它的复合效用分可能反而高于 B。
这个机制解决了一个真实的问题:高相关性不等于高价值。一段 400 token 的套话,里面只有一个有用的句子;一段 50 token 的代码,每行都有意义——如果只看相关性,前者可能留下来,后者可能被挤掉。

设计决策三:重排序是反「lost in the middle」的工程手段
说到这里,就必须认真讲一下「lost in the middle」了,因为整个重排序步骤(Reorder by Priority)的存在,完全是为了对抗这个效应。
「Lost in the Middle」是什么? 研究者发现(斯坦福大学 2023 年的论文 Lost in the Middle: How Language Models Use Long Contexts),当上下文变长时,语言模型对放在中间部分的内容的注意力会系统性地衰减。最开头的内容和最末尾的内容,模型能更好地「记住」和「使用」;而夹在中间的内容,即便是关键信息,也可能被忽略。
Skill 的重排策略非常直接:
“最高效用分的 chunk → 放第一位第二高效用分的 chunk → 放最后一位其余的 chunk → 按分数降序填中间
这不是随机优化,而是有理论依据的位置编排。对于一个 32K token 的上下文窗口,这个策略的收益非常明显——Skill 说,这种效果在 context window 超过 8K token 之后尤为显著。(h4vzz/awesome-ai-agent-skills,截至 2026 年 5 月)
有一个细节值得关注:「lost in the middle 的程度因模型架构而异」——不同模型的注意力衰减曲线不同,最好实测验证,而不是假设所有模型表现一致。Skill 的 Best Practices 里也特别提到了这一点。
设计决策四:按 context window 大小换策略
这一条揭示了一个容易被忽视的事实:优化策略不是通用的,窗口大小本身就是一个关键变量。
Skill 把优化策略分成了三档:
| 4K token | ||
| 32K token | ||
| 128K+ token |
最反直觉的一条是最后一行:128K 的大窗口,lost-in-the-middle 效应反而更严重。
这是为什么?想象一下,一个 128K 的上下文就像一篇超长报告,模型需要「跨越」更长的距离才能把开头的信息和结尾的信息联系起来——中间的部分被稀释得更彻底。小窗口反而因为总量有限,每个位置的权重差异没那么极端。
所以如果你用的是 GPT-4o 或 Claude 的超大窗口模式,喂进去 100 个 chunk 却以为「反正放得下,不用在意顺序」,这个认知需要更新。大窗口提供了容量,但不免除你对顺序的责任。

设计决策五:过滤要留日志,因为你早晚要来 debug
这条规则看起来是工程实践,但它背后的逻辑是一个很深的认知:你的过滤决策会导致模型回答不完整,而你第一次不会意识到这是过滤的问题。
Skill 的 Best Practices 里明确写道:「记录哪些 chunk 被移除了、为什么被移除。这样当模型给出不完整的答案时,你才能追溯是不是某个关键 chunk 被过滤掉了。」
这一条来自真实踩坑。当你问 AI「退货政策和保修条款分别是什么」,它只回答了退货政策,只字未提保修——你大概率会先去检查 prompt,或者怀疑模型没有理解你的问题。但真正的原因可能是:保修相关的 chunk,在过滤阶段因为分数不够被扔掉了。
如果没有过滤日志,这个 bug 几乎不可调试。
配合这条规则的还有一个相关的 Edge Case 处理:覆盖度验证(Validate Coverage)。在过滤之后,Skill 要求做一次「查漏」——如果用户的问题包含多个子问题,确保每个子问题都还有至少一个 chunk 覆盖到它。即便那个 chunk 的效用分低于阈值,为了覆盖度也要把它保留。
这个设计体现了一个权衡:「精炼」和「完整」有时候是矛盾的,覆盖度验证是在说「完整优先于精炼」。
横向对比:这个 Skill 在 context-engineering 里处于什么位置
到目前为止,这个系列已经拆解了 context-engineering 下的三个 Skill:
| context-compression | ||
| context-ranking | ||
| context-optimization |
三个 Skill 的关系是流水线关系,而不是竞争关系。一个完整的 RAG 管道,大致是先 retrieval → 再 ranking → 再 optimization → 最后 compression(如果还超长的话)。
有一个有趣的重叠:ranking 和 optimization 都涉及「重排序」,但出发点不同。Ranking 的重排是为了「让最相关的排在前面」;Optimization 的重排是为了「让最重要的出现在模型注意力最强的位置」。前者是相关性驱动,后者是注意力机制驱动。

结尾:上下文质量是个系统问题
这几个 context-engineering 的 Skill,拆解下来有一个共同的底层逻辑:进入模型的信息质量,是人为可干预的,不是随机的。
检索回来 20 个 chunk,不是扔进去就完事了。每一个 chunk 都带着自己的「注意力成本」——它会稀释其他 chunk 的权重。你往上下文里塞的每一条内容,都在影响模型最终「注意到」什么。
Skill 的存在是在做一件事:把这个干预过程系统化、可重复。
但有一件事这些 Skill 都不能替你做:判断哪些信息在你的具体场景里是真的重要。阈值是多少,哪个子问题不能遗漏,上下文密度的定义是不是符合你的领域——这些都是人的判断。
所谓「优化上下文」,最终优化的,是你对自己任务的理解清不清楚。
夜雨聆风