# history

source:
  print("Hello from AIO Sandbox!")
  import sys
  print(f"Python version: {sys.version}")
  print(f"Platform: {sys.platform}")
  result = sum(range(100))
  print(f"Sum of 0..99 = {result}")

source_raw:
  print("Hello from AIO Sandbox!")
  import sys
  print(f"Python version: {sys.version}")
  print(f"Platform: {sys.platform}")
  result = sum(range(100))
  print(f"Sum of 0..99 = {result}")


source:
  print("Hello from AIO Sandbox!")
  import sys
  print(f"Python version: {sys.version}")
  print(f"Platform: {sys.platform}")
  result = sum(range(100))
  print(f"Sum of 0..99 = {result}")
  import pandas as pd
  import numpy as np
  df = pd.DataFrame({'A': np.random.randn(5), 'B': np.random.randint(1, 10, 5)})
  print("\nPandas Demo:")
  print(df)

source_raw:
  print("Hello from AIO Sandbox!")
  import sys
  print(f"Python version: {sys.version}")
  print(f"Platform: {sys.platform}")
  result = sum(range(100))
  print(f"Sum of 0..99 = {result}")
  import pandas as pd
  import numpy as np
  df = pd.DataFrame({'A': np.random.randn(5), 'B': np.random.randint(1, 10, 5)})
  print("\nPandas Demo:")
  print(df)


source:
  import sys
  import platform
  import math

  # 基本计算
  result = sum(range(1, 101))
  pi_approx = 4 * sum((-1)**k / (2*k + 1) for k in range(100000))

  # 数据处理
  data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
  mean = sum(data) / len(data)
  variance = sum((x - mean)**2 for x in data) / len(data)
  std_dev = math.sqrt(variance)

  print(f"🐍 Python 版本: {sys.version}")
  print(f"📐 1+2+...+100 = {result}")
  print(f"🥧 π 近似值 = {pi_approx:.10f}")
  print(f"📊 数据统计: 均值={mean:.2f}, 标准差={std_dev:.2f}")
  print(f"✅ Python 代码执行正常！")

source_raw:
  import sys
  import platform
  import math

  # 基本计算
  result = sum(range(1, 101))
  pi_approx = 4 * sum((-1)**k / (2*k + 1) for k in range(100000))

  # 数据处理
  data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
  mean = sum(data) / len(data)
  variance = sum((x - mean)**2 for x in data) / len(data)
  std_dev = math.sqrt(variance)

  print(f"🐍 Python 版本: {sys.version}")
  print(f"📐 1+2+...+100 = {result}")
  print(f"🥧 π 近似值 = {pi_approx:.10f}")
  print(f"📊 数据统计: 均值={mean:.2f}, 标准差={std_dev:.2f}")
  print(f"✅ Python 代码执行正常！")


source:
  import matplotlib
  matplotlib.use('Agg')
  import matplotlib.pyplot as plt
  import numpy as np

  # 创建一个综合图表
  fig, axes = plt.subplots(2, 2, figsize=(12, 10))
  fig.suptitle('AIO Sandbox 数据可视化测试', fontsize=16, fontweight='bold')

  # 1. 正弦波
  x = np.linspace(0, 4*np.pi, 200)
  axes[0,0].plot(x, np.sin(x), 'b-', linewidth=2, label='sin(x)')
  axes[0,0].plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)')
  axes[0,0].set_title('Trigonometric Functions')
  axes[0,0].legend()
  axes[0,0].grid(True, alpha=0.3)

  # 2. 柱状图
  categories = ['Python', 'JS', 'Bash', 'File I/O', 'Browser', 'GUI']
  scores = [100, 100, 80, 100, 90, 95]
  colors = ['#667eea', '#764ba2', '#f093fb', '#4facfe', '#00f2fe', '#43e97b']
  axes[0,1].bar(categories, scores, color=colors, edgecolor='white', linewidth=2)
  axes[0,1].set_title('AIO Sandbox Test Scores')
  axes[0,1].set_ylim(0, 110)
  for i, v in enumerate(scores):
      axes[0,1].text(i, v+2, str(v), ha='center', fontweight='bold')

  # 3. 散点图
  np.random.seed(42)
  n = 100
  x_scatter = np.random.randn(n)
  y_scatter = x_scatter * 0.5 + np.random.randn(n) * 0.5
  axes[1,0].scatter(x_scatter, y_scatter, c=np.sqrt(x_scatter**2 + y_scatter**2), 
                    cmap='viridis', alpha=0.7, s=60, edgecolors='white', linewidth=0.5)
  axes[1,0].set_title('Correlation Scatter Plot')
  axes[1,0].set_xlabel('X'); axes[1,0].set_ylabel('Y')

  # 4. 饼图
  labels = ['Code Exec', 'File Ops', 'Browser', 'GUI', 'System']
  sizes = [30, 20, 25, 15, 10]
  explode = (0.05, 0, 0.05, 0, 0)
  axes[1,1].pie(sizes, explode=explode, labels=labels, autopct='%1.0f%%',
                colors=['#667eea','#764ba2','#f093fb','#4facfe','#43e97b'],
                shadow=True, startangle=90)
  axes[1,1].set_title('Capability Distribution')

  plt.tight_layout()
  plt.savefig('/tmp/aio_test_chart.png', dpi=150, bbox_inches='tight')
  print("✅ 图表已保存到 /tmp/aio_test_chart.png")
  print(f"📊 matplotlib 版本: {matplotlib.__version__}")
  print(f"📊 numpy 版本: {np.__version__}")

source_raw:
  import matplotlib
  matplotlib.use('Agg')
  import matplotlib.pyplot as plt
  import numpy as np

  # 创建一个综合图表
  fig, axes = plt.subplots(2, 2, figsize=(12, 10))
  fig.suptitle('AIO Sandbox 数据可视化测试', fontsize=16, fontweight='bold')

  # 1. 正弦波
  x = np.linspace(0, 4*np.pi, 200)
  axes[0,0].plot(x, np.sin(x), 'b-', linewidth=2, label='sin(x)')
  axes[0,0].plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)')
  axes[0,0].set_title('Trigonometric Functions')
  axes[0,0].legend()
  axes[0,0].grid(True, alpha=0.3)

  # 2. 柱状图
  categories = ['Python', 'JS', 'Bash', 'File I/O', 'Browser', 'GUI']
  scores = [100, 100, 80, 100, 90, 95]
  colors = ['#667eea', '#764ba2', '#f093fb', '#4facfe', '#00f2fe', '#43e97b']
  axes[0,1].bar(categories, scores, color=colors, edgecolor='white', linewidth=2)
  axes[0,1].set_title('AIO Sandbox Test Scores')
  axes[0,1].set_ylim(0, 110)
  for i, v in enumerate(scores):
      axes[0,1].text(i, v+2, str(v), ha='center', fontweight='bold')

  # 3. 散点图
  np.random.seed(42)
  n = 100
  x_scatter = np.random.randn(n)
  y_scatter = x_scatter * 0.5 + np.random.randn(n) * 0.5
  axes[1,0].scatter(x_scatter, y_scatter, c=np.sqrt(x_scatter**2 + y_scatter**2), 
                    cmap='viridis', alpha=0.7, s=60, edgecolors='white', linewidth=0.5)
  axes[1,0].set_title('Correlation Scatter Plot')
  axes[1,0].set_xlabel('X'); axes[1,0].set_ylabel('Y')

  # 4. 饼图
  labels = ['Code Exec', 'File Ops', 'Browser', 'GUI', 'System']
  sizes = [30, 20, 25, 15, 10]
  explode = (0.05, 0, 0.05, 0, 0)
  axes[1,1].pie(sizes, explode=explode, labels=labels, autopct='%1.0f%%',
                colors=['#667eea','#764ba2','#f093fb','#4facfe','#43e97b'],
                shadow=True, startangle=90)
  axes[1,1].set_title('Capability Distribution')

  plt.tight_layout()
  plt.savefig('/tmp/aio_test_chart.png', dpi=150, bbox_inches='tight')
  print("✅ 图表已保存到 /tmp/aio_test_chart.png")
  print(f"📊 matplotlib 版本: {matplotlib.__version__}")
  print(f"📊 numpy 版本: {np.__version__}")


source:
  import urllib.request
  import os
  from datetime import datetime

  # 两张截图的 URL
  screenshots = {
      "alibaba_loading.jpg": "https://lobehz.hka.mefans.com/f/f22afd3d-1fba-4b7d-b175-c0bbb7c9bd00",
      "alibaba_loaded.jpg": "https://lobehz.hka.mefans.com/f/09dc190b-ca57-45d4-92cd-92240aee6502"
  }

  saved = []
  for name, url in screenshots.items():
      path = f"/tmp/{name}"
      urllib.request.urlretrieve(url, path)
      size = os.path.getsize(path)
      saved.append(f"{name}: {size/1024:.1f} KB")
      print(f"✅ 已保存: {path} ({size/1024:.1f} KB)")

  print(f"\n共保存 {len(saved)} 张截图")

source_raw:
  import urllib.request
  import os
  from datetime import datetime

  # 两张截图的 URL
  screenshots = {
      "alibaba_loading.jpg": "https://lobehz.hka.mefans.com/f/f22afd3d-1fba-4b7d-b175-c0bbb7c9bd00",
      "alibaba_loaded.jpg": "https://lobehz.hka.mefans.com/f/09dc190b-ca57-45d4-92cd-92240aee6502"
  }

  saved = []
  for name, url in screenshots.items():
      path = f"/tmp/{name}"
      urllib.request.urlretrieve(url, path)
      size = os.path.getsize(path)
      saved.append(f"{name}: {size/1024:.1f} KB")
      print(f"✅ 已保存: {path} ({size/1024:.1f} KB)")

  print(f"\n共保存 {len(saved)} 张截图")


