EvidencePack 协议

EvidencePack 是 EICPS 的神经-符号接口协议,将 AI 决策过程转化为可审计、可追溯、可形式化验证的执行证明链。

神经网络给出”意图”,符号系统给出”证明”。AI 可以做创意,但每一步动作都必须有物理证据。

EvidencePack 协议:Proposal → ActionPlan → EvidencePack 三段执行流

三段执行流

从 VLA 大脑到物理本体的每一条指令,必须经历两道”门”过滤:

Proposal语义流形  Msem    Φ  凸优化投影    ActionPlan物理可行集  Cphys    STL 形式化验证    EvidencePack形式化证明包\underbrace{\text{Proposal}}_{\text{语义流形}\;\mathcal{M}_{sem}} \;\xrightarrow{\;\Phi\;\text{凸优化投影}\;}\; \underbrace{\text{ActionPlan}}_{\text{物理可行集}\;\mathcal{C}_{phys}} \;\xrightarrow{\;\text{STL 形式化验证}\;}\; \underbrace{\text{EvidencePack}}_{\text{形式化证明包}}

两道门都是硬门Φ\Phi 门过滤物理不可行性,STL 门过滤规约违反——任何一道不通,指令不得下发到电机。


Stage 1:Proposal(神经提案)

Proposal 是 VLA 大脑在语义流形 Msem\mathcal{M}_{sem} 上生成的原始意图,包含五个核心字段:proposal_idsourceintenttrajectoryconfidence

{
  "proposal_id":  "P-20250101-042",
  "source":       "VLA-v2.3",
  "intent":       "approach_red_buoy",
  "trajectory":   [[34.50, 120.10], [34.51, 120.11], [34.52, 120.12]],
  "confidence":   0.92,
  "reasoning":    "Red buoy detected at bearing 045°, confidence 92%"
}

⚠️ 物理幻觉警告:Proposal 尚未经过任何物理约束检验——在语义空间合理的意图,在物理流形上可能完全不可行(穿越障碍、超出关节力矩上限、违反动力学约束)。这是 Φ\Phi 投影门存在的根本原因。


Φ 投影:凸优化过滤

Φ\Phi 门将 Proposal 从语义流形投影到物理可行集 Cphys\mathcal{C}_{phys},保持 AI 意图的同时做最小修正:

ActionPlan=argminaCphysaProposal\text{ActionPlan} = \arg\min_{a \,\in\, \mathcal{C}_{phys}} \|a - \text{Proposal}\|

Cphys=动力学约束安全边界关节限位\mathcal{C}_{phys} = \text{动力学约束} \cap \text{安全边界} \cap \text{关节限位}

工程上实现为 CBF-QP(控制屏障函数二次规划),在每个控制周期内求解,保证安全集不变性。投影完成后输出 projection_delta——Proposal 与 ActionPlan 之间的语义偏离量:delta 越大,说明 AI 幻觉越严重;delta 超出阈值时触发回退安全策略,不再执行当前 Proposal。


Stage 2:ActionPlan(物理执行令)

ActionPlan 是经 Φ\Phi 投影后的物理可行版本,包含六个核心字段:

{
  "plan_id":          "AP-20250101-042",
  "proposal_ref":     "P-20250101-042",
  "waypoints": [
    {"t": 0.0, "x": 34.500, "y": 120.100, "v": 1.2, "heading": 45.0},
    {"t": 2.5, "x": 34.505, "y": 120.105, "v": 1.5, "heading": 43.2},
    {"t": 5.0, "x": 34.510, "y": 120.110, "v": 1.4, "heading": 44.1}
  ],
  "projection_delta": 0.031,
  "cbf_active":       true,
  "safety_margin":    2.3
}

proposal_ref 建立了 ActionPlan → Proposal 的审计链(可追溯性的基础)。cbf_active: true 表示 CBF 安全监控在执行全程持续激活。


STL 门:形式化验证

ActionPlan 进入 STL 门,对每条 STL 规约计算鲁棒度 ρ\rho

  • ρ>0\rho > 0:规约满足,裕度越大越安全 → PASS
  • ρ0\rho \leq 0:规约违反 → FAILverdict = REJECTED,Spine 拒绝执行

