Files
xsl e50a9424a1 feat(rules): data-driven decision table engine with hard constraints
kb_rule DSL 解析 + 纯域求值(优先级分组/硬约束/用户禁忌压过专业推荐)
+ 400 条基准 + 黄金集雏形(T-P2-02,TD-10)。

实现:dsl.py 封闭词汇表 pydantic 校验(未识别键拒绝)+ match 纯逻辑
(等值/include/exclude/min-max,缺字段不命中);engine.py 纯域求值
(priority 降序、confidence 次序、is_hard avoid → hard_blocks、高优先级
avoid 剔除冲突 recommend);service.py+repo.py published 整表载入进程内
缓存 + CRUD + draft→published→archived 状态机(同 T6 语义)。
测试:DSL 解析与 match 矩阵、排序/硬约束/禁忌优先、状态机矩阵、
黄金集 11 组(含用户禁忌压过专业推荐与多规则叠加)、400 条 × 1000 次
基准(实测均值 0.26ms/次、p95 0.41ms,预算 50ms);集成 3 用例
(published 载入命中拦截、draft 不载入、DSL 写入拒绝与状态机守卫)。
单测 310 通过(+72),集成 19 通过(+3)。

偏差说明:
1. 冲突仲裁按通用优先级语义实现(高优先级 avoid 剔除"严格更低"优先级的
   冲突 recommend),任务文档的"用户禁忌(≥95)永远压过专业推荐(≤90)"
   是该规则的特例,黄金集已含该场景用例。
2. include 子句按字段类型取语义:标量字段=命中列表任一值;集合字段=
   列表全部在场(子集,精确命中);文档未区分,此实现两类字段均可用。
3. 单测引擎文件命名为 tests/unit/test_rules_evaluation.py(而非
   test_rules_engine.py):与契约指定的集成文件 tests/integration/
   test_rules_engine.py 同名会导致 pytest 收集冲突(tests 目录非包)。
4. 集成测试每用例独立 engine 并 dispose:pytest-asyncio 每用例一个事件
   循环,直接用全局 session 工厂会让连接跨 loop 污染其它集成用例。
5. 规则不提供物理删除(命中链需可追溯,下线走 archived);kb_rule 契约
   无 reviewing 状态,状态机为 draft→published→archived(draft 可撤稿)。
2026-08-14 20:10:21 +08:00

29 lines
1.8 KiB
Markdown
Raw Permalink 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.
# `packages/rules` — 规则引擎(TD-10 自研数据驱动决策表)
架构 §8.1 / ADR-05:**结论由规则引擎产出,LLM 只负责表达**(防幻觉红线)。
## 模块
- `dsl.py` —— kb_rule DSL 的 pydantic 解析校验 + 画像匹配(纯逻辑)。封闭词汇表:
未识别的键一律拒绝而非忽略,规则不会静默失效。
- `engine.py` —— 纯域求值:priority 降序(同序按 confidence)、`is_hard` 的 avoid
命中进 `hard_blocks`(调用方必须据此做硬过滤)、高优先级 avoid 剔除严格低优先级
的冲突 recommend(用户禁忌 95 压过专业推荐 ≤90)。
- `repo.py` —— kb_rule 表的唯一读写点(经共享 ORM 访问)。
- `service.py` —— CRUD、draft→published→archived 状态机(同 T6 语义)、published
规则进程内缓存(量级 ~400,整表载入,管理动作后 `invalidate()`)。
## 设计约束
- **规则是数据不是代码**。求值器是代码,规则本身在 `kb_rule` 表里,
顾问在后台维护,改规则不发版(NFR-MAINT-05)。
- 每次求值必须输出**命中链**(`rule_hits`:rule_key/priority/category/is_hard/
confidence/explanation),这是报告与 Agent 可解释性的来源,
也是 `pf_diagnosis.rule_hits` 与 `ag_message.rule_hits` 的数据来源。
- p95 < 50ms(FR-KB-05):求值是纯内存操作,400 条规则量级实测远低于预算
(见 `tests/unit/test_rules_engine.py` 的基准用例)。
- 黄金集雏形:`tests/unit/test_rules_golden.py`(固定画像 → 期望输出,含硬禁忌
与多规则叠加场景),改引擎行为必须先过黄金集。
- 已发布规则集缓存在进程内;Redis TTL + 发布广播失效(架构 §10)为后续接入项,
失效入口已收敛到 `service.invalidate_published_cache()`。