Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
71 lines
2.9 KiB
Python
71 lines
2.9 KiB
Python
"""
|
||
配置模块:集中读取环境变量。
|
||
|
||
阶段化系统提示词附加项目 使用 OpenAI 官方 SDK,所有可调项都通过环境变量注入,
|
||
方便切换到兼容 OpenAI 协议的其他厂商(Kimi / Doubao 等)。
|
||
"""
|
||
|
||
import os
|
||
|
||
try:
|
||
# 允许把配置写在 .env 里(可选依赖)
|
||
from dotenv import load_dotenv
|
||
|
||
load_dotenv()
|
||
except Exception: # pragma: no cover - dotenv 不是硬性依赖
|
||
pass
|
||
|
||
|
||
def _to_openrouter_model(model: str) -> str:
|
||
"""把模型名映射到 OpenRouter 命名空间(用于无 OPENAI_API_KEY 的回退路径)。"""
|
||
if "/" in model:
|
||
return model # 已是 OpenRouter 命名空间,原样使用
|
||
if model.startswith("gpt-"):
|
||
return "openai/" + model # gpt-* -> openai/gpt-*
|
||
if model.startswith("claude-"):
|
||
return "anthropic/claude-opus-4.8"
|
||
return "openai/gpt-5.6-luna" # 兜底:当前便宜旗舰
|
||
|
||
|
||
class Config:
|
||
"""运行时配置。"""
|
||
|
||
# 必填:OpenAI API Key(本实验默认用 OPENAI_API_KEY)
|
||
API_KEY: str = os.environ.get("OPENAI_API_KEY", "")
|
||
|
||
# 可选:兼容 OpenAI 协议的 base_url,默认官方地址
|
||
BASE_URL: str = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
|
||
|
||
# 可选:模型名,默认用当前便宜旗舰 gpt-5.6-luna 控制演示成本
|
||
MODEL: str = os.environ.get("OPENAI_MODEL", "gpt-5.6-luna")
|
||
|
||
# 采样温度,稍低一些让行为更稳定可复现
|
||
TEMPERATURE: float = float(os.environ.get("OPENAI_TEMPERATURE", "0.3"))
|
||
|
||
@classmethod
|
||
def validate(cls) -> None:
|
||
"""校验并按需应用通用回退。
|
||
|
||
0) gpt-5.x 系列直连 OpenAI 需组织验证(且这类推理模型只接受默认温度),
|
||
因此只要设置了 OPENROUTER_API_KEY,即便同时有 OPENAI_API_KEY,也优先走
|
||
OpenRouter,省去组织验证的麻烦;
|
||
1) 否则有 OPENAI_API_KEY -> 直连 OpenAI(尊重 OPENAI_BASE_URL);
|
||
2) 否则有 OPENROUTER_API_KEY -> 改走 OpenRouter,并映射模型名;
|
||
3) 都没有则报清晰错误。
|
||
"""
|
||
or_key = os.environ.get("OPENROUTER_API_KEY", "")
|
||
# gpt-5.x(含 gpt-5.6-luna 等推理旗舰)优先走 OpenRouter,规避组织验证。
|
||
needs_openrouter = cls.MODEL.startswith("gpt-5") and "/" not in cls.MODEL
|
||
if or_key and (needs_openrouter or not cls.API_KEY):
|
||
cls.API_KEY = or_key
|
||
cls.BASE_URL = "https://openrouter.ai/api/v1"
|
||
cls.MODEL = _to_openrouter_model(cls.MODEL)
|
||
return
|
||
if cls.API_KEY:
|
||
return
|
||
raise SystemExit(
|
||
"错误:未检测到 OPENAI_API_KEY 或 OPENROUTER_API_KEY 环境变量。\n"
|
||
"请先 `export OPENAI_API_KEY=...`(或 OPENROUTER_API_KEY),"
|
||
"或复制 env.example 为 .env 并填写。"
|
||
)
|