3519 字
约 11 分钟
3
使用 Skill 时,如何解决上下文窗口限制问题?

使用 Skill 时,如何解决上下文窗口限制问题?

在 Agent 系统里,Skill 是非常好用的能力封装。

比如:

PDF 处理 Skill
Excel 分析 Skill
网页抓取 Skill
代码生成 Skill
图片识别 Skill
邮件编写 Skill

每个 Skill 里面可能包含说明文档、使用规则、示例、脚本、参数定义、异常处理方式。

问题也随之来了:

Skill 内容一多,大模型的上下文窗口很容易被撑爆。

所以使用 Skill 时,不能简单粗暴地把所有内容一次性塞给大模型。

更好的做法是:

少量识别
按需加载
局部读取
结果压缩
外部存储

这篇文章就聊聊:使用 Skill 时,如何解决上下文窗口限制问题。


一、上下文窗口到底是什么?

可以把大模型的上下文窗口理解成一张工作台。

用户问题、历史对话、系统提示词、Skill 文档、工具返回结果,都会被放到这张工作台上。

模型只能看到工作台上的内容。

但这张工作台不是无限大的。

如果内容太多,就会出现几个问题:

放不下
成本升高
响应变慢
重点被稀释
模型容易抓错重点

所以,上下文窗口限制并不只是“Token 不够”的问题。

它更像是一个注意力管理问题。

内容越多,模型越难知道到底什么最重要。


二、为什么 Skill 特别容易占上下文?

因为 Skill 通常不是一句话,而是一包资料。

一个完整 Skill 可能长这样:

metadata.yaml
skill.md
examples/example-1.md
examples/example-2.md
scripts/helper.py
docs/faq.md
docs/best-practices.md

如果每次执行任务都把这些内容全部加载进去,就会非常浪费。

比如用户只是说:

帮我提取 PDF 里的标题

结果系统把 PDF Skill 的全部说明、全部示例、全部脚本都塞给模型。

这就像用户只想查一个单词,你却把整本字典都搬上桌。

能用,但很笨。


三、核心思路:不要一次性全部加载

解决上下文窗口限制的核心原则是:

模型当前需要什么,就只给什么。

不要让模型背完整个 Skill。

而是让模型先知道:

有哪些 Skill
哪个 Skill 可能相关
这个 Skill 怎么用
当前任务需要哪一小段说明

所以使用 Skill 时,最重要的不是“能不能加载”,而是“加载多少”。


四、第一招:只加载 Skill 元数据

第一层只加载最轻的信息。

比如:

name: pdf-processor
description: 处理 PDF 文件,支持文本提取、表格识别、表单解析

这一层通常只有几十个 Token。

它的作用是让模型知道:

系统里有这个能力
这个能力大概能解决什么问题

如果用户任务和 PDF 无关,就不继续加载 PDF Skill。

这样可以避免每次对话都把所有 Skill 文档塞进上下文。

这一层解决的是:

先识别,不展开。

五、第二招:任务匹配后再加载主文档

如果用户任务和某个 Skill 匹配,再加载它的主文档。

比如用户说:

帮我从 PDF 合同里提取甲方、乙方和金额

这时系统判断需要 PDF Skill,于是加载:

skill.md

主文档里一般放核心规则:

# PDF 处理 Skill

## 能力
- 提取文本
- 提取表格
- 提取表单字段

## 使用方式
当用户上传 PDF,并要求解析、提取、总结内容时使用。

## 输出格式
优先输出结构化 JSON。

注意,这里仍然不是加载全部资料。

只是加载最核心的使用说明。

这一层解决的是:

确定要用,再看说明。

六、第三招:需要细节时再加载附件

有时候主文档不够。

比如用户要求:

从 PDF 表单里提取字段,并按照指定 JSON 格式返回

这时可能需要加载示例:

examples/extract-form.md

如果需要执行复杂解析,还可能加载脚本说明:

scripts/pdf-helper.py

