#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""AMD AAI2026 全栈 AI 基础设施 · 12 页 .pptx 生成脚本

依赖：python-pptx >= 0.6.21
输出：/var/www/html/share/AMD-AAI2026-演示.pptx
"""

import os
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.oxml.ns import qn
from copy import deepcopy
from lxml import etree

# ---- 品牌色 ----
AMD_RED   = RGBColor(0xED, 0x1C, 0x24)
NV_GREEN  = RGBColor(0x76, 0xB9, 0x00)
DARK      = RGBColor(0x1A, 0x1F, 0x2A)
GREY      = RGBColor(0x5A, 0x64, 0x78)
LIGHT     = RGBColor(0xE7, 0xEA, 0xF0)
PANEL     = RGBColor(0xF7, 0xF8, 0xFA)
WHITE     = RGBColor(0xFF, 0xFF, 0xFF)
WARN      = RGBColor(0xD4, 0x4A, 0x3A)

# ---- 中文字体 ----
CN_FONT = "Noto Sans CJK SC"  # Linux 字体回退
EN_FONT = "Arial"

IMG_DIR = "/var/www/html/share/helios-imgs"
OUT_PPTX = "/var/www/html/share/AMD-AAI2026-演示.pptx"

# ---- 16:9 ----
SLIDE_W = Inches(13.333)
SLIDE_H = Inches(7.5)


def add_rect(slide, x, y, w, h, fill, line=None, line_w=None):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid(); shp.fill.fore_color.rgb = fill
    if line is None:
        shp.line.fill.background()
    else:
        shp.line.color.rgb = line
        if line_w is not None:
            shp.line.width = line_w
    shp.shadow.inherit = False
    return shp


def add_text(slide, x, y, w, h, text, *, size=18, bold=False, color=DARK,
             align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP, font=CN_FONT,
             fill=None, line=None):
    if fill is not None:
        bg = add_rect(slide, x, y, w, h, fill, line=line)
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.margin_left = Inches(0.08); tf.margin_right = Inches(0.08)
    tf.margin_top = Inches(0.04); tf.margin_bottom = Inches(0.04)
    tf.word_wrap = True
    tf.vertical_anchor = anchor
    # 支持多行：按 \n 拆分
    lines = text.split("\n") if isinstance(text, str) else [str(text)]
    for i, ln in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.alignment = align
        run = p.add_run()
        run.text = ln
        run.font.size = Pt(size)
        run.font.bold = bold
        run.font.name = font
        # 中文字体设置
        rPr = run._r.get_or_add_rPr()
        ea = rPr.find(qn('a:ea'))
        if ea is None:
            ea = etree.SubElement(rPr, qn('a:ea'))
        ea.set('typeface', CN_FONT)
        run.font.color.rgb = color
    return tb


def add_title_bar(slide, title, subtitle=None):
    """顶部红色标题条 + 白色标题"""
    add_rect(slide, 0, 0, SLIDE_W, Inches(0.9), AMD_RED)
    add_text(slide, Inches(0.5), Inches(0.1), SLIDE_W - Inches(1), Inches(0.55),
             title, size=26, bold=True, color=WHITE, anchor=MSO_ANCHOR.MIDDLE)
    if subtitle:
        add_text(slide, Inches(0.5), Inches(0.5), SLIDE_W - Inches(1), Inches(0.38),
                 subtitle, size=12, color=LIGHT, anchor=MSO_ANCHOR.TOP)


def add_footer(slide, page_num, total=12):
    """底部数据来源 + 页码"""
    src = "数据来源：AMD 官网 / IR + 半导体行业观察（19 张实拍）+ Semianalysis / TrendForce"
    add_rect(slide, 0, SLIDE_H - Inches(0.35), SLIDE_W, Inches(0.35),
             RGBColor(0xF2, 0xF3, 0xF6))
    add_text(slide, Inches(0.4), SLIDE_H - Inches(0.32), Inches(10.5), Inches(0.3),
             src, size=9, color=GREY, anchor=MSO_ANCHOR.MIDDLE)
    add_text(slide, SLIDE_W - Inches(1.0), SLIDE_H - Inches(0.32),
             Inches(0.7), Inches(0.3),
             f"{page_num} / {total}", size=10, color=GREY,
             align=PP_ALIGN.RIGHT, anchor=MSO_ANCHOR.MIDDLE)


def safe_img(slide, path, x, y, w, h):
    """安全插入图片，找不到则返回 False"""
    try:
        if os.path.exists(path):
            slide.shapes.add_picture(path, x, y, width=w, height=h)
            return True
    except Exception:
        pass
    return False


# ============================================================
# 主流程
# ============================================================
prs = Presentation()
prs.slide_width = SLIDE_W
prs.slide_height = SLIDE_H
BLANK = prs.slide_layouts[6]


# -------- Slide 1 · 封面 --------
s = prs.slides.add_slide(BLANK)
add_rect(s, 0, 0, SLIDE_W, SLIDE_H, AMD_RED)
# 大色块装饰
add_rect(s, 0, SLIDE_H - Inches(2.0), SLIDE_W, Inches(2.0), DARK)
add_text(s, Inches(0.8), Inches(1.0), Inches(11), Inches(0.6),
         "AMD AAI2026", size=20, bold=True, color=WHITE)
add_text(s, Inches(0.8), Inches(1.7), Inches(12), Inches(1.6),
         "全栈 AI 基础设施", size=58, bold=True, color=WHITE)
add_text(s, Inches(0.8), Inches(3.2), Inches(12), Inches(0.8),
         "Open AI Must Win — 从芯片到机架",
         size=28, color=LIGHT)
add_text(s, Inches(0.8), Inches(4.2), Inches(12), Inches(0.6),
         "AMD vs NVIDIA · Helios vs Vera Rubin NVL72",
         size=18, color=LIGHT)
add_text(s, Inches(0.8), Inches(6.0), Inches(12), Inches(0.6),
         "2026-07-24  ·  制作者 Claude",
         size=14, color=LIGHT)


# -------- Slide 2 · TL;DR --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "TL;DR · 三个数字看懂 Helios", "AMD 单机架总算力 / 内存 / scale-up 互联带宽")

# 三个大数字卡片
cards = [
    ("2.9", "EFLOPS MXFP4", "机架级 FP4 推理"),
    ("31", "TB HBM4", "比 NV 多 50%"),
    ("260", "TB/s UALoE", "scale-up 互联"),
]
for i, (big, unit, desc) in enumerate(cards):
    x = Inches(0.5 + i * 2.6)
    add_rect(s, x, Inches(1.3), Inches(2.3), Inches(2.0), PANEL,
             line=LIGHT, line_w=Pt(0.75))
    add_text(s, x, Inches(1.4), Inches(2.3), Inches(0.9),
             big, size=44, bold=True, color=AMD_RED,
             align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, x, Inches(2.25), Inches(2.3), Inches(0.4),
             unit, size=14, bold=True, color=DARK, align=PP_ALIGN.CENTER)
    add_text(s, x, Inches(2.65), Inches(2.3), Inches(0.55),
             desc, size=11, color=GREY, align=PP_ALIGN.CENTER)

# 左侧机架渲染
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-08.webp",
                  Inches(8.3), Inches(1.3), Inches(4.6), Inches(3.2))
if not img_ok:
    add_rect(s, Inches(8.3), Inches(1.3), Inches(4.6), Inches(3.2), PANEL,
             line=LIGHT, line_w=Pt(0.75))
    add_text(s, Inches(8.3), Inches(2.7), Inches(4.6), Inches(0.6),
             "Helios 内部液冷渲染", size=14, color=GREY,
             align=PP_ALIGN.CENTER)

# 底部 take-away
add_rect(s, Inches(0.5), Inches(3.7), Inches(7.5), Inches(3.0),
         RGBColor(0xFE, 0xF6, 0xF4), line=LIGHT, line_w=Pt(0.5))
add_text(s, Inches(0.7), Inches(3.85), Inches(7.1), Inches(0.5),
         "单机架 = 72× MI455X + 18× EPYC Venice",
         size=18, bold=True, color=DARK)
add_text(s, Inches(0.7), Inches(4.4), Inches(7.1), Inches(2.2),
         ("• 峰值算力 2.9 EFLOPS MXFP4，机架 HBM 容量 31 TB\n"
          "• UALoE 全互联 scale-up 带宽 260 TB/s\n"
          "• 对标 NVIDIA Rubin NVL72：HBM +50%、FP4 峰值约 -20%\n"
          "• 整机功耗 225–245 kW，单机架估价 $5.0–5.5M（行业估）"),
         size=14, color=DARK)
add_footer(s, 2)


# -------- Slide 3 · 大会概览 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "AAI2026 大会概览 · 量产节奏已锁定",
              "时间地点 / 主题论点 / 量产时间表 / 首批客户")

# 时间线（横排 4 个节点）
nodes = [
    ("2026-07-22~23", "AAI2026 大会\n旧金山 Moscone", AMD_RED),
    ("2026 Q3 末", "MI455X 首批\n出货", DARK),
    ("2026 H2", "OpenAI 1 GW\nAzure ND MI455X", DARK),
    ("2027 H1", "Anthropic\n2 GW 启动", DARK),
]
nx0 = Inches(0.7); ny = Inches(2.5); nw = Inches(2.85); nh = Inches(1.5)
gap = Inches(0.15)
for i, (date, ev, col) in enumerate(nodes):
    x = nx0 + (nw + gap) * i
    add_rect(s, x, ny, nw, nh, col)
    add_text(s, x, ny + Inches(0.15), nw, Inches(0.4),
             date, size=14, bold=True, color=WHITE,
             align=PP_ALIGN.CENTER)
    add_text(s, x, ny + Inches(0.55), nw, Inches(0.85),
             ev, size=14, color=WHITE, align=PP_ALIGN.CENTER,
             anchor=MSO_ANCHOR.MIDDLE)
# 节点之间连线
for i in range(3):
    x = nx0 + nw + (nw + gap) * i + Inches(0.05)
    add_rect(s, x, ny + Inches(0.7), gap - Inches(0.1), Inches(0.1), GREY)

# 底部论点和量产节奏
add_text(s, Inches(0.5), Inches(4.4), Inches(12.3), Inches(0.4),
         "Lisa Su 主旨核心论点", size=18, bold=True, color=AMD_RED)
add_text(s, Inches(0.5), Inches(4.85), Inches(12.3), Inches(2.2),
         ("• 从单芯片到机架级交付 — Helios 是 AMD 首个端到端 AI 机柜参考设计\n"
          "• 开放标准叙事：Ultra Ethernet / UALink / OCP ORW / ROCm 7\n"
          "• \"Open AI Must Win\" — 拉拢 OpenAI / Anthropic / Microsoft / Meta / Oracle 背书\n"
          "• TCO / tokens-per-dollar 优势 = 对 NVIDIA 的核心叙事武器"),
         size=15, color=DARK)
add_footer(s, 3)


# -------- Slide 4 · MI455X --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "MI455X · 代际翻倍反击",
              "CDNA 5 / 2nm / HBM4 432GB / 40 PFLOPS MXFP4")

# 左侧 4 颗 MI455X 实物
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-03.jpg",
                  Inches(0.5), Inches(1.2), Inches(5.5), Inches(4.0))
if not img_ok:
    add_rect(s, Inches(0.5), Inches(1.2), Inches(5.5), Inches(4.0), PANEL,
             line=LIGHT, line_w=Pt(0.75))
    add_text(s, Inches(0.5), Inches(3.0), Inches(5.5), Inches(0.6),
             "AMD Instinct MI455X × 4", size=14, color=GREY,
             align=PP_ALIGN.CENTER)

# 右侧 4 行硬参数
specs = [
    ("架构", "CDNA 5（AMD 首个 2 nm GPU）"),
    ("封装", "TSMC 2nm XCD + N3P IOD，320 亿晶体管"),
    ("内存", "HBM4 432 GB / 卡，12-Hi 堆叠，23.3 TB/s"),
    ("算力", "40 PFLOPS MXFP4 · 20 PFLOPS MXFP8"),
    ("vs MI355X", "FP4 +2×  /  HBM +50%  /  带宽 +2.9×"),
]
for i, (k, v) in enumerate(specs):
    y = Inches(1.3 + i * 0.85)
    add_rect(s, Inches(6.4), y, Inches(6.4), Inches(0.75),
             PANEL if i % 2 == 0 else WHITE, line=LIGHT, line_w=Pt(0.5))
    add_text(s, Inches(6.55), y + Inches(0.1), Inches(1.5), Inches(0.55),
             k, size=14, bold=True, color=AMD_RED, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(8.1), y + Inches(0.1), Inches(4.65), Inches(0.55),
             v, size=13, color=DARK, anchor=MSO_ANCHOR.MIDDLE)

# 底部 AMD 自测标注
add_text(s, Inches(6.4), Inches(5.7), Inches(6.4), Inches(0.4),
         "代际提升数据来源：AMD 官方产品页（vs MI355X）",
         size=10, color=GREY)
add_footer(s, 4)


# -------- Slide 5 · EPYC Venice --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "EPYC Venice · 256 核 Zen 6 反击",
              "Zen 6 / 2nm / 1.6 TB/s / vs NVIDIA Vera 88C")

# 左：Venice 实物
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-02.webp",
                  Inches(0.5), Inches(1.2), Inches(5.5), Inches(4.0))
if not img_ok:
    add_rect(s, Inches(0.5), Inches(1.2), Inches(5.5), Inches(4.0), PANEL,
             line=LIGHT, line_w=Pt(0.75))

# 右：对比表（精简 4 行）
add_text(s, Inches(6.4), Inches(1.2), Inches(6.4), Inches(0.4),
         "Venice vs Vera（精简）", size=14, bold=True, color=AMD_RED)
rows = [
    ("维度", "EPYC Venice", "NVIDIA Vera"),
    ("核心 / 线程", "256C / 512T", "88C / 176T"),
    ("内存带宽", "DDR5 1.6 TB/s", "LPDDR5X 1.2 TB/s"),
    ("指令集", "x86-64 (Zen 6)", "Armv9.2 (Olympus)"),
    ("单核性能", "AMD 称 +20% (自测)", "NV 称 SPEC 925"),
]
ry = Inches(1.65)
col_w = [Inches(1.6), Inches(2.4), Inches(2.4)]
for ri, row in enumerate(rows):
    rx = Inches(6.4)
    fill = LIGHT if ri == 0 else (PANEL if ri % 2 == 1 else WHITE)
    add_rect(s, Inches(6.4), ry + Inches(0.5) * ri, Inches(6.4),
             Inches(0.5), fill, line=LIGHT, line_w=Pt(0.5))
    cx = Inches(6.4)
    for ci, cell in enumerate(row):
        bold = ri == 0 or ci == 1  # 表头 + AMD 列加粗
        col = AMD_RED if ri == 0 else DARK
        add_text(s, cx, ry + Inches(0.5) * ri, col_w[ci], Inches(0.5),
                 cell, size=12, bold=bold, color=col,
                 align=PP_ALIGN.CENTER if ri == 0 else PP_ALIGN.LEFT,
                 anchor=MSO_ANCHOR.MIDDLE)
        cx += col_w[ci]

# 底部 take-away
add_text(s, Inches(6.4), Inches(4.4), Inches(6.4), Inches(0.4),
         "在通用云 / 容器 / VM 密度场景：Venice 占优",
         size=15, bold=True, color=AMD_RED)
add_text(s, Inches(6.4), Inches(4.85), Inches(6.4), Inches(2.2),
         ("• Venice：通用 x86 主机，拉 4 颗 GPU\n"
          "• Vera：与 Rubin 紧耦合的 NVLink 控制平面\n"
          "• 单核延迟 / agent 控制循环 → Vera 占优\n"
          "• AMD 称机架级总吞吐 2.2× vs Vera（互引自测）"),
         size=13, color=DARK)
add_text(s, Inches(6.4), Inches(5.7), Inches(6.4), Inches(0.4),
         "* +20% / 2.2× 数据来源：AMD 自测",
         size=10, color=GREY)
add_footer(s, 5)


# -------- Slide 6 · Helios 整机 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "Helios 整机 · 72 GPU + 18 CPU 机柜级",
              "18 计算托盘 + 6 交换托盘 + Pensando Salina + UALoE 260 TB/s")

# 左：Scale-Up Cartridges
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-09.jpg",
                  Inches(0.4), Inches(1.2), Inches(6.4), Inches(4.5))
if not img_ok:
    add_rect(s, Inches(0.4), Inches(1.2), Inches(6.4), Inches(4.5), PANEL,
             line=LIGHT, line_w=Pt(0.75))

# 右：拓扑 + 规格
add_text(s, Inches(7.1), Inches(1.2), Inches(5.7), Inches(0.5),
         "机柜拓扑（72+18）", size=16, bold=True, color=AMD_RED)
items = [
    ("18", "计算托盘：1× Venice + 4× MI455X"),
    ("6", "交换托盘：12× Tomahawk 6 ASIC"),
    ("144", "Pensando Vulcano 800G AI NIC（3×/GPU）"),
    ("72", "Pensando Salina DPU"),
    ("260", "TB/s UALoE scale-up 互联"),
    ("225–245", "kW 整机功耗（液冷）"),
]
for i, (big, desc) in enumerate(items):
    y = Inches(1.75 + i * 0.7)
    add_text(s, Inches(7.1), y, Inches(0.95), Inches(0.55),
             big, size=22, bold=True, color=AMD_RED,
             align=PP_ALIGN.RIGHT, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(8.15), y + Inches(0.08), Inches(4.65), Inches(0.55),
             desc, size=12, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
add_footer(s, 6)


# -------- Slide 7 · 软件栈 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "软件栈 · ROCm 7 + 全开放标准",
              "UALoE / Ultra Ethernet / OCP ORW / UALink 联盟 100+ 成员")

# 左：Dual Network Switches 图（含 UALink 联盟）
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-12.jpg",
                  Inches(0.4), Inches(1.2), Inches(7.0), Inches(4.5))
if not img_ok:
    add_rect(s, Inches(0.4), Inches(1.2), Inches(7.0), Inches(4.5), PANEL,
             line=LIGHT, line_w=Pt(0.75))

# 右：开放栈 3 层
add_text(s, Inches(7.7), Inches(1.2), Inches(5.2), Inches(0.4),
         "AMD 开放栈三层", size=16, bold=True, color=AMD_RED)
layers = [
    ("硬件层", "Ultra Accelerator Link · Ultra Ethernet · OCP ORW", AMD_RED),
    ("软件层", "ROCm 7 · ROCm.ai · Gorgon Halo · PyTorch 主线", DARK),
    ("生态层", "vLLM · SGLang · Triton · ONNX · Hugging Face", DARK),
]
for i, (k, v, col) in enumerate(layers):
    y = Inches(1.75 + i * 1.4)
    add_rect(s, Inches(7.7), y, Inches(5.2), Inches(1.2),
             PANEL, line=LIGHT, line_w=Pt(0.5))
    add_rect(s, Inches(7.7), y, Inches(0.12), Inches(1.2), col)
    add_text(s, Inches(7.9), y + Inches(0.1), Inches(5.0), Inches(0.4),
             k, size=14, bold=True, color=col)
    add_text(s, Inches(7.9), y + Inches(0.55), Inches(5.0), Inches(0.6),
             v, size=12, color=DARK)

add_footer(s, 7)


# -------- Slide 8 · 客户落地 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "客户落地 · GW 级订单已签字",
              "OpenAI / Anthropic / Microsoft Azure / Meta / Oracle")

# 上：OpenAI / Anthropic 主图
img_ok = safe_img(s, f"{IMG_DIR}/wx-helios-13.webp",
                  Inches(0.4), Inches(1.2), Inches(6.8), Inches(4.4))
if not img_ok:
    add_rect(s, Inches(0.4), Inches(1.2), Inches(6.8), Inches(4.4), PANEL,
             line=LIGHT, line_w=Pt(0.75))

# 右：客户 × 规模 × 时间表
add_text(s, Inches(7.5), Inches(1.2), Inches(5.4), Inches(0.4),
         "5 大客户 × 落地时间表", size=16, bold=True, color=AMD_RED)
rows = [
    ("OpenAI",        "1 GW（首阶段）",   "2026 H2"),
    ("Anthropic",     "2 GW（首阶段 1 GW）", "2027 H1"),
    ("Microsoft Azure", "ND MI455X v7 VM",  "2026 H2"),
    ("Meta",          "ORW 共建 + 自用",    "2026 H2+"),
    ("Oracle Cloud",  "已签 OCI 部署",      "2026 H2+"),
]
ry = Inches(1.75)
add_rect(s, Inches(7.5), ry, Inches(5.4), Inches(0.5), LIGHT)
add_text(s, Inches(7.6), ry, Inches(1.6), Inches(0.5), "客户", size=12, bold=True, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
add_text(s, Inches(9.3), ry, Inches(2.2), Inches(0.5), "规模", size=12, bold=True, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
add_text(s, Inches(11.5), ry, Inches(1.3), Inches(0.5), "时间", size=12, bold=True, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
for i, row in enumerate(rows):
    y = ry + Inches(0.5) * (i + 1)
    add_rect(s, Inches(7.5), y, Inches(5.4), Inches(0.5),
             PANEL if i % 2 == 0 else WHITE, line=LIGHT, line_w=Pt(0.5))
    add_text(s, Inches(7.6), y, Inches(1.6), Inches(0.5),
             row[0], size=12, bold=True, color=AMD_RED,
             anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(9.3), y, Inches(2.2), Inches(0.5),
             row[1], size=11, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(11.5), y, Inches(1.3), Inches(0.5),
             row[2], size=11, color=DARK, anchor=MSO_ANCHOR.MIDDLE,
             align=PP_ALIGN.CENTER)

# 底部金句
add_text(s, Inches(0.4), Inches(5.85), Inches(12.5), Inches(0.4),
         "Anthropic + AMD 投资 ≤ $50 亿  =  AMD 史上最大单笔 AI 客户投资",
         size=15, bold=True, color=AMD_RED, align=PP_ALIGN.CENTER)
add_text(s, Inches(0.4), Inches(6.3), Inches(12.5), Inches(0.4),
         "绑定意义 > 订单金额本身",
         size=13, color=GREY, align=PP_ALIGN.CENTER)
add_footer(s, 8)


# -------- Slide 9 · AMD vs NVIDIA 主对比（精简 8 行）--------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "AMD vs NVIDIA · 主对比（精简 8 行）",
              "完整 25 行见 PDF 报告")

headers = ["维度", "AMD Helios / MI455X / Venice", "NVIDIA Rubin NVL72", "备注"]
col_w = [Inches(1.7), Inches(3.6), Inches(3.6), Inches(3.4)]
data = [
    ("单卡 HBM",     "432 GB HBM4",      "288 GB HBM4",      "AMD +50%"),
    ("单卡 FP4",     "40 PFLOPS MXFP4",  "~50 PFLOPS NVFP4", "NV +25%（峰值口径）"),
    ("机架 FP4",     "2.9 EFLOPS",       "~3.6 EFLOPS",      "NV 领先"),
    ("机架 HBM",     "31 TB",            "20.7 TB",          "AMD +50%"),
    ("Scale-up",     "UALoE 260 TB/s",   "NVLink 6 260 TB/s","持平（架构差异）"),
    ("CPU",          "256C Zen 6 x86",   "88C Olympus Arm",  "AMD +190% 核心"),
    ("量产",         "Q3 末 / H2 出货",  "Q1 已量产",        "NV 早 1 季度"),
    ("tokens/$",     "+30% vs Rubin",    "NV 称 FP4 领先",   "互引自测"),
]
ty = Inches(1.3); rh = Inches(0.55)
# 表头
add_rect(s, Inches(0.4), ty, sum(col_w, Inches(0)), rh, LIGHT)
cx = Inches(0.4)
for ci, h in enumerate(headers):
    add_text(s, cx, ty, col_w[ci], rh, h, size=13, bold=True, color=DARK,
             align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    cx += col_w[ci]
# 数据行
for ri, row in enumerate(data):
    y = ty + rh * (ri + 1)
    add_rect(s, Inches(0.4), y, sum(col_w, Inches(0)), rh,
             PANEL if ri % 2 == 0 else WHITE, line=LIGHT, line_w=Pt(0.5))
    cx = Inches(0.4)
    for ci, cell in enumerate(row):
        col = AMD_RED if ci == 1 else (NV_GREEN if ci == 2 else DARK)
        bold = ci in (1, 2)
        add_text(s, cx, y, col_w[ci], rh, cell, size=11, bold=bold, color=col,
                 align=PP_ALIGN.LEFT if ci > 0 else PP_ALIGN.CENTER,
                 anchor=MSO_ANCHOR.MIDDLE)
        cx += col_w[ci]

# 底部 takeaway
add_text(s, Inches(0.4), Inches(6.3), Inches(12.5), Inches(0.4),
         "AMD 用 HBM +50% 换 FP4 -20%：长上下文 / MoE 推理更友好，dense 训练逊一筹",
         size=15, bold=True, color=AMD_RED, align=PP_ALIGN.CENTER)
add_text(s, Inches(0.4), Inches(6.7), Inches(12.5), Inches(0.3),
         "* tokens/$ 来自 AMD 自测，详见报告脚注",
         size=10, color=GREY, align=PP_ALIGN.CENTER)
add_footer(s, 9)


# -------- Slide 10 · 差异化 vs 壁垒 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "AMD 差异化 vs NVIDIA 壁垒 · 战略对决",
              "本质之争：开放生态 vs 专有锁定")

# 左：AMD 红
add_rect(s, Inches(0.4), Inches(1.2), Inches(6.2), Inches(5.0), PANEL,
         line=AMD_RED, line_w=Pt(2))
add_rect(s, Inches(0.4), Inches(1.2), Inches(6.2), Inches(0.6), AMD_RED)
add_text(s, Inches(0.4), Inches(1.25), Inches(6.2), Inches(0.5),
         "AMD Helios · 差异化", size=18, bold=True, color=WHITE,
         align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
amd_pts = [
    ("开放互联", "UALoE + Ultra Ethernet + UALink 联盟"),
    ("开放机架", "OCP ORW（Meta 2025 提交）"),
    ("HBM 容量", "+50% vs Rubin（432 vs 288 GB）"),
    ("x86 主机", "256C Venice + PCIe 6 拉 4 GPU"),
    ("TCO 叙事", "tokens/$ +30% AMD 自测"),
]
for i, (k, v) in enumerate(amd_pts):
    y = Inches(2.0 + i * 0.8)
    add_text(s, Inches(0.6), y, Inches(1.6), Inches(0.6),
             k, size=14, bold=True, color=AMD_RED, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(2.3), y, Inches(4.2), Inches(0.6),
             v, size=12, color=DARK, anchor=MSO_ANCHOR.MIDDLE)

# 右：NV 绿
add_rect(s, Inches(6.8), Inches(1.2), Inches(6.2), Inches(5.0), PANEL,
         line=NV_GREEN, line_w=Pt(2))
add_rect(s, Inches(6.8), Inches(1.2), Inches(6.2), Inches(0.6), NV_GREEN)
add_text(s, Inches(6.8), Inches(1.25), Inches(6.2), Inches(0.5),
         "NVIDIA Rubin · 壁垒", size=18, bold=True, color=WHITE,
         align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
nv_pts = [
    ("CUDA 黏性", "全球 AI 工程师 + 主流模型库原生支持"),
    ("NVLink 6", "每 GPU 22 TB/s，成熟，与 Rubin 同代磨合"),
    ("量产节奏", "Q1 2026 已量产，H2 OEM 大量出货"),
    ("软件生态", "TensorRT + NeMo + NIM 端到端"),
    ("云厂绑定", "CoreWeave / Lambda / Azure 部分 / AWS"),
]
for i, (k, v) in enumerate(nv_pts):
    y = Inches(2.0 + i * 0.8)
    add_text(s, Inches(7.0), y, Inches(1.6), Inches(0.6),
             k, size=14, bold=True, color=NV_GREEN, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(8.7), y, Inches(4.2), Inches(0.6),
             v, size=12, color=DARK, anchor=MSO_ANCHOR.MIDDLE)

# 底部结论
add_rect(s, Inches(0.4), Inches(6.4), Inches(12.5), Inches(0.5), DARK)
add_text(s, Inches(0.4), Inches(6.4), Inches(12.5), Inches(0.5),
         "谁先达到「开箱即用 9 成以上」谁就赢下下一个 24 个月",
         size=16, bold=True, color=WHITE,
         align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
add_footer(s, 10)


# -------- Slide 11 · 采购决策树 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "采购决策树 · Helios vs Rubin",
              "按负载场景 / 生态依赖 / TCO 敏感度分流")

# 顶部节点：你的需求
add_rect(s, Inches(5.4), Inches(1.2), Inches(2.5), Inches(0.8), DARK)
add_text(s, Inches(5.4), Inches(1.2), Inches(2.5), Inches(0.8),
         "你的 AI 负载", size=16, bold=True, color=WHITE,
         align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)

# 两个分支
add_text(s, Inches(0.5), Inches(2.3), Inches(6.0), Inches(0.4),
         "→ 选 Helios", size=15, bold=True, color=AMD_RED,
         align=PP_ALIGN.CENTER)
add_text(s, Inches(6.8), Inches(2.3), Inches(6.0), Inches(0.4),
         "→ 选 Rubin NVL72", size=15, bold=True, color=NV_GREEN,
         align=PP_ALIGN.CENTER)

# 分隔线
add_rect(s, Inches(6.65), Inches(2.4), Pt(1), Inches(3.5), GREY)

# 左：Helios 选型条件（红框）
add_rect(s, Inches(0.5), Inches(2.8), Inches(6.0), Inches(3.0), PANEL,
         line=AMD_RED, line_w=Pt(1.5))
helios_conds = [
    "• >200B 参数推理 / 长上下文 / MoE 大 KV",
    "• 已绑定 x86 生态（VMWare / KVM / 通用 Linux）",
    "• 希望避开 CUDA 锁定（ROCm / Triton / vLLM）",
    "• TCO 敏感，需要 Ultra Ethernet 多供应商交换",
    "• 已在 Azure / OCI，可走 Helios VM 快速接入",
]
for i, c in enumerate(helios_conds):
    add_text(s, Inches(0.7), Inches(2.95 + i * 0.5), Inches(5.6), Inches(0.4),
             c, size=13, color=DARK)

# 右：Rubin 选型条件（绿框）
add_rect(s, Inches(6.8), Inches(2.8), Inches(6.0), Inches(3.0), PANEL,
         line=NV_GREEN, line_w=Pt(1.5))
rubin_conds = [
    "• 大规模 MoE / dense 训练（>1T 参数）",
    "• 已有 CUDA / TensorRT / NeMo 深度优化栈",
    "• 需要 NVLink 高带宽 + Transformer Engine 稀疏",
    "• 已签 Azure / AWS / GCP 的 NVIDIA 实例",
    "• 对「量产稳定性」敏感于「极致 TCO」",
]
for i, c in enumerate(rubin_conds):
    add_text(s, Inches(7.0), Inches(2.95 + i * 0.5), Inches(5.6), Inches(0.4),
             c, size=13, color=DARK)

# 底部：双供提示
add_rect(s, Inches(0.5), Inches(6.0), Inches(12.5), Inches(0.8), DARK)
add_text(s, Inches(0.5), Inches(6.0), Inches(12.5), Inches(0.4),
         "大客户已不押单一供应商 — AI 基础设施进入「双供时代」",
         size=15, bold=True, color=WHITE, align=PP_ALIGN.CENTER,
         anchor=MSO_ANCHOR.MIDDLE)
add_text(s, Inches(0.5), Inches(6.4), Inches(12.5), Inches(0.4),
         "OpenAI / Anthropic / Meta 均已签双供协议",
         size=12, color=LIGHT, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
add_footer(s, 11)


# -------- Slide 12 · 风险与待核实 --------
s = prs.slides.add_slide(BLANK)
add_title_bar(s, "风险与待核实 · 5 项关键警示",
              "AMD 自测 / NVIDIA 自测 ≠ 第三方实测结论")

risks = [
    ("01", "MI455X 真实量产频率 / 良率 / 功耗",
     "2nm 量产爬坡曲线待 2026 Q3 末实际出货批次确认"),
    ("02", "\"34× 吞吐 / 30% tokens/$\" 数字",
     "AMD 内部测试，未公开完整模型 / batch / 量化配置"),
    ("03", "Venice 单核 vs Vera SPEC 2026",
     "AMD 称 +20% / NV 称 925 vs 898，互引未给测试条件"),
    ("04", "UALoE 多供应商端到端互通",
     "UALink / Ultra Ethernet 联盟实际互通性待 2026 H2 验证"),
    ("05", "ROCm 7 + Gorgon Halo 生产稳定性",
     "MoE all-to-all / KV cache 命中率需 2026 Q4 实测"),
]
ry = Inches(1.3); rh = Inches(0.95)
for i, (num, title, desc) in enumerate(risks):
    y = ry + (rh + Inches(0.1)) * i
    add_rect(s, Inches(0.4), y, Inches(12.5), rh,
             PANEL, line=LIGHT, line_w=Pt(0.5))
    add_rect(s, Inches(0.4), y, Inches(1.0), rh, WARN)
    add_text(s, Inches(0.4), y, Inches(1.0), rh, num,
             size=22, bold=True, color=WHITE,
             align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(1.6), y + Inches(0.08), Inches(11.2), Inches(0.4),
             title, size=15, bold=True, color=DARK, anchor=MSO_ANCHOR.MIDDLE)
    add_text(s, Inches(1.6), y + Inches(0.5), Inches(11.2), Inches(0.4),
             desc, size=12, color=GREY, anchor=MSO_ANCHOR.MIDDLE)

# 底部数据来源声明
add_rect(s, Inches(0.4), Inches(6.55), Inches(12.5), Inches(0.5), DARK)
add_text(s, Inches(0.4), Inches(6.55), Inches(12.5), Inches(0.5),
         "数据来源：AMD 官网 / IR + Helios 客户（OpenAI/Anthropic/MS）公开声明 + 半导体行业观察 + Semianalysis / TrendForce",
         size=11, color=WHITE, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
add_footer(s, 12)


# ---- 保存 ----
prs.save(OUT_PPTX)
print(f"OK saved → {OUT_PPTX}")
print(f"Slides: {len(prs.slides)}")