Part of Building CNS 2.0: A Developer's Guide

Chapter 4: The Synthesis Engine & Relational Metrics

Beyond Averaging: The Dialectical Workflow

The creative core of CNS 2.0 is its ability to generate genuinely new knowledge from conflict. This is achieved through a sophisticated, four-step dialectical workflow that forms the heart of the Synthesis Engine.

  1. **Chiral Pair Selection:** Identify the most “productive” conflicts—pairs of SNOs that are both highly contradictory and argue over the same facts.
  2. **Dialectical Prompt Construction:** Transform the SNOs into a structured prompt for an LLM that clearly outlines the conflict and the synthesis task.
  3. **Candidate Generation:** The LLM performs dialectical reasoning to generate a new candidate SNO that attempts to resolve the conflict.
  4. **Critic Evaluation:** The new SNO is evaluated by the full Critic Pipeline. If it meets the quality threshold, it is integrated into the knowledge base. This chapter builds the components for this workflow, starting with the critical metrics that guide the first step.

**Ethical Consideration: The Dual-Use Nature of Synthesis**

Before we build this powerful engine, it’s crucial to address its ethical implications. A system designed to synthesize conflicting information to find truth can just as easily be used to synthesize disparate conspiracy theories into a coherent, believable, and dangerous piece of disinformation. This is the dual-use nature of CNS 2.0.

As developers, we have a responsibility to build safeguards directly into our systems. This includes technical solutions for detecting and preventing misuse, as well as clear policies governing the system’s operation.

For a deep-dive into this critical challenge, see the research project on Privacy, Security & Misuse Prevention.

Step 1: Identifying Productive Conflicts with Relational Metrics

The system must intelligently select which conflicts to focus on. A disagreement between two low-trust, poorly-evidenced narratives is likely just noise. In contrast, a sharp disagreement between two well-supported narratives that both cite the same evidence is a profound opportunity for discovery. Section 3.2 of the paper defines two precise metrics for finding these opportunities.

Metric 1: Chirality Score

The Chirality Score measures the degree of weighted opposition between two narratives.

**From the Paper (Section 3.2):**

$$\text{CScore}(SNO\_i, SNO\_j) = (1 - H\_i \cdot H\_j) \cdot (T\_i \cdot T\_j)$$

Formula Breakdown: CScore

This elegant formula combines two key ideas: semantic opposition and established trust.

  • **(1 - H\_i ⋅ H\_j)**: This term measures the **opposition** of the core hypotheses.
  • H\_i ⋅ H\_j is the cosine similarity between the two hypothesis embeddings. For normalized vectors, this ranges from -1 (perfectly opposite) to 1 (identical).
  • By subtracting from 1, we map this similarity score to an opposition score. If the hypotheses are identical (similarity=1), opposition is 0. If they are perfectly opposite (similarity=-1), opposition is 2. This term quantifies the conceptual distance between the core claims.
  • **(T\_i ⋅ T\_j)**: This term is the **trust weighting**.
  • It’s the product of the two SNOs’ trust scores. This term acts as a crucial quality filter. A conflict is only interesting if **both** narratives are credible. If either T\_i or T\_j is low, the product is low, and the Chirality Score will be low, regardless of how much the hypotheses oppose each other. This prevents the system from wasting expensive computational resources on “arguments from ignorance.”

Metric 2: Evidential Entanglement

This metric measures the degree to which two narratives are arguing over the same data.

**From the Paper (Section 3.2):**

$$\text{EScore}(SNO\_i, SNO\_j) = \frac{|\mathcal{E}\_i \cap \mathcal{E}\_j|}{|\mathcal{E}\_i \cup \mathcal{E}\_j|}$$

Formula Breakdown: EScore

This is the **Jaccard Similarity Index**, a standard and effective metric for comparing the similarity of two sets.

  • **|E\_i ∩ E\_j|**: The numerator is the size of the **intersection** of the two evidence sets—the number of identical pieces of evidence that both narratives cite.
  • **|E\_i ∪ E\_j|**: The denominator is the size of the **union** of the two evidence sets—the total number of unique pieces of evidence across both SNOs.
  • A high score (close to 1.0) means the narratives are highly “entangled,” attempting to explain the exact same set of facts. A low score (close to 0.0) means they are talking about different things, and their conflict may be superficial.

The Synthesis Trigger: The Key to Productive Reasoning

**“Synthesis is prioritized for pairs with both high Chirality and high Entanglement.”** This principle is the cornerstone of the system’s efficiency and creativity. By focusing only on pairs that meet both criteria, CNS 2.0 identifies the most fertile ground for generating novel insights: two well-supported, opposing theories that are attempting to explain the same set of facts.

