文档思维导图与摘要
用户发来 PDF / Word / Excel / PPT / 音频 / 视频时,用本技能把文件转成
"看得懂、能转发"的可视化报告。所有产物默认本地交付,不发布公网。
何时使用(触发词表)
A. 关键词触发(无需附文件也要响应)
| 用户说 | 动作 |
|---|---|
| 【提炼】【总结】【思维导图】 | 调本技能。产出思维导图 HTML+PNG、500 字以上摘要,并把摘要直接发回对话供用户查看 |
| 【通知】 | 把文件简化为带 emoji 的通知文本,直接发回对话(可一键复制转发) |
| 【导出】【排版】【一键排版】 | 先按本技能生成内容,再调用 xtsy-official-writing 技能做 GB/T 9704-2012 排版,导出 .docx |
| 【纪要】【会议纪要】【录音整理】 | 音频/视频转写后,额外产出录音纪要文本 |
B. 文件触发(附上或指向即启用)
| 扩展名 | 流程 |
|---|---|
.pdf .docx .doc .xlsx .xlsm .csv .pptx .ppt |
直接进入提取 → 导图 → 摘要 → 报告 |
.mp3 .wav .m4a .ogg .aac .flac .wma .amr .opus |
先语音转文字,再进入上述流程,并追加录音纪要 |
.mp4 .mov .avi .mkv .wmv .flv .m4v 等 |
先抽音轨 → 转文字,再进入上述流程,并追加录音纪要 |
用户未指定输出位置时,统一放到工作区 out/<文件名>/,中间文件放work/。
默认交付(不必逐项询问)
| 文件类型 | 必交付 |
|---|---|
| 全部类型 | ① 思维导图 HTML(本地单文件,可直接转发)② 思维导图 PNG ③ ≥500 字内容摘要 ④ 单页分析报告 HTML |
通知类(is_notice=true)或用户说【通知】 |
追加:带 emoji 的精简通知摘要(Markdown + 渲染进报告 + 直接发回对话) |
| Excel / 表格类 | 追加:可交互图表 HTML + 每图PNG + 文字数据说明(Markdown) |
| 音频 / 视频类 | 追加:转写稿(work/transcript.txt)+ 录音纪要(Markdown + 渲染进报告) |
以上全部是默认必交付,缺一不可。
摘要与通知必须"发回对话"
除写入文件供报告渲染外,还要在最终回复里完整呈现,方便用户直接查看/复制:
- 500 字以上摘要:在回复中直接给出摘要正文(可折叠,但内容必须完整),
不要让用户"自己打开 HTML 才能看到摘要"。 - 通知文本:完整给出带 emoji 的通知,用户可直接复制转发到工作群。
- 录音纪要:完整给出纪要正文。
判断标准:用户在对话里就能读到全部文字成果,文件只是备份与可视化载体。
交付形态默认是本地文件:
- 思维导图与报告均为单文件自包含 HTML(CSS/JS/SVG 全内联,无 CDN、无外链),
微信/邮件直接转发,对方双击即可打开;
- PNG 一并交付,便于插入文档或打印;
- 不发布到公网 —— 见下方说明。
为什么不默认发布公网
文档常含内部制度、人员姓名、电话、单位职务等敏感信息,而公网链接:
- 无密码、无登录、无白名单,知道 URL 即可访问;
- 一旦被转发或截图,无法召回;
- 搜索引擎可能收录(本技能的 prepare_publish.py 会加 noindex + robots.txt
降低该概率,但这只是缓解,不是访问控制)。
因此默认只交付本地文件。 仅当用户在本轮对话中明确要求
"生成分享链接 / 发布上线 / 传到网上"时,才执行发布(见第 5 步),
且必须先提示上述风险。
执行流程
第0 步:确认 Python 解释器
所有脚本依赖 pymupdf、python-docx、openpyxl、python-pptx、matplotlib、Pillow。
统一使用隔离环境的解释器:
# Windows(Git Bash)
PY="C:/Users/Administrator/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
# 若该venv 不存在,用托管Python 创建:
# C:/Users/Administrator/.workbuddy/binaries/python/versions/3.13.12/python.exe -m venv \
# C:/Users/Administrator/.workbuddy/binaries/python/envs/default
# C:/Users/Administrator/.workbuddy/binaries/python/envs/default/Scripts/pip install \
# pymupdf python-docx openpyxl python-pptx matplotlib pillow
若缺包,用 pip install --user 或上述 venv 安装后再继续,不要污染系统 Python。
第 0.5 步:音频/视频先转文字(仅媒体文件)
转写优先用内置 AudioTranscribe 工具(无需 API key,
支持中文/方言/多说话人分离,做纪要首选):
AudioTranscribe(file_path="<音频或视频路径>")
拿不到该工具时,用备选脚本(需 OPENAI_API_KEY):
# 音频直接转写
"$PY" scripts/extract_media.py meeting.m4a -o work/transcript.txt
# 视频需先抽音轨(需 ffmpeg)
"$PY" scripts/extract_media.py meeting.mp4 --extract-audio-only -o work/audio.wav
# 再把 audio.wav 交给 AudioTranscribe,或:
"$PY" scripts/extract_media.py work/audio.wav -o work/transcript.txt
转写稿写入 work/transcript.txt 后,把它当作文本文档继续走
第 1 步之后的流程(可用 --mindmap-json 自定义导图结构),
并在第 2 步额外撰写录音纪要(规范见
references/meeting-minutes-guide.md,
输出 work/minutes.md)。
视频抽音轨需要 ffmpeg。若环境没有 ffmpeg:
提示用户安装,或让用户先自行转成 mp3/wav 再发。不要静默跳过。
第 1 步:提取内容
"$PY" scripts/extract.py "<输入文件>" -o work/document.json
产出 document.json,重点字段:
title— 主标题full_text— 全文纯文本(写摘要的唯一依据)sections[]— 章节:{heading, level, text}outline[]— 提纲:{level, text}tables[]— 表格:{name, header, rows, n_rows, n_cols}sheets[]— Excel 专属:{name, header, columns[{name,kind,sum,avg,max,distinct}], preview}columns[].kind∈number | category | date | text,是自动选图的关键is_notice/notice_signals— 通知类判定结果与依据
读取 full_text 后再动笔写摘要,不要凭文件名猜测内容。
第 2 步:撰写文字稿(由模型完成,脚本不做)
按 document.json 内容写以下 Markdown 文件(按类型取舍):
| 文件 | 何时写 | 规范 |
|---|---|---|
work/summary.md |
全部类型 | references/summary-guide.md,≥500 字 |
work/notice.md |
is_notice == true 或用户说【通知】 |
references/notice-guide.md,150~350 字,带 emoji |
work/findings.md |
Excel 或含表格 | references/findings-guide.md,200~450 字 |
work/minutes.md |
音频/视频类必写 | references/meeting-minutes-guide.md,300~600 字 |
用户说【通知】时,无论 is_notice 判定为何,都要写 notice.md
—— 判定只是辅助,用户意图优先。
写完检查字数:
"$PY" -c "import re;print(len(re.sub(r'\s','',open('work/summary.md',encoding='utf-8').read())))"
不足 500 字则继续补写,不要交付短摘要。
第 3 步:一键生成全部产物
"$PY" scripts/pipeline.py "<输入文件>" \
-o "out/<文件名>" --work work \
--summary work/summary.md \
--notice work/notice.md \
--findings work/findings.md \
--depth 4 \
--title "<报告标题>"
流水线自动完成:提取 → 导图(HTML+PNG)→ 图表(HTML+PNG,Excel 专属)→ 合成单页报告。
--depth 说明:导图层级深度。标准/制度类文件(职称评审条件、规章制度等章节层级明确)
建议用 4,可完整呈现"章 → 分项方向 → 具体条款";一般叙述性文件用默认 3 即可。
产出:
out/<文件名>/
<文件名>_分析报告.html ← 主交付:单文件自包含,含概览/通知/摘要/导图/图表/数据说明
mindmap.html ← 思维导图(自包含,可单独分享)
mindmap.png ← 思维导图位图
charts.html ← 图表页(仅表格类)
c1.png c2.png ... ← 各图表位图(仅表格类)
末尾会打印提示(摘要字数不足、通知类缺 notice、表格类缺 findings 等),
逐条处理完再交付。
第 4 步:本地交付(默认)
产物全部落在 out/<文件名>/,向用户交付这些本地文件:
out/<文件名>/
<文件名>_分析报告.html ← 主交付:单文件自包含,可直接转发
mindmap.html ← 思维导图(自包含,可单独转发)
mindmap.png ← 思维导图位图
charts.html ← 图表页(仅表格类)
c1.png c2.png ... ← 各图表位图(仅表格类)
本地 HTML 的安全属性:单文件、无外链、无远程请求,
不发到公网就不被搜索引擎收录,也不产生任何可被他人访问的 URL。
转发给同事时对方双击即可打开,无需安装任何东西。
用 present_files 展示报告 HTML、导图 PNG,Excel 场景一并展示图表 PNG。
第 5 步:发布公网(仅用户明确要求时才做)
默认不做。 只有当用户在本轮对话中明确说
"生成分享链接 / 发布上线 / 传到网上 / 让其他人也能访问"时才执行。
执行前必须先提示风险(内部制度、人员信息、链接不可召回),
用户仍坚持才继续:
- 组装发布目录:
bash "$PY" scripts/prepare_publish.py -o "out/<名称>_发布" \ --report "out/<名称>/<名称>_分析报告.html" \ --mindmap-png "out/<名称>/mindmap.png" \ --mindmap-html "out/<名称>/mindmap.html" \ --charts-html "out/<名称>/charts.html" \ --charts-png "out/<名称>/c1.png"
脚本自动:注入 noindex meta、生成 robots.txt、自检
(导图已内联、无磁盘路径泄漏、防索引齐全),自检不过返回退出码 1。 - 调
workbuddy_sites_deploy:directory=发布目录、entryHtml="index.html"、
language="static"、userAskedToPublish=true。 - 抓取返回的
shareLink验证内容正确再交给用户
(用直接抓取,不要只依赖 WebFetch——它自身有缓存)。 - 告知可在「设置—数据管理—应用」中管理,并可随时用
action="unpublish"下线。
注意:同一目录重复发布会覆盖已有内容;
多份文档要并存应合并为一个带导航首页的站点,且文件名用英文
(中文文件名在 URL 中需 percent-encode,分享体验差)。
敏感信息的处理建议
若原文档含真实人名、电话、身份证、住址等:
- 优先只交付本地文件,不发布公网;
- 用户坚持要公网时,建议先做脱敏版(真实姓名电话替换为示例值)再发布;
- 交付前可用正则自检(手机号
1[3-9]\d{9}、邮箱、身份证号)确认没有敏感数据。
第 6 步:一键排版导出 Word(用户说【导出】【排版】【一键排版】时)
用户提到导出、排版、一键排版时,说明他要的是可直接提交/归档的 Word,
不是 HTML。此时调用 xtsy-official-writing 技能做 GB/T 9704-2012 排版:
"$PY" scripts/export_docx.py -i work/document.json \
-o "out/<文件名>/<文件名>.docx" \
--title "<标题>" \
--summary work/summary.md \
--notice work/notice.md \
--findings work/findings.md \
--minutes work/minutes.md \
--type report # 正式公文用 --type official
正式公文(--type official)额外需要三个公文要素,由用户提供,不得臆造:
--issuer "邢台水业集团有限公司" \ # 发文机关
--doc-number "邢水业〔2026〕1号" \ # 发文字号
--print-date "2026年10月16日" \ # 印发日期(版记必需)
--cc "各有关单位" \ # 抄送(可选)
--printer "集团办公室" # 印发机关(可选,默认用发文机关)
缺任一项脚本会返回退出码 7 并说明缺什么——此时去问用户,不要自己编。
脚本会:把摘要/通知/纪要组装成 report.json → 调用
xtsy-official-writing 的 create_report.py 排版 → 自动执行
validate_docx.py 校验。
必须遵守:
- 字体层级、自动编号、页码、表格规则全部由 xtsy-official-writing 决定,
不要自己另写 Word 生成逻辑;
- Markdown → Word 的块映射由 export_docx.py::md_blocks() 完成,
已按公文技能的块协议对齐:heading{level} / paragraph /
table{title,headers,rows} / imprint{cc,issue_agency,issue_date};
- 排版完成后同时保留 HTML 报告(本地可转发)与 docx(正式归档),
不要只给其中一个;
- 校验未全部通过时,提醒用户打开 Word/WPS 人工核对页数与页码。
分步调用(需要精细控制时)
# 只出导图
"$PY" scripts/mindmap.py work/document.json --auto -o out/mindmap --depth 3
# 只出图表(可传自定义 charts.json 精确控制图形与配色)
"$PY" scripts/charts.py work/charts.json -o out/charts
# 只合成报告
"$PY" scripts/report.py -i work/document.json -o out/报告 \
--summary work/summary.md --notice work/notice.md --findings work/findings.md \
--mindmap out/mindmap.html --charts out/charts.html
# 音频/视频转写(备选路径;优先用内置 AudioTranscribe 工具)
"$PY" scripts/extract_media.py meeting.mp4 --extract-audio-only -o work/audio.wav
"$PY" scripts/extract_media.py meeting.m4a -o work/transcript.txt
charts.json 结构:
{"title": "报表标题",
"charts": [
{"id":"c1", "type":"bar|pie|line", "title":"图表标题",
"categories":["类别A","类别B"], "unit":"人",
"series":[{"name":"系列名","data":[1,2,3]}],
"note":"口径说明"}
]}
自动选图规则(charts.py::auto_charts):有日期列→折线图;分类列+数值列→饼图;
兜底单数值列→柱状图。需要别的组合就手写 charts.json。
模板类 Excel 不自动出图(looks_like_template() 判定,命中任一即跳过):
1. 任一单元格含"注:""说明:""填写说明"开头且长度>40 的大段说明;
2. 首列(序号)全空;
3. 数据行 ≤2 行。
这类表是采集模板而非数据集(常见:花名册模板、台账模板、审批单模板),
做统计图表只会把占位符(张三、10000000000)和说明文字画进图里,没有意义。
正确做法:摘要中如实说明"当前为空白模板、仅含示例数据",
数据说明里指出字段结构与填写规范。真实数据填报后再跑一次即可出图。
质量约束
- 质量闸门(硬性):
pipeline.py内置三层拦截,不满足即拒绝生成报告:
- 前置闸门(提取前跑):摘要缺失或<min_sum字 → 退出码 3,
且不产生任何中间文件,不白跑;
- 后置闸门(提取后跑):通知类缺通知摘要、表格类缺数据说明 → 退出码 3;
---force可跳过,但仅用于调试,正常流程禁止使用。
---min-summary可调下限,默认 500。 - 摘要 ≥500 字:这是默认必交付项,不达标闸门会拦住。
写作规范见 references/summary-guide.md。 - 只写原文有的:摘要、通知、数据说明里的每个数字都能在
document.json里找到。 - 图表自包含:HTML 用原生 SVG + JS,不引CDN,保证离线与内网可看。
- 导图不裁切:导图脚本已处理字体度量与自动裁边,改动
mindmap.py的
布局或字号后,务必跑一次回归:
bash "$PY" scripts/test_wrap.py # 换行完整性(4000 组随机模糊测试) "$PY" scripts/check_overflow.py # 节点文字是否溢出框 "$PY" scripts/check_bounds.py out/mindmap.png 0.08 # 是否有贴边裁切 - 摘要里的数字逐字核对:日期、比例、金额不要改写或四舍五入。
- 通知要能独立阅读:群里没看过原文的人也要明白要求。
- 发布前必自检:
prepare_publish.py会检查导图内联与路径泄漏,
自检不通过不得发布。
交付话术
文字成果必须在回复中完整呈现(用户要求"方便直接查看"):
- 500 字以上摘要:完整给出摘要正文,不要让用户"打开 HTML 才能看到摘要";
- 通知文本:完整给出带 emoji 的通知,用户可直接复制转发;
- 录音纪要:完整给出纪要正文;
- 同时列出本地文件路径清单,并说明各部分内容要点、摘要字数;
- 表格类额外说明"自动图表基于数据预览行,建议按需调整分析维度"。
明确说明 HTML 的可用性:"这是单文件 HTML,无外部依赖,
微信/邮件直接转发,对方双击就能打开"——不要含糊,
也不要暗示本地文件就是公网链接。
用 present_files 展示报告 HTML、导图 PNG,Excel 场景一并展示图表 PNG。
用户要求【导出】【排版】时,额外交付 docx,并说明哪些公文要素需其补填。
不要主动发布公网。 若用户后续要求分享链接,先提示风险(见第 5 步)再执行。
常见问题
| 现象 | 处理 |
|---|---|
ModuleNotFoundError |
用隔离 venv 的解释器,或按第 0 步装包 |
| PDF 提取字符数很少 | 多为扫描件,先用 pdf-ocr-md 技能 OCR,再走本流程 |
| 图表显示"无数值数据" | 该列kind 判定为 text/date,检查 columns[].kind 是否识别正确,必要时手写 charts.json |
| 退出码 3、提示"质量闸门未通过" | 正常行为:摘要不足 500 字/缺通知摘要/缺数据说明。按提示补写后重跑,不要用 --force 绕过 |
| 表格类 Excel 没出图 | 已命中模板检测(含"注:"说明/首列全空/≤2 行)。模板无真实数据,出图只会画进占位符,属正确行为;摘要应说明"空白模板" |
| 音频转写失败(无 key) | 改用内置 AudioTranscribe 工具(无需 key,支持说话人分离) |
| 视频无法抽音轨 | 环境缺 ffmpeg。提示用户安装,或让其先转 mp3/wav 再发,不要静默跳过 |
用户说【通知】但 is_notice=false |
仍要生成通知文本。用户意图优先于自动判定 |
| 用户要 Word/正式文档 | 走第 6 步 export_docx.py,调 xtsy-official-writing 排版;公文要素(机关/文号/抄送)留空待用户补填,不臆造 |
| Excel 行数很多(>5万) | extract.py 每表最多读 5000 行,提示用户这是抽样统计 |
| 旧版 Word(.doc) | python-docx 不支持二进制 .doc,提示用户另存为 .docx |
| PDF 标题变成"— 9 —"等页码 | 已内置 _is_page_noise 过滤;若仍出现,检查标题是否被排在首页正文之后 |
| 导图节点过多/过少 | 章节类文件用 --depth 4;条目零散可用 --mindmap-json 自定义树结构 |
| 报告里导图区显示成本地路径文字 | 传的是文件路径而非 SVG 内容;build() 已用 _load_svg() 兼容,仍异常则检查 _load_svg 是否被改动 |
| 用户要求"生成分享链接" | 先提示风险(无密码/不可召回/可能含敏感信息),用户坚持才走第 5 步 |
PDF 提取的已知特性
_line_level 采用保守策略,避免把条款正文误判为标题:
- 顶级编号(
一、第一章)与括号编号((一)(1))视为标题; - 数字编号(
1.2.)仅在 ≤30 字时视为标题 —— 职称评审标准里
"1.作为科研项目完成人完成国家级科研项目,或省(部)级科研项目2 项以上…"
属于条款正文而非标题,不加长度限制会被切成几十个碎片; - 硬换行由
_reflow_pages回接:未以句末标点(含冒号)收尾的行与下一行合并; - 页码噪声(
— 9 —第3页纯数字)由_is_page_noise剔除; - 主标题优先用字体大小识别(
_title_by_font),比按行文猜测可靠。
改动 extract.py 的标题判定后,务必用同目录下的多份 PDF 回归验证
(职称评审类文件结构相似,最能暴露误判)。