本节摘要:决策入图之后,本节装配让图"活起来"的三件套。因果链追踪:
trace_decision_causality(context_graph.py 第 3544 行起)沿显式因果边(CAUSED/INFLUENCED/PRECEDENT_FOR)递归回放,辅以"共享实体+时间戳"的启发式补链,每条链附置信度衰减与距离带解释;CausalChainAnalyzer提供 Cypher 变长路径与trace_at_time时态版本。先例语义搜索:find_precedents_by_scenario以 0.7 内容相似 + 0.3 结构相似的混合公式在历史决策里找"同类怎么判"——法律与金融的先例原则在图上的实现。影响面分析:analyze_decision_influence回答"动了一个事实,波及哪些历史决策"。最后剖析AgentMemory(2302 行)的短/长期分层记忆,并对照业界 Agent 记忆方案看它的独特分工。
内容来源:
semantica/context/context_graph.py(3323—4000 行决策三件套)、causal_analyzer.py(779 行)、agent_memory.py(2302 行)、agent_context.py(get_causal_chain/trace_decision_explainability)、docs/guides/decision-intelligence.md
⚠️ 注意:稠密图上因果路径是组合爆炸的——
trace_decision_causality默认max_chains=10000,触顶时在返回里追加{"truncated": True}标记而不是悄悄截断(第 3565 行 docstring 与第 3667 行 warning 日志)。审计代码必须检查这个标记,否则你看到的是部分因果链。启发式补链(共享实体即视为潜在原因)是加法式猜测,与显式记录的因果边证据等级不同,报告里要分开呈现。
trace_decision_causality 的双通道机制:显式因果边优先、启发式补链为辅,以及环检测与链数上限。find_precedents_by_scenario 做混合先例检索,理解 0.7/0.3 权重的含义与 as_of 时态过滤。analyze_decision_influence 的直接/间接影响两层与三因子打分。6.1 节的决策节点彼此孤立时价值有限,add_causal_relationship(a, b, relationship_type) 用三种边给决策定型(context_graph.py 第 439 行):
_CAUSAL_EDGE_TYPES = ("CAUSED", "INFLUENCED", "PRECEDENT_FOR")
CAUSED 是强因果(分类决策导致升级决策),INFLUENCED 是弱因果(压力测试影响了审批),PRECEDENT_FOR 是先例关系(老案子是新案子的先例)。README 的贷款示例串法:add_causal_relationship(app_id, uw_id, relationship_type="CAUSED")、add_causal_relationship(uw_id, rate_id, relationship_type="INFLUENCED")——申请→核保→定价,一条链记完。
追踪入口 trace_decision_causality(decision_id, max_depth=5, max_chains=10000)(第 3544—3676 行)的核心结构:
# 显式因果边反索引:一次性构建,避免逐节点重扫边表 incoming_causal_edges = defaultdict(list) for edge_type in _CAUSAL_EDGE_TYPES: for edge in self.edge_type_index.get(edge_type, []): if edge.source_id in self._decisions: incoming_causal_edges[edge.target_id].append(edge) def trace_recursive(current_id, depth, path, path_ids): # 环检测按路径而非全局:一条分支走过的决策,另一条分支仍要能走 if truncated or depth >= max_depth or current_id in path_ids: return path_ids = path_ids | {current_id} ... for edge in explicit_causes: # ① 显式边优先(调用方记录的事实) hop = {"from": cause_id, ..., "type": edge.edge_type, "edge_weight": edge_weight} ... trace_recursive(cause_id, depth + 1, cause_path, path_ids) ... for cause_id in potential_causes: # ② 启发式补链 ...
两个通道分工明确:通道①只认 add_causal_relationship 显式记录的边——这是调用方拍板过的因果事实,每条平行边都单独成链不合并;通道②是启发式:当前决策的 entities 里有谁、谁的 timestamp 更早,谁就是"潜在原因"(第 3639—3645 行),hop 类型记作 "influences"、边权取对方置信度。环检测用 path_ids(不可变集合按路径传递)而非全局 visited——分支图里一条链走过的节点,另一条链仍允许经过,只防"同一条链自己绕圈"。每条完整链交给 _build_causal_chain_report(第 3938 行)出报告:
confidence_decay = 1.0 for hop in hops: edge_weight = float(hop.get("edge_weight", 1.0)) confidence_decay *= edge_weight # 链上边权连乘 ... if hop_count <= 1: interpretation = f"Direct influence with confidence {confidence_decay:.2f}." elif confidence_decay > 0.7: interpretation = f"Mediated through {hop_count - 1} step(s) with high confidence..."
三件统计随之出炉:hop_count(链长)、confidence_decay(各跳边权连乘——每过一手衰减一次)、weakest_link(最弱一环)与距离带解释文本。指南里的回放示例展示了这份报告在审计现场的读法:
chains = graph.trace_decision_causality(patch_id, max_depth=5) for chain in chains: print("Chain: {} hops | band={} | decay={:.3f}".format( chain["hop_count"], chain["distance_band"], chain["confidence_decay"])) print(" Interpretation:", chain["interpretation"]) # e.g. "Decision chain spans 2 hops in the 'near' band with 84% confidence # — causal attribution is reliable."
AgentContext.trace_decision_explainability(第 2108 行)再把上下游各 5 层的因果链与关系路径打包成一份审计报告(total_connections、upstream_decisions、downstream_decisions)。另一个细节是 CausalChainAnalyzer.trace_at_time(causal_analyzer.py 第 156 行):只沿 recorded_at <= at_time 的边回溯——"当时的信息条件下,因果链长什么样",把时态维度引入了因果审计。
先例(precedent)是法律与金融的深层直觉:新案子先看老案子。find_precedents_by_scenario(第 3323—3399 行)的检索公式:
# Content similarity content_sim = self._calculate_decision_content_similarity(scenario, decision) # Structural similarity (graph-based) structural_sim = 0.0 if self.config.get("advanced_analytics"): structural_sim = self._calculate_structural_similarity_for_decision(decision_id, scenario) # Combined similarity combined_sim = 0.7 * content_sim + 0.3 * structural_sim if combined_sim >= similarity_threshold: precedents.append({...})
0.7 内容相似走向量语义——决策的 scenario/reasoning 文本经嵌入后在向量库里找近邻(AgentContext 装配时向 DecisionQuery 传入 vector_store,向量库侧挂 initialize_decision_pipeline 注入图特征);0.3 结构相似走 Node2Vec 等图嵌入——决策节点在因果/关联拓扑里的位置。两者互补:措辞完全不同的两个场景可能在图上位置相近,反之亦然。候选先经类别倒排索引初筛(category 传入则只扫 _decision_index[category]),实体过滤可再交集收窄;include_superseded 控制是否纳入已失效决策,as_of 参数让"截至某时刻的先例"成为可能——监管问"当时你们依据什么先例",就靠它回放。指南的调用姿势一目了然:
# Search before classifying a new unattributed cluster precedents = context.find_precedents( "unattributed C2 cluster Twitter dead-drop infrastructure", limit=5) for p in precedents: print("[{:.2f} confidence] {} → {}".format(p.confidence, p.category, p.outcome)) print(" Similarity: {:.3f}".format(p.metadata.get("similarity_score", 0)))
排序后返回的先例自带相似度分数,AgentContext.find_precedents_advanced(第 2317 行)还会把因果距离叠进排序(_apply_causal_proximity_to_precedents)——因果链上离得近的先例再加权,语义与拓扑两路信号在最终榜单上合流。
指南的用法哲学值得抄录:第二个 Agent 分类同一个威胁集群前先查先例,"uses it as a prior"(把首个决策当先验)——一致性是先例搜索的产出,同一类场景不该因为两次运行而判罚迥异。但指南同时警告:相似度高分只说明场景相关,不说明相同,先例是指导不是证明。
第三个问题是反向的:一个事实/决策要变更,下游谁受影响?analyze_decision_influence(decision_id, max_depth=3)(第 3401—3489 行)分两层作答:
# Direct influence (same entities, category) direct_influence = set() for entity in decision["entities"]: direct_influence.update(self._entity_index.get(entity, set())) direct_influence.discard(decision_id) direct_influence.update(self._decision_index.get(decision["category"], set())) # 显式因果边双向都算直接影响 for edge_type in _CAUSAL_EDGE_TYPES: for edge in self.edge_type_index.get(edge_type, []): if edge.source_id == decision_id and edge.target_id in self._decisions: direct_influence.add(edge.target_id) elif edge.target_id == decision_id and edge.source_id in self._decisions: direct_influence.add(edge.source_id) # Indirect influence (through graph relationships) if include_indirect and self.config.get("advanced_analytics"): indirect_influence = self._find_indirect_decision_influence(decision_id, max_depth) - direct_influence
直接影响 = 共享实体 ∪ 同类别 ∪ 显式因果边两端;间接影响 = 图上多跳扩散再扣掉直接层。每个受影响决策再按三因子打分(第 3472—3483 行的 score_breakdown):entity_overlap(实体重叠)、category_match(类别一致)、temporal_proximity(时间邻近),输出按分排序的影响清单。README 里的对应物是 analyze_decision_impact(uw_id)——核保决策一改,波及哪些定价决策一目了然。
三件套的输入(历史决策、实体证据)都躺在记忆层上。AgentMemory(agent_memory.py 第 160 行起)是三层结构:
self.memory_items: Dict[str, MemoryItem] = {} # 长期:全量条目 self.memory_index: deque = deque(maxlen=self.max_memory_size) # 时间索引 self.short_term_memory: List[MemoryItem] = [] # 短期缓冲(默认 10 条)
short_term_memory 列表,short_term_limit 默认 10 条,按 token 上限(token_limit 默认 2000)与条数双重剪枝(_prune_short_term_memory)——Agent 工作台上的便签。store() 写透(write-through)到向量库(带嵌入)与 memory_items 全量字典;retrieve() 先走向量相似检索,向量库不可用时回退关键词重合度(_keyword_search),保证记忆功能零依赖可用。_update_knowledge_graph(第 872 行)把记忆里的实体/关系同步进图谱——记忆不只存文本,还喂图。工程细节也有讲究:save/load 用 JSON 且拒绝加载旧 pickle 文件(第 270 行,防反序列化攻击);retention_policy 按 "{days}_days" 或 "unlimited" 驱动定期清理(_apply_retention_policy)。
与业界对照,这套"短期缓冲 + 长期向量 + 图结构化"的三层与主流 Agent 记忆方案(MemGPT/Letta 式分层、Mem0 式向量记忆)同构,Semantica 的差异化在两点:其一,记忆与决策智能显式分家——指南的官方定义是"Agent Memory stores external knowledge (documents, facts, observations). Decision Intelligence stores internal decisions";其二,记忆、图谱、向量库在同一容器里三向同步,先例搜索才能同时吃到语义与结构两路信号。
这张装配图串起本节全部主角:Agent 的输入经 store 流入 AgentMemory(短期+长期),ContextRetriever 做混合检索,决策经 record_decision 入图,因果链与先例搜索在图上闭环。
💡 装配要点:三件套在管线里各守一问——因果链答"为什么"(显式 CAUSED/INFLUENCED/PRECEDENT_FOR 边优先、共享实体启发式补链、confidence_decay 边权连乘、truncated 标记必须检查),先例搜索答"有无先例"(0.7 语义+0.3 结构,as_of 支持时点回放),影响面分析答"动了谁"(直接层三来源+间接层多跳,三因子打分)。AgentMemory 是底座:短期限 10 条/2000 token,长期写透向量库,
_update_knowledge_graph同步图谱;记忆存外部知识、决策存内部判断,勿混。
add_causal_relationship 是因果追踪的前提,孤立决策节点是反模式。trace_decision_causality:显式边反索引 + 递归回溯(每路径环检测)+ 启发式补链(共享实体+更早时间戳);max_chains 触顶追加 truncated 标记;报告含 hop_count/confidence_decay(边权连乘)/weakest_link/距离带解释。CausalChainAnalyzer 提供 Cypher 变长路径版与 trace_at_time(只沿 recorded_at ≤ 截点的边回溯);trace_decision_explainability 上下游各 5 层打包成审计报告。find_precedents_by_scenario = 0.7 内容相似(向量)+ 0.3 结构相似(Node2Vec),类别/实体索引初筛,as_of 时点回放;先例保持判罚一致性,但相似≠相同。下一节:
03 PolicyEngine 策略门禁与贷款审批配方 ★——版本化策略、min_/max_/required_ 规则 DSL、违规拦截与例外审批,以及从录入到审计的端到端贷款审批配方。