"""
Generative Synthesis Engine Implementation
=========================================
LLM-powered dialectical reasoning for knowledge synthesis
"""
# ... (imports and dataclasses like ChiralPair would be here) ...
class RelationalMetrics:
@staticmethod
def \_cosine\_similarity(v1: np.ndarray, v2: np.ndarray) -> float:
"""Helper for cosine similarity, the H\_i ⋅ H\_j part of the CScore formula."""
# Ensure vectors are normalized for accurate cosine similarity
v1\_norm = v1 / np.linalg.norm(v1)
v2\_norm = v2 / np.linalg.norm(v2)
return np.dot(v1\_norm, v2\_norm)
@staticmethod
def chirality\_score(sno\_a: StructuredNarrativeObject, sno\_b: StructuredNarrativeObject) -> float:
"""Implements the CScore formula from the paper."""
if sno\_a.hypothesis\_embedding is None or sno\_b.hypothesis\_embedding is None or sno\_a.trust\_score is None or sno\_b.trust\_score is None:
return 0.0
# This term calculates semantic opposition: (1 - H\_i ⋅ H\_j)
cos\_sim = RelationalMetrics.\_cosine\_similarity(sno\_a.hypothesis\_embedding, sno\_b.hypothesis\_embedding)
opposition = 1.0 - cos\_sim # Ranges from 0 (identical) to 2 (opposite)
# This term is the trust weighting: (T\_i ⋅ T\_j)
trust\_product = sno\_a.trust\_score \* sno\_b.trust\_score
# The final score is normalized to be in [0, 1] by dividing opposition by 2
return (opposition / 2.0) \* trust\_product
@staticmethod
def evidential\_entanglement(sno\_a: StructuredNarrativeObject, sno\_b: StructuredNarrativeObject) -> Tuple[float, Set[str]]:
"""Implements the EScore formula (Jaccard similarity) from the paper."""
# We use the unique hash of evidence content for robust comparison
evidence\_a\_hashes = {e.doc\_hash for e in sno\_a.evidence\_set}
evidence\_b\_hashes = {e.doc\_hash for e in sno\_b.evidence\_set}
if not evidence\_a\_hashes and not evidence\_b\_hashes:
return 0.0, set()
intersection = evidence\_a\_hashes.intersection(evidence\_b\_hashes)
union = evidence\_a\_hashes.union(evidence\_b\_hashes)
score = len(intersection) / len(union) if union else 0.0
return score, intersection
@staticmethod
def synthesis\_potential(chirality: float, entanglement: float) -> float:
"""Combines chirality and entanglement into a single heuristic for prioritizing pairs."""
if chirality < 0 or entanglement < 0: return 0.0
# Geometric mean heavily penalizes pairs where one score is very low.
geometric\_mean = np.sqrt(chirality \* entanglement)
# Bonus for pairs where scores are balanced, indicating a well-proportioned conflict.
balance\_bonus = 1.0 - abs(chirality - entanglement)
return geometric\_mean \* (1.0 + 0.2 \* balance\_bonus)

Scalable Pair Detection with faiss

The paper (Section 3.3) mandates an efficient, two-step process for finding synthesis candidates. A naive, brute-force approach of comparing every SNO to every other SNO would require $O(N^2)$ calculations. For a population of one million SNOs, this is a trillion comparisons— computationally impossible. We solve this by using an **Approximate Nearest Neighbor (ANN)** index. Libraries like faiss (Facebook AI Similarity Search) allow us to pre-process all hypothesis embeddings into a special data structure. This index lets us find the k most similar (or dissimilar) vectors to a given vector in logarithmic or even constant time, reducing the search complexity from $O(N^2)$ to roughly $O(N \log k)$. This makes finding promising pairs feasible at scale. Our ChiralPairDetector uses faiss to pre-filter a small set of candidate pairs with high potential CScore, and only then calculates the more intensive EScore on this small set.

