支持自动加载.env并补充环境变量模板
- 为 configuration.py 增加项目根目录 .env 自动加载能力,启动时无需再手动 export\n- 新增 .env.example,补齐数据库、Redis、邮件、LLM 与后台 secret 等完整环境变量模板\n- 更新 .gitignore 与 README,明确 .env 的使用方式与优先级说明
This commit is contained in:
57
.env.example
Normal file
57
.env.example
Normal file
@@ -0,0 +1,57 @@
|
||||
# ABOT 生产环境示例配置
|
||||
# 使用方式:
|
||||
# 1. 复制为 `.env`
|
||||
# 2. 按实际情况替换敏感值
|
||||
# 3. 直接启动 `python main.py`,程序会自动加载该文件
|
||||
|
||||
ABOT_ENVIRONMENT=production
|
||||
ABOT_PLUGIN_DIR=plugins
|
||||
|
||||
ABOT_DB_POOL_NAME=wechat_boot_pool
|
||||
ABOT_DB_POOL_SIZE=10
|
||||
ABOT_DB_HOST=127.0.0.1
|
||||
ABOT_DB_PORT=3306
|
||||
ABOT_DB_USER=root
|
||||
ABOT_DB_PASSWORD=please_change_me
|
||||
ABOT_DB_NAME=message_archive
|
||||
ABOT_DB_CHARSET=utf8mb4
|
||||
|
||||
ABOT_REDIS_HOST=127.0.0.1
|
||||
ABOT_REDIS_PORT=6379
|
||||
ABOT_REDIS_PASSWORD=
|
||||
ABOT_REDIS_DB=0
|
||||
|
||||
ABOT_EMAIL_SMTP_SERVER=smtp.163.com
|
||||
ABOT_EMAIL_SMTP_PORT=465
|
||||
ABOT_EMAIL_SENDER=
|
||||
ABOT_EMAIL_PASSWORD=
|
||||
ABOT_EMAIL_ALERT_RECIPIENT=
|
||||
|
||||
ABOT_GLANCES_HOST=127.0.0.1
|
||||
ABOT_GLANCES_PORT=61208
|
||||
|
||||
ABOT_WX_ADMIN=admin
|
||||
|
||||
ABOT_LLM_DEFAULT_BACKEND=dify_workflow_chat
|
||||
ABOT_LLM_DIFY_API_BASE_URL=http://127.0.0.1:8080/v1
|
||||
ABOT_LLM_DIFY_WORKFLOW_CHAT_API_KEY=
|
||||
ABOT_LLM_DIFY_MEMBER_CONTEXT_API_KEY=
|
||||
ABOT_LLM_DIFY_MESSAGE_SUMMARY_API_KEY=
|
||||
ABOT_LLM_DIFY_DOUYU_REPORT_API_KEY=
|
||||
ABOT_LLM_DIFY_GLOBAL_NEWS_API_KEY=
|
||||
ABOT_LLM_DIFY_AUTO_REPLY_API_KEY=
|
||||
|
||||
ABOT_LLM_GAME_TASK_API_URL=https://api.example.com/v1/chat/completions
|
||||
ABOT_LLM_GAME_TASK_API_KEY=
|
||||
ABOT_LLM_GAME_TASK_MODEL=doubao-1-5-lite-32k-250115
|
||||
|
||||
ABOT_LLM_AUTO_REPLY_API_BASE_URL=https://api.example.com/v1
|
||||
ABOT_LLM_AUTO_REPLY_API_KEY=
|
||||
ABOT_LLM_AUTO_REPLY_MODEL=gpt-5.4
|
||||
|
||||
ABOT_LLM_IMAGE_API_BASE_URL=https://api.example.com/v1
|
||||
ABOT_LLM_IMAGE_API_KEY=
|
||||
ABOT_LLM_IMAGE_MODEL=gpt-image-1
|
||||
|
||||
# 可选:若希望后台登录会话在重启后保持稳定,建议显式配置。
|
||||
ABOT_DASHBOARD_SECRET_KEY=
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.*
|
||||
!.gitignore
|
||||
!.env.example
|
||||
!.github/
|
||||
|
||||
*pyc
|
||||
|
||||
10
README.MD
10
README.MD
@@ -126,18 +126,16 @@ sudo apt-get install -y fonts-noto-color-emoji fonts-noto-cjk fonts-wqy-microhei
|
||||
|
||||
### 1. 配置文件
|
||||
|
||||
推荐先复制 `config.example.yaml` 为 `config.yaml`,再通过环境变量注入敏感信息:
|
||||
推荐先复制 `config.example.yaml` 为 `config.yaml`,再在项目根目录放置 `.env` 文件。程序启动时会自动加载该文件,不需要每次手动 `export`:
|
||||
|
||||
```bash
|
||||
# Linux / Mac
|
||||
cp config.example.yaml config.yaml
|
||||
export ABOT_DB_PASSWORD="你的数据库密码"
|
||||
export ABOT_LLM_DIFY_WORKFLOW_CHAT_API_KEY="你的 Dify Key"
|
||||
cp .env.example .env
|
||||
|
||||
# Windows PowerShell
|
||||
Copy-Item config.example.yaml config.yaml
|
||||
$env:ABOT_DB_PASSWORD="你的数据库密码"
|
||||
$env:ABOT_LLM_DIFY_WORKFLOW_CHAT_API_KEY="你的 Dify Key"
|
||||
Copy-Item .env.example .env
|
||||
```
|
||||
|
||||
`config.yaml` 现已支持 `${ENV_NAME}` / `${ENV_NAME:默认值}` 两种写法:
|
||||
@@ -145,6 +143,8 @@ $env:ABOT_LLM_DIFY_WORKFLOW_CHAT_API_KEY="你的 Dify Key"
|
||||
- `${ABOT_DB_PASSWORD}`:必须由环境变量提供,否则启动时报错
|
||||
- `${ABOT_DB_HOST:127.0.0.1}`:若环境变量缺失,则回退默认值
|
||||
|
||||
如果项目根目录存在 `.env`,系统会先自动加载该文件,再执行 `config.yaml` 占位符解析。
|
||||
|
||||
启动时系统会自动执行配置完整性检查,并在日志中输出脱敏后的配置快照。包含以下主要配置项:
|
||||
|
||||
#### 数据库配置
|
||||
|
||||
@@ -42,6 +42,11 @@ class Config(object):
|
||||
def __init__(self, config_path: str = None) -> None:
|
||||
self.project_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
self.config_path = config_path or os.path.join(self.project_dir, "config.yaml")
|
||||
# 启动阶段优先尝试自动加载项目根目录下的 `.env`:
|
||||
# 1. 用户只需要把 `.env` 放到线上目录,不必每次手动 export;
|
||||
# 2. 这里刻意保持“已有系统环境变量优先”,避免覆盖运维层显式注入的值;
|
||||
# 3. 不额外引入第三方依赖,保持部署门槛尽量低。
|
||||
self._load_local_env_file(os.path.join(self.project_dir, ".env"))
|
||||
self.raw_config = {}
|
||||
self.resolved_config = {}
|
||||
self.unresolved_placeholders = []
|
||||
@@ -54,6 +59,50 @@ class Config(object):
|
||||
yconfig = yaml.safe_load(fp) or {}
|
||||
return yconfig
|
||||
|
||||
@staticmethod
|
||||
def _strip_optional_quotes(value: str) -> str:
|
||||
"""去掉 `.env` 中常见的首尾引号。"""
|
||||
text = str(value or "").strip()
|
||||
if len(text) >= 2 and text[0] == text[-1] and text[0] in {"'", '"'}:
|
||||
return text[1:-1]
|
||||
return text
|
||||
|
||||
def _load_local_env_file(self, env_path: str) -> None:
|
||||
"""从本地 `.env` 文件加载环境变量。"""
|
||||
if not os.path.exists(env_path):
|
||||
return
|
||||
|
||||
try:
|
||||
with open(env_path, "r", encoding="utf-8") as env_file:
|
||||
for raw_line in env_file:
|
||||
line = str(raw_line or "").strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
|
||||
# 兼容 `export KEY=value` 写法,方便 Linux 用户直接复用 shell 风格文件。
|
||||
if line.startswith("export "):
|
||||
line = line[len("export "):].strip()
|
||||
|
||||
if "=" not in line:
|
||||
continue
|
||||
|
||||
key, value = line.split("=", 1)
|
||||
key = str(key or "").strip()
|
||||
value = self._strip_optional_quotes(value)
|
||||
if not key:
|
||||
continue
|
||||
|
||||
# `.env` 只在“当前进程还没有这个变量”时兜底注入:
|
||||
# 1. 显式传入的系统环境变量优先级更高;
|
||||
# 2. 这样本地调试和线上运维都可以覆盖 `.env` 默认值;
|
||||
# 3. 也避免启动时误把运维平台上的密钥覆盖掉。
|
||||
if key not in os.environ:
|
||||
os.environ[key] = value
|
||||
except Exception:
|
||||
# `.env` 自动加载属于增强能力,不应因为格式问题直接把启动打死。
|
||||
# 真正的必填项缺失会在后续 validate 阶段给出明确错误。
|
||||
return
|
||||
|
||||
def _resolve_env_placeholders_in_string(self, raw_value: str, path: str) -> str:
|
||||
"""解析字符串中的环境变量占位符。"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user