|
| 1 | +import matplotlib |
| 2 | +matplotlib.use('Agg') |
| 3 | +import matplotlib.pyplot as plt |
| 4 | +import matplotlib.patches as mpatches |
| 5 | +from matplotlib.patches import FancyBboxPatch, FancyArrowPatch |
| 6 | +import numpy as np |
| 7 | + |
| 8 | +OUTPUT = r"d:\WorkPlace\AI\MinerU-public-release\docs\submissions\shared\assets\system_architecture.png" |
| 9 | + |
| 10 | +plt.rcParams.update({ |
| 11 | + 'font.family': 'sans-serif', |
| 12 | + 'font.sans-serif': ['Microsoft YaHei', 'DejaVu Sans'], |
| 13 | + 'font.size': 10, |
| 14 | +}) |
| 15 | + |
| 16 | +fig, ax = plt.subplots(1, 1, figsize=(20, 14)) |
| 17 | +ax.set_xlim(0, 20) |
| 18 | +ax.set_ylim(0, 14) |
| 19 | +ax.set_aspect('equal') |
| 20 | +ax.axis('off') |
| 21 | + |
| 22 | +BG = '#0B1120' |
| 23 | +CARD_BG = '#111B2E' |
| 24 | +BORDER = '#1E3A5F' |
| 25 | +ACCENT_ORANGE = '#F59E0B' |
| 26 | +ACCENT_BLUE = '#3B82F6' |
| 27 | +ACCENT_GREEN = '#10B981' |
| 28 | +ACCENT_PURPLE = '#8B5CF6' |
| 29 | +ACCENT_RED = '#EF4444' |
| 30 | +TEXT_WHITE = '#F1F5F9' |
| 31 | +TEXT_GRAY = '#94A3B8' |
| 32 | +CHUNK_GREEN = '#059669' |
| 33 | +DOC_BLUE = '#2563EB' |
| 34 | + |
| 35 | +fig.patch.set_facecolor(BG) |
| 36 | +ax.set_facecolor(BG) |
| 37 | + |
| 38 | + |
| 39 | +def draw_card(cx, cy, w, h, color, border_color=None, radius=0.3): |
| 40 | + box = FancyBboxPatch((cx - w/2, cy - h/2), w, h, |
| 41 | + boxstyle=f"round,pad=0,rounding_size={radius}", |
| 42 | + facecolor=color, edgecolor=border_color or color, |
| 43 | + linewidth=1.5, zorder=2) |
| 44 | + ax.add_patch(box) |
| 45 | + |
| 46 | + |
| 47 | +def draw_icon(cx, cy, icon_type, size=0.35, zorder=10): |
| 48 | + if icon_type == 'github': |
| 49 | + path_data = [ |
| 50 | + (np.array([-1, -1, -0.55, -1, -1, -0.55, -0.55, 0, 0.55, 0.55, 1, 1, 0.55, 1, 1, 0.55, 0.55, 0, -0.55]), |
| 51 | + np.array([-0.5, -0.8, -0.8, -1, -0.8, -0.5, -0.2, 0, -0.2, -0.5, -0.8, -1, -1.2, -1.2, -1, -0.7, -1, -1, -1])), |
| 52 | + ] |
| 53 | + for xp, yp in path_data: |
| 54 | + ax.fill(cx + xp * size * 0.5, cy + yp * size * 0.5, color=TEXT_WHITE, zorder=zorder, alpha=0.9) |
| 55 | + elif icon_type == 'hf': |
| 56 | + ax.text(cx, cy, '\uD83E\uDD17', fontsize=size * 24, ha='center', va='center', zorder=zorder) |
| 57 | + elif icon_type == 'demo': |
| 58 | + ax.plot(cx, cy, 'o', color=ACCENT_GREEN, markersize=size * 10, zorder=zorder, alpha=0.8) |
| 59 | + ax.text(cx, cy, '\u25B6', fontsize=size * 14, ha='center', va='center', zorder=zorder+1, color='white') |
| 60 | + |
| 61 | + |
| 62 | +def draw_arrow(x1, y1, x2, y2, color=TEXT_GRAY, lw=1.5, zorder=1, style='simple'): |
| 63 | + ax.annotate('', xy=(x2, y2), xytext=(x1, y1), |
| 64 | + arrowprops=dict(arrowstyle='->', color=color, lw=lw, |
| 65 | + connectionstyle='arc3,rad=0'), zorder=zorder) |
| 66 | + |
| 67 | + |
| 68 | +fig.text(10, 13.55, 'CONTROLMIND — Cross-Track Unified Architecture', ha='center', va='center', |
| 69 | + fontsize=20, fontweight='bold', color=TEXT_WHITE, zorder=20) |
| 70 | +fig.text(10, 13.10, 'One Corpus · Three Tracks · Full Reproducibility | CC-BY-4.0', ha='center', va='center', |
| 71 | + fontsize=11, color=TEXT_GRAY, zorder=20) |
| 72 | + |
| 73 | +# ── TOP: Cross-cutting findings bar ── |
| 74 | +findings_y = 12.35 |
| 75 | +bar_w, bar_h = 18.5, 0.9 |
| 76 | +bar = FancyBboxPatch((10 - bar_w/2, findings_y - bar_h/2), bar_w, bar_h, |
| 77 | + boxstyle="round,pad=0,rounding_size=0.25", |
| 78 | + facecolor='#1A2740', edgecolor='#2D4A6F', linewidth=1.5, zorder=2) |
| 79 | +ax.add_patch(bar) |
| 80 | +ax.text(10, findings_y + 0.38, 'CROSS-CUTTING FINDINGS', ha='center', va='center', |
| 81 | + fontsize=8, color=TEXT_GRAY, fontweight='bold', zorder=3, alpha=0.7) |
| 82 | +findings = ['PPL Paradox', 'Anti-Scaling Law', 'Vision Injection', 'QLoRA Cross-Arch', 'Fleiss\' \u03BA=0.575'] |
| 83 | +for i, f in enumerate(findings): |
| 84 | + fx = 3.5 + i * 3.4 |
| 85 | + ax.text(fx, findings_y + 0.02, f, ha='center', va='center', fontsize=10, |
| 86 | + color=ACCENT_ORANGE, fontweight='bold', zorder=3) |
| 87 | + |
| 88 | +# ── TRACK CARDS ── |
| 89 | +track_y = 10.1 |
| 90 | +track_w, track_h = 5.4, 3.8 |
| 91 | +tracks = [ |
| 92 | + {'x': 3.7, 'color': '#1A2740', 'border': ACCENT_BLUE, 'title': 'TRACK 1 — Sci-Align', |
| 93 | + 'sub': '4-Dimension Benchmark', 'items': [ |
| 94 | + ('500 Questions', 'A/B/C/D balanced'), |
| 95 | + ('9-Model Leaderboard', 'MiMo-v2-flash 0.647'), |
| 96 | + ('CC-BY-4.0 \u00B7 HuggingFace', 'core.json 1.1 MB'), |
| 97 | + ('Fleiss\' \u03BA=0.575', '14-Entity Judge Matrix'), |
| 98 | + ], 'icons': ['hf']}, |
| 99 | + {'x': 10, 'color': '#1A2740', 'border': ACCENT_PURPLE, 'title': 'TRACK 2 — Data Agent', |
| 100 | + 'sub': '14-Intent Autonomous Agent', 'items': [ |
| 101 | + ('14 Intent Registry', '8-dim validation'), |
| 102 | + ('391s D-Flywheel Loop', 'arXiv \u2192 Parse \u2192 Chunk'), |
| 103 | + ('Self-Correction 50%', '\u0394 +0.352 mean score'), |
| 104 | + ('4-Path Scheduling', 'API / Ollama / vLLM / Script'), |
| 105 | + ], 'icons': ['github']}, |
| 106 | + {'x': 16.3, 'color': '#1A2740', 'border': ACCENT_GREEN, 'title': 'TRACK 3 — Medical RAG', |
| 107 | + 'sub': 'Evidence-Grounded Clinical QA', 'items': [ |
| 108 | + ('97 PMC Papers', '3,348 Medical Chunks'), |
| 109 | + ('MedBench 630 Q', 'VLM EI 4.33%'), |
| 110 | + ('Vision Injection 8/8', 'Text-only 0/8 \u2192 Full 8/8'), |
| 111 | + ('Hybrid FAISS+BM25', 'IMRAD-aware Chunking'), |
| 112 | + ], 'icons': ['demo']}, |
| 113 | +] |
| 114 | + |
| 115 | +for tk in tracks: |
| 116 | + cx, cy = tk['x'], track_y |
| 117 | + draw_card(cx, cy, track_w, track_h, tk['color'], tk['border']) |
| 118 | + ax.text(cx, cy + track_h/2 - 0.45, tk['title'], ha='center', va='center', |
| 119 | + fontsize=12, fontweight='bold', color=tk['border'], zorder=5) |
| 120 | + ax.text(cx, cy + track_h/2 - 0.9, tk['sub'], ha='center', va='center', |
| 121 | + fontsize=8, color=TEXT_GRAY, zorder=5) |
| 122 | + for j, (label, detail) in enumerate(tk['items']): |
| 123 | + iy = cy + track_h/2 - 1.4 - j * 0.65 |
| 124 | + ax.text(cx - track_w/2 + 0.5, iy, label, ha='left', va='center', |
| 125 | + fontsize=9, color=TEXT_WHITE, fontweight='bold', zorder=5) |
| 126 | + ax.text(cx - track_w/2 + 0.5, iy - 0.28, detail, ha='left', va='center', |
| 127 | + fontsize=7.5, color=TEXT_GRAY, zorder=5) |
| 128 | + if 'icons' in tk: |
| 129 | + icon_x = cx + track_w/2 - 0.8 |
| 130 | + icon_base_y = cy - track_h/2 + 0.6 |
| 131 | + for idx, it in enumerate(tk['icons']): |
| 132 | + ix = icon_x |
| 133 | + iy = icon_base_y + idx * 1.0 |
| 134 | + if it == 'hf': |
| 135 | + ax.text(ix, iy, 'HF', fontsize=9, ha='center', va='center', zorder=10, |
| 136 | + color=ACCENT_ORANGE, fontweight='bold') |
| 137 | + elif it == 'github': |
| 138 | + ax.text(ix, iy, 'GH', fontsize=9, ha='center', va='center', zorder=10, |
| 139 | + color=ACCENT_BLUE, fontweight='bold') |
| 140 | + elif it == 'demo': |
| 141 | + ax.text(ix, iy, 'DEMO', fontsize=8, ha='center', va='center', zorder=10, |
| 142 | + color=ACCENT_GREEN, fontweight='bold') |
| 143 | + |
| 144 | +# ── Linking arrows: tracks <-> chunks ── |
| 145 | +for tk in tracks: |
| 146 | + draw_arrow(tk['x'], track_y - track_h/2, tk['x'], 7.85, color='#334155', lw=1.2) |
| 147 | + |
| 148 | +# ── CHUNK LAYER ── |
| 149 | +chunk_y = 6.8 |
| 150 | +draw_card(10, chunk_y, 17.5, 1.6, '#0F2027', CHUNK_GREEN) |
| 151 | +ax.text(10, chunk_y + 0.45, '28,514 STRUCTURED CHUNKS', ha='center', va='center', |
| 152 | + fontsize=14, fontweight='bold', color=CHUNK_GREEN, zorder=5) |
| 153 | +chunk_details = 'LaTeX Formulas 253,012 \u00B7 Image-Formula Pairs 4,996 \u00B7 23 Textbooks + 339 arXiv Papers \u00B7 corpus/chunks/ on GitHub' |
| 154 | +ax.text(10, chunk_y - 0.1, chunk_details, ha='center', va='center', |
| 155 | + fontsize=8.5, color=TEXT_GRAY, zorder=5) |
| 156 | + |
| 157 | +# ── DOC LAYER ── |
| 158 | +doc_y = 4.6 |
| 159 | +draw_card(10, doc_y, 17.5, 1.4, '#0A1628', DOC_BLUE) |
| 160 | +ax.text(10, doc_y + 0.35, '362 DOCUMENTS via MinerU', ha='center', va='center', |
| 161 | + fontsize=14, fontweight='bold', color=DOC_BLUE, zorder=5) |
| 162 | +ax.text(10, doc_y - 0.15, '23 Control Textbooks (ZIP Encoding, Calabi-Yau) + 339 arXiv Papers (MPC, CBF, Adaptive, Robust, Nonlinear)', |
| 163 | + ha='center', va='center', fontsize=8.5, color=TEXT_GRAY, zorder=5) |
| 164 | + |
| 165 | +# ── Arrows: docs -> chunks ── |
| 166 | +draw_arrow(10, doc_y + 0.7, 10, chunk_y - 0.8, color=DOC_BLUE, lw=2.0) |
| 167 | + |
| 168 | +# ── PUBLIC LINKS BAR (bottom) ── |
| 169 | +link_y = 2.3 |
| 170 | +links = [ |
| 171 | + ('GitHub', 'github.com/MorningStar0709/control-sci', ACCENT_BLUE), |
| 172 | + ('HuggingFace', 'huggingface.co/datasets/MorningStar0709/control-sci-corpus', ACCENT_ORANGE), |
| 173 | + ('Live Demo', 'demo.askiler.com (code: ControlMind@2026)', ACCENT_GREEN), |
| 174 | +] |
| 175 | +for i, (label, url, color) in enumerate(links): |
| 176 | + lx = 3.5 + i * 6.5 |
| 177 | + draw_card(lx, link_y, 5.8, 1.4, '#111B2E', color) |
| 178 | + ax.text(lx, link_y + 0.3, label, ha='center', va='center', fontsize=11, |
| 179 | + fontweight='bold', color=color, zorder=5) |
| 180 | + ax.text(lx, link_y - 0.25, url, ha='center', va='center', fontsize=7.5, color=TEXT_GRAY, zorder=5) |
| 181 | + |
| 182 | +# ── LICENSE BAR ── |
| 183 | +ax.text(10, 1.0, 'CC-BY-4.0 | Full Reproducibility | DATA-TRACE Auditable | Single RTX 5090', |
| 184 | + ha='center', va='center', fontsize=9, color=TEXT_GRAY, zorder=5) |
| 185 | + |
| 186 | +plt.tight_layout(pad=0) |
| 187 | +fig.savefig(OUTPUT, dpi=200, facecolor=BG, edgecolor='none', bbox_inches='tight', pad_inches=0.3) |
| 188 | +plt.close() |
| 189 | +print(f"Saved: {OUTPUT}") |
0 commit comments