ray-pse-sharing — 事故分享卡片生成
将一份工艺安全事故报告(PDF/Word/文本 + 人工归纳)转化为一页美观大方的 A4 分享 PDF,用于安全培训、经验交流。
一、整体流程
事故调查报告 ──→ 人工/AI提取 ──→ JSON数据 ──→ pipeline.py ──→ HTML ──→ Playwright/Edge ──→ A4 PDF
↑ ↑ ↑
提取关键信息 填充{{placeholder}}模板 page.pdf(A4)
步骤:
1. 信息提取:从调查报告提炼 JSON 数据(见下节数据模型);缺失字段显式标注「未知」,不编造
2. 选择布局:side(描述较短 ≤400字)或 stack(描述较长),或自动
3. 运行管道:python pipeline.py --json data.json --layout side
4. 交付:编号-事故名称.pdf(单页 A4)
二、JSON 数据模型
{
"accident_info": {
"date": "2018年11月28日",
"location": "河北省张家口市盛华化工公司",
"type": "氯乙烯泄漏爆燃",
"severity": "重大事故(23死22伤)",
"severity_class": "high",
"material": "氯乙烯 (C₂H₃Cl)"
},
"accident_title": "培训版标题(结论式):直接给出教训判断,如「不受控的加热会导致气瓶爆炸」",
"viral_title": "公众号版标题(悬念式,可选):事故主体 + 核心矛盾反问,如「10KPa联锁为何挡不住40KPa静压?」",
"share_date": "2026年7月",
"sort_date": "20181128",
"description": "事故经过(≤380字,多段落,可用【事故】【失效链】【启示】分节)",
"highlight": ["企业名/核心概念", "可选,描述中要自动高亮的关键词(如企业名/物料/核心概念)"],
"image": {
"type": "svg",
"diagram_type": "gas_holder"
},
"protection_failure": [
"🧱 每条配独立emoji的保护层失效项(5条)",
"🔧 不同项用不同emoji,告别单调"
],
"knowledge": [
"工艺安全知识点(4-5条,~180字 total),原理/标准/教训类,带具体数值/型号。历史事故不再放这里",
"历史事故锚点全部移入独立 history 字段(v1.7)"
],
"history": [
"🏛️ 历史事故锚点标签带(v1.7 新增,可选):2-3条,每条≤30字",
"格式:年份+地点+事故+伤亡/损失数字,如「2015年天津港:约725吨硝酸铵爆炸,173人遇难」",
"渲染在知识/行动行之下、保护层失效之上的全宽米黄金色带——对标CCPS的差异化独有板块",
"缺省时此单元不渲染,完全兼容旧 JSON"
],
"what_to_do": [
"行动建议(5条,~200字 total)",
"祈使句省略主语(动词开头),不用「你应该」"
],
"hse_tools": [
"📋 安全要素/HSE工具标签(~10条,每条配独立emoji)",
"🔍 覆盖SOP/PHA/MI/GDS/SIS/PSI/MOC/培训/应急等"
],
"takeaway": "★ 可执行警句:一句能照做的安全要求(15~25字),如「应急程序必须涵盖所有主要危害,并通过演练来掌握」",
"reference": "参见:PSI-2021-002(同类RTO事故)/ CSB报告No.2019-1TX(可选,自家卡片互链或外部权威报告)",
"footer": {
"number": "PSI-2026-002",
"brand": "Ray谈化工 · 安全事故分享"
}
}
字段约束
| 字段 | 字数建议 | 条数 | 说明 |
|---|---|---|---|
sort_date |
YYYYMMDD | - | 事故发生的准确日期,以正文「事故经过」章节陈述为准——文件名尾缀年份有两种口径混用(事故年/报告批复发布年),封面日期也可能是发布日,均不能作事实来源(2026-09-04 用户红线:恒翔案封面 2020-08-10=发布日,正文 2019-10-11 才是事故日;全量扫描 188 份同类漂移仅 1 份)。批量时写卡前必须用正文日期正则提取并标注 date_source(body/cover/ambiguous),ambiguous 人工复核。单卡文件名用 {编号}-{标题}.pdf(footer.number,如 PSI-2026-009-xxx.pdf);sort_date 仅供合集按年代排序(批量时可作前缀 {sort_date}-{标题}.pdf) |
accident_title |
≤25字 | - | 上卡标题。默认培训版结论式(如「关闭不等于关到位,溶剂装车必须双人复核」);当结论式超过~20字或多重禁令显晦涩影响传播时,改用悬念式上卡(用户确认规则),被换下的培训版精简后存入 viral_title 轨 |
viral_title |
≤35字 | 0-1 | 双轨备用标题。与 accident_title 并行:培训版上卡时此字段存悬念式(公众号传播用);悬念式上卡时此字段存精简版培训结论。两轨不丢失 |
description |
≤380字 | 多段落 | 事故经过+机理+后果,可用【事故】【失效链】【启示】分节;超 380 字 footer 会被挤出第 1 页 |
highlight |
每词≤8字 | 1-3个 | 可选;描述中要自动高亮的词(企业名/物料/核心概念),如 ["利安隆凯亚"];缺省不高亮。不再硬编码(pipeline 从 JSON 读取) |
knowledge |
≤180字(合计) | 4-5条 | 工艺安全原理知识,带具体数值/型号(如自燃点464℃、LQD-350)更硬核。历史事故锚点移入 history(v1.7) |
history |
每条≤30字 | 2-3条 | v1.7 新增:历史事故锚点标签带(年份+地点+数字),渲染在知识/行动行之下、保护层失效之上。缺省不渲染 |
what_to_do |
≤180字(合计) | 5条 | 祈使句省略主语(动词开头:立即校核/加装/纳入),不用「你应该」 |
protection_failure |
每条≤25字 | 5条 | 每条配独立契合 emoji |
hse_tools |
每条≤20字 | ≤8条 | 每条配独立契合 emoji;超 8 条有溢出风险 |
takeaway |
≤30字 | - | ★ text ★ 对称装饰。可执行式警句:一句能照做的安全要求(Beacon 风格),不用文艺比喻式——文艺感留给标题 |
reference |
≤40字 | 0-1 | 可选。参见行:自家历史卡片互链(PSI-2021-00X)或外部权威报告(CSB No.XXX)。渲染在警句上方灰色小字 |
Image 类型
| type | 说明 | 需要参数 |
|---|---|---|
"photo" |
真实照片 | path: 图片路径(Base64内嵌) |
"svg" |
概念示意图 | diagram_type: gas_holder / explosion_fire / gas_leak / isolation_failure / insulation_fire / thermal_runaway / spherical_tank_bleve / thermal_oil_dry_heating / generic |
"" |
无图片 | 显示占位提示 |
三、双布局系统(原则:排版服务于内容和谐)
> 选布局的最终目的是让「具体文字内容」与「照片/示意图」的大小排布和谐。
> side(横排)与 stack(上下排)只是两种工具——Beacon 两种都有,按当期内容定。
> 拿不准时先生成两版截图对比,选更饱满、更平衡的那版。
Side 布局(侧边式)
- 适用:描述较短(≤400字)且条目少(<5),图片与文字同侧竖排
- 结构:左侧 50%(图片190px↑ + 描述)| 右侧 50%(你知道吗↑ + 你能做什么↓)
- 底部全宽:保护层失效 → HSE工具 → 参见行 → 红色核心警句
Stack 布局(堆叠式)
- 适用:描述较长(>400字)或知识/行动条目多(≥5)——Beacon 常见的「事故经过(上),你知道吗(下右)/你能做什么(下左)」即此形态
- 结构:上半行(描述 + 图片左右分栏)| 下半行(你知道吗左 + 你能做什么右)
- 底部全宽:同 side
自动选择
n_know = len(knowledge); n_act = len(what_to_do)
if len(description) > 400 or n_know >= 5 or n_act >= 5:
layout = "stack" # 描述长 或 条目多 → 左右并列更紧凑
else:
layout = "side" # 轻量卡片(描述短 + 条目 <5)
> ⚠️ side 布局陷阱:知识/行动各 5 条(标准配置)时,side 右侧「你知道吗↑你能做什么↓」上下堆叠会与左侧(图片+描述)高度不匹配,导致「你能做什么」下方大片空白。标准卡片(条目≥5)必须走 stack,side 仅用于条目 <5 的轻量卡片。
2026-08 Beacon 对标新增规范(v1.6.0,v1.7.0 修订)
- takeaway 可执行式:警句 = 一句能照做的安全要求(15~25字),不用文艺比喻——文艺感留给标题
- history 历史事故单元(v1.7 独立化):锚点不再放 knowledge,独立「🏛️ 历史事故」金色标签带(2-3条,年份+地点+伤亡数字),渲染在知识/行动行之下、保护层失效之上——对标CCPS的差异化独有板块,同时填补版面空白段
- 双标题轨:accident_title 结论式(培训分发)/ viral_title 悬念式(公众号传播,可选)
- reference 参见行:自家卡片互链或外部权威报告,可溯源=可信
- 示意图标注式:示意图必须画出关键设备 + 失效点红圈/箭头标注(图片是证据不是装饰,Beacon 全部图片带标注)
- 多区降饱和:保护层失效粉底、HSE工具蓝灰底、历史事故米黄金带、知识区浅灰——色彩柔和退后,内容站前排面
四、模板设计要点(经验总结)
| 元素 | 最终值 | 要点 |
|---|---|---|
| 页头标题 | 24px | 从 20px 起步逐步放大 |
| 事故标题 | 18px | 每轮约 +1-2px |
| 描述正文 | 14px | 行距 1.9 |
| 知识/行动项 | 12px | 行距 1.7 |
| 标签 | 11-12px | 保护层和HSE标签字号一致 |
| 核心警句 | 14px | 红色横幅白字,★ 装饰 |
核心教训:字体不是一次设对的。先确定字数范围,再反推字号。每轮"放大→截图→看留白→继续放大"直到刚好填满 A4。
- 字数上下限:描述 ≤380(超则溢出)/ ≥350(不足则底部留白)、知识/行动各 5 条 为撑满基准,配合 14px/12px 字号刚好填满 A4
- 满版拉伸机制(v1.11.1 起,Beacon 对标):
.protect-fail { margin-top:auto }已移除——改用 flex 拉伸让色块随空间生长:stack 的 content-cols/row-bot/know/dodo 均flex:1;side 的右栏 know/dodoflex:1上下顶满、左栏 card-imgheight:auto; min-height:150px随空间等比增长。内容不足时色块自动撑满,无空白段 - 布局比例:70/30 → 55/45 → 52/48 → 50/50 是 side 布局最终平衡点
- 保护层 vs HSE 工具:保护层失效(红 #FFF5F5 / #D50032 左边框)是事后分析;HSE 工具(蓝 #EBF5FB / #1A5276 左边框)是事前预防
- PDF 优于 PNG:PDF 矢量输出缩放无损,打印友好
.page用height: 297mm(v1.11.1 起):满版拉伸依赖固定高度分配 flex 空间;配 overflow:hidden 兜底。前提是底部块 padding 已压到位(hist/pf/hse 4px、takeaway 7px、reference 2px、footer 4px,合计留 ~23px 余量)——若新增内容导致 footer 溢出,第一步查底部块 padding 余量,而非改回 min-height
常见调优参数
| 问题 | 修复位置 |
|---|---|
| 底部留白太多 | 先确认内容达下限(描述≥350、知识/行动各5条);模板已内置 flex 满版拉伸,仍留白再增大 padding/字号/行距 |
| 内容溢出/警句被截 | 先查底部块 padding 余量(是否被调大);再减字号/行距/图片高度;最后查 .page 是否被改成 min-height |
| 描述过长 | 精简 JSON 描述至 400 字以内 |
| 图片太小 | 调 .layout-side .col-left .card-img { height: } |
| 标签换行不美观 | 增加 .pf-items / .ht-items 的 gap 值 |
| emoji 想换 | 直接改 JSON 数组中的 emoji 字符 |
五、管道使用
环境依赖
- Python 3.13+(标准库即可,无额外 pip 依赖)
- 渲染引擎:Playwright + Chromium(首选,稳定)或 Microsoft Edge(本机可能失效,见红线)
- ⚠️ 批量渲染链路必须用 venv python 完整路径(2026-09-05 实测:本机
py/pythonlauncher 会解析到无 playwright 的系统 Python,报No module named 'playwright'且 15 连败);py -c跑无依赖脚本不受影响。开工前先$PYV -c "import playwright"验证 - 资产文件同目录:
template.html、concept_diagram.py
命令
# side 布局(描述 ≤400字推荐)
python assets/pipeline.py --json shenghua_data.json --layout side
# stack 布局(描述 >400字推荐)
python assets/pipeline.py --json haidekai_data.json --layout stack
# 自动选择布局
python assets/pipeline.py --json my_accident.json
# 仅生成 HTML 中间文件
python assets/pipeline.py --json my_accident.json --no-shot
# 指定输出路径
python assets/pipeline.py --json my_accident.json --out 输出.pdf
输出
- PDF:
{编号}-{事故名称}.pdf(如PSI-2026-002-氯乙烯气柜泄漏...事故.pdf) - HTML 中间文件:
output_card.html(调试用)
六、批量模式(>20 张卡片)
单卡流程看第一~五章即可;批量生产时追加以下机制(2026-08-29 在 148 项批次中确立)。
批次执行总顺序(机制对应编号,顺序错了会返工):
批前:数据源全量提取(Excel→all_remaining.json)→ 按批切片 batch_XXX.json →
类型聚类统计(泄漏/火灾/爆炸/人身伤害分布)→ 锚点需求规划 →
承接批次先实测磁盘(ls+字段校验,不信会话总结——总结永远滞后于磁盘)
批中:每批 20-25 张,写卡(anchor_db.py pick 调度锚点 + history 整行复制 label_30 +
人名脱敏入词表)→ gen 一体化自检 → precheck(脱敏/乱码/字段/EN 残留)
渲染:Playwright 手动生命周期(禁用 browser.close())→ 页数自检=1 →
stack 溢出注入压缩 CSS → QC 拼屏目检
验收:judge 视觉验收(fitz 导 PNG(dpi=100) → Agent(judge) 分两组 8+7 并行 →
疑点先 grep JSON/fitz 抽 PDF 文本层证伪 → fail 修复后重渲复检)——
judge PASS 才算批完成;judge prompt 预声明已知模板特征防误报
批后:anchor_db.py scan-cards 全量对账 → consistency_check 全套体检 →
日志逐批记录(HANDOFF 只在切换对话时更新)→ 锚点库新核实条目回流
- 锚点数据库法(v1.9 起,替代旧台账法):history 锚点统一从内置数据库调度——
assets/anchor_db.json(数据)+scripts/anchor_db.py(CLI)。写卡前python anchor_db.py pick <事故类型> --dir <卡目录> --from N --to M拿推荐锚点(S级经典→年份新→批内少用排序);写卡后python anchor_db.py scan-cards <卡目录>全量对账(违规仅两种:pending 未核实/retired 已淘汰被引用;批内同锚点≥3次仅软提示)。新事故锚点必须 WebSearch 核实三要素(年份/伤亡/原因)后verify转 active 才可入卡;库外标签会被扫描指出,应补录入库。
- 设计原则(2026-08-29 用户确认):①首要任务是扩库——覆盖各类事故类型(特别是工艺安全),量足够大才能「快速定位直接应用」;②典型性三条款:a.影响大较知名 b.与类型适配 c.新事故优于旧事故(特别出名的经典除外);③「毕业」= 典型性复审(review --retire)而非使用次数上限——重要事故允许反复使用,事故分享就是要反复揣摩学习;used_count 仅作记录+防扎堆软提示。
- 分级:S=经典知名(不限次数,跨类型优先)/ A=典型行业事故(本类型首选)/ B=补充案例(复审不达标淘汰)。
- 换实体必须同步 4 字段:锚点改用另一条事故(原实体查无实据/张冠李戴)时,event+aliases+label_30要一起改,核实后置verified=true。只改 label_30 → 匹配走event/aliases对不上,scan-cards 把已入库锚点误报成「库外标签」(2026-08-29 实测 ANC-096 因此误报 6 张卡)。aliases 要覆盖卡内可能出现的写法(含「2021年黑龙江七台河」这类带省份前缀的完整写法)。
- history 整行复制 label_30:写卡时 history 条目整行复制锚点 label_30 原文(含年份),不凭记忆手打年份。手打会让同一锚点在不同卡里出现多个年份(实测 2024/2023/2019 三种写法并存),属 history 三要素失真。
- 库外标签先查匹配口径再改数据:scan-cards 报「库外标签」有两种成因——①卡内年份/写法错(改卡)②库内 event/aliases 缺该写法(改库)。先读match_anchor/norm_label判定逻辑再归因,不要一律当成卡错。
- 库随批自动收录已发卡事故(2026-09-05 实测,190 批):渲染交付后该卡事故会进入锚点库——后续批次的 pick 结果里会出现近期批事故(如「2019年中卫新澧」「2020年湖北天门」),本卡自己的事故严禁进自己的 history,pick 落盘分配 history 时逐批排除;近期批事故引用不受限(跨批重新计数)。 - 生成脚本一体化自检:JSON 校验 + 必填字段 + 脱敏词扫描 + PDF 页数自检写进同一 gen 脚本;支持单卡过滤参数断点重生成(
gen.py 66)。脱敏词库模块化(desens_vocab.py),生成与预检共用。词表三段式BAD = BASE + COMPANY + PERSONS(基地名/公司承包商/真实人名);每批写卡前把本批数据源里的真实人名全量追加进 PERSONS(148 批次每批 60-80 个),公司/承包商名入 COMPANY——漏一个就泄漏一个,precheck 扫 JSON 全文兜底。 - precheck 三档语义:P0 必修(脱敏残留/乱码/缺字段/PDF 页数≠1,零容忍)/ EN 白名单(60+ 正常术语不算英文残留)/
--legacy档(早期基线卡放宽不阻塞)。预检覆盖文本层,人工目检只看版式溢出与图表错位。 - 编号匹配交付物:验证脚本用 footer.number 编号前缀 glob 匹配 PDF,不按事故 type 反推文件名(文件会被重命名,编号不会)。
- 批后一致性检查:consistency_check 跑 8 维数值分布 + 结构检查(三段式/★/brand/emoji)+ 编号连续性,informational 输出保全套统一。禁用 emoji(⏱U+23F1/⏳U+23F3/⌛U+231B,白名单 U+1F300-1FAFF/U+2600-27BF 之外)已升为 precheck P0 FAIL 硬拦截(2026-09-05,190 批历次 3 次复发后落地,首跑清出 3 处历史存量)——写卡时表「时间」语义一律用 🕐/🕒,勿依赖事后人工查规则。
- 中间产物回收站清理:QC 截图/临时 HTML 用 SHFileOperationW + FOF_ALLOWUNDO 删除;rc 返回码不可信,以 os.path.exists 复核为准;不用 os.remove(不可恢复)。
- description 饱满区间 240-440 字(stack 布局实测):380 是溢出硬红线需逐卡验证,240 以下底部留白明显;「字数下限」用软警告不用硬报错。
- 编号与日期一致性:footer.number 用
PSI-{事故年份}-{三位 seq}——年份按事故发生年(非发布年/写卡年),同一年份内 seq 连续(148 批次:2023 年卡用 PSI-2023-099~110、2024 年卡用 PSI-2024-111~126、2025 年卡用 PSI-2025-127~148);share_date 同批统一、跨批递进(001-028=8月批/029+=9月批/074+=10月批);footer.brand、三段式【事故】【失效链】【启示】、★ 包裹、reference 互链格式批间一致(consistency_check 负责抓漂移,写卡时就要守)。
- 交付文件名 v2(2026-09-06 用户拍板):PSI-{事故年月日}-{年内序号3位}-{事故名称}.pdf(例PSI-20150716-001-日照石大科技「7·16」…)——序号=该事故在同年内按事故日期排序的位次,与 footer.number 一致,gen/precheck 的命名逻辑统一取自 footer.number(单卡重渲染自动带序号);全局时间浏览顺序由日期前缀天然保证。
- 年中插入重排策略(标识与序号分离):稳定标识=文件名「日期+事故名称」(永不改、全库唯一);序号=年内派生位次,可随时由脚本按 (sort_date, 原页脚序) 稳定排序重算。新事故落到年中→先临时末号交付→随后跑年内重排(更新 JSON+manifest footer→重渲染受影响卡→清旧名 PDF→其余原地改名),波及范围仅「该年、该日期之后」的卡(实证:2 张补录落年中,波及 23 张、数分钟);同日期对按原页脚序稳定 tie-break;不用空洞编号或子编号(重排成本已被确定性脚本摊平)。 - 渲染层两条:①禁用 browser.close()——本环境 close() 永久挂起且吞掉全部 stdout(exit 1 空输出),一律
pw = sync_playwright().start()手动管理生命周期、结束pw.stop(),print 加flush=True;不复用 pipeline 内置渲染函数(render_XXX.py 独立脚本按批复制改名,路径替换要同时改目录+文件名两段)。②stack 溢出注入压缩 CSS:knowledge 5 条×每条约 50-60 字导致 A4 溢出 2 页时,在</head>前注入.layout-stack局部压缩 CSS(字号 13→11px、行距 1.65→1.5、卡片图 200px 上限)——只对本批渲染生效,不改模板资产,批量一致性不被局部调整破坏。 - judge 视觉验收三协议(2026-09-05,190 项目 8-11 批 60 张验证):①100dpi PNG 字形误读率极高——judge 报「错字/截断/缺句」一律先 grep 卡 JSON 或 fitz 抽 PDF 文本层证伪,本周期 30+ 待核点全部为误读、JSON 层零实错;只有 JSON 确有问题才 fail。②judge prompt 预声明已知模板特征(右栏下部留白=与左列等高对齐的统一设计、示意图为通用图式小标签与情节不完全对应)——预声明后误报显著下降。③judge 并发受限(model concurrency limit)时不重试连发,先推进其他批工序稍后再派。
- QC PNG 匹配用「PSI-{事故日期}*{企业核心词}*」子串模式:交付名是
PSI-{事故日期}-{省市}{企业}「X·X」事故.pdf,不含 footer.number(编号匹配交付物那条仅适用于交付名=编号开头的项目);裸关键词/短词会撞历史同名卡——实测 3 次(同日期双匹配取 m[0] 错卡、「焦化厂」「中天东方」撞 2020/2022 同名卡),撞名后 QC 图错、交付 PDF 本身正确,判 fail 前先核对导出环节。 - 写卡脚本三条 assert + 薄素材纪律:写卡脚本 main 内置三断言——sort_date==body_date、footer.number==footer_number、description 不以「【启示】」结尾(分段写卡漏写启示正文=悬空标签,consistency 只查标记存在不查非空,曾由 judge 抓出)。薄素材卡(dump<4000字)WebSearch 官方通报补直接原因,来源层级:省政府公报批复 > 政府官网报告全文 > 行业站转载全文(世展网/安全管理网)> 媒体报道;素材 OCR 错字集中时对照官方全文修正后再写卡(实测:施工单位三名异写均为同一误读、介质「茶」实为「苯」、产品「氯丙炔」勿凭直觉写成「氯丙烯」);PERSONS 有源才录——无源记忆/猜测名/「X某X」脱敏写法一律不入词表。
- 高效源三个(2026-09-05,190 批阶段 3-7 实测):①ichemsafe.com 结构化事故库——直接原因+根本原因分类+编号可搜,素材极薄时第一站;②调查报告全文转载页(王康律师网/北极星/搜狐等)——官方官网反爬或已下架时拿全文,WebFetch 直抓;③应急管理部「历史上X月发生的危险化学品事故」清单页——每条一句话直接原因,但按年滚动更新,旧年份条目会被移出最新版(2026 版已无马钢 6·17),需搜历史年份版本。
- 直接原因拿不到官方原文时降级写法:只写已证实的时间线+调查认定的方向(如标题「对设备设施维护不力」),不指明未经核实的泄漏部位/失效机理——宁可粗一点不可编造(马钢 6·17 卡实例)。
- 金句与文案语言质量自检(2026-09-06,193 张全量审查后回流):takeaway/description 为凑字数压缩时不得省关键虚词(不/必/先/了),不生造压缩词——实测 8 条硬伤全因此产生:「氮封未停不下器」「不降压迫盲板」「置换换点必办票」(三字连读打结)、「票批预制场」(压缩过度费解)、「堵漏四回」(生造量词)、「残料不清净转料」(歧义像「不清净」)、「也代替隔离确认」(缺「不了」语病)、「法兰不替人保密」(费解拟人);定稿前通读一遍,读着绕即改。合成词首次出现用全称(氮气釜勿写「氮釜」、爆破片勿写「破片」)。用户点出一处后应主动全量审查同类问题,勿只改被点名的那条。
- 微信补录管线(2026-09-06 实测):公众号推送正文为图片版不可提取时→WebSearch 官方调查报告全文核实年份/时刻/直接原因原文(⚠️ 多事故合并报道中另一篇的直接原因不可混用——两起氟化氢事故同页报道实测);manifest records 末尾追加记录(file 加「微信补录-」前缀 + source_url/verified 溯源字段)+
_txt2溯源 JSON(precheck 对缺 _txt2 记录优雅降级,但溯源必须留);推送顺序≠事故日期顺序——seq 按用户指定顺序,编号按事故年各自接续。 - 日期裁定冲突回查正文:裁定表/manifest 也是二手信息——写卡时正文与 body_date 裁定冲突(实证:把「4-14 20时装料加热开始」误当事故时刻,正文两处明写 4-15 6:40 发生事故),必须回查报告正文确认后同步修 manifest 记录与裁定脚本行(防重新 finalize 回退),靠写卡期日期 assert 兜底拦截。
- 微信补录管线(2026-09-06 实测):公众号推送正文为图片版不可提取时→WebSearch 官方调查报告全文核实年份/时刻/直接原因原文(⚠️ 多事故合并报道中另一篇的直接原因不可混用——两起氟化氢事故同页报道实测);manifest records 末尾追加记录(file 加「微信补录-」前缀 + source_url/verified 溯源字段)+
diagram_type 合法值(写卡必查)
非规范名会静默 fallback 成 generic(无专属 SVG、无红圈标注,且渲染不报错)。只允许:explosion_fire / gas_leak / isolation_failure / insulation_fire / thermal_runaway / gas_holder / spherical_tank_bleve / thermal_oil_dry_heating / generic。
七、工作建议
当用户要求"将某事故报告做成分享卡片"时:
- 先看报告:提取关键信息(时间/地点/物料/伤亡/损失/直接原因/间接原因/保护层失效/相关工具)
- 缺失字段显式标注:报告里没有的信息(如无照片、无伤亡数字、无直接原因)显式写「未知」或留占位,绝不编造推测值——卡片是安全培训材料,编造数据比留白危害更大
- 写 JSON:按数据模型填入,注意字数约束
- 选布局:描述 ≤400字 → side,否则 → stack
- 跑管道:
python pipeline.py --json data.json - 检查 PDF:打开看是否填满 A4、是否溢出、emoji 是否正确。核心警句被截先查 CSS
heightvsmin-height - 微调:字体/CSS 在
template.html中改,数据在 JSON 中改 - 交付 PDF:文件名格式
编号-事故名称.pdf
八、红线(Guardrails)
每条红线对应一个具体反噬方式,违反会直接破坏卡片质量或可信度:
- 事实与推断分离 — 事故描述区分「确认事实」与「推断/推测」,不夸大严重程度。过度断言会让懂行读者质疑整张卡片权威性。
- 技术描述精确 — 涉及自燃、爆炸极限、LOC 等概念务必准确(区分 pyrophoric 常温自燃 vs self-heating 蓄热自燃)。knowledge 栏是技术根因总结,不是科普。
- 脱敏在数据源层 — 地点/人名脱敏在 JSON 层
replace_all完成,不在 PDF/HTML 层改,否则重新生成时脱敏丢失。脱敏尺度由调用方按文档性质决定(公开材料基地名可保留,内部材料应连基地名一起脱敏为「某基地」) - 枚举字段必须校验合法值 — diagram_type 等枚举字段写卡前对照合法值清单;fallback 机制是静默降级,「能渲染」≠「渲染对了」。
- 装饰符号由 JSON 控制 — ★/• 等符号写在 JSON 里,CSS 不做隐式装饰(伪元素)——隐式装饰用户看不见改不了,一旦冲突极难排查。
- 溢出先查容器 — 底部截断第一步查 CSS
heightvsmin-height,第二步才考虑压缩字号。 - Edge 失败即切 Playwright — Edge headless 试 2-3 种参数仍静默失败(exit 0 无输出)就直接切 Playwright 同步 API,时间成本最低。
- SKILL.md 是真相来源 — 改模板/管道文件名要同步更新 pipeline.py 常量与文档,三处对齐。
经验索引
完整踩坑记录(15+ 轮迭代、文件系统坑、渲染引擎坑、批量并发坑、批量质量基建)见 references/pitfalls.md,按需加载:
- 核心教训 9 条 · 管道与文件系统(第 10-14 条)· 模板与符号控制(第 15-21 条)· 示意图与精确性(第 22-26 条)· 渲染与批量生产(第 27-28 条)· 批量续产与质量基建(第 29-35 条)· 锚点数据库与典型性毕业(第 36 条)· 实战速记表(2026-08-29 收官新增 5 条:换实体四字段同步 / history 复制 label_30 / 库外标签两种成因 / 承接先实测磁盘 / glob 假阴性)· v1.11.0 批量端到端总顺序(批前聚类锚点规划→批中写卡自检→渲染→批后对账)+ 脱敏词表每批扩充 + 编号年份规则 + 渲染层两条 · v1.12.0(2026-09-05,190 项目 8-11 批 60 张回流):总顺序补「验收」环节(judge 视觉验收三协议:100dpi 证伪/模板特征预声明/并发受限处理)+ QC PNG 日期+子串匹配 + venv 完整路径前置 + 写卡三 assert + 薄素材来源层级与 OCR 对照修正 + PERSONS 有源才录 · v1.12.1(2026-09-05,190 批阶段 7+self-neat 回流):锚点库随批自动收录已发卡事故(pick 需排除本卡,近期批事故可引用)+ 薄素材高效源三个(ichemsafe 结构化事故库/调查报告全文转载页/应急部「历史上X月事故」清单含年份滚动移出)+ 直接原因缺官方原文时降级写法(只写已证实时间线+认定方向,不指明未核实失效机理)+ 禁用 emoji(⏱⏳⌛)升 precheck P0 FAIL 硬拦截(写卡用 🕐/🕒) · v1.13.0(2026-09-06,190 批收官 12-13 批+微信补录+命名v2 回流):交付文件名 v2(PSI-日期-年内序号-名称,序号=页脚序号)与年中插入重排策略(标识与序号分离/波及仅当年该日期之后)+ 写卡金句语言质量自检(193 条全量审查出 8 条硬伤全为压缩省虚词,定稿通读+用户点名后主动全量审查)+ 微信补录管线(图片版正文→官方全文核实年份时刻原因、manifest+_txt2 溯源、推送顺序≠事故日期)+ 日期裁定冲突回查正文(裁定表是二手信息)