OpenClaw 插件 SmartContext 开发解析(中篇):五层优先级如何教会 LLM 分清主次
上篇我们讨论了痛点定位和架构决策。现在进入一个更具体的问题:如何设计一套规则,让 LLM 能够可靠地判断什么信息比什么信息更重要?
这个问题比听起来难。传统的做法是在 Prompt 里写“请重点关注重要信息”——这等于没说。另一种做法是给一个简单的三档分类(高/中/低优先级),但 LLM 对“高优先级”的理解会因上下文漂移:今天它觉得 API 契约是高优先级,明天可能觉得代码格式也是高优先级。
SmartContext 给出的答案是:五层分级体系(Tier 0–4),每层有明确的语义定义和典型内容举例,并且每条规则都标注来源领域。
01
—
为什么是五层,不是三层或七层
三层(高/中/低)的问题在于:中间档太宽。架构决策和功能需求都塞进“中优先级”,模型无法区分。七层又过于精细,大部分场景用不到,且增加 Prompt 长度。
五层是一个经验上合理的粒度:
-
Tier 0 – 始终优先(绝不能忽视):数量最少,优先级最高。包括用户明确标记的内容、硬性约束(“必须/一定不能”)、架构级决策。
-
Tier 1 – 最高优先级关注:代码审查意见、性能优化方案、安全设计、API 契约。这些是专业对话的核心产出。
-
Tier 2 – 高优先级注意:功能需求、详细设计、测试用例、决策演进链。比 Tier 1 低一档,但仍需重点保留。
-
Tier 3 – 记住这些:编码规范、项目配置、调试记录、待办事项。需要记住,但在 token 紧张时可以被压缩。
-
Tier 4 – 可以简要参考:通用知识、确认性回复、重复内容、第三方文档。可以被丢弃。
这个分层有一个关键特征:Tier 0–2 不随时间衰减,Tier 3–4 可以衰减。这是从实际工程教训中提炼的规则——架构决策不会因为过了三天就变得不重要,但一条调试信息确实会过时。
—
让规则“可执行”:从语义到具体类型
很多 Prompt 工程失败的原因是指令太抽象。“关注重要信息”是语义级的,模型不知道什么是“重要”。
SmartContext 的做法是:不写“重要”,写具体的信息类型。
看一个 Tier 0 的实际条目:
已确认的架构决策:技术选型、架构风格、系统边界、模块划分
带有“必须”“一定不能”“绝对不要”等强约束信号的信息
用户独有的、LLM 自身知识库中不可能有的特殊约束
这些不是抽象的描述,而是可匹配的模式。模型看到用户说“数据库必须使用 PostgreSQL”,触发“强约束信号”模式,归入 Tier 0。看到“我们之前讨论过用 Redis 做缓存”,没有强约束词,但属于“已确认的架构决策”,也归入 Tier 0。
这种设计让判断变得可操作,而不是依赖模型的“理解力”。
03
—
Skill:领域规则的容器
不同领域的重要性判断标准不同。软件工程认为 API 契约是 Tier 1,生物信息学认为实验原始数据是 Tier 0。硬编码在插件里是不可能的——领域太多,且用户需要自己扩展。
SmartContext 采用了 OpenClaw 原生的 Skill 机制。每个 Skill 是一个 Markdown 文件,放在 skills/smartcontext-{domain}/SKILL.md中,格式固定:
# SmartContext Skill: 软件工程## 领域摘要...## 优先级声明高/中/低## 优先级指南 (Tier 0–4)### Tier 0 — ...- 条目1- 条目2## 动态调整规则...## 用户角色适配...## 跨领域协作...
插件启动时,扫描 skills/目录下所有 smartcontext-*文件夹,加载被用户启用的领域 Skill。新增领域不需要改代码,只需要添加一个新的 Skill 文件。
这个设计的核心价值是:规则与代码分离。领域专家(而不是插件开发者)可以编写和维护 Skill。插件只负责解析和注入。
04
—
多领域组合:冲突怎么解决
用户可能同时启用多个领域,比如软件工程 + 生物信息学。两个领域对同一类信息的判断可能冲突。
SmartContext 的处理策略是:
-
取并集:各领域的 Tier 条目合并,每条标注来源领域。
-
优先级声明:每个 Skill 有一个
优先级声明字段(高/中/低),冲突时高优先级领域覆盖低优先级。 -
跨领域协作规则:Skill 中可以声明与特定领域协作时的特殊规则。例如软件工程的 Skill 里写:“与医疗领域协作时,涉及数据隐私的条目无条件优先。”
-
冲突仲裁:当无法通过上述规则解决时,保留双方,但标注冲突和仲裁依据。
实际 Prompt 中会呈现为:
## Tier 0- [software-engineering] 已确认的架构决策- [bioinformatics] 实验原始数据(与软件工程 Tier 3 冲突,按优先级声明归入 Tier 0)
这种显式标注让用户(和模型)都能看到冲突是如何解决的,而不是黑盒处理。
05
—
角色适配:让规则响应“谁在问”
同一个领域,不同角色的用户关注点不同。前端工程师更在意 UI 约束,后端工程师更在意 API 契约。
SmartContext 通过 roleTags配置和 Skill 中的“用户角色适配”表格实现动态调整:
## 用户角色适配| 标签 | 提升项 | 调整 ||------|--------|------|| frontend | UI 约束、组件设计、样式方案 | 相关条目 +1 Tier || backend | API 契约、数据库设计、性能指标 | 相关条目 +1 Tier |
用户设置 /smartcontext-set-role frontend typescript后,引擎会在生成准则时,将匹配 frontend标签的条目(如“UI 约束”)从原 Tier 提升一级。
注意这里是“提升”,不是“覆盖”。Tier 0 的条目不会被提升到更高(因为没有更高),但 Tier 2 可以提升到 Tier 1。这种设计保持了原始规则的语义,同时允许个性化微调。
06
—
动态调整:对话过程中的规则演化
除了静态的 Tier 分级,SmartContext 还定义了几条动态调整规则,在对话过程中实时生效:
-
引用频率提升:被用户反复提及的信息 → 提升 1 个 Tier。
-
跨阶段引用临时提升:当前讨论阶段与信息所属阶段不同但被引用 → 临时提升至 Tier 2。
-
时间衰减(仅 Tier 3–4):超过一定轮数未提及 → 降低关注度。Tier 0–2 不衰减。
-
依赖关系同步提升:被 Tier 0–1 信息直接引用的内容 → 同步提升至该 Tier。
-
冲突处理:矛盾信息保留最新版 + 否决原因;架构级冲突保留完整演进链。
这些规则不是由 SmartContext 代码执行的——插件不维护对话状态,也不做实时追踪。它们是以自然语言形式写入 Prompt 的指令,由 LLM 在生成回答时自行遵守。
这看起来像是“把责任推给模型”,但实际上是经过考量的设计。动态规则需要理解语义(“这个信息是被反复提及的吗”),这正是 LLM 擅长的。插件做不了,也不应该做。
07
—
Prompt 优化:如何让 LLM 真正执行
有了分级体系和规则,最后一步是把它们写进 Prompt,并且确保 LLM 会遵守。
SmartContext 的 Prompt 设计有几个关键细节:
1. 关键上下文前置
[Context]- 当前活跃领域: 软件工程(主领域)- 用户角色标签: frontend, typescript- 标记内容: "本项目使用 TypeScript"
放在 Prompt 开头,让模型在阅读具体规则之前就获得全局视角。
2. 指令强度用明确词汇
不是“可以考虑”,而是“始终优先(绝不能忽视)”。不是“应该关注”,而是“最高优先级关注”。
3. 规则标注来源
每条规则前加 [software-engineering],方便模型追溯规则出处,也方便调试。
4. 提供示例
对于复杂的动态规则,给出具体例子。例如:
例: 某 API 契约被反复引用 → 从 Tier 2 提升到 Tier 1
示例将抽象规则具象化,显著提升执行一致性。
5. 分级 Token 预算
Prompt 中明确暗示:Tier 0–1 的内容要详细保留,Tier 4 的内容可以忽略。这相当于给模型一个“内存分配策略”。
08
—
小结
中篇的核心是回答了“如何设计一套可执行的优先级规则”。我们得到了几个关键结论:
-
五层分级比三层或七层更实用,且 Tier 0–2 不衰减、Tier 3–4 可衰减。
-
规则必须具体到信息类型,而不是抽象的重要性描述。
-
Skill 机制实现了规则与代码分离,支持无限领域扩展。
-
多领域组合通过并集、优先级声明、跨领域规则解决冲突。
-
角色适配和动态调整让规则能够响应上下文变化。
-
Prompt 工程的细节(前置上下文、强度词汇、来源标注、示例)决定了规则是否被有效执行。
规则设计好了,但工程实现中还有很多坑:Skill 文件损坏怎么办?配置持久化怎么设计?一个扩展加载失败要不要让整个插件崩溃?
这些是下篇要讨论的内容。
夜雨聆风