source:
  import subprocess
  import os

  # 用 xdotool 确认当前窗口
  result = subprocess.run(['xdotool', 'getactivewindow', 'getwindowname'], 
                         capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
  print(f"当前活动窗口: {result.stdout.strip()}")

  # 列出所有窗口
  result2 = subprocess.run(['xdotool', 'search', '--name', ''], 
                          capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
  windows = result2.stdout.strip().split('\n')[:10]
  for w in windows:
      name = subprocess.run(['xdotool', 'getwindowname', w], 
                           capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
      if name.stdout.strip():
          print(f"  窗口 {w}: {name.stdout.strip()}")

source_raw:
  import subprocess
  import os

  # 用 xdotool 确认当前窗口
  result = subprocess.run(['xdotool', 'getactivewindow', 'getwindowname'], 
                         capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
  print(f"当前活动窗口: {result.stdout.strip()}")

  # 列出所有窗口
  result2 = subprocess.run(['xdotool', 'search', '--name', ''], 
                          capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
  windows = result2.stdout.strip().split('\n')[:10]
  for w in windows:
      name = subprocess.run(['xdotool', 'getwindowname', w], 
                           capture_output=True, text=True, env={**os.environ, 'DISPLAY': ':99'})
      if name.stdout.strip():
          print(f"  窗口 {w}: {name.stdout.strip()}")


source:
  import subprocess, os

  env = {**os.environ, 'DISPLAY': ':99'}

  # 尝试用 Python PIL 直接从 X11 截图
  try:
      from PIL import Image
      import io

      # 用 xwd 截图然后转换
      result = subprocess.run(
          ['bash', '-c', 'DISPLAY=:99 xwd -root | convert xwd:- png:/tmp/alibaba_full.png'],
          capture_output=True, text=True, timeout=10
      )
      print(f"xwd+convert: {result.returncode}, stderr: {result.stderr[:200] if result.stderr else 'none'}")

      if os.path.exists('/tmp/alibaba_full.png'):
          size = os.path.getsize('/tmp/alibaba_full.png')
          img = Image.open('/tmp/alibaba_full.png')
          print(f"✅ 截图成功: {img.size}, {size/1024:.1f} KB")
      else:
          print("❌ 文件未生成")
  except Exception as e:
      print(f"错误: {e}")

source_raw:
  import subprocess, os

  env = {**os.environ, 'DISPLAY': ':99'}

  # 尝试用 Python PIL 直接从 X11 截图
  try:
      from PIL import Image
      import io
      
      # 用 xwd 截图然后转换
      result = subprocess.run(
          ['bash', '-c', 'DISPLAY=:99 xwd -root | convert xwd:- png:/tmp/alibaba_full.png'],
          capture_output=True, text=True, timeout=10
      )
      print(f"xwd+convert: {result.returncode}, stderr: {result.stderr[:200] if result.stderr else 'none'}")
      
      if os.path.exists('/tmp/alibaba_full.png'):
          size = os.path.getsize('/tmp/alibaba_full.png')
          img = Image.open('/tmp/alibaba_full.png')
          print(f"✅ 截图成功: {img.size}, {size/1024:.1f} KB")
      else:
          print("❌ 文件未生成")
  except Exception as e:
      print(f"错误: {e}")


source:
  import subprocess, os

  # 用 gnome-screenshot
  result = subprocess.run(
      ['gnome-screenshot', '-f', '/tmp/alibaba_full.png'],
      capture_output=True, text=True, 
      env={**os.environ, 'DISPLAY': ':99'},
      timeout=10
  )
  print(f"gnome-screenshot: rc={result.returncode}")
  print(f"stderr: {result.stderr[:300] if result.stderr else 'none'}")

  if os.path.exists('/tmp/alibaba_full.png'):
      size = os.path.getsize('/tmp/alibaba_full.png')
      print(f"✅ 文件大小: {size/1024:.1f} KB")
  else:
      print("❌ 文件未生成")

      # 尝试 import (ImageMagick)
      result2 = subprocess.run(
          ['bash', '-c', 'DISPLAY=:99 import -window root -quality 90 /tmp/alibaba_full.jpg'],
          capture_output=True, text=True, timeout=10
      )
      print(f"\nimport 尝试: rc={result2.returncode}")
      print(f"stderr: {result2.stderr[:300] if result2.stderr else 'none'}")

      if os.path.exists('/tmp/alibaba_full.jpg'):
          size = os.path.getsize('/tmp/alibaba_full.jpg')
          from PIL import Image
          img = Image.open('/tmp/alibaba_full.jpg')
          print(f"✅ 截图成功: {img.size}, {size/1024:.1f} KB")

source_raw:
  import subprocess, os

  # 用 gnome-screenshot
  result = subprocess.run(
      ['gnome-screenshot', '-f', '/tmp/alibaba_full.png'],
      capture_output=True, text=True, 
      env={**os.environ, 'DISPLAY': ':99'},
      timeout=10
  )
  print(f"gnome-screenshot: rc={result.returncode}")
  print(f"stderr: {result.stderr[:300] if result.stderr else 'none'}")

  if os.path.exists('/tmp/alibaba_full.png'):
      size = os.path.getsize('/tmp/alibaba_full.png')
      print(f"✅ 文件大小: {size/1024:.1f} KB")
  else:
      print("❌ 文件未生成")
      
      # 尝试 import (ImageMagick)
      result2 = subprocess.run(
          ['bash', '-c', 'DISPLAY=:99 import -window root -quality 90 /tmp/alibaba_full.jpg'],
          capture_output=True, text=True, timeout=10
      )
      print(f"\nimport 尝试: rc={result2.returncode}")
      print(f"stderr: {result2.stderr[:300] if result2.stderr else 'none'}")
      
      if os.path.exists('/tmp/alibaba_full.jpg'):
          size = os.path.getsize('/tmp/alibaba_full.jpg')
          from PIL import Image
          img = Image.open('/tmp/alibaba_full.jpg')
          print(f"✅ 截图成功: {img.size}, {size/1024:.1f} KB")


source:
  import subprocess, os

  # 查看 VNC/display 的实际配置
  result = subprocess.run(['bash', '-c', 'ps aux | grep -E "vnc|Xvfb|Xvnc|chromium|display" | grep -v grep'], 
                         capture_output=True, text=True)
  print("=== 相关进程 ===")
  print(result.stdout)

  # 检查 DISPLAY 环境变量
  result2 = subprocess.run(['bash', '-c', 'echo $DISPLAY'], capture_output=True, text=True)
  print(f"当前 DISPLAY: '{result2.stdout.strip()}'")

  # 检查 X11 sockets
  result3 = subprocess.run(['bash', '-c', 'ls -la /tmp/.X11-unix/'], capture_output=True, text=True)
  print(f"\nX11 sockets:\n{result3.stdout}")

source_raw:
  import subprocess, os

  # 查看 VNC/display 的实际配置
  result = subprocess.run(['bash', '-c', 'ps aux | grep -E "vnc|Xvfb|Xvnc|chromium|display" | grep -v grep'], 
                         capture_output=True, text=True)
  print("=== 相关进程 ===")
  print(result.stdout)

  # 检查 DISPLAY 环境变量
  result2 = subprocess.run(['bash', '-c', 'echo $DISPLAY'], capture_output=True, text=True)
  print(f"当前 DISPLAY: '{result2.stdout.strip()}'")

  # 检查 X11 sockets
  result3 = subprocess.run(['bash', '-c', 'ls -la /tmp/.X11-unix/'], capture_output=True, text=True)
  print(f"\nX11 sockets:\n{result3.stdout}")


source:
  import urllib.request, json, os

  # 尝试通过 AIO 内部 API 获取截图
  ports = [8080, 8088, 8091, 8100, 8200, 8888]
  for port in ports:
      try:
          url = f"http://localhost:{port}"
          req = urllib.request.Request(url, method='GET')
          resp = urllib.request.urlopen(req, timeout=2)
          content_type = resp.headers.get('Content-Type', '')
          data = resp.read(500)
          print(f"Port {port}: status={resp.status}, type={content_type}, data={data[:100]}")
      except Exception as e:
          print(f"Port {port}: {str(e)[:80]}")

source_raw:
  import urllib.request, json, os

  # 尝试通过 AIO 内部 API 获取截图
  ports = [8080, 8088, 8091, 8100, 8200, 8888]
  for port in ports:
      try:
          url = f"http://localhost:{port}"
          req = urllib.request.Request(url, method='GET')
          resp = urllib.request.urlopen(req, timeout=2)
          content_type = resp.headers.get('Content-Type', '')
          data = resp.read(500)
          print(f"Port {port}: status={resp.status}, type={content_type}, data={data[:100]}")
      except Exception as e:
          print(f"Port {port}: {str(e)[:80]}")


source:
  import urllib.request, json

  # 8080 是 AIO 的主服务，看看有没有截图相关的 API
  for path in ['/api', '/screenshot', '/api/screenshot', '/api/browser/screenshot', 
               '/cdp', '/vnc', '/api/v1']:
      try:
          url = f"http://localhost:8080{path}"
          resp = urllib.request.urlopen(url, timeout=2)
          ct = resp.headers.get('Content-Type', '')
          data = resp.read(200)
          print(f"{path}: {resp.status} {ct} -> {data[:150]}")
      except Exception as e:
          print(f"{path}: {str(e)[:80]}")

  # 也看看 VNC 截图
  print("\n--- VNC ---")
  try:
      resp = urllib.request.urlopen("http://localhost:6080/api/framebuffer", timeout=2)
      print(f"VNC framebuffer: {resp.status}")
  except Exception as e:
      print(f"VNC: {str(e)[:80]}")

source_raw:
  import urllib.request, json

  # 8080 是 AIO 的主服务，看看有没有截图相关的 API
  for path in ['/api', '/screenshot', '/api/screenshot', '/api/browser/screenshot', 
               '/cdp', '/vnc', '/api/v1']:
      try:
          url = f"http://localhost:8080{path}"
          resp = urllib.request.urlopen(url, timeout=2)
          ct = resp.headers.get('Content-Type', '')
          data = resp.read(200)
          print(f"{path}: {resp.status} {ct} -> {data[:150]}")
      except Exception as e:
          print(f"{path}: {str(e)[:80]}")

  # 也看看 VNC 截图
  print("\n--- VNC ---")
  try:
      resp = urllib.request.urlopen("http://localhost:6080/api/framebuffer", timeout=2)
      print(f"VNC framebuffer: {resp.status}")
  except Exception as e:
      print(f"VNC: {str(e)[:80]}")


source:
  import urllib.request, os
  from PIL import Image
  import io

  # 从 AIO 内部截图 API 获取
  resp = urllib.request.urlopen("http://localhost:8080/screenshot", timeout=10)
  data = resp.read()
  print(f"截图数据大小: {len(data)/1024:.1f} KB")

  # 保存
  with open('/tmp/alibaba_aio_screenshot.png', 'wb') as f:
      f.write(data)

  img = Image.open(io.BytesIO(data))
  print(f"图片尺寸: {img.size}")
  print(f"图片模式: {img.mode}")

  # 检查是否全黑/全白
  from collections import Counter
  pixels = list(img.getdata())
  sample = Counter(pixels[:1000])
  print(f"前1000像素采样: {sample.most_common(3)}")

  # 也试试带参数
  for endpoint in ['/screenshot?format=jpeg', '/screenshot?quality=90']:
      try:
          resp2 = urllib.request.urlopen(f"http://localhost:8080{endpoint}", timeout=5)
          d = resp2.read()
          print(f"{endpoint}: {len(d)/1024:.1f} KB")
      except Exception as e:
          print(f"{endpoint}: {e}")

source_raw:
  import urllib.request, os
  from PIL import Image
  import io

  # 从 AIO 内部截图 API 获取
  resp = urllib.request.urlopen("http://localhost:8080/screenshot", timeout=10)
  data = resp.read()
  print(f"截图数据大小: {len(data)/1024:.1f} KB")

  # 保存
  with open('/tmp/alibaba_aio_screenshot.png', 'wb') as f:
      f.write(data)

  img = Image.open(io.BytesIO(data))
  print(f"图片尺寸: {img.size}")
  print(f"图片模式: {img.mode}")

  # 检查是否全黑/全白
  from collections import Counter
  pixels = list(img.getdata())
  sample = Counter(pixels[:1000])
  print(f"前1000像素采样: {sample.most_common(3)}")

  # 也试试带参数
  for endpoint in ['/screenshot?format=jpeg', '/screenshot?quality=90']:
      try:
          resp2 = urllib.request.urlopen(f"http://localhost:8080{endpoint}", timeout=5)
          d = resp2.read()
          print(f"{endpoint}: {len(d)/1024:.1f} KB")
      except Exception as e:
          print(f"{endpoint}: {e}")


source:
  import json, asyncio, websockets, base64

  async def take_screenshot():
      # CDP URL from browser_get_info
      cdp_url = "ws://192.168.2.10:8080/cdp"

      try:
          async with websockets.connect(cdp_url, close_timeout=5, open_timeout=5) as ws:
              # 获取页面列表
              await ws.send(json.dumps({"id": 1, "method": "Target.getTargets"}))
              resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
              print(f"Targets: {json.dumps(resp, indent=2)[:500]}")
      except Exception as e:
          print(f"CDP 连接失败: {e}")

      # 尝试直接用 HTTP 的 CDP
      import urllib.request
      try:
          resp = urllib.request.urlopen("http://192.168.2.10:8080/json/list", timeout=5)
          data = json.loads(resp.read())
          print(f"\nCDP targets via HTTP: {json.dumps(data, indent=2)[:500]}")
      except Exception as e:
          print(f"HTTP CDP 失败: {e}")

  asyncio.run(take_screenshot())

source_raw:
  import json, asyncio, websockets, base64

  async def take_screenshot():
      # CDP URL from browser_get_info
      cdp_url = "ws://192.168.2.10:8080/cdp"
      
      try:
          async with websockets.connect(cdp_url, close_timeout=5, open_timeout=5) as ws:
              # 获取页面列表
              await ws.send(json.dumps({"id": 1, "method": "Target.getTargets"}))
              resp = json.loads(await asyncio.wait_for(ws.recv(), timeout=5))
              print(f"Targets: {json.dumps(resp, indent=2)[:500]}")
      except Exception as e:
          print(f"CDP 连接失败: {e}")
          
      # 尝试直接用 HTTP 的 CDP
      import urllib.request
      try:
          resp = urllib.request.urlopen("http://192.168.2.10:8080/json/list", timeout=5)
          data = json.loads(resp.read())
          print(f"\nCDP targets via HTTP: {json.dumps(data, indent=2)[:500]}")
      except Exception as e:
          print(f"HTTP CDP 失败: {e}")

  asyncio.run(take_screenshot())


source:
  # 先确认截图文件的质量
  from PIL import Image
  img = Image.open('/tmp/alibaba_real.png')
  print(f"尺寸: {img.size}")

  # 检查是否有实际内容（非全黑）
  import os
  pixels = list(img.getdata())
  non_black = sum(1 for p in pixels if sum(p) > 30)
  total = len(pixels)
  print(f"非黑色像素: {non_black}/{total} ({non_black/total*100:.1f}%)")
  print(f"文件大小: {os.path.getsize('/tmp/alibaba_real.png')/1024:.1f} KB")

  # 颜色采样
  from collections import Counter
  sample = Counter(pixels[::100]).most_common(5)
  print(f"颜色采样: {sample}")

source_raw:
  # 先确认截图文件的质量
  from PIL import Image
  img = Image.open('/tmp/alibaba_real.png')
  print(f"尺寸: {img.size}")

  # 检查是否有实际内容（非全黑）
  import os
  pixels = list(img.getdata())
  non_black = sum(1 for p in pixels if sum(p) > 30)
  total = len(pixels)
  print(f"非黑色像素: {non_black}/{total} ({non_black/total*100:.1f}%)")
  print(f"文件大小: {os.path.getsize('/tmp/alibaba_real.png')/1024:.1f} KB")

  # 颜色采样
  from collections import Counter
  sample = Counter(pixels[::100]).most_common(5)
  print(f"颜色采样: {sample}")


source:
  # 在沙盒内启动一个简单的 HTTP 服务来提供文件下载
  import http.server
  import threading
  import os

  PORT = 9876

  class Handler(http.server.SimpleHTTPRequestHandler):
      def __init__(self, *args, **kwargs):
          super().__init__(*args, directory='/tmp', **kwargs)

  httpd = http.server.HTTPServer(('0.0.0.0', PORT), Handler)
  t = threading.Thread(target=httpd.serve_forever, daemon=True)
  t.start()
  print(f"✅ HTTP 服务已启动在端口 {PORT}")
  print(f"📁 文件: /tmp/alibaba_real.png ({os.path.getsize('/tmp/alibaba_real.png')/1024:.1f} KB)")

  # 保持运行一段时间
  import time
  time.sleep(120)

source_raw:
  # 在沙盒内启动一个简单的 HTTP 服务来提供文件下载
  import http.server
  import threading
  import os

  PORT = 9876

  class Handler(http.server.SimpleHTTPRequestHandler):
      def __init__(self, *args, **kwargs):
          super().__init__(*args, directory='/tmp', **kwargs)

  httpd = http.server.HTTPServer(('0.0.0.0', PORT), Handler)
  t = threading.Thread(target=httpd.serve_forever, daemon=True)
  t.start()
  print(f"✅ HTTP 服务已启动在端口 {PORT}")
  print(f"📁 文件: /tmp/alibaba_real.png ({os.path.getsize('/tmp/alibaba_real.png')/1024:.1f} KB)")

  # 保持运行一段时间
  import time
  time.sleep(120)


source:
  from pptx import Presentation
  from pptx.util import Inches, Pt, Emu
  from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
  from pptx.dml.color import RGBColor
  from pptx.enum.shapes import MSO_SHAPE
  import os

  # Create presentation (16:9)
  prs = Presentation()
  prs.slide_width = Inches(13.333)
  prs.slide_height = Inches(7.5)

  # Color palette - "Ocean Gradient"
  PRIMARY = RGBColor(0x06, 0x5A, 0x82)
  SECONDARY = RGBColor(0x1C, 0x72, 0x93)
  ACCENT = RGBColor(0x21, 0x29, 0x5C)
  WHITE = RGBColor(0xFF, 0xFF, 0xFF)
  LIGHT_BG = RGBColor(0xF0, 0xF4, 0xF8)
  DARK_TEXT = RGBColor(0x1A, 0x1A, 0x2E)
  GRAY = RGBColor(0x66, 0x66, 0x66)

  def add_filled_shape(slide, left, top, width, height, color, shape=MSO_SHAPE.ROUNDED_RECTANGLE):
      shape = slide.shapes.add_shape(shape, left, top, width, height)
      shape.fill.solid()
      shape.fill.fore_color.rgb = color
      shape.line.fill.background()
      return shape

  def add_textbox(slide, left, top, width, height, text, font_size=18, bold=False, color=DARK_TEXT, alignment=PP_ALIGN.LEFT, font_name="Calibri"):
      txBox = slide.shapes.add_textbox(left, top, width, height)
      tf = txBox.text_frame
      tf.word_wrap = True
      p = tf.paragraphs[0]
      p.text = text
      p.font.size = Pt(font_size)
      p.font.bold = bold
      p.font.color.rgb = color
      p.font.name = font_name
      p.alignment = alignment
      return txBox

  # ==================== SLIDE 1: Title ====================
  slide1 = prs.slides.add_slide(prs.slide_layouts[6])  # blank
  # Dark background
  add_filled_shape(slide1, Inches(0), Inches(0), prs.slide_width, prs.slide_height, ACCENT)

  # Accent bar
  add_filled_shape(slide1, Inches(1), Inches(2.8), Inches(0.3), Inches(2.0), RGBColor(0x02, 0xC3, 0x9A))

  add_textbox(slide1, Inches(1.6), Inches(2.5), Inches(10), Inches(1.5),
              "AI 驱动的未来", font_size=48, bold=True, color=WHITE, font_name="Georgia")

  add_textbox(slide1, Inches(1.6), Inches(3.8), Inches(10), Inches(1),
              "探索人工智能如何重塑我们的工作与生活方式", font_size=22, color=RGBColor(0xC0, 0xD8, 0xE8))

  add_textbox(slide1, Inches(1.6), Inches(5.5), Inches(5), Inches(0.8),
              "2026.06  由 Qwen Assistant 生成", font_size=14, color=GRAY)

  # ==================== SLIDE 2: Overview ====================
  slide2 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide2, Inches(0), Inches(0), prs.slide_width, prs.slide_height, LIGHT_BG)

  # Title
  add_textbox(slide2, Inches(1), Inches(0.6), Inches(11), Inches(1),
              "核心亮点", font_size=40, bold=True, color=PRIMARY, font_name="Georgia")

  # Accent line under title
  add_filled_shape(slide2, Inches(1), Inches(1.4), Inches(1.2), Inches(0.08), PRIMARY)

  # Three cards
  card_data = [
      ("🤖", "智能自动化", "AI Agent 自主完成复杂任务，提升 10x 工作效率"),
      ("🎨", "多模态交互", "文本、图像、语音、视频全面融合，打破沟通壁垒"),
      ("🌐", "全球化部署", "多云架构 + 边缘推理，服务覆盖全球 200+ 国家"),
  ]

  for i, (icon, title, desc) in enumerate(card_data):
      cx = Inches(1.2 + i * 3.8)
      cy = Inches(2.2)
      cw = Inches(3.4)
      ch = Inches(4.2)

      # Card background
      card = add_filled_shape(slide2, cx, cy, cw, ch, WHITE)
      card.shadow.inherit = False

      # Icon circle
      circle = add_filled_shape(slide2, cx + Inches(0.3), Inches(2.8), Inches(1), Inches(1),
                                RGBColor(0xE8, 0xF4, 0xFD), MSO_SHAPE.OVAL)
      add_textbox(slide2, cx + Inches(0.3), Inches(2.8), Inches(1), Inches(1),
                  icon, font_size=36, alignment=PP_ALIGN.CENTER)

      # Title and desc
      add_textbox(slide2, cx + Inches(0.3), Inches(4.0), cw - Inches(0.6), Inches(0.8),
                  title, font_size=22, bold=True, color=ACCENT)
      add_textbox(slide2, cx + Inches(0.3), Inches(4.8), cw - Inches(0.6), Inches(1.2),
                  desc, font_size=14, color=GRAY)

  # ==================== SLIDE 3: Data ====================
  slide3 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide3, Inches(0), Inches(0), prs.slide_width, prs.slide_height, WHITE)

  add_textbox(slide3, Inches(1), Inches(0.6), Inches(11), Inches(1),
              "关键数据", font_size=40, bold=True, color=PRIMARY, font_name="Georgia")
  add_filled_shape(slide3, Inches(1), Inches(1.4), Inches(1.2), Inches(0.08), PRIMARY)

  stats = [
      ("87%", "企业已部署 AI"),
      ("3.5x", "平均效率提升"),
      ("$1.8T", "2026 市场规模"),
      ("92%", "用户满意度"),
  ]

  for i, (number, label) in enumerate(stats):
      sx = Inches(1.5 + i * 3.0)
      sy = Inches(2.5)

      # Number
      add_textbox(slide3, sx, sy, Inches(2.5), Inches(1.5),
                  number, font_size=54, bold=True, color=PRIMARY, alignment=PP_ALIGN.CENTER)
      # Label
      add_textbox(slide3, sx, sy + Inches(1.3), Inches(2.5), Inches(0.8),
                  label, font_size=16, color=GRAY, alignment=PP_ALIGN.CENTER)

      # Divider line (except last)
      if i < len(stats) - 1:
          add_filled_shape(slide3, sx + Inches(2.2), sy + Inches(0.2), Inches(0.04), Inches(1.8),
                           RGBColor(0xDD, 0xDD, 0xDD))

  # ==================== SLIDE 4: Thank You ====================
  slide4 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide4, Inches(0), Inches(0), prs.slide_width, prs.slide_height, ACCENT)

  add_filled_shape(slide4, Inches(1), Inches(2.5), Inches(0.3), Inches(2.5), RGBColor(0x02, 0xC3, 0x9A))

  add_textbox(slide4, Inches(1.6), Inches(2.2), Inches(10), Inches(1.5),
              "感谢观看", font_size=52, bold=True, color=WHITE, font_name="Georgia")

  add_textbox(slide4, Inches(1.6), Inches(3.8), Inches(10), Inches(1),
              "让我们一起构建更智能的未来", font_size=24, color=RGBColor(0xC0, 0xD8, 0xE8))

  add_textbox(slide4, Inches(1.6), Inches(5.8), Inches(5), Inches(0.8),
              "Qwen Assistant  ·  2026", font_size=14, color=GRAY)

  # Save
  output_path = "/tmp/demo_ai_future.pptx"
  prs.save(output_path)
  print(f"✅ PPT saved to: {output_path}")
  print(f"File size: {os.path.getsize(output_path)} bytes")
  print(f"Total slides: {len(prs.slides)}")

source_raw:
  from pptx import Presentation
  from pptx.util import Inches, Pt, Emu
  from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
  from pptx.dml.color import RGBColor
  from pptx.enum.shapes import MSO_SHAPE
  import os

  # Create presentation (16:9)
  prs = Presentation()
  prs.slide_width = Inches(13.333)
  prs.slide_height = Inches(7.5)

  # Color palette - "Ocean Gradient"
  PRIMARY = RGBColor(0x06, 0x5A, 0x82)
  SECONDARY = RGBColor(0x1C, 0x72, 0x93)
  ACCENT = RGBColor(0x21, 0x29, 0x5C)
  WHITE = RGBColor(0xFF, 0xFF, 0xFF)
  LIGHT_BG = RGBColor(0xF0, 0xF4, 0xF8)
  DARK_TEXT = RGBColor(0x1A, 0x1A, 0x2E)
  GRAY = RGBColor(0x66, 0x66, 0x66)

  def add_filled_shape(slide, left, top, width, height, color, shape=MSO_SHAPE.ROUNDED_RECTANGLE):
      shape = slide.shapes.add_shape(shape, left, top, width, height)
      shape.fill.solid()
      shape.fill.fore_color.rgb = color
      shape.line.fill.background()
      return shape

  def add_textbox(slide, left, top, width, height, text, font_size=18, bold=False, color=DARK_TEXT, alignment=PP_ALIGN.LEFT, font_name="Calibri"):
      txBox = slide.shapes.add_textbox(left, top, width, height)
      tf = txBox.text_frame
      tf.word_wrap = True
      p = tf.paragraphs[0]
      p.text = text
      p.font.size = Pt(font_size)
      p.font.bold = bold
      p.font.color.rgb = color
      p.font.name = font_name
      p.alignment = alignment
      return txBox

  # ==================== SLIDE 1: Title ====================
  slide1 = prs.slides.add_slide(prs.slide_layouts[6])  # blank
  # Dark background
  add_filled_shape(slide1, Inches(0), Inches(0), prs.slide_width, prs.slide_height, ACCENT)

  # Accent bar
  add_filled_shape(slide1, Inches(1), Inches(2.8), Inches(0.3), Inches(2.0), RGBColor(0x02, 0xC3, 0x9A))

  add_textbox(slide1, Inches(1.6), Inches(2.5), Inches(10), Inches(1.5),
              "AI 驱动的未来", font_size=48, bold=True, color=WHITE, font_name="Georgia")

  add_textbox(slide1, Inches(1.6), Inches(3.8), Inches(10), Inches(1),
              "探索人工智能如何重塑我们的工作与生活方式", font_size=22, color=RGBColor(0xC0, 0xD8, 0xE8))

  add_textbox(slide1, Inches(1.6), Inches(5.5), Inches(5), Inches(0.8),
              "2026.06  由 Qwen Assistant 生成", font_size=14, color=GRAY)

  # ==================== SLIDE 2: Overview ====================
  slide2 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide2, Inches(0), Inches(0), prs.slide_width, prs.slide_height, LIGHT_BG)

  # Title
  add_textbox(slide2, Inches(1), Inches(0.6), Inches(11), Inches(1),
              "核心亮点", font_size=40, bold=True, color=PRIMARY, font_name="Georgia")

  # Accent line under title
  add_filled_shape(slide2, Inches(1), Inches(1.4), Inches(1.2), Inches(0.08), PRIMARY)

  # Three cards
  card_data = [
      ("🤖", "智能自动化", "AI Agent 自主完成复杂任务，提升 10x 工作效率"),
      ("🎨", "多模态交互", "文本、图像、语音、视频全面融合，打破沟通壁垒"),
      ("🌐", "全球化部署", "多云架构 + 边缘推理，服务覆盖全球 200+ 国家"),
  ]

  for i, (icon, title, desc) in enumerate(card_data):
      cx = Inches(1.2 + i * 3.8)
      cy = Inches(2.2)
      cw = Inches(3.4)
      ch = Inches(4.2)
      
      # Card background
      card = add_filled_shape(slide2, cx, cy, cw, ch, WHITE)
      card.shadow.inherit = False
      
      # Icon circle
      circle = add_filled_shape(slide2, cx + Inches(0.3), Inches(2.8), Inches(1), Inches(1),
                                RGBColor(0xE8, 0xF4, 0xFD), MSO_SHAPE.OVAL)
      add_textbox(slide2, cx + Inches(0.3), Inches(2.8), Inches(1), Inches(1),
                  icon, font_size=36, alignment=PP_ALIGN.CENTER)
      
      # Title and desc
      add_textbox(slide2, cx + Inches(0.3), Inches(4.0), cw - Inches(0.6), Inches(0.8),
                  title, font_size=22, bold=True, color=ACCENT)
      add_textbox(slide2, cx + Inches(0.3), Inches(4.8), cw - Inches(0.6), Inches(1.2),
                  desc, font_size=14, color=GRAY)

  # ==================== SLIDE 3: Data ====================
  slide3 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide3, Inches(0), Inches(0), prs.slide_width, prs.slide_height, WHITE)

  add_textbox(slide3, Inches(1), Inches(0.6), Inches(11), Inches(1),
              "关键数据", font_size=40, bold=True, color=PRIMARY, font_name="Georgia")
  add_filled_shape(slide3, Inches(1), Inches(1.4), Inches(1.2), Inches(0.08), PRIMARY)

  stats = [
      ("87%", "企业已部署 AI"),
      ("3.5x", "平均效率提升"),
      ("$1.8T", "2026 市场规模"),
      ("92%", "用户满意度"),
  ]

  for i, (number, label) in enumerate(stats):
      sx = Inches(1.5 + i * 3.0)
      sy = Inches(2.5)
      
      # Number
      add_textbox(slide3, sx, sy, Inches(2.5), Inches(1.5),
                  number, font_size=54, bold=True, color=PRIMARY, alignment=PP_ALIGN.CENTER)
      # Label
      add_textbox(slide3, sx, sy + Inches(1.3), Inches(2.5), Inches(0.8),
                  label, font_size=16, color=GRAY, alignment=PP_ALIGN.CENTER)
      
      # Divider line (except last)
      if i < len(stats) - 1:
          add_filled_shape(slide3, sx + Inches(2.2), sy + Inches(0.2), Inches(0.04), Inches(1.8),
                           RGBColor(0xDD, 0xDD, 0xDD))

  # ==================== SLIDE 4: Thank You ====================
  slide4 = prs.slides.add_slide(prs.slide_layouts[6])
  add_filled_shape(slide4, Inches(0), Inches(0), prs.slide_width, prs.slide_height, ACCENT)

  add_filled_shape(slide4, Inches(1), Inches(2.5), Inches(0.3), Inches(2.5), RGBColor(0x02, 0xC3, 0x9A))

  add_textbox(slide4, Inches(1.6), Inches(2.2), Inches(10), Inches(1.5),
              "感谢观看", font_size=52, bold=True, color=WHITE, font_name="Georgia")

  add_textbox(slide4, Inches(1.6), Inches(3.8), Inches(10), Inches(1),
              "让我们一起构建更智能的未来", font_size=24, color=RGBColor(0xC0, 0xD8, 0xE8))

  add_textbox(slide4, Inches(1.6), Inches(5.8), Inches(5), Inches(0.8),
              "Qwen Assistant  ·  2026", font_size=14, color=GRAY)

  # Save
  output_path = "/tmp/demo_ai_future.pptx"
  prs.save(output_path)
  print(f"✅ PPT saved to: {output_path}")
  print(f"File size: {os.path.getsize(output_path)} bytes")
  print(f"Total slides: {len(prs.slides)}")


