修改干预skill

This commit is contained in:
wangsenhao
2026-06-10 21:20:15 +08:00
parent 54bc581cf2
commit a6e7d2260b
+102 -17
View File
@@ -6,40 +6,125 @@ aliases: intervention, rule-intervention, 干预数据
allowed_tools: read_file, write_file, edit_file, grep_search, glob_search, ask_user_question, python_exec
---
使用这个 skill 处理“query/多轮表达 -> 干预 TSV 候选 -> 合法性校验”的任务。
使用这个 skill 处理“query/多轮表达 -> 干预候选 -> 合并 + 上传 HDFS”的任务。
干预数据目前有两类
干预数据目前有两类,**文件无扩展名**(HDFS 上文件名是 `260610` 这种纯日期),内容是真实 TAB 字符分隔的纯文本,**绝不是字面 `\t` 两字符**。下文所有 `\t` 都表示一个真实的 TAB。
- **单句精确干预**:一行四列,格式为 `设备\tquery\tcode\t下发domain`
- **正则干预**:一行三列,格式为 `设备\t正则\t标签`
- **单句精确干预codeTopQuery**:一行 4 列,`设备\tquery\tcode\t下发domain`
示例:
```
unify 播放音乐 Agent(tag="音乐") contentCopilot|music
unify 小爱同学 Chat(type="wakeup") dialogCopilot|michat
```
- **正则干预(codeIntervene**:一行 3 列,`设备\t正则\t标签`
示例:
```
unify ^query#播放歌曲关机又关机$ Agent(tag="音乐")
unify ^beforeQuery#播放歌曲#query#关机又关机$ Agent(tag="音乐")
glass ^query#这是什么$ QA()
```
其中单句精确干预的 `code` 和正则干预的 `标签` 使用同一套 target 语法,和 `label-master` 的输出一致,但不包含复杂度判断。校验时必须复用 `skills/label-master/scripts/validate_label_output.py` 的逻辑。
精确干预的 `code` 和正则干预的 `标签` 使用同一套 target 语法,和 `label-master` 的输出一致,但不包含复杂度判断。校验时必须复用 `skills/label-master/scripts/validate_label_output.py` 的逻辑。
## 关键约定
- `unify` 表示全部设备。
- 设备必须优先从历史干预文件中归纳,不要随手发明设备名。
- 单句精确干预如果用户没有提供 `下发domain`,必须从历史精确干预表中按 `code -> 下发domain` 的多数映射推断
- 设备必须优先从下载下来的最新干预文件中归纳,不要随手发明设备名。
- **单句精确干预的 `下发domain` 必须由人拍板**:脚本基于最新干预文件按 `code 下发domain` 频次给出 top-N 候选 + 计数,agent 列出来让用户从用户给的 tag 信息出发选一个,**不要默认用多数派直接落盘**
- 正则干预支持多轮。多轮正则使用 `beforeQuery#上一轮#query#当前轮` 这种片段表达,最终通常包在 `^...$` 中。
- 默认只生成候选 TSV 和校验结果,不直接追加到历史干预文件。只有用户明确要求“追加到某个文件末尾”或“修改某个文件”时,才使用通用文件编辑能力
- 所有产物优先写到当前会话的 `output/``scratchpad/` 下,不要写到项目根目录的 `output/`
- 默认只生成候选行 + 校验结果,不直接追加到历史干预文件。上传 HDFS 必须等用户明确确认
- 所有产物优先写到当前会话的 `$AUTORESEARCH_CHAT_ROOT/output/` 或 `scratchpad/` 下,不要写到项目根目录的 `output/`。
## HDFS 干预文件路径
线上干预的权威源在 HDFS。两类文件 × 四个环境(p4t = 测试,ptr = 灰度,preview = 预发,production = 生产):
| 类型 | HDFS 目录 |
|---|---|
| 单句精确干预(codeTopQuery | `hdfs://zjyprc-hadoop/user/s_ai_service/nlp/PlanningPredict/all/<env>/strategy/codeTopQuery` |
| 正则干预(codeIntervene | `hdfs://zjyprc-hadoop/user/s_ai_service/nlp/PlanningPredict/all/<env>/strategy/codeIntervene` |
`<env>` 取值:`p4t` / `ptr` / `preview` / `production`。每个目录下文件名"形式"按日期 `yymmdd` 命名(**纯数字、无扩展名**,例:`260609`),但实际值不要求严格等于当天日期——新增一份就是上一份**按一天 +1**(要正确处理月末/年末进位),最大值仍须落在合法 `yymmdd` 范围内(最大不超过今天)。**最新文件 = 文件名尾号最大的那一个**。
## 推荐流程
1. 先确认用户要哪种干预方式:
0. **先确认链接到远端**(强制第一步,不通过就停下)。
- "远端"概念同 [model-iteration](../model-iteration/SKILL.md)bash 实际跑在远端 jupyter pod 工作区,`$AUTORESEARCH_CHAT_ROOT` 是后端注入的远端 chat 工作区路径(位于共享 NFS:`/mnt/<email_prefix>/autoresearch-zk-users/<chat_session_id>/`)。系统提示里的"当前会话目录"是后端宿主机本地路径,**不是**远端,不能拿来跑脚本或读历史文件。
- 起手第一条 bash 必须是预检(同时验远端 + HDFS 工具):
```bash
pwd && echo "AUTORESEARCH_CHAT_ROOT=$AUTORESEARCH_CHAT_ROOT" && uname -a && which hls hget hput
```
- 通过条件:`pwd` 返回远端绝对路径(一般 `/root/zk_agent_workspaces/LOCALID_xxx` 或类似 Linux 路径)、`$AUTORESEARCH_CHAT_ROOT` 非空、`hls/hget/hput` 都能找到。
- 不通过的情形(任一命中就停下问用户):
- `$AUTORESEARCH_CHAT_ROOT` 为空 → 后端没注入,会话没绑定 chat。
- `pwd` 是 Windows 路径(如 `D:\...`、`/d/...`)或后端本地路径(如 `/home/mi/zk-data-agent-wsh/...`)→ 当前在本地,不是远端。
- `hls/hget/hput` 找不到 → 远端环境没装 HDFS 客户端,下一步拉文件直接卡死。
- bash 报命令找不到 / 没权限 → 远端 pod 没起来。
1. **获取最新的干预文件**(强制第二步,所有后续校验和上传都基于这一步拉下来的文件)。
- 先确认 (a) 干预类型:精确干预 → `codeTopQuery`,正则干预 → `codeIntervene`(b) 目标环境(`p4t/ptr/preview/production`,用户没说就问,建议先在 `p4t` 验证)。
- 用 `hls` 列目录,按文件名尾号取最大的那个作为最新文件,然后用 `hget` 拉下来:
```bash
ENV=p4t # 或 ptr / preview / production
TYPE=codeTopQuery # 或 codeIntervene
HDFS_DIR=hdfs://zjyprc-hadoop/user/s_ai_service/nlp/PlanningPredict/all/$ENV/strategy/$TYPE
hls "$HDFS_DIR"
LATEST=$(hls "$HDFS_DIR" | awk '{print $NF}' | grep -v '^$' | sort -V | tail -1)
echo "LATEST=$LATEST"
WORK="$AUTORESEARCH_CHAT_ROOT/intervention/${ENV}_${TYPE}"
mkdir -p "$WORK"
# base 不带扩展名(HDFS 上原文件名就是日期),保持原貌
hget "$LATEST" "$WORK/base"
wc -l "$WORK/base"
# 抽 1-2 行肉眼校验是不是真 TAB 分隔(cat -A 把 TAB 显成 ^I
head -2 "$WORK/base" | cat -A
```
- **设备枚举、`code → 下发domain` 频次、重复/冲突检查全部基于这份刚拉下来的 `base`**,不要再用本地历史快照(旧快照可能已过时)。文件是 TAB 分隔纯文本,无扩展名,不要当 csv/json 处理。
2. 先确认用户要哪种干预方式(如果第 1 步还没定就在这里定,确定后回到第 1 步拉对应文件):
- 单句精确干预:query 必须完全命中。
- 正则干预:适合一类表达、多轮上下文或需要泛化的高频 case。
2. 确认设备。用户没说设备时,必须问设备;可以提示 `unify` 表示全部设备。
3. 确认目标标签/code。它必须是完整 target,例如 `Agent(tag="地图导航")``QA()``Chat()` 或合法 function 调用。
4. 如果是单句精确干预:
3. 确认设备。用户没说设备时,必须问设备;可以提示 `unify` 表示全部设备。设备枚举从 base.tsv 第一列归纳。
4. 确认目标标签/code。它必须是完整 target,例如 `Agent(tag="地图导航")`、`QA()`、`Chat()` 或合法 function 调用。
5. 如果是单句精确干预:
- 确认 `query`。
- 如果没有 `下发domain`,调用脚本根据历史数据推断。
5. 如果是正则干预:
- **下发domain 必须人选**:基于 base 文件统计该 `code`target)历史上配过的 `下发domain` 频次,给出 top-N 候选 + 计数,让用户结合自己提的 tag 信息选一个。例:
```bash
# 用 awk 抽该 target 的下发domain 分布
awk -F'\t' -v t='Agent(tag="音乐")' '$3==t {print $4}' "$WORK/base" \
| sort | uniq -c | sort -rn | head -5
```
把结果(如 `12345 contentCopilot|music / 87 contentCopilot|audio_book / ...`)作为候选给用户,**不要默认取第一个直接落盘**。
6. 如果是正则干预:
- 确认当前轮 query。
- 如果有多轮,确认前序 query 顺序。
- 用户给了原始正则就保留;没给时由脚本生成 `^query#...$` 或 `^beforeQuery#...#query#...$`。
6. 调用 `scripts/generate_intervention_candidate.py` 生成候选 TSV 和校验报告。
7. 展示时只展示必要信息:干预类型、设备、候选 TSV、校验是否通过、需要用户确认的问题。
7. 调用 `scripts/generate_intervention_candidate.py` 生成候选 TSV 和校验报告(产物写到 `$AUTORESEARCH_CHAT_ROOT/output/` 或 `scratchpad/`
8. **合并 + diff 给人看**。把候选行追加进 `base` 副本,跑 unified diff
```bash
cp "$WORK/base" "$WORK/merged"
cat candidate >> "$WORK/merged" # candidate 是上一步生成的候选行文件,纯 TAB 分隔
diff -u "$WORK/base" "$WORK/merged" | tee "$WORK/diff.patch"
```
9. 展示给用户:干预类型、设备、候选行(原文 TAB 分隔)、校验结果、diff 摘要、目标 HDFS 路径。**用户没明确说"上传 / 推到 X 环境 / hput"前不要执行 hput**——这是写远端 + 影响线上的不可逆动作,必须等确认。
10. **用户确认后 hput 上传**。新文件名规则:**取 `LATEST` 的尾号「按一天」+1**——必须正确处理月末 / 年末进位(260131 +1 = 260201261231 +1 = 270101260228 在闰年 +1 = 260229、平年 +1 = 260301),**不是**数值 `+1`(那样 260131+1=260132 直接失效)。用 `date` 做日期算术:
```bash
OLD_NUM=$(basename "$LATEST") # 例:260609 或 260131
NEW_NUM=$(date -d "20${OLD_NUM} + 1 day" +%y%m%d)
TODAY=$(date +%y%m%d)
# 校验:date 解析失败(OLD_NUM 本身就不合法)会直接报错;新尾号也必须是合法 yymmdd
if ! [[ "$NEW_NUM" =~ ^[0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$ ]]; then
echo "ERR: $NEW_NUM 不符合 yymmdd 形式,停下问用户"; exit 1
fi
if [ "$NEW_NUM" -gt "$TODAY" ]; then
echo "ERR: $NEW_NUM=$NEW_NUM 超过今天 $TODAY(说明上一份就是今天的,已经发过一版),停下问用户"; exit 1
fi
hput "$WORK/merged" "$HDFS_DIR/$NEW_NUM"
hls "$HDFS_DIR" | tail -3 # 校验新文件已落、尾号最大
```
说明:HDFS 上文件名"形式"按日期来,实际值是「上一份按一天 +1」而不是严格当天日期;只要 +1 后仍是合法 yymmdd 且不超过今天就行。如果上一份已经是今天(OLD_NUM == TODAY),`date +1 day` 会算出明天 → 命中"超过今天"分支,停下问用户怎么处理(通常是当天已经发过一版,要不要并入现有版本,或推迟到明天再发)。
11. 展示最终结果:上传后的 HDFS 路径 + 新文件尾号。
## 脚本能力