全部规约通过后,STL 门生成 EvidencePack,verdict = APPROVED,指令才得以下发。


Stage 3:EvidencePack(验证证明包)

EvidencePack 是三段执行流的最终产物,由四个字段构成:

EP={ActionPlan执行令,  ϕSTL规约集,  ρ(ϕSTL)鲁棒度,  πexec执行证明链}\text{EP} = \left\{ \underbrace{\text{ActionPlan}}_{\text{执行令}},\; \underbrace{\phi_{STL}}_{\text{规约集}},\; \underbrace{\rho(\phi_{STL})}_{\text{鲁棒度}},\; \underbrace{\pi_{exec}}_{\text{执行证明链}} \right\}

evidence_hash(sha256)在生成时锁定全部字段,防止事后篡改:

{
  "pack_id":       "EP-20250101-042",
  "plan_ref":      "AP-20250101-042",
  "stl_specs": [
    {"formula": "G[0,5] (d_obs > 2.0)", "robustness": 1.34, "status": "SATISFIED"},
    {"formula": "G[0,5] (v < 3.0)",     "robustness": 0.87, "status": "SATISFIED"},
    {"formula": "F[0,10] (arrive_goal)", "robustness": 2.10, "status": "SATISFIED"}
  ],
  "verdict":       "APPROVED",
  "evidence_hash": "sha256:a3f9b2...",
  "timestamp":     "2025-01-01T12:00:05.123Z"
}

三条规约全部 SATISFIEDverdict: APPROVED → Spine 下发执行。任一 VIOLATEDverdict: REJECTED → 强制回退,不可绕过。


STL 形式化规约

信号时序逻辑(Signal Temporal Logic, STL) 是 EvidencePack 的数学语言,同时提供定性(满足/违反)和定量(鲁棒度)两种语义:

算子语义示例
G[a,b]ϕG_{[a,b]}\, \phi全局(Always):区间 [a,b][a,b]ϕ\phi 恒成立G[0,5](dobs>2.0)G_{[0,5]}(d_{obs} > 2.0)
F[a,b]ϕF_{[a,b]}\, \phi未来(Eventually):区间 [a,b][a,b]ϕ\phi 至少成立一次F[0,10](arrived)F_{[0,10]}\text{(arrived)}
ϕ1U[a,b]ϕ2\phi_1 \,\mathcal{U}_{[a,b]}\, \phi_2直到(Until):ϕ1\phi_1 成立直到 ϕ2\phi_2 发生avoid  U[0,20]  reach\text{avoid}\;\mathcal{U}_{[0,20]}\;\text{reach}

鲁棒度语义ρ(ϕ,s,t)>0\rho(\phi, s, t) > 0 规约满足,裕度越大越安全;ρ=0\rho = 0 临界;ρ<0\rho < 0 违规。鲁棒度的定量性质使 STL 门不仅能判断”是否满足”,还能量化”满足了多少”——这是二值布尔逻辑做不到的。


三项工程保证

EvidencePack 协议赋予 EICPS 三项可操作的工程保证:

① 可追溯性(Traceability) — 审计链 EP.plan_ref → AP.proposal_ref → Proposal.proposal_id 完整闭合。每条执行令都能回溯到发起的 VLA 意图,事故调查有据可查。

② 可否决性(Vetability)verdict = REJECTED 时 Spine 层强制拒绝执行,回退到安全策略,不可被上层逻辑绕过。AI 幻觉或规约违反在此处硬性截断,不会传播到电机。

③ 可问责性(Accountability)evidence_hash(sha256)在 EvidencePack 生成时签名,锁定 ActionPlan、STL 结果和执行信号的完整记录,防止事后篡改,支持合规审查与责任认定。


算法实现

import hashlib, json, time
import numpy as np
from dataclasses import dataclass, field

# ── STL 鲁棒度计算 ────────────────────────────────────────────

def robustness_G(signal: np.ndarray, a: int, b: int,
                  predicate: callable) -> float:
    """G[a,b] φ 的鲁棒度:区间内 predicate 的最小值(ρ>0 满足)"""
    values = np.array([predicate(s) for s in signal[a : b + 1]])
    return float(values.min())