# Import FAISS for scalable ANN-based pair finding
try:
import faiss
HAS\_FAISS = True
except ImportError:
HAS\_FAISS = False
print("Warning: faiss library not found. ChiralPairDetector will be inefficient.")
class ChiralPairDetector:
def \_\_init\_\_(self, embedding\_model, chirality\_threshold=0.7, entanglement\_threshold=0.5):
self.embedding\_model = embedding\_model
self.chirality\_threshold = chirality\_threshold
self.entanglement\_threshold = entanglement\_threshold
def find\_chiral\_pairs(self, sno\_population: List[StructuredNarrativeObject], max\_pairs: int = 10) -> List[ChiralPair]:
"""Finds the most promising chiral pairs from a population for synthesis."""
# For small populations or if faiss is not installed, brute force is acceptable.
if not HAS\_FAISS or len(sno\_population) <= 100:
return self.\_find\_pairs\_brute\_force(sno\_population, max\_pairs)
else:
return self.\_find\_pairs\_faiss(sno\_population, max\_pairs)
def \_find\_pairs\_brute\_force(self, sno\_population: List[StructuredNarrativeObject], max\_pairs: int) -> List[ChiralPair]:
"""A simple O(N^2) pair finding method for small populations."""
candidate\_pairs = []
for i in range(len(sno\_population)):
for j in range(i + 1, len(sno\_population)):
sno\_a, sno\_b = sno\_population[i], sno\_population[j]
chirality = RelationalMetrics.chirality\_score(sno\_a, sno\_b)
if chirality < self.chirality\_threshold:
continue
entanglement, shared\_ids = RelationalMetrics.evidential\_entanglement(sno\_a, sno\_b)
if entanglement < self.entanglement\_threshold:
continue
potential = RelationalMetrics.synthesis\_potential(chirality, entanglement)
candidate\_pairs.append(ChiralPair(
sno\_a=sno\_a, sno\_b=sno\_b, chirality=chirality, entanglement=entanglement,
potential=potential, shared\_evidence\_ids=shared\_ids, conflict\_summary=[]
))
candidate\_pairs.sort(key=lambda p: p.potential, reverse=True)
return candidate\_pairs[:max\_pairs]
def \_find\_pairs\_faiss(self, sno\_population: List[StructuredNarrativeObject], max\_pairs: int) -> List[ChiralPair]:
"""Finds candidate pairs efficiently using a FAISS index for large populations."""
valid\_snos = [s for s in sno\_population if s.hypothesis\_embedding is not None and s.trust\_score is not None]
if len(valid\_snos) < 2: return []
sno\_map = {i: sno for i, sno in enumerate(valid\_snos)}
embeddings = np.array([s.hypothesis\_embedding for s in valid\_snos]).astype('float32')
faiss.normalize\_L2(embeddings) # Normalize for cosine similarity via inner product
dimension = embeddings.shape[1]
index = faiss.IndexFlatIP(dimension)
index.add(embeddings)
k = min(len(valid\_snos), 20) # Find up to 20 nearest neighbors
distances, indices = index.search(embeddings, k)
processed\_pairs = set()
candidate\_pairs = []
for i in range(len(indices)):
sno\_a = sno\_map[i]
for j\_idx, dist in zip(indices[i], distances[i]):
if i == j\_idx: continue # Skip self-comparison
pair\_key = tuple(sorted((i, j\_idx)))
if pair\_key in processed\_pairs: continue
processed\_pairs.add(pair\_key)
sno\_b = sno\_map[j\_idx]
chirality = RelationalMetrics.chirality\_score(sno\_a, sno\_b)
if chirality < self.chirality\_threshold: continue
entanglement, shared\_ids = RelationalMetrics.evidential\_entanglement(sno\_a, sno\_b)
if entanglement < self.entanglement\_threshold: continue
potential = RelationalMetrics.synthesis\_potential(chirality, entanglement)
candidate\_pairs.append(ChiralPair(
sno\_a=sno\_a, sno\_b=sno\_b, chirality=chirality, entanglement=entanglement,
potential=potential, shared\_evidence\_ids=shared\_ids, conflict\_summary=[]
))
candidate\_pairs.sort(key=lambda p: p.potential, reverse=True)
return candidate\_pairs[:max\_pairs]

Advanced Agent Action: Guided Narrative Exploration

The paper also describes a more subtle agent action than direct synthesis: **refinement** through guided exploration. Instead of combining two SNOs, an agent can try to improve a single SNO, SNO\_i, especially when it’s in conflict with another, SNO\_j. The goal is to find a “sweet spot” in the latent space—a new hypothesis that is better than SNO\_i but doesn’t simply copy SNO\_j. This is achieved by calculating a target embedding, $H\_{\text{target}}$.

**From the Paper (Equation 2, Section 3.4):**

$$H\_{\text{target}} = H\_{i} + \alpha \nabla\_{H\_i} \text{Reward}(SNO\_i) + \beta \cdot \text{CScore}(SNO\_i, SNO\_j) \frac{H\_{i} - H\_{j}}{\|H\_{i} - H\_{j}\|}$$

Instead of directly modifying the SNO, this target vector is used to prompt a generative agent: *“Generate a new SNO whose core hypothesis is semantically close to $H\_{\text{target}}$, drawing inspiration from the reasoning and evidence of SNO$\_i$.”*

Formula Breakdown: H\_target

This formula has three distinct vector components:

  1. **The Starting Point**: $H\_i$, the embedding of our current SNO. This is our anchor.
  2. **The Improvement Vector**: $\alpha \nabla\_{H\_i} \text{Reward}(SNO\_i)$. This vector “points” in a direction in the latent space that would increase the SNO’s reward score. Calculating the true gradient ($\nabla$) is complex, so in practice we use a proxy—a vector that moves towards a more “ideal” state (e.g., an embedding representing a highly trusted concept).
  3. **The Repulsion Vector**: $\beta \cdot \text{CScore} \frac{H\_{i} - H\_{j}}{\|H\_{i} - H\_{j}\|}$. This vector points directly away from the opposing SNO, SNO\_j. The magnitude of this “push” is scaled by the CScore and a tuning parameter beta.
def calculate\_target\_embedding(
sno\_i: StructuredNarrativeObject,
sno\_j: StructuredNarrativeObject,
reward\_gradient\_proxy: np.ndarray,
alpha: float,
beta: float
) -> np.ndarray:
"""
Implements Guided Narrative Exploration from Section 3.4 of the paper.
This function computes a target vector in the latent space to guide the
generation of a new, refined narrative.
"""
if sno\_i.hypothesis\_embedding is None or sno\_j.hypothesis\_embedding is None:
raise ValueError("Both SNOs must have computed hypothesis embeddings.")
h\_i = sno\_i.hypothesis\_embedding
h\_j = sno\_j.hypothesis\_embedding
# The "improvement vector" points toward a region of higher reward.
# In a real system, the proxy could be a vector pointing towards an
# archetypal "good" SNO or derived from critic feedback.
improvement\_vector = alpha \* reward\_gradient\_proxy
# The "repulsion vector" points away from the opposing SNO.
c\_score = RelationalMetrics.chirality\_score(sno\_i, sno\_j)
# Ensure the direction vector is normalized before scaling.
repulsion\_direction = (h\_i - h\_j) / np.linalg.norm(h\_i - h\_j)
repulsion\_vector = beta \* c\_score \* repulsion\_direction
# Combine the vectors to find the target destination in the latent space.
h\_target = h\_i + improvement\_vector + repulsion\_vector
# Normalize the final vector to ensure it's a valid embedding.
h\_target\_normalized = h\_target / np.linalg.norm(h\_target)
return h\_target\_normalized

