| def generate_flow_html(active_phase="idle"): |
| """ |
| Generates animated SVG for the MVM² Architecture Flow. |
| Phases: 'idle', 'enhance', 'ocr', 'reasoning', 'heuristics', 'verification', 'consensus', 'success' |
| """ |
| |
| |
| bg_color = "#1e293b" |
| accent = "#e63946" |
| success = "#16a34a" |
| text = "#94a3b8" |
| |
| |
| def get_pulse(phase): |
| return 'active-pulse' if active_phase == phase else '' |
|
|
| def get_node_style(phase): |
| if active_phase == 'success': return f'stroke: {success}; filter: drop-shadow(0 0 8px {success});' |
| if active_phase == phase: return f'stroke: {accent}; filter: drop-shadow(0 0 8px {accent});' |
| return 'stroke: rgba(255,255,255,0.1);' |
|
|
| html = f""" |
| <div style="width: 100%; height: 400px; display: flex; justify-content: center; align-items: center; overflow: hidden; position: relative; background: rgba(30, 30, 30, 0.6); border-radius: 12px; border: 1px solid rgba(255,255,255,0.05);"> |
| <svg width="800" height="350" viewBox="0 0 800 350" preserveAspectRatio="xMidYMid meet"> |
| <!-- Definitions for markers and gradients --> |
| <defs> |
| <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto"> |
| <polygon points="0 0, 10 3.5, 0 7" fill="{text}" /> |
| </marker> |
| <style> |
| .flow-line {{ stroke-dasharray: 1000; stroke-dashoffset: 1000; }} |
| .active-pulse {{ stroke-dashoffset: 0; animation: pulse-flow 2s infinite linear; stroke: {accent} !important; opacity: 1; }} |
| @keyframes pulse-flow {{ 0% {{ stroke-dashoffset: 1000; opacity: 0.3; }} 50% {{ opacity: 1; }} 100% {{ stroke-dashoffset: 0; opacity: 0.3; }} }} |
| .thinking circle {{ animation: thinking-pulse 1.5s infinite ease-in-out; }} |
| @keyframes thinking-pulse {{ 0%, 100% {{ transform: scale(1); opacity: 0.8; }} 50% {{ transform: scale(1.1); opacity: 1; filter: brightness(1.2); }} }} |
| .thinking {{ transform-origin: 450px 175px; }} |
| </style> |
| </defs> |
| |
| <!-- CONNECTIONS --> |
| <!-- Enhance to OCR --> |
| <path d="M100 175 H200" class="flow-line {get_pulse('enhance')}" stroke="{text}" stroke-width="2" marker-end="url(#arrowhead)" /> |
| |
| <!-- OCR to Reasoning --> |
| <path d="M300 175 H400" class="flow-line {get_pulse('ocr')}" stroke="{text}" stroke-width="2" marker-end="url(#arrowhead)" /> |
| |
| <!-- Reasoning to Consensus (4 Parallel) --> |
| <path d="M500 100 Q 525 100 550 175" class="flow-line {get_pulse('reasoning')}" stroke="{text}" stroke-width="1.5" /> |
| <path d="M500 150 Q 525 150 550 175" class="flow-line {get_pulse('reasoning')}" stroke="{text}" stroke-width="1.5" /> |
| <path d="M500 200 Q 525 200 550 175" class="flow-line {get_pulse('reasoning')}" stroke="{text}" stroke-width="1.5" /> |
| <path d="M500 250 Q 525 250 550 175" class="flow-line {get_pulse('reasoning')}" stroke="{text}" stroke-width="1.5" /> |
| |
| <!-- Heuristics to Consensus --> |
| <path d="M600 175 H640" class="flow-line {get_pulse('heuristics')}" stroke="{accent}" stroke-width="2" marker-end="url(#arrowhead)" /> |
| |
| <!-- Symbolic Bridge --> |
| <path d="M450 300 Q 450 250 450 250" class="flow-line {get_pulse('verification')}" stroke="{success}" stroke-width="3" stroke-dasharray="5,5" /> |
| |
| <!-- NODES --> |
| <!-- 1. Input/Enhance --> |
| <rect x="20" y="140" width="80" height="70" rx="10" fill="{bg_color}" style="{get_node_style('enhance')}" /> |
| <text x="60" y="180" text-anchor="middle" fill="white" font-size="10" font-weight="600">ENHANCE</text> |
| |
| <!-- 2. OCR Module --> |
| <circle cx="250" cy="175" r="45" fill="{bg_color}" style="{get_node_style('ocr')}" /> |
| <text x="250" y="180" text-anchor="middle" fill="white" font-size="10" font-weight="600">OCR</text> |
| |
| <!-- 3. Reasoning Agents (Parallel) --> |
| <g class="{'thinking' if active_phase == 'reasoning' else ''}"> |
| <circle cx="450" cy="80" r="25" fill="{bg_color}" style="{get_node_style('reasoning')}" /> |
| <circle cx="450" cy="140" r="25" fill="{bg_color}" style="{get_node_style('reasoning')}" /> |
| <circle cx="450" cy="200" r="25" fill="{bg_color}" style="{get_node_style('reasoning')}" /> |
| <circle cx="450" cy="260" r="25" fill="{bg_color}" style="{get_node_style('reasoning')}" /> |
| <text x="450" y="45" text-anchor="middle" fill="{text}" font-size="10">REASONING</text> |
| </g> |
| |
| <!-- 4. Heuristics Module --> |
| <rect x="550" y="150" width="50" height="50" rx="5" fill="{bg_color}" style="{get_node_style('heuristics')}" /> |
| <text x="575" y="180" text-anchor="middle" fill="white" font-size="8" font-weight="600">FILTER</text> |
| |
| <!-- 5. Verification Bridge (SymPy) --> |
| <rect x="400" y="300" width="100" height="40" rx="5" fill="{bg_color}" style="{get_node_style('verification')}" /> |
| <text x="450" y="325" text-anchor="middle" fill="{success}" font-size="10" font-weight="bold">SYMPY CORE</text> |
| |
| <!-- 6. Consensus --> |
| <polygon points="650,125 750,175 650,225" fill="{bg_color}" style="{get_node_style('consensus')}" /> |
| <text x="680" y="180" text-anchor="middle" fill="white" font-size="10" font-weight="600">CONSENSUS</text> |
| </svg> |
| |
| <div style="position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); font-size: 0.8em; color: {text};"> |
| Current Stage: <span style="color: {accent if active_phase != 'success' else success}; font-weight: bold; text-transform: uppercase;">{active_phase}</span> |
| </div> |
| </div> |
| """ |
| return html |
|
|