Codette-Demo / reasoning_forge /synthesis_engine.py
Claude
Initial Codette cognitive architecture demo Space
7c3f0ce
"""
Synthesis Engine - Combines all agent perspectives into a unified multi-perspective response.
Takes the concept, all agent analyses, and critic feedback, then produces
a synthesized explanation that highlights how different perspectives complement
each other. Includes a Final Integrated Understanding section.
"""
import random
import re
class SynthesisEngine:
"""Combines multi-agent analyses into coherent synthesized responses."""
# Opening templates that set up the multi-perspective frame
_opening_templates = [
(
"To understand '{concept}' with genuine depth, we must examine it through "
"multiple lenses, each revealing structure that the others miss."
),
(
"'{concept}' resists single-framework analysis. Its full meaning emerges "
"only at the intersection of several distinct modes of reasoning."
),
(
"A comprehensive understanding of '{concept}' requires weaving together "
"insights from fundamentally different ways of thinking."
),
(
"No single perspective captures '{concept}' adequately. What follows is "
"an integrated analysis drawing on physics, philosophy, ethics, creativity, "
"and human experience."
),
(
"The richness of '{concept}' becomes apparent only when we hold multiple "
"analytical frameworks simultaneously and let them inform each other."
),
]
# Bridge templates connecting one perspective to another
_bridge_templates = [
"Where {agent_a} reveals {insight_a}, {agent_b} adds the crucial dimension of {insight_b}.",
"The {agent_a} analysis and the {agent_b} analysis converge on a shared insight: {shared}.",
"What appears as {aspect_a} from the {agent_a} perspective is revealed as {aspect_b} when viewed through {agent_b}.",
"The tension between {agent_a}'s emphasis on {focus_a} and {agent_b}'s emphasis on {focus_b} is productive, not contradictory.",
"{agent_a} identifies the mechanism; {agent_b} identifies the meaning.",
"Combining {agent_a}'s structural analysis with {agent_b}'s human-centered analysis yields a fuller picture.",
]
# Closing templates for the Final Integrated Understanding
_closing_templates = [
(
"**Final Integrated Understanding:** {concept} is simultaneously a "
"{physical_desc}, a {philosophical_desc}, a {ethical_desc}, a "
"{creative_desc}, and a {human_desc}. These are not competing descriptions "
"but complementary facets of a single complex reality. The most robust "
"understanding holds all five in view, using each to compensate for the "
"blind spots of the others."
),
(
"**Final Integrated Understanding:** The multi-perspective analysis reveals "
"that {concept} cannot be reduced to any single framework without distortion. "
"The physical analysis provides causal grounding, the philosophical analysis "
"excavates hidden assumptions, the ethical analysis maps the stakes, the "
"creative analysis opens new solution spaces, and the empathic analysis "
"anchors everything in lived human experience. Together they constitute "
"not a list of separate views but an integrated understanding richer than "
"any view alone."
),
(
"**Final Integrated Understanding:** What emerges from this multi-lens "
"examination of {concept} is not a single 'correct' interpretation but a "
"structured understanding of how different valid interpretations relate to "
"each other. The causal structure identified by physics, the meaning "
"structure identified by philosophy, the value structure identified by "
"ethics, the possibility structure identified by creative reasoning, and "
"the experience structure identified by empathy are all real and all "
"essential. Wisdom lies in knowing which lens to apply in which context "
"and how to translate insights between them."
),
]
def synthesize(
self,
concept: str,
analyses: dict[str, str],
critique: dict,
) -> str:
"""Produce a synthesized multi-perspective response.
Args:
concept: The original concept.
analyses: Dict mapping agent_name -> analysis_text.
critique: Output from CriticAgent.evaluate_ensemble().
Returns:
A synthesized text of 200-400 words.
"""
sections = []
# 1. Opening
opening = random.choice(self._opening_templates).replace("{concept}", concept)
sections.append(opening)
# 2. Per-perspective summaries (compressed)
perspective_summaries = self._extract_perspective_summaries(analyses)
for agent_name, summary in perspective_summaries.items():
sections.append(f"**{agent_name} perspective:** {summary}")
# 3. Cross-perspective bridges (pick 2-3)
bridges = self._generate_bridges(analyses, perspective_summaries)
if bridges:
sections.append("") # blank line for readability
for bridge in bridges[:2]:
sections.append(bridge)
# 4. Incorporate critic insights
critic_section = self._incorporate_critique(critique)
if critic_section:
sections.append("")
sections.append(critic_section)
# 5. Final Integrated Understanding
closing = self._generate_closing(concept, perspective_summaries)
sections.append("")
sections.append(closing)
raw_synthesis = "\n\n".join(sections)
# Trim to 200-400 words if needed
return self._trim_to_target(raw_synthesis, min_words=200, max_words=400)
def _extract_perspective_summaries(
self, analyses: dict[str, str]
) -> dict[str, str]:
"""Extract a 1-2 sentence summary from each agent's analysis."""
summaries = {}
for agent_name, text in analyses.items():
sentences = [s.strip() for s in re.split(r'(?<=[.!?])\s+', text) if s.strip()]
if len(sentences) >= 3:
# Take the 2nd and 3rd sentences (skip the opening framing)
summary = " ".join(sentences[1:3])
elif len(sentences) >= 1:
summary = sentences[0]
else:
summary = text[:200]
# Trim to ~40 words
words = summary.split()
if len(words) > 45:
summary = " ".join(words[:40]) + "..."
summaries[agent_name] = summary
return summaries
def _generate_bridges(
self,
analyses: dict[str, str],
summaries: dict[str, str],
) -> list[str]:
"""Generate cross-perspective bridge statements."""
bridges = []
agent_names = list(analyses.keys())
# Define perspective focus areas for bridge generation
focus_map = {
"Newton": "causal mechanisms and measurable dynamics",
"Quantum": "uncertainty, probability, and the limits of definite knowledge",
"Ethics": "moral stakes, fairness, and human impact",
"Philosophy": "foundational assumptions and the structure of meaning",
"DaVinci": "creative possibilities and cross-domain innovation",
"Empathy": "emotional reality and lived human experience",
}
# Generate a few meaningful bridges
if len(agent_names) >= 2:
pairs = []
for i in range(len(agent_names)):
for j in range(i + 1, len(agent_names)):
pairs.append((agent_names[i], agent_names[j]))
random.shuffle(pairs)
for name_a, name_b in pairs[:3]:
focus_a = focus_map.get(name_a, "its analytical focus")
focus_b = focus_map.get(name_b, "its analytical focus")
template = random.choice(self._bridge_templates)
bridge = template.format(
agent_a=name_a,
agent_b=name_b,
insight_a=focus_a,
insight_b=focus_b,
shared="the importance of understanding the full system rather than isolated parts",
aspect_a="a structural feature",
aspect_b="a deeply human concern",
focus_a=focus_a,
focus_b=focus_b,
)
bridges.append(bridge)
return bridges
def _incorporate_critique(self, critique: dict) -> str:
"""Turn critic feedback into a synthesis-relevant observation."""
parts = []
if critique.get("missing_perspectives"):
gap = critique["missing_perspectives"][0]
# Extract just the perspective name
parts.append(
f"A notable gap in the analysis is the limited attention to "
f"{gap.split('lacks a ')[1].split(' perspective')[0] if 'lacks a ' in gap else 'additional'} "
f"dimensions, which future analysis should address."
)
if critique.get("improvement_suggestions"):
suggestion = critique["improvement_suggestions"][0]
# Compress the suggestion
words = suggestion.split()
if len(words) > 25:
suggestion = " ".join(words[:25]) + "..."
parts.append(f"The critic notes: {suggestion}")
overall = critique.get("overall_quality", 0)
if overall >= 0.75:
parts.append(
"Overall, the multi-perspective ensemble achieves strong analytical "
"coverage with good complementarity between viewpoints."
)
elif overall >= 0.5:
parts.append(
"The ensemble provides reasonable coverage but would benefit from "
"deeper engagement between perspectives."
)
return " ".join(parts) if parts else ""
def _generate_closing(
self, concept: str, summaries: dict[str, str]
) -> str:
"""Generate the Final Integrated Understanding section."""
template = random.choice(self._closing_templates)
# Build descriptors from available perspectives
descriptors = {
"physical_desc": "system governed by causal dynamics and conservation principles",
"philosophical_desc": "concept whose meaning depends on the framework from which it is examined",
"ethical_desc": "domain of genuine moral stakes affecting real people",
"creative_desc": "space of untapped possibilities waiting for cross-domain insight",
"human_desc": "lived experience with emotional texture that abstract analysis alone cannot capture",
}
result = template
result = result.replace("{concept}", concept)
for key, value in descriptors.items():
result = result.replace("{" + key + "}", value)
return result
def _trim_to_target(
self, text: str, min_words: int = 200, max_words: int = 400
) -> str:
"""Trim or pad text to fall within the target word range."""
words = text.split()
if len(words) > max_words:
# Trim from the middle sections, preserving opening and closing
lines = text.split("\n\n")
while len(" ".join(lines).split()) > max_words and len(lines) > 3:
# Remove the longest middle section
middle_indices = list(range(1, len(lines) - 1))
if not middle_indices:
break
longest_idx = max(middle_indices, key=lambda i: len(lines[i].split()))
lines.pop(longest_idx)
return "\n\n".join(lines)
return text