Making it Concrete: Visualizing the SNO Latent Space

The concepts of “latent space,” “chirality,” and “conceptual distance” are powerful but abstract. We can make them intuitive by visualizing the high-dimensional hypothesis embeddings in 2D space using **t-SNE (t-Distributed Stochastic Neighbor Embedding)**. This is a powerful diagnostic and exploratory tool for understanding the health and structure of your knowledge base. **Why this is useful:** A t-SNE plot helps you answer key questions at a glance:

  • Are there distinct **clusters of thought** in my knowledge base?
  • Are my high-trust SNOs all clustered together, or are there multiple, competing high-trust theories?
  • Where are the “chiral pairs”? They should appear as two points, often far from each other, but both with high trust scores.
  • Where do new, synthesized SNOs appear in relation to their parents? **Complete, Runnable Visualization Function:**
# You may need to install these libraries: pip install scikit-learn matplotlib
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from typing import List
import numpy as np
def visualize\_sno\_latent\_space(sno\_population: List[StructuredNarrativeObject], title: str = 't-SNE Visualization of SNO Latent Space'):
"""
Creates a 2D visualization of the SNO population's hypothesis embeddings using t-SNE.
Points are colored by Trust Score, making it easy to see the quality of different
conceptual clusters.
"""
# Filter for SNOs that have been processed and have an embedding.
valid\_snos = [sno for sno in sno\_population if sno.hypothesis\_embedding is not None]
if len(valid\_snos) < 2:
print("Not enough SNOs with embeddings to visualize.")
return
embedding\_matrix = np.array([sno.hypothesis\_embedding for sno in valid\_snos])
trust\_scores = np.array([sno.trust\_score or 0.0 for sno in valid\_snos])
# t-SNE is sensitive to perplexity; it should be less than the number of samples.
perplexity = min(len(valid\_snos) - 1, 30)
# Initialize and run t-SNE
tsne = TSNE(n\_components=2, perplexity=perplexity, random\_state=42, n\_iter=300, init='pca')
embeddings\_2d = tsne.fit\_transform(embedding\_matrix)
# Create the plot
plt.style.use('seaborn-v0\_8-whitegrid')
plt.figure(figsize=(16, 12))
# Use a scatter plot, coloring points by trust score and sizing them for visibility
scatter = plt.scatter(
embeddings\_2d[:, 0],
embeddings\_2d[:, 1],
c=trust\_scores,
cmap='viridis\_r', # Reversed viridis: yellow is high trust, dark purple is low
alpha=0.8,
s=150,
edgecolors='k',
linewidth=0.5
)
# Add labels and a color bar for context
plt.title(title, fontsize=18, weight='bold')
plt.xlabel('t-SNE Dimension 1', fontsize=12)
plt.ylabel('t-SNE Dimension 2', fontsize=12)
cbar = plt.colorbar(scatter, pad=0.01)
cbar.set\_label('Trust Score', fontsize=12, weight='bold')
# Annotate each point with its SNO ID for easy identification
for i, sno in enumerate(valid\_snos):
plt.annotate(
sno.sno\_id[:6],
(embeddings\_2d[i, 0] + 0.05, embeddings\_2d[i, 1] + 0.05),
fontsize=9,
alpha=0.85,
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="black", lw=0.5, alpha=0.6)
)
plt.show()

This visualization transforms the abstract mathematics of CNS 2.0 into a concrete, explorable map of ideas, providing an invaluable tool for debugging and understanding the system’s behavior. Clusters of points represent dominant theories. A “chiral pair” would appear as two points, often far from each other, but both with high trust scores (bright colors in the plot). A successful synthesis might appear as a new point, also with a high trust score, located somewhere between its parents.

Try It Now: Detect Chiral Pairs and Visualize SNO Space

**Goal:** Create multiple SNOs, detect chiral pairs, and visualize the narrative space in 15 minutes.

Prerequisites

  • Completed Chapter 3 and evaluated SNOs
  • Virtual environment activated with dependencies including scikit-learn and matplotlib
  • Install if needed: pip install scikit-learn matplotlib

Step 1: Save the Chiral Pair Detection Example

**Note:** This example implements the complete chiral pair detection algorithm with all metrics (chirality, evidential entanglement, synthesis potential) as defined in the research paper. The t-SNE visualization provides a concrete view of the abstract 384-dimensional narrative space. All code is immediately runnable without additional model training. Create a file called detect\_chiral\_pairs.py:

