- 新增 inference/factory.build_inference_engine:读 GENESIS_INFERENCE__* / 裸 DEEPSEEK_API_KEY·LLM_BASE_URL 环境变量与 .env,构造 HttpLLMClient + InferenceEngine - orchestrator/qa_loop 的 engine=None 分支改用工厂,真正接通真实 LLM 路径 - 脚本注入校验改为通用(非空段落数 + 残留占位符),适配真实模式 - 补工厂测试(缺密钥/前缀变量/裸变量/默认值/.env 解析),覆盖率 99.04%
69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
"""真实 InferenceEngine 工厂:读取环境变量/.env 构造 HttpLLMClient + InferenceEngine。
|
||
|
||
设计要点:
|
||
- 不硬编码任何密钥;优先级 GENESIS_INFERENCE__* 环境变量 > 裸 DEEPSEEK_API_KEY/LLM_BASE_URL > 默认值。
|
||
- 自动加载仓库根目录 .env(被 .gitignore 忽略,密钥不入库)。
|
||
- engine=None 时由 orchestrator/qa_loop 调用,接通 P5-T10 人工质量门禁的真实 LLM 路径。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
from pathlib import Path
|
||
|
||
from genesis.config import InferenceModels, ModelSpec
|
||
from genesis.inference.client import HttpLLMClient
|
||
from genesis.inference.engine import InferenceEngine
|
||
from genesis.inference.exceptions import LLMNotConfiguredError
|
||
|
||
_DEFAULT_BASE_URL = "https://api.deepseek.com"
|
||
_DEFAULT_MODEL = "deepseek-chat"
|
||
_DEFAULT_FALLBACK = "qwen-max"
|
||
|
||
|
||
def _load_dotenv(path: Path = Path(".env")) -> None:
|
||
"""将 .env 中的 KEY=VALUE 注入 os.environ(仅当变量尚未设置时)。"""
|
||
if not path.is_file():
|
||
return
|
||
for raw in path.read_text(encoding="utf-8").splitlines():
|
||
line = raw.strip()
|
||
if not line or line.startswith("#") or "=" not in line:
|
||
continue
|
||
key, _, val = line.partition("=")
|
||
key = key.strip()
|
||
val = val.strip()
|
||
if len(val) >= 2 and val[0] in "\"'":
|
||
if val[-1] == val[0]:
|
||
val = val[1:-1]
|
||
os.environ.setdefault(key, val)
|
||
|
||
|
||
def build_inference_engine() -> InferenceEngine:
|
||
_load_dotenv()
|
||
api_key = os.environ.get("GENESIS_INFERENCE__API_KEY") or os.environ.get("DEEPSEEK_API_KEY")
|
||
base_url = (
|
||
os.environ.get("GENESIS_INFERENCE__BASE_URL")
|
||
or os.environ.get("LLM_BASE_URL")
|
||
or _DEFAULT_BASE_URL
|
||
)
|
||
model = (
|
||
os.environ.get("GENESIS_INFERENCE__MODEL")
|
||
or os.environ.get("LLM_MODEL")
|
||
or _DEFAULT_MODEL
|
||
)
|
||
fallback = (
|
||
os.environ.get("GENESIS_INFERENCE__FALLBACK_MODEL")
|
||
or os.environ.get("LLM_FALLBACK_MODEL")
|
||
or _DEFAULT_FALLBACK
|
||
)
|
||
if not api_key:
|
||
raise LLMNotConfiguredError(
|
||
"缺少 LLM API Key:请设置 GENESIS_INFERENCE__API_KEY"
|
||
"(或 .env / 环境变量 DEEPSEEK_API_KEY)"
|
||
)
|
||
models = InferenceModels(
|
||
primary=ModelSpec(name=model),
|
||
fallback=ModelSpec(name=fallback),
|
||
)
|
||
client = HttpLLMClient(base_url=base_url, api_key=api_key)
|
||
return InferenceEngine(client=client, models=models)
|