CIE-Unified

git clone 

commit
423d812
parent
bcde56d
author
im_wower
date
2026-04-01 09:58:10 +0800 CST
integration phase2: PendingSignal信号队列移植(来自A) — 12/12 tests pass
3 files changed,  +143, -50
M cie/__init__.py
+2, -2
 1@@ -1,7 +1,7 @@
 2 """CIE — Cognitive Inference Engine"""
 3 from .graph import Graph, Node, Edge
 4-from .state import CIEState, AttentionPool
 5+from .state import CIEState, AttentionPool, PendingSignal
 6 from .dynamics import Dynamics
 7 from .runtime import CIERuntime
 8 
 9-__all__ = ['Graph', 'Node', 'Edge', 'CIEState', 'AttentionPool', 'Dynamics', 'CIERuntime']
10+__all__ = ['Graph', 'Node', 'Edge', 'CIEState', 'AttentionPool', 'PendingSignal', 'Dynamics', 'CIERuntime']
M cie/runtime.py
+118, -48
  1@@ -9,7 +9,7 @@ import random
  2 import math
  3 from typing import Optional
  4 from .graph import Graph
  5-from .state import CIEState
  6+from .state import CIEState, PendingSignal
  7 from .dynamics import Dynamics
  8 
  9 
 10@@ -32,7 +32,6 @@ class CIERuntime:
 11         self._last_output: Optional[dict] = None
 12 
 13         # ── 回灌标记 ──
 14-        self._feedback_pending = False
 15 
 16     # ──────────────────────────────────────
 17     # §5.1 ingest — 接收输入,注入图中
 18@@ -55,8 +54,7 @@ class CIERuntime:
 19         # ── 输出即输入回灌 ──
 20         if self._last_output is not None and self._feedback_pending:
 21             self._feedback_loop(self._last_output)
 22-            self._feedback_pending = False
 23-
 24+    
 25         # ── 解析输入为 token 序列 ──
 26         if isinstance(input_data, str):
 27             tokens = list(input_data)
 28@@ -113,11 +111,75 @@ class CIERuntime:
 29     def step(self, n: int = 1):
 30         """
 31         推进 n 步内部动力学演化。
 32-        必须真实改变内部状态。
 33+        第一步先消费所有 pending_signals,然后跑动力学。
 34         """
 35-        for _ in range(n):
 36+        for i in range(n):
 37+            # 第一步消费所有信号
 38+            if i == 0:
 39+                self._consume_signals()
 40             self.dynamics.step()
 41 
 42+    def _consume_signals(self):
 43+        """消费所有排队的信号——来自 ingest/emit/feedback"""
 44+        signals = list(self.state.pending_signals)
 45+        self.state.pending_signals.clear()
 46+
 47+        for signal in signals:
 48+            self._apply_signal(signal)
 49+
 50+    def _apply_signal(self, signal):
 51+        """应用一个信号到图上"""
 52+        tokens = signal.tokens
 53+        if not tokens:
 54+            return
 55+
 56+        # ── 注入节点和激活 ──
 57+        for token in tokens:
 58+            if not self.graph.has_node(token):
 59+                self.graph.add_node(token, label=token)
 60+                self.state.init_node(token, phi_val=self.rng.gauss(0.0, 0.1))
 61+
 62+            inject_amount = (100.0 / max(len(tokens), 1) * 0.5) * signal.strength
 63+            if signal.polarity >= 0:
 64+                self.state.activate(token, inject_amount)
 65+            else:
 66+                # 负极性:衰减
 67+                self.state.phi[token] = self.state.phi.get(token, 0.0) * 0.5
 68+                self.state.weaken_confidence(token, amount=abs(signal.strength))
 69+
 70+        # ── 建立 bigram 边(非对称) ──
 71+        for i in range(len(tokens) - 1):
 72+            src, dst = tokens[i], tokens[i + 1]
 73+            existing_w = self.graph.get_edge_weight(src, dst)
 74+            asym = self.rng.gauss(0.0, 0.1)
 75+            increment = 1.0 / (1.0 + existing_w * 0.1) * signal.strength
 76+            self.graph.add_edge(
 77+                src, dst,
 78+                weight=existing_w + increment + abs(asym),
 79+                bwd_weight=existing_w + increment - abs(asym) * 0.5,
 80+                edge_type='bigram'
 81+            )
 82+            self.state.update_confidence(src, 0, amount=0.5 * signal.strength)
 83+            self.state.update_confidence(dst, 1, amount=0.5 * signal.strength)
 84+
 85+        # ── 锚点注入 ──
 86+        for anchor in signal.anchor_tokens:
 87+            if not self.graph.has_node(anchor):
 88+                self.graph.add_node(anchor, label=anchor)
 89+                self.state.init_node(anchor, phi_val=1.0)
 90+            self.state.update_confidence(anchor, 2, amount=10.0 * signal.strength)
 91+            self.state.phi[anchor] = self.state.phi.get(anchor, 0.0) + 1.0 * signal.strength
 92+
 93+        # ── 回灌信号额外处理 ──
 94+        if signal.source == "emit":
 95+            # 回灌的激活量较弱
 96+            for token in tokens:
 97+                mu_val = signal.metadata.get("mu_" + token, 0.0)
 98+                feedback_amount = mu_val * 0.05
 99+                if feedback_amount > 0.001 and self.graph.has_node(token):
