Files
life-echo/api/docs/configuration.md
Sully 53e0065e3e refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
2026-05-22 13:44:50 +08:00

112 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 配置 SSOTTOML + .env
Life Echo API 配置分为两层,避免 env 膨胀,同时保留密钥安全边界。
## 两层 SSOT
| 层 | 来源 | 改什么 | 如何生效 |
|----|------|--------|----------|
| **Secrets / bootstrap** | [`.env.example`](../.env.example) → `.env.development` / staging / production | `DATABASE_URL``SECRET_KEY`、API 密钥、支付/Liblib 私钥 | 改 env重启进程 |
| **非密钥配置** | [`config/default.toml`](../config/default.toml) + `config/{APP_ENV}.toml` | 功能开关、token 过期、SMS 模板 ID、Chat/Memoir 调参、OTel 等 | 改 TOML**发版**(随镜像/代码部署) |
`APP_ENV` 必须在 `.env` 中设置,用于选择 overlay`development` / `staging` / `production`
加载逻辑:[`app/core/app_config_loader.py`](../app/core/app_config_loader.py) 深合并 `default.toml``{APP_ENV}.toml`,经 Pydantic 校验后暴露为 [`app_config`](../app/core/app_config.py)。
## 文件说明
```
api/config/
default.toml # 全量默认值(所有 section
development.toml # 本地差异OTel、mock 登录、dev COS 等)
staging.toml # 预发差异CORS、SMS/COS 业务 ID 等)
production.toml # 生产差异
```
TOML 顶层 section 与代码模块对应:
| Section | 用途 |
|---------|------|
| `[deploy]` | 原 Settings 非密钥项开关、SMS 模板、CORS、OTel endpoint 等) |
| `[chat]` | 访谈 / 对话 |
| `[memoir]` | 回忆录流水线 |
| `[memory]` | Memory 富化 / compaction |
| `[story]` | Story / 章节 |
| `[eval]` | 内网评测 / judge |
| `[llm]` `[asr]` `[tts]` `[celery]` `[alembic]` `[agent_log]` `[otel]` `[misc]` | 运行时默认 |
业务代码仍可通过原有 import 读取(薄 re-export
- `from app.features.conversation.constants import chat`
- `from app.core.runtime_constants import llm_defaults`
- `settings.enable_tts` 等 deploy 字段通过 [`SettingsFacade`](../app/core/config.py) 代理到 TOML
## 常见操作
**改访谈温度**
```toml
# config/default.toml 或 config/staging.toml
[chat]
interview_temperature = 0.7
```
**改生产 CORS**
```toml
# config/production.toml
[deploy]
api_cors_origins = "https://your-domain.com"
```
**改 DeepSeek API Key** — 仍在 `.env`
```env
DEEPSEEK_API_KEY=sk-...
```
## 旧 env 键对照(节选)
| 旧 env 键 | 新位置 |
|-----------|--------|
| `CHAT_INTERVIEW_PERSONA` | `[chat] interview_persona` |
| `CHAT_INTERVIEW_TEMPERATURE` | `[chat] interview_temperature` |
| `MEMOIR_ORAL_NORMALIZE_MODE` | `[memoir] oral_normalize_mode` |
| `MEMORY_COMPACTION_ENABLED` | `[memory] compaction_enabled` |
| `EVAL_JUDGE_MODEL` | `[eval] judge_model` |
| `DEEPSEEK_BASE_URL` | `[llm] deepseek_base_url` |
| `ENABLE_TTS` | `[deploy] enable_tts` |
| `TENCENT_SMS_SDK_APP_ID` | `[deploy] tencent_sms_sdk_app_id` |
| `OTEL_ENABLED` | `[deploy] otel_enabled` |
| `SECRET_KEY` | 仍在 `.env` |
## 测试
- 设置 `CONFIG_DIR` 指向 fixture 目录可隔离加载:见 [`tests/test_app_config_loader.py`](../tests/test_app_config_loader.py)
- `tests/test_settings_allowlist.py` 防止 Settings 字段反弹
## Docker
`config/``COPY . .` 打入镜像compose 仍 `env_file: .env` 注入密钥。确保容器内 `APP_ENV` 与目标 overlay 文件名一致。
### Redis / Celery 分离
| 用途 | 默认 DB | 环境变量 |
|------|---------|----------|
| 会话、对话历史、task tracker 等业务 key | DB/0 | `REDIS_URL` |
| Celery broker + result backend | DB/1 | `CELERY_REDIS_URL`compose 显式注入;未设时由 `REDIS_URL` 自动 +1 |
**升级注意:** 启用 DB 分离后,旧版在 DB/0 上未消费的 Celery 消息会被丢弃(一次性 cutover无需迁移脚本
`REDIS_URL` 使用 DB/15必须显式设置 `CELERY_REDIS_URL`Redis 仅支持 logical DB 015无法 auto +1
## Shell 脚本与 TOML
| 脚本 | 仍读 `.env` | 已改读 TOML |
|------|-------------|-------------|
| `development.sh` | `APP_ENV`、密钥、`OTEL_ENABLED`legacy 覆盖) | `deploy.otel_enabled` → 是否起 Grafana 栈;`eval.internal_enable_docs` → 是否打印 `/docs` 链接 |
| `deploy.sh` | 密钥、`DATABASE_URL` 等 | SMS 模板等不再检查 env`config/production.toml` |
| `verify_observability_metrics.sh` | — | 提示文案指向 `deploy.otel_enabled` |
**勿再依赖** `.env` 中的 `OTEL_ENABLED``MOCK_SMS_LOGIN_ENABLED``INTERNAL_EVAL_ENABLE_DOCS` 等(应用运行时已从 TOML 读取);测试里 `os.environ["OTEL_ENABLED"]` 亦已无效,见 `tests/conftest.py`