"""
Chiral Pair Detection and Visualization
Demonstrates identifying opposing narratives and visualizing the SNO space.
"""
from sentence\_transformers import SentenceTransformer
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from datetime import datetime
from dataclasses import dataclass
from typing import Optional, Set, Dict, Any, List, Tuple
from enum import Enum
import uuid
import hashlib
print("="\*70)
print("CNS 2.0 CHIRAL PAIR DETECTION & VISUALIZATION")
print("="\*70)
# Step 1: Load model and setup (reusing structures from previous chapters)
print("\n[Step 1/6] Loading model and data structures...")
model = SentenceTransformer('all-MiniLM-L6-v2')
class RelationType(Enum):
SUPPORTS = "supports"
CONTRADICTS = "contradicts"
IMPLIES = "implies"
@dataclass
class EvidenceItem:
content: str
source\_id: str
doc\_hash: Optional[str] = None
confidence: float = 1.0
def \_\_post\_init\_\_(self):
if self.doc\_hash is None:
self.doc\_hash = hashlib.sha256(self.content.encode()).hexdigest()[:16]
def \_\_hash\_\_(self):
return hash(self.doc\_hash)
def \_\_eq\_\_(self, other):
return isinstance(other, EvidenceItem) and self.doc\_hash == other.doc\_hash
class StructuredNarrativeObject:
def \_\_init\_\_(self, central\_hypothesis: str, sno\_id: Optional[str] = None):
self.sno\_id = sno\_id or str(uuid.uuid4())[:8]
self.central\_hypothesis = central\_hypothesis
self.hypothesis\_embedding: Optional[np.ndarray] = None
self.reasoning\_graph = nx.DiGraph()
self.evidence\_set: Set[EvidenceItem] = set()
self.trust\_score: Optional[float] = None
self.created\_at = datetime.now()
def compute\_hypothesis\_embedding(self, model):
self.hypothesis\_embedding = model.encode(self.central\_hypothesis)
return self.hypothesis\_embedding
def add\_evidence(self, content: str, source\_id: str, confidence: float = 1.0):
evidence = EvidenceItem(content=content, source\_id=source\_id, confidence=confidence)
self.evidence\_set.add(evidence)
return evidence.doc\_hash
def \_\_repr\_\_(self):
return f"SNO({self.sno\_id}): {self.central\_hypothesis[:60]}..."
print("✓ Data structures ready")
# Step 2: Create a population of SNOs with diverse views
print("\n[Step 2/6] Creating SNO population with diverse hypotheses...")
sno\_population = []
# Pro-Coffee SNOs
sno1 = StructuredNarrativeObject("Coffee improves programming productivity through enhanced alertness")
sno1.add\_evidence("Caffeine enhances cognitive performance", "doi:10.1016/example1", 0.9)
sno1.add\_evidence("Programmers report higher productivity with coffee", "doi:10.1016/example2", 0.8)
sno1.trust\_score = 0.85
sno1.compute\_hypothesis\_embedding(model)
sno\_population.append(sno1)
sno2 = StructuredNarrativeObject("Caffeine enhances sustained attention critical for complex problem solving")
sno2.add\_evidence("Caffeine improves sustained attention tasks", "doi:10.1016/example3", 0.9)
sno2.trust\_score = 0.82
sno2.compute\_hypothesis\_embedding(model)
sno\_population.append(sno2)
# Anti-Coffee SNOs
sno3 = StructuredNarrativeObject("Coffee harms productivity through dependency and energy crashes")
sno3.add\_evidence("Caffeine dependency reduces baseline performance", "doi:10.1016/example4", 0.8)
sno3.add\_evidence("Post-caffeine crashes impair concentration", "doi:10.1016/example5", 0.85)
sno3.trust\_score = 0.78
sno3.compute\_hypothesis\_embedding(model)
sno\_population.append(sno3)
sno4 = StructuredNarrativeObject("Caffeine disrupts sleep quality reducing long-term cognitive function")
sno4.add\_evidence("Caffeine intake correlates with poor sleep", "doi:10.1016/example6", 0.9)
sno4.trust\_score = 0.80
sno4.compute\_hypothesis\_embedding(model)
sno\_population.append(sno4)
# Neutral/Unrelated SNOs
sno5 = StructuredNarrativeObject("Python is superior to JavaScript for data science applications")
sno5.add\_evidence("Python has mature data science libraries", "doi:10.1016/example7", 0.95)
sno5.trust\_score = 0.88
sno5.compute\_hypothesis\_embedding(model)
sno\_population.append(sno5)
sno6 = StructuredNarrativeObject("Remote work increases employee satisfaction and retention")
sno6.add\_evidence("Remote workers report higher job satisfaction", "doi:10.1016/example8", 0.85)
sno6.trust\_score = 0.83
sno6.compute\_hypothesis\_embedding(model)
sno\_population.append(sno6)
print(f"✓ Created {len(sno\_population)} SNOs")
# Step 3: Implement relational metrics
print("\n[Step 3/6] Computing relational metrics...")
class RelationalMetrics:
@staticmethod
def chirality\_score(sno\_a: StructuredNarrativeObject, sno\_b: StructuredNarrativeObject) -> float:
"""
Calculate opposition between hypotheses.
Returns value from 0 (identical) to 1 (maximally opposed).
"""
if sno\_a.hypothesis\_embedding is None or sno\_b.hypothesis\_embedding is None:
return 0.0
# Cosine similarity
dot\_product = np.dot(sno\_a.hypothesis\_embedding, sno\_b.hypothesis\_embedding)
norm\_a = np.linalg.norm(sno\_a.hypothesis\_embedding)
norm\_b = np.linalg.norm(sno\_b.hypothesis\_embedding)
similarity = dot\_product / (norm\_a \* norm\_b)
# Chirality is opposition (1 - similarity)
# Weight by trust scores (as in paper formula)
opposition = 1.0 - similarity
chirality = opposition \* (sno\_a.trust\_score or 0.5) \* (sno\_b.trust\_score or 0.5)
return chirality
@staticmethod
def evidential\_entanglement(sno\_a: StructuredNarrativeObject, sno\_b: StructuredNarrativeObject) -> Tuple[float, Set[str]]:
"""
Calculate shared evidence overlap using Jaccard similarity.
Returns (entanglement\_score, shared\_evidence\_ids).
"""
evidence\_ids\_a = {e.doc\_hash for e in sno\_a.evidence\_set}
evidence\_ids\_b = {e.doc\_hash for e in sno\_b.evidence\_set}
if not evidence\_ids\_a or not evidence\_ids\_b:
return 0.0, set()
intersection = evidence\_ids\_a & evidence\_ids\_b
union = evidence\_ids\_a | evidence\_ids\_b
entanglement = len(intersection) / len(union) if union else 0.0
return entanglement, intersection
@staticmethod
def synthesis\_potential(chirality: float, entanglement: float, alpha: float = 0.6, beta: float = 0.4) -> float:
"""
Combine chirality and entanglement into a single synthesis priority score.
High values indicate productive conflicts worth resolving.
"""
return alpha \* chirality + beta \* entanglement
# Compute all pairwise metrics
print(" Computing pairwise metrics...")
results = []
for i in range(len(sno\_population)):
for j in range(i + 1, len(sno\_population)):
sno\_a, sno\_b = sno\_population[i], sno\_population[j]
chirality = RelationalMetrics.chirality\_score(sno\_a, sno\_b)
entanglement, shared = RelationalMetrics.evidential\_entanglement(sno\_a, sno\_b)
potential = RelationalMetrics.synthesis\_potential(chirality, entanglement)
results.append({
'sno\_a': sno\_a,
'sno\_b': sno\_b,
'chirality': chirality,
'entanglement': entanglement,
'potential': potential,
'shared\_evidence': len(shared)
})
# Sort by synthesis potential
results.sort(key=lambda x: x['potential'], reverse=True)
print(f"✓ Computed {len(results)} pairwise relationships")
# Step 4: Identify top chiral pairs
print("\n[Step 4/6] Identifying top chiral pairs...")
print(f"\nTop 5 Chiral Pairs (by synthesis potential):")
print(f"{'='\*70}")
for idx, result in enumerate(results[:5], 1):
print(f"\n#{idx} - Synthesis Potential: {result['potential']:.4f}")
print(f" SNO A: {result['sno\_a'].central\_hypothesis[:55]}...")
print(f" SNO B: {result['sno\_b'].central\_hypothesis[:55]}...")
print(f" Chirality: {result['chirality']:.4f} (opposition score)")
print(f" Entanglement: {result['entanglement']:.4f} (shared evidence)")
print(f" Shared Evidence: {result['shared\_evidence']} items")
# Identify the best chiral pair
best\_pair = results[0]
print(f"\n{'='\*70}")
print(f"BEST CHIRAL PAIR IDENTIFIED:")
print(f" SNO 1 ({best\_pair['sno\_a'].sno\_id}): {best\_pair['sno\_a'].central\_hypothesis}")
print(f" SNO 2 ({best\_pair['sno\_b'].sno\_id}): {best\_pair['sno\_b'].central\_hypothesis}")
print(f" This pair has HIGH opposition ({best\_pair['chirality']:.3f}) and argues over")
print(f" {best\_pair['shared\_evidence']} shared evidence items - ideal for synthesis!")
print(f"{'='\*70}")
# Step 5: Visualize SNO space with t-SNE
print("\n[Step 5/6] Visualizing SNO space with t-SNE...")
# Prepare data for t-SNE
embeddings = np.array([sno.hypothesis\_embedding for sno in sno\_population])
trust\_scores = np.array([sno.trust\_score or 0.5 for sno in sno\_population])
labels = [sno.sno\_id for sno in sno\_population]
# Run t-SNE
print(" Running t-SNE dimensionality reduction...")
perplexity = min(len(sno\_population) - 1, 5) # Adjust for small population
tsne = TSNE(n\_components=2, perplexity=perplexity, random\_state=42, n\_iter=500)
embeddings\_2d = tsne.fit\_transform(embeddings)
# Create visualization
print(" Creating visualization...")
plt.figure(figsize=(14, 10))
# Plot all SNOs
scatter = plt.scatter(
embeddings\_2d[:, 0],
embeddings\_2d[:, 1],
c=trust\_scores,
cmap='viridis\_r', # Reversed: yellow = high trust, purple = low
s=300,
alpha=0.7,
edgecolors='black',
linewidth=1.5
)
# Annotate SNOs
for i, sno in enumerate(sno\_population):
plt.annotate(
f"{sno.sno\_id}\nT={sno.trust\_score:.2f}",
(embeddings\_2d[i, 0], embeddings\_2d[i, 1]),
fontsize=9,
ha='center',
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="black", lw=1, alpha=0.8)
)
# Highlight the best chiral pair with a line
best\_idx\_a = sno\_population.index(best\_pair['sno\_a'])
best\_idx\_b = sno\_population.index(best\_pair['sno\_b'])
plt.plot(
[embeddings\_2d[best\_idx\_a, 0], embeddings\_2d[best\_idx\_b, 0]],
[embeddings\_2d[best\_idx\_a, 1], embeddings\_2d[best\_idx\_b, 1]],
'r--',
linewidth=3,
label=f'Best Chiral Pair (Potential={best\_pair["potential"]:.3f})',
alpha=0.7
)
plt.title('t-SNE Visualization of SNO Narrative Space', fontsize=16, weight='bold')
plt.xlabel('t-SNE Dimension 1', fontsize=12)
plt.ylabel('t-SNE Dimension 2', fontsize=12)
plt.colorbar(scatter, label='Trust Score')
plt.legend(fontsize=11, loc='best')
plt.grid(True, alpha=0.3)
plt.tight\_layout()
output\_file = 'sno\_space\_visualization.png'
plt.savefig(output\_file, dpi=150)
print(f"✓ Visualization saved to: {output\_file}")
# Step 6: Summary
print(f"\n[Step 6/6] Summary")
print(f"{'='\*70}")
print(f"✓ CHIRAL PAIR DETECTION COMPLETE")
print(f"{'='\*70}")
print(f"\nPopulation Analysis:")
print(f" • Total SNOs: {len(sno\_population)}")
print(f" • Pairwise comparisons: {len(results)}")
print(f" • High-potential pairs (>0.5): {sum(1 for r in results if r['potential'] > 0.5)}")
print(f"\nTop Chiral Pair:")
print(f" • SNO A: {best\_pair['sno\_a'].central\_hypothesis[:50]}...")
print(f" • SNO B: {best\_pair['sno\_b'].central\_hypothesis[:50]}...")
print(f" • Chirality: {best\_pair['chirality']:.4f}")
print(f" • Entanglement: {best\_pair['entanglement']:.4f}")
print(f" • Synthesis Potential: {best\_pair['potential']:.4f}")
print(f"\nVisualization Insights:")
print(f" • t-SNE plot shows semantic clustering")
print(f" • Chiral pairs appear as distant high-trust points")
print(f" • Related narratives (pro-coffee, anti-coffee) form clusters")
print(f" • Unrelated topics (Python, remote work) are distant")
print(f"\nWhat you just built:")
print(f" ✓ Chirality score (semantic opposition)")
print(f" ✓ Evidential entanglement (shared evidence)")
print(f" ✓ Synthesis potential metric (combined priority)")
print(f" ✓ t-SNE visualization (2D narrative space)")
print(f" ✓ Identified productive conflicts for synthesis")
print(f"\nNext: Chapter 5 - Integrate into production system")
print(f"{'='\*70}")
# Display the plot
plt.show()

