LightRAG/scripts/lib/generate_env.py
Claude 0a48c633cd
Add Schema-Driven Configuration Pattern
Implement comprehensive configuration management system with:

**Core Components:**
- config/config.schema.yaml: Configuration metadata (single source of truth)
- scripts/lib/generate_from_schema.py: Schema → local.yaml generator
- scripts/lib/generate_env.py: local.yaml → .env converter
- scripts/setup.sh: One-click configuration initialization

**Key Features:**
- Deep merge logic preserves existing values
- Auto-generation of secrets (32-char random strings)
- Type inference for configuration values
- Nested YAML → flat environment variables
- Git-safe: local.yaml and .env excluded from version control

**Configuration Coverage:**
- Trilingual entity extractor (Chinese/English/Swedish)
- LightRAG API, database, vector DB settings
- LLM provider configuration
- Entity/relation extraction settings
- Security and performance tuning

**Documentation:**
- docs/ConfigurationGuide-zh.md: Complete usage guide with examples

**Usage:**
```bash
./scripts/setup.sh  # Generate config/local.yaml and .env
```

This enables centralized configuration management with automatic
secret generation and safe handling of sensitive data.
2025-11-19 19:33:13 +00:00

206 lines
5.3 KiB
Python
Executable file
Raw 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.

#!/usr/bin/env python3
"""
环境变量生成器 - 将 YAML 配置转换为 .env 格式
从 config/local.yaml 读取配置,生成 .env 文件。
支持嵌套 YAML 扁平化为环境变量。
"""
import sys
from pathlib import Path
from typing import Any, Dict, List
import yaml
def flatten_dict(data: Dict, parent_key: str = '', sep: str = '_') -> Dict[str, Any]:
"""
扁平化嵌套字典
Args:
data: 嵌套字典
parent_key: 父级键名
sep: 分隔符
Returns:
扁平化后的字典
Example:
{'trilingual': {'enabled': True}} -> {'TRILINGUAL_ENABLED': True}
"""
items = []
for key, value in data.items():
# 转换为大写并组合键名
new_key = f"{parent_key}{sep}{key}".upper() if parent_key else key.upper()
if isinstance(value, dict):
# 递归处理嵌套字典
items.extend(flatten_dict(value, new_key, sep=sep).items())
else:
items.append((new_key, value))
return dict(items)
def format_env_value(value: Any) -> str:
"""
格式化环境变量值
Args:
value: 原始值
Returns:
格式化后的字符串
Example:
True -> 'true'
123 -> '123'
'hello world' -> 'hello world'
"""
if isinstance(value, bool):
return 'true' if value else 'false'
elif isinstance(value, (int, float)):
return str(value)
elif isinstance(value, str):
# 如果字符串包含空格或特殊字符,添加引号
if ' ' in value or any(c in value for c in ['#', '$', '&', '|', ';']):
# 转义内部引号
escaped = value.replace('"', '\\"')
return f'"{escaped}"'
return value
elif value is None:
return ''
else:
return str(value)
def load_config(config_path: Path) -> Dict:
"""
加载 YAML 配置
Args:
config_path: 配置文件路径
Returns:
配置字典
"""
if not config_path.exists():
raise FileNotFoundError(f"配置文件不存在: {config_path}")
with open(config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
return config if config else {}
def generate_env_content(config: Dict) -> str:
"""
生成 .env 文件内容
Args:
config: 配置字典
Returns:
.env 格式的字符串
"""
# 扁平化配置
flat_config = flatten_dict(config)
# 按键名排序
sorted_items = sorted(flat_config.items())
# 生成 .env 内容
lines = [
"# LightRAG 环境变量配置",
"# 此文件由 scripts/setup.sh 自动生成,请勿手动编辑",
"# 修改 config/local.yaml 后重新运行 ./scripts/setup.sh 更新此文件",
"",
]
current_section = None
for key, value in sorted_items:
# 提取顶级 section第一个下划线之前的部分
section = key.split('_')[0]
# 如果切换到新 section添加分隔注释
if section != current_section:
if current_section is not None:
lines.append("") # 添加空行分隔
lines.append(f"# {section}")
current_section = section
# 添加键值对
formatted_value = format_env_value(value)
lines.append(f"{key}={formatted_value}")
return '\n'.join(lines) + '\n'
def save_env_file(content: str, env_path: Path) -> None:
"""
保存 .env 文件
Args:
content: .env 文件内容
env_path: 输出文件路径
"""
with open(env_path, 'w', encoding='utf-8') as f:
f.write(content)
def main():
"""主函数"""
# 获取项目根目录
project_root = Path(__file__).parent.parent.parent
# 文件路径
config_path = project_root / 'config' / 'local.yaml'
env_path = project_root / '.env'
print("=" * 70)
print(" 环境变量生成器")
print("=" * 70)
print()
try:
# 加载配置
print(f"📖 读取配置: {config_path.relative_to(project_root)}")
config = load_config(config_path)
print(f" 找到 {len(config)} 个顶级配置节")
# 生成 .env 内容
print(f"\n⚙️ 生成环境变量...")
env_content = generate_env_content(config)
# 统计生成的环境变量数量
env_count = len([line for line in env_content.split('\n') if '=' in line])
print(f" 生成 {env_count} 个环境变量")
# 保存 .env 文件
print(f"\n💾 保存文件: {env_path.relative_to(project_root)}")
save_env_file(env_content, env_path)
print()
print("=" * 70)
print(" ✅ 环境变量生成成功")
print("=" * 70)
print()
print(f"输出文件: {env_path}")
print()
print("提示:")
print(" - .env 文件已添加到 .gitignore不会提交到 Git")
print(" - 修改 config/local.yaml 后重新运行此脚本更新 .env")
print(" - 环境变量命名规则: 嵌套路径转大写并用下划线连接")
print(" 例如: trilingual.chinese.enabled -> TRILINGUAL_CHINESE_ENABLED")
print()
except Exception as e:
print(f"\n❌ 错误: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
main()