用 GPT 直接生成可编辑 PPTX 的实操记录,artifact-tool是OpenAICodex环境专用

这次的目标是:根据一张参考图,生成一页可编辑的 PPTX,文字可改、图形可替换,版式尽量贴近原图。

我的思路

不直接让 GPT "画一张图",而是让它走一条更可控的链路:

复制代码
参考图 → 版式识别 → 字体/图片环境检查 → python-pptx 生成 → 校验 → 输出可编辑 .pptx

这样生成的不是截图,而是真正的 PPTX 文件,打开后可以继续改文字、换配色、调整图形。

关键步骤

1. 先看工作区里有什么文件

bash 复制代码
pwd && rg --files -g '*.png' -g '*.jpg' -g '*.pptx' -g 'AGENTS.md' .

这一步主要是确认参考图、已有 PPTX、配置文件是否都在工作区里。

2. 查 PPT 生成 API 文档

bash 复制代码
cat "$CODEX_PRIMARY_RUNTIME_NODE_MODULES/@oai/artifact-tool/docs/presentations/api/API_DOCS.md"
cat "$CODEX_PRIMARY_RUNTIME_NODE_MODULES/@oai/artifact-tool/docs/presentations/api/references/rich-text.spec.md"

这里会看生成 PPT 时支持哪些元素,比如标题、正文、形状、图片、备注等。

3. 检查中文字体

bash 复制代码
fc-list :lang=zh family | sort -u

中文 PPT 很容易踩字体坑,所以要先确认环境里有没有可用的中文字体。

4. 查找 CJK / 黑体类字体

bash 复制代码
rg --files "$CODEX_PRIMARY_RUNTIME_ROOT" -g '*.ttf' -g '*.otf' -g '*.ttc' \
  | rg 'CJK|[Ss]ans[Ss][Cc]|[Ss]ans[Hh]ans|[Aa]rial|[Mm]icrosoft|[Ww]qy'

如果要用中文排版,优先找 Noto Sans SC、思源黑体、微软雅黑、WenQuanYi 这类字体。

5. 查看运行时字体加载逻辑

bash 复制代码
ls "$CODEX_PRIMARY_RUNTIME_ROOT/dependencies"
rg --files "$CODEX_PRIMARY_RUNTIME_ROOT" | rg -i 'font|cjk' | tail -35
sed -n '1,160p' /root/.codex/skills/builtins/presentations/container_tools/runtime_helpers.mjs

这一步是为了确认 PPT 生成流程里,字体是怎么注册、怎么加载的。

6. 检查字体相关代码

bash 复制代码
rg -n 'font|Font' /root/.codex/skills/builtins/presentations/container_tools/artifact_tool_utils.mjs | head -45
ls /usr/share/fonts
rg --files /usr/share/fonts | head -15
rg --files "$CODEX_PRIMARY_RUNTIME_NODE_MODULES" | rg -i 'CJK|NotoSansSC|\.ttc' | head -15

如果环境里没有合适的中文字体,生成的中文可能会显示异常,所以这里要重点确认。

7. 查看构建校验结果

bash 复制代码
cat build/validation.json

用来确认之前的生成或校验有没有报错。

8. 分析 artifact 工具内部逻辑

python 复制代码
from pathlib import Path
import os, re

p = Path(os.environ['CODEX_PRIMARY_RUNTIME_NODE_MODULES']) / '@oai/artifact-tool/dist/artifact_tool.mjs'
s = p.read_text()

for term in ['FONT', 'fontPaths', 'loadFonts', 'registerFont', 'fontDirectory', 'FONTCONFIG', 'GlobalFonts']:
    matches = list(re.finditer(term, s))
    print(term, len(matches))
    for m in matches[:3]:
        print(s[max(0, m.start() - 130):m.end() + 220])

这段脚本用来快速定位 PPT 生成工具里和字体相关的函数。

9. 查看核心生成函数

python 复制代码
from pathlib import Path
import os