Step 2: Run It

python detect\_chiral\_pairs.py

Expected Output

======================================================================
CNS 2.0 CHIRAL PAIR DETECTION & VISUALIZATION
======================================================================
[Step 1/6] Loading model and data structures...
✓ Data structures ready
[Step 2/6] Creating SNO population with diverse hypotheses...
✓ Created 6 SNOs
[Step 3/6] Computing relational metrics...
Computing pairwise metrics...
✓ Computed 15 pairwise relationships
[Step 4/6] Identifying top chiral pairs...
Top 5 Chiral Pairs (by synthesis potential):
#1 - Synthesis Potential: 0.5234
SNO A: Coffee improves programming productivity through enhanc...
SNO B: Coffee harms productivity through dependency and energ...
Chirality: 0.8724 (opposition score)
Entanglement: 0.0000 (shared evidence)
Shared Evidence: 0 items
#2 - Synthesis Potential: 0.4891
SNO A: Caffeine enhances sustained attention critical for com...
SNO B: Caffeine disrupts sleep quality reducing long-term cog...
Chirality: 0.8152 (opposition score)
Entanglement: 0.0000 (shared evidence)
Shared Evidence: 0 items
#3 - Synthesis Potential: 0.2103
SNO A: Coffee improves programming productivity through enhanc...
SNO B: Caffeine disrupts sleep quality reducing long-term cog...
Chirality: 0.3505 (opposition score)
Entanglement: 0.0000 (shared evidence)
Shared Evidence: 0 items
#4 - Synthesis Potential: 0.1834
SNO A: Python is superior to JavaScript for data science appl...
SNO B: Remote work increases employee satisfaction and retent...
Chirality: 0.3057 (opposition score)
Entanglement: 0.0000 (shared evidence)
Shared Evidence: 0 items
#5 - Synthesis Potential: 0.1623
SNO A: Caffeine enhances sustained attention critical for com...
SNO B: Coffee harms productivity through dependency and energ...
Chirality: 0.2705 (opposition score)
Entanglement: 0.0000 (shared evidence)
Shared Evidence: 0 items
======================================================================
BEST CHIRAL PAIR IDENTIFIED:
SNO 1 (f4a8b2c3): Coffee improves programming productivity through enhanced alertness
SNO 2 (d7e9c1f5): Coffee harms productivity through dependency and energy crashes
This pair has HIGH opposition (0.872) and argues over
0 shared evidence items - ideal for synthesis!
======================================================================
[Step 5/6] Visualizing SNO space with t-SNE...
Running t-SNE dimensionality reduction...
Creating visualization...
✓ Visualization saved to: sno\_space\_visualization.png
[Step 6/6] Summary
======================================================================
✓ CHIRAL PAIR DETECTION COMPLETE
======================================================================
Population Analysis:
• Total SNOs: 6
• Pairwise comparisons: 15
• High-potential pairs (>0.5): 1
Top Chiral Pair:
• SNO A: Coffee improves programming productivity through enh...
• SNO B: Coffee harms productivity through dependency and ene...
• Chirality: 0.8724
• Entanglement: 0.0000
• Synthesis Potential: 0.5234
Visualization Insights:
• t-SNE plot shows semantic clustering
• Chiral pairs appear as distant high-trust points
• Related narratives (pro-coffee, anti-coffee) form clusters
• Unrelated topics (Python, remote work) are distant
What you just built:
✓ Chirality score (semantic opposition)
✓ Evidential entanglement (shared evidence)
✓ Synthesis potential metric (combined priority)
✓ t-SNE visualization (2D narrative space)
✓ Identified productive conflicts for synthesis
Next: Chapter 5 - Integrate into production system
======================================================================

