Skip to content

多场景评委体系 · 技术参考

本页记录多场景评委体系的工程实现细节: 配置文件结构、关键脚本用法、OP2 输出格式与验证流程。

概念与设计原理见 多场景评委体系。 VM 部署步骤见 VM 多场景部署


1. 配置文件 Schema

1.1 scene.yaml

yaml
# scenes/<scene-slug>/scene.yaml
slug: <scene-slug>              # 必填: 全局唯一, a-z0-9 + 连字符

scene_type: review              # 必填: review | competition
                                # competition 场景强制: anchor_judge=null, show_scores_publicly=true

feishu:
  app_id_env: LARK_APP_ID_<SLUG>        # 飞书 App ID 的 env var 名
  app_secret_env: LARK_APP_SECRET_<SLUG>

access:
  whitelist_env: BOSS_WHITELIST_<SLUG>  # 白名单 env var (可选)
  rate_limit: 5                         # 每小时请求上限 (可选, 默认全局 cfg)

report:
  brand_prefix: <slug>          # 报告品牌前缀 (用于 reports/<brand>/)
  redact_review: false          # 是否脱敏回推结果

anchor_judge: tian              # review 场景: 锚点 slug; competition 场景: null (必须)
show_scores_publicly: false     # competition 场景: true (必须)

1.2 panel.yaml

yaml
# scenes/<scene-slug>/panel.yaml
extends: panels/default.yaml    # 继承基础 panel (推荐); 不填则完整定义

scoring_mode: sum_max_score     # 当前仅支持此模式
output_format: op2_6section     # 产出形态: op2_6section (打分报告) | workshop_ranking (排名榜)
                                # | meeting_summary (定性会议总结 deck, 见 §2.6)

# Panel 差异覆盖 (仅需描述与 extends 的不同之处)
judges_drop:
  - org-strategy                # 移除不需要的维度评委

judges_add:
  - slug: custom-judge
    display_name_cn: 自定义评委
    judge_category: dimension   # anchor | dimension
    skill_path: scenes/<slug>/judges/custom-judge/SKILL.md

judges_override:
  - slug: tian
    judge_category: anchor
    skill_path: anchors/tian/perspective/SKILL.md
    always_active: true

scoring_lenses_override:        # competition 场景常用: 完全替换 5 镜头
  - slug: biz_value
    display_name_cn: 业务价值
    max_score: 3
  - slug: ai_depth
    display_name_cn: AI 含量
    max_score: 3
  - slug: completeness
    display_name_cn: 完成度
    max_score: 2
  - slug: innovation
    display_name_cn: 创新性
    max_score: 2

Panel 继承规则:

  • extends 最多 1 层 (超出抛 PanelError)
  • judges_drop 按 slug 移除
  • judges_add 追加
  • judges_override 按 slug 覆盖字段
  • scoring_lenses_override 完全替换镜头列表

2. 关键脚本

2.1 scene_loader.py

bash
# 列出所有已定义场景 (含 scene_type / bot_env / anchor_judge)
python3 scripts/scene_loader.py list

# 加载单个场景 (输出 JSON)
python3 scripts/scene_loader.py load <scene-slug>

# 校验所有场景的配置合法性
python3 scripts/scene_loader.py validate

主要函数:

函数用途
load_scene(slug)加载并校验 scene.yaml,返回 SceneConfig
list_scenes()遍历 scenes/ 目录,返回所有已定义场景
find_scene_by_app_id(app_id)按飞书 App ID 反查场景 (路由用)
validate_scene(cfg)校验约束: competition 必须 anchor=null 等

2.2 panel_loader.py

bash
# 解析某场景的完整 panel(含 extends 合并后)
python3 scripts/panel_loader.py resolve scenes/<slug>/panel.yaml

# 计算总分上限
python3 scripts/panel_loader.py total-max <panel-path>

主要函数:

