Add intervention data skill

This commit is contained in:
wuyang6
2026-05-19 11:59:49 +08:00
parent 201058dfb2
commit 5684df3caf
7 changed files with 1316 additions and 0 deletions
@@ -0,0 +1,220 @@
#!/usr/bin/env python3
"""校验单句精确干预和正则干预候选 TSV。"""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
from typing import Any
from intervention_common import (
DEFAULT_EXACT_SOURCE,
DEFAULT_REGEX_SOURCE,
build_source_summary,
domain_compatible,
historical_targets,
infer_configured_dispatch_domain,
infer_dispatch_domain_for_device,
load_exact_records,
load_regex_records,
normalize_device,
normalize_target,
parse_candidate_lines,
validate_target,
json_dumps,
)
def load_input_text(path: str | None) -> str:
if path:
return Path(path).read_text(encoding="utf-8")
return sys.stdin.read()
def validate_exact_rows(rows: list[list[str]], args: argparse.Namespace) -> dict[str, Any]:
summary = build_source_summary(Path(args.exact_source), Path(args.regex_source))
devices = set(summary["devices"])
known_historical_targets = historical_targets(summary)
existing: dict[tuple[str, str], list[Any]] = {}
for record in load_exact_records(Path(args.exact_source)):
existing.setdefault((record.device, record.query), []).append(record)
results = []
for index, row in enumerate(rows, start=1):
errors: list[str] = []
warnings: list[str] = []
if len(row) != 4:
errors.append(f"单句精确干预必须是 4 列,当前 {len(row)}")
results.append({"line": index, "valid": False, "errors": errors, "warnings": warnings, "row": row})
continue
device, query, target, dispatch_domain = [cell.strip() for cell in row]
device = normalize_device(device)
target = normalize_target(target)
if device not in devices:
errors.append(f"设备不在历史枚举中:{device},可选:{', '.join(sorted(devices))}")
if not query:
errors.append("query 不能为空")
if "\t" in query or "\n" in query or "\r" in query:
errors.append("query 不能包含制表符或换行")
target_result = validate_target(target)
if not target_result["valid"]:
if target in known_historical_targets:
warnings.append("target 未通过 label-master 知识库校验,但历史干预文件中已存在;建议后续补齐标签知识库")
target_result["normalized_output"] = target
else:
errors.extend([f"target 不合法:{message}" for message in target_result.get("errors", [])])
if not dispatch_domain:
errors.append("下发domain 不能为空")
inferred = infer_dispatch_domain_for_device(target, device, summary)
if inferred and dispatch_domain and dispatch_domain != inferred["dispatch_domain"]:
message = (
f"下发domain 与推断映射不一致:当前 {dispatch_domain}"
f"推断为 {inferred['dispatch_domain']},来源 {inferred.get('source', 'historical')},置信度 {inferred.get('confidence')}"
)
if args.strict_domain:
errors.append(message)
else:
warnings.append(message)
if not inferred:
warnings.append("未在历史精确干预表中找到该 target 的下发domain 映射,需要人工确认")
configured = infer_configured_dispatch_domain(target, device, summary)
if configured and dispatch_domain and not domain_compatible(dispatch_domain, configured["dispatch_domain"]):
warnings.append(
f"下发domain 与 type_match_agent 配置不兼容:当前 {dispatch_domain}"
f"配置 {configured['matched_key']} -> {configured['dispatch_domain']}"
)
if not configured:
warnings.append("type_match_agent 下发表中未找到该 Agent tag 的设备/通用映射")
conflicts = existing.get((device, query), [])
for item in conflicts:
if item.target == target and item.dispatch_domain == dispatch_domain:
warnings.append(f"历史文件已存在相同单句干预:line {item.line_no}")
else:
errors.append(
f"历史文件存在同设备同 query 的不同干预:line {item.line_no}"
f"{item.target} / {item.dispatch_domain}"
)
results.append(
{
"line": index,
"valid": not errors,
"errors": errors,
"warnings": warnings,
"normalized": {
"device": device,
"query": query,
"target": target_result.get("normalized_output", target),
"dispatch_domain": dispatch_domain,
},
"configured_dispatch_domain": configured,
}
)
return summarize_results(results)
def validate_regex_rows(rows: list[list[str]], args: argparse.Namespace) -> dict[str, Any]:
summary = build_source_summary(Path(args.exact_source), Path(args.regex_source))
devices = set(summary["devices"])
known_historical_targets = historical_targets(summary)
existing: dict[tuple[str, str], list[Any]] = {}
for record in load_regex_records(Path(args.regex_source)):
existing.setdefault((record.device, record.pattern), []).append(record)
results = []
for index, row in enumerate(rows, start=1):
errors: list[str] = []
warnings: list[str] = []
if len(row) != 3:
errors.append(f"正则干预必须是 3 列,当前 {len(row)}")
results.append({"line": index, "valid": False, "errors": errors, "warnings": warnings, "row": row})
continue
device, pattern, target = [cell.strip() for cell in row]
device = normalize_device(device)
target = normalize_target(target)
if device not in devices:
errors.append(f"设备不在历史枚举中:{device},可选:{', '.join(sorted(devices))}")
if not pattern:
errors.append("正则不能为空")
else:
try:
re.compile(pattern)
except re.error as exc:
errors.append(f"正则无法编译:{exc}")
if "query#" not in pattern:
errors.append("正则必须包含 query# 片段")
if not pattern.startswith("^") or not pattern.endswith("$"):
warnings.append("历史常见正则通常使用 ^...$ 完整锚定,建议确认是否需要锚定")
target_result = validate_target(target)
if not target_result["valid"]:
if target in known_historical_targets:
warnings.append("target 未通过 label-master 知识库校验,但历史干预文件中已存在;建议后续补齐标签知识库")
target_result["normalized_output"] = target
else:
errors.extend([f"target 不合法:{message}" for message in target_result.get("errors", [])])
conflicts = existing.get((device, pattern), [])
for item in conflicts:
if item.target == target:
warnings.append(f"历史文件已存在相同正则干预:line {item.line_no}")
else:
errors.append(
f"历史文件存在同设备同正则的不同干预:line {item.line_no}{item.target}"
)
results.append(
{
"line": index,
"valid": not errors,
"errors": errors,
"warnings": warnings,
"normalized": {
"device": device,
"pattern": pattern,
"target": target_result.get("normalized_output", target),
},
}
)
return summarize_results(results)
def summarize_results(results: list[dict[str, Any]]) -> dict[str, Any]:
return {
"valid": all(item["valid"] for item in results),
"total": len(results),
"invalid": sum(1 for item in results if not item["valid"]),
"warning_count": sum(len(item.get("warnings", [])) for item in results),
"results": results,
}
def main() -> int:
parser = argparse.ArgumentParser(description="校验干预 TSV 候选")
parser.add_argument("--mode", choices=["exact", "regex"], required=True, help="干预类型")
parser.add_argument("--input", help="候选 TSV 文件路径;不传则读取 stdin")
parser.add_argument("--exact-source", default=str(DEFAULT_EXACT_SOURCE), help="历史单句精确干预 TSV")
parser.add_argument("--regex-source", default=str(DEFAULT_REGEX_SOURCE), help="历史正则干预 TSV")
parser.add_argument("--strict-domain", action="store_true", help="下发domain 和历史多数映射不一致时直接报错")
args = parser.parse_args()
text = load_input_text(args.input)
rows = parse_candidate_lines(text)
if args.mode == "exact":
payload = validate_exact_rows(rows, args)
else:
payload = validate_regex_rows(rows, args)
print(json_dumps(payload))
return 0 if payload["valid"] else 1
if __name__ == "__main__":
raise SystemExit(main())