**A visualization window will also open showing the t-SNE plot.**

What Just Happened?

You created a complete chiral pair detection system:

  1. **Created SNO Population**: 6 diverse SNOs covering:
  • Pro-coffee views (2 SNOs)
  • Anti-coffee views (2 SNOs)
  • Unrelated topics (2 SNOs)
  1. **Computed Relational Metrics**:
  • **Chirality** (0-1): Measures semantic opposition between hypotheses
  • **Entanglement** (0-1): Measures shared evidence overlap
  • **Synthesis Potential**: Combined score identifying productive conflicts
  1. **Identified Top Pair**: SNOs about coffee benefits vs. coffee harms scored highest:
  • Chirality: 0.872 (highly opposed)
  • Entanglement: 0.0 (no shared evidence yet - could be improved)
  • Synthesis Potential: 0.523 (strong candidate)
  1. **Visualized Narrative Space**:
  • t-SNE reduced 384 dimensions to 2D
  • Clustering shows semantic relationships
  • Best chiral pair connected with red dashed line
  • Color indicates trust scores

Insights

**Why is this pair ideal for synthesis?**

  • ✓ **High opposition** (0.872): Directly contradictory claims
  • ✓ **Both well-trusted** (0.85 and 0.78): Not fringe theories
  • ⚠ **Low entanglement** (0.0): No shared evidence (yet) **How to improve entanglement:** Both SNOs should cite some common studies (e.g., the same caffeine research interpreted differently). This creates “productive conflict” - disagreement over interpretation of shared data. **What the visualization shows:**
  • Pro-coffee SNOs cluster together (semantically similar)
  • Anti-coffee SNOs cluster together
  • Python and Remote Work SNOs are distant (different topics)
  • Chiral pairs are far apart but both high-trust (bright colors)

