为什么 Vertex AI Studio 保存的 Prompt 在 Python 中加载时触发 ParseError?

作者:袖梨 2026-09-17

Vertex AI Studio 保存的 Prompt 在 Python 中加载时触发 google.protobuf.json_format.ParseError,如果错误路径指向 generationConfig.speechConfig.languageCode,根因通常不是提示词文本有语法错误,而是 Studio 写入的服务端元数据字段与当时 Python 客户端携带的 protobuf schema 不一致。官方 issue 5176 已确认这是 Vertex AI Studio 缺陷,并于 2025 年 5 月修复。当前遇到相同堆栈时,应先升级客户端并重新保存一个最小 Prompt 复测,不要直接修改线上 Prompt 数据。

识别这类 ParseError

典型故障发生在 prompts.get() 或读取版本时,而不是创建 Python 字典时。堆栈会进入 google.protobuf.json_format.ParseDict(),并报告某个消息类型不存在服务端返回的字段。例如历史故障中的关键信息是:

google.protobuf.json_format.ParseError:
Message type "google.cloud.aiplatform.v1beta1.SpeechConfig"
has no field named "languageCode"
at "GenerateContentRequest.generationConfig.speechConfig".
Available Fields: ["voiceConfig"]

这段信息说明客户端已经成功取得 Prompt 元数据,但在把 JSON 字典转换为本地 protobuf 消息时失败。服务端数据包含 languageCode,本地 SpeechConfig 描述符却只认识 voiceConfig,因此反序列化在模型调用之前就中止。

官方 issue 中的历史现场

问题报告使用 Python 3.11.10 和 google-cloud-aiplatform 1.81.0。通过 Vertex AI Studio 新建 Prompt 或保存新版本后,下面的旧 preview API 调用会失败,而较早保存的版本仍能读取:

import vertexai
from vertexai.preview import prompts

prompt_ref = prompts.list()[0]
loaded = prompts.get(prompt_ref.prompt_id)

维护者明确回复这是 Vertex AI Studio 的缺陷,随后在 2025 年 5 月 20 日确认问题已经修复,并亲自验证可以读取在 UI 中保存的 Prompt。因而不能把该 issue 解读为“所有 Studio Prompt 永远不能通过 Python 读取”,也不能把旧版本固定为长期解决方案。

先收集环境证据

排查前记录 Python、SDK 和 protobuf 版本,并确认当前解释器确实来自预期虚拟环境。只查看依赖文件不够,因为终端、IDE、Lambda 层或容器可能加载另一套 site-packages。

python --version
python -m pip show google-cloud-aiplatform
python -m pip show protobuf
python -m pip check

再用 Python 打印实际导入路径和版本:

import google.protobuf
import vertexai

print("vertexai path:", vertexai.__file__)
print("protobuf version:", google.protobuf.__version__)
print("protobuf path:", google.protobuf.__file__)

同时记录项目、区域、Prompt ID、Version ID、Prompt 是从 Studio 还是 SDK 保存、保存时间和完整异常字段路径。不要在公开日志中输出 Prompt 正文、凭据或用户数据。

在隔离环境升级并复测

由于原问题已在服务端修复,第一步应使用新的干净虚拟环境安装当前 google-cloud-aiplatform,排除旧依赖锁、残留 protobuf 包和 Lambda Layer 造成的 schema 滞后。

python -m venv .venv-vertex-prompt
source .venv-vertex-prompt/bin/activate
python -m pip install --upgrade pip
python -m pip install --upgrade google-cloud-aiplatform
python -m pip check

不要只单独强制升级 protobuf 到任意最新版本。Google 客户端依赖之间存在版本约束,绕过解析错误可能引入另一组不兼容。让 pip 根据当前 SDK 解析依赖,并用 pip check 验证环境。

使用当前 Prompt 客户端读取

旧 issue 使用 vertexai.preview.prompts。新代码应优先使用当前 vertexai.Client 接口,显式指定项目与区域,然后按稳定的 Prompt ID 读取,不要用列表第一个元素碰运气。

import vertexai

PROJECT_ID = "your-project-id"
LOCATION = "us-central1"
PROMPT_ID = "1234567890123456789"

client = vertexai.Client(
    project=PROJECT_ID,
    location=LOCATION,
)

prompt = client.prompts.get(
    prompt_id=PROMPT_ID,
)

print("prompt_id:", prompt.prompt_id)
print("version_id:", prompt.version_id)

如果需要检查指定历史版本,先列出版本引用,再使用 get_version()

versions = list(
    client.prompts.list_versions(
        prompt_id=PROMPT_ID,
    )
)

