Pydantic 配置 Schema 设计
Pydantic 配置 Schema 设计
学习目标
理解 Nanobot 如何使用 Pydantic 实现 JSON 友好的 camelCase 配置格式与环境变量 snake_case 的统一。
前置知识
- SSOT 双写模式 — 配置管理的单一真相源
下文假设你已理解上述概念,直接聚焦 Nanobot 的具体实现。
项目实践
camelCase/snakeCase 双向兼容
基础模型通过 alias_generator 实现自动转换:
class Base(BaseModel): model_config = ConfigDict( alias_generator=to_camel, # snake_case → camelCase populate_by_name=True, # 接受两种格式 )这使得配置文件可以写为:
{ "agents": { "defaults": { "contextWindowTokens": 65536, // camelCase (JSON 推荐) "model": "anthropic/claude-opus-4-5" } }}同时也接受 Python 风格的 context_window_tokens。
环境变量自动映射
Config 继承 BaseSettings,支持环境变量覆盖:
class Config(BaseSettings): model_config = ConfigDict( env_prefix="NANOBOT_", # 前缀 env_nested_delimiter="__", # 嵌套分隔符 )环境变量映射规则:
NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-sonnet-4-6→config.agents.defaults.modelNANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-xxx→config.providers.openrouter.api_key
延迟类型解析
ToolsConfig 的工具子配置存在循环导入问题(工具模块需要 from nanobot.config.schema import Base),采用延迟解析:
class ToolsConfig(Base): web: WebToolsConfig = Field( default_factory=lambda: _lazy_default("nanobot.agent.tools.web", "WebToolsConfig") ) # ...
def _resolve_tool_config_refs(): """运行时延迟导入并 rebuild model。""" from nanobot.agent.tools.web import WebToolsConfig # ... ToolsConfig.model_rebuild() Config.model_rebuild()模型验证器
Config 使用 @model_validator 确保引用完整性:
@model_validator(mode="after")def _validate_model_preset(self) -> "Config": if "default" in self.model_presets: raise ValueError("model_preset name 'default' is reserved") name = self.agents.defaults.model_preset if name and name not in self.model_presets: raise ValueError(f"model_preset {name!r} not found") # ...智能 Provider 匹配
Config._match_provider() 实现了复杂的多级匹配逻辑:
- 强制指定 → 直接返回
- 模型前缀精确匹配 →
anthropic/claude→anthropic - 关键词模糊匹配 → 模型名包含
gpt→openai - 本地提供商 base URL 检测 →
api_base包含11434→ollama - 有 API Key 的网关回退 → OpenRouter、AiHubMix 等
问题与规避
循环导入
问题:工具配置类在工具模块中定义,但工具模块导入 config.schema。
规避:_resolve_tool_config_refs() 延迟到所有模块加载后调用,try/except ImportError 兼容首次导入失败。
设计取舍
为什么用 Pydantic 而非 configparser/YAML
原因:Pydantic 提供了 JSON 友好的序列化/反序列化、类型验证、环境变量映射、别名生成,一次性解决配置管理的所有痛点。