100+                    self.state.activate(token, feedback_amount)
101+                    self.state.phi[token] = self.state.phi.get(token, 0.0) + feedback_amount * 0.01
102+
103     # ──────────────────────────────────────
104     # §5.3 emit — 生成输出
105     # ──────────────────────────────────────
106@@ -168,6 +230,20 @@ class CIERuntime:
107             'active_count': len(self.state.active_region),
108         }
109 
110+        # 创建回灌信号排队
111+        metadata = {"mode": output["mode"]}
112+        for item in output.get("activated", []):
113+            metadata["mu_" + item["node"]] = item.get("mu", 0.0)
114+
115+        feedback_signal = PendingSignal(
116+            source="emit",
117+            tokens=[item["node"] for item in output.get("activated", [])[:5]],
118+            strength={"full": 0.5, "degraded": 0.3, "minimal": 0.1}.get(output["mode"], 0.1),
119+            polarity=1,
120+            metadata=metadata,
121+        )
122+        self.state.pending_signals.append(feedback_signal)
123+
124         self._last_output = output
125         self._output_buffer.append(output)
126         return output
127@@ -178,50 +254,48 @@ class CIERuntime:
128 
129     def commit_feedback(self, feedback: dict):
130         """
131-        把反馈写回系统——经验沉积、技能带修正、能力核慢更新。
132-        
133-        feedback: dict
134-            - 'correct': list[str] — 正确的节点,增强置信度
135-            - 'wrong': list[str] — 错误的节点,降低置信度
136-            - 'reward': float — 全局奖励信号
137+        把反馈写回系统——通过信号队列。
138         """
139         effect = {'reinforced': [], 'weakened': [], 'reward': 0.0}
140 
141-        # 正确的节点:增强置信度(cat2=独立引用) + 势场
142-        for node_id in feedback.get('correct', []):
143-            if self.graph.has_node(node_id):
144-                self.state.update_confidence(node_id, 2, amount=2.0)
145-                self.state.phi[node_id] = (
146-                    self.state.phi.get(node_id, 0.0) + 0.5
147-                )
148-                effect['reinforced'].append(node_id)
149-
150-        # 错误的节点:衰减势场 + 削弱置信度
151-        for node_id in feedback.get('wrong', []):
152-            if self.graph.has_node(node_id):
153-                self.state.phi[node_id] = (
154-                    self.state.phi.get(node_id, 0.0) * 0.5
155-                )
156-                self.state.weaken_confidence(node_id, amount=3.0)
157-                effect['weakened'].append(node_id)
158+        # 正确的节点——创建正向信号
159+        correct = feedback.get('correct', [])
160+        if correct:
161+            signal = PendingSignal(
162+                source="feedback",
163+                tokens=correct,
164+                strength=2.0,
165+                polarity=1,
166+                metadata={"type": "correct"},
167+            )
168+            self.state.pending_signals.append(signal)
169+            effect['reinforced'] = list(correct)
170+
171+        # 错误的节点——创建负向信号
172+        wrong = feedback.get('wrong', [])
173+        if wrong:
174+            signal = PendingSignal(
175+                source="feedback",
176+                tokens=wrong,
177+                strength=3.0,
178+                polarity=-1,
179+                metadata={"type": "wrong"},
180+            )
181+            self.state.pending_signals.append(signal)
182+            effect['weakened'] = list(wrong)
183 
184-        # 全局奖励
185+        # 全局奖励——对当前活跃区域
186         reward = feedback.get('reward', 0.0)
187         effect['reward'] = reward
188-        if reward > 0:
189-            # 正奖励强化当前激活区域——按已有最强分量方向增强
190-            for node_id in self.state.active_region:
191-                if node_id in self.state.confidence:
192-                    alphas = self.state.confidence[node_id]
193-                    best_cat = alphas.index(max(alphas))
194-                    self.state.update_confidence(node_id, best_cat, amount=reward)
195-                else:
196-                    self.state.update_confidence(node_id, 0, amount=reward)
197-        elif reward < 0:
198-            # 负奖励衰减当前激活区域(势场+置信度)
199-            for node_id in self.state.active_region:
200-                self.state.phi[node_id] *= max(0.1, 1.0 + reward)
201-                self.state.weaken_confidence(node_id, amount=abs(reward))
202+        if reward != 0 and self.state.active_region:
203+            signal = PendingSignal(
204+                source="feedback",
205+                tokens=list(self.state.active_region)[:10],
206+                strength=abs(reward),
207+                polarity=1 if reward > 0 else -1,
208+                metadata={"type": "reward", "reward": reward},
209+            )
210+            self.state.pending_signals.append(signal)
211 
212         self.state.last_feedback_effect = effect
213 
214@@ -261,16 +335,12 @@ class CIERuntime:
215         # 清理输出缓冲
216         self._output_buffer.clear()
217         self._last_output = None
218-        self._feedback_pending = False
219 
220         # 保留:phi, confidence, anchor_nodes, ability_cores,
221         #        experience_hits, experience_regions, skill_belt_candidates
222 
223         self.state.output_mode = 'minimal'
224 
225-    # ──────────────────────────────────────
226-    # 内部:输出即输入回灌
227-    # ──────────────────────────────────────
228 
229     def _feedback_loop(self, last_output: dict):
230         """
M cie/state.py
+23, -0
 1@@ -8,6 +8,26 @@ J(u,v) = 边流(中速)— 技能/流动偏置
 2 注意力池总量 100 点守恒。
 3 """
 4 
 5+
 6+from dataclasses import dataclass, field as dc_field
 7+from typing import Any as TypAny
 8+
 9+
10+@dataclass
11+class PendingSignal:
12+    """
13+    统一信号对象(来自 Branch A)。
14+    所有输入/反馈/回灌都先排队为 PendingSignal,在下一步 step 时消费。
15+    """
16+    source: str              # "external" | "emit" | "feedback"
17+    tokens: list             # 主 token 列表
18+    context_tokens: list = dc_field(default_factory=list)
19+    anchor_tokens: list = dc_field(default_factory=list)
20+    strength: float = 1.0    # 信号强度
21+    polarity: int = 1        # 1=正向, -1=负向
22+    metadata: dict = dc_field(default_factory=dict)
23+
24+
25 from collections import defaultdict
26 import math
27 import random
28@@ -113,6 +133,9 @@ class CIEState:
29         # ── 步计数 ──
30         self.step_count: int = 0
31 
32+        # ── 信号队列(来自 Branch A) ──
33+        self.pending_signals: list = []  # List[PendingSignal]
34+
35         # ── 反馈效果 ──
36         self.last_feedback_effect: dict = {}
37