feat(scenarios): 增强场景摘要与题型展示

This commit is contained in:
2026-05-30 00:33:34 +08:00
parent 81f17319ff
commit c57ab2f194
4 changed files with 36 additions and 2 deletions

View File

@@ -36,9 +36,23 @@ def _get_nested(config: dict, path: tuple[str, ...]):
def validate_scenario(config: dict) -> dict: def validate_scenario(config: dict) -> dict:
# 只校验真正影响运行闭环的必填字段;
# 页面展示类字段如 applicable_questions 允许缺失,并在归一化阶段补默认值。
for field_path in REQUIRED_FIELDS: for field_path in REQUIRED_FIELDS:
_get_nested(config, field_path) _get_nested(config, field_path)
return config 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", {}))
normalized["rag"]["enabled"] = bool(normalized["rag"].get("enabled"))
normalized["tools"] = list(config.get("tools") or [])
normalized["tool_count"] = len(normalized["tools"])
normalized["is_enabled"] = True
return normalized
def _scenario_files() -> list[Path]: def _scenario_files() -> list[Path]:
@@ -49,6 +63,7 @@ def _scenario_files() -> list[Path]:
def list_scenarios() -> list[dict]: def list_scenarios() -> list[dict]:
# 首页每次读取最新 YAML便于复试现场快速改题。
scenarios = [] scenarios = []
for path in _scenario_files(): for path in _scenario_files():
with path.open("r", encoding="utf-8") as file: with path.open("r", encoding="utf-8") as file:

View File

@@ -4,4 +4,5 @@ from .services import list_scenarios
def index(request): def index(request):
# 首页只消费服务层给出的场景摘要,不自行拼装配置字段。
return render(request, "scenarios/index.html", {"scenarios": list_scenarios()}) return render(request, "scenarios/index.html", {"scenarios": list_scenarios()})

View File

@@ -17,8 +17,16 @@
<ul class="meta-list"> <ul class="meta-list">
<li class="meta-badge">场景 ID{{ scenario.id }}</li> <li class="meta-badge">场景 ID{{ scenario.id }}</li>
<li class="meta-badge">输出:{{ scenario.output.type }}</li> <li class="meta-badge">输出:{{ scenario.output.type }}</li>
<li class="meta-badge">工具数:{{ scenario.tools|length }}</li> <li class="meta-badge">RAG{% if scenario.rag.enabled %}已启用{% else %}未启用{% endif %}</li>
<li class="meta-badge">工具数:{{ scenario.tool_count }}</li>
</ul> </ul>
<p class="muted" style="margin-top: 14px;">适用题型:
{% if scenario.applicable_questions %}
{{ scenario.applicable_questions|join:"、" }}
{% else %}
暂未配置
{% endif %}
</p>
<p style="margin-top: 16px;"> <p style="margin-top: 16px;">
<a class="button button-primary" href="{% url 'chat:index' scenario.id %}">进入对话</a> <a class="button button-primary" href="{% url 'chat:index' scenario.id %}">进入对话</a>
</p> </p>

View File

@@ -23,8 +23,18 @@ def test_get_scenario_returns_full_agent_config():
assert scenario["agent"]["role"] == "质量管理专家" assert scenario["agent"]["role"] == "质量管理专家"
assert scenario["rag"]["enabled"] is True assert scenario["rag"]["enabled"] is True
assert scenario["output"]["type"] == "quality_report" assert scenario["output"]["type"] == "quality_report"
assert "质量异常分析" in scenario["applicable_questions"][0]
def test_get_scenario_raises_clear_error_for_missing_id(): def test_get_scenario_raises_clear_error_for_missing_id():
with pytest.raises(ScenarioNotFound, match="场景不存在"): with pytest.raises(ScenarioNotFound, match="场景不存在"):
get_scenario("missing") get_scenario("missing")
def test_home_page_shows_applicable_questions(client):
response = client.get("/")
content = response.content.decode("utf-8")
assert response.status_code == 200
assert "适用题型" in content
assert "SOP 问答" in content