def robustness_F(signal: np.ndarray, a: int, b: int,
                  predicate: callable) -> float:
    """F[a,b] φ 的鲁棒度:区间内 predicate 的最大值"""
    values = np.array([predicate(s) for s in signal[a : b + 1]])
    return float(values.max())

def check_stl_spec(spec: dict, signal: np.ndarray) -> dict:
    """检查单条 STL 规约,返回 robustness 与 status"""
    fn  = robustness_G if spec["type"] == "G" else robustness_F
    rho = fn(signal, spec["a"], spec["b"], spec["predicate"])
    return {
        "formula":    spec.get("formula", f"{spec['type']}[{spec['a']},{spec['b']}] φ"),
        "robustness": rho,
        "status":     "SATISFIED" if rho > 0 else "VIOLATED",
    }


# ── Proposal → ActionPlan 凸优化投影(Φ 门)────────────────────

@dataclass
class Proposal:
    proposal_id: str
    trajectory:  np.ndarray   # shape (N, state_dim)
    confidence:  float
    source:      str = "VLA"

@dataclass
class ActionPlan:
    plan_id:          str
    proposal_ref:     str
    waypoints:        np.ndarray
    projection_delta: float    # ‖ActionPlan − Proposal‖,幻觉严重度量
    cbf_active:       bool
    safety_margin:    float

def project_to_physical(proposal: Proposal,
                         max_speed:   float = 2.5,
                         safety_dist: float = 2.0,
                         delta_limit: float = 0.5) -> ActionPlan:
    """
    Φ 投影:argmin ‖a − Proposal‖  s.t. a ∈ C_phys
    delta > delta_limit 时调用方应触发回退
    """
    import cvxpy as cp
    N, D = proposal.trajectory.shape
    wp   = cp.Variable((N, D))
    obj  = cp.Minimize(cp.sum_squares(wp - proposal.trajectory))
    cons = [cp.norm(wp[i+1] - wp[i], 2) <= max_speed * 2.5
            for i in range(N - 1)]
    cp.Problem(obj, cons).solve(solver=cp.OSQP, warm_start=True, verbose=False)
    wp_val = wp.value if wp.value is not None else proposal.trajectory
    delta  = float(np.linalg.norm(wp_val - proposal.trajectory))
    return ActionPlan(
        plan_id          = f"AP-{proposal.proposal_id[2:]}",
        proposal_ref     = proposal.proposal_id,
        waypoints        = wp_val,
        projection_delta = delta,
        cbf_active       = True,
        safety_margin    = safety_dist + 0.3,
    )


# ── ActionPlan → EvidencePack(STL 门)───────────────────────

@dataclass
class EvidencePack:
    pack_id:       str
    plan_ref:      str
    stl_results:   list[dict]
    verdict:       str         # "APPROVED" | "REJECTED"
    evidence_hash: str
    timestamp:     float = field(default_factory=time.time)

    def to_json(self) -> str:
        return json.dumps({"pack_id": self.pack_id, "plan_ref": self.plan_ref,
                           "stl_specs": self.stl_results, "verdict": self.verdict,
                           "evidence_hash": self.evidence_hash,
                           "timestamp": self.timestamp}, indent=2)

def generate_evidence_pack(plan:      ActionPlan,
                            signal:    np.ndarray,
                            stl_specs: list[dict]) -> EvidencePack:
    """STL 门:检验所有规约,生成防篡改 EvidencePack"""
    results = [check_stl_spec(spec, signal) for spec in stl_specs]
    verdict = "APPROVED" if all(r["status"] == "SATISFIED" for r in results) \
              else "REJECTED"
    evidence_str = json.dumps({
        "plan_ref":    plan.plan_id,
        "waypoints":   plan.waypoints.tolist(),
        "signal_hash": hashlib.sha256(signal.tobytes()).hexdigest(),
        "stl_results": results,
    }, sort_keys=True)
    return EvidencePack(
        pack_id       = f"EP-{plan.plan_id[3:]}",
        plan_ref      = plan.plan_id,
        stl_results   = results,
        verdict       = verdict,
        evidence_hash = "sha256:" + hashlib.sha256(
                            evidence_str.encode()).hexdigest()[:16],
    )

延伸阅读