File size: 10,283 Bytes
ae1e90a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | #!/usr/bin/env python3
"""
Shared Blackboard System
ISL-safe expert collaboration via evidence store
NO direct expert-to-expert messaging
"""
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field
from datetime import datetime
import json
@dataclass
class Evidence:
"""
Immutable evidence entry from an expert
Write-only, no modification after creation
"""
expert: str
finding: Any
method: str
confidence: float
scope: str
timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
metadata: Dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> Dict:
"""Convert to dictionary"""
return {
"expert": self.expert,
"finding": self.finding,
"method": self.method,
"confidence": self.confidence,
"scope": self.scope,
"timestamp": self.timestamp,
"metadata": self.metadata
}
class SharedBlackboard:
"""
Shared evidence store for expert collaboration
Rules:
- Experts can ONLY write (no modification)
- Entries are immutable
- No expert-to-expert messaging
- Orchestration by Grok Layer only
"""
def __init__(self):
self.evidence: List[Evidence] = []
self.request_id: Optional[str] = None
self._locked = False
def start_request(self, request_id: str):
"""Start new request - clears previous evidence"""
self.evidence = []
self.request_id = request_id
self._locked = False # Unlock for new request
def write_evidence(
self,
expert: str,
finding: Any,
method: str,
confidence: float,
scope: str = "general",
metadata: Optional[Dict] = None
) -> Evidence:
"""
Expert writes evidence to blackboard
Args:
expert: Expert identifier
finding: The finding (structured data)
method: How it was derived
confidence: 0.0-1.0
scope: What domain this applies to
metadata: Additional context
Returns:
Evidence entry
"""
if self._locked:
raise RuntimeError("Blackboard is locked - no more writes allowed")
# Validate confidence
if not 0.0 <= confidence <= 1.0:
raise ValueError(f"Confidence must be 0.0-1.0, got {confidence}")
# Create immutable evidence
evidence = Evidence(
expert=expert,
finding=finding,
method=method,
confidence=confidence,
scope=scope,
metadata=metadata or {}
)
self.evidence.append(evidence)
return evidence
def read_evidence(
self,
expert_filter: Optional[str] = None,
scope_filter: Optional[str] = None
) -> List[Evidence]:
"""
Read evidence from blackboard (read-only)
Args:
expert_filter: Only return evidence from this expert
scope_filter: Only return evidence for this scope
Returns:
List of matching evidence
"""
results = self.evidence
if expert_filter:
results = [e for e in results if e.expert == expert_filter]
if scope_filter:
results = [e for e in results if e.scope == scope_filter]
return results
def lock(self):
"""Lock blackboard - no more writes allowed"""
self._locked = True
def get_all_evidence(self) -> List[Dict]:
"""Get all evidence as dictionaries"""
return [e.to_dict() for e in self.evidence]
def get_summary(self) -> Dict[str, Any]:
"""Get summary of blackboard state"""
return {
"request_id": self.request_id,
"total_evidence": len(self.evidence),
"experts_contributed": len(set(e.expert for e in self.evidence)),
"locked": self._locked,
"evidence": self.get_all_evidence()
}
class Arbitrator:
"""
Arbitrates evidence from blackboard
Implements consensus rules (NOT voting)
"""
def __init__(self, blackboard: SharedBlackboard):
self.blackboard = blackboard
def aggregate_confidence(self) -> float:
"""
Aggregate confidence from all evidence
Rule: Confidence bounded by WEAKEST critical check
NOT average, NOT voting
"""
evidence = self.blackboard.evidence
if not evidence:
return 0.0
# Find minimum confidence (weakest link)
min_confidence = min(e.confidence for e in evidence)
# If any expert has very low confidence, that dominates
if min_confidence < 0.5:
return min_confidence
# Otherwise, use weighted average biased toward lower values
confidences = [e.confidence for e in evidence]
# Geometric mean (more conservative than arithmetic)
product = 1.0
for c in confidences:
product *= c
geometric_mean = product ** (1.0 / len(confidences))
return geometric_mean
def detect_conflicts(self) -> List[Dict[str, Any]]:
"""
Detect conflicting evidence
Returns:
List of conflicts found
"""
conflicts = []
evidence = self.blackboard.evidence
# Group by scope
by_scope: Dict[str, List[Evidence]] = {}
for e in evidence:
if e.scope not in by_scope:
by_scope[e.scope] = []
by_scope[e.scope].append(e)
# Check for contradictions within each scope
for scope, scope_evidence in by_scope.items():
if len(scope_evidence) < 2:
continue
# Check if findings contradict
findings = [e.finding for e in scope_evidence]
# Simple contradiction check (can be enhanced)
if len(set(str(f) for f in findings)) > 1:
conflicts.append({
"scope": scope,
"experts": [e.expert for e in scope_evidence],
"findings": findings,
"confidences": [e.confidence for e in scope_evidence]
})
return conflicts
def synthesize_answer(self) -> Dict[str, Any]:
"""
Synthesize final answer from all evidence
Returns:
Synthesized result with confidence
"""
evidence = self.blackboard.evidence
if not evidence:
return {
"answer": None,
"confidence": 0.0,
"method": "no_evidence"
}
# Aggregate confidence
confidence = self.aggregate_confidence()
# Detect conflicts
conflicts = self.detect_conflicts()
# If conflicts exist, reduce confidence
if conflicts:
confidence *= 0.7 # Penalty for conflicts
# Get primary finding (highest confidence)
primary = max(evidence, key=lambda e: e.confidence)
return {
"answer": primary.finding,
"confidence": confidence,
"method": "arbitrated",
"primary_expert": primary.expert,
"supporting_experts": [e.expert for e in evidence if e.expert != primary.expert],
"conflicts": conflicts
}
def test_blackboard():
"""Test shared blackboard system"""
print("="*70)
print("Testing Shared Blackboard System")
print("="*70)
# Create blackboard
blackboard = SharedBlackboard()
blackboard.start_request("test_001")
# Math expert writes evidence
print("\n1. Math Expert writes evidence:")
math_evidence = blackboard.write_evidence(
expert="math",
finding=150.0,
method="direct_multiplication",
confidence=1.0,
scope="calculation",
metadata={"operation": "60 * 2.5"}
)
print(f" Written: {math_evidence.finding} (confidence: {math_evidence.confidence})")
# Logic expert writes evidence
print("\n2. Logic Expert writes evidence:")
logic_evidence = blackboard.write_evidence(
expert="logic",
finding="Units consistent: mph × hours → miles",
method="unit_analysis",
confidence=0.95,
scope="validation"
)
print(f" Written: {logic_evidence.finding} (confidence: {logic_evidence.confidence})")
# Security expert writes evidence (lower confidence)
print("\n3. Security Expert writes evidence:")
security_evidence = blackboard.write_evidence(
expert="security",
finding="No security concerns",
method="static_analysis",
confidence=0.6,
scope="validation"
)
print(f" Written: {security_evidence.finding} (confidence: {security_evidence.confidence})")
# Lock blackboard
blackboard.lock()
print("\n4. Blackboard locked")
# Arbitrate
print("\n5. Arbitration:")
arbitrator = Arbitrator(blackboard)
confidence = arbitrator.aggregate_confidence()
print(f" Aggregated confidence: {confidence:.3f}")
conflicts = arbitrator.detect_conflicts()
print(f" Conflicts detected: {len(conflicts)}")
result = arbitrator.synthesize_answer()
print(f" Final answer: {result['answer']}")
print(f" Final confidence: {result['confidence']:.3f}")
print(f" Primary expert: {result['primary_expert']}")
# Summary
print("\n6. Blackboard Summary:")
summary = blackboard.get_summary()
print(f" Total evidence: {summary['total_evidence']}")
print(f" Experts contributed: {summary['experts_contributed']}")
print(f" Locked: {summary['locked']}")
print("\n" + "="*70)
print("✓ Blackboard system working!")
print("="*70)
if __name__ == "__main__":
test_blackboard()
|