但是这些附件不应该默认加载。

只有当任务真的需要时才加载。

这就是渐进式引用:

元数据 → 主文档 → 示例 → 脚本

它解决的是:

先少后多,按需展开。

七、第四招:长文档切片,只取相关片段

有些 Skill 的主文档本身就很长。

比如一个 Excel Skill 可能包含:

读取表格
清洗数据
生成图表
透视分析
公式处理
异常值检测
导出文件

如果用户只问:

帮我生成一个柱状图

那就没必要加载“公式处理”和“透视分析”的内容。

更好的方式是把 Skill 文档切成多个小片段:

chunk_1:读取表格
chunk_2:数据清洗
chunk_3:生成图表
chunk_4:公式处理
chunk_5:导出文件

任务来了之后,只检索最相关的片段。

比如这次只加载:

chunk_3:生成图表
chunk_5:导出文件

这就像查书时只翻相关章节,而不是从第一页读到最后一页。

这一招解决的是:

文档可以很长,但每次只读相关部分。

八、第五招:把示例压缩成规则

示例很有用,但也很占 Token。

比如一个 Skill 里有 10 个完整示例,每个示例几百行。

如果全部塞进上下文,窗口很快就爆了。

更好的做法是先把示例沉淀成简短规则。

例如原始示例很多:

示例 1:提取合同字段
示例 2:提取发票字段
示例 3:提取简历字段
示例 4:提取报名表字段

可以压缩成规则:

字段提取任务优先输出 JSON。
字段不存在时返回空字符串。
金额字段保留原文单位。
日期字段统一为 yyyy-MM-dd。
不要编造 PDF 中不存在的信息。

这样模型不一定需要看完整示例,也能知道该怎么做。

这一招解决的是:

用规则代替大量样例。

九、第六招:给上下文做预算

上下文窗口虽然有限,但可以规划。

比如一次模型调用前,可以给不同内容分配预算:

系统提示词:10%
用户当前问题:15%
历史对话:15%
Skill 文档:30%
工具返回结果:20%
输出格式要求:10%

当然,实际系统里不一定真的按百分比写死。

但一定要有这个意识:

不是谁先来谁占位置,而是谁重要谁留下。

比如当前任务强依赖 Skill,那就减少历史对话。

如果当前任务强依赖用户上传文件,那就减少示例内容。

如果工具返回内容太长,就先摘要再放进去。

上下文管理的本质是排序:

最相关的留下
最不相关的丢掉
太长的先压缩
可以外部存的不要塞进来

十、第七招:中间结果放外部,别都塞回模型

很多人做 Agent 时容易犯一个错误:

每一步工具结果都完整塞回上下文。

比如 PDF 有 100 页,解析后得到几万字。

如果全部塞回模型,窗口肯定爆。

更合理的做法是:

完整内容放外部存储
上下文里只放摘要和引用地址
需要具体内容时再读取局部片段

比如:

{
  "fileId": "pdf_001",
  "summary": "这是一份采购合同,包含甲方、乙方、金额、交付时间等信息",
  "sections": [
    {
      "title": "合同主体",
      "range": "page 1-2"
    },
    {
      "title": "付款条款",
      "range": "page 5-6"
    }
  ]
}

模型不需要一开始看到全文。

它先看到摘要和结构。

如果后面要查付款条款,再读取第 5 到 6 页。

这一招解决的是:

上下文里放索引,不放全文。

十一、第八招:工具执行和模型理解分开

Skill 里经常会带脚本。

比如:

scripts/pdf-helper.py
scripts/excel-analyzer.py
scripts/image-cleaner.py

这些脚本不一定要完整塞给模型。

模型真正需要知道的是:

这个脚本能做什么
输入是什么
输出是什么
什么时候调用

而不是脚本每一行怎么写。

所以可以给模型看接口说明:

工具名:extract_pdf_text
输入:PDF 文件路径
输出:按页拆分的文本
用途:当用户要求读取 PDF 内容时使用