s = (Path(os.environ['CODEX_PRIMARY_RUNTIME_NODE_MODULES']) / '@oai/artifact-tool/dist/artifact_tool.mjs').read_text()
i = s.find('function hqt()')
print(s[i - 1400:i + 6500])

找到核心函数后,可以判断它是否支持文本框、形状、图片、备注等元素。

10. 执行生成

bash 复制代码
"$CODEX_PRIMARY_RUNTIME_NODE" build/create.mjs > build/run.log 2>&1
tail -c 1300 build/run.log

这里真正触发 PPTX 生成,并把日志输出到 build/run.log。

11. 校验字体文件

python 复制代码
from fontTools.ttLib import TTFont

f = TTFont('fonts/DroidSansFallback.ttf')
print(f['OS/2'].__dict__)
print(f['hhea'].__dict__)

如果生成结果里中文显示异常,可以用 fontTools 检查字体是否完整、是否包含中文字形。

12. 查看最终日志

bash 复制代码
tail -n 3 build/run.log | cut -c 1-200

确认最后几步有没有报错。

13. 应用补丁并输出文件

json 复制代码
{
  "path": "/connector_openai_library/implicit_link::connector_openai_library/create_library_file",
  "args": {
    "file": "/workspace/scratch/0b5208d9034e/output/入职感悟与成长体会_可编辑.pptx",
    "library_artifact_type": "slides"
  }
}

这一步把生成的 PPTX 注册为可下载或可引用的产物。

14. 写入扩展属性

bash 复制代码
python3 /workspace/scratch/0b5208d9034e/build/library_file_transfer.py apply-xattrs \
  '/workspace/scratch/0b5208d9034e/output/入职感悟与成长体会_可编辑.pptx' \
  'libfile_9d7bf7ba58e48191907930c0f4174794' <<'JSON'
[{"name":"user.library-file-version","value":"0"}]
JSON

给输出文件加上版本标记,方便后续追踪。

最终输出

生成后的文件路径是:

复制代码
/workspace/scratch/0b5208d9034e/output/入职感悟与成长体会_可编辑.pptx

它是一个真正的 PPTX,不是图片。打开后可以继续编辑文字、调整图形、替换配色。

踩坑提醒

  • 中文优先确认字体:没有中文字体时,中文可能变成方框或默认字体。
  • 不要只靠截图还原:截图只能参考版式,真正可编辑要靠 PPTX 元素生成。
  • 生成后要校验:至少打开确认文字、图片、版式是否正常。
  • 复杂版式建议分步:先做标题区,再做内容区,最后加图形和图片。

命令和脚本都按语言加了语法高亮。

1. 查看工作区文件

bash 复制代码
pwd && rg --files -g '*.png' -g '*.jpg' -g '*.pptx' -g 'AGENTS.md' .

2. 查看 PPT 生成 API 文档

bash 复制代码
cat "$CODEX_PRIMARY_RUNTIME_NODE_MODULES/@oai/artifact-tool/docs/presentations/api/API_DOCS.md"
cat "$CODEX_PRIMARY_RUNTIME_NODE_MODULES/@oai/artifact-tool/docs/presentations/api/references/rich-text.spec.md"

3. 检查中文字体

bash 复制代码
fc-list :lang=zh family | sort -u

4. 查找 CJK / 黑体类字体

bash 复制代码
rg --files "$CODEX_PRIMARY_RUNTIME_ROOT" -g '*.ttf' -g '*.otf' -g '*.ttc' \
  | rg 'CJK|[Ss]ans[Ss][Cc]|[Ss]ans[Hh]ans|[Aa]rial|[Mm]icrosoft|[Ww]qy'

5. 查看运行时字体加载逻辑

bash 复制代码
ls "$CODEX_PRIMARY_RUNTIME_ROOT/dependencies"
rg --files "$CODEX_PRIMARY_RUNTIME_ROOT" | rg -i 'font|cjk' | tail -35
sed -n '1,160p' /root/.codex/skills/builtins/presentations/container_tools/runtime_helpers.mjs