函数用途
resolve_panel(path)解析 panel.yaml,执行 extends 合并,返回 Panel
total_max_score(panel)所有 scoring_lenses.max_score 之和
grade_for_score(score, panel)按归一百分比返回 S/A/B/C/D 等级

等级标准 (与总分制无关,均按百分比):

等级百分比区间
S≥ 95%
A≥ 85%
B≥ 70%
C≥ 55%
D< 55%

2.3 op2_output.py

OP2 6 段式报告渲染器 — 纯函数,无 IO,无外部依赖。

python
from scripts.op2_output import render_op2_6section

report_md = render_op2_6section(
    panel=panel,          # resolve_panel() 的返回值
    scores={              # {lens_slug: score}
        "biz_value": 2.5,
        "ai_depth": 2.0,
        ...
    },
    comments={            # {lens_slug: "评委点评"}
        "biz_value": "方案在业务价值上...",
        ...
    },
    must_fix=["…"],       # 必改项列表 (<60%)
    suggestions=["…"],    # 补充建议列表 (60-79%)
    cuts=["…"],           # 删减建议列表
)

6 段输出结构:

段落内容触发条件
§1 总分 + 等级X / Y 分 · 等级 Z总是输出
§2 分项得分各维度进度条总是输出
§3 必改项红色警告,分项得分 < 60%有则输出
§4 补充建议分项得分 60-79%有则输出
§5 删减建议可去掉的冗余内容有则输出
§6 一页汇总表所有维度汇总总是输出

2.4 smoke_e2e.py

全链路静态校验 — 不调 LLM,不写磁盘,纯校验。

bash
# 校验单个场景(推荐)
make smoke-scene SCENE=<scene-slug>

# 等价命令
python3 scripts/smoke_e2e.py smoke-scene <scene-slug>

# 校验所有场景
python3 scripts/smoke_e2e.py smoke-all

校验内容:

  • scene_loader.load_scene(slug) 不抛错
  • panel_loader.resolve_panel(panel_path) 解析成功
  • 所有 skill_path 指向的文件实际存在
  • competition 场景:anchor_judge is None + show_scores_publicly: true
  • review 场景:anchor_judge 非空 + skill_path 指向锚点 SKILL.md

2.5 add_scene.py

scenes/_template/ 克隆新场景。

bash
# 创建 review 类型场景
python3 scripts/add_scene.py my-new-scene --type review

# 创建 competition 类型场景(自动处理 anchor=null / 公开/输出格式)
python3 scripts/add_scene.py my-new-scene --type competition

# 演习模式(不写磁盘)
python3 scripts/add_scene.py my-new-scene --type review --dry-run

2.6 meeting_summary 定性总结渲染器

output_format: meeting_summary 的场景 (会议总结评审) 不走打分 run_pipeline, 而是由 review_workeroutput_format 分派到平行的定性流水线 meeting_summary_pipeline.py (不进 Phase 0-5 打分 / 合议)。三个脚本各司其职:

脚本职责IO
meeting_summary_output.py纯函数: prompt 装配 / 评委产出解析 / markdown deck 渲染无 IO, 已单测
meeting_summary_pipeline.py装配层: 读会议材料 → 每评委各调一次 LLM → 渲 deck → 落 report.md + meeting-summary.md + reviews/<judge>.mdLLM + 磁盘
meeting_summary_pptx.pydeck → 4:1 大屏 PPTX (封面 + 每评委页)python-pptx (可选)
bash
# 手动跑一场会议总结 (worker 平时按 output_format 自动分派, 此命令供联调)
python3 scripts/meeting_summary_pipeline.py --doc <会议材> --brand <brand> --scene meeting-review