真正执行脚本的事情交给后端。

这样可以大幅减少上下文占用。

这一招解决的是:

模型负责决策,工具负责执行。

十二、第九招:历史对话也要裁剪

上下文窗口不只被 Skill 占用,历史对话也会占很多。

如果用户连续聊了很多轮,系统不能每次都把全部历史塞进去。

更好的做法是:

保留最近几轮
保留关键决策
压缩旧对话
丢弃无关闲聊

例如把长历史压缩成:

用户正在实现一个 Agent 工作流系统。
已讨论过图构建、参数传递、Function Calling、OpenAI 兼容协议。
当前正在讨论 Skill 的上下文管理。

这样模型仍然知道背景,但不用读取所有历史原文。

这一招解决的是:

历史要保留结论,不保留废话。

十三、第十招:输出格式单独保留,不能被挤掉

很多任务失败,不是模型能力不行,而是输出格式要求被上下文挤没了。

比如用户要求输出 JSON。

如果上下文太长,模型可能最后忘了格式要求。

所以建议把输出格式要求放在靠近末尾的位置,并保持简短明确。

比如:

请只输出 JSON,不要输出解释。
字段包括:name、amount、date。
缺失字段返回空字符串。

这类规则很短,但非常关键。

不要让它被大量 Skill 文档淹没。

这一招解决的是:

重要格式要求,要靠近最终调用位置。

十四、完整流程可以这样设计

使用 Skill 时,一个比较稳的上下文管理流程是:

用户提出任务
      ↓
加载 Skill 元数据
      ↓
匹配相关 Skill
      ↓
加载 Skill 主文档
      ↓
判断是否需要示例或脚本
      ↓
按需加载局部片段
      ↓
裁剪历史对话
      ↓
压缩工具返回结果
      ↓
构造最终 Prompt
      ↓
检查 Token 是否超限
      ↓
调用大模型

重点不是某一个技巧,而是整条链路都要控制上下文。


十五、一个简单例子

用户说:

帮我从这个 PDF 合同里提取甲方、乙方、金额和签署日期。

不要这样做:

加载全部 PDF Skill 文档
加载全部示例
加载全部脚本
加载 PDF 全文
加载完整历史对话
然后一起塞给模型

更好的做法是:

1. 通过元数据匹配到 PDF Skill
2. 加载 PDF Skill 主文档
3. 只加载“字段提取”相关片段
4. PDF 先由工具解析
5. 上下文里只放相关页面文本
6. 输出格式明确要求 JSON
7. 字段不存在返回空字符串

最终给模型的内容可以很精简:

任务:从合同文本中提取字段。

字段:
- 甲方
- 乙方
- 金额
- 签署日期

规则:
- 只根据文本提取,不要编造
- 找不到返回空字符串
- 只输出 JSON

合同相关片段:
……

这样上下文更短,模型也更容易抓住重点。


十六、最终总结

使用 Skill 时,解决上下文窗口限制的核心不是“换一个更长上下文的模型”。

更重要的是做好上下文管理。

可以总结成一句话:

Skill 不要一次性全量加载,而要按任务相关性逐步加载、局部读取、压缩表达。

常用方法包括:

只加载元数据
匹配后加载主文档
需要时加载附件
长文档切片检索
示例压缩成规则
工具结果先摘要
中间数据放外部
历史对话做裁剪
输出格式单独保留
调用前检查 Token

如果再压缩成一个架构原则,就是:

上下文窗口里只放当前任务最需要的内容。

Skill 系统真正成熟的标志,不是 Skill 文档写得有多大,而是系统能不能在正确的时候,加载正确的一小部分。

这样既能节省 Token,又能减少干扰,还能让模型更稳定地完成任务。

使用 Skill 时,如何解决上下文窗口限制问题?
http://www.clxhxhhr.top/posts/595/
作者
clxstart
发布于
2026-09-13
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。