Gemini API 的 response_format 怎么填
Gemini API 的 response_format 由三个键组成:type 写 text、mime_type 写 application/json、schema 传 JSON Schema;官方示例固定用这三个值。(核验 2026-11-05,F11、F12)
一、Gemini API 的 response_format 怎么填:问题在两套位置、两套键名
上一节你已经知道要传 response_format,于是照着自己两年前的项目写了一段:
config=types.GenerateContentConfig(
response_mime_type="application/json",
response_schema=Recipe,
)
这段代码在旧接口里是对的,在新接口里既不报错也不生效——因为 response_mime_type 与 response_schema 是 generateContent 时代的键,它们嵌在 config/generationConfig 里面;而 Interactions API 把格式控制挪到了顶层的 response_format,键名也换了(F78)。
这就是本节要解决的问题:同一个意图,两套位置、两套键名,混用的后果是静默失效而不是报错。
先看官方三个键的定义(F11、F12):
| 键 | 该填什么 | 常见错法 | 后果 |
|---|---|---|---|
type |
text |
填 json |
官方未给错误码,按不生效对待 |
mime_type |
application/json |
填 text/json、带 ; charset |
同上 |
schema |
JSON Schema 对象 | 传 Pydantic 类、传字符串 | 序列化阶段就可能失败 |
「后果」这一列是工程判断,不是官方结论:官方没有为这三个键各写一条错误码,只明确了 schema 里不支持的约束会被静默剥离(见 5.3)。所以填错时你通常不会收到报错,只会收到一段不听话的文本。
二、Gemini API 请求体检:最小可运行示例
发请求之前先扫一遍,比上线后猜「为什么返回还是纯文本」便宜得多。下面这段只用标准库。
## EXPECT: 错误写法 2 处:type 应为 text(当前 json)|schema 不是 JSON Schema 对象(当前 str) | 正确写法 0 处
VALID = {"type": "text", "mime_type": "application/json"}
def audit(request):
fmt = request.get("response_format")
if fmt is None:
return ["缺 response_format"]
if isinstance(fmt, list):
fmt = fmt[0] if fmt else {}
problems = []
if fmt.get("type") != VALID["type"]:
problems.append(f"type 应为 text(当前 {fmt.get('type')})")
if fmt.get("mime_type") != VALID["mime_type"]:
problems.append(f"mime_type 应为 application/json(当前 {fmt.get('mime_type')})")
schema = fmt.get("schema")
if not isinstance(schema, dict) or schema.get("type") != "object":
problems.append(f"schema 不是 JSON Schema 对象(当前 {type(schema).__name__})")
return problems
BAD = {"model": "gemini-3.8-flash", "input": "抽取工单",
"response_format": {"type": "json", "mime_type": "application/json", "schema": "Ticket"}}
GOOD = {"model": "gemini-3.8-flash", "input": "抽取工单",
"response_format": {"type": "text", "mime_type": "application/json",
"schema": {"type": "object", "properties": {"title": {"type": "string"}}}}}
bad, good = audit(BAD), audit(GOOD)
assert len(bad) == 2 and good == []
print(f"错误写法 {len(bad)} 处:{'|'.join(bad)} | 正确写法 {len(good)} 处")
体检器的判断依据只有三条:type 是不是 text、mime_type 是不是 application/json、schema 是不是一个 type 为 object 的字典。它不检查你的 schema 写得好不好——那个问题见 5.3。
体检通过之后,请求本身长这样(需要密钥与 SDK,本机不执行):
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="把这段话抽成工单:导出报表跑了四十分钟还没结束。",
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Ticket.model_json_schema(),
},
)
三个键全在 response_format 里,而 response_format 与 model、input 平级——这就是「顶层」的意思。Ticket 是你项目里的 Pydantic 模型,model_json_schema() 产出的就是上一节那种 dict。旧写法里那对 response_mime_type/response_schema 在顶层根本不存在,塞进 config 也不会被这条调用路径读到。
三、解释与边界:位置、取值、复合
第一条,位置随接口变,键名跟着变。 generateContent 用 response_mime_type + response_schema,放在 config/generationConfig 里;Interactions 用 response_format,放在请求顶层,内含 type/mime_type/schema(F78)。官方迁移页把两段代码并排列出来,就是为了让你别把旧的那套平移到新接口——它不会报错,只会不生效。
第二条,三个值都是固定值,不是枚举里挑一个。 生成 JSON 对象时,type 就是 text、mime_type 就是 application/json(F12)。type 取值写 json 是很自然的误写,因为你想表达的确实是 JSON;但官方这一层表达的是「输出通道是文本」,JSON 这件事由 mime_type 承担。
第三条,response_format 还能传数组。 官方说明在需要多种输出类型时,可以传单个格式对象,也可以传格式对象数组(F79)。单个请求只出一种结构时用对象即可,别为了「以后可能扩展」提前套一层数组——体检器里那个 isinstance(fmt, list) 分支只是为了容错,不是鼓励你这么写。
如何确认服务端真的接受了格式约束? 官方没有提供「回显我收到的 response_format」这类字段,所以只能从结果侧观察,三个点按可靠性排序:返回的字符串能否直接被 json.loads 吃下、字段名是否与 schema 逐一对应、required 里的键是否每次都出现。三点都过,基本可以认为约束生效了。反过来,如果返回里出现「好的,以下是提取结果」,那说明格式约束没进到生成过程,先查位置和键名,别急着改提示词。
边界。 本节只谈「三个键怎么写、放在哪」。schema 里哪些约束会被服务端丢掉、写多复杂会被拒,见 5.3;拿到不合格输出之后怎么重试与降级,见 5.4。生成配置里的其他参数(思考强度、输出上限)见 4.3、见 9.1,不在这里混着讲。
四、预期输出与异常分支
真跑输出:
错误写法 2 处:type 应为 text(当前 json)|schema 不是 JSON Schema 对象(当前 str) | 正确写法 0 处
五类分支。type 写成 json:最像「正确」的错误,体检器能抓到,不体检就只能等返回纯文本时才发现。mime_type 带参数:写成 application/json; charset=utf-8 看起来很规范,但它不等于官方示例里的那个值,是否被接受官方没写,别赌。schema 传了 Pydantic 类本身:Python 侧序列化就会失败,报错点不在 API,而在你的 HTTP 客户端;正确做法是 model_json_schema()。把 response_format 塞进 config:这是旧位置,新接口顶层没有这个键,请求照发、约束不生效,属于最难查的一类。schema 是合法对象但空:{"type": "object", "properties": {}} 能过体检,但它什么也没约束,输出会是一坨自由字段——体检器只能保证「形状对」,保证不了「约束有用」。
五、判据卡:怎么确认字段被服务端接受了
| 该这么做 | 不该这么做 |
|---|---|
| 三个键按官方固定值写,位置放顶层 | 从旧项目抄 config 里的两个旧键 |
schema 传 model_json_schema() 的结果 |
直接把 Pydantic 类塞进字典 |
| 用返回能否直接反序列化验证约束 | 认为「请求没报错」就等于生效 |
| 需要多种输出时才传数组 | 单输出也套一层数组「留扩展余地」 |
六、来源与核验
https://aistudio.google.com/docs/structured-output.md(核验 2026-11-05,F11、F12)https://aistudio.google.com/docs/migrate-to-interactions.md(核验 2026-11-05,F78、F79)
两个旧键名与新位置的关系属于「API 结构」档事实,复核周期三个月,见 1.3。官方若再次调整格式配置的位置,以迁移页 Before/After 两段原文为准,本节的键名表要整表重核。
七、动手试
- 把
GOOD里的mime_type改成"application/json; charset=utf-8",重跑。预期正确写法变成 1 处错误;验收标准是你能说清「为什么它看起来更规范,却不该这么填」。 - 给
audit加一条检查:schema的properties为空时返回「schema 空约束」提示。重跑。验收标准:GOOD仍然 0 问题,而你要能构造出一个能过原有三条检查、却被新检查拦下的请求。 - 打开你项目里的请求构造代码,确认格式配置在顶层还是
config里。验收标准:能写出一行「当前位置 + 对应接口」;写不出来,说明这段代码是抄来的,还没核对过。

TRAE-AI编程


更多建议: