From 2b9a7febded4bab62dee3c3d4f045307ecb5ebcd Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 18 Jun 2026 15:24:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(skill):=20brief=20=E9=87=8D=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E4=B8=BA=E9=87=8D=E8=A6=81=E6=96=87=E7=8C=AE=E9=80=9F?= =?UTF-8?q?=E8=A7=88(=E8=AE=BA=E6=96=87=E5=88=97=E8=A1=A8+=E6=80=BB?= =?UTF-8?q?=E7=BB=93,=E5=8F=AA=E6=8F=8F=E8=BF=B0=E4=B8=8D=E7=BB=99?= =?UTF-8?q?=E5=BB=BA=E8=AE=AE)+=20=E7=B2=BE=E7=AE=80=E4=B8=89=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20+=20bump=200.20.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重定位:重要论文列表(各大期刊,Elsevier 数据库优先,每篇带简介/摘要概述)+ 内容总结;去掉建议/启示/热点聚类/判断 - 三路取数:research + documents 取文献为主力,web search 取政策·标准·产业动向单列(不混进论文总结) - 精简 8→3 文件:SKILL.md 自包含(spec 字段/骨架/检索法/核验铁律/渲染说明)+ references/journals.md(各建材子领域主流期刊清单,Elsevier 标注 + 精确 publication_name + 0 命中降级)+ scripts/render_docx.py;删 templates/spec.md、templates/brief_outline.md、references/search_strategy.md、references/citation_verify.md、scripts/quality_check.py - render_docx.py:论文列表段(标题含"论文列表/文献列表/参考文献")H3 期刊子标题下的 [n] 条目仍作锚点(只在 H1/H2 重判段类型);条目内 DOI 子串(末尾 "DOI: 10.xxx")也做 https://doi.org 超链接;smoke test 验证锚点/回链/外链/化学式下标全在 Co-Authored-By: Claude Opus 4.8 (1M context) --- PROGRESS.md | 10 +- SKILL_LIST.md | 30 +-- core/__init__.py | 2 +- skills/brief/SKILL.md | 148 ++++++----- skills/brief/references/citation_verify.md | 60 ----- skills/brief/references/journals.md | 58 +++++ skills/brief/references/search_strategy.md | 61 ----- skills/brief/scripts/quality_check.py | 270 --------------------- skills/brief/scripts/render_docx.py | 23 +- skills/brief/templates/brief_outline.md | 60 ----- skills/brief/templates/spec.md | 54 ----- 11 files changed, 174 insertions(+), 602 deletions(-) delete mode 100644 skills/brief/references/citation_verify.md create mode 100644 skills/brief/references/journals.md delete mode 100644 skills/brief/references/search_strategy.md delete mode 100644 skills/brief/scripts/quality_check.py delete mode 100644 skills/brief/templates/brief_outline.md delete mode 100644 skills/brief/templates/spec.md diff --git a/PROGRESS.md b/PROGRESS.md index 45d5662..c86ab7c 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -2,7 +2,7 @@ > 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。 -最后更新:2026-06-18(定时任务 v1:scheduled_jobs 表 + plain-asyncio 守护循环 + 3 工具 + send_email,DESIGN §8.5) +最后更新:2026-06-18(brief 简报重定位为「重要文献速览」+ 精简到三文件 + bump 0.20.0) --- @@ -21,6 +21,14 @@ ## 已完成关键能力 +### 2026-06-18 / brief 简报重定位「重要文献速览」+ 精简三文件(bump 0.20.0) + +- 需求漂移收敛:brief 从"热点聚类趋势判断型简报"重定位为**「重要论文列表 + 内容总结」速览型** —— ①只描述不给建议(去掉启示/判断/空白争议);②开头一份重要期刊论文列表(各大相关刊、**Elsevier 数据库优先**),每篇带一段简介/摘要概述;③对这批论文做客观总结即可。 +- 数据源:**research + documents 都是取文献主力**(research 逐刊精确取最新 Elsevier 论文 + DOI;documents 取内部材料库全文),web search 取动向**单列**不混进论文总结。 +- **精简到三文件**(原 8 文件):`SKILL.md`(自包含:spec 字段/骨架/检索法/核验铁律/渲染说明)+ `references/journals.md`(各建材子领域主流期刊清单,Elsevier 标注 + 精确 publication_name + 0 命中降级)+ `scripts/render_docx.py`。删 `templates/spec.md`、`templates/brief_outline.md`、`references/search_strategy.md`、`references/citation_verify.md`、`scripts/quality_check.py`。 +- `render_docx.py` 两处小改并已 smoke test 验证:①「重要论文列表」段(标题含"论文列表/文献列表/参考文献")H3 期刊子标题下的 `[n]` 条目仍作锚点(只在 H1/H2 重判段类型);②条目内 DOI 子串(末尾 "DOI: 10.xxx")也做 https://doi.org 超链接。验证:ref 锚点/内部回链/外部 DOI 链/化学式下标全在。 +- 文件:`skills/brief/{SKILL.md,references/journals.md,scripts/render_docx.py}`;`core/__init__.py` 0.19.0→0.20.0;`SKILL_LIST.md`(brief 条目重写,总数仍 17)同步。 + ### 2026-06-18 / 定时任务 v1(scheduled_jobs,DESIGN §8.5) - 需求:对话方式建"每天 X 点干 Y"的定时任务(跑 skill 出简报 / 发邮件 / 打招呼皆可)。调研 OpenClaw/Autobot/Claude Code/geta 四源收敛,定方案见 DESIGN §8.5。 diff --git a/SKILL_LIST.md b/SKILL_LIST.md index 2817f3a..1432a30 100644 --- a/SKILL_LIST.md +++ b/SKILL_LIST.md @@ -23,7 +23,7 @@ zcbot 的"skill"是一份可加载的工作流脚本(`skills//SKILL.md` + | 演示出图 | [plot_pub](#plot_pub) | 出版级 matplotlib 学术图(中文 + viridis + 矢量 + 投稿级复合图设计纪律) | | 文献检索 | [research](#research) | 查 paper_server(OpenAlex 元数据 + Sci-Hub 下载) | | 文献检索 | [documents](#documents) | 查内部 7 学科材料知识库(100W+ 论文,跨语言检索;host-side tool 持 key) | -| 文献检索 | [brief](#brief) | 科研方向简报:三路检索(内部库 + research + web)→ 热点聚类趋势简报 | +| 文献检索 | [brief](#brief) | 科研方向简报:三路检索(research + 内部库取文献 / web 取动向)→ 重要论文列表(带摘要概述)+ 内容总结,只描述不给建议 | | 科研计算 | [pymatgen](#pymatgen) | 晶体结构 / XRD 模拟 / 相图 / Materials Project(host-side tool 持 key) | | 科研计算 | [stats_ml](#stats_ml) | 配方-性能建模与机器学习(三库分工) | | 内容生成 | [imagegen](#imagegen) | 豆包 Seedream 5.0 文生图 + 改图 i2i(¥0.22 / 张) | @@ -291,32 +291,32 @@ paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 S --- ### brief -**生成科研方向简报(文献计量趋势型简报)。** +**生成科研方向简报(重要文献速览)。** -给定一个研究方向 + 时间窗,用**三路真实数据**(documents 内部库取全文 / research 取近期 DOI 元数据 / web 取政策·会议·标准动向)产出一份**有判断、可溯源**的简报:热点聚类 + 新兴方法 + 关键进展 + 研究空白 + 产业政策动向。简报 ≠ 综述论文 —— 要**快、准、有取舍**("重要性优先于完整性"),帮决策者 / 课题组 5–20 分钟掌握一个方向近期态势。 +给定一个研究方向 + 时间窗,从各大相关期刊(**Elsevier 数据库优先**)挑选近期**重要论文**,产出两段式简报:**先一份重要论文列表(每篇带标题/作者/期刊/年月/DOI + 一段简介或摘要概述),再对这批论文做内容总结**。三路取数:research(逐刊精确取最新 Elsevier 论文 + DOI)+ documents(内部材料库取全文)取文献,web search 取政策·标准·产业动向(单列)。**只描述不给建议**——呈现"发了什么、讲了什么",判断留给读者。简报 ≠ 综述论文,要**快、准、客观**,5–20 分钟掌握一个方向近期发了哪些重要论文。 -**六阶段**:定题对齐 spec(方向+边界 / 时间窗 / 受众 / 深度 / 源开关 / 语言 / 关注点)→ 三路检索取数(中→英术语转译 + 跨源去重,证据表)→ 趋势分析(3–7 热点簇,对齐后再写)→ 逐段起草 → 引文核验(复用 paper 三层协议)→ 渲染验收。 +**五阶段**:定题对齐 spec(方向+边界 / 时间窗 / 期刊范围 / 深度 / 数据源 / 语言 / 关注点)→ 三路取数(research+documents 取文献、web 取动向;中→英术语转译 + 跨源去重)→ 列清单(带摘要概述)+ 内容总结 → 引文核验 → 渲染验收。 -**深度三档**:`flash` 快报(1–2 页)/ `standard` 标准(4–6 页)/ `deep` 深度(8+ 页,含机构-地理计量),各配字数 / 簇数 / 引文数预算。 +**深度三档(按篇数)**:`flash` 10–20 篇 / `standard` 20–40 篇 / `deep` 40–80 篇。 **何时用**: -- ✅ 用户要"简报 / 方向简报 / 研究动态 / 趋势报告 / 调研快报 / 跟踪某领域最新研究 / 某方向近期进展" -- ✅ 立项前想快速摸清一个方向近期态势再决定要不要做(产出可喂 proposal / analyze) +- ✅ 用户要"简报 / 方向简报 / 最新文献 / 重要论文列表 / 研究动态 / 某方向近期重要论文 / 跟踪某领域最新研究" +- ✅ 立项前想快速摸清一个方向近期发了哪些重要论文(产出可喂 proposal / analyze) **何时不用**: - ⛔ 只要文献清单 / DOI / PDF → research / documents - ⛔ 要写可投稿的综述论文(几十页、定论)→ paper(review 类型) - ⛔ 要把模糊科学问题拆成子问题 + 路线图 → analyze -- ⛔ 要写本子 → proposal +- ⛔ 要"对本院的建议" / 写本子 → proposal **核心能力**: -- **三路检索分工 + 去重**(`search_strategy.md`):documents 全文首选、research 补 DOI 卡 year_gte、web 单列产业政策动向不混学术引文计数;中文方向→英文术语转译(SCM/LC3 等缩写展开) -- **趋势分析纪律**:热点聚成簇(主题句写判断不堆关键词)、新兴方法、争议空白、机构-地理格局(deep);取舍优先于穷尽 -- **引文核验**(复用 paper 三层协议):存在性 / 三角印证 / 支撑度,编造零容忍;web 来源标 URL + 日期 + 文号 -- `quality_check.py`:结构 / 簇数预算 / 过度宣称 / **无源句式**("据报道""有研究表明"无引文)/ 引文交叉核对 -- **自带 `render_docx.py`**:商务红主题 + 正文 `[n]`/`[Wn]` 引文上标并锚到文末 + DOI/URL 可点击超链接 + 化学式下标(CO₂/C₃S...,白名单不误伤 LC3/Ca2+)+ TL;DR / 判断 callout 底纹;做 deck 转 ppt +- **逐刊取重要论文**(`references/journals.md`):各建材子领域主流期刊清单(Elsevier 优先),精确 `publication_name` + `year_gte` 取最新,0 命中降级到 keyword 搜;按重要性(期刊层级 + 主题相关性 + 发现分量)筛、按 publication_date 留最新 +- **三路分工 + 去重**:research+documents 取文献(同 DOI 一条、documents 全文优先)、web 单列产业政策动向不混论文总结;中文方向→英文术语转译(SCM/LC3 等缩写展开) +- **每篇带摘要概述**:列表不只标题,每篇 2–4 句讲研究对象/方法/主要发现,基于 abstract 或全文、不夸张不评判 +- **引文核验**:存在性 / DOI 真伪(以库返回字段为准)/ 支撑度(摘要概述与原文一致,partial 改概述迁就证据),编造零容忍 +- **自带 `render_docx.py`**:商务红主题 + 论文列表 `[n]` 作锚点、正文 `[n]`/`[Wn]` 引文上标回链 + DOI/URL 可点击超链接(条目内 DOI 子串也链)+ 化学式下标(CO₂/C₃S...,白名单不误伤 LC3/Ca2+);做 deck 转 ppt -**典型产物**:`<方向>-简报.md`(默认)+ `evidence.md`(证据表)+ `CITATIONS.md`(引文核验台账);可选转 docx / deck。 +**典型产物**:`<方向>-简报.md`(默认,含 `01_papers` 重要论文列表 + `02_summary` 内容总结)+ `evidence.md`(证据表);可选转 docx / deck。 --- @@ -528,7 +528,7 @@ paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 S - **写本子全流程**:analyze(拆问题) → research / documents(查文献) → stats_ml(算配方-性能模型出预实验数据) → plot_pub(出图) → proposal(写本子) → review(审稿) - **写专利全流程**:patent(挖点 + 检索 + 起草) → research(查现有技术) → plot_pub(出附图) → review(终审) - **写标准全流程**:analyze(定标准化对象) → stats_ml(配方-性能 / 精密度试验数据定指标) → research / documents(查国内外现有标准与现状) → standard(起草标准 + 编制说明) → plot_pub(出图) → review(送审前终审) -- **方向简报 → 立项**:brief(三路检索摸方向近期态势) → analyze(把方向拆成子问题 + 路线图) → proposal(写本子) / paper(写综述);简报要做成汇报 → ppt +- **方向简报 → 立项**:brief(三路取数,出重要论文列表 + 内容总结,只描述) → analyze(把方向拆成子问题 + 路线图) → proposal(写本子、给建议) / paper(写综述);简报要做成汇报 → ppt - **PPT 汇报**:analyze(提炼论点) → research / documents(找数据 + 引文) → plot_pub(出图) → ppt(组装 deck) → imagegen(可选,做封面 / 引子页) - **晶体计算**:pymatgen(算 XRD / 相图) → plot_pub(出图) → proposal / patent(写到本子 / 交底书里) - **定制能力**:skill-creator(fork 某内置 skill,如 ppt / proposal) → 改造成本组 / 本人专属版本(术语 / 模板 / 默认值),之后日常任务直接用改造版 diff --git a/core/__init__.py b/core/__init__.py index 9c42e8b..a0f7bb1 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,3 +1,3 @@ # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # 改版本只动这一行。 -__version__ = "0.19.0" +__version__ = "0.20.0" diff --git a/skills/brief/SKILL.md b/skills/brief/SKILL.md index ff5c0d3..dfd052d 100644 --- a/skills/brief/SKILL.md +++ b/skills/brief/SKILL.md @@ -1,114 +1,108 @@ --- name: brief -description: 生成科研方向简报(research direction briefing / 文献计量趋势型简报)。给定一个研究方向 + 时间窗,用三路真实数据(documents 内部库取全文 / research 取近期 DOI 元数据 / web 取政策·会议·标准动向),产出一份热点聚类 + 新兴方法 + 关键进展 + 研究空白 + 产业政策动向的可读简报,每条论断可溯源、不编造引文。当用户要"简报 / 方向简报 / 研究动态 / 趋势报告 / 调研快报 / 某方向近期进展 / 文献综述快讯 / 跟踪某领域最新研究"时使用。 +description: 生成科研方向简报(research direction briefing / 重要文献速览)。给定一个研究方向 + 时间窗,从各大相关期刊(Elsevier 数据库优先)挑选近期重要论文,产出一份「重要论文列表 + 内容总结」的可读简报:先列清单(每篇带标题/作者/期刊/年月/DOI + 一段简介或摘要概述),再对这批论文做客观归纳。可溯源、不编造引文,**只描述不给建议**。当用户要"简报 / 方向简报 / 最新文献 / 重要论文列表 / 研究动态 / 某方向近期重要论文 / 跟踪某领域最新研究"时使用。 --- -# 科研方向简报 +# 科研方向简报(重要文献速览) -把"某研究方向最近发生了什么"变成一份**可读、可溯源、有判断**的简报。**先定题对齐 → 三路检索取数 → 趋势分析 → 逐段起草 → 引文核验渲染** —— 不要一口气出全文,定题和分析阶段先和用户对齐方向与边界。 +把"某方向近期发了哪些重要论文、都在讲什么"做成一份**可读、可溯源、客观**的简报。两段式:**先一份重要期刊论文列表(各大相关期刊、Elsevier 数据库优先;每篇带一段简介/摘要概述),再对这批论文做内容总结**。 -简报 ≠ 综述论文(paper review):综述要全面、深、给定论;简报要**快、准、有取舍**——"重要性优先于完整性",帮决策者 / 课题组 5–20 分钟掌握一个方向近期态势。 +> **只描述、不给建议。** 简报呈现"发了什么、讲了什么",不给"本院应当……/可切入……/建议……"。判断留给读者。 +> +> **"重要"怎么挑**:来自主流期刊(Elsevier 旗舰刊优先)、方向上居中而非边缘、有实质发现。近期论文引用尚少,故主要看**期刊层级 + 主题相关性 + 发现的分量**,不是单纯按引用数。控量靠"重要性 + 时新",不靠主观褒贬。 -进度展示建议:用 `task_progress` 标记「定题对齐 / 三路检索 / 趋势分析 / 逐段起草 / 引文核验 / 渲染」关键阶段。 +简报 ≠ 综述论文(paper review):综述要全面、深、给定论;简报要**快、准、客观**——5–20 分钟掌握一个方向近期发了哪些重要论文、各讲了什么。 -## 边界(先划清,免得和别的 skill 撞) +## 边界(免得和别的 skill 撞) -| 与谁区分 | 边界 | -|---|---| -| vs `research`/`documents` | 它们**只取文献**(候选清单 / 全文);brief 是消费方,把取回的文献**组织成有判断的趋势简报**,引文核验接到它们头上 | -| vs `paper`(review 类型) | paper-review 写**可投稿的综述论文**(IMRaD/主题式、几十页、定论);brief 出**轻量趋势简报**(几页、有取舍、面向决策),不投稿 | -| vs `analyze` | analyze 把**模糊科学问题**拆成子问题 + 路线图(不查文献);brief 围绕**一个已定方向**摸近期态势(重检索)。两者可互为上下游(先拆问题再摸态势,或先摸态势再拆) | -| vs `proposal` | proposal 写**本子**(立项依据);brief 只摸方向近期态势,不写立项依据。要立项 → 把简报喂给 proposal | +- vs `research`/`documents`:它们**只取文献**;brief 把取回的论文**组织成可读列表 + 客观总结**。 +- vs `paper`(review):paper 写**可投稿综述**(几十页、定论);brief 出**轻量速览**(几页、客观、不给判断)。 +- vs `analyze`:analyze 拆**科学问题**;brief 围绕**已定方向**列近期重要论文。 +- vs `proposal`:proposal 写**本子、给建议**;brief 只列论文 + 客观总结。要"对本院的建议" → 转 proposal。 -**何时不用**:只要文献清单 / DOI / PDF → research/documents;要写可投稿综述 → paper(review);要拆科学问题 → analyze;要写本子 → proposal。 +## 资源(路径相对 `load_skill` 头里的 `dir=<绝对路径>`) -## 资源 +- `references/journals.md` —— 各建材子领域主流期刊清单(Elsevier 数据库优先)+ 精确 `publication_name` + 0 命中降级法。**阶段二必读**。 +- `scripts/render_docx.py` —— md→docx,商务红主题 + 列表 `[n]` 锚点 + 正文 `[n]`/`[Wn]` 引文上标回链 + DOI/URL 可点超链接 + 化学式下标白名单(CO2/C3S/Na2O...,不误伤 LC3/C595/Ca2+)。用 `.venv/Scripts/python.exe` 跑。 -下面所有路径相对 **``** —— `load_skill` 返回头里的 `[skill=brief, dir=<绝对路径>]`,用这个绝对路径拼脚本/资源,不要假设 cwd。 +产物默认 `.md`;要 docx 用 render_docx.py;要 deck 转 `ppt` skill。 -**先读(always)**: -- `/templates/brief_outline.md` —— 简报骨架 + 按深度(快报/标准/深度)的字数预算与簇数/引文数 -- `/references/search_strategy.md` —— 三路检索分工(documents/research/web)+ 跨源去重 + 中文方向→英文术语转译 +## 阶段一:定题对齐(BLOCKING) -**阶段五必读**: -- `/references/citation_verify.md` —— 引文核验协议(存在性 / 三角印证 / 支撑度,复用 paper 思路,接 documents/research/web) +写一份 task 级 spec(命名见 system prompt《task 级「宪法」文件命名约定》),填下面字段,**有歧义先反问、不替用户拍板**,写完复述确认再往下: -**模板**: -- `templates/spec.md` —— 七条定题对齐固定字段(复制到 task 级 spec 文件) - -**脚本**(`.venv/Scripts/python.exe /scripts/...`): -- `scripts/quality_check.py` —— `--depth {flash,standard,deep}`,结构完整性 / 占位符泄漏 / 过度宣称 / 无源句式 / 引文交叉核对(orphan/uncited/编号连续) -- `scripts/render_docx.py` —— md→docx,**简报专属版式**:商务红主题(`--no-color` 关)+ 正文 `[n]`/`[Wn]` 引文上标并锚到文末 + DOI/URL 可点击超链接 + 化学式下标白名单(CO2/C3S/Na2O...,不误伤 LC3/C595/Ca2+)+ TL;DR / 判断 行做底纹 callout - -**产物与渲染**:简报默认产物是 `.md`。要 docx → 本 skill 自带 `render_docx.py`(见上);要做成汇报 deck → 转 `ppt` skill。 - -## 阶段一:定题对齐(写 spec)BLOCKING - -产物:**task 级 spec 文件**,简报的"宪法",后续每阶段前重读。命名按 system prompt 的《task 级「宪法」文件命名约定》: - - /--.spec.md - -复制 `templates/spec.md` 填七条,**有歧义先反问,不要替用户拍板**: - -1. **方向 + 边界**:具体到子方向(不是"水泥"而是"低碳水泥 SCM");明确**纳入/排除**(如"只看辅助胶凝材料替代,不含碱激发") -2. **时间窗**:默认**近 3 年**;用户说"最新/近期"→ 近 1 年;"这两年"→ 近 2 年。换算成 `year_gte`(今年是 system prompt 给的当前年) -3. **受众**:院领导汇报 / 课题组内部 / 立项前调研 / 对外交流 —— 决定语气与详略 -4. **深度**:`flash` 快报(1–2 页)/ `standard` 标准(4–6 页)/ `deep` 深度(8+ 页,含机构-地理计量)—— 见 brief_outline.md 预算 -5. **数据源开关**:documents(内部库,材料类首选)/ research(补 DOI 与近期元数据)/ web(政策·会议·标准·产业动向)—— 默认三路并用,用户可关 +1. **方向 + 边界**:具体到子方向(不是"水泥"而是"低碳水泥 SCM");明确纳入/排除 +2. **时间窗**:默认**近 1 年**(简报是"最新文献",窗口宜短);换算成 `year_gte`(今年见 system prompt) +3. **期刊范围**:默认按方向所属子领域取 `journals.md` 主流期刊(Elsevier 优先);用户可增删指定刊 +4. **深度 / 篇数**:`flash` 10–20 篇 / `standard`(默认)20–40 篇 / `deep` 40–80 篇 +5. **数据源(默认三路并用)**:research + documents **都是获取文献的主力**(research 按期刊精确取最新 Elsevier 论文 + DOI;documents 取内部材料库全文),web search 取政策·标准·产业动向(**单列、不混进论文总结**)。某一路不可用时降级用其余两路,不整体放弃 6. **语言**:中文(默认)/ 英文 -7. **特殊关注点**:用户特别想知道的(如"重点看 CCUS 与水泥结合""谁在做工业固废路线")—— 写进 spec,分析阶段重点回应 +7. **特殊关注点**(可选):想重点呈现的材料体系 / 方法(仍只描述,不给建议) -写完把 spec 七条**复述给用户确认**,认可后进阶段二。 +## 阶段二:三路取数(research + documents 取文献 / web 取动向) -## 阶段二:三路检索取数 +**先读 `references/journals.md`**。**中文方向先转专业英文术语**(库主语料英文):低碳水泥→low-carbon cement / clinker substitution;SCM→supplementary cementitious materials / fly ash / GGBFS / calcined clay;LC3→limestone calcined clay cement;碳化养护→CO2 curing / carbonation。缩写与全称都试。 -**先读 `references/search_strategy.md`**(三路分工 + 中→英术语 + 去重)。流程: +**research(逐刊取最新 Elsevier 论文 + DOI)** —— `run_python`: -1. **中文方向 → 英文检索词组**:库里主语料是英文,`SCM` 这类要展开(supplementary cementitious materials / fly ash / GGBFS / calcined clay / limestone calcined clay cement / LC3 ...) -2. **documents**(材料类首选):语义检索,中英 query 都行;胶凝材料库(classification_id=1)。取 `md_content` 备引文核验 -3. **research**:`search(keyword=英文, year_gte=<窗>, limit=...)` 拉近期候选 + DOI;`has_pdf`/`is_oa` 按需 filter。看 list 自带 abstract 判切题 -4. **web**(可选):政策(双碳、水泥行业碳配额)、标准(新国标/团标)、行业会议、企业中试/产线 —— web 的东西**单独标"产业/政策动向",不混进学术引文计数** -5. 汇成**证据表** `/evidence.md`(仿 lit_matrix):一行一条 = 来源 | 标题 | 年 | 一句话 takeaway | 归属簇 | 引文可用性(documents全文/DOI/web) +```python +from skills.research.paper import search +# 逐刊拉最新:publication_name 精确匹配 + 时间窗;list 自带 abstract,看前 200-400 字判切题与分量 +for jname in ["Cement and Concrete Research", "Cement and Concrete Composites", + "Construction and Building Materials", "Journal of Cleaner Production"]: + papers = search(publication_name=jname, year_gte=2025, limit=50) + # 按 publication_date 倒序取最新若干;留重要的(主题居中 + 有实质发现),弃边缘 +``` +某刊精确名 0 命中 → 换 `keyword=<方向英文术语>` 再搜,从返回里挑 `publication_name` 命中目标刊的;仍空记"该刊本窗口库内无收录"。 -收 20–80 条(按深度),**不求穷尽**,够支撑各簇即可。命中 0 条先换同义词/放宽年份,3 次仍空如实告诉用户库未覆盖,**不脑补文献**。 +**documents(内部材料库取全文,材料类首选)** —— host-side tool `document_search`,中英 query 都行(后端跨语言语义检索);胶凝材料库 `classification_id=1`。取 `md_content` 既做候选也供引文核验抓锚点最顺。 -## 阶段三:趋势分析(和用户对齐结构)BLOCKING-lite +**web search(取动向)** —— 政策(双碳/碳配额)、标准(新国标/团标)、行业会议、企业产线中试。**单列"其他动向",不混进论文列表与总结**。 -把证据表**聚成 3–7 个热点簇**(按深度),给用户看簇划分 + 每簇代表文献,认可后再起草。每簇判断: +- 汇成证据表 `/evidence.md`:期刊 | 标题 | 第一作者(机构)| 年-月 | 摘要概述 | DOI | 来源(research/documents/web)。 +- 跨源去重:同 DOI 一条(documents 全文优先,DOI 记自 research);web 不与论文去重、单列。 -- **这个簇在做什么 / 解决什么问题**(一句话主题句,不是关键词堆砌) -- **代表性进展**(2–4 篇,带真实引文) -- **新兴方法 / 技术**(出现的新表征、新建模、新工艺) -- **争议 / 分歧 / 未解**(哪里还没共识) +> **库时效(必交代)**:research(OpenAlex)约 3 个月索引滞后,"最新"= 库内最新。窗口内 0 篇 → 如实告知库未收录该窗口,可用 web 补更近的非论文动向,**不脑补文献**。 -横向再扫:**研究空白**(大家都没做的)、**机构-地理格局**(deep 才做,元数据够时:谁在领跑、中国占比)、**产业/政策动向**(来自 web)。 +## 阶段三:列清单 + 内容总结(写 `/sections/*.md`) -> 取舍纪律:一个方向近期可能上百篇,简报只留**改变判断的**。重复验证性工作合并成一句"多篇验证了 X";边缘工作直接不收。宁缺毋滥。 +骨架四段(`flash` 可省 `00`/`03`): -## 阶段四:逐段起草 +- **`00_overview.md` 概览**:方向 + 纳入/排除边界 + 时间窗 + 覆盖了哪些期刊 + 收录多少篇。无引文。 +- **`01_papers.md` 重要论文列表(主体)**:按期刊 `###` 分组,每篇一条,行首 `[n]`(渲染时此段作参考锚点、`[n]` 带 DOI 超链接): + ``` + ### Cement and Concrete Research(Elsevier) -按 `brief_outline.md` 骨架写 `/sections/*.md`,**每段一个论断 + 证据**: + [1] <标题>. <第一作者> et al., Cement and Concrete Research, 2026-03. DOI: 10.1016/j.cemconres.2026.xxxxxx -- TL;DR 要点(5 行内,先给结论)→ 方向概览与边界 → 研究热点聚类(各簇)→ 新兴方法 → 近期标志性进展 → 研究空白与争议 → 产业/政策/标准动向(web,可选)→ 参考文献 -- 起草时引文用占位 `[CITE-]`,阶段五核验后映射真实条目并编号 -- 数字 / 定量结论必须挂引文;"据报道""有研究表明"这种无源句式禁止 + <简介/摘要概述:2–4 句,讲研究对象、方法/表征、主要发现与关键数据 —— 基于 abstract 或全文,不夸张、不评判> + ``` + 按 `publication_date` 倒序,最新在前。每篇都要有摘要概述,不能只留标题。 +- **`02_summary.md` 内容总结**:对这批论文**客观归纳**——主题分布、常涉材料体系、常用方法/表征、共同关注点;引具体论文挂 `[n]` 上标(回链到 01)。**只描述"这批论文在讲什么",不给"应当/建议/可切入"**。 +- **`03_web.md` 其他动向(仅 spec 开 web 时)**:政策/标准/会议/产业,`[W1]` 标来源 + 日期,单列。 -## 阶段五:引文核验(渲染前必跑) +数字/定量结论必须挂 `[n]`;"据报道""有研究表明"这类无源句式禁止。 -**先读 `references/citation_verify.md`**,对所有引文逐条核验:存在性(两库/web 命中)→ 三角印证(关键论断 ≥2 源)→ 支撑度(抓原文锚点,partial 就改论断迁就证据)。台账写 `/CITATIONS.md`。 +## 阶段四:引文核验(渲染前必跑) -**铁律(同 paper)**:status 非 verified 的引文不得进最终稿;不为凑数编造文献;支撑不足改论断不改证据;两库/web 都查不到如实告诉用户。 +论文直接来自 research/documents,DOI 以**库返回字段为准**(不沿用记忆、不编造)。逐条核验: -## 阶段六:渲染验收 +1. **存在性**:`search()`/`get_paper(doi)` 或 documents 命中确认真实存在;查不到 → 标 `[未核实]`,告诉用户"找不到来源,请提供 DOI 或删去",**不编造**。 +2. **支撑度**:摘要概述 / `[n]` 论断要和 abstract(或全文)一致;不一致 → **改概述迁就证据**,不是改证据。 +3. **web**:记原始 URL + 访问日期 + 发布机构,标"截至 <日期>";不当学术结论引。 -1. `quality_check.py --depth ` 跑 sections:结构 / 簇数预算 / 占位符 / 过度宣称 / 无源句式 / 引文交叉核对 -2. 用户要 docx → `.venv/Scripts/python.exe /scripts/render_docx.py -o <方向>-简报.docx`(商务红 + 引文上标超链接 + 化学式下标;`--no-color` 出黑白);要 deck → 转 ppt skill -4. 交付时一句话说清:覆盖了哪几路源、收了多少条证据、哪些被取舍、哪些点是单源待复核 +台账可写 `/CITATIONS.md`。**铁律**:不为凑数编造文献;支撑不足改论断不改证据;查不到如实说。 + +## 阶段五:渲染验收 + +- 用户要 docx → `.venv/Scripts/python.exe /scripts/render_docx.py -o <方向>-简报.docx`(`--no-color` 出黑白);要 deck → 转 ppt。 +- 渲染前自查:`[CITE-]`/`` 占位是否清干净、正文 `[n]` 与列表 `[n]` 是否对得上(无 orphan)、有没有混进"建议/启示/本院应当"措辞。 +- 交付一句话说清:覆盖了哪些期刊、收了多少篇、时间窗、哪些刊本窗口库内无收录。 ## 反模式 -- ❌ 跳过定题直接检索 —— 方向边界没定,检索词发散,收一堆不相关 -- ❌ 把命中的文献**全部**堆进简报 —— 简报是取舍的艺术,不是清单转储 -- ❌ web 抓的资讯当学术结论引 —— web 动向单列,学术论断要文献支撑 -- ❌ 编造 DOI / "据报道"无源句 —— 走 citation_verify,查不到就如实说 -- ❌ 用中文 keyword 搜英文库 —— 先转专业英文术语(见 search_strategy.md) +- ❌ **给建议/启示/"本院应当"** —— 只描述论文讲了什么,判断留给读者 +- ❌ 列表只留标题、没摘要概述 —— 每篇都要 2–4 句简介 +- ❌ 跳过定题直接检索 / 用中文 keyword 搜英文库 / 期刊名不精确 —— 先定题、转英文术语、用精确 `publication_name` +- ❌ web 资讯混进论文列表/总结 —— 单列"其他动向" +- ❌ 编造 DOI / "据报道"无源句 —— 查不到就如实说 diff --git a/skills/brief/references/citation_verify.md b/skills/brief/references/citation_verify.md deleted file mode 100644 index d75f4f4..0000000 --- a/skills/brief/references/citation_verify.md +++ /dev/null @@ -1,60 +0,0 @@ -# 引文核验协议(简报版) - -与 `paper` skill 的引文三角核验**同一套思路**,这里按简报场景收口。简报虽轻,但**编造引文 / 引而不实**同样致命——决策者会照着简报判断方向,假信息代价更高。 - -> 协议不是脚本——你(模型)拿 host-side tool 逐条执行。quality_check.py 只做机械的 orphan/uncited/编号核对,真伪与支撑度靠本协议。 - -## 何时跑 - -阶段四逐段起草后、阶段六渲染前,对所有 `[CITE-xx]` 占位逐条核验。用户自带的引文也要跑。 - -## 三层核验(逐条) - -### 第 1 层 — 存在性 - -1. `documents` 语义检索 / `research` 的 `search()` / `get_paper(doi)` 确认文献真实存在 -2. 命中 → 以**库里返回字段为准**记 DOI/作者/年/期刊,不沿用记忆 -3. 两库都查不到 → 标 `[未核实]`,**不得编造**;告诉用户"这条找不到来源,请提供 DOI 或删去该论断" - -### 第 2 层 — 三角印证 - -关键论断(趋势判断、定量结论、"标志性进展")至少 **2 个独立源**一致才稳: - -- documents 命中 + research/DOI 一致 → 通过 -- 仅单一来源 → 标"单源,谨慎",简报交付时点出"此点单源待复核" -- 来源字段冲突 → 以可验证 DOI 元数据为准 - -### 第 3 层 — 支撑度 - -文献存在但**不支撑你写的那句话**是最容易翻车的: - -1. 抓 `md_content`(documents)/ `fetch_xml`/`fetch_pdf`(research) -2. 定位 ≤25 词原文锚点 + 段落位置 -3. 三档:**support** 通过;**partial/需限定** → 改写论断迁就证据;**not-support/反向** → 删引用或换文献 -4. 抓不到全文 → abstract 弱核验,标"仅摘要核验" - -## web 来源的核验(简报特有) - -web 资讯(政策/标准/产业)**不进学术引文三角**,但同样要可溯源: - -- 记**原始 URL + 访问日期 + 发布机构**;优先官方源(政府/标委会/期刊/企业官网),而非二手转载 -- 政策 / 标准类:能找到文号 / 标准号就记(如"GB/T xxxxx""国办发〔2025〕x号") -- web 信息标注"截至 <日期>",时效性内容明确边界——避免简报过期后误导 - -## 产出:核验台账 `CITATIONS.md` - -```markdown -# 引文核验台账 -- [1] , | exists:✓(documents+DOI) | triangulate:✓ | claim:support "<≤25词锚点>"(§x) | status: verified -- [2] | exists:✓ | claim:partial → 已把"大幅提升"改为"28d 提高约 15%" | status: verified-revised -- [W1] <机构> <标题>, , 访问 <日期> | 类型:政策动向 | status: web-sourced -- [3] | exists:✗ 两库未命中 | status: 待用户提供 -``` - -## 铁律(同 paper) - -- ❌ status 非 verified/verified-revised/用户确认的学术引文不得进最终稿 -- ❌ 不为凑数编造"看起来合理"的文献 -- ❌ web 资讯当学术结论引(单列动向段,标 URL+日期) -- ✅ 支撑不足**改论断迁就证据**,不是改证据迁就论断 -- ✅ 两库/web 都查不到如实告诉用户,给"提供来源 / 删论断"两个选项 diff --git a/skills/brief/references/journals.md b/skills/brief/references/journals.md new file mode 100644 index 0000000..4db124d --- /dev/null +++ b/skills/brief/references/journals.md @@ -0,0 +1,58 @@ +# 各建材子领域主流期刊清单(Elsevier 数据库优先) + +逐刊取最新论文时用。**绝大多数是 Elsevier**(下表 `E` 标),少数主流非 Elsevier 刊也列上(标出版商),取数时 Elsevier 优先。 + +> **用法**:`search(publication_name="<下表精确名>", year_gte=<窗>, limit=50)`,按 `publication_date` 倒序取最新。 +> **名字要精确**:OpenAlex 的期刊显示名就是下表这串,带副标题的(如 `Composites Part B: Engineering`)要带全。 +> **0 命中降级**:精确名搜不到 → 换 `keyword=<期刊核心词>` 或 `keyword=<方向英文术语>` 搜,从返回里挑 `publication_name` 命中该刊的;仍空 → 记"该刊本窗口库内无收录",不脑补。 + +## 水泥 / 混凝土 / 胶凝材料(本院核心) + +| 期刊 | 出版商 | 备注 | +|---|---|---| +| Cement and Concrete Research | E | 领域顶刊,机理与材料 | +| Cement and Concrete Composites | E | 复合胶凝、SCM、耐久 | +| Construction and Building Materials | E | 体量最大,工程材料广谱 | +| Cement | E | 较新 OA 刊,水泥专门 | +| Journal of Building Engineering | E | 建筑工程材料与结构 | +| Materials and Structures | Springer(RILEM) | 非 E 主流,RILEM 旗舰 | +| Cement, Concrete and Aggregates | ASTM | 非 E | + +## 绿色 / 低碳 / 固废资源化 + +| 期刊 | 出版商 | 备注 | +|---|---|---| +| Journal of Cleaner Production | E | 低碳、生命周期、固废 | +| Resources, Conservation and Recycling | E | 工业固废资源化 | +| Journal of Environmental Management | E | 环境与固废处置 | +| Waste Management | E | 固废(矿渣/粉煤灰/赤泥)| +| Journal of CO2 Utilization | E | 碳化养护 / CCUS | + +## 陶瓷 / 玻璃 / 耐火 + +| 期刊 | 出版商 | 备注 | +|---|---|---| +| Ceramics International | E | 陶瓷综合顶刊 | +| Journal of the European Ceramic Society | E | 陶瓷,欧洲旗舰 | +| Journal of Non-Crystalline Solids | E | 玻璃 / 非晶 | +| Journal of the American Ceramic Society | Wiley | 非 E,陶瓷顶刊(JACerS)| +| International Journal of Applied Glass Science | Wiley | 非 E,玻璃 | + +## 复合材料 / 新型建材 / 通用材料 + +| 期刊 | 出版商 | 备注 | +|---|---|---| +| Composites Part B: Engineering | E | 复合材料(纤维增强等)| +| Composites Part A: Applied Science and Manufacturing | E | 复合材料 | +| Materials & Design | E | 材料设计广谱 | +| Journal of Materials Research and Technology | E | 材料制备表征 | +| Materials Today Communications | E | 材料快报 | +| Powder Technology | E | 粉体 / 颗粒 | +| Fuel | E | 燃煤灰渣相关 | + +## 取数策略 + +- 按 spec 方向所属子领域,从上面对应表里取 **3–8 本主流刊**(Elsevier 优先),逐刊拉最新。 +- 跨子领域的方向(如"低碳水泥固废路线")→ 水泥表 + 绿色表合并取。 +- 每本刊取最新若干篇后,**按重要性筛**:主题居中、有实质发现的留,边缘/纯验证性的弃(控量见 SKILL.md 篇数预算)。 +- 主流刊都覆盖到了就够,不必穷举所有刊。哪些刊本窗口库内 0 收录,交付时如实点出。 diff --git a/skills/brief/references/search_strategy.md b/skills/brief/references/search_strategy.md deleted file mode 100644 index 0c8711e..0000000 --- a/skills/brief/references/search_strategy.md +++ /dev/null @@ -1,61 +0,0 @@ -# 三路检索策略(documents / research / web) - -简报数据底座最多三路并用。**三路分工不同、去重要做、学术与资讯分开计数**。 - -## 三路分工 - -| 路 | 拿什么 | 怎么调 | 强项 | 注意 | -|---|---|---|---|---| -| **documents** | 材料学科论文**全文 md**(胶凝材料库 classification_id=1) | host-side tool `document_search`,中英 query 都行(后端跨语言语义检索) | LLM 直接读全文、引文核验抓锚点最顺;材料类首选 | 需宿主配 `DOCUMENT_SEARCH_API_KEY`;只覆盖预收的 7 学科 | -| **research** | OpenAlex 元数据 + DOI + abstract,可拉 PDF/XML | `from skills.research.paper import search, get_paper, fetch_xml`,`run_python` 调 | 补近期文献与 DOI、`year_gte` 卡时间窗、`is_oa`/`has_pdf` filter | keyword **英文为主**;SearchFilter 匹配 title/author 不含 abstract | -| **web** | 政策 / 标准 / 会议 / 产业动向 | WebSearch / WebFetch | 时效性最强,学术库覆盖不到的非论文信息 | **不当学术结论引**;单列"产业/政策动向"段,标来源 + 日期 | - -> documents / research 任一不可用(key 没配 / 服务器连不上)时**降级用另一路 + web**,别整体放弃。research 不持 key,通常是降级首选。 - -## 中文方向 → 英文术语(关键) - -库里 95%+ 文献 title 是英文,中文 keyword 命中率很低。**中文方向先转专业英文词组再搜**,缩写要展开: - -| 中文方向 | 英文检索词组(同义/展开) | -|---|---| -| 低碳水泥 | low-carbon cement / low-CO2 cement / clinker substitution | -| 辅助胶凝材料 SCM | supplementary cementitious materials / SCM / fly ash / GGBFS / ground granulated blast-furnace slag / calcined clay / silica fume / limestone powder | -| LC3 石灰石煅烧黏土水泥 | limestone calcined clay cement / LC3 / calcined clay cement | -| 水泥窑碳捕集 | cement CCUS / carbon capture cement kiln / oxyfuel cement | -| 工业固废资源化 | industrial solid waste / steel slag / red mud / phosphogypsum in cement | -| 碳化养护 | CO2 curing / carbonation curing / accelerated carbonation | -| 水化机理 | cement hydration / C-S-H / hydration kinetics | - -转译策略:用领域标准英文术语;不确定就先英文 keyword 试一次看返回 title 是否相关;多个同义词分别搜一遍合并去重;缩写(SCM/LC3/GGBFS)与全称都搜。 - -## research 调用范式 - -```python -from skills.research.paper import search - -# 时间窗 = 近1年 → year_gte=<当前年-1>;多个英文同义词分别搜 -for kw in ["limestone calcined clay cement", "LC3 cement", "supplementary cementitious materials"]: - papers = search(keyword=kw, year_gte=2025, limit=15) - for p in papers: - # list 已带 abstract,直接看前 200-400 字判切题,不必再 get_paper - print(p["publication_year"], p["title"], p["doi"]) - if p["abstract"]: - print(p["abstract"][:300]) -``` - -要全文做引文核验:`has_fulltext_xml=True` 先 `fetch_xml`(结构化,LLM 友好),否则 `fetch_pdf`。 - -## 跨源去重 - -同一篇 / 同一结论可能三路都出现: - -- **同 DOI** → 一条(documents 全文优先,记 DOI 来自 research) -- **同结论不同文献**(多篇验证同一现象)→ 合并成一句"多篇(refN, refN)验证了 X",不逐条铺开 -- **web 资讯 vs 学术论文** → 不去重、不混算;web 进"产业/政策动向"段,学术进簇与引文计数 -- 证据表 `evidence.md` 一行一条标"来源(documents/research/web)",去重在表上做完再起草 - -## 收多少 / 收到什么程度 - -- 按深度收 20–80 条候选(见 brief_outline 预算),**不求穷尽**——够支撑各簇判断即可 -- 每簇至少 2 篇代表文献(关键论断 ≥2 源,接 citation_verify 三角印证) -- 命中 0 条:换同义词 / 展开缩写 / 放宽年份;3 次仍空 → 如实告诉用户库未覆盖该窗口,**不脑补** diff --git a/skills/brief/scripts/quality_check.py b/skills/brief/scripts/quality_check.py deleted file mode 100644 index 9ab7cae..0000000 --- a/skills/brief/scripts/quality_check.py +++ /dev/null @@ -1,270 +0,0 @@ -"""科研方向简报质量检查 — 渲染前跑一遍。 - -检查项: -- 结构完整性: 按深度(flash/standard/deep)必备段落是否齐全 -- 占位符泄漏: / [CITE-xx] 占位是否还在 -- 过度宣称: "国际领先 / 首次 / 颠覆 / unprecedented" 等无证据夸张词(简报要有判断但别吹) -- 无源句式: "据报道 / 有研究表明 / 业内普遍认为" 等不挂引文的论断(简报每条论断要可溯源) -- 引文交叉核对: 文中学术引 [n] 与参考文献清单 [n] 互查(orphan / uncited / 编号连续) -- web 来源计数: [W1].. 单独统计,提醒和学术引文分开 - -用法: - python quality_check.py --depth standard - python quality_check.py --depth flash --strict -""" -from __future__ import annotations -import argparse -import re -import sys -from pathlib import Path - - -# 各深度必备段落(stem 前缀匹配;references 单独判) -REQUIRED_SECTIONS: dict[str, list[str]] = { - "flash": ["00_tldr", "02_clusters", "references"], - "standard": ["00_tldr", "01_overview", "02_clusters", "05_gaps", "references"], - "deep": ["00_tldr", "01_overview", "02_clusters", "04_progress", "05_gaps", "references"], -} - -# 各深度热点簇数预算(02_clusters 里 '### 簇' 计数) -CLUSTER_BUDGET: dict[str, tuple[int, int]] = { - "flash": (2, 3), - "standard": (3, 5), - "deep": (5, 7), -} - -OVERCLAIM_PHRASES = [ - "国际领先", "国际一流", "世界领先", "世界一流", "填补空白", "重大突破", - "划时代", "前所未有", "颠覆性", "革命性", - "world-first", "world-leading", "unprecedented", "groundbreaking", - "revolutionary", "state of the art", -] - -# 无源句式: 出现这些但同段没有 [n]/[CITE-] 引文 → 论断悬空 -UNSOURCED_PHRASES = [ - "据报道", "有研究表明", "研究显示", "业内普遍认为", "众所周知", - "大量研究", "普遍认为", "据悉", -] - -PLACEHOLDER_PATTERNS = [ - r"]*>", - r"\[CITE-[A-Za-z0-9_\-]+\]", - r"\bXX+\b", -] - -_INTEXT_CITE_RE = re.compile(r"\[(\d[\d,\s\-]*)\]") # 学术引 [7] / [7-9] / [7,9] -_REF_ENTRY_RE = re.compile(r"^\s*\[(\d+)\]") # 参考文献条目 [n] -_WEB_CITE_RE = re.compile(r"\[W\d+\]") # web 来源 [W1] -_CITE_TOKEN_RE = re.compile(r"\[(?:\d[\d,\s\-]*|CITE-[A-Za-z0-9_\-]+)\]") - - -def _is_references_file(stem: str) -> bool: - s = stem.lower() - return "reference" in s or s.endswith("_refs") or "参考文献" in stem or "08_" in s - - -def check_structure(sections_dir: Path, depth: str) -> list[str]: - required = REQUIRED_SECTIONS.get(depth, []) - existing = {f.stem for f in sections_dir.glob("*.md")} - issues = [] - for req in required: - if req == "references": - if not any(_is_references_file(s) for s in existing): - issues.append("缺段落: 参考文献 (08_references)") - continue - if not any(s.startswith(req) for s in existing): - issues.append(f"缺段落: {req}") - return issues - - -def check_clusters(sections_dir: Path, depth: str) -> list[str]: - lo, hi = CLUSTER_BUDGET.get(depth, (0, 999)) - n = 0 - for md in sections_dir.glob("*.md"): - if md.stem.startswith("02_clusters"): - n += len(re.findall(r"^#{2,4}\s*簇", md.read_text(encoding="utf-8"), re.MULTILINE)) - if n == 0: - return ["02_clusters 里没找到 '### 簇N' 小节 — 热点聚类是简报主体"] - if n < lo: - return [f"热点簇 {n} 个, 少于 {depth} 档预算 {lo}-{hi} (簇太少, 方向覆盖可能不足)"] - if n > hi: - return [f"热点簇 {n} 个, 多于 {depth} 档预算 {lo}-{hi} (簇太多, 考虑合并 — 重要性优先于完整性)"] - return [] - - -def check_phrases(text: str, label: str) -> list[str]: - issues = [] - low = text.lower() - for phrase in OVERCLAIM_PHRASES: - if phrase in text or phrase.lower() in low: - issues.append(f"[{label}] 过度宣称: '{phrase}' — 换成可被数据支撑的具体表述") - return issues - - -def check_unsourced(text: str, label: str) -> list[str]: - """无源句式: 整段出现却无任何引文标记 → 悬空论断。按段落(空行分隔)判。""" - issues = [] - for para in re.split(r"\n\s*\n", text): - if _CITE_TOKEN_RE.search(para) or _WEB_CITE_RE.search(para): - continue # 本段有引文, 放过 - for phrase in UNSOURCED_PHRASES: - if phrase in para: - snippet = para.strip().replace("\n", " ")[:40] - issues.append(f"[{label}] 无源论断: '{phrase}' 所在段无引文标记 — 挂 [n] 或删 (\"{snippet}...\")") - break - return issues - - -def check_placeholders(text: str, label: str) -> list[str]: - issues = [] - for pat in PLACEHOLDER_PATTERNS: - for m in re.findall(pat, text): - issues.append(f"[{label}] 占位符未替换: '{m}'") - return issues - - -def _expand_cite_group(grp: str) -> set[int]: - out: set[int] = set() - for part in grp.split(","): - part = part.strip() - if not part: - continue - if "-" in part: - a, _, b = part.partition("-") - try: - lo, hi = int(a), int(b) - except ValueError: - continue - if 0 < lo <= hi <= 999: - out.update(range(lo, hi + 1)) - else: - try: - out.add(int(part)) - except ValueError: - continue - return out - - -def check_citations(sections_dir: Path) -> list[str]: - issues: list[str] = [] - cited: set[int] = set() - ref_nums: list[int] = [] - web_in_text = 0 - web_refs = 0 - - for md in sorted(sections_dir.glob("*.md")): - text = md.read_text(encoding="utf-8") - if _is_references_file(md.stem): - for ln in text.splitlines(): - m = _REF_ENTRY_RE.match(ln) - if m: - ref_nums.append(int(m.group(1))) - if re.match(r"^\s*\[W\d+\]", ln): - web_refs += 1 - else: - for grp in _INTEXT_CITE_RE.findall(text): - cited.update(_expand_cite_group(grp)) - web_in_text += len(_WEB_CITE_RE.findall(text)) - - if not ref_nums and not cited: - return ["未发现任何学术引文 (文中 [n] 和参考文献清单都为空) — 简报论断需文献支撑"] - - ref_set = set(ref_nums) - - orphan = sorted(cited - ref_set) - if orphan: - issues.append(f"orphan cite — 文中引了 {orphan} 但参考文献清单缺对应条目 (编造/漏排, 走 citation_verify)") - - uncited = sorted(ref_set - cited) - if uncited: - issues.append(f"uncited ref — 参考文献第 {uncited} 条正文从未引用 (删除或补引)") - - dups = sorted({n for n in ref_nums if ref_nums.count(n) > 1}) - if dups: - issues.append(f"参考文献编号重复: {dups}") - - if ref_set: - gaps = sorted(set(range(1, max(ref_set) + 1)) - ref_set) - if gaps: - issues.append(f"参考文献编号不连续, 缺号: {gaps} (顺序编码制需 1..N 连续)") - if 1 not in ref_set: - issues.append("参考文献编号未从 [1] 起") - - # web 来源只提示, 不判错(它们和学术引文分开计数) - if web_in_text and not web_refs: - issues.append(f"文中有 {web_in_text} 处 [W..] web 引用但参考文献无 [W..] 条目 — 补 web 来源(URL+日期)") - - return issues - - -def main() -> None: - ap = argparse.ArgumentParser(description="科研方向简报质量检查") - ap.add_argument("sections_dir", type=Path) - ap.add_argument("--depth", required=True, choices=list(REQUIRED_SECTIONS.keys())) - ap.add_argument("--strict", action="store_true", help="严格模式: 任何问题退出 1") - args = ap.parse_args() - - if not args.sections_dir.is_dir(): - print(f"[ERR] {args.sections_dir} not a directory", file=sys.stderr) - sys.exit(2) - - print(f"\n[简报质量检查] depth={args.depth}\n") - all_issues: list[str] = [] - - struct = check_structure(args.sections_dir, args.depth) - if struct: - print("[ERR] 结构问题:") - for s in struct: - print(f" - {s}") - all_issues.extend(struct) - else: - print("[OK] 结构完整") - - cl = check_clusters(args.sections_dir, args.depth) - if cl: - print("\n[WARN] 热点簇数:") - for s in cl: - print(f" - {s}") - all_issues.extend(cl) - else: - print("[OK] 热点簇数在预算内") - - files = sorted(args.sections_dir.glob("*.md")) - print(f"\n共 {len(files)} 个段落, 逐段扫描 (过度宣称 / 无源论断 / 占位符)...\n") - for f in files: - text = f.read_text(encoding="utf-8") - sub = (check_phrases(text, f.stem) - + check_unsourced(text, f.stem) - + check_placeholders(text, f.stem)) - if sub: - print(f"[WARN] {f.stem}:") - for s in sub: - print(f" - {s.split('] ', 1)[1] if '] ' in s else s}") - all_issues.extend(sub) - - cite_issues = check_citations(args.sections_dir) - if cite_issues: - print("\n[ERR] 引文交叉核对:") - for s in cite_issues: - print(f" - {s}") - all_issues.extend(cite_issues) - else: - print("\n[OK] 学术引文 [n] 与参考文献清单一致 (无 orphan / uncited, 编号连续)") - - print("\n" + "=" * 60) - if all_issues: - print(f"[WARN] 共发现 {len(all_issues)} 个问题。") - print("\n建议:") - print(" - 过度宣称 -> 换成数据支撑的具体表述") - print(" - 无源论断 -> 挂 [n] 引文或删该句") - print(" - 占位符未替换 -> 走 citation_verify 把 [CITE-] 映射成真实引文") - print(" - orphan cite -> 大概率编造, 走 citation_verify 三角核验") - print(" - uncited ref -> 删条目或正文补引") - if args.strict: - sys.exit(1) - else: - print("[OK] 未发现问题。") - - -if __name__ == "__main__": - main() diff --git a/skills/brief/scripts/render_docx.py b/skills/brief/scripts/render_docx.py index dba8e4b..7ad26e8 100644 --- a/skills/brief/scripts/render_docx.py +++ b/skills/brief/scripts/render_docx.py @@ -2,8 +2,9 @@ 相对 paper/render_docx.py 的简报专属增强: - **商务红配色**(主色 #C00000):标题分级染色 + 标题下细色条;TL;DR / 「判断」行做浅红底纹 callout -- **引文上标 + 内部超链接**:正文 [1] / [W3] → 上标红色,点击锚到文末参考文献对应条目 -- **参考文献可点击**:DOI → https://doi.org/... 蓝色超链接;web 条目里的域名/路径 → https:// 超链接 +- **引文上标 + 内部超链接**:正文 [1] / [W3] → 上标红色,点击锚到「重要论文列表 / 参考文献」段对应条目 +- **论文列表 / 参考文献可点击**:标题含「论文列表 / 文献列表 / 参考文献」的段,行首 [n] 条目作锚点; + 条目内 DOI(整条是 DOI 或末尾 "DOI: 10.xxx")→ https://doi.org/... 蓝色超链接;web 条目里的域名/路径 → https:// 超链接 - **化学式下标(白名单)**:CO2 / C3S2 / Na2O / SO4 ... → 真实下标,**白名单精确匹配**,不误伤 LC3 / EN 197-5 / 8.5 Mt / 2026 字体规范同院内其它渲染:中文宋体小四 / 英文 Times New Roman 小四 / 行距 1.5 / 首行缩进 2 字符。 @@ -407,6 +408,7 @@ def add_page_footer(doc: Document, color: bool) -> None: _REF_RE = re.compile(r"^\[(W?\d+)\]\s+(.+)$") _DOI_RE = re.compile(r"^10\.\d{4,9}/\S+$") +_DOI_INLINE_RE = re.compile(r"10\.\d{4,9}/\S+") # 条目内 DOI 子串(论文列表条目末尾常带 "DOI: 10.xxx") _URL_TOKEN_RE = re.compile(r"([a-z0-9][\w.\-]*\.[a-z]{2,}(?:/[^\s]+)?)", re.IGNORECASE) @@ -428,6 +430,18 @@ def add_reference_item(doc: Document, cid: str, value: str, bm_id: int, color: b if _DOI_RE.match(value): add_external_link(p, f"https://doi.org/{value}", value, size_pt=10.5) return + # 论文列表条目:行内含 DOI(如 "<标题>. <作者>, <刊>, 2026-03. DOI: 10.1016/...") + # → 把 DOI 子串做成超链接,前后文正常 + m_doi = _DOI_INLINE_RE.search(value) + if m_doi: + doi = m_doi.group(0).rstrip(".,;)") + pre, post = value[:m_doi.start()], value[m_doi.start() + len(doi):] + if pre: + _emit_plain_run(p, pre, size_pt=10.5, cn_font="宋体") + add_external_link(p, f"https://doi.org/{doi}", doi, size_pt=10.5) + if post: + _emit_plain_run(p, post, size_pt=10.5, cn_font="宋体") + return # web 条目:把第一个像 URL 的 token 变成超链接 m = _URL_TOKEN_RE.search(value) if m and ("/" in m.group(1) or m.group(1).count(".") >= 1) and " " not in m.group(1): @@ -604,7 +618,10 @@ def render_md_block(doc: Document, md_text: str, ctx: dict) -> None: if m: title = m.group(2).strip() level = min(len(m.group(1)), 3) - in_refs = "参考文献" in title + # 只在 H1/H2 重判段类型 —— 让「重要论文列表」段下的 ### 期刊子标题不重置 in_refs, + # 子标题下的 [n] 条目才能继续按参考锚点渲染(带 DOI 超链接) + if level <= 2: + in_refs = ("参考文献" in title) or ("论文列表" in title) or ("文献列表" in title) expect_meta = (level == 1) if level <= 2: in_tldr = ("要点" in title) or ("TL;DR" in title.upper()) diff --git a/skills/brief/templates/brief_outline.md b/skills/brief/templates/brief_outline.md deleted file mode 100644 index 29c74f6..0000000 --- a/skills/brief/templates/brief_outline.md +++ /dev/null @@ -1,60 +0,0 @@ -# 简报骨架 + 篇幅预算 - -简报按深度分三档,骨架同构、详略不同。`sections/` 一节一文件,文件名见各段标注。 - -## 篇幅预算(按深度) - -| 深度 | 页数 | 总字数(中) | 热点簇数 | 引文数(学术) | 机构-地理计量 | -|---|---|---|---|---|---| -| `flash` 快报 | 1–2 | 800–1500 | 2–3 | 8–15 | 不做 | -| `standard` 标准 | 4–6 | 2500–4000 | 3–5 | 20–40 | 可选(一句话点格局) | -| `deep` 深度 | 8+ | 6000+ | 5–7 | 40–80 | 做(发文量趋势 / 国别机构格局) | - -> 字数是预算不是硬指标;宁可短而准,不要灌水凑页。"重要性优先于完整性"。 - -## 骨架(各档同构) - -### `00_tldr.md` — 一句话要点(TL;DR) - -- 5 行内,**先给结论**:这个方向近期最值得知道的 3–5 件事,每行一句带判断 -- 决策者只读这段也能拿到核心态势 -- 例:`- LC3(石灰石煅烧黏土水泥)从中试走向标准化,近 1 年多国发布技术规程` - -### `01_overview.md` — 方向概览与边界 - -- 这个方向**解决什么问题**(1–2 段)、本简报的**纳入/排除边界**(照搬 spec) -- 时间窗 + 数据源覆盖说明(收了哪几路、多少条),让读者知道简报的"视野范围" - -### `02_clusters.md` — 研究热点聚类(主体) - -按 spec 深度分 3–7 簇,每簇一个 `###` 小节: - -``` -### 簇N:<主题句,写判断不写关键词> -- 在做什么 / 解决什么:<1–2 句> -- 代表性进展:<2–4 篇,带 [CITE-xx],各一句 takeaway + 关键数字> -- 新兴方法/技术:<若有> -- 争议/未解:<若有> -``` - -### `03_methods.md` — 新兴方法 / 技术(可并入 02,deep 单列) - -- 跨簇出现的新表征 / 新建模(如 ML 配比优化)/ 新工艺,各带代表文献 - -### `04_progress.md` — 近期标志性进展 - -- 近 N 年**改变判断**的标志性成果(里程碑论文 / 中试 / 突破),3–8 条,带引文与数字 - -### `05_gaps.md` — 研究空白与争议 - -- 大家都没做的(空白)、还没共识的(争议)、方法学局限 —— 这段是简报"有判断"的体现 - -### `06_industry.md` — 产业 / 政策 / 标准动向(web,可选) - -- 双碳政策 / 碳配额 / 新国标团标 / 行业会议 / 企业产线中试 —— **单列,标注来源为 web 资讯** -- 与学术引文分开计数;时效性内容注明日期 - -### `08_references.md` — 参考文献 - -- 仅 citation_verify 核验通过(verified / verified-revised / 用户确认)的进清单 -- 学术引文按文中首次出现顺序编 `[1][2]...`,带 DOI;web 来源另起一段标 URL + 访问日期 diff --git a/skills/brief/templates/spec.md b/skills/brief/templates/spec.md deleted file mode 100644 index d9886d2..0000000 --- a/skills/brief/templates/spec.md +++ /dev/null @@ -1,54 +0,0 @@ -# 简报 spec(定题对齐"宪法") - -> 阶段一产物。写定后不再改,阶段二/三/四每阶段前都要 read。`` 是占位符,需用户明确填值,不要硬编。 - -## 1. 方向 + 边界 - -- 研究方向(具体到子方向):`` -- 纳入范围:`` -- 排除范围:`` - -## 2. 时间窗 - -- 口径:`` -- 换算 `year_gte`:``(当前年见 system prompt) - -## 3. 受众 - -- ``(决定语气与详略) - -## 4. 深度 - -- `` -- 对应字数预算 / 簇数 / 引文数见 brief_outline.md - -## 5. 数据源开关(默认三路并用) - -- documents(内部库,材料类首选):`` -- research(补 DOI 与近期元数据):`` -- web(政策·会议·标准·产业动向):`` - -## 6. 语言 - -- `` - -## 7. 特殊关注点 - -> 用户特别想知道的,分析阶段重点回应。 - -- `` - -## 检索词组(阶段二填,中→英) - -> 中文方向转成的英文检索词,库里主语料英文。 - -``` - -``` - -## 待用户提供 / TODO - -- [ ] `` -- [ ] ``