for ref in versions:
    loaded = client.prompts.get_version(
        prompt_id=ref.prompt_id,
        version_id=ref.version_id,
    )
    print(ref.version_id, loaded.prompt_data.model)

逐版本读取可以判断故障只影响某个版本,还是所有版本都失败。如果旧版本可读、新版本不可读,并且异常字段路径一致,说明问题更可能位于保存数据与客户端 schema 的交界处。

建立最小复现矩阵

不要直接用复杂生产 Prompt 反复试验。新建一个只含纯文本、单轮内容且不含语音配置、工具或多模态部分的 Prompt,分别从 SDK 与 Studio 保存,再按 ID 读取。建议记录以下组合:

A. SDK 创建 -> SDK 读取
B. Studio 创建 -> SDK 读取
C. Studio 修改已有 Prompt -> SDK 读取最新版本
D. SDK 读取修改前的历史版本

若 A 成功而 B、C 失败,问题集中在 Studio 写入路径;若所有组合失败,应优先检查认证、区域和本地依赖;若只有一个历史版本失败,则保留该 Version ID 和异常字段路径提交支持案例。

为何不应忽略未知字段

protobuf JSON 解析器可以在某些场景配置忽略未知字段,但在 SDK 内部反序列化链路中强行打补丁并不安全。被忽略的字段可能改变模型行为,例如语音、生成配置或安全设置。读取虽然不再报错,应用却可能悄悄丢失配置,形成更难发现的数据一致性问题。

同样不应直接修改 SDK 私有函数、猴子补丁 ParseDict 或编辑服务端 Dataset 元数据。这些做法依赖内部实现,升级后容易失效,也会让后续支持团队无法复现原始问题。

如何处理仍然不可读的旧版本

如果新建 Prompt 已能读取,而某个旧版本仍持续报相同 ParseError,先保留该版本作为审计证据,不要删除。可以在 Studio 中查看其内容,并在测试项目中以受支持字段重新创建等价 Prompt,随后通过 Python 回读验证。

迁移时记录旧 Prompt ID、旧 Version ID、新 Prompt ID、新 Version ID、字段差异和审批人。若应用必须继续使用原 Prompt ID,应向 Google Cloud 支持提交修复请求,而不是私自复制后静默切换,因为资源身份变化会影响配置、权限和审计链。

提交可操作的支持案例

当当前 SDK 和新保存的最小 Prompt 仍能复现时,支持案例至少应包含以下信息:

项目与区域(敏感部分脱敏)
Prompt ID 与 Version ID
Studio 保存时间
Python、google-cloud-aiplatform、protobuf 版本
实际模块导入路径
最小复现代码
完整 ParseError 字段路径
SDK 创建与 Studio 创建的对照结果

重点是给出字段路径和对照矩阵,而不只是“get 失败”。这能帮助维护者快速判断是 Studio 写入了客户端未知字段、客户端生成代码落后,还是某个历史资源残留不兼容数据。

不要误读旧 issue 的模型限制

该 issue 关闭时,维护者还说明当时的 Vertex SDK Prompt Management 只支持 1.5 系列模型且不支持多轮 Prompt。这是 2025 年特定接口状态,不应直接作为当前长期结论。现在使用的模型和对象结构必须以当前 API 文档为准;旧 issue 只用于解释当时 ParseError 的根因与修复时间。

如果旧 Prompt 绑定已停用或不再受支持的模型,迁移模型与修复 schema 是两个不同问题。先证明 Prompt 能被客户端正确读取,再单独验证新模型调用,避免把解析错误、模型生命周期和生成请求错误混在一起。

生产环境的防护措施

在 CI 中增加跨入口兼容测试:用 SDK 创建并回读 Prompt,再对由 Studio 保存的受控 Prompt 做读取检查。部署前固定并验证 SDK 依赖集合,保存 pip freeze,同时定期在隔离环境测试当前版本。

应用启动时不要枚举列表后直接取第一个 Prompt。应从配置读取明确的 Prompt ID 和 Version ID,失败时输出结构化错误并停止切换。这样既能减少误读其他资源,也能在 schema 回归时准确定位受影响版本。

判断问题已经解决的标准

仅仅不再抛出异常还不够。应确认当前客户端能读取 Studio 新保存的最小 Prompt,返回的 Prompt ID 和 Version ID 与目标一致,模型、内容、系统指令和变量结构没有丢失,并能列出及读取历史版本。

对于历史 speechConfig.languageCode ParseError,正确结论是 Studio 曾写入与 Python SDK schema 不一致的数据,官方后来修复了该缺陷。今天的处理顺序应是确认字段路径、升级隔离环境、使用当前客户端复测、建立最小对照,仍失败再携带完整证据升级支持,而不是永久降级或隐藏未知字段。

相关文章

精彩推荐