source:
  # Check available Python visualization libraries
  import subprocess, sys

  for pkg in ['matplotlib', 'pillow', 'diagrams', 'graphviz', 'pydot', 'drawsvg']:
      try:
          mod = __import__(pkg)
          print(f"✅ {pkg}: {getattr(mod, '__version__', 'installed')}")
      except ImportError:
          print(f"❌ {pkg}: not available")

source_raw:
  # Check available Python visualization libraries
  import subprocess, sys

  for pkg in ['matplotlib', 'pillow', 'diagrams', 'graphviz', 'pydot', 'drawsvg']:
      try:
          mod = __import__(pkg)
          print(f"✅ {pkg}: {getattr(mod, '__version__', 'installed')}")
      except ImportError:
          print(f"❌ {pkg}: not available")


source:
  import matplotlib.pyplot as plt
  import matplotlib.patches as patches
  from matplotlib.patches import FancyArrowPatch, FancyBboxPatch, Rectangle
  import matplotlib.patheffects as pe

  plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS', 'WenQuanYi Micro Hei']
  plt.rcParams['axes.unicode_minus'] = False

  fig, ax = plt.subplots(figsize=(28, 32), facecolor='#f0f4f8')
  ax.set_xlim(0, 28)
  ax.set_ylim(0, 32)
  ax.axis('off')

  def draw_box(ax, x, y, w, h, text, facecolor, edgecolor='#2c3e50', fontsize=10, bold=False, subtext=None, title=None):
      """绘制一个带样式的盒子"""
      box = FancyBboxPatch(
          (x - w/2, y - h/2), w, h,
          boxstyle="round,pad=0.15",
          facecolor=facecolor,
          edgecolor=edgecolor,
          linewidth=1.5,
          zorder=2
      )
      ax.add_patch(box)

      if title:
          ax.text(x, y + h*0.25, title, 
                  ha='center', va='center', 
                  fontsize=fontsize, fontweight='bold', color='white',
                  zorder=3, 
                  path_effects=[pe.withStroke(linewidth=1, foreground='#333')])
          ax.text(x, y - h*0.15, subtext if subtext else '',
                  ha='center', va='center',
                  fontsize=fontsize-1, color='#ecf0f1',
                  zorder=3)
      else:
          ax.text(x, y, text,
                  ha='center', va='center',
                  fontsize=fontsize, fontweight='bold' if bold else 'normal',
                  color='white',
                  zorder=3,
                  path_effects=[pe.withStroke(linewidth=1, foreground='#333')])

  def draw_dashed_line(ax, x1, y1, x2, y2, color='#e74c3c', label=''):
      """绘制虚线箭头"""
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=1.5, 
                                 linestyle='dashed', connectionstyle='arc3,rad=0.1'))
      if label:
          mid_x, mid_y = (x1+x2)/2, (y1+y2)/2
          ax.text(mid_x + 1.5, mid_y, label, fontsize=7, color=color, 
                  ha='center', va='center',
                  bbox=dict(boxstyle='round,pad=0.2', facecolor='white', edgecolor=color, alpha=0.8))

  def draw_arrow(ax, x1, y1, x2, y2, color='#34495e', lw=1.5):
      """绘制实线箭头"""
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=lw, 
                                 connectionstyle='arc3,rad=0'))

  # ============ 标题 ============
  ax.text(14, 30.5, '千问模型团队组织架构图', fontsize=26, fontweight='bold',
          color='#2c3e50', ha='center', va='center',
          path_effects=[pe.withStroke(linewidth=2, foreground='white')])
  ax.text(14, 29.8, 'Qwen Model Team — Organizational Architecture', fontsize=13,
          color='#7f8c8d', ha='center', va='center', style='italic')

  # ============ 资源协调小组（右上角）============
  coord_box = FancyBboxPatch(
      (19.5, 27.3), 8, 2.4,
      boxstyle="round,pad=0.2",
      facecolor='#f39c12',
      edgecolor='#d35400',
      linewidth=2.5,
      zorder=2, linestyle='dashed'
  )
  ax.add_patch(coord_box)
  ax.text(23.5, 29.0, '🔑 资源协调小组', fontsize=13, fontweight='bold',
          color='white', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=1.5, foreground='#333')])
  ax.text(23.5, 28.3, '模型能力方向 & 算力资源统筹', fontsize=10,
          color='#fff8dc', ha='center', va='center', zorder=3)
  ax.text(23.5, 27.75, 'CEO Eddie + CTO 范禹 + 刘大一恒 (P9)', fontsize=9.5,
          color='#fff8dc', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=0.8, foreground='#d35400')])

  # ============ CEO ============
  draw_box(ax, 4, 25.5, 5, 2.2, '', '#e74c3c', fontsize=13,
           title='CEO Eddie', subtext='资源协调小组核心')

  # ============ CTO ============
  draw_box(ax, 13, 21.5, 5.5, 2.2, '', '#3498db', fontsize=13,
           title='范禹 (CTO)', subtext='资源协调小组核心 · 管线协调')

  # 箭头: CEO -> CTO
  draw_arrow(ax, 4, 24.4, 13, 22.6, color='#7f8c8d', lw=2.5)

  # ============ CEO 到 资源协调小组的虚线 ============
  draw_dashed_line(ax, 6.5, 25.5, 19.5, 28.8, color='#e74c3c', label='牵头')

  # ============ 三大技术板块 + 垂直Agent大组 ============

  # --- 板块1: 基础模型研发 ---
  draw_box(ax, 4.5, 17.5, 6.5, 2.2, '', '#2ecc71', fontsize=12,
           title='刘大一恒 (P9)', subtext='基础模型研发 · 资源协调小组核心')
  ax.text(4.5, 15.5, '板块 1: 基础模型研发', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  # 子团队
  teams_1 = [
      ('预训练', 1.0),
      ('多模态模型\nOmni/VL/Image', 4.5),
      ('后训练\nSFT/DPO', 8.0),
  ]
  for name, cx in teams_1:
      draw_box(ax, cx, 13.5, 3.2, 1.8, name, '#27ae60', fontsize=9)

  # 箭头
  draw_arrow(ax, 4.5, 16.4, 1.0, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 16.4, 4.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 16.4, 8.0, 14.4, color='#95a5a6', lw=1)

  # --- 板块2: 前沿能力 ---
  draw_box(ax, 13, 17.5, 6, 2.2, '', '#2ecc71', fontsize=12,
           title='周昊 (P10)', subtext='前沿能力')
  ax.text(13, 15.5, '板块 2: 前沿能力', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  teams_2 = [
      ('Coding 专项', 10.5),
      ('混训RL框架\n和算法 (含Agent底座)', 15.5),
  ]
  for name, cx in teams_2:
      draw_box(ax, cx, 13.5, 3.5, 1.9, name, '#27ae60', fontsize=8.5)

  draw_arrow(ax, 13, 16.4, 10.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 13, 16.4, 15.5, 14.4, color='#95a5a6', lw=1)

  # --- 板块3: 评测及交付 ---
  draw_box(ax, 21.5, 17.5, 5.5, 2.2, '', '#2ecc71', fontsize=12,
           title='黄斐 (P8)', subtext='评测及交付')
  ax.text(21.5, 15.5, '板块 3: 评测及交付', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  teams_3 = [
      ('评测/RM', 19.0),
      ('模型交付', 21.5),
      ('多语言', 24.0),
  ]
  for name, cx in teams_3:
      draw_box(ax, cx, 13.5, 2.8, 1.6, name, '#27ae60', fontsize=9)

  draw_arrow(ax, 21.5, 16.4, 19.0, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 16.4, 21.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 16.4, 24.0, 14.4, color='#95a5a6', lw=1)

  # --- 板块4: 垂直Agent大组 ---
  draw_box(ax, 13, 9.5, 16, 2.5, '', '#9b59b6', fontsize=13,
           title='板块 4: 垂直 Agent 大组', subtext='范禹直管 · 各组长直接面向行业')
  ax.text(13, 7.5, '范禹 (CTO) 直管协调 | 各小组直接面向垂直行业真实问题', fontsize=10,
          color='#8e44ad', ha='center', va='center', style='italic')

  teams_4 = [
      ('金融 Agent\n陈蓓 (P9)', 5.5),
      ('白领 Agent\n待定', 9.5),
      ('互联网 to C\n待定', 13.5),
      ('医疗 Agent\n待定', 17.5),
      ('专业研发 Agent\n待定', 21.5),
  ]
  for name, cx in teams_4:
      fc = '#8e44ad' if '陈蓓' in name else '#b57edc'
      draw_box(ax, cx, 4.5, 3.2, 1.8, name, fc, fontsize=8.5)

  # CTO 到板块4的箭头
  draw_arrow(ax, 13, 20.3, 13, 10.75, color='#8e44ad', lw=2.5)

  # 垂直组内部虚线
  for cx in [5.5, 9.5, 13.5, 17.5, 21.5]:
      draw_arrow(ax, 13, 8.3, cx, 5.4, color='#c39bd3', lw=1.2)

  # ============ 资源协调小组虚线连接 ============
  # Fanyu -> 协调小组
  draw_dashed_line(ax, 15.75, 22.0, 19.5, 28.0, color='#f39c12')

  # ============ CEO 到 协调小组的连接 ============
  # Already drawn above

  # ============ 图例 ============
  legend_y = 0.8
  ax.text(1, legend_y + 1.2, '图例说明', fontsize=12, fontweight='bold', color='#2c3e50')

  legend_items = [
      ('#e74c3c', 'CEO / 最高决策者', '#7f8c8d'),
      ('#3498db', 'CTO / 技术总负责人', '#7f8c8d'),
      ('#2ecc71', '技术板块负责人', '#7f8c8d'),
      ('#9b59b6', '垂直 Agent 大组方向', '#7f8c8d'),
      ('#f39c12', '资源协调小组 (虚线连接 = 协调关系)', '#7f8c8d'),
  ]

  for i, (color, label, _) in enumerate(legend_items):
      legend_box = Rectangle(
          (1, legend_y + 0.7 - i * 0.4), 0.65, 0.35,
          facecolor=color, edgecolor='#2c3e50', linewidth=1
      )
      ax.add_patch(legend_box)
      ax.text(2.0, legend_y + 0.88 - i * 0.4, label, fontsize=9, color='#2c3e50', va='center')

  # 右侧说明文字
  ax.text(25.5, legend_y + 2.5, '关键设计说明', fontsize=11, fontweight='bold', color='#2c3e50')
  points = [
      '• 垂直Agent大组不设总负责人，',
      '  各组直接面向行业真实问题',
      '• 范禹更多承担管线协调角色，',
      '  而非垂直管理',
      '• 资源协调小组负责跨板块的',
      '  算力资源分配与模型能力规划',
      '• 大版本合版由刘大一恒总控，',
      '  按项目优先级融合领域Teacher',
  ]
  for i, p in enumerate(points):
      ax.text(24.5, 2.2 - i * 0.32, p, fontsize=8.5, color='#555')

  # ============ 大版本合版流程箭头 ============
  draw_dashed_line(ax, 8, 14.4, 15.5, 14.4, color='#f39c12', label='合版协同')

  # ============ 评测交付门禁箭头 ============
  ax.annotate('', xy=(21, 13), xytext=(16, 13),
              arrowprops=dict(arrowstyle='<->', color='#e74c3c', lw=1.5, linestyle='dashed'))
  ax.text(18.5, 12.4, '交付门禁 ←→ 评测', fontsize=8, color='#e74c3c', ha='center')

  # ============ 保存 ============
  fig.tight_layout()
  fig.savefig('/tmp/千问模型团队组织架构图.png', dpi=150, facecolor='#f0f4f8', 
              bbox_inches='tight', pad_inches=0.3)
  print("✅ 架构图已保存到 /tmp/千问模型团队组织架构图.png")
  print(f"图像尺寸: {fig.get_figwidth()}x{fig.get_figheight()} inches")

source_raw:
  import matplotlib.pyplot as plt
  import matplotlib.patches as patches
  from matplotlib.patches import FancyArrowPatch, FancyBboxPatch, Rectangle
  import matplotlib.patheffects as pe

  plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS', 'WenQuanYi Micro Hei']
  plt.rcParams['axes.unicode_minus'] = False

  fig, ax = plt.subplots(figsize=(28, 32), facecolor='#f0f4f8')
  ax.set_xlim(0, 28)
  ax.set_ylim(0, 32)
  ax.axis('off')

  def draw_box(ax, x, y, w, h, text, facecolor, edgecolor='#2c3e50', fontsize=10, bold=False, subtext=None, title=None):
      """绘制一个带样式的盒子"""
      box = FancyBboxPatch(
          (x - w/2, y - h/2), w, h,
          boxstyle="round,pad=0.15",
          facecolor=facecolor,
          edgecolor=edgecolor,
          linewidth=1.5,
          zorder=2
      )
      ax.add_patch(box)
      
      if title:
          ax.text(x, y + h*0.25, title, 
                  ha='center', va='center', 
                  fontsize=fontsize, fontweight='bold', color='white',
                  zorder=3, 
                  path_effects=[pe.withStroke(linewidth=1, foreground='#333')])
          ax.text(x, y - h*0.15, subtext if subtext else '',
                  ha='center', va='center',
                  fontsize=fontsize-1, color='#ecf0f1',
                  zorder=3)
      else:
          ax.text(x, y, text,
                  ha='center', va='center',
                  fontsize=fontsize, fontweight='bold' if bold else 'normal',
                  color='white',
                  zorder=3,
                  path_effects=[pe.withStroke(linewidth=1, foreground='#333')])

  def draw_dashed_line(ax, x1, y1, x2, y2, color='#e74c3c', label=''):
      """绘制虚线箭头"""
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=1.5, 
                                 linestyle='dashed', connectionstyle='arc3,rad=0.1'))
      if label:
          mid_x, mid_y = (x1+x2)/2, (y1+y2)/2
          ax.text(mid_x + 1.5, mid_y, label, fontsize=7, color=color, 
                  ha='center', va='center',
                  bbox=dict(boxstyle='round,pad=0.2', facecolor='white', edgecolor=color, alpha=0.8))

  def draw_arrow(ax, x1, y1, x2, y2, color='#34495e', lw=1.5):
      """绘制实线箭头"""
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=lw, 
                                 connectionstyle='arc3,rad=0'))

  # ============ 标题 ============
  ax.text(14, 30.5, '千问模型团队组织架构图', fontsize=26, fontweight='bold',
          color='#2c3e50', ha='center', va='center',
          path_effects=[pe.withStroke(linewidth=2, foreground='white')])
  ax.text(14, 29.8, 'Qwen Model Team — Organizational Architecture', fontsize=13,
          color='#7f8c8d', ha='center', va='center', style='italic')

  # ============ 资源协调小组（右上角）============
  coord_box = FancyBboxPatch(
      (19.5, 27.3), 8, 2.4,
      boxstyle="round,pad=0.2",
      facecolor='#f39c12',
      edgecolor='#d35400',
      linewidth=2.5,
      zorder=2, linestyle='dashed'
  )
  ax.add_patch(coord_box)
  ax.text(23.5, 29.0, '🔑 资源协调小组', fontsize=13, fontweight='bold',
          color='white', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=1.5, foreground='#333')])
  ax.text(23.5, 28.3, '模型能力方向 & 算力资源统筹', fontsize=10,
          color='#fff8dc', ha='center', va='center', zorder=3)
  ax.text(23.5, 27.75, 'CEO Eddie + CTO 范禹 + 刘大一恒 (P9)', fontsize=9.5,
          color='#fff8dc', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=0.8, foreground='#d35400')])

  # ============ CEO ============
  draw_box(ax, 4, 25.5, 5, 2.2, '', '#e74c3c', fontsize=13,
           title='CEO Eddie', subtext='资源协调小组核心')

  # ============ CTO ============
  draw_box(ax, 13, 21.5, 5.5, 2.2, '', '#3498db', fontsize=13,
           title='范禹 (CTO)', subtext='资源协调小组核心 · 管线协调')

  # 箭头: CEO -> CTO
  draw_arrow(ax, 4, 24.4, 13, 22.6, color='#7f8c8d', lw=2.5)

  # ============ CEO 到 资源协调小组的虚线 ============
  draw_dashed_line(ax, 6.5, 25.5, 19.5, 28.8, color='#e74c3c', label='牵头')

  # ============ 三大技术板块 + 垂直Agent大组 ============

  # --- 板块1: 基础模型研发 ---
  draw_box(ax, 4.5, 17.5, 6.5, 2.2, '', '#2ecc71', fontsize=12,
           title='刘大一恒 (P9)', subtext='基础模型研发 · 资源协调小组核心')
  ax.text(4.5, 15.5, '板块 1: 基础模型研发', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  # 子团队
  teams_1 = [
      ('预训练', 1.0),
      ('多模态模型\nOmni/VL/Image', 4.5),
      ('后训练\nSFT/DPO', 8.0),
  ]
  for name, cx in teams_1:
      draw_box(ax, cx, 13.5, 3.2, 1.8, name, '#27ae60', fontsize=9)

  # 箭头
  draw_arrow(ax, 4.5, 16.4, 1.0, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 16.4, 4.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 16.4, 8.0, 14.4, color='#95a5a6', lw=1)

  # --- 板块2: 前沿能力 ---
  draw_box(ax, 13, 17.5, 6, 2.2, '', '#2ecc71', fontsize=12,
           title='周昊 (P10)', subtext='前沿能力')
  ax.text(13, 15.5, '板块 2: 前沿能力', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  teams_2 = [
      ('Coding 专项', 10.5),
      ('混训RL框架\n和算法 (含Agent底座)', 15.5),
  ]
  for name, cx in teams_2:
      draw_box(ax, cx, 13.5, 3.5, 1.9, name, '#27ae60', fontsize=8.5)

  draw_arrow(ax, 13, 16.4, 10.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 13, 16.4, 15.5, 14.4, color='#95a5a6', lw=1)

  # --- 板块3: 评测及交付 ---
  draw_box(ax, 21.5, 17.5, 5.5, 2.2, '', '#2ecc71', fontsize=12,
           title='黄斐 (P8)', subtext='评测及交付')
  ax.text(21.5, 15.5, '板块 3: 评测及交付', fontsize=11, fontweight='bold',
          color='#27ae60', ha='center', va='center')

  teams_3 = [
      ('评测/RM', 19.0),
      ('模型交付', 21.5),
      ('多语言', 24.0),
  ]
  for name, cx in teams_3:
      draw_box(ax, cx, 13.5, 2.8, 1.6, name, '#27ae60', fontsize=9)

  draw_arrow(ax, 21.5, 16.4, 19.0, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 16.4, 21.5, 14.4, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 16.4, 24.0, 14.4, color='#95a5a6', lw=1)

  # --- 板块4: 垂直Agent大组 ---
  draw_box(ax, 13, 9.5, 16, 2.5, '', '#9b59b6', fontsize=13,
           title='板块 4: 垂直 Agent 大组', subtext='范禹直管 · 各组长直接面向行业')
  ax.text(13, 7.5, '范禹 (CTO) 直管协调 | 各小组直接面向垂直行业真实问题', fontsize=10,
          color='#8e44ad', ha='center', va='center', style='italic')

  teams_4 = [
      ('金融 Agent\n陈蓓 (P9)', 5.5),
      ('白领 Agent\n待定', 9.5),
      ('互联网 to C\n待定', 13.5),
      ('医疗 Agent\n待定', 17.5),
      ('专业研发 Agent\n待定', 21.5),
  ]
  for name, cx in teams_4:
      fc = '#8e44ad' if '陈蓓' in name else '#b57edc'
      draw_box(ax, cx, 4.5, 3.2, 1.8, name, fc, fontsize=8.5)

  # CTO 到板块4的箭头
  draw_arrow(ax, 13, 20.3, 13, 10.75, color='#8e44ad', lw=2.5)

  # 垂直组内部虚线
  for cx in [5.5, 9.5, 13.5, 17.5, 21.5]:
      draw_arrow(ax, 13, 8.3, cx, 5.4, color='#c39bd3', lw=1.2)

  # ============ 资源协调小组虚线连接 ============
  # Fanyu -> 协调小组
  draw_dashed_line(ax, 15.75, 22.0, 19.5, 28.0, color='#f39c12')

  # ============ CEO 到 协调小组的连接 ============
  # Already drawn above

  # ============ 图例 ============
  legend_y = 0.8
  ax.text(1, legend_y + 1.2, '图例说明', fontsize=12, fontweight='bold', color='#2c3e50')

  legend_items = [
      ('#e74c3c', 'CEO / 最高决策者', '#7f8c8d'),
      ('#3498db', 'CTO / 技术总负责人', '#7f8c8d'),
      ('#2ecc71', '技术板块负责人', '#7f8c8d'),
      ('#9b59b6', '垂直 Agent 大组方向', '#7f8c8d'),
      ('#f39c12', '资源协调小组 (虚线连接 = 协调关系)', '#7f8c8d'),
  ]

  for i, (color, label, _) in enumerate(legend_items):
      legend_box = Rectangle(
          (1, legend_y + 0.7 - i * 0.4), 0.65, 0.35,
          facecolor=color, edgecolor='#2c3e50', linewidth=1
      )
      ax.add_patch(legend_box)
      ax.text(2.0, legend_y + 0.88 - i * 0.4, label, fontsize=9, color='#2c3e50', va='center')

  # 右侧说明文字
  ax.text(25.5, legend_y + 2.5, '关键设计说明', fontsize=11, fontweight='bold', color='#2c3e50')
  points = [
      '• 垂直Agent大组不设总负责人，',
      '  各组直接面向行业真实问题',
      '• 范禹更多承担管线协调角色，',
      '  而非垂直管理',
      '• 资源协调小组负责跨板块的',
      '  算力资源分配与模型能力规划',
      '• 大版本合版由刘大一恒总控，',
      '  按项目优先级融合领域Teacher',
  ]
  for i, p in enumerate(points):
      ax.text(24.5, 2.2 - i * 0.32, p, fontsize=8.5, color='#555')

  # ============ 大版本合版流程箭头 ============
  draw_dashed_line(ax, 8, 14.4, 15.5, 14.4, color='#f39c12', label='合版协同')

  # ============ 评测交付门禁箭头 ============
  ax.annotate('', xy=(21, 13), xytext=(16, 13),
              arrowprops=dict(arrowstyle='<->', color='#e74c3c', lw=1.5, linestyle='dashed'))
  ax.text(18.5, 12.4, '交付门禁 ←→ 评测', fontsize=8, color='#e74c3c', ha='center')

  # ============ 保存 ============
  fig.tight_layout()
  fig.savefig('/tmp/千问模型团队组织架构图.png', dpi=150, facecolor='#f0f4f8', 
              bbox_inches='tight', pad_inches=0.3)
  print("✅ 架构图已保存到 /tmp/千问模型团队组织架构图.png")
  print(f"图像尺寸: {fig.get_figwidth()}x{fig.get_figheight()} inches")


source:
  import matplotlib.pyplot as plt
  import matplotlib.patches as patches
  from matplotlib.patches import FancyBboxPatch, Rectangle, FancyArrowPatch
  import matplotlib.patheffects as pe
  from matplotlib.lines import Line2D

  # 使用 Noto Sans CJK 中文字体
  plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC', 'Noto Sans CJK']
  plt.rcParams['axes.unicode_minus'] = False

  fig, ax = plt.subplots(figsize=(26, 30), facecolor='#f0f4f8')
  ax.set_xlim(0, 26)
  ax.set_ylim(0, 30)
  ax.axis('off')

  # ========== 辅助函数 ==========
  def draw_box(ax, cx, cy, w, h, title, subtitle, facecolor, edgecolor='#2c3e50', lw=2):
      box = FancyBboxPatch(
          (cx - w/2, cy - h/2), w, h,
          boxstyle="round,pad=0.12",
          facecolor=facecolor,
          edgecolor=edgecolor,
          linewidth=lw,
          zorder=2
      )
      ax.add_patch(box)

      # 多行标题
      lines = title.split('\n')
      if len(lines) > 1:
          for i, line in enumerate(lines):
              ax.text(cx, cy + h*0.15 - i*0.42, line,
                      ha='center', va='center',
                      fontsize=12, fontweight='bold', color='white', zorder=3,
                      path_effects=[pe.withStroke(linewidth=1.2, foreground='#333')])
      else:
          ax.text(cx, cy + h*0.1, title,
                  ha='center', va='center',
                  fontsize=13, fontweight='bold', color='white', zorder=3,
                  path_effects=[pe.withStroke(linewidth=1.2, foreground='#333')])

      if subtitle:
          ax.text(cx, cy - h*0.28, subtitle,
                  ha='center', va='center',
                  fontsize=9, color='#ecf0f1', zorder=3)

  def draw_arrow(ax, x1, y1, x2, y2, color='#34495e', lw=1.5, style='solid'):
      ls = 'dashed' if style == 'dashed' else 'solid'
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=lw,
                                 linestyle=ls, connectionstyle='arc3,rad=0'))

  # ========== 标题 ==========
  ax.text(13, 29, '千问模型团队架构图', fontsize=28, fontweight='bold',
          color='#2c3e50', ha='center', va='center')
  ax.text(13, 28.3, 'Qwen Model Team — Organizational Architecture', fontsize=12,
          color='#7f8c8d', ha='center', va='center', style='italic')

  # ========== 资源协调小组 (右上) ==========
  coord_w, coord_h = 9, 2.8
  coord_box = FancyBboxPatch(
      (16.5, 26.5), coord_w, coord_h,
      boxstyle="round,pad=0.15",
      facecolor='#f39c12', edgecolor='#d35400', linewidth=2.5,
      zorder=2, linestyle='dashed'
  )
  ax.add_patch(coord_box)
  ax.text(21, 28.15, '🔑 资源协调小组', fontsize=15, fontweight='bold',
          color='white', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=2, foreground='#8B4513')])
  ax.text(21, 27.5, '模型能力方向 & 算力资源统筹', fontsize=11,
          color='#fff8dc', ha='center', va='center', zorder=3)
  ax.text(21, 26.9, 'CEO Eddie + CTO 范禹 + 刘大一恒(P9)', fontsize=11,
          color='#fff8dc', ha='center', va='center', zorder=3)

  # ========== CEO ==========
  draw_box(ax, 3.5, 25, 5.5, 2.4, 'CEO Eddie', '资源协调小组核心', '#e74c3c')

  # ========== CTO ==========
  draw_box(ax, 13, 21, 6, 2.4, '范禹 (CTO)', '资源协调小组核心 · 管线协调', '#3498db')

  # CEO -> CTO 箭头
  draw_arrow(ax, 5.5, 24, 10, 22, color='#7f8c8d', lw=2.5)

  # CTO -> 资源协调小组 虚线
  draw_arrow(ax, 16, 22.0, 16.5, 27.3, color='#f39c12', lw=2, style='dashed')

  # CEO -> 资源协调小组 虚线
  draw_arrow(ax, 6.25, 25.5, 16.5, 28.0, color='#e74c3c', lw=1.8, style='dashed')

  # ========== 三大技术板块 Leader ==========
  # 板块1
  draw_box(ax, 4.5, 17, 6, 2.4, '刘大一恒 (P9)', '基础模型研发 · 资源协调小组核心', '#27ae60')
  # 板块2
  draw_box(ax, 13, 17, 6, 2.4, '周昊 (P10)', '前沿能力', '#27ae60')
  # 板块3
  draw_box(ax, 21.5, 17, 5.5, 2.4, '黄斐 (P8)', '评测及交付', '#27ae60')

  # CTO -> 三大板块
  draw_arrow(ax, 11, 20, 7.5, 18.2, color='#95a5a6', lw=1.8)
  draw_arrow(ax, 13, 19.8, 13, 18.2, color='#95a5a6', lw=1.8)
  draw_arrow(ax, 15, 20, 18.75, 18.2, color='#95a5a6', lw=1.8)

  # ========== 板块1 子团队 ==========
  ax.text(4.5, 15.3, '板块 1: 基础模型研发', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b1_teams = [
      (1.2, 13.3, '预训练'),
      (4.5, 13.3, '多模态模型\nOmni/VL/Image'),
      (7.8, 13.3, '后训练\nSFT/DPO'),
  ]
  for cx, cy, name in b1_teams:
      draw_box(ax, cx, cy, 2.8, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 4.5, 15.8, 1.2, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 15.8, 4.5, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 15.8, 7.8, 14.3, color='#95a5a6', lw=1)

  # ========== 板块2 子团队 ==========
  ax.text(13, 15.3, '板块 2: 前沿能力', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b2_teams = [
      (10.2, 13.3, 'Coding 专项'),
      (15.8, 13.3, '混训RL框架和算法\n(含 Agent 底座)'),
  ]
  for cx, cy, name in b2_teams:
      draw_box(ax, cx, cy, 3.0, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 13, 15.8, 10.2, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 13, 15.8, 15.8, 14.3, color='#95a5a6', lw=1)

  # ========== 板块3 子团队 ==========
  ax.text(21.5, 15.3, '板块 3: 评测及交付', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b3_teams = [
      (19.0, 13.3, '评测/RM'),
      (21.5, 13.3, '模型交付'),
      (24.0, 13.3, '多语言'),
  ]
  for cx, cy, name in b3_teams:
      draw_box(ax, cx, cy, 2.6, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 21.5, 15.8, 19.0, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 15.8, 21.5, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 15.8, 24.0, 14.3, color='#95a5a6', lw=1)

  # ========== 板块4: 垂直Agent大组 ==========
  draw_box(ax, 13, 9.5, 18, 2.6, '板块 4: 垂直 Agent 大组', '范禹直管 · 各组直接面向行业', '#9b59b6')

  ax.text(13, 7.8, '范禹 (CTO) 直管协调 · 各小组直接面向行业真实问题 · 不设总负责人', 
          fontsize=10, color='#8e44ad', ha='center', va='center', style='italic')

  # CTO -> 板块4 箭头
  draw_arrow(ax, 13, 19.8, 13, 10.8, color='#8e44ad', lw=2.5)

  # 板块4 子团队
  b4_teams = [
      (4.0, 5.8, '金融 Agent\n陈蓓(P9)', '#7d3c98'),
      (8.0, 5.8, '白领 Agent\n待定', '#a569bd'),
      (13, 5.8, '互联网 to C Agent\n待定', '#a569bd'),
      (18, 5.8, '医疗 Agent\n待定', '#a569bd'),
      (22, 5.8, '专业研发 Agent\n待定', '#a569bd'),
  ]

  for cx, cy, name, fc in b4_teams:
      draw_box(ax, cx, cy, 3.0, 1.8, name, '', fc, lw=1.2)

  # 板块4 -> 子团队
  for cx, cy, _, _ in b4_teams:
      draw_arrow(ax, 13, 8.2, cx, 6.7, color='#c39bd3', lw=1.2)

  # ========== 关键协同线 ==========
  # 板块1 <-> 板块2 合版协同
  draw_arrow(ax, 8.2, 13.3, 10.2, 13.3, color='#f39c12', lw=1.8, style='dashed')
  ax.text(9.2, 12.5, '大版本合版', fontsize=8, color='#e67e22', ha='center', fontweight='bold')

  # 板块3 交付门禁
  ax.annotate('', xy=(16.5, 12.8), xytext=(13.5, 12.8),
              arrowprops=dict(arrowstyle='<->', color='#e74c3c', lw=1.3, linestyle='dashed'))
  ax.text(15, 12.1, '交付门禁 ←→ 评测', fontsize=8, color='#e74c3c', ha='center')

  # ========== 图例 ==========
  legend_items = [
      ('#e74c3c', 'CEO / 最高决策'),
      ('#3498db', 'CTO / 技术总负责 · 管线协调'),
      ('#27ae60', '技术板块负责人'),
      ('#2ecc71', '技术团队 (子组)'),
      ('#9b59b6', '垂直 Agent 大组 · 范禹直管'),
      ('#f39c12', '资源协调小组 (虚线=协调)'),
  ]

  legend_x = 1.0
  ax.text(legend_x, 3.5, '图例:', fontsize=11, fontweight='bold', color='#2c3e50')
  for i, (color, label) in enumerate(legend_items):
      rect = Rectangle((legend_x, 3.0 - i*0.5), 0.7, 0.38, facecolor=color, edgecolor='#2c3e50', linewidth=1)
      ax.add_patch(rect)
      ax.text(legend_x + 1.0, 3.19 - i*0.5, label, fontsize=9, color='#2c3e50', va='center')

  # ========== 右侧说明 ==========
  ax.text(25, 3.2, '关键设计原则:', fontsize=11, fontweight='bold', color='#2c3e50')
  notes = [
      '1. 垂直Agent大组不设总负责人',
      '   各组直接面向行业真实问题',
      '2. 范禹承担管线协调角色',
      '   而非垂直管理',
      '3. 资源协调小组统筹跨板块',
      '   算力分配与模型能力规划',
      '4. 大版本合版由刘大一恒总控',
      '   按项目优先级融合Teacher',
  ]
  for i, note in enumerate(notes):
      ax.text(24.0, 2.6 - i*0.38, note, fontsize=8.5, color='#555')

  fig.tight_layout()
  fig.savefig('/tmp/千问模型团队组织架构图_v2.png', dpi=160, facecolor='#f0f4f8',
              bbox_inches='tight', pad_inches=0.5)
  print("✅ 架构图生成成功")

source_raw:
  import matplotlib.pyplot as plt
  import matplotlib.patches as patches
  from matplotlib.patches import FancyBboxPatch, Rectangle, FancyArrowPatch
  import matplotlib.patheffects as pe
  from matplotlib.lines import Line2D

  # 使用 Noto Sans CJK 中文字体
  plt.rcParams['font.sans-serif'] = ['Noto Sans CJK SC', 'Noto Sans CJK']
  plt.rcParams['axes.unicode_minus'] = False

  fig, ax = plt.subplots(figsize=(26, 30), facecolor='#f0f4f8')
  ax.set_xlim(0, 26)
  ax.set_ylim(0, 30)
  ax.axis('off')

  # ========== 辅助函数 ==========
  def draw_box(ax, cx, cy, w, h, title, subtitle, facecolor, edgecolor='#2c3e50', lw=2):
      box = FancyBboxPatch(
          (cx - w/2, cy - h/2), w, h,
          boxstyle="round,pad=0.12",
          facecolor=facecolor,
          edgecolor=edgecolor,
          linewidth=lw,
          zorder=2
      )
      ax.add_patch(box)
      
      # 多行标题
      lines = title.split('\n')
      if len(lines) > 1:
          for i, line in enumerate(lines):
              ax.text(cx, cy + h*0.15 - i*0.42, line,
                      ha='center', va='center',
                      fontsize=12, fontweight='bold', color='white', zorder=3,
                      path_effects=[pe.withStroke(linewidth=1.2, foreground='#333')])
      else:
          ax.text(cx, cy + h*0.1, title,
                  ha='center', va='center',
                  fontsize=13, fontweight='bold', color='white', zorder=3,
                  path_effects=[pe.withStroke(linewidth=1.2, foreground='#333')])
      
      if subtitle:
          ax.text(cx, cy - h*0.28, subtitle,
                  ha='center', va='center',
                  fontsize=9, color='#ecf0f1', zorder=3)

  def draw_arrow(ax, x1, y1, x2, y2, color='#34495e', lw=1.5, style='solid'):
      ls = 'dashed' if style == 'dashed' else 'solid'
      ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                  arrowprops=dict(arrowstyle='->', color=color, lw=lw,
                                 linestyle=ls, connectionstyle='arc3,rad=0'))

  # ========== 标题 ==========
  ax.text(13, 29, '千问模型团队架构图', fontsize=28, fontweight='bold',
          color='#2c3e50', ha='center', va='center')
  ax.text(13, 28.3, 'Qwen Model Team — Organizational Architecture', fontsize=12,
          color='#7f8c8d', ha='center', va='center', style='italic')

  # ========== 资源协调小组 (右上) ==========
  coord_w, coord_h = 9, 2.8
  coord_box = FancyBboxPatch(
      (16.5, 26.5), coord_w, coord_h,
      boxstyle="round,pad=0.15",
      facecolor='#f39c12', edgecolor='#d35400', linewidth=2.5,
      zorder=2, linestyle='dashed'
  )
  ax.add_patch(coord_box)
  ax.text(21, 28.15, '🔑 资源协调小组', fontsize=15, fontweight='bold',
          color='white', ha='center', va='center', zorder=3,
          path_effects=[pe.withStroke(linewidth=2, foreground='#8B4513')])
  ax.text(21, 27.5, '模型能力方向 & 算力资源统筹', fontsize=11,
          color='#fff8dc', ha='center', va='center', zorder=3)
  ax.text(21, 26.9, 'CEO Eddie + CTO 范禹 + 刘大一恒(P9)', fontsize=11,
          color='#fff8dc', ha='center', va='center', zorder=3)

  # ========== CEO ==========
  draw_box(ax, 3.5, 25, 5.5, 2.4, 'CEO Eddie', '资源协调小组核心', '#e74c3c')

  # ========== CTO ==========
  draw_box(ax, 13, 21, 6, 2.4, '范禹 (CTO)', '资源协调小组核心 · 管线协调', '#3498db')

  # CEO -> CTO 箭头
  draw_arrow(ax, 5.5, 24, 10, 22, color='#7f8c8d', lw=2.5)

  # CTO -> 资源协调小组 虚线
  draw_arrow(ax, 16, 22.0, 16.5, 27.3, color='#f39c12', lw=2, style='dashed')

  # CEO -> 资源协调小组 虚线
  draw_arrow(ax, 6.25, 25.5, 16.5, 28.0, color='#e74c3c', lw=1.8, style='dashed')

  # ========== 三大技术板块 Leader ==========
  # 板块1
  draw_box(ax, 4.5, 17, 6, 2.4, '刘大一恒 (P9)', '基础模型研发 · 资源协调小组核心', '#27ae60')
  # 板块2
  draw_box(ax, 13, 17, 6, 2.4, '周昊 (P10)', '前沿能力', '#27ae60')
  # 板块3
  draw_box(ax, 21.5, 17, 5.5, 2.4, '黄斐 (P8)', '评测及交付', '#27ae60')

  # CTO -> 三大板块
  draw_arrow(ax, 11, 20, 7.5, 18.2, color='#95a5a6', lw=1.8)
  draw_arrow(ax, 13, 19.8, 13, 18.2, color='#95a5a6', lw=1.8)
  draw_arrow(ax, 15, 20, 18.75, 18.2, color='#95a5a6', lw=1.8)

  # ========== 板块1 子团队 ==========
  ax.text(4.5, 15.3, '板块 1: 基础模型研发', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b1_teams = [
      (1.2, 13.3, '预训练'),
      (4.5, 13.3, '多模态模型\nOmni/VL/Image'),
      (7.8, 13.3, '后训练\nSFT/DPO'),
  ]
  for cx, cy, name in b1_teams:
      draw_box(ax, cx, cy, 2.8, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 4.5, 15.8, 1.2, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 15.8, 4.5, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 4.5, 15.8, 7.8, 14.3, color='#95a5a6', lw=1)

  # ========== 板块2 子团队 ==========
  ax.text(13, 15.3, '板块 2: 前沿能力', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b2_teams = [
      (10.2, 13.3, 'Coding 专项'),
      (15.8, 13.3, '混训RL框架和算法\n(含 Agent 底座)'),
  ]
  for cx, cy, name in b2_teams:
      draw_box(ax, cx, cy, 3.0, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 13, 15.8, 10.2, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 13, 15.8, 15.8, 14.3, color='#95a5a6', lw=1)

  # ========== 板块3 子团队 ==========
  ax.text(21.5, 15.3, '板块 3: 评测及交付', fontsize=11, fontweight='bold', color='#27ae60', ha='center')
  b3_teams = [
      (19.0, 13.3, '评测/RM'),
      (21.5, 13.3, '模型交付'),
      (24.0, 13.3, '多语言'),
  ]
  for cx, cy, name in b3_teams:
      draw_box(ax, cx, cy, 2.6, 1.8, name, '', '#2ecc71', lw=1)

  draw_arrow(ax, 21.5, 15.8, 19.0, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 15.8, 21.5, 14.3, color='#95a5a6', lw=1)
  draw_arrow(ax, 21.5, 15.8, 24.0, 14.3, color='#95a5a6', lw=1)

  # ========== 板块4: 垂直Agent大组 ==========
  draw_box(ax, 13, 9.5, 18, 2.6, '板块 4: 垂直 Agent 大组', '范禹直管 · 各组直接面向行业', '#9b59b6')

  ax.text(13, 7.8, '范禹 (CTO) 直管协调 · 各小组直接面向行业真实问题 · 不设总负责人', 
          fontsize=10, color='#8e44ad', ha='center', va='center', style='italic')

  # CTO -> 板块4 箭头
  draw_arrow(ax, 13, 19.8, 13, 10.8, color='#8e44ad', lw=2.5)

  # 板块4 子团队
  b4_teams = [
      (4.0, 5.8, '金融 Agent\n陈蓓(P9)', '#7d3c98'),
      (8.0, 5.8, '白领 Agent\n待定', '#a569bd'),
      (13, 5.8, '互联网 to C Agent\n待定', '#a569bd'),
      (18, 5.8, '医疗 Agent\n待定', '#a569bd'),
      (22, 5.8, '专业研发 Agent\n待定', '#a569bd'),
  ]

  for cx, cy, name, fc in b4_teams:
      draw_box(ax, cx, cy, 3.0, 1.8, name, '', fc, lw=1.2)

  # 板块4 -> 子团队
  for cx, cy, _, _ in b4_teams:
      draw_arrow(ax, 13, 8.2, cx, 6.7, color='#c39bd3', lw=1.2)

  # ========== 关键协同线 ==========
  # 板块1 <-> 板块2 合版协同
  draw_arrow(ax, 8.2, 13.3, 10.2, 13.3, color='#f39c12', lw=1.8, style='dashed')
  ax.text(9.2, 12.5, '大版本合版', fontsize=8, color='#e67e22', ha='center', fontweight='bold')

  # 板块3 交付门禁
  ax.annotate('', xy=(16.5, 12.8), xytext=(13.5, 12.8),
              arrowprops=dict(arrowstyle='<->', color='#e74c3c', lw=1.3, linestyle='dashed'))
  ax.text(15, 12.1, '交付门禁 ←→ 评测', fontsize=8, color='#e74c3c', ha='center')

  # ========== 图例 ==========
  legend_items = [
      ('#e74c3c', 'CEO / 最高决策'),
      ('#3498db', 'CTO / 技术总负责 · 管线协调'),
      ('#27ae60', '技术板块负责人'),
      ('#2ecc71', '技术团队 (子组)'),
      ('#9b59b6', '垂直 Agent 大组 · 范禹直管'),
      ('#f39c12', '资源协调小组 (虚线=协调)'),
  ]

  legend_x = 1.0
  ax.text(legend_x, 3.5, '图例:', fontsize=11, fontweight='bold', color='#2c3e50')
  for i, (color, label) in enumerate(legend_items):
      rect = Rectangle((legend_x, 3.0 - i*0.5), 0.7, 0.38, facecolor=color, edgecolor='#2c3e50', linewidth=1)
      ax.add_patch(rect)
      ax.text(legend_x + 1.0, 3.19 - i*0.5, label, fontsize=9, color='#2c3e50', va='center')

  # ========== 右侧说明 ==========
  ax.text(25, 3.2, '关键设计原则:', fontsize=11, fontweight='bold', color='#2c3e50')
  notes = [
      '1. 垂直Agent大组不设总负责人',
      '   各组直接面向行业真实问题',
      '2. 范禹承担管线协调角色',
      '   而非垂直管理',
      '3. 资源协调小组统筹跨板块',
      '   算力分配与模型能力规划',
      '4. 大版本合版由刘大一恒总控',
      '   按项目优先级融合Teacher',
  ]
  for i, note in enumerate(notes):
      ax.text(24.0, 2.6 - i*0.38, note, fontsize=8.5, color='#555')

  fig.tight_layout()
  fig.savefig('/tmp/千问模型团队组织架构图_v2.png', dpi=160, facecolor='#f0f4f8',
              bbox_inches='tight', pad_inches=0.5)
  print("✅ 架构图生成成功")


source:
  from matplotlib import font_manager
  import os

  # 查找系统上所有可用的中文字体
  font_paths = [
      '/usr/share/fonts/opentype/noto/NotoSansCJK-Black.ttc',
      '/usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc', 
      '/usr/share/fonts/truetype/arphic/uming.ttc',
      '/usr/share/fonts/truetype/arphic/ukai.ttc',
  ]

  for fp in font_paths:
      if os.path.exists(fp):
          print(f"✅ Found: {fp}")
          # 尝试注册字体
          try:
              fprops = font_manager.FontProperties(fname=fp)
              print(f"   Name: {fprops.get_name()}, Family: {fprops.get_family()}")
          except Exception as e:
              print(f"   Error: {e}")
      else:
          print(f"❌ Not found: {fp}")

  # 列出 /usr/share/fonts 下所有 CJK 相关字体
  import subprocess
  result = subprocess.run(['find', '/usr/share/fonts', '-name', '*CJK*', '-o', '-name', '*NotoSans*SC*'], 
                         capture_output=True, text=True)
  print("\n--- CJK font files ---")
  print(result.stdout)

source_raw:
  from matplotlib import font_manager
  import os

  # 查找系统上所有可用的中文字体
  font_paths = [
      '/usr/share/fonts/opentype/noto/NotoSansCJK-Black.ttc',
      '/usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc', 
      '/usr/share/fonts/truetype/arphic/uming.ttc',
      '/usr/share/fonts/truetype/arphic/ukai.ttc',
  ]

  for fp in font_paths:
      if os.path.exists(fp):
          print(f"✅ Found: {fp}")
          # 尝试注册字体
          try:
              fprops = font_manager.FontProperties(fname=fp)
              print(f"   Name: {fprops.get_name()}, Family: {fprops.get_family()}")
          except Exception as e:
              print(f"   Error: {e}")
      else:
          print(f"❌ Not found: {fp}")

  # 列出 /usr/share/fonts 下所有 CJK 相关字体
  import subprocess
  result = subprocess.run(['find', '/usr/share/fonts', '-name', '*CJK*', '-o', '-name', '*NotoSans*SC*'], 
                         capture_output=True, text=True)
  print("\n--- CJK font files ---")
  print(result.stdout)


source:
  import matplotlib.pyplot as plt
  import matplotlib.font_manager as fm
  import matplotlib.patheffects as pe
  from matplotlib.patches import FancyBboxPatch, Rectangle

  # 直接通过文件路径创建字体属性
  font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
  font_path_reg = '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'

  # 手动注册字体
  fm.fontManager.addfont(font_path)
  fm.fontManager.addfont(font_path_reg)

  # 获取字体的fontname
  fp_bold = fm.FontProperties(fname=font_path)
  fp_reg = fm.FontProperties(fname=font_path_reg)

  bold_name = fp_bold.get_name()
  reg_name = fp_reg.get_name()
  print(f"Bold font name: '{bold_name}'")
  print(f"Regular font name: '{reg_name}'")

  # 设置字体
  plt.rcParams['font.family'] = 'DejaVu Sans'

source_raw:
  import matplotlib.pyplot as plt
  import matplotlib.font_manager as fm
  import matplotlib.patheffects as pe
  from matplotlib.patches import FancyBboxPatch, Rectangle

  # 直接通过文件路径创建字体属性
  font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
  font_path_reg = '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'

  # 手动注册字体
  fm.fontManager.addfont(font_path)
  fm.fontManager.addfont(font_path_reg)

  # 获取字体的fontname
  fp_bold = fm.FontProperties(fname=font_path)
  fp_reg = fm.FontProperties(fname=font_path_reg)

  bold_name = fp_bold.get_name()
  reg_name = fp_reg.get_name()
  print(f"Bold font name: '{bold_name}'")
  print(f"Regular font name: '{reg_name}'")

  # 设置字体
  plt.rcParams['font.family'] = 'DejaVu Sans'


