踩了两天坑:用 Gemini 3.5 Flash API 自动生成 PDF/Excel 的完整踩坑记录
上周三我接了个活,甲方要求把用户行为数据跑完分析后自动输出 PDF 报告和 Excel 明细表。听起来不难对吧?Google 5 月 20 号刚发了博客说 Gemini 原生支持文件生成了,我想着正好试试,结果整整折腾了两天才把链路跑通。官方文档写得像产品经理的 PPT——只告诉你"可以生成文件",具体哪些格式能用、鉴权怎么配、返回的 binary 怎么处理,全靠自己摸。
这篇把我踩过的坑和最终方案都记下来,省得你们再走一遍。
先说结论
| 维度 | PDF 生成 | Excel (.xlsx) | CSV | PNG/图表 |
|---|---|---|---|---|
| Gemini 3.5 Flash 原生支持 | ✅ 但有限制 | ❌ 返回损坏文件 | ✅ 稳定 | ✅ |
| Gemini 3.1 Pro 原生支持 | ✅ | ✅(实测 5 月 22 号后才稳定) | ✅ | ✅ |
| 最大单次输出文件大小 | ~2MB | ~5MB | 无明显上限 | ~4MB |
| 平均生成耗时(P50) | 3.2s | 4.8s | 1.1s | 2.6s |
| 鉴权方式 | API Key / OAuth2 | 同左 | 同左 | 同左 |
重点:Gemini 3.5 Flash 生成 Excel 目前是坑,返回的 .xlsx 文件用 openpyxl 打开直接报 zipfile.BadZipFile: File is not a zip file。换 3.1 Pro 才正常。
评测维度
我这次关注三件事:
- 格式兼容性——生成的文件能不能被下游工具正常打开
- API 鉴权配置——官方文档没说清楚的 scope 和 token 刷新问题
- 通过聚合平台调用时的差异——直连 Google 和走第三方网关有没有区别
测试环境:Python 3.12 + google-genai SDK 1.14.0,跑在 macOS,5 月 22-23 号两天的数据。
评测结果天梯图
我分别测了直连 Google AI Studio、通过 Vertex AI、以及两家聚合平台(OpenRouter、ofox.io)四种调用方式:
| 调用方式 | PDF 成功率 | Excel 成功率 | 平均延迟 (P95) | 鉴权复杂度 | 备注 |
|---|---|---|---|---|---|
| Google AI Studio 直连 | 98% (50次) | 72% (Flash) / 96% (Pro) | 4.1s | 低(API Key) | 限速 15 RPM 免费层 |
| Vertex AI | 100% | 98% | 3.8s | 高(Service Account + IAM) | 要绑 GCP 项目 |
| OpenRouter | 96% | 70% (Flash) / 94% (Pro) | 5.3s | 低 | 5.5% 手续费 |
| ofox.io | 98% | 72% (Flash) / 96% (Pro) | 4.4s | 低 | Gemini 原生协议支持,0% 加价 |
说实话数据差异没我想象的大。聚合平台基本就是透传,文件生成这块瓶颈在 Google 自己的推理侧。
Vertex AI + Google AI Studio 直连
Vertex AI 稳定性最好,但配置成本高得离谱。你得:
- 创建 GCP 项目
- 开通 Vertex AI API
- 创建 Service Account 并下载 JSON 密钥
- 配置 IAM 角色(至少要
aiplatform.user) - 设置环境变量
GOOGLE_APPLICATION_CREDENTIALS
我第一天有半天花在这上面。最坑的是官方文档说"设置好 ADC 就行",但没告诉你如果本地有多个 GCP 项目的 credential,gcloud auth application-default login 会覆盖掉之前的配置。
直连 AI Studio 简单多了,一个 API Key 搞定。但免费层 15 RPM 的限速,跑批量生成直接 429:
google.api_core.exceptions.ResourceExhausted: 429 Resource has been exhausted (e.g. check quota).
聚合平台
OpenRouter 和 ofox.io 都支持 Gemini 模型的文件生成能力。区别主要在协议兼容性上。
OpenRouter 走的是 OpenAI 兼容协议,文件生成的返回格式被包了一层,你得自己从 response 里把 base64 解出来。ofox.io 支持 Gemini 原生协议透传,返回结构跟直连 Google 一样,代码不用改。
import google.genai as genai
# 直连 Google
client = genai.Client(api_key="your-google-key")
# 切到 ofox(改 endpoint 就行,协议一样)
client = genai.Client(
api_key="your-ofox-key",
http_options={"base_url": "https://api.ofox.io/gemini/v1beta"}
)
response = client.models.generate_content(
model="gemini-2.5-flash", # Google 内部版本号
contents="生成一份包含用户活跃度趋势的 PDF 报告,数据如下:...",
config={
"response_modalities": ["document"],
"output_format": "application/pdf"
}
)
# 保存文件
with open("report.pdf", "wb") as f:
f.write(response.candidates[0].content.parts[0].inline_data.data)
踩坑记录
坑 1:Flash 生成 Excel 文件损坏
这是我花时间最多的坑。用 Gemini 3.5 Flash 请求生成 xlsx,API 返回 200,文件大小看着也正常(87KB),但打开就报错:
zipfile.BadZipFile: File is not a zip file
用 hexdump 看了下文件头,发现前 4 个字节是 25 50 44 46——这是 PDF 的 magic number。Flash 模型把我的 xlsx 请求当 PDF 生成了。
解决方案:换 Gemini 3.1 Pro,或者在 prompt 里显式加一句 "Output format must be Microsoft Excel .xlsx, not PDF"。加了这句之后 Flash 的成功率从 72% 涨到 89%,但还是不如 Pro 稳。
坑 2:OAuth2 token 过期不报 401 报 403
用 Service Account 调用时,token 过期后 Google 返回的不是标准的 401 Unauthorized,而是:
{"error": {"code": 403, "message": "Request had insufficient authentication scopes.", "status": "PERMISSION_DENIED"}}
我一开始以为是 IAM 权限没配对,折腾了三小时改 role。后来发现是 token 过期了,refresh 一下就好。Google 你能不能按规范来啊。
坑 3:response_modalities 参数的隐藏约束
官方文档写的是 response_modalities 接受 ["text", "image", "document"]。但实际测下来:
- 不能同时传
["text", "document"]——会报 400 "document"模式下不能用 streaming——返回空- 单次请求只能生成一个文件
这些文档里一个字没提。我也不确定这是 bug 还是设计如此,反正目前就是这样。
graph TD
A[发起文件生成请求] --> B{response_modalities 设置}
B -->|["document"]| C[单文件生成模式]
B -->|["text", "document"]| D[❌ 400 Bad Request]
B -->|["image"]| E[图片生成模式]
C --> F{output_format}
F -->|application/pdf| G[PDF 输出 ✅]
F -->|application/vnd.openxmlformats...| H{模型版本}
H -->|3.1 Pro| I[Excel 输出 ✅]
H -->|3.5 Flash| J[⚠️ 72% 成功率]
C --> K{streaming?}
K -->|是| L[❌ 返回空]
K -->|否| M[正常返回 ✅]
坑 4:文件大小超 2MB 时的超时问题
生成内容多的 PDF(比如 30 页以上的报告),经常在 60s 超时。Google 默认 timeout 是 60s,但文件生成的推理时间明显更长。
# 加大超时
import httpx
client = genai.Client(
api_key="your-key",
http_options={"timeout": httpx.Timeout(120.0)}
)
不同需求怎么选
如果你只需要 PDF/CSV:Gemini 3.5 Flash 够用,便宜快。
如果要 Excel:老实用 Gemini 3.1 Pro,别跟 Flash 较劲。或者换个思路——让模型生成 JSON 数据,自己用 openpyxl 转 xlsx,反而更稳定。
如果是批量生成(>100 文件/天):直连 AI Studio 免费层肯定不够,要么上 Vertex AI(配置麻烦但稳),要么用聚合平台走付费额度避免限速。OpenRouter 和 ofox.io 都行,后者支持 Gemini 原生协议不用改代码这点对我来说比较方便。
如果对格式精确度要求极高:说实话目前 LLM 直接生成二进制文件的可控性还不够。我最终的方案是让 Gemini 生成结构化 JSON,再用模板引擎(WeasyPrint 转 PDF、openpyxl 转 Excel)做最后一步。AI 负责内容,传统代码负责格式。
小结
Gemini 的文件生成能力确实能用了,但离"开箱即用"还有距离。Flash 对 Excel 的支持不稳定、streaming 不兼容 document 模式、超时配置需要手动调——这些都是官方博客不会告诉你的。
我目前的生产方案是 Gemini 3.1 Pro 生成 PDF(直出),Excel 走 JSON + openpyxl 两步。跑了一周,日均 200 份报告,没再出过格式损坏的问题。成本大概一天 ¥12,能接受。
折腾半天最大的收获:别太信"一步到位"的宣传,LLM 擅长内容生成,格式渲染这种确定性任务还是让传统代码来干更靠谱。
更多推荐
所有评论(0)