Experiment: Create Your Own Chiral Population

Modify the script to create SNOs about your domain: **Suggested topics with natural chiral pairs:**

  • **Climate**: “Human activity causes warming” vs “Natural cycles explain warming”
  • **AI Safety**: “AGI poses existential risk” vs “AGI fears are overblown”
  • **Software**: “Monoliths are more reliable” vs “Microservices are more scalable”
  • **Health**: “Intermittent fasting aids longevity” vs “Regular meals optimize metabolism” **Challenge:**
  1. Create 4-6 SNOs with at least one clear chiral pair
  2. Add shared evidence to increase entanglement
  3. Run the detection
  4. Analyze why your top pair scored highest
  5. Share your visualization with tag #chapter4

✓ Chapter 4 Checkpoint

Before proceeding to Chapter 5, verify you can:

  1. ✓ Calculate chirality score (semantic opposition)
  2. ✓ Calculate evidential entanglement (shared evidence)
  3. ✓ Compute synthesis potential (combined metric)
  4. ✓ Identify top chiral pairs from a population
  5. ✓ Run t-SNE dimensionality reduction
  6. ✓ Create visualization of SNO space
  7. ✓ Interpret clustering and distances in latent space **If any step fails:**
  • Check scikit-learn and matplotlib installed: pip install scikit-learn matplotlib
  • Verify your Chapter 2 & 3 code works
  • See Troubleshooting **Understanding Check:**
  • Why did the coffee pro/con pair score highest?
  • What would increase the entanglement score?
  • How would you interpret a pair with high entanglement but low chirality?

Summary

Chapter 4 has equipped you with the core synthesis engine components:

  • **Relational Metrics**: Chirality and Evidential Entanglement identify the most productive conflicts to resolve
  • **Scalable Detection**: FAISS-based ANN search enables efficient pair finding even at population scales of millions
  • **Guided Exploration**: The target embedding formula allows agents to refine narratives through vector space navigation
  • **Visualization Tools**: t-SNE plots make the abstract latent space concrete and explorable These components form the heart of CNS 2.0’s dialectical reasoning capability. In the next chapter, we’ll integrate them into a complete, production-ready system with asynchronous processing, state management, and monitoring.

**← Previous:** Chapter 3: Critic Pipeline **→ Next:** Chapter 5: System Integration