解决Pydantic AI与Gemini API交互时的JSON Schema兼容性难题
解决Pydantic AI与Gemini API交互时的JSON Schema兼容性难题
你是否在使用Pydantic AI构建智能应用时,遇到过与Gemini API交互时的JSON Schema兼容性问题?比如模型突然返回空字典、工具调用参数缺失,或者收到莫名其妙的"invalid schema"错误?本文将深入剖析这些兼容性陷阱,并提供经过验证的解决方案,帮助你在15分钟内解决90%的集成难题。
读完本文你将获得:
- 理解Pydantic AI与Gemini API的JSON Schema差异点
- 掌握5种关键兼容性问题的识别与修复方法
- 获取可直接复用的兼容性适配代码
- 学会使用内置工具调试Schema转换问题
兼容性问题根源解析
Pydantic AI生成的JSON Schema与Gemini API支持的子集之间存在系统性差异。Gemini API仅支持OpenAPI v3.0.3的一个受限子集,这与Pydantic默认生成的完整JSON Schema规范存在冲突。
主要冲突点体现在三个方面:
-
关键字支持差异:Gemini不支持
additionalProperties、title、$schema等标准关键字,如profiles/google.py所示,这些关键字会被主动移除 -
类型系统差异:Gemini对枚举类型、数值范围等有特殊处理要求,需要将数值枚举转换为字符串类型
-
引用处理限制:Gemini不支持递归
$ref引用,如tests/models/test_gemini.py中的测试用例所示,递归引用会直接抛出UserError
五大兼容性问题及解决方案
1. additionalProperties导致的空字典问题
当使用dict[str, MyType]类型定义工具参数时,Pydantic会自动生成包含additionalProperties: false的Schema。但Gemini API会忽略此关键字,导致工具收到空字典。
解决方案:
from pydantic import BaseModel, field_validator
class ProductInventory(BaseModel):
items: dict[str, int] # 原定义会生成additionalProperties: false
@field_validator('items', mode='before')
def allow_additional_properties(cls, v):
# 兼容Gemini忽略additionalProperties的行为
if isinstance(v, dict):
return v
return {}
Pydantic AI已在profiles/google.py中实现了自动移除additionalProperties的逻辑,但仍需在应用层处理空字典情况。
2. 递归引用导致的Schema错误
当定义包含自引用的Pydantic模型(如树结构、图节点)时,生成的Schema会包含$ref关键字,这在Gemini API中是明确不支持的。
错误示例:
from pydantic import BaseModel
from typing import Optional
class TreeNode(BaseModel):
value: str
children: Optional[list['TreeNode']] = None # 递归引用
TreeNode.model_rebuild()
解决方案:使用平面对象替代递归结构,或使用模型展平工具预处理Schema。
3. 数值枚举类型不兼容
Gemini API仅支持字符串类型的枚举值,而Pydantic默认会保留原始数值类型,导致参数解析失败。
修复代码:
from enum import Enum
from pydantic import BaseModel
class OrderStatus(int, Enum):
PENDING = 1
CONFIRMED = 2
SHIPPED = 3
class OrderUpdate(BaseModel):
status: OrderStatus
class Config:
# 自动将枚举值转换为字符串
json_encoders = {OrderStatus: lambda v: v.name}
Pydantic AI在profiles/google.py中已实现枚举自动转换,但建议显式定义以提高可读性。
4. const关键字不支持
当使用Literal类型或Field(const=...)定义常量值时,Pydantic会生成const关键字,而Gemini需要转换为单元素枚举。
转换示例:
# Pydantic生成
{
"type": "string",
"const": "required_value"
}
# 需要转换为
{
"type": "string",
"enum": ["required_value"]
}
此转换已在profiles/google.py中自动处理,但复杂场景仍需手动验证。
5. 数值范围关键字被忽略
Gemini API会忽略exclusiveMaximum和exclusiveMinimum等关键字,导致参数范围验证失效。
解决方案:使用Field(ge=..., le=...)替代,并在描述中明确说明范围:
from pydantic import BaseModel, Field
class TemperatureSetting(BaseModel):
# 使用包容性范围替代排他性范围
value: float = Field(
...,
ge=18.0, # 替代exclusiveMinimum
le=30.0, # 替代exclusiveMaximum
description="Temperature in Celsius (18.0-30.0, inclusive)"
)
兼容性适配工具使用指南
Pydantic AI提供了专门的GoogleJsonSchemaTransformer工具,可自动处理大部分兼容性问题:
from pydantic_ai.profiles.google import GoogleJsonSchemaTransformer
from pydantic import BaseModel
class UserQuery(BaseModel):
query: str
max_results: int = Field(..., ge=1, le=50)
# 生成兼容Gemini的Schema
schema = UserQuery.model_json_schema()
transformer = GoogleJsonSchemaTransformer(schema)
compatible_schema = transformer.transform(schema)
print(compatible_schema)
转换前后的Schema对比:
| 原始Schema | 转换后Schema |
|---|---|
"title": "UserQuery" |
移除title关键字 |
"max_results": {"type": "integer", "exclusiveMinimum": 0, "exclusiveMaximum": 51} |
"max_results": {"type": "integer", "minimum": 1, "maximum": 50} |
"additionalProperties": false |
移除该关键字 |
调试与监控最佳实践
使用内置调试工具
启用Schema转换调试日志,可在settings.py中配置:
from pydantic_ai import settings
settings.log_level = "DEBUG"
settings.log_schema_transformations = True
这将输出详细的Schema转换过程,帮助定位问题根源。
监控Schema兼容性问题
集成Logfire监控可实时跟踪Schema相关错误:
from pydantic_ai import Agent, logfire
agent = Agent(tools=[...])
logfire.configure() # 启用监控
# 所有Schema转换和错误将被记录
response = agent.run("处理用户请求")
总结与展望
Pydantic AI与Gemini API的JSON Schema兼容性问题主要源于标准实现差异,通过本文介绍的转换工具和适配模式,大部分问题可自动解决。关键是要:
- 避免使用递归数据结构
- 显式处理枚举和常量类型
- 使用包容性数值范围
- 启用Schema转换调试日志
随着Gemini API对JSON Schema支持的不断完善,这些兼容性层将逐步简化。Pydantic AI团队也在持续优化google.py中的转换逻辑,建议定期更新至最新版本以获取更好的兼容性支持。
希望本文解决了你在集成过程中遇到的兼容性问题!如果有其他疑问或发现新的兼容性问题,欢迎在项目issues中反馈。
点赞+收藏本文,下次遇到Schema问题时可快速查阅解决方案。关注我们获取更多Pydantic AI最佳实践指南!
更多推荐


所有评论(0)