"""前向链推理机:知识库规则驱动的工作记忆演化(专家系统推理核心,零依赖)。 流程(经典前向链 forward chaining): 1. 初始化黑板:写入领域/难度/置信度等事实 2. 循环:在领域内匹配规则(未触发过的)→ 按优先级执行 - 命中即记录轨迹 rule:@ - 规则带 output 模板 → 渲染后写入黑板章节(部分解) - 规则带 actions → 执行动作(写事实/写章节) 3. 终止:无新规则可触发 / 达到步数上限(防死循环) 确定性保证:规则匹配基于子串包含,无随机性;同输入 → 同轨迹。 """ from __future__ import annotations from typing import Any, Dict, List, Optional from .knowledge import KnowledgeBase, Rule from .memory import WorkingMemory def render_template(template: str, query: str, facts: Dict[str, Any]) -> str: """渲染输出模板:替换 {query} 与 {facts.} 占位符;缺失以 [未提供] 占位,不抛异常。""" out = template.replace("{query}", query) for key, value in facts.items(): out = out.replace(f"{{facts.{key}}}", str(value)) # 剩余占位符兜底 while "{" in out and "}" in out: start = out.find("{") end = out.find("}", start) if end == -1: break out = out[:start] + "[未提供]" + out[end + 1:] return out class InferenceEngine: """前向链推理机。""" def __init__(self, kb: KnowledgeBase, max_steps: int = 20): self.kb = kb self.max_steps = max_steps # --------------------------------------------------------------- def initialize(self, query: str, domain: str, difficulty: str, confidence: float, memory: WorkingMemory) -> None: """把分类结果写入黑板(事实初始化)。""" memory.write_fact("query", query) memory.write_fact("domain", domain) memory.write_fact("difficulty", difficulty) memory.write_fact("confidence", round(confidence, 4)) memory.add_trace(f"init:domain={domain},difficulty={difficulty},conf={confidence:.2f}") # --------------------------------------------------------------- def run(self, query: str, domain: str, memory: WorkingMemory, max_steps: Optional[int] = None) -> List[str]: """前向链主循环。返回触发规则 id 列表(按触发顺序)。""" steps = max_steps or self.max_steps fired: List[str] = [] for _ in range(steps): rules = self.kb.match(query, domain=domain) # 选第一个"未触发过"的规则 target: Optional[Rule] = None for r in rules: if r.id not in fired: target = r break if target is None: break # 无新规则可触发 → 终止 fired.append(target.id) self._fire(target, query, memory) return fired # --------------------------------------------------------------- def _fire(self, rule: Rule, query: str, memory: WorkingMemory) -> None: """执行一条规则:记录轨迹 + 写事实 + 产出章节。""" memory.add_trace(f"rule:{rule.id}@{rule.priority}") # 规则动作 for action in rule.actions: self._apply_action(action, rule, query, memory) # 规则输出模板 → 章节 if rule.output: text = render_template(rule.output, query, memory.facts) memory.write_section(rule.id, text) def _apply_action(self, action: str, rule: Rule, query: str, memory: WorkingMemory) -> None: """动作格式:write_fact:key=value(value 支持 {query} 占位)。""" if action.startswith("write_fact:"): kv = action[len("write_fact:"):] key, _, value = kv.partition("=") value = value.replace("{query}", query) memory.write_fact(key.strip(), value.strip(), rule_id=rule.id) # 其他动作类型暂不实现(保留扩展位)