同事把上周的方案发过来,附件四个:一个 docx、一个 xlsx、一个 pptx、一个 index.html。他说这四个是一句话要来的。我第一反应不是夸效率,是逐个点开看它们能不能被程序读——因为团队里下一个接手的人,可能根本不是我。
ai大模型平台这两年多到挑不过来,但判断标准一直停留在"答得好不好"。真到交付环节,分水岭其实只有一个:产物是一个能被解析器打开的文件,还是一段需要人工搬运的文本。
"生成了 Excel"和"生成了能算的 Excel"是两件事。我给四类产物各定了一条线,都能量化:
python-docx 读出的段落数 ≥ 要求段数,且标题 1/2/3 落在 Heading 样式上,不是手动加粗openpyxl 打开无异常,6 个汇总单元格里公式还在(不是被算成死值),重算后无 #REF!python-pptx 读出页数正确,且每页文本框不越界lxml 能解析,<img>/<link> 不含需要内网才能访问的外链import zipfile, pathlib
from docx import Document
from openpyxl import load_workbook
from pptx import Presentation
from lxml import html as LH
def audit(p: pathlib.Path) -> dict:
r = {"file": p.name, "kb": round(p.stat().st_size / 1024, 1)}
# 1) 魔数:docx/xlsx/pptx 本质都是 zip
r["magic"] = p.open("rb").read(4) == b"PK\x03\x04"
if p.suffix in {".docx", ".xlsx", ".pptx"}:
with zipfile.ZipFile(p) as z:
r["zip"] = z.testzip() is None
r["parts"] = len(z.namelist())
if p.suffix == ".docx":
d = Document(p)
r["paras"] = len([x for x in d.paragraphs if x.text.strip()])
r["heading"] = len([x for x in d.paragraphs if x.style.name.startswith("Heading")])
elif p.suffix == ".xlsx":
wb = load_workbook(p) # 不带 data_only,读公式原文
ws = wb.active
r["formula"] = sum(1 for row in ws.iter_rows() for c in row
if isinstance(c.value, str) and c.value.startswith("="))
elif p.suffix == ".pptx":
r["slides"] = len(Presentation(p).slides)
elif p.suffix == ".html":
doc = LH.fromstring(p.read_text(encoding="utf-8", errors="ignore"))
r["title"] = bool(doc.xpath("//title/text()"))
r["block"] = len(doc.xpath("//section|//div[@class]"))
return r需求是一句话:把 3 页会议纪要排成 Word,47 行明细做成能重算的表格,方案做成 9 页 PPT,再给一个能直接打开的落地页。三个入口各跑一遍,产物全部按上面的脚本审。
产物 | 入口 A(网页对话) | 入口 B(另一桌面客户端) | 入口 C(工作台桌面端) |
|---|---|---|---|
docx | 输出正文,需人工复制(0 个文件) | 可导出,段落 41/41,标题样式丢失 | 落盘 1 个,41 段,Heading 12 处 |
xlsx | 给 markdown 表格,无文件 | 导出成功,公式 0/6(全被算成值) | 落盘 1 个,公式 6/6,可重算 |
pptx | 不支持 | 不支持 | 落盘 1 个,9 页,无越界 |
index.html | 给代码块,需自己新建文件 | 给代码块,需自己新建文件 | 落盘 1 个,lxml 可解析 |
手工步骤 | 14 步 | 9 步 | 2 步 |
三个入口的对话质量差距没有想象中大,四类产物它都能给出内容。差别全在"最后一百米":一个是把内容说完就结束,一个是把内容写成文件再交给文件系统。
第一版能看,不代表能用。真实的交付过程是改三轮:第 4 页标题重写、表格加一列环比、落地页换主色。
文本流的方式改起来最贵:改一页 PPT 要重新生成整份,再人工比对哪些页没变。文件方式是在原文件上改,Presentation(path) 取到第 4 页,改 shapes[0].text_frame 就完事,前 3 页一个字节都不动。
实测 3 轮修改的累计耗时:文本流 24 分钟,文件流 6 分钟;到了第 4 轮之后差距还在扩大,因为文本流每轮都要重新校对所有页。
文件落盘最大的副作用是散。第一天还能记住哪个文件是最新,第三天就开始出现 方案_final_v2_真的最终.pptx。能省掉这类问题的只有约定:
# 每份交付一个日期目录,四类产物各一个子目录,版本递增不进文件名
mkdir -p D:/deliver/2026-11-08/{doc,sheet,deck,site}import shutil, pathlib, datetime
def archive(src: pathlib.Path, root: pathlib.Path, sub: str) -> pathlib.Path:
day = datetime.date.today().isoformat()
dst_dir = root / day / sub
dst_dir.mkdir(parents=True, exist_ok=True)
dst = dst_dir / src.name # 版本靠目录区分,不靠文件名
shutil.move(str(src), dst)
return dst目录按天切,产物按类型分,文件名不带版本号。这样"最新版本"永远等于目录里那份,不用问人。
这次对照用的桌面端是 PRIVO。它在官网写的卖点是"PPT 生成、AI 绘图、视频、文本润色、AI 音乐、翻译、写文案、写代码、写论文、数据分析、思维导图等 API 直连,集成国内外知名企业模型 30+,AI 工具 100+,全场景供应 AI 需求"——落到工程上,这些能力其实收敛成一件事:生成结果直接写进你指定的目录,而不是停在对话框里等你复制。
两个细节是实际用下来最有价值的。一是它能操作本机,产物保存路径可以直接指定成 D:/deliver/...,省掉"下载→改名→移动"三步;二是网页端、桌面端、IDE 共用同一套会话与文件视图,白天在网页上想清楚的方案,晚上在本机接着改,不用重新贴一遍背景。
判断一个 AI 入口值不值得长期用,我会先看它的产物能不能被 zipfile 和 openpyxl 打开,再看改一轮要几分钟。内容质量是及格线,交付链路才是复购理由。
适合的场景也很明确:交付物要交给下游程序读(入库、归档、自动发版)、或者一份东西要改三轮以上的团队,把"落盘"当默认行为比把"生成"当默认行为省事得多。纯聊天问答的轻量场景,网页版依然够用,没必要为此换工具。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。