# 把已有 deck 单独渲成 4:1 大屏 PPTX (读 reports/<brand>/reviews/)
python3 scripts/meeting_summary_pptx.py <brand>
# → reports/<brand>/meeting-summary.pptx
  • deck 每评委四块: 判断逻辑 + 3 个亮点 + 3 项不足 + 一句话评价 (与打分场景的 5 镜头无关)。
  • 大屏 PPTX 为 best-effort: 缺 python-pptx 只是不出 pptx, 不影响 markdown deck 与 HTML/PDF 交付。
  • 交付: report.md / HTML / PDF 随飞书卡片回推; 大屏 PPTX 在出站脱敏关闭的内部场景下随卡一并回推 (meeting-summary.pptx), 脱敏开启的场景则留在 VM 供内部大屏取用 (§9.2 fail-close)。

3. HTTP API

boss_server (FastAPI, port 8421) 提供以下端点:

GET /v1/healthz

无需认证,始终返回 200。

json
{"status": "ok", "timestamp": "2026-06-26T12:00:00Z"}

GET /v1/scenes

需要 Bearer token (BOSS_API_TOKEN)。返回所有已定义场景及飞书 env 就绪状态。

json
{
  "scenes": [
    {
      "slug": "op2-company",
      "scene_type": "review",
      "panel_path": "scenes/op2-company/panel.yaml",
      "feishu": {
        "app_id_env": "LARK_APP_ID_OP2_COMPANY",
        "env_ready": true
      }
    }
  ],
  "env_ready_count": 2
}

env_ready 为 true 表示对应 env var 已在运行环境中设置(不暴露实际 App ID 值)。

POST /feishu/event

飞书事件回调入口。需要 FEISHU_VERIFICATION_TOKEN

当前为 A3 骨架(feishu_events.py 未完整实现),返回 {"status": "ignored", "reason": "事件处理器未部署 (A3)"} 作为降级兜底。


4. 系统服务与启动顺序

三个 systemd 服务,必须按顺序启动

boss-hermes        (HTTP API + 健康检查)

boss-review-worker (job queue 消费,调 LLM 跑评审)

boss-feishu-ws     (飞书长连接,多 bot 路由)

各服务对应的 systemd 模板见 templates/ 目录:

  • templates/boss-hermes.service.example
  • templates/boss-review-worker.service.example
  • templates/boss-feishu-ws.service.example

5. 开发流程

新增一个场景

bash
# 1. 克隆模板
python3 scripts/add_scene.py <new-slug> --type review

# 2. 编辑 scene.yaml(填写 feishu bot env var 名称等)
# 3. 编辑 panel.yaml(选择评委组合)
# 4. 如需专属评委,在 scenes/<slug>/judges/ 下新建 SKILL.md

# 5. 静态全链路校验
make smoke-scene SCENE=<new-slug>

# 6. 跑完整测试套件
make test

添加共享评委

bash
# 1. 在 scenes/shared-judges/<judge-slug>/ 下新建 SKILL.md
# 2. 跑 skill_lint 校验
python3 scripts/skill_lint.py scenes/shared-judges/<judge-slug>/SKILL.md

# 3. 在需要该评委的 panel.yaml 中追加引用
# 4. make smoke-scene + make test

6. 常见问题

Q: 场景加载时提示 PanelError: extends depth > 1 A: panel.yamlextends 目标本身也有 extends。目前只支持 1 层继承。改为直接继承 panels/default.yaml

Q: competition 场景加载报错 anchor_judge must be null A: 竞赛场景不能设置 anchor_judge,删除或设为 null

Q: smoke-scene 通过但 bot 没响应 A: smoke 是静态校验,不测试运行时状态。检查:① .env 中对应 LARK_APP_ID_* 是否已填;② boss-feishu-ws 服务日志是否有 "WS connected";③ GET /v1/scenesenv_ready: true

Q: /v1/scenes 返回 503 A: BOSS_API_TOKEN 未在 .env 配置,或未 export 到 systemd 服务环境。


相关: 多场景评委体系概念 · VM 多场景部署 · 开发路线图 · ADR-012

判断力工程化 · Judgement, Engineered · 主站 · GitHub