refactor: layer fast slow routing knowledge

This commit is contained in:
wuyang6
2026-07-23 21:35:18 +08:00
parent 6116d10e8f
commit ecc02c06b7
21 changed files with 776 additions and 925 deletions
+81 -132
View File
@@ -1,191 +1,140 @@
--- ---
name: label-fast-slow-routing name: label-fast-slow-routing
description: 依据 XA4.1 2026.6 新标准,对单条或批量 query、带会话上下文的请求和快慢分流评测数据进行“快 / 慢 / 模糊”三档可解释打标,给出默认路由、原因码、证据、置信度和复核标记,并在需要时兼容旧 FAST_DIRECT / SLOW_* 评测标签。用于快慢系统策略标注、评测集重标、边界 case 仲裁、标注 Prompt 编写、标签一致性检查和 badcase 分析;可结合相邻 label-master skill 判断业务领域、候选标签、复杂度、多指令和自动任务,但不得把这些辅助维度直接等同于快慢标签 description: 依据 2026.7 产品标准,对单条或批量 query 进行“快 / 慢 / 模糊”三档可解释打标。先用精简标签知识召回垂域,再优先应用垂域规则;未覆盖时依次使用多指令、自动任务等结构规则和产品核心原则,并输出决策层级、规则 ID、证据、冲突和能力承接状态。用于快慢分流标注、评测、边界仲裁和 badcase 分析
--- ---
# 快慢分流打标 # 快慢分流打标
## 目标 ## 目标
按用户对响应速度和结果质量的预期判断语义标签,不按当前系统能力反推标签。始终分开输出: 按用户对响应速度和结果质量的预期判断 `快``慢``模糊`。业务垂域、结构信号和当前系统能力只参与解释与路由,不代替语义标签。
- `label``快``慢``模糊` ## 渐进加载
- `default_route`:三档标签的默认系统策略。
- `fast_system_pending`:已确认的快系统能力缺口。
- 业务标签及 `complex`、多指令、自动任务等辅助维度。
## 加载知识 每条 case 按下面顺序读取,命中后及时停止,不要加载整个 `references/`
1. 每次打标前读取 [references/policy.md](references/policy.md)。 1. 第一动作读取 [references/index.md](references/index.md),完成垂域召回和结构信号预判;垂域不明显或命中召回边界时,再读取 [references/preclassification.md](references/preclassification.md)。
2. 处理边界 case、校准标注员或编写 Prompt 时,读取 [references/golden-examples.md](references/golden-examples.md) 2. 读取一个主垂域卡;只有主垂域确实无法确定时,读取第二个候选垂域卡
3. 迁移旧评测集、输出 `FAST_DIRECT` / `SLOW_*`、设计评测集或做质检时,再读取 [references/legacy-eval-and-quality.md](references/legacy-eval-and-quality.md) 3. 出现多指令或自动任务信号时,再读取对应结构卡。自动任务还要读取自动化垂域卡
4. 需要业务领域、业务标签、候选标签或结构维度时,按“结合 label-master”一节渐进加载相邻知识;不要一次读取整个知识库 4. 垂域和结构卡都没有明确覆盖时,才读取 [references/core-policy.md](references/core-policy.md)
5. 命中标记为冲突的规则,或做规则维护时,再读取 [references/policy-conflicts.md](references/policy-conflicts.md)。
6. 处理边界样本或校准时,按需读取 [references/golden-examples.md](references/golden-examples.md)。
## 遵守真源优先级 普通 case 通常只需读取索引和一个垂域卡。不要运行时读取相邻 `label-master`;本 Skill 已包含所需的精简知识快照。
按以下顺序处理冲突: ## 决策优先级
1. 用户在当前任务中明确给出的已批准新口径。 按以下优先级裁决:
2. 《【XA4.1】快慢分流新标准-2026.6》最终汇总(物理页 7–10)。
3. 同文档的垂域调研细则(物理页 2–7),仅补充最终汇总未覆盖的场景。
4. 《快慢系统分发-评测集构建》的旧八类标签,仅用于原因解释、旧数据迁移和评测方法。
5. `label-master` 的业务标签与正交维度,仅用于辅助理解。
明确处理以下冲突: 1. 用户当前任务明确给出的已批准口径。
2. 2026.7 产品文档中的明确垂域规则。
3. 2026.7 跨垂域结构规则。
4. 2026.7 产品核心原则。
5. 快系统能力状态,只记录承接情况,不修改语义标签。
- 把“导航去附近评分 4.5 以上的泰国菜”标为 `快`,不要沿用旧的筛选即慢 垂域规则和核心原则冲突时,以垂域规则为最终结论,并记录 `policy_conflict=true` 和冲突证据
- 把“那个压线噔噔的声音关掉”标为 `快`,前提是功能可唯一识别且动作明确。
- 把纯静态产品知识、故障诊断、设备或环境状态查询标为 `模糊`,不要直接沿用旧的快或慢。
- 把多个全部明确的设备控制动作标为 `快`;不要仅因多指令就标慢。
- 不要使用“长度不超过 5 字默认快”。它只是旧候选挖掘捷径,不是语义规则。
## 执行工作流 ## 工作流
### 1. 整理输入 1. 提取当前 query、前轮、设备、端侧、时间窗口和已提供的能力清单。
2. 使用索引输出一个主垂域、最多两个候选垂域,以及多指令、自动任务、上下文依赖信号。
3. 读取主垂域卡并查找明确规则。命中时设置 `decision_level="domain"`
4. 未命中垂域规则时检查结构卡。命中时设置 `decision_level="structure"`
5. 仍未命中时使用核心原则,设置 `decision_level="core"`
6. 做反证检查,说明为什么没有选择其他档位。
7. 只在有明确能力清单或验证结果时填写 `fast_system_pending`;未检查时填 `null`
8. 需要完整落盘时,按 schema 输出并运行校验脚本。
提取并保留: ## 输出
- 当前 `query` 默认返回简短结论:
- 已提供的前轮、系统回复、时间窗口、设备、端侧和场景。
- 用户要求的输出格式和旧标签兼容要求。
- 已提供的快系统能力清单;没有清单时不要猜测能力支持状态。
只使用可见上下文。缺少会改变结论的上下文时,保留不确定点并设置 `review_required=true` ```text
标签:慢
判断层级:导航/生服垂域
命中规则:NAV_SLOW_CONDITIONED_POI
依据:单地点规划带明确筛选条件,命中导航垂域慢规则。
```
### 2. 判断业务与结构辅助信息 如果外层评测协议只接受 `prediction``reason` 等通用字段,把层级和规则 ID
写在 `reason` 开头,例如:
需要时使用 `label-master` 判断: ```text
[domain:NAV_SLOW_CONDITIONED_POI] 单地点规划带明确筛选条件,按导航垂域给慢。
```
- 业务领域和 2–5 个候选业务标签。 需要落盘、批量评测或用户要求完整记录时,输出符合 [schemas/label-record.schema.json](schemas/label-record.schema.json) 的对象:
- 是否为多指令、自动任务或 `complex`
- 当前轮是否真正依赖上文。
保持这些结果与快慢标签正交。特别注意:
- `complex=true` 不自动等于 `慢`
- 多指令不自动等于 `慢`
- 自动任务要结合端侧专项策略。
- 业务标签不自动决定快慢。
### 3. 按三档策略裁决
使用 [references/policy.md](references/policy.md) 的完整决策树。执行以下最小顺序:
1. 先区分纯信息获取和带副作用的执行请求。
2. 对执行请求,先检查是否必须反推意图、映射场景、消歧、补槽、依赖上下文或规划多步;命中则倾向 `慢`
3. 再检查动作和目标能否直接识别、是否无需先决定“做什么”;满足则标 `快`
4. 对纯闲聊、开放问答、产品知识、故障诊断、设备或环境状态查询标 `模糊`
5. 无法可靠归入快或慢、或速度和质量预期同时明显存在时标 `模糊`,不要把“模型自己不确定”伪装成确定标签。
6. 聚合多个子请求时使用 `慢 > 模糊 > 快`;多个全部明确的设备控制动作使用 `快`特例。
同时做反证检查:说明为什么没有选择另外两档。不要只凭关键词命中一个规则。
### 4. 确定默认路由和能力状态
按固定映射填写:
- `快``default_route="快系统"`
- `慢``default_route="慢系统"`
- `模糊` → 默认 `default_route="慢系统"`;只有用户另给细分部署策略时才在下游覆盖,语义标签保持 `模糊`
仅在有明确能力清单或验证结果证明“语义上应为快,但当前快系统尚不支持”时填写 `fast_system_pending=true`。没有检查能力时填 `null`,不要填 `false` 假装已验证。
### 5. 生成可审查结果
默认每条样本输出一个符合 [schemas/label-record.schema.json](schemas/label-record.schema.json) 的 JSON 对象:
```json ```json
{ {
"query": "太冷了,调一下空调", "query": "导航去附近评分4.5以上的泰国菜",
"label": "", "label": "",
"default_route": "系统", "default_route": "系统",
"primary_reason_code": "DIRECT_ACTION", "domain": "导航/生服",
"reason_codes": ["DIRECT_ACTION"], "candidate_domains": ["导航/生服"],
"reason": "用户明确给出调节动作和空调对象,无需反推要操作什么。", "decision_level": "domain",
"evidence": ["“调一下空调”同时包含动作和可识别对象"], "decision_rule_id": "NAV_SLOW_CONDITIONED_POI",
"counterevidence": ["含感受词“太冷”,但感受词不覆盖明确执行目标"], "decision_source": "references/domain-navigation-life.md",
"domain_label": "设备控制", "decision_path": [
"candidate_domain_labels": ["设备控制", "车载控制"], "preclassification:导航/生服",
"domain:NAV_SLOW_CONDITIONED_POI"
],
"reason": "单地点规划带明确筛选条件,命中导航垂域慢规则。",
"evidence": ["“评分4.5以上”是明确筛选条件"],
"counterevidence": ["核心快规则把目标明确的简单条件操作视为快"],
"structural_signals": { "structural_signals": {
"complex": null, "complex": null,
"multi_instruction": false, "multi_instruction": false,
"auto_task": false "auto_task": false,
"context_dependent": false
}, },
"context_used": false, "context_used": false,
"fast_system_pending": null, "fast_system_pending": null,
"legacy_eval_label": "FAST_DIRECT", "route_override": null,
"policy_conflict": true,
"conflict_refs": ["CONFLICT_NAV_CONDITIONED_POI"],
"confidence": "high", "confidence": "high",
"review_required": false, "review_required": false,
"uncertainties": [], "uncertainties": [],
"policy_version": "XA4.1-2026.6" "policy_version": "FAST-SLOW-2026.7"
} }
``` ```
使用 `null` 表示未评估,不要猜测值补齐辅助字段。用户只要求简表时至少保留 `query``label``primary_reason_code``reason``review_required`;落盘数据仍使用完整契约 使用 `null` 表示未评估,不要猜测端侧、上下文、能力状态或复杂度
### 6. 校验后再落盘 ## 校验
单条结果执行 单条记录
```bash ```bash
python skills/label-fast-slow-routing/scripts/validate_label.py \ python scripts/validate_label.py --record '<JSON object>'
--record '{"query":"开空调","label":"快","default_route":"快系统","primary_reason_code":"DIRECT_ACTION","reason_codes":["DIRECT_ACTION"],"reason":"动作和对象明确。","evidence":["开+空调"],"context_used":false,"fast_system_pending":null,"confidence":"high","review_required":false,"uncertainties":[],"policy_version":"XA4.1-2026.6"}'
``` ```
JSONJSONL 文件执行 JSONJSONL
```bash ```bash
python skills/label-fast-slow-routing/scripts/validate_label.py \ python scripts/validate_label.py --file output/fast_slow_labels.jsonl
--file output/fast_slow_labels.jsonl
``` ```
出现 `valid=false` 时先修正结构和不变量,再写入训练集或评测集。校验器只保证结构和跨字段一致性,不能替代语义复核 校验器会检查字段不变量、决策层级、知识来源文件和规则 ID。结构通过不代表语义正确
## 结合 label-master
需要业务标签时按以下最短路径读取:
1. 读取 `../label-master/knowledge/决策流程.md`
2. 读取 `../label-master/knowledge/索引/候选召回索引.md``../label-master/knowledge/标签总览.md`
3.`../label-master/knowledge/索引/标签索引.md` 召回 25 个候选。
4. 命中高频混淆时读取对应边界卡,再读取候选标签卡。
5. 只在任务需要时读取复杂度、多指令或自动任务文件。
复用它的“候选召回 → 边界比较 → 排除理由 → 不确定点”方法,不复用它的 `Agent` / function target 作为快慢输出。
`label-master` 与本策略冲突时:
- 保留其业务标签与结构维度结论。
- 按本 skill 的真源优先级独立重算快慢标签。
-`counterevidence` 中记录冲突,不静默覆盖。
## 批量与评测集要求
- 保留原始 ID、query、上下文和来源,不修改原始数据。
- 逐条执行完整语义判断,不按字数、关键词或既有类别比例直接定标。
- 对同一 session 使用相同的上下文截取规则;缺上下文样本单独标记。
-`模糊` 保留为语义标签;需要二值评测时另派生默认路由,不要覆盖原标签。
- 旧八类标签只写入 `legacy_eval_label`;无法无损映射时填 `null` 并解释。
- 对高流量、高分歧、高风险误分样本优先双人盲标并仲裁。
- 分别统计三档标签、垂域、端侧和方向性错误;不要只看总准确率。
## 复核门禁 ## 复核门禁
满足任一情况时设置 `review_required=true` 满足任一情况时设置 `review_required=true`
- 缺少会改变标签的前轮、设备或端侧信息。 - 缺少会改变垂域或标签的前轮、端侧或设备信息。
- 快慢规则同时有强证据,且优先级无法消解 - 两个同优先级规则给出不同结论
- 只能依赖未确认的系统能力或白名单 - 自动任务端侧未知,且不同端侧策略不同
- 旧标签无法无损迁移到新三档 - 只能依赖未确认的能力清单
- `confidence="low"` - `confidence="low"`
`模糊` 不自动等于需要人工复核。产品知识或状态查询可以高置信地标为 `模糊` 已由优先级解决的产品文档冲突只需记录,不自动要求人工复核
## 禁止事项 ## 禁止事项
-要因快系统当前不支持而把 `快`改成 `慢` -按字数、句长、关键词数量或既有标签比例直接定标
-要把 `complex=true`、长 query、联网、搜索、排序、模糊词或多轮中的任一项当成单独硬触发器 -因快系统当前不支持而把 `快`改成`慢`
-要把非标准叫法等同于真实歧义;先判断对象能否唯一识别 -`complex=true` 直接等同于`慢`
-要脑补前轮、设备位置、说话人位置或能力清单 -把所有多指令或自动任务无条件判慢,必须检查专项例外
-要把旧评测集的样本占比当成先验配额 -使用 2026.6、`FAST_DIRECT``SLOW_*` 旧策略
-输出没有证据或排除理由的裸标签。 - 不输出没有规则 ID、证据和判断层级的裸标签。
@@ -1,4 +1,4 @@
interface: interface:
display_name: "快慢分流打标" display_name: "快慢分流打标"
short_description: "依据 2026.6 新标准完成快、慢、模糊三档可解释打标" short_description: "依据 2026.7 标准按垂域、结构和核心原则分层打标"
default_prompt: "Use $label-fast-slow-routing to label these queries as 快、慢或模糊并给出可复核依据。" default_prompt: "Use $label-fast-slow-routing to label these queries as 快、慢或模糊并给出可复核依据。"
@@ -0,0 +1,47 @@
# 2026.7 核心原则
本文件只在垂域和结构规则没有明确覆盖时作为兜底。
## 三档定义
| 标签 | 用户状态 | 定义 | 默认路由 |
| --- | --- | --- | --- |
| 快 | 操控 | 期望说完即得,延迟敏感 | 快系统 |
| 慢 | 委托 | 能接受等待,期待系统推理、规划或生成高质量结果 | 慢系统 |
| 模糊 | 问询 | 速度和质量都重要,或难以明确归类 | 慢系统 |
核心问题:用户说出这句话时,能接受等多久?
## 快
- `CORE_FAST_DIRECT_ACTION`:操作目标明确,动作和对象可直接识别,不需要先决定做什么。
- `CORE_FAST_OPERATION_FLOW`:用户正在明确操作流中执行直接动作。
- `CORE_FAST_DETERMINISTIC_QUERY`:高频、结果唯一、无需加工的确定性工具查询。
条件修饰、感受描述和非标准叫法不会自动变慢。只要动作与目标仍然明确,保持快。
## 慢
- `CORE_SLOW_INTENT_INFERENCE`:只表达感受、状态或不满,没有明确动作和功能,需要反推动作。
- `CORE_SLOW_SCENE_MAPPING`:描述想达到的场景或氛围,需要映射成一组操作。
- `CORE_SLOW_MULTI_STEP_PLANNING`:需要多步计算、换算、跨源聚合、上下文推理或先规划再执行。
- `CORE_SLOW_TRUE_DISAMBIGUATION`:存在真实多候选或必需槽位缺失,需要澄清或推断。
## 模糊
- `CORE_AMBIGUOUS_OPEN_QA`:闲聊或不属于明确垂域的开放问答。
- `CORE_AMBIGUOUS_PRODUCT_QA`:没有更具体垂域规则覆盖的产品知识、故障咨询。
- `CORE_AMBIGUOUS_STATE_QUERY`:没有更具体垂域规则覆盖的设备或环境信息查询。
- `CORE_AMBIGUOUS_POLICY_GAP`:快慢证据同时存在,当前规则没有明确优先级。
`模糊`不代表模型没把握。规则明确规定的模糊场景可以是高置信结果。
## 能力承接
语义上应为快、但当前快系统未支持时:
- `label` 保持 `快`
- 有能力清单或验证证据时设置 `fast_system_pending=true`
- 没有检查能力时设置 `fast_system_pending=null`
禁止根据当前 parser、白名单、接口或模型能力反推语义标签。
@@ -0,0 +1,18 @@
# 自动化垂域
使用前先读取 `references/structure-automation.md`,确认 query 确实是条件触发任务或自动化管理。
## 音箱 / 家庭自动化
- `AUTO_SLOW_HOME_AUTOMATION`:音箱端家庭自动化默认慢,包括明确触发动作和意向化自动化设计。
## 车载自动化
- `AUTO_FAST_CAR_REMINDER`:车载闹钟或条件提醒给快。
- `AUTO_SLOW_CAR_REGULAR_TASK`:车载常规条件任务语义上按慢记录,并设置 `route_override="座舱AC"`
## 未知端侧
- `AUTO_AMBIGUOUS_ENDPOINT_UNKNOWN`:端侧未知且音箱、车载策略会产生不同结论时,给模糊并设置 `review_required=true`
无条件创建普通闹钟、提醒或日程不属于自动任务,回到通用工具垂域。
@@ -0,0 +1,27 @@
# 车控垂域
适用于车辆设备、驾驶功能和座舱能力的执行控制。
## 慢
- `CAR_SLOW_INTENT_EXPRESSION`:只表达冷、热、刺眼、拥挤等感受,没有明确功能或动作。
- `CAR_SLOW_SCENE_EXPRESSION`:只描述会议、睡眠、节日氛围等场景目标,需要组合车辆功能。
- `CAR_SLOW_FUZZY_FUNCTION`:不知道功能名称,以模糊描述指代车辆功能。
- `CAR_SLOW_MULTI_POSITION_REASONING`:包含位置选择、排除或复杂设备逻辑。
- `CAR_SLOW_CONFIRMATION_CHAIN`:前轮慢系统主动询问,当前轮只表达确认、取消或简短执行。
## 快
- `CAR_FAST_EXPLICIT_CONTROL`:除上述慢场景外,动作、车辆设备或功能可直接识别。
- `CAR_FAST_EXPLICIT_MULTI_CONTROL`:多个动作全部是明确车辆设备控制,且不需要规划依赖。
## 冲突标记
`CAR_SLOW_FUZZY_FUNCTION` 与核心汇总中的“非标准叫法但可识别时给快”冲突。按垂域优先给慢,并记录:
```text
policy_conflict=true
conflict_refs=["CONFLICT_CAR_FUZZY_FUNCTION"]
```
示例“那个压线噔噔的声音关掉”在本层级判慢。
@@ -0,0 +1,27 @@
# 内容垂域
适用于音乐、视频、电台、新闻、歌单、内容搜索、播放控制和内容问答。
## 慢
- `CONTENT_SLOW_DESCRIPTION_SEARCH`:依赖描述性语言识别资源。
- `CONTENT_SLOW_QA`:内容知识问答或需要生成 answer。
- `CONTENT_SLOW_SCENE_RECOMMENDATION`:按场景进行内容推荐。
- `CONTENT_SLOW_LYRIC_SEARCH`:根据歌词片段搜索资源。
- `CONTENT_SLOW_FRESHNESS_OR_RANKING`:最新、最热、排行等时效或排序请求。
- `CONTENT_SLOW_PLAYLIST_OR_FAVORITES`:歌单编排、收藏搜索和复杂个人资源检索。
- `CONTENT_SLOW_NON_EXPLICIT_PLAY`:没有明确播放意图,需要先理解用户要什么。
- `CONTENT_SLOW_MULTI_STEP`:需要联网、澄清或多步推理后才能满足。
## 快
- `CONTENT_FAST_EXPLICIT_PLAY`:播放对象、歌手、类型或资源明确。
- `CONTENT_FAST_PLAYER_CONTROL`:暂停、继续、上一首、下一首、快进等直接播控。
- `CONTENT_FAST_SIMPLE_SEARCH`:精准搜索、泛推荐或已有上下文中的直接资源切换。
## 多轮
- `CONTENT_SLOW_CONTEXT_INHERIT`:前轮为慢路径,90 秒内当前轮补充、修正或反馈,且与上轮请求存在明确重叠。
- `CONTENT_FAST_CONTEXT_CONTROL`:前轮建立明确资源上下文后,当前轮执行直接播控。
仅因当前快系统没有资源或能力失败,不修改语义标签;失败后的实际升级属于执行策略。
@@ -0,0 +1,17 @@
# 通用工具垂域
适用于计算、时间、天气、翻译、闹钟、提醒、电话等确定性工具能力。
## 慢
- `TOOLS_SLOW_MULTI_STEP_REASONING`:需要多步推理、复杂计算或多次换算,不能直接查询得到。
- `TOOLS_SLOW_EXTERNAL_PROCESSING`:需要结合上下文或外部信息进行加工。
- `TOOLS_SLOW_MISSING_SLOT`:执行所需关键槽位不全,需要追问或推断补齐。
- `TOOLS_SLOW_UNSTRUCTURED_REQUEST`:表达开放,无法稳定结构化为工具参数。
## 快
- `TOOLS_FAST_DETERMINISTIC_QUERY`:当前时间、简单天气、确定性换算等可直接查询或计算。
- `TOOLS_FAST_EXPLICIT_ACTION`:时间、对象和动作明确的闹钟、提醒、电话等操作。
普通“明天提醒我开会”属于工具操作;带事件触发条件的提醒继续读取自动化规则。
@@ -0,0 +1,25 @@
# IoT 垂域
适用于家庭设备控制、房间环境查询和 IoT 设备信息查询。
## 慢
- `IOT_SLOW_INTENT_CONTROL`:只给舒适、温馨等目标状态,需要反推设备组合。
- `IOT_SLOW_ENV_QUERY`:环境查询未明确指定房间或需要比较、聚合。
- `IOT_SLOW_OTHER_QUERY`:其他 IoT 查询没有明确设备与属性。
## 快
- `IOT_FAST_EXPLICIT_CONTROL`:设备、位置和动作可直接识别。
- `IOT_FAST_ROOM_ENV_QUERY`:环境查询明确指定房间。
- `IOT_FAST_DEVICE_PROPERTY_QUERY`:明确指定设备和属性。
- `IOT_FAST_EXPLICIT_MULTI_CONTROL`:多个动作全部是明确 IoT 设备控制。
## 冲突标记
IoT 查询的细粒度规则覆盖核心汇总的“设备/环境信息问答给模糊”。命中查询规则时记录:
```text
policy_conflict=true
conflict_refs=["CONFLICT_IOT_QUERY_VS_AMBIGUOUS"]
```
@@ -0,0 +1,31 @@
# 导航 / 生活服务垂域
适用于导航、路线、地图操作、位置与路况问答、POI 搜索及相关生活服务请求。
## 慢
- `NAV_SLOW_CONDITIONED_POI`:单地点规划带明确筛选条件,如评分、品类属性或多个约束。
- `NAV_SLOW_FUZZY_POI`:单地点规划使用隐喻、外形或模糊描述识别目标。
- `NAV_SLOW_MULTI_PLACE`:一次规划多个地点或先后目的地。
- `NAV_SLOW_MULTI_ACTION`:导航请求同时要求路线选择、沿途搜索、终点搜索等多个动作。
- `NAV_SLOW_LOW_FREQUENCY_QA`:沿途城市、红绿灯数量等非高频复杂问答。
- `NAV_SLOW_COMPLEX_EXPRESSION`:自纠正、非人机话语或描述性表达使目标需要额外推理。
- `NAV_SLOW_CONTEXT_INHERIT`:前轮进入慢系统,当前轮延续同一规划或补充约束。
## 快
- `NAV_FAST_SIMPLE_SINGLE_POI`:不带筛选条件的单地点规划,包括 A、A 的 B、A 附近的 B、顺路的 A、A 最近的 B。
- `NAV_FAST_MAP_OPERATION`:删除途经点、地址设置、导航播报、路线切换等地图操作。
- `NAV_FAST_HIGH_FREQUENCY_QA`:到目的地或途经点的时间、距离、位置,当前位置、路名和路况查询。
- `NAV_FAST_CONTEXT_SIMPLE`:前轮为快路径,当前轮是同一操作流中的简单续接。
## 冲突标记
`NAV_SLOW_CONDITIONED_POI` 与核心汇总中的“目标明确且带简单条件可快”冲突。按垂域优先给慢,并记录:
```text
policy_conflict=true
conflict_refs=["CONFLICT_NAV_CONDITIONED_POI"]
```
“最近、附近、顺路”在本垂域被明确列为无筛选条件的快路径,不按普通筛选条件处理。
@@ -0,0 +1,24 @@
# 产品问答垂域
适用于产品知识、故障诊断、设置入口和车辆动态信息查询。
## 慢
- `PRODUCT_SLOW_FAULT_DIAGNOSIS`:报告异常、询问原因、要求排查或处理建议。
- `PRODUCT_SLOW_STATIC_KNOWLEDGE`:询问功能说明、概念、规则、规格、使用方法或知识库内容。
- `PRODUCT_SLOW_COMPLEX_DYNAMIC_QUERY`:读取本车信号、档案或统计值,并进行条件判断、聚合、比较、换算或够否判断。
- `PRODUCT_SLOW_CONTEXT_REQUIRED`:当前 query 省略对象或属性,必须依赖上一轮才能判断。
## 快
- `PRODUCT_FAST_SETTINGS_ENTRY`:定位设置项入口、询问在哪里设置或直接跳转设置页。
- `PRODUCT_FAST_SIMPLE_DYNAMIC_QUERY`:直接读取一个当前值、档案值或统计值。
## 冲突标记
本垂域与核心汇总的模糊档存在两组冲突:
- 静态知识和故障诊断按本垂域给慢:`CONFLICT_PRODUCT_QA_SLOW_VS_AMBIGUOUS`
- 简单动态状态查询按本垂域给快:`CONFLICT_PRODUCT_STATE_FAST_VS_AMBIGUOUS`
命中时设置 `policy_conflict=true` 并记录对应冲突 ID。
@@ -0,0 +1,18 @@
# 系统 / App 控制垂域
适用于系统设置、应用操作、屏幕操作和系统功能控制。
## 慢
- `SYSTEM_SLOW_INTENT_EXPRESSION`:只表达刺眼、吵、费眼等状态,没有明确操作目标。
- `SYSTEM_SLOW_SCENE_EXPRESSION`:描述会议、睡眠、专注等场景,需要映射多个系统功能。
- `SYSTEM_SLOW_DISAMBIGUATION`:指代不清、存在多个候选或功能名称无法唯一识别,需要追问。
- `SYSTEM_SLOW_COMPLEX_TASK`:包含选择、排除、条件判断或多步编排。
## 快
- `SYSTEM_FAST_EXPLICIT_CONTROL`:系统功能、应用、页面或屏幕元素可直接识别,动作明确。
- `SYSTEM_FAST_OPERATION_FLOW`:当前操作流中的返回、确认、取消、点击、切换等直接动作。
- `SYSTEM_FAST_EXPLICIT_MULTI_CONTROL`:多个动作全部是明确系统或设备控制,且没有规划依赖。
应用内搜索、内容消费或外部服务如果已有更具体垂域卡,优先进入对应垂域。
@@ -1,61 +1,47 @@
# 黄金边界样例 # 2026.7 黄金边界样例
使用这些样例校准规则,不要把词面模板机械迁移到所有场景。`来源`中的页码为 PDF 物理页码;“推导”表示按规则组合得到,不是文档逐字给出的标签 样例按“垂域优先、结构其次、核心兜底”口径校准
| # | query / 上下文 | label | 主原因码 | 边界说明 | 来源 | | Query / 上下文 | 标签 | 判断层级 | 规则 ID |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- |
| 1 | 开空调 | 快 | `DIRECT_ACTION` | 动作和对象明确 | 新标准 p8 | | 开空调 | 快 | 车控 | `CAR_FAST_EXPLICIT_CONTROL` |
| 2 | 太冷了,调一下空调 | 快 | `DIRECT_ACTION` | 感受词不覆盖明确动作和对象 | 新标准 p8,规则推导 | | 太冷了,调一下空调 | 快 | 车控 | `CAR_FAST_EXPLICIT_CONTROL` |
| 3 | 我感觉好冷快冻死了,帮我调一下 | 慢 | `INTENT_INFERENCE` | 未说明要调什么,需反推动作 | 新标准 p9 | | 我感觉好冷快冻死了,帮我调一下 | 慢 | 车控 | `CAR_SLOW_INTENT_EXPRESSION` |
| 4 | 调一个浪漫点的氛围灯 | 快 | `DIRECT_ACTION` | 风格是简单修饰,功能目标明确 | 新标准 p8–9 | | 调一个浪漫点的氛围灯 | 快 | 车控 | `CAR_FAST_EXPLICIT_CONTROL` |
| 5 | 帮我把房间布置得舒适温馨一些 | 慢 | `SCENE_GOAL_MAPPING` | 需把目标状态映射成动作组合 | 新标准 p9 | | 帮我把车里布置得浪漫一点 | 慢 | 车控 | `CAR_SLOW_SCENE_EXPRESSION` |
| 6 | 导航去附近评分 4.5 以上的泰国菜 | 快 | `DIRECT_ACTION` | 最终汇总覆盖调研版“筛选即慢” | 新标准 p2 与 p8 | | 导航去附近评分 4.5 以上的泰国菜 | 慢 | 导航/生服 | `NAV_SLOW_CONDITIONED_POI` |
| 7 | 导航去附近最大的停车场 | 快 | `DIRECT_ACTION` | 单目标、单一简单排序可直接满足 | 旧评测 p3 与新标准 p8,规则推导 | | 导航去最近的加油站 | 快 | 导航/生服 | `NAV_FAST_SIMPLE_SINGLE_POI` |
| 8 | 推荐一家安静、亲子、评分高、停车方便且别排太久的酒店 | 慢 | `COMPLEX_REASONING` | 多个主观/实时条件需权衡 | 旧评测 p3,新标准规则推导 | | 导航去大裤衩,再沿途找充电站 | 慢 | 导航/生服 | `NAV_SLOW_MULTI_ACTION` |
| 9 | 导航去大裤衩,再沿途找充电站,并看看终点附近哪里好停车 | 慢 | `MULTI_STEP_PLANNING` | 多地点、多步骤路线编排 | 新标准 p9 | | 删除途经点 | 快 | 导航/生服 | `NAV_FAST_MAP_OPERATION` |
| 10 | 删除途经点 | | `DIRECT_OPERATION_FLOW` | 导航操作流中的直接动作 | 新标准 p8 | | 那个压线噔噔的声音关掉 | 慢 | 车控 | `CAR_SLOW_FUZZY_FUNCTION` |
| 11 | 把空调调到 24 度,然后打开座椅加热 | 快 | `EXPLICIT_DEVICE_MULTI_ACTION` | 多个动作全部为明确设备控制 | 新标准 p8 | | 小米 SU7 支持哪些驾驶模式 | 慢 | 产品问答 | `PRODUCT_SLOW_STATIC_KNOWLEDGE` |
| 12 | 查天气再决定要不要开窗 | 慢 | `MULTI_STEP_PLANNING` | 查询结果决定后续控制 | 旧评测 p4 | | 我的车怎么突然没声音了 | 慢 | 产品问答 | `PRODUCT_SLOW_FAULT_DIAGNOSIS` |
| 13 | 那个压线噔噔的声音关掉 | 快 | `DIRECT_ACTION` | 名称不标准但目标可唯一识别且动作明确 | 新标准 p4 与 p9 | | 现在胎压是多少 | 快 | 产品问答 | `PRODUCT_FAST_SIMPLE_DYNAMIC_QUERY` |
| 14 | 打开那个灯(场景中有多个灯) | 慢 | `TRUE_DISAMBIGUATION` | 存在真实多候选,需澄清 | 旧评测 p3,新标准规则推导 | | 哨兵模式在哪里设置 | 快 | 产品问答 | `PRODUCT_FAST_SETTINGS_ENTRY` |
| 15 | 导航到那个像大裤衩一样的楼 | | `TRUE_DISAMBIGUATION` | 需先识别隐含地标再定位 | 旧评测 p3 | | 播放周杰伦的歌 | 快 | 内容 | `CONTENT_FAST_EXPLICIT_PLAY` |
| 16 | 播放周杰伦的歌 | 快 | `DIRECT_ACTION` | 明确播放意图和资源 | 新标准 p8 | | 播放最近短视频里很火的那首歌 | 慢 | 内容 | `CONTENT_SLOW_FRESHNESS_OR_RANKING` |
| 17 | 播放最近短视频里很火的那首歌 | 慢 | `TRUE_DISAMBIGUATION` | 资源身份不确定且依赖外部热点 | 旧评测 p3,新标准内容细则 | | 现在几点了 | 快 | 通用工具 | `TOOLS_FAST_DETERMINISTIC_QUERY` |
| 18 | 找王菲在春晚与别人合唱的歌,再用网易云播放 | 慢 | `MULTI_STEP_PLANNING` | 外部检索后跨步骤播放 | 新标准 p9 | | 上午 9:18 到 12:18,再加下午 2 点到 6 点共多久 | 慢 | 通用工具 | `TOOLS_SLOW_MULTI_STEP_REASONING` |
| 19 | 现在几点了 | 快 | `DIRECT_DETERMINISTIC_QUERY` | 高频、唯一、确定性工具查询 | 旧评测 p3 | | 把空调调到 24 度,然后打开座椅加热 | 快 | 车控 | `CAR_FAST_EXPLICIT_MULTI_CONTROL` |
| 20 | 帮我定明天早上 9 点的闹钟 | 快 | `DIRECT_ACTION` | 时间和动作明确 | 新标准 p8 | | 查天气再决定要不要开窗 | 慢 | 多指令结构 | `MULTI_SLOW_CROSS_DOMAIN_WORKFLOW` |
| 21 | 小米 SU7 支持哪些驾驶模式 | 模糊 | `PRODUCT_KNOWLEDGE` | 纯静态产品知识 | 新标准 p10 | | 音箱端:每天晚上 8 点开灯开空调 | 慢 | 自动化 | `AUTO_SLOW_HOME_AUTOMATION` |
| 22 | 我的车怎么突然没声音了 | 模糊 | `FAULT_DIAGNOSIS` | 纯故障原因/诊断请求 | 新标准 p4 与 p10 | | 车载端:车速超过 70 提醒我减速 | 快 | 自动化 | `AUTO_FAST_CAR_REMINDER` |
| 23 | 现在胎压是多少 | 模糊 | `DEVICE_OR_ENV_STATE_QUERY` | 最终模糊档覆盖调研版简单动态查询快 | 新标准 p4 与 p10,规则推导 | | 车载端:每次上车就导航去公司 | 慢 | 自动化 | `AUTO_SLOW_CAR_REGULAR_TASK` |
| 24 | 家里哪个房间最热 | 模糊 | `DEVICE_OR_ENV_STATE_QUERY` | 环境状态查询,无控制副作用 | 新标准 p10 | | 自动帮我设置一下,端侧未知 | 模糊 | 自动化 | `AUTO_AMBIGUOUS_ENDPOINT_UNKNOWN` |
| 25 | 给我讲个笑话 | 模糊 | `OPEN_CHAT_OR_QA` | 闲聊/开放内容 | 新标准 p10 | | 无聊了,陪我聊聊天 | 模糊 | 核心 | `CORE_AMBIGUOUS_OPEN_QA` |
| 26 | 做一个介绍 AI4S 的 PPT | 慢 | `MULTI_STEP_PLANNING` | 复杂产物生成与内容组织 | 新标准 p9 |
| 27 | 音箱端:每天晚上 8 点开灯开空调 | 慢 | `AUTOMATION_SLOW_POLICY` | 音箱家庭自动化专项默认慢 | 新标准 p7 |
| 28 | 车载端:车速超过 70 提醒我减速 | 快 | `DIRECT_ACTION` | 车载闹钟/提醒专项走快 | 新标准 p7 |
| 29 | 前轮慢系统询问“确认开启湿滑模式吗”;当前轮“帮我开启” | 慢 | `CONTEXT_REQUIRED` | 继承慢确认链路 | 新标准 p4 |
| 30 | 仅当前轮“帮我开启”,无任何前轮 | 慢 | `MISSING_REQUIRED_SLOT` | 无法确定开启对象;低置信并复核 | 新标准规则推导 |
| 31 | 自动帮我设置一下(端侧未知) | 模糊 | `POLICY_UNCERTAIN` | 端侧会改变正式自动化策略;默认慢并复核 | 新标准 p7,规则推导 |
## 最小对照组 重点检查以下紧邻对:
校准时至少同时检查以下紧邻对:
```text ```text
太冷了,调一下空调 -> 快 太冷了,调一下空调 -> 快
我感觉好冷快冻死了,帮我调一下 -> 慢 我感觉好冷,帮我调一下 -> 慢
调一个浪漫点的氛围灯 -> 快 导航去最近的加油站 -> 快
帮我把房间布置得浪漫一点 -> 慢 导航去评分 4.5 以上的泰国菜 -> 慢
导航去附近评分 4.5 以上的泰国菜 -> 快 现在胎压是多少 -> 快
帮我综合挑一家不踩雷、少排队、停车方便的餐厅 -> 慢 刚刚谁动了我的车 -> 慢
那个压线噔噔的声音关掉 -> 快 多个明确设备控制 -> 快
打开那个灯(存在多个候选) -> 慢 查询结果决定后续控制 -> 慢
现在几点 -> 快
现在胎压多少 -> 模糊
开空调并打开座椅加热 -> 快
查天气再决定是否开窗 -> 慢
``` ```
@@ -0,0 +1,52 @@
# 渐进加载索引
本文件只负责召回知识,不直接给快慢结论。
## 第一阶段输出
先提取:
- 当前 query 和可见上下文。
- 操作、询问或聊天。
- 对象、设备、资源、位置和端侧。
- 主垂域和最多两个候选垂域。
- 多指令、自动任务和上下文依赖信号。
主垂域不明显、控制与问答边界不清或同时召回多个领域时,读取
`references/preclassification.md`;明显的单垂域请求无需额外加载。
## 垂域召回
| 主要信号 | 主垂域 | 读取文件 |
| --- | --- | --- |
| 导航、路线、目的地、途经点、当前位置、路况、附近 POI、沿途 POI | 导航/生服 | `references/domain-navigation-life.md` |
| 车窗、座椅、空调、雨刮、车灯、驾驶模式、智驾、泊车等车辆操作 | 车控 | `references/domain-car-control.md` |
| 小米产品、汽车功能说明、故障、设置入口、本车动态状态 | 产品问答 | `references/domain-product-qa.md` |
| 音乐、视频、电台、新闻、歌单、播放和内容搜索 | 内容 | `references/domain-content.md` |
| 系统设置、应用打开关闭、屏幕操作、免打扰、亮度、音量 | 系统/App控制 | `references/domain-system-app.md` |
| 计算、时间、天气、翻译、闹钟、提醒、电话等工具能力 | 通用工具 | `references/domain-general-tools.md` |
| 家庭灯具、家电、扫地机、房间环境、IoT 设备状态 | IoT | `references/domain-iot.md` |
| 当、如果、时候、之后、每、一...就、自动化、智能习惯、超级任务 | 自动化 | `references/domain-automation.md` |
## 召回边界
- 车辆“怎么设置、什么意思、为什么异常”优先产品问答;“打开、关闭、调节”优先车控。
- 家庭设备“打开、关闭、调节”优先 IoT;系统自身的亮度、音量、应用和页面操作优先系统/App控制。
- “附近有什么”同时可能命中导航和生活服务,先看用户要导航、查询还是消费服务。
- 闹钟或提醒没有条件触发结构时属于通用工具;存在事件条件触发时同时召回自动化。
- query 只表达通用知识、闲聊或开放问题时,不强行归入垂域,后续读取核心原则。
## 结构信号
| 信号 | 何时读取 |
| --- | --- |
| 多个独立动作、跨对象/跨垂域、并列连接、多方向调整 | `references/structure-multi-instruction.md` |
| 条件触发 + 动作、自动化、智能习惯、超级任务 | `references/structure-automation.md`,并读取 `references/domain-automation.md` |
| 当前轮含省略、指代、确认/取消,且结论依赖前轮 | 读取主垂域卡中的多轮规则 |
## 停止条件
- 主垂域卡命中明确规则后停止加载其他垂域卡。
- 只有主垂域无法确定时才读取第二张候选垂域卡。
- 垂域和结构规则均未覆盖时读取 `references/core-policy.md`
- 命中卡片中的冲突标记时读取 `references/policy-conflicts.md`
@@ -1,153 +0,0 @@
# 旧评测标签迁移与质量控制
## 目录
- [文档定位](#文档定位)
- [旧八类标签](#旧八类标签)
- [迁移到新三档](#迁移到新三档)
- [关键口径变化](#关键口径变化)
- [评测集构建](#评测集构建)
- [质检门禁](#质检门禁)
- [禁止固化的旧信息](#禁止固化的旧信息)
## 文档定位
《快慢系统分发-评测集构建》是早期策略、评测集项目计划和一次候选挖掘实验的混合文档。其项目日期早于 2026.6 新标准。
使用它:
- 解释复杂性原因。
- 迁移旧 `FAST_DIRECT` / `SLOW_*` 数据。
- 复用候选挖掘、人工盲标、主动学习和流量回放方法。
不要使用它覆盖新三档语义标准。
## 旧八类标签
| 旧标签 | 旧定义 |
| --- | --- |
| `FAST_DIRECT` | 当前轮可直接、安全、确定性满足 |
| `SLOW_FILTER_RANK` | 候选筛选、排序、优化或推荐 |
| `SLOW_DISAMBIGUATE` | 目标身份不确定,需先消歧 |
| `SLOW_GOAL_STATE` | 给目标状态,需反推参数 |
| `SLOW_WORKFLOW` | 多动作、多工具或显式多步骤 |
| `SLOW_CONTEXT_DEPENDENT` | 复杂性主要来自上文或记忆 |
| `SLOW_UNCLEAR` | 结合必要上下文仍不明确 |
| `SLOW_ADVANCED_CAPABILITY` | 不在旧快系统白名单的高级能力 |
旧文档没有给多原因冲突优先级。迁移时允许先保留多个原因,再选择决定性主因。
## 迁移到新三档
不要做固定的一对一映射。先按 2026.6 语义重标,再按需要回填最接近的旧标签。
| 旧标签 | 新标准处理 |
| --- | --- |
| `FAST_DIRECT` | 通常为快;仍检查它是否属于新标准明确列出的模糊信息型 |
| `SLOW_FILTER_RANK` | 简单单目标条件搜索可改为快;复杂权衡、推荐、外部验证仍慢 |
| `SLOW_DISAMBIGUATE` | 非标准称呼但可唯一识别且动作明确可改为快;真实多候选仍慢 |
| `SLOW_GOAL_STATE` | 只有目标状态、需反推动作时慢;动作和对象已明确时可能改为快 |
| `SLOW_WORKFLOW` | 多步/跨工具仍慢;多个全部明确的设备控制动作改为快 |
| `SLOW_CONTEXT_DEPENDENT` | 真正依赖上文推理时慢;已建立快操作流中的简单直接续接可快 |
| `SLOW_UNCLEAR` | 执行意图需澄清时慢;若缺端侧导致政策无法确定,可标模糊并复核 |
| `SLOW_ADVANCED_CAPABILITY` | 废除按能力白名单直接定语义;按用户预期重判,能力缺口另记 |
兼容输出规则:
- 只有新结论能被旧标签无损表达时才填写 `legacy_eval_label`
- `模糊`通常无法无损映射到旧二值标签,默认填 `null`
- 业务方明确要求旧二值路由时,可从 `default_route` 派生,但不要覆盖新 `label`
- 不要把 `complex_task=true``慢`画等号。
## 关键口径变化
| 维度 | 旧评测文档 | 2026.6 新标准 |
| --- | --- | --- |
| 核心视角 | 快系统白名单与能力边界 | 用户等待预期 |
| 标签空间 | 1 个 FAST + 7 个 SLOW | 快 / 慢 / 模糊 |
| 简单筛选 | 普遍视为 `SLOW_FILTER_RANK` | 目标明确、无需多步时可快 |
| 模糊称呼 | 普遍视为 `SLOW_DISAMBIGUATE` | 可唯一识别且动作明确时可快 |
| 多动作 | 普遍视为 `SLOW_WORKFLOW` | 全部明确设备控制是快特例 |
| 产品知识/故障/状态 | 快慢二分 | 正式标为模糊 |
| 能力不支持 | `SLOW_ADVANCED_CAPABILITY` | 标签不变;快能力缺口标待承接 |
| 边界 case | 短期一律慢 | 保留模糊语义,默认路由慢 |
| 短 query | 实验中 ≤5 字默认快 | 禁止作为语义规则 |
内部冲突也要处理:
- 新标准物理页 2 把“评分 4.5 以上的泰国菜”列入导航慢,物理页 8 又明确列为快;使用最终汇总的快。
- 新标准垂域调研把“压线噔噔的声音关掉”归入模糊功能指代慢,物理页 9 明确改为快;使用最终汇总的快。
- 新标准调研把静态知识、故障和部分状态查询直接分快慢,物理页 10 统一为模糊;保留模糊标签。
## 评测集构建
复用旧文档的闭环:
```text
候选挖掘
-> LLM 预打标
-> 人工背靠背盲标
-> 分歧仲裁与规则回灌
-> 种子模型
-> 主动学习
-> 真实流量回放
-> 覆盖分析
```
候选来源:
1. 线上真实流量。
2. 明确功能点 TopQuery。
3. 现有快慢评测集。
4. LLM 生成或改写的紧邻边界对。
建议数据记录至少保留:
- 原始 ID、query、session 和上下文。
- 端侧、设备、来源和时间。
- 新三档语义标签及默认路由。
- 原因码、证据、置信度、复核状态。
- 可选旧标签和结构维度。
- 标注员、规则版本和仲裁结果。
## 质检门禁
### 标注一致性
- 使用同一份边界基准集校准 Prompt 和标注员。
- 对高分歧样本执行两名标注员背靠背盲标。
- 计算 IAA,并把分歧原因回灌规则和黄金样例。
- 把人机分歧与人人分歧分开分析。
### 数据完整性
- 对同一 session 使用一致的上下文窗口。
- 区分真实流量、旧集迁移和合成改写来源。
- 对 session 去重,并隔离训练集和评测集。
- 保留 `模糊`,不要在语义真值中提前二值化。
### 覆盖与指标
- 按快/慢/模糊、原因码、垂域、端侧和来源分层统计。
- 单独统计慢误分为快的高风险错误,以及快误分为慢的延迟损失。
- 同时报告宏平均、各类召回和混淆矩阵,不只报告总准确率。
- 不使用旧实验分布作为目标配额。
### 两道门
1. 语义门:人工或模型是否依据当前规则得出正确结论。
2. 结构门:记录是否通过 `scripts/validate_label.py`
结构校验通过不代表语义正确。
## 禁止固化的旧信息
不要把以下内容写成新策略:
- “≤5 字默认快”。
- “上轮慢则次轮必慢”的无条件继承。
- “边界一律慢”的永久语义规则。
- 旧快系统白名单或 `SLOW_ADVANCED_CAPABILITY`
- 旧实验中任一类别占比。
- 2K/3K 种子规模、5K/1W 最终规模等互相冲突的项目目标。
- 95%/98% 等未统一口径的验收数字。
@@ -0,0 +1,19 @@
# 2026.7 规则冲突表
本表记录产品文档内部已知冲突。当前口径为垂域规则优先,冲突不会静默覆盖。
| 冲突 ID | 场景 | 垂域结论 | 核心汇总结论 | 当前结论 |
| --- | --- | --- | --- | --- |
| `CONFLICT_NAV_CONDITIONED_POI` | 带评分等明确条件的单地点导航 | 慢 | 快 | 慢 |
| `CONFLICT_CAR_FUZZY_FUNCTION` | 非标准名称描述车辆功能 | 慢 | 快 | 慢 |
| `CONFLICT_PRODUCT_QA_SLOW_VS_AMBIGUOUS` | 静态产品知识、故障诊断 | 慢 | 模糊 | 慢 |
| `CONFLICT_PRODUCT_STATE_FAST_VS_AMBIGUOUS` | 简单车辆动态状态查询 | 快 | 模糊 | 快 |
| `CONFLICT_IOT_QUERY_VS_AMBIGUOUS` | IoT 环境或设备信息查询 | 细分为快/慢 | 模糊 | 按 IoT 细则 |
命中时:
1. 使用垂域标签。
2. 设置 `policy_conflict=true`
3. 把对应冲突 ID 写入 `conflict_refs`
4.`counterevidence` 中简述另一层规则。
5. 优先级已经解决时不自动设置 `review_required=true`
@@ -1,332 +0,0 @@
# XA4.1 2026.6 快慢分流策略
## 目录
- [真源与概念](#真源与概念)
- [三档标签](#三档标签)
- [决策树](#决策树)
- [快的规则](#快的规则)
- [慢的规则](#慢的规则)
- [模糊的规则](#模糊的规则)
- [上下文、多指令和聚合](#上下文多指令和聚合)
- [垂域补充](#垂域补充)
- [原因码](#原因码)
- [能力与默认路由](#能力与默认路由)
## 真源与概念
使用《【XA4.1】快慢分流新标准-2026.6》的最终汇总作为主真源。该文档物理页 7–10 的最终汇总高于物理页 2–7 的垂域调研草案;更早的《快慢系统分发-评测集构建》只提供旧原因分类和评测方法。
判断核心问题:
> 用户说出这句话时,心里能接受等多久?
不要用“当前快系统能不能做”代替这个问题。
保持以下概念正交:
- 语义标签:快、慢、模糊。
- 默认路由:快系统或慢系统。
- 能力承接:当前快系统是否已支持。
- 业务标签:导航、车控、产品问答等。
- 结构维度:complex、多指令、自动任务、上下文依赖。
## 三档标签
| 标签 | 用户预期 | 默认策略 |
| --- | --- | --- |
| 快 | 立即响应,通常期望 2–3 秒内得到动作或确定结果 | 快系统 |
| 慢 | 愿意等几秒换取规划、推理或高质量结果 | 慢系统 |
| 模糊 | 对速度和质量都有要求,或难以可靠归入快/慢 | 默认慢系统,可由明确细分策略覆盖 |
`模糊` 是正式语义标签,不是模型置信度。高置信产品知识问答仍可标为 `模糊`;低置信执行请求不一定因此成为 `模糊`,还要看是否需要澄清或补上下文。
## 决策树
按顺序执行:
```text
1. query 是否包含要产生副作用的执行请求?
否:
a. 闲聊/开放问答/产品静态知识/故障诊断/
设备或环境状态查询 -> 模糊
b. 高频、唯一、确定性的工具或导航流查询 -> 快
c. 需要多步分析、换算、聚合或生成复杂产物 -> 慢
是:
a. 只有感受/意向,无法确定要做什么 -> 慢
b. 只有目标状态/场景,需映射动作组合 -> 慢
c. 真实歧义、缺关键槽位、需依赖上文才可决定 -> 慢
d. 需规划、多步、多工具、复杂比较或跨源推理 -> 慢
e. 动作与目标直接可识别,无需先决定“做什么” -> 快
2. 多个子请求:
a. 全部是明确设备控制动作 -> 快
b. 其他情况按 慢 > 模糊 > 快 聚合
3. 仍无法归类,或端侧缺失导致策略确实不同 -> 模糊,
default_route=慢系统,review_required=true
```
“快系统当前不支持”不出现在语义决策树中。
## 快的规则
命中以下一类且没有更高优先级慢条件时标 `快`
### 明确直接动作
- 有明确操作目标。
- 动作和设备、对象或资源可直接识别。
- 不需要先推断用户到底想做什么。
例:
- 开空调。
- 把温度调到 24 度。
- 关车窗。
- 播放周杰伦的歌。
- 帮我定明天早上 9 点的闹钟。
感受词不覆盖明确目标:
- “太冷了,调一下空调”仍是快。
- “调一个浪漫点的氛围灯”仍是快。
### 简单条件与非标准称呼
- 单一明确目标可以带位置、距离、评分、附近、风格等简单修饰。
- 非标准称呼只要能唯一映射到对象,并且动作明确,仍为快。
例:
- 导航去附近评分 4.5 以上的泰国菜。
- 导航去附近最大的停车场。
- 那个压线噔噔的声音关掉。
不要把“有筛选词”或“名称不标准”直接当成慢。只有需要权衡多个方案、外部事实验证、真实澄清或多步规划时才转慢。
### 操作流中的直接动作
- 删除途经点。
- 切换导航播报。
- 切换路线。
- 下一首、暂停、声音调大。
- 高频且答案唯一的工具查询,例如“现在几点”。
### 多个明确设备控制
多个动作全部为明确设备控制时仍标快:
- 把空调调到 24 度,然后打开座椅加热。
- 关客厅灯并打开空调。
跨工具编排、查询后再决定、先推荐再执行不适用该特例。
## 慢的规则
命中以下任一决定性条件时标 `慢`
### 意向反推
用户只表达主观感受、身体状态、情绪、不满或潜在需求,没有给出可直接识别的操作目标,系统必须反推要做什么。
例:
- 我感觉好冷快冻死了,帮我调一下。
- 脚底下好冷,腿快冻麻了。
- 屏幕太亮有点刺眼,帮我弄一下。
对照:
- “太冷了,调一下空调”有明确对象和动作,标快。
### 场景或目标状态映射
用户描述结果应是什么样,而不是要执行什么动作;系统必须把场景映射为一个或多个功能。
例:
- 后排宝宝睡着了,把车里调成适合睡觉的状态。
- 今天情人节,帮我营造点节日氛围。
- 帮我把房间布置得舒适温馨。
### 规划、推理和多步编排
需要先决定方案,再执行;或需要多步计算、数值换算、跨源聚合、复杂比较、多工具承接。
例:
- 导航到主目的地,路上找充电站,再看看终点附近哪里好停车。
- 找王菲在春晚与别人合唱的歌,再用网易云播放。
- 查天气再决定要不要开窗。
- 做一个介绍 AI4S 的 PPT。
### 真实消歧、补槽和上下文推理
- 存在多个可行对象,必须追问才能选择。
- 缺少执行所必需且不能稳定默认的槽位。
- 当前短句必须结合前轮才能确定对象或字段。
- 上一轮慢系统已发起确认,当前轮为确认、取消或继续。
例:
- “打开那个灯”,且场景里存在多个灯。
- 前轮慢系统询问是否开启湿滑模式;当前轮“帮我开启”。
不要把非标准称呼、口语改口或简单补充一律视为真实消歧。
### 复杂选择
单个简单筛选条件可快;需要综合主观体验、实时状态、风险、外部事实或多个相互权衡的条件时标慢。
例:
- 推荐一家安静、适合亲子、评分高、停车方便且别排太久的酒店。
- 找一个冷门但不能踩雷、出餐快且人不多的餐厅。
## 模糊的规则
### 纯信息型
以下纯信息请求标 `模糊`
- 闲聊、聊天和开放问答。
- 产品功能、规格、概念、规则、使用方法等静态知识。
- 报异常、问故障、问原因、要排查建议。
- 设备状态或环境信息查询,无控制副作用。
例:
- 给我讲个笑话。
- 为什么天空是蓝色的?
- 小米 SU7 支持哪些驾驶模式?
- 哨兵模式是什么意思?
- 我的车怎么突然没声音了?
- 家里哪个房间最热?
- 空调已经开了多久?
### 不要扩大模糊档
- 现在几点、高频导航状态等唯一且期望即时的工具查询可标快。
- 需要制作复杂产物或多步分析的信息任务标慢。
- 执行对象不明且需要澄清时通常标慢,不要仅因“有歧义”就标模糊。
### 策略不完整
如果缺失的端侧或场景信息会导致正式规则给出不同标签,可标 `模糊`,并设置低置信和人工复核。不要把普通的模型犹豫都标成模糊。
## 上下文、多指令和聚合
### 上下文
- 只在输入真实提供前轮时使用。
- 区分“继承已建立的直接操作流”和“必须推理上文才能理解”。
- 上一轮慢系统主动追问后的确认/取消继续走慢。
- 上一轮快时,当前简单直接动作可继续快;复杂补充转慢。
- 缺少前轮而当前短句不可独立理解时,标慢并复核;若端侧政策本身不确定,可标模糊并复核。
### 多指令
- 全部为明确设备控制动作:快。
- 含查询后判断、跨 App、跨工具、规划或生成:慢。
- 可独立拆分路由时先对子请求分别标注,再保留聚合标签。
### 聚合
默认使用风险主导顺序:
```text
慢 > 模糊 > 快
```
只对“全部为明确设备控制动作”应用快特例。
## 垂域补充
### 导航和生活服务
- 单地点、目标明确、简单条件筛选:快。
- 地图操作和高频导航问答:快。
- 多地点、多动作路线编排、复杂综合决策、外部事实定位:慢。
- “评分 4.5 以上的泰国菜”按最终汇总标快,覆盖调研草案中的慢标签。
### 车控、系统控制和 IoT
- 明确设备、功能和动作:快。
- 只有感受、场景目标、复杂排除或位置集合推理:慢。
- 非标准功能名但可唯一识别且动作明确:快。
- 设备或环境状态查询:模糊。
### 内容和媒体
- 精确播放、明确资源、直接播控:快。
- 描述性搜歌、歌词片段、场景推荐、歌单编排、收藏搜索、复杂内容承接:慢。
- 纯内容知识问答按信息型处理,通常模糊。
### 通用工具
- 原子化且结果唯一的查询或控制:快。
- 多步换算、结合外部信息再加工、缺关键槽位、开放生成:慢。
- 不要仅因需要联网或 parser 暂不支持就标慢。
### 自动化
- 音箱端家庭自动化默认慢。
- 音箱定时任务和意向化自动化慢。
- 车载闹钟或提醒按文档专项策略可快。
- 缺端侧且端侧会改变标签时,标模糊并复核。
## 原因码
每条记录选择一个决定性的 `primary_reason_code`,并在 `reason_codes` 中补充其他命中原因。
### 快
| 原因码 | 含义 |
| --- | --- |
| `DIRECT_ACTION` | 动作和目标直接可识别 |
| `DIRECT_DETERMINISTIC_QUERY` | 高频、唯一、确定性的直接查询 |
| `EXPLICIT_DEVICE_MULTI_ACTION` | 多个动作全部为明确设备控制 |
| `DIRECT_OPERATION_FLOW` | 已建立操作流中的直接操作或播控 |
### 慢
| 原因码 | 含义 |
| --- | --- |
| `INTENT_INFERENCE` | 从感受或不满反推动作 |
| `SCENE_GOAL_MAPPING` | 将场景或目标状态映射为动作组合 |
| `MULTI_STEP_PLANNING` | 多步骤、多工具或任务编排 |
| `COMPLEX_REASONING` | 换算、聚合、外部验证或复杂比较 |
| `TRUE_DISAMBIGUATION` | 存在真实多候选,必须消歧 |
| `CONTEXT_REQUIRED` | 必须依赖前轮才能决定 |
| `MISSING_REQUIRED_SLOT` | 缺关键且不可默认的执行槽位 |
| `AUTOMATION_SLOW_POLICY` | 命中明确的慢自动化专项策略 |
### 模糊
| 原因码 | 含义 |
| --- | --- |
| `OPEN_CHAT_OR_QA` | 闲聊或开放问答 |
| `PRODUCT_KNOWLEDGE` | 产品静态知识 |
| `FAULT_DIAGNOSIS` | 故障、异常、原因或排查建议 |
| `DEVICE_OR_ENV_STATE_QUERY` | 无副作用的设备或环境状态查询 |
| `POLICY_UNCERTAIN` | 缺少会改变正式策略的端侧或规则信息 |
## 能力与默认路由
固定派生:
| label | default_route |
| --- | --- |
| 快 | 快系统 |
| 慢 | 慢系统 |
| 模糊 | 慢系统 |
`fast_system_pending`
- `true`:已有证据证明本应为快,但快系统尚未承接。
- `false`:已有能力清单或验证证明已承接。
- `null`:未评估能力;默认使用该值。
不得因为 `fast_system_pending=true` 修改 `label``default_route`
@@ -0,0 +1,31 @@
# 垂域预分类知识
本文件是从标签大师提炼的粗粒度召回知识,只帮助选择快慢分流垂域卡,不输出业务标签、function 或 Agent target。
## 预分类顺序
1. 先识别自动任务和多指令结构。
2. 再判断请求是控制、查询、内容消费还是知识问答。
3. 最后结合对象和端侧选择主垂域。
## 粗粒度映射
| 标签大师领域或典型标签 | 快慢分流垂域 |
| --- | --- |
| 地图导航、地图设置、地图问答、地址设置、走哪问哪、餐饮/旅游/汽车服务 POI | 导航/生服 |
| 车载控制 | 车控 |
| 小米产品帮助、手车互联、系统/车载/家用设备状态查询 | 产品问答 |
| 音乐、视频、电台、新闻、播放控制、歌单、内容问答 | 内容 |
| 系统控制、应用控制、屏幕操作、相机、声纹 | 系统/App控制 |
| 时间、天气、计算、翻译、闹钟、提醒、电话等工具标签 | 通用工具 |
| 设备控制、家庭 IoT 环境和设备查询 | IoT |
| 自动任务、系统/应用/设备定时控制 | 自动化 |
## 关键边界
- 同一个设备名可能落入控制或产品问答。动作执行进入控制垂域,功能说明、故障和状态查询进入产品问答。
- “附近餐厅”根据满足方式区分:要路线或地图结果进入导航/生服;要团购、订座或消费服务仍属于导航/生服大类,但保留候选业务标签。
- “提醒我明天开会”是普通提醒;“到公司时提醒我开会”是自动任务。
- 自动任务和多指令是结构信号,也可能同时存在业务垂域。
预分类不做最终裁决。关键词冲突时,以用户真实满足方式和候选垂域卡的适用范围为准。
@@ -0,0 +1,29 @@
# 自动任务结构
本文件提炼自标签大师的自动任务知识,只判断是否存在条件触发结构。
## 正例
常见结构:
- 当 / 如果 / 时候 / 之后 / 到达 / 每 / 一...就。
- 条件状态 + 动作,如“电量低于 20% 时提醒我充电”。
- 自动化、智能场景、智能习惯、超级任务等显式管理请求。
- 持续或延迟条件,如“座椅加热十分钟”。
`就`分隔条件和动作时,`就`之前的完整内容属于条件;`且`连接的多个状态都属于条件。条件默认向右作用,不影响前面的动作。
## 负例
- 无条件创建普通闹钟、提醒、日程或倒计时。
- 车辆已有固定功能的描述或控制,如“打开车道偏离预警”。
- 只有条件描述而没有要执行的动作。
- 普通功能名称中带“自动”,但用户没有创建条件任务。
## 输出信号
- `auto_task=true`:确认存在条件触发任务或自动化管理。
- `auto_task=false`:普通控制、查询或无条件工具操作。
- `auto_task=null`:缺少端侧或上下文,无法可靠判断。
确认 `auto_task=true` 后,继续读取 `references/domain-automation.md`。自动任务结构本身不直接决定快慢。
@@ -0,0 +1,28 @@
# 多指令结构
本文件提炼自标签大师的多指令知识。它只判断结构及快慢例外,不生成拆分后的业务 target。
## 识别
`multi_instruction=true` 需要至少两个可独立执行的子任务。常见信号:
- 和、并、然后、再、顺便、同时、并且连接独立动作。
- 多个对象分别执行不同操作。
- 同一设备存在多个独立方向调整。
- 跨垂域动作或前一步结果决定下一步。
以下通常仍是单意图:
- 同一设备的打开后设置属性,如“打开空调调到 26 度”。
- 同一动作作用于同品类多个位置。
- 打开应用后搜索、点击、播放等共同完成一个任务的顺序操作。
- 口误、重复、改口和连续相反操作。
- 多个并列查询目标。
## 快慢规则
- `MULTI_FAST_EXPLICIT_DEVICE_CONTROLS`:全部子任务都是明确设备控制动作,不含查询依赖、选择、排除或规划,给快。
- `MULTI_SLOW_INDEPENDENT_ACTIONS`:多个独立动作需要编排,且不满足设备控制快例外,给慢。
- `MULTI_SLOW_CROSS_DOMAIN_WORKFLOW`:跨垂域、跨工具,或前一步结果决定后一步,给慢。
垂域卡已经明确覆盖时,保留多指令信号并服从垂域规则。结构规则只在垂域未覆盖时裁决。
@@ -1,19 +1,27 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://local.skills/label-fast-slow-routing/label-record.schema.json", "$id": "https://local.skills/label-fast-slow-routing/label-record.schema.json",
"title": "快慢分流打标记录", "title": "2026.7 快慢分流分层打标记录",
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"required": [ "required": [
"query", "query",
"label", "label",
"default_route", "default_route",
"primary_reason_code", "domain",
"reason_codes", "candidate_domains",
"decision_level",
"decision_rule_id",
"decision_source",
"decision_path",
"reason", "reason",
"evidence", "evidence",
"structural_signals",
"context_used", "context_used",
"fast_system_pending", "fast_system_pending",
"route_override",
"policy_conflict",
"conflict_refs",
"confidence", "confidence",
"review_required", "review_required",
"uncertainties", "uncertainties",
@@ -33,15 +41,52 @@
"default_route": { "default_route": {
"enum": ["快系统", "慢系统"] "enum": ["快系统", "慢系统"]
}, },
"primary_reason_code": { "domain": {
"$ref": "#/$defs/reasonCode" "enum": [
"导航/生服",
"车控",
"产品问答",
"内容",
"系统/App控制",
"通用工具",
"IoT",
"自动化",
null
]
}, },
"reason_codes": { "candidate_domains": {
"type": "array", "type": "array",
"minItems": 1,
"uniqueItems": true, "uniqueItems": true,
"items": { "items": {
"$ref": "#/$defs/reasonCode" "enum": [
"导航/生服",
"车控",
"产品问答",
"内容",
"系统/App控制",
"通用工具",
"IoT",
"自动化"
]
}
},
"decision_level": {
"enum": ["domain", "structure", "core"]
},
"decision_rule_id": {
"type": "string",
"pattern": "^[A-Z][A-Z0-9_]+$"
},
"decision_source": {
"type": "string",
"pattern": "^references/[a-z0-9-]+\\.md(?:#.*)?$"
},
"decision_path": {
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"minLength": 1
} }
}, },
"reason": { "reason": {
@@ -63,21 +108,15 @@
"minLength": 1 "minLength": 1
} }
}, },
"domain_label": {
"type": ["string", "null"]
},
"candidate_domain_labels": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1
}
},
"structural_signals": { "structural_signals": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"required": ["complex", "multi_instruction", "auto_task"], "required": [
"complex",
"multi_instruction",
"auto_task",
"context_dependent"
],
"properties": { "properties": {
"complex": { "complex": {
"type": ["boolean", "null"] "type": ["boolean", "null"]
@@ -87,6 +126,9 @@
}, },
"auto_task": { "auto_task": {
"type": ["boolean", "null"] "type": ["boolean", "null"]
},
"context_dependent": {
"type": ["boolean", "null"]
} }
} }
}, },
@@ -96,18 +138,19 @@
"fast_system_pending": { "fast_system_pending": {
"type": ["boolean", "null"] "type": ["boolean", "null"]
}, },
"legacy_eval_label": { "route_override": {
"enum": [ "type": ["string", "null"]
"FAST_DIRECT", },
"SLOW_FILTER_RANK", "policy_conflict": {
"SLOW_DISAMBIGUATE", "type": "boolean"
"SLOW_GOAL_STATE", },
"SLOW_WORKFLOW", "conflict_refs": {
"SLOW_CONTEXT_DEPENDENT", "type": "array",
"SLOW_UNCLEAR", "uniqueItems": true,
"SLOW_ADVANCED_CAPABILITY", "items": {
null "type": "string",
] "pattern": "^CONFLICT_[A-Z0-9_]+$"
}
}, },
"confidence": { "confidence": {
"enum": ["high", "medium", "low"] "enum": ["high", "medium", "low"]
@@ -123,7 +166,7 @@
} }
}, },
"policy_version": { "policy_version": {
"const": "XA4.1-2026.6" "const": "FAST-SLOW-2026.7"
} }
}, },
"allOf": [ "allOf": [
@@ -140,24 +183,6 @@
"properties": { "properties": {
"default_route": { "default_route": {
"const": "快系统" "const": "快系统"
},
"primary_reason_code": {
"enum": [
"DIRECT_ACTION",
"DIRECT_DETERMINISTIC_QUERY",
"EXPLICIT_DEVICE_MULTI_ACTION",
"DIRECT_OPERATION_FLOW"
]
},
"reason_codes": {
"items": {
"enum": [
"DIRECT_ACTION",
"DIRECT_DETERMINISTIC_QUERY",
"EXPLICIT_DEVICE_MULTI_ACTION",
"DIRECT_OPERATION_FLOW"
]
}
} }
} }
} }
@@ -166,7 +191,7 @@
"if": { "if": {
"properties": { "properties": {
"label": { "label": {
"const": "慢" "enum": ["慢", "模糊"]
} }
}, },
"required": ["label"] "required": ["label"]
@@ -178,32 +203,6 @@
}, },
"fast_system_pending": { "fast_system_pending": {
"enum": [false, null] "enum": [false, null]
},
"primary_reason_code": {
"enum": [
"INTENT_INFERENCE",
"SCENE_GOAL_MAPPING",
"MULTI_STEP_PLANNING",
"COMPLEX_REASONING",
"TRUE_DISAMBIGUATION",
"CONTEXT_REQUIRED",
"MISSING_REQUIRED_SLOT",
"AUTOMATION_SLOW_POLICY"
]
},
"reason_codes": {
"items": {
"enum": [
"INTENT_INFERENCE",
"SCENE_GOAL_MAPPING",
"MULTI_STEP_PLANNING",
"COMPLEX_REASONING",
"TRUE_DISAMBIGUATION",
"CONTEXT_REQUIRED",
"MISSING_REQUIRED_SLOT",
"AUTOMATION_SLOW_POLICY"
]
}
} }
} }
} }
@@ -211,39 +210,16 @@
{ {
"if": { "if": {
"properties": { "properties": {
"label": { "policy_conflict": {
"const": "模糊" "const": true
} }
}, },
"required": ["label"] "required": ["policy_conflict"]
}, },
"then": { "then": {
"properties": { "properties": {
"default_route": { "conflict_refs": {
"const": "慢系统" "minItems": 1
},
"fast_system_pending": {
"enum": [false, null]
},
"primary_reason_code": {
"enum": [
"OPEN_CHAT_OR_QA",
"PRODUCT_KNOWLEDGE",
"FAULT_DIAGNOSIS",
"DEVICE_OR_ENV_STATE_QUERY",
"POLICY_UNCERTAIN"
]
},
"reason_codes": {
"items": {
"enum": [
"OPEN_CHAT_OR_QA",
"PRODUCT_KNOWLEDGE",
"FAULT_DIAGNOSIS",
"DEVICE_OR_ENV_STATE_QUERY",
"POLICY_UNCERTAIN"
]
}
} }
} }
} }
@@ -262,32 +238,8 @@
"review_required": { "review_required": {
"const": true "const": true
} }
},
"required": ["review_required"]
} }
} }
], }
"$defs": {
"reasonCode": {
"enum": [
"DIRECT_ACTION",
"DIRECT_DETERMINISTIC_QUERY",
"EXPLICIT_DEVICE_MULTI_ACTION",
"DIRECT_OPERATION_FLOW",
"INTENT_INFERENCE",
"SCENE_GOAL_MAPPING",
"MULTI_STEP_PLANNING",
"COMPLEX_REASONING",
"TRUE_DISAMBIGUATION",
"CONTEXT_REQUIRED",
"MISSING_REQUIRED_SLOT",
"AUTOMATION_SLOW_POLICY",
"OPEN_CHAT_OR_QA",
"PRODUCT_KNOWLEDGE",
"FAULT_DIAGNOSIS",
"DEVICE_OR_ENV_STATE_QUERY",
"POLICY_UNCERTAIN"
] ]
}
}
} }
@@ -1,85 +1,66 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Validate fast/slow/ambiguous label records without external dependencies.""" """Validate 2026.7 hierarchical fast/slow routing records."""
from __future__ import annotations from __future__ import annotations
import argparse import argparse
import json import json
import re
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
POLICY_VERSION = "XA4.1-2026.6" POLICY_VERSION = "FAST-SLOW-2026.7"
SKILL_ROOT = Path(__file__).resolve().parent.parent
REASON_CODES_BY_LABEL: dict[str, set[str]] = { CONFLICT_FILE = SKILL_ROOT / "references" / "policy-conflicts.md"
"": {
"DIRECT_ACTION",
"DIRECT_DETERMINISTIC_QUERY",
"EXPLICIT_DEVICE_MULTI_ACTION",
"DIRECT_OPERATION_FLOW",
},
"": {
"INTENT_INFERENCE",
"SCENE_GOAL_MAPPING",
"MULTI_STEP_PLANNING",
"COMPLEX_REASONING",
"TRUE_DISAMBIGUATION",
"CONTEXT_REQUIRED",
"MISSING_REQUIRED_SLOT",
"AUTOMATION_SLOW_POLICY",
},
"模糊": {
"OPEN_CHAT_OR_QA",
"PRODUCT_KNOWLEDGE",
"FAULT_DIAGNOSIS",
"DEVICE_OR_ENV_STATE_QUERY",
"POLICY_UNCERTAIN",
},
}
DEFAULT_ROUTE_BY_LABEL = { DEFAULT_ROUTE_BY_LABEL = {
"": "快系统", "": "快系统",
"": "慢系统", "": "慢系统",
"模糊": "慢系统", "模糊": "慢系统",
} }
LEGACY_LABELS = {
"FAST_DIRECT",
"SLOW_FILTER_RANK",
"SLOW_DISAMBIGUATE",
"SLOW_GOAL_STATE",
"SLOW_WORKFLOW",
"SLOW_CONTEXT_DEPENDENT",
"SLOW_UNCLEAR",
"SLOW_ADVANCED_CAPABILITY",
}
CONFIDENCE_VALUES = {"high", "medium", "low"} CONFIDENCE_VALUES = {"high", "medium", "low"}
DECISION_LEVELS = {"domain", "structure", "core"}
DOMAIN_VALUES = {
"导航/生服",
"车控",
"产品问答",
"内容",
"系统/App控制",
"通用工具",
"IoT",
"自动化",
}
RULE_ID_PATTERN = re.compile(r"^[A-Z][A-Z0-9_]+$")
CONFLICT_ID_PATTERN = re.compile(r"^CONFLICT_[A-Z0-9_]+$")
REQUIRED_FIELDS = { REQUIRED_FIELDS = {
"query", "query",
"label", "label",
"default_route", "default_route",
"primary_reason_code", "domain",
"reason_codes", "candidate_domains",
"decision_level",
"decision_rule_id",
"decision_source",
"decision_path",
"reason", "reason",
"evidence", "evidence",
"structural_signals",
"context_used", "context_used",
"fast_system_pending", "fast_system_pending",
"route_override",
"policy_conflict",
"conflict_refs",
"confidence", "confidence",
"review_required", "review_required",
"uncertainties", "uncertainties",
"policy_version", "policy_version",
} }
OPTIONAL_FIELDS = { OPTIONAL_FIELDS = {
"id", "id",
"counterevidence", "counterevidence",
"domain_label",
"candidate_domain_labels",
"structural_signals",
"legacy_eval_label",
} }
@@ -107,6 +88,82 @@ def _check_string_list(
errors.append(f"{field} 不允许重复项") errors.append(f"{field} 不允许重复项")
def _validate_decision_source(
record: dict[str, Any],
*,
errors: list[str],
) -> None:
source = record.get("decision_source")
rule_id = record.get("decision_rule_id")
level = record.get("decision_level")
if not _is_nonempty_string(source):
errors.append("decision_source 必须是非空字符串")
return
relative_path = source.split("#", 1)[0]
if not relative_path.startswith("references/") or not relative_path.endswith(".md"):
errors.append("decision_source 必须指向 references/*.md")
return
resolved = (SKILL_ROOT / relative_path).resolve()
references_root = (SKILL_ROOT / "references").resolve()
if references_root not in resolved.parents:
errors.append("decision_source 不允许跳出 references 目录")
return
if not resolved.is_file():
errors.append(f"decision_source 文件不存在: {relative_path}")
return
try:
source_text = resolved.read_text(encoding="utf-8")
except OSError as exc:
errors.append(f"无法读取 decision_source: {exc}")
return
if _is_nonempty_string(rule_id) and rule_id not in source_text:
errors.append(f"decision_rule_id 未出现在来源文件中: {rule_id}")
filename = resolved.name
if level == "domain" and not filename.startswith("domain-"):
errors.append("decision_level=domain 时来源文件必须是 domain-*.md")
if level == "structure" and not filename.startswith("structure-"):
errors.append("decision_level=structure 时来源文件必须是 structure-*.md")
if level == "core" and filename != "core-policy.md":
errors.append("decision_level=core 时来源文件必须是 core-policy.md")
def _validate_conflicts(
record: dict[str, Any],
*,
errors: list[str],
) -> None:
policy_conflict = record.get("policy_conflict")
conflict_refs = record.get("conflict_refs")
if not isinstance(policy_conflict, bool):
errors.append("policy_conflict 必须是布尔值")
_check_string_list(
conflict_refs,
field="conflict_refs",
errors=errors,
unique=True,
)
if not isinstance(conflict_refs, list):
return
if policy_conflict is True and not conflict_refs:
errors.append("policy_conflict=true 时 conflict_refs 至少包含一项")
if policy_conflict is False and conflict_refs:
errors.append("policy_conflict=false 时 conflict_refs 必须为空")
try:
known_conflicts = CONFLICT_FILE.read_text(encoding="utf-8")
except OSError as exc:
errors.append(f"无法读取冲突表: {exc}")
return
for conflict_id in conflict_refs:
if not isinstance(conflict_id, str):
continue
if not CONFLICT_ID_PATTERN.fullmatch(conflict_id):
errors.append(f"冲突 ID 格式非法: {conflict_id!r}")
elif conflict_id not in known_conflicts:
errors.append(f"冲突 ID 未登记: {conflict_id}")
def validate_record(record: Any, index: int) -> dict[str, Any]: def validate_record(record: Any, index: int) -> dict[str, Any]:
errors: list[str] = [] errors: list[str] = []
warnings: list[str] = [] warnings: list[str] = []
@@ -118,7 +175,6 @@ def validate_record(record: Any, index: int) -> dict[str, Any]:
"errors": ["记录必须是 JSON 对象"], "errors": ["记录必须是 JSON 对象"],
"warnings": [], "warnings": [],
} }
if "__parse_error__" in record: if "__parse_error__" in record:
return { return {
"index": index, "index": index,
@@ -130,61 +186,75 @@ def validate_record(record: Any, index: int) -> dict[str, Any]:
missing = sorted(REQUIRED_FIELDS - set(record)) missing = sorted(REQUIRED_FIELDS - set(record))
if missing: if missing:
errors.append(f"缺少必填字段: {', '.join(missing)}") errors.append(f"缺少必填字段: {', '.join(missing)}")
unknown = sorted(set(record) - REQUIRED_FIELDS - OPTIONAL_FIELDS) unknown = sorted(set(record) - REQUIRED_FIELDS - OPTIONAL_FIELDS)
if unknown: if unknown:
errors.append(f"存在未知字段: {', '.join(unknown)}") errors.append(f"存在未知字段: {', '.join(unknown)}")
query = record.get("query") if not _is_nonempty_string(record.get("query")):
if not _is_nonempty_string(query):
errors.append("query 必须是非空字符串") errors.append("query 必须是非空字符串")
label = record.get("label") label = record.get("label")
if label not in REASON_CODES_BY_LABEL: if not isinstance(label, str) or label not in DEFAULT_ROUTE_BY_LABEL:
errors.append("label 必须是 快、慢、模糊 之一") errors.append("label 必须是 快、慢、模糊 之一")
expected_route = DEFAULT_ROUTE_BY_LABEL.get(label) if isinstance(label, str) else None
default_route = record.get("default_route") if expected_route is not None and record.get("default_route") != expected_route:
expected_route = DEFAULT_ROUTE_BY_LABEL.get(label)
if expected_route is not None and default_route != expected_route:
errors.append(f"label={label} 时 default_route 必须是 {expected_route}") errors.append(f"label={label} 时 default_route 必须是 {expected_route}")
primary_reason_code = record.get("primary_reason_code") domain = record.get("domain")
reason_codes = record.get("reason_codes") if domain is not None and (
allowed_reasons = REASON_CODES_BY_LABEL.get(label, set()) not isinstance(domain, str) or domain not in DOMAIN_VALUES
if primary_reason_code not in allowed_reasons: ):
errors.append( errors.append("domain 不是受支持的粗粒度垂域")
f"primary_reason_code={primary_reason_code!r} 与 label={label!r} 不兼容" _check_string_list(
record.get("candidate_domains"),
field="candidate_domains",
errors=errors,
unique=True,
) )
candidate_domains = record.get("candidate_domains")
if not isinstance(reason_codes, list): if isinstance(candidate_domains, list):
errors.append("reason_codes 必须是数组") unknown_domains = [
else: value
if not reason_codes: for value in candidate_domains
errors.append("reason_codes 至少包含一项") if not isinstance(value, str) or value not in DOMAIN_VALUES
if all(isinstance(code, str) for code in reason_codes):
if len(reason_codes) != len(set(reason_codes)):
errors.append("reason_codes 不允许重复")
invalid_reason_codes = [
code
for code in reason_codes
if not isinstance(code, str) or code not in allowed_reasons
] ]
if invalid_reason_codes: if unknown_domains:
rendered_codes = ", ".join(repr(code) for code in invalid_reason_codes) errors.append(f"candidate_domains 包含未知垂域: {unknown_domains}")
errors.append(f"reason_codes 包含与 label 不兼容的值: {rendered_codes}")
if primary_reason_code not in reason_codes: level = record.get("decision_level")
errors.append("primary_reason_code 必须同时出现在 reason_codes 中") if not isinstance(level, str) or level not in DECISION_LEVELS:
errors.append("decision_level 必须是 domain、structure、core 之一")
if level == "domain" and domain is None:
errors.append("decision_level=domain 时 domain 不能为空")
rule_id = record.get("decision_rule_id")
if not _is_nonempty_string(rule_id) or not RULE_ID_PATTERN.fullmatch(rule_id):
errors.append("decision_rule_id 必须是大写下划线规则 ID")
_check_string_list(
record.get("decision_path"),
field="decision_path",
errors=errors,
require_nonempty=True,
)
decision_path = record.get("decision_path")
if (
isinstance(decision_path, list)
and _is_nonempty_string(rule_id)
and not any(rule_id in str(item) for item in decision_path)
):
errors.append("decision_path 必须包含 decision_rule_id")
_validate_decision_source(record, errors=errors)
if not _is_nonempty_string(record.get("reason")): if not _is_nonempty_string(record.get("reason")):
errors.append("reason 必须是非空字符串") errors.append("reason 必须是非空字符串")
_check_string_list( _check_string_list(
record.get("evidence"), record.get("evidence"),
field="evidence", field="evidence",
errors=errors, errors=errors,
require_nonempty=True, require_nonempty=True,
) )
if "counterevidence" in record: if "counterevidence" in record:
_check_string_list( _check_string_list(
record.get("counterevidence"), record.get("counterevidence"),
@@ -192,32 +262,23 @@ def validate_record(record: Any, index: int) -> dict[str, Any]:
errors=errors, errors=errors,
) )
if "domain_label" in record:
domain_label = record.get("domain_label")
if domain_label is not None and not _is_nonempty_string(domain_label):
errors.append("domain_label 必须是非空字符串或 null")
if "candidate_domain_labels" in record:
_check_string_list(
record.get("candidate_domain_labels"),
field="candidate_domain_labels",
errors=errors,
unique=True,
)
structural_signals = record.get("structural_signals") structural_signals = record.get("structural_signals")
if structural_signals is not None: expected_signal_keys = {
"complex",
"multi_instruction",
"auto_task",
"context_dependent",
}
if not isinstance(structural_signals, dict): if not isinstance(structural_signals, dict):
errors.append("structural_signals 必须是对象") errors.append("structural_signals 必须是对象")
else: else:
expected_keys = {"complex", "multi_instruction", "auto_task"}
actual_keys = set(structural_signals) actual_keys = set(structural_signals)
if actual_keys != expected_keys: if actual_keys != expected_signal_keys:
errors.append( errors.append(
"structural_signals 必须且只能包含 " "structural_signals 必须且只能包含 "
"complex、multi_instruction、auto_task" "complex、multi_instruction、auto_task、context_dependent"
) )
for key in expected_keys: for key in expected_signal_keys:
value = structural_signals.get(key) value = structural_signals.get(key)
if value is not None and not isinstance(value, bool): if value is not None and not isinstance(value, bool):
errors.append(f"structural_signals.{key} 必须是布尔值或 null") errors.append(f"structural_signals.{key} 必须是布尔值或 null")
@@ -231,20 +292,15 @@ def validate_record(record: Any, index: int) -> dict[str, Any]:
if fast_system_pending is True and label != "": if fast_system_pending is True and label != "":
errors.append("只有 label=快 时 fast_system_pending 才能为 true") errors.append("只有 label=快 时 fast_system_pending 才能为 true")
legacy_eval_label = record.get("legacy_eval_label") route_override = record.get("route_override")
if ( if route_override is not None and not _is_nonempty_string(route_override):
"legacy_eval_label" in record errors.append("route_override 必须是非空字符串或 null")
and legacy_eval_label is not None
and legacy_eval_label not in LEGACY_LABELS _validate_conflicts(record, errors=errors)
):
errors.append("legacy_eval_label 不是受支持的旧八类标签")
if label == "模糊" and legacy_eval_label is not None:
warnings.append("模糊档通常无法无损映射到旧二值标签,请确认迁移依据")
confidence = record.get("confidence") confidence = record.get("confidence")
if confidence not in CONFIDENCE_VALUES: if not isinstance(confidence, str) or confidence not in CONFIDENCE_VALUES:
errors.append("confidence 必须是 high、medium、low 之一") errors.append("confidence 必须是 high、medium、low 之一")
review_required = record.get("review_required") review_required = record.get("review_required")
if not isinstance(review_required, bool): if not isinstance(review_required, bool):
errors.append("review_required 必须是布尔值") errors.append("review_required 必须是布尔值")
@@ -301,7 +357,7 @@ def _load_records_from_file(path: Path) -> list[Any]:
def _parse_args() -> argparse.Namespace: def _parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="校验 XA4.1-2026.6 快慢分流打标 JSON/JSONL" description="校验 FAST-SLOW-2026.7 分层打标 JSON/JSONL"
) )
source_group = parser.add_mutually_exclusive_group(required=True) source_group = parser.add_mutually_exclusive_group(required=True)
source_group.add_argument("--record", help="单条 JSON 对象字符串") source_group.add_argument("--record", help="单条 JSON 对象字符串")