Files
iAOP/templates/ti-cl4/impurity-forecast/_sanity_check_rules.py
T
bot_dev1 4dcaf47af6 feat(#72): 预警规则与阈值设定(声明式AlertRule三级severity+SOP联动,PRD 5.3 ③ 场景A)
把行业知识——预警分级(P0/P1/P2)+阈值+处置SOP——外置为模板配置(PRD line 152/171
阈值外置,行业工程师配置台维护),规则引擎零改动。

- alert_rules.py:AlertSeverity(P0/P1/P2) + AlertCondition(6 运算) + AlertRule(AND 语义)
  + AlertRuleEngine(按 severity 降序 + primary_alert) + 零依赖 YAML 解析(flow map)。
- config/alert_rules.template.yaml:6 条规则,特征名对齐 #70 FeatureSpec.name,sop 引用
  异常处置 SOP(供 #11 LLM 报警解释 + 驾驶舱红色告警 + 值班长确认,PRD 场景A)。
- tests/test_alert_rules.py:16 项单测(运算/规则/引擎排序/配置/端到端P0)全通过。
- _sanity_check_rules.py:冒烟(正常无告警 + 急升温P0)。

PRD line 333:关键告警不直接联动执行机构,高利害输出人工确认 → severity 分级支撑。
2026-08-05 02:13:18 +08:00

60 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""炉层杂质预警规则引擎冒烟脚本(Issue #72)。
直接运行验证:模板规则资产可加载、规则引擎对急升温特征向量产出 P0 告警、
无异常时不告警。零第三方依赖。
"""
import importlib.util
import os
import sys
_PKG_DIR = os.path.dirname(os.path.abspath(__file__))
def _load_pkg(name, path):
if name in sys.modules:
return
spec = importlib.util.spec_from_file_location(
name, os.path.join(path, "__init__.py"),
submodule_search_locations=[path])
mod = importlib.util.module_from_spec(spec)
sys.modules[name] = mod
spec.loader.exec_module(mod)
_load_pkg("impurity_forecast", _PKG_DIR)
from impurity_forecast import AlertRuleEngine, AlertSeverity # noqa: E402
CONFIG = os.path.join(_PKG_DIR, "config", "alert_rules.template.yaml")
def main() -> int:
eng = AlertRuleEngine.from_template_config(CONFIG)
print(f"[OK] 规则配置加载: {len(eng.rules)} 条预警规则")
for r in eng.rules:
print(f" {r.describe()} (sop={r.sop or '-'})")
# 1) 正常工况不告警
normal = eng.evaluate(1, {"炉温_ema5": 850.0, "炉温_rate10": 0.01,
"氯气流量_std10": 3.0, "炉压_rate10": 0.01,
"炉层状态_mean10": 60.0})
assert not normal, "正常工况不应告警"
print("[OK] 正常工况:无告警")
# 2) 急升温 + 炉压急变 → P0 红色告警(PRD 场景A)
abnormal = eng.evaluate(2, {"炉温_ema5": 905.0, "炉温_rate10": 0.06,
"氯气流量_std10": 4.0, "炉压_rate10": 0.09,
"炉层状态_mean10": 60.0})
assert abnormal, "异常工况应触发告警"
primary = eng.primary_alert(abnormal)
assert primary.severity == AlertSeverity.P0, "主告警应为 P0"
print(f"[OK] 异常工况:主告警 {primary.severity.value}({primary.message})"
f" sop={primary.sop}")
print("炉层杂质预警规则引擎冒烟通过 ✅")
return 0
if __name__ == "__main__":
raise SystemExit(main())