6. 检查字体相关代码

bash 复制代码
rg -n 'font|Font' /root/.codex/skills/builtins/presentations/container_tools/artifact_tool_utils.mjs | head -45
ls /usr/share/fonts
rg --files /usr/share/fonts | head -15
rg --files "$CODEX_PRIMARY_RUNTIME_NODE_MODULES" | rg -i 'CJK|NotoSansSC|\.ttc' | head -15

7. 查看构建校验结果

bash 复制代码
cat build/validation.json

8. 分析 artifact 工具内部逻辑

python 复制代码
from pathlib import Path
import os, re

p = Path(os.environ['CODEX_PRIMARY_RUNTIME_NODE_MODULES']) / '@oai/artifact-tool/dist/artifact_tool.mjs'
s = p.read_text()

for term in ['FONT', 'fontPaths', 'loadFonts', 'registerFont', 'fontDirectory', 'FONTCONFIG', 'GlobalFonts']:
    matches = list(re.finditer(term, s))
    print(term, len(matches))
    for m in matches[:3]:
        print(s[max(0, m.start() - 130):m.end() + 220])

9. 查看核心生成函数

python 复制代码
from pathlib import Path
import os

s = (Path(os.environ['CODEX_PRIMARY_RUNTIME_NODE_MODULES']) / '@oai/artifact-tool/dist/artifact_tool.mjs').read_text()
i = s.find('function hqt()')
print(s[i - 1400:i + 6500])

10. 执行生成

bash 复制代码
"$CODEX_PRIMARY_RUNTIME_NODE" build/create.mjs > build/run.log 2>&1
tail -c 1300 build/run.log

11. 校验字体文件

python 复制代码
from fontTools.ttLib import TTFont

f = TTFont('fonts/DroidSansFallback.ttf')
print(f['OS/2'].__dict__)
print(f['hhea'].__dict__)

12. 查看最终日志

bash 复制代码
tail -n 3 build/run.log | cut -c 1-200

13. 应用补丁并输出文件

json 复制代码
{
  "path": "/connector_openai_library/implicit_link::connector_openai_library/create_library_file",
  "args": {
    "file": "/workspace/scratch/0b5208d9034e/output/入职感悟与成长体会_可编辑.pptx",
    "library_artifact_type": "slides"
  }
}

14. 写入扩展属性

bash 复制代码
python3 /workspace/scratch/0b5208d9034e/build/library_file_transfer.py apply-xattrs \
  '/workspace/scratch/0b5208d9034e/output/入职感悟与成长体会_可编辑.pptx' \
  'libfile_9d7bf7ba58e48191907930c0f4174794' <<'JSON'
[{"name":"user.library-file-version","value":"0"}]
JSON
相关推荐
爱读书的小胖1 小时前
Codewars: A Brave New Wordle(C)解题分析
c语言·数据结构·算法
Escalating_xu1 小时前
【数据结构】顺序表的应用:动态通讯录项目与双指针经典算法
c语言·数据结构·算法
其实防守也摸鱼1 小时前
CTF Web 6 题全解 Writeup
linux·sql·学习·算法·安全·ctf·xss
宇明一不急1 小时前
string和byte的相互转换
算法
波力海苔夹心脆6751 小时前
VisionPro 与 VisionMaster 对比(上):软件定位、开发环境与核心视觉工具对照
图像处理·算法·计算机视觉·c#·视觉检测·个人开发·vp9
动词ing2 小时前
【题目练习】盛最多水的容器
算法·目标检测
海绵宝宝转agent2 小时前
2026-10-14算法+面经总结
java·笔记·算法·缓存
虚无的纽扣2 小时前
【力扣刷题】第四天:三数之和、四数之和
算法·leetcode·职场和发展
ZiLing2 小时前
2026 ROS 2 Lyrical 工程实例(一):从零搭建 AMR 激光 SLAM——Gazebo、slam_toolbox 与 Nav2 全链路跑通
算法