Skip to content

[Bug] .env 配置加载系统 8 个 bug — 从类型转换到 AttributeError 崩溃 #22

Description

@T0708H

Summary

在对 .env 配置加载、YAML 合并逻辑和环境变量映射的代码审查中,发现 8 个配置加载系统 bug,分布在 app/config/app/infra/ 两个并行配置系统中。这些问题会导致运行崩溃、配置忽略和调试困难。


🔴 CRITICAL

Bug 1: _Settings 缺失 rerank_* 属性 → 运行时 AttributeError

  • 文件: app/config/settings.py, app/services/rag/reranker.py, app/test/eval/runner.py
  • 症状: _Settings 类仅定义了 appserverrdbmsllmembeddingchunkagenticasrlangsmithsessionredissecurity 属性,缺少 rerank_enabledrerank_providerrerank_modelrerank_top_n 属性
  • 后果: reranker.py:205 访问 settings.rerank_enabled 时抛出 AttributeErrorrunner.py:343-346_config_snapshot() 同样崩溃
  • 修复: 在 _Settings 中添加对应的 rerank_* property
# settings.py 需添加:
@property
def rerank_enabled(self) -> bool:
    return bool(_get("rerank", "enabled", default=False))

🟠 HIGH

Bug 2: infra/config.pyenv_file 为相对路径

  • 文件: app/infra/config.py
  • 症状: model_configenv_file=".env" 是相对路径,若从非项目根目录启动应用,pydantic-settings 无法找到 .env 文件
  • 对比: app/config/loader.py_load_dotenv() 正确使用了绝对路径 (root / ".env")
  • 影响范围: app/infra/rdbms.pyapp/infra/redis.pyapp/infra/mongo.pyapp/infra/milvus.pyapp/infra/minio.py 等所有 infra 组件
  • 修复: 改为相对于 __file__ 的绝对路径,或使用 pydantic-settings 的 env_file 绝对路径

Bug 3: test_config_cleanup.py 测试断言与代码不一致

  • 文件: app/test/test_config_cleanup.py, app/infra/config.py
  • 症状: 测试 TestInfraConfigHasNoAgenticSection 断言 infra_config 不含 agentic 字段,但 infra/config.py:366 仍定义了 agentic: AgenticSection
  • 后果: 运行此测试必然失败
  • 修复: 要么移除 infra/config.py 中的 agentic 字段(如果已废弃),要么更新测试断言

🟡 MEDIUM

Bug 4: 旧版环境变量无法覆盖 YAML 值

  • 文件: app/config/loader.py
  • 症状: _apply_legacy_env_overrides 仅在 existing is None or existing == "" 时生效。但 YAML 已设置 tracing_v2: true(布尔值),导致用户在 .env 中设置 LANGCHAIN_TRACING_V2=false静默忽略
  • 后果: 用户无法通过环境变量关闭 LangSmith trace
  • 修复: 旧版 env var 的优先级应高于 YAML(与文档声明的配置层级一致)
# loader.py:121 应改为:
if existing is None:
    # 环境变量优先级高于 YAML,不存在时才用 YAML 默认值
    node[path[-1]] = value

Bug 5: 环境变量字符串未做类型转换

  • 文件: [app/config/loader.py](app/config/loader.py#L111, L129)
  • 症状: 新旧两种 env var 映射都直接将 os.environ 字符串存为值。bool("false") 在 Python 中为 True(非空字符串为真)
  • 后果: _Settings 中用 bool() 转换始终返回 True,用户无法通过 env var 设置 false
  • 对比: infra/config.py 的 Pydantic 层正确处理了类型转换
  • 修复: 在 _apply_new_style_env_overrides_apply_legacy_env_overrides 中添加类型推断逻辑

Bug 6: 新式 env var(双下划线)可注入任意配置路径

  • 文件: app/config/loader.py
  • 症状: _apply_new_style_env_overrides 对任意包含 __ 的环境变量创建中间字典节点,无白名单/校验
  • 后果: 设置 FAKE__NONEXISTENT__KEY=value 会在配置树中静默创建路径,无人读取但占用内存
  • 修复: 添加已知配置键白名单校验,或记录未知键的 warning 日志

🟢 LOW

Bug 7: LANGSMITH_API_KEY 命名不一致

  • 文件: app/config/default.yaml, app/config/config.yaml, .env
  • 症状: default.yaml:172 注释写 LANGSMITH__API_KEY(双下划线),config.yaml:234 注释写 LANGSMITH_API_KEY(单下划线),.env:115 使用单下划线形式
  • 后果: 虽然两种形式通过不同路径都能工作,但注释矛盾会误导开发者
  • 修复: 统一注释和文档

Bug 8: minio.bucketdefault.yamlconfig.yaml 中不一致

  • 文件: app/config/default.yaml, app/config/config.yaml
  • 症状: default.yamlbucket: drive-videosconfig.yamlbucket: bilirag。由于 config.yaml 后加载覆盖,实际使用 bilirag
  • 后果: 若启用 BILIRAG_SKIP_CONFIG=1 跳过 config.yaml,bucket 名会静默变为 drive-videos
  • 修复: 统一两个文件中的 bucket 值

根因分析

项目存在两套并行配置系统

  1. app/config/loader.py → 自定义层级 YAML 查看器 + env 覆盖
  2. app/infra/config.py → Pydantic-settings + YamlConfigSettingsSource

两套系统各自加载 .env 和 YAML,但路径解析、类型转换和变量映射逻辑相互独立,容易产生行为分歧。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions