feat(scenarios): 兼容非法配置并展示错误摘要
This commit is contained in:
@@ -36,15 +36,15 @@ def _get_nested(config: dict, path: tuple[str, ...]):
|
||||
|
||||
|
||||
def validate_scenario(config: dict) -> dict:
|
||||
# 只校验真正影响运行闭环的必填字段;
|
||||
# 页面展示类字段如 applicable_questions 允许缺失,并在归一化阶段补默认值。
|
||||
# 仅校验真正影响运行闭环的必填字段;
|
||||
# 页面展示字段允许缺失,并在归一化阶段补默认值。
|
||||
for field_path in REQUIRED_FIELDS:
|
||||
_get_nested(config, field_path)
|
||||
return normalize_scenario(config)
|
||||
|
||||
|
||||
def normalize_scenario(config: dict) -> dict:
|
||||
"""补齐页面和其他模块常用的派生字段,减少模板中的条件判断。"""
|
||||
"""补齐页面和其它模块常用的派生字段,避免模板层重复判断。"""
|
||||
normalized = dict(config)
|
||||
normalized["applicable_questions"] = list(config.get("applicable_questions") or [])
|
||||
normalized["rag"] = dict(config.get("rag", {}))
|
||||
@@ -62,16 +62,47 @@ def _scenario_files() -> list[Path]:
|
||||
return sorted([*config_dir.glob("*.yaml"), *config_dir.glob("*.yml")])
|
||||
|
||||
|
||||
def _read_yaml_file(path: Path) -> dict:
|
||||
with path.open("r", encoding="utf-8") as file:
|
||||
return yaml.safe_load(file) or {}
|
||||
|
||||
|
||||
def _collect_scenario_load_result() -> tuple[list[dict], list[dict]]:
|
||||
"""
|
||||
统一读取配置目录中的所有场景文件。
|
||||
|
||||
返回值:
|
||||
- scenarios: 校验通过的场景列表
|
||||
- issues: 非法 YAML / 缺字段等错误摘要,供首页展示
|
||||
"""
|
||||
scenarios = []
|
||||
issues = []
|
||||
for path in _scenario_files():
|
||||
try:
|
||||
config = _read_yaml_file(path)
|
||||
scenarios.append(validate_scenario(config))
|
||||
except (yaml.YAMLError, ScenarioValidationError) as exc:
|
||||
issues.append(
|
||||
{
|
||||
"file_name": path.name,
|
||||
"message": str(exc),
|
||||
}
|
||||
)
|
||||
return scenarios, issues
|
||||
|
||||
|
||||
def list_scenarios() -> list[dict]:
|
||||
# 首页每次读取最新 YAML,便于复试现场快速改题。
|
||||
scenarios = []
|
||||
for path in _scenario_files():
|
||||
with path.open("r", encoding="utf-8") as file:
|
||||
config = yaml.safe_load(file) or {}
|
||||
scenarios.append(validate_scenario(config))
|
||||
scenarios, _issues = _collect_scenario_load_result()
|
||||
return scenarios
|
||||
|
||||
|
||||
def list_scenario_issues() -> list[dict]:
|
||||
"""返回配置异常摘要,便于页面明确提示而不是直接 500。"""
|
||||
_scenarios, issues = _collect_scenario_load_result()
|
||||
return issues
|
||||
|
||||
|
||||
def get_scenario(scenario_id: str) -> dict:
|
||||
for scenario in list_scenarios():
|
||||
if scenario["id"] == scenario_id:
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
from .services import list_scenarios
|
||||
from .services import list_scenario_issues, list_scenarios
|
||||
|
||||
|
||||
def index(request):
|
||||
# 首页只消费服务层给出的场景摘要,不自行拼装配置字段。
|
||||
return render(request, "scenarios/index.html", {"scenarios": list_scenarios()})
|
||||
return render(
|
||||
request,
|
||||
"scenarios/index.html",
|
||||
{
|
||||
"scenarios": list_scenarios(),
|
||||
"scenario_issues": list_scenario_issues(),
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user