概述
最近在看一个开源项目 cognee ,其中有很多下面类似的pydantic配置文件,由于对 pydantic 没有深入了解,所以对 pydantic 中的 BaseSettings
的作用不是很了解。为了更清楚的了解 BaseSettings
的使用,通过查阅资料,本文记录一下其如何使用和配置。
python
class EmbeddingConfig(BaseSettings):
"""
Manage configuration settings for embedding operations, including provider, model
details, API configuration, and tokenizer settings.
Public methods:
- to_dict: Serialize the configuration settings to a dictionary.
"""
embedding_provider: Optional[str] = "openai"
embedding_model: Optional[str] = "openai/text-embedding-3-large"
embedding_dimensions: Optional[int] = 3072
embedding_endpoint: Optional[str] = None
embedding_api_key: Optional[str] = None
embedding_api_version: Optional[str] = None
embedding_max_tokens: Optional[int] = 8191
huggingface_tokenizer: Optional[str] = None
model_config = SettingsConfigDict(env_file=".env", extra="allow") # 从环境变量或.env文件中填充模型的字段
pydantic 中的 BaseSettings 介绍
在Pydantic库中,BaseSettings
是一个特殊的基类,用于定义配置管理模型。它扩展了Pydantic的BaseModel
,专门用于处理应用程序的设置或配置,这些配置通常来自多个来源(如环境变量、配置文件、秘密管理等)。使用BaseSettings
可以方便地管理和验证应用程序的配置。
主要作用:
- 多来源配置加载 :
BaseSettings
可以从多个来源加载配置,包括:
-
环境变量(默认)
-
环境文件(如
.env
文件) -
初始化时传入的字典或关键字参数
-
其他自定义来源(通过重写类方法实现)
-
自动类型转换和验证 :和
BaseModel
一样,BaseSettings
会对配置值进行类型转换和验证,确保配置项符合声明的类型和约束。 -
环境变量优先 :默认情况下,
BaseSettings
会优先从环境变量中读取配置,然后才是初始化参数或环境文件。这样便于在部署时通过环境变量覆盖配置。 -
敏感信息管理:支持从秘密管理服务(如Docker Secrets、Kubernetes Secrets)加载敏感数据。
使用示例:
下面是一个简单的BaseSettings
使用示例:
python
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppSettings(BaseSettings):
app_name: str = "My App"
host: str = "localhost"
port: int = 8000
debug: bool = False
model_config = SettingsConfigDict(env_file=".env", env_prefix="APP_")
在这个例子中:
-
配置类
AppSettings
继承自BaseSettings
。 -
定义了四个配置项,并提供了默认值。
-
通过
model_config
指定了环境文件为.env
,并且环境变量前缀为APP_
。
加载顺序:
当创建AppSettings
实例时,配置的加载顺序如下(从高优先级到低优先级):
-
初始化参数(如
AppSettings(port=8080)
) -
环境变量(如
APP_PORT
) -
环境文件(如
.env
文件中的APP_PORT
) -
类中字段的默认值
环境变量命名规则:
默认情况下,环境变量名由以下方式生成:
-
将字段名转换为大写
-
如果指定了
env_prefix
,则添加前缀 -
嵌套模型的环境变量名使用双下号
__
分隔(由env_nested_delimiter
配置,默认是双下划线)
例如,对于字段database_port
,如果env_prefix
设置为MYAPP_
,则环境变量名为MYAPP_DATABASE_PORT
。
与普通BaseModel
的区别:
特性 | BaseModel |
BaseSettings |
---|---|---|
主要用途 | 数据验证和解析 | 应用程序配置管理 |
配置加载来源 | 仅初始化参数 | 环境变量、文件、初始化参数等 |
环境变量支持 | 无 | 有(默认) |
环境文件支持 | 无 | 有(通过配置) |
敏感信息管理 | 无 | 有(通过secrets 配置) |
高级用法:
-
自定义来源 :通过重写
customise_sources
类方法,可以自定义配置加载的来源和顺序。 -
嵌套模型 :支持嵌套模型,环境变量可以通过分隔符(如
__
)来设置嵌套字段。 -
秘密管理 :通过
secrets_dir
指定目录,从文件中读取敏感信息(如SettingsConfigDict(secrets_dir="/run/secrets")
)。
Pydantic 的 SettingsConfigDict 配置作用解析
在Pydantic中,SettingsConfigDict
是一个用于配置模型行为的类,特别是在处理设置(通常来自环境变量或.env文件)时。它替代了旧版本Pydantic(v1)中的Config
内部类。
在前面提供的代码中,EmbeddingConfig
类继承自BaseSettings
(在pydantic_settings模块中)。 在这个类中,有一个类属性model_config
,它被赋值为SettingsConfigDict
的一个实例(在代码中是直接赋值,但通常我们会看到它被赋值为一个字典或一个SettingsConfigDict
对象)。 这里,SettingsConfigDict
的作用是配置EmbeddingConfig
类的行为。具体来说:
-
env_file=".env"
:指定从名为.env
的文件中读取环境变量。这意味着Pydantic在加载设置时会读取项目根目录下的.env
文件(如果存在的话),并将文件中的变量加载到环境变量中,然后这些环境变量会被用来填充模型的字段。例如:如果.env
中有EMBEDDING_API_KEY=sk-xxx
,会自动赋值给embedding_api_key
字段 -
extra="allow"
:这个配置表示,如果模型在初始化时遇到了不在模型定义中的额外字段(extra fields),那么允许这些字段存在,并且将它们存储在模型的__pydantic_extra__
属性中(而不是引发验证错误)。默认情况下,Pydantic模型会拒绝额外字段(即extra="forbid"
)。
总结一下,SettingsConfigDict
在这里的作用是配置EmbeddingConfig
类如何从环境变量(包括从.env文件加载)中获取设置,并且允许模型接受并存储额外的配置项(这些额外配置项虽然不会被用于模型定义的字段,但会被保留,可以通过 model_instance.__pydantic_extra__
访问)。
注意:在旧版Pydantic(v1)中,我们通常使用内部类Config
来设置这些配置,例如:
python
class Config:
env_file = ".env"
extra = "allow"
而在Pydantic v2中,推荐使用model_config
属性并赋值为SettingsConfigDict
的实例(或者也可以直接赋值为一个字典,因为SettingsConfigDict
本质上是一个字典的子类)。所以,这里使用的是Pydantic v2的方式。
另外,由于EmbeddingConfig
继承自BaseSettings
,它也会自动从环境变量中读取匹配的字段(不区分大小写,但通常使用大写)。例如,embedding_provider
字段会尝试从环境变量EMBEDDING_PROVIDER
中读取值。
所以,这个配置使得EmbeddingConfig
类可以从.env文件中加载环境变量,并且允许在初始化时传入额外的配置项。
完整功能说明:
配置项 | 作用 | 示例值 |
---|---|---|
env_file |
从指定文件加载环境变量 | ".env" , [".env", ".prod"] |
extra |
处理未定义字段的策略 | "allow" , "ignore" , "forbid" |
env_prefix |
环境变量前缀(自动添加) | "APP_" → 读取 APP_API_KEY |
case_sensitive |
环境变量名是否区分大小写 | False (默认不区分) |
env_nested_delimiter |
嵌套环境变量分隔符(如 DB__HOST → db.host ) |
"__" |
典型使用场景:
python
# .env 文件内容示例
EMBEDDING_PROVIDER=huggingface
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
UNEXPECTED_SETTING=123 # 会被保留到 __pydantic_extra__
python
# 使用配置
config = EmbeddingConfig() # 自动加载 .env 中的设置
print(config.embedding_provider) # 输出: "huggingface"
print(config.__pydantic_extra__) # 输出: {"unexpected_setting": 123}
注意事项:
-
优先级顺序 :
手动传入参数 > 环境变量 >
.env
文件变量 > 类默认值 -
安全建议 :
敏感字段(如 API keys)应通过环境变量传递,避免硬编码在代码或
.env
文件中 -
Pydantic 版本:
- v1 使用内部
Config
类 - v2 开始使用
model_config = SettingsConfigDict(...)
风格
- v1 使用内部
通过这种配置,Pydantic 实现了灵活的环境感知设置加载,非常适合需要多环境部署的应用(开发/测试/生产)。
代码演示
python
from pydantic_settings import BaseSettings, SettingsConfigDict
import os
class AppSettings(BaseSettings):
app_name: str = "My App"
host: str = "localhost"
port: int = 8000
debug: bool = False
model_config = SettingsConfigDict(env_file=".env", env_prefix="APP_")
# 当创建`AppSettings`实例时,配置的加载顺序如下(从高优先级到低优先级):
print(f'默认参数 AppSettings() =====> {AppSettings()}')
# 1. 初始化参数(如`AppSettings(port=8080)`)
print(f'指定初始化参数 AppSettings(port=8080) =====> {AppSettings(port=8080)}')
# 2. 环境变量(如`APP_PORT`)
os.environ['APP_PORT'] = "8888"
print(f'设置环境变量os.environ["APP_PORT"] = "8888",AppSettings() =====> {AppSettings()}')
print(f'设置环境变量os.environ["APP_PORT"] = "8888",AppSettings(port=8080) =====> {AppSettings(port=8080)}')
ini
默认参数 AppSettings() =====> app_name='My App' host='localhost' port=1 debug=False
指定初始化参数 AppSettings(port=8080) =====> app_name='My App' host='localhost' port=8080 debug=False
设置环境变量os.environ["APP_PORT"] = "8888",AppSettings() =====> app_name='My App' host='localhost' port=8888 debug=False
设置环境变量os.environ["APP_PORT"] = "8888",AppSettings(port=8080) =====> app_name='My App' host='localhost' port=8080 debug=False
最佳实践:
-
为敏感字段不设置默认值,强制从环境获取
-
使用
env_prefix
避免环境变量命名冲突 -
生产环境使用
secrets_dir
代替.env
文件pythonmodel_config = SettingsConfigDict( secrets_dir="/run/secrets", env_prefix="DB_" )
总结:
BaseSettings
是Pydantic中用于管理应用程序配置的强大工具,它简化了从不同来源加载和验证配置的过程,特别是在云原生和容器化环境中,环境变量是配置的主要来源时非常有用,特别适合需要遵循 12-Factor App 原则的应用程序。