diff --git a/SKILL_LIST.md b/SKILL_LIST.md index cfed89c..d5766e9 100644 --- a/SKILL_LIST.md +++ b/SKILL_LIST.md @@ -1,7 +1,7 @@ # zcbot Skill 清单 服务对象:中国建筑材料科学研究总院 —— 无机非金属材料 R&D(水泥 / 混凝土 / 玻璃 / 陶瓷 / 耐火 / 新型建材) -最后更新:2026-08-21(coding 增加 Node.js/TypeScript 优先的技术栈路由与静态多文件 Web 预览) +最后更新:2026-08-25(research / documents 统一支持论文、书籍与章节查阅,并精简检索路由约束) Skill 总数:18 zcbot 的"skill"是一份可加载的工作流脚本(`skills//SKILL.md` + 配套 templates / scripts / Python helper),模型在识别用户意图后挂载对应 skill,按其内置的阶段化流程产出可交付物。本文档面向**使用方 / 协作方**,按"做什么、什么时候用、什么时候别用、典型产物"组织。 @@ -22,8 +22,8 @@ zcbot 的"skill"是一份可加载的工作流脚本(`skills//SKILL.md` + | 科研写作 | [rebuttal](#rebuttal) | 回复审稿意见(修回):逐点回复信 + 稿件修改清单 + 修回 cover letter | | 演示出图 | [ppt](#ppt) | 生成可编辑 PowerPoint(SVG-first:逐页手写 SVG → 原生 DrawingML;总院红品牌模板可选) | | 演示出图 | [plot_pub](#plot_pub) | 出版级 matplotlib 学术图(中文 + viridis + 矢量 + 投稿级复合图设计纪律) | -| 文献检索 | [research](#research) | 查 paper_server(OpenAlex 元数据 + Sci-Hub 下载) | -| 文献检索 | [documents](#documents) | 查内部 7 学科材料知识库(100W+ 论文,跨语言检索;host-side tool 持 key) | +| 文献检索 | [research](#research) | 查 paper_server 中的论文、书籍与章节(题录 / 摘要 / 可用全文) | +| 文献检索 | [documents](#documents) | 查内部 7 学科材料知识库(论文 / 书籍 / 全文语义检索) | | 文献检索 | [brief](#brief) | 科研方向简报:三路检索(research + 内部库取文献 / web 取动向)→ 重要论文列表(带摘要概述)+ 内容总结,只描述不给建议 | | 科研计算 | [pymatgen](#pymatgen) | 晶体结构 / XRD 模拟 / 相图 / Materials Project(host-side tool 持 key) | | 科研计算 | [stats_ml](#stats_ml) | 配方-性能建模与机器学习(三库分工) | @@ -254,36 +254,22 @@ zcbot 的"skill"是一份可加载的工作流脚本(`skills//SKILL.md` + ## 文献检索 ### research -**查 paper_server 文献库(基于 OpenAlex 元数据 + Sci-Hub 下载的内部部署)。** +**检索独立 `paper_server` 项目中的论文、书籍和书籍章节。** -paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 Sci-Hub / OpenAlex 异步抓取。**库里主语料是英文**(OpenAlex 主索引英文文献),少量中文。 +`research` 是 zcbot 对 `paper_server` 的客户端适配,可取得题录、DOI、摘要及记录实际提供的 PDF/XML。适合跨学科发现、精确题名或 DOI 查找、出版类型识别和引文核验;材料领域任务可与 `documents` 并查。 -**何时用**: -- 查 / 找 / 看 / 推荐文献 -- 要 DOI、要某篇 PDF、要 abstract -- 写申报书 / 研究方案 / 调研报告的"国内外现状"段需要真实文献支撑 -- 配合 `proposal` skill 的「立项依据」起草 +按任务所需证据深度选择题录、摘要或全文:结构化段落适合 XML,页码、公式、图表与版式核验适合 PDF。输出明确区分“仅题录”“摘要已核对”“全文已核对”。 -**何时不用**: -- 只问通识 → 直接答 -- 已经给了具体文献清单 → 直接用,不要二次校验 +**四个 helper**:`search` / `get_paper` / `fetch_pdf` / `fetch_xml`。 -**关键规则**:`keyword` 优先用英文(库里 95%+ 文献 title 是英文,中文 keyword 命中率很低)。中文术语先转专业英文术语再搜。 - -**四个 helper**: -- `search(keyword, year, year_gte, year_lte, doi, first_author, publication_name, has_pdf, is_oa, limit)` —— SearchFilter 匹配 title / first_author / first_author_institution -- `get_paper(id_or_doi)` —— 精准取一篇 -- `fetch_pdf(id_or_doi)` —— 拉 PDF 文件 -- `fetch_xml(id_or_doi)` —— 拉 OpenAlex 全文 XML - -**典型产物**:候选文献清单(16 字段) → 选定文献的 abstract / PDF / 引用条目。 +**典型产物**:论文、书籍和章节候选清单,以及可核验的摘要、全文和引用条目。 --- ### documents -**查内部材料学科知识库(document_search API)。** +**检索内部 7 个材料学科知识库中的论文、书籍及其他学术文档。** -部署在 `https://ai.ctc-zc.com:8100/api`。后端按 `kb_name` 分库存 7 个材料学科,共 **100W+ 英文学术论文**(Elsevier 期刊为主,DOI 前缀文件名)。每个文档带 `md_content`(整篇 Markdown,LLM 友好)+ 可选原 PDF 下载。 +按 `kb_name` 分为胶凝、陶瓷、玻璃、晶体、复合、耐火和检验检测 7 个材料学科库,提供跨语言语义检索、Markdown 正文片段和原件下载。 **7 大学科库**(`classification_id` 1-7): | 学科 | 内容 | @@ -297,14 +283,14 @@ paper_server 是内部 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 S | 检验检测 | 表征方法 / 标准 / 仪器 | **核心特色**: -- **跨语言语义检索** —— 中文 query 也能命中英文论文(API 后端处理) -- **已 Markdown 化** —— LLM 直接读,免 OCR / XML 解析 +- **跨语言语义检索** —— 中英文查询均可用于发现学术文档 +- **Markdown 正文** —— 可直接筛选论点、数据和章节,必要时再读取原件 **何时用**: -- 查材料领域文献 / 特定材料性能 / 工艺数据 -- 写申报书 "国内外现状" 段(本库 Markdown 比 research 拿到的裸 PDF/XML 更直接可用) +- 查材料领域论文、书籍、性能数据或工艺信息 +- 需要全文语义检索,或为申报书、方案、报告和综述寻找可核验证据 -**关系**:与 research 互补 —— research 搜全网,documents 是本地预收的材料学科子集。**找材料类文献优先 documents,找其他学科或要 DOI 走 research,两者命中不重叠时可并用**。 +**关系**:与 `research` 互补。`documents` 擅长材料领域全文语义检索,`research` 擅长跨学科题录和 DOI 检索;重要任务可并查,并按 DOI 或规范化题名去重。论文或书籍的来源类型不作为排他路由条件。 **三个 host-side tool**:`document_list_kb` / `document_search` / `document_download`。只有宿主配置 `DOCUMENT_SEARCH_API_KEY` 时注册;key 不进入 sandbox。 diff --git a/skills/documents/SKILL.md b/skills/documents/SKILL.md index 7215a63..f673ade 100644 --- a/skills/documents/SKILL.md +++ b/skills/documents/SKILL.md @@ -1,99 +1,41 @@ --- name: documents -description: 查内部材料学科知识库(document_search API,7 个学科:胶凝 / 陶瓷 / 玻璃 / 晶体 / 复合 / 耐火 / 检验检测,100W+ 英文学术论文 Markdown 化,跨语言语义检索)。用户找材料领域文献、特定学科论文、材料性能数据时使用;与 research(OpenAlex 外部库)互补,可并用 / 同时试。 +description: 检索内部 7 个材料学科知识库中的论文、书籍及其他学术文档。适合材料领域主题检索、全文语义检索、性能或工艺数据查找;可与 research(paper_server)并用并按 DOI 或题名去重。 --- # Documents -部署在 `https://ai.ctc-zc.com:8100/api` 的文档检索 API。后端按 `kb_name` 分库存储 7 个材料学科库(中文命名:胶凝 / 陶瓷基 / 玻璃基 / 晶体材料 / 复合材料 / 耐火材料 / 检验检测,共 100W+ 文件),**文档主体是英文学术论文**(Elsevier 期刊为主,DOI 前缀文件名),每个文档带 `md_content`(整篇 Markdown,LLM 友好)+ 可选的原 PDF 下载。**API 后端有跨语言语义检索**,中英文 query 都能命中英文文档。本 skill 使用三个 host-side tool:`document_list_kb` / `document_search` / `document_download`,**不要**自己 `httpx` 裸调,也不要在 `run_python` 里读 `DOCUMENT_SEARCH_API_KEY`。 +`documents` 是内部材料知识库的客户端 skill。知识库覆盖胶凝、陶瓷、玻璃、晶体、复合、耐火和检验检测,提供跨语言语义检索、Markdown 正文片段和原件下载。 -> ⚠️ **配置条件**:只有宿主后端配置了 `DOCUMENT_SEARCH_API_KEY` 时,上述 tool 才会出现在可用工具列表里。若没有 `document_*` tool,降级走 `research` skill(OpenAlex + Sci-Hub,不受影响,中文 query 先转专业英文术语)/ 用户自己导出文档落 task 目录后用 `read` 工具读。**别让 LLM 误推**:research 跟本 skill 不同范式,research 不持 secret,任何模式都能用。 +## 选择与协作 -## 何时用 +- 材料领域主题、性能数据或全文语义检索:优先使用 `documents`。 +- 跨学科发现、精确 DOI 或题录检索:优先使用 `research`。 +- 系统调研、综述或重要引用:可同时查询两者;按 DOI 去重,无 DOI 时按规范化题名、作者和年份去重。 +- 用户已提供文件或个人知识库路径:直接读取该来源。 -- 用户要查材料领域文献(7 个学科:胶凝 / 陶瓷 / 玻璃 / 晶体 / 复合 / 耐火 / 检验检测) -- 用户要查特定材料性能 / 工艺数据(实验数据 / 表征结果 / 公式 / 表格) -- 写申报书 / 方案 / 报告需要"国内外现状"段,本库 Markdown 化的论文比 research 拿到的裸 PDF/XML 更直接可用 -- **跟 research 并列**:都是文献检索 —— research 走 OpenAlex 元数据 + Sci-Hub PDF,搜全网;documents 是本地预收的材料学科子集,**已转 Markdown**(LLM 直接读,免 OCR / XML 解析)+ **跨语言语义检索**(中文 query 也能命中英文论文)。找材料类文献优先 documents,找其他学科或要 DOI 走 research,**两者命中不重叠时可并用** +论文、书籍和书籍章节都可作为候选,来源类型本身不决定使用哪个 skill;以相关性、元数据完整度和可核验正文为准。 -## 何时不用 +## 工具 -- 用户只问通识(直接答) -- 用户已经给了具体内部文档路径(直接读,不要二次校验) -- 用户问的是**自己上传的自建资料**(规范 / 报告 / 内部文档)→ 走个人知识库(system prompt「个人知识库」段注入的 `.kb/` 索引,fs 工具直接 read/grep),不在本库搜 +本 skill 使用宿主工具,API Key 不进入 sandbox: -## 三个 tool +- `document_list_kb()`:列出当前有效知识库。用户未指定材料方向且需要缩窄库范围时调用。 +- `document_search(queries, kb_names=None, classification_ids=None, max_documents=6, content_chars_per_doc=1200)`:批量搜索,返回文件元数据与截断的 `md_content`。中文和英文均可,专业术语可同时准备中英文表达。 +- `document_download(items)`:把选定原件下载到当前任务的 `documents/` 目录。`items` 使用搜索结果中的 `file_name` 和 `kb_name`。 -### `document_list_kb()` +工具会自动限制批量大小、去重并控制返回体积。需要更多正文时,对少量高相关候选增加 `content_chars_per_doc`,或下载原件后读取。 -列所有有效知识库(分类 1-7)。每条含 `id` / `kb_name` / `ch_name` / `kb_info` / `file_count` 等。 +## 工作流 -**用途**:用户没指定库 → 先 `document_list_kb` 看有哪些库(中文名 `ch_name` 看分类),再选 `kb_names` / `classification_ids` 缩窄 search 范围。 +1. 根据用户问题形成少量有区分度的查询;需要分类时先列知识库。 +2. 搜索并依据题名、文件名、正文片段和库来源筛选候选。 +3. 相关性判断可使用片段;论点、数据、公式、表格、章节或页码核验应读取足够正文或原件。 +4. 与 `research` 并查时合并去重,优先保留正文更完整、元数据更可靠的记录。 +5. 输出时区分“仅题录”“片段已核对”“全文已核对”,并标注可追溯的文件名、DOI 或其他真实标识。 -### `document_search(queries, kb_names=None, classification_ids=None, max_documents=6, content_chars_per_doc=1200)` +## 失败与真实性 -搜文档,**一次可传多个 query 并发搜**,返回精简列表,每条带 **截断后的 `md_content`**。 - -- `queries`:**搜索词列表**(1-8 条)。把你这一轮想搜的所有不同 query 一次性传进来(`queries=["alkali-activated slag strength", "fly ash cement hydration", ...]`),**别一个 query 一轮 tool call** —— 反复来回每轮重发整段上下文,轮数是 token 体量的线性乘数。**中英文均可** —— 文档主体是英文学术论文,但 API 后端有跨语言语义检索;复杂技术术语用**英文**更精准(`cement hydration` > `水泥水化`),日常概念中文 OK。**批内自动去重**;**别堆一堆只差几个词的近义 query**(边际递减),先想清楚一组互不重叠的 query 再批量发 -- `kb_names`:知识库白名单(从 `document_list_kb` 选,对所有 query 生效);`None` 走 server 默认(单库 `mu_34_1740625285897` 胶凝)。**多库联查就显式传**,如 `kb_names=["mu_34_1740625285897", "mu_34_1740625303475"]` -- `classification_ids`:分类 ID 白名单(1-7,对应 7 个学科库,对所有 query 生效);`None` 不过滤 -- `max_documents`:每个 query 返回几篇,1-20,默认 6(**批量多 query 时自动缩量**控制总输出) -- `content_chars_per_doc`:每篇返回多少 Markdown 字符,默认 1200,最大 5000(**批量多 query 时自动缩量**);不要一上来拉满 - -**学科库 → kb_name 速查**(`document_list_kb` 拿全量,这里只列常用): - -| 学科 | kb_name | -|---|---| -| 胶凝材料(水泥 / 混凝土 / 砂浆) | `mu_34_1740625285897` | -| 陶瓷基材料 | `mu_34_1740625303475` | -| 玻璃基材料 | `mu_34_1740625318986` | -| 晶体材料 | `mu_34_1740625346474` | -| 复合材料 | `mu_34_1740625355308` | -| 耐火材料 | `mu_34_1740625365079` | -| 检验检测 | `mu_34_1740625376621` | - -### `document_download(items)` - -下载原始文档(PDF / Word / ...)到 `/documents/`,返回各自相对路径。**一次可传多个文档并发下载**,单条失败不连坐其余。已存在跳过下载直接复用。 - -- `items`:文档列表(1-10 条),每条 `{file_name, kb_name, preview?}`,如 `items=[{"file_name":"a.pdf","kb_name":"mu_34_1740625285897"}, {"file_name":"b.pdf","kb_name":"mu_34_1740625285897"}]`。**要下几篇就一次性列进来,别一篇一轮 tool call** -- `file_name` 支持原始文件名(`example.pdf`)或 Markdown 名(`example.md`),server 自动回退 - -## 标准工作流 - -1. **(可选)`document_list_kb`** —— 用户没指定库 / 不确定分类时看一下有哪些 -2. **`document_search(queries=[...])`** —— 先规划好一组互不重叠的 query 一次性批量搜,中英文均可,专业技术术语优先英文 -3. **看返回**: - - 用 `file_name + character_count + md_content` 判断切题 - - 切题 → 直接用返回的 Markdown 摘要给 LLM 引用;需要更多上下文时对**少数**命中文档提高 `content_chars_per_doc` 单独重搜 - - 需要看图表 / 表格原貌 / 给用户附件 → `document_download(items=[...])` 一次性批量拿原文档,然后用主 agent 的 `read` 工具读(zcbot 已内置 PDF/Word 文本抽取) -4. **写产出**:把 md_content 关键段落引到申报书 / 方案里,标注来源文件名 - -## md_content 优先 vs 原件下载 - -- **绝大多数场景用 md_content 就够** —— API 已把原文档转成 Markdown,LLM 直接读,无需 OCR 或 PDF 抽取 -- **仅以下场景下载原件**: - - 用户明说"要原文件"(给客户附件 / 存档 / 引用页码) - - md_content 里图表 / 表格 / 公式信息丢失(Markdown 转换无损不了) - - 文档过大(`character_count` > 10 万),想用 PDF reader 跳页抽取局部 - -## 错误处理 - -- 没有 `document_*` tool:`DOCUMENT_SEARCH_API_KEY` 未在宿主配置,改走降级路径 -- 401 / 403 `Invalid API key`:`httpx.HTTPStatusError` —— key 错或失效,告诉用户检查 env -- 404 `未找到知识库`:`kb_names` 拼写错或库已下线,改 `document_list_kb` 看当前有效列表 -- 404 `文件不存在: xxx`:`document_download` 时常见,可能 server 侧文件丢失或 `file_name` 拼写错 -- search 命中 0 条:同义词 / 切换中英文 / 缩短 query / 放宽 `classification_ids` 再试 2-3 次,还是 0 条就明确告诉用户"本库没覆盖,改走 research 或换关键词",**不要凭训练数据脑补文献** -- 网络超时 / server 不可达:`httpx.ConnectError` / `httpx.TimeoutException` —— 告诉用户"document_search 暂时连不上",不要重试堆栈刷屏 - -## 反模式 - -- 用 `httpx` / `requests` 裸调 API(走 host tool,免得 base_url / auth / 字段名漂移时四处改,也避免 key 进入 sandbox) -- `document_search(max_documents=20, content_chars_per_doc=5000)` 一次拉满(20 条直接爆 LLM 上下文)—— 先用默认值判断切题,只对少数命中文档加大 `content_chars_per_doc` -- **一个 query 一轮 tool call 地反复搜**(同一意图换着措辞搜十几遍)—— 这是最烧 token 的反模式:每轮重发整段上下文。改成**先列一组去重 query 一次 `queries=[...]` 批量发**;一批结果看完不够再发下一批,而不是一条一条挤 -- `document_download` 一篇一轮 tool call —— 把要下的都列进 `items=[...]` 一次下完 -- 看到 md_content 切题还 `download` 一遍原件(md_content 已是 LLM 友好的 Markdown,大多数引用场景够用) -- 凭 `ch_name`("胶凝材料学科知识库")就以为 query 要用中文 —— 文档主体是英文,复杂术语用英文更精准 -- 编造 file_name / kb_name —— 不在 `document_list_kb` / `document_search` 返回里就**明确告诉用户"未命中"**,不要瞎传 ID -- 把 `document_download` 返回的相对路径当绝对路径用(它是相对 task_dir 的) -- 尝试给 `document_download` 传 `working_dir`(tool 已绑定当前 task_dir,`items` 里只放 `file_name` / `kb_name`,不要让模型指定路径) +- 工具不可用或认证失败时,说明 `document_search` 当前不可用,并改用 `research` 或用户提供的文件。 +- 未命中时可调整术语、语言或库范围;没有新增检索思路时如实说明覆盖不足。 +- 只使用工具返回的 `file_name`、`kb_name` 和来源信息,不推测缺失的作者、DOI、ISBN、页码或正文内容。 diff --git a/skills/research/SKILL.md b/skills/research/SKILL.md index 3dc53f0..1f2bbe1 100644 --- a/skills/research/SKILL.md +++ b/skills/research/SKILL.md @@ -1,138 +1,46 @@ --- name: research -description: 查 paper_server 文献库(基于 OpenAlex 元数据 + Sci-Hub 下载的内部部署)。用户要查文献、找 DOI、拉 PDF、做文献综述、写带引文的申报书 / 研究方案 / 调研报告时使用。 +description: 检索 paper_server 中的论文、书籍和书籍章节,获取题录、DOI、摘要及可用的 PDF/XML 全文。适合跨学科文献发现、精确文献查找和引文核验;材料领域可与 documents 并用。 --- # Research -paper_server 是内部部署的 Django 文献库:元数据来自 OpenAlex,PDF / XML 由 Sci-Hub / OpenAlex 异步抓取。**库里主语料是英文**(OpenAlex 主索引英文文献),少量中文。本 skill 给你四个 helper(`search` / `get_paper` / `fetch_pdf` / `fetch_xml`),用 `run_python` 调用,**不要**自己 `httpx` 裸调 API。 +`research` 是 zcbot 对独立 `paper_server` 项目的客户端适配。`paper_server` 以 OpenAlex 元数据为基础,并按记录实际可用性提供摘要、PDF 或 XML;当前语料以英文为主,也包含中文文献。 -## 何时用 +## 选择与协作 -- 用户要查 / 找 / 看 / 推荐文献 -- 要 DOI、要某篇 PDF、要 abstract -- 写申报书 / 研究方案 / 调研报告的"国内外现状"段需要真实文献支撑 -- 配合 `proposal` skill 的「立项依据」起草 —— 先 `search` 拿候选,看 abstract 决定要不要引 +- 跨学科发现、题名或 DOI 检索、出版类型识别:优先使用 `research`。 +- 材料领域全文语义检索、性能或工艺数据:优先使用 `documents`。 +- 系统调研、综述或重要引用:可同时查询两者;按 DOI 去重,无 DOI 时按规范化题名、作者和年份去重。 +- 用户已提供具体文件:直接读取;用户只提供题录而任务要求核验论断时,继续获取摘要或全文。 -## 何时不用 +论文、书籍和书籍章节均可检索。是否读取摘要、XML 或 PDF,由用户问题所需的证据深度决定。 -- 用户只问通识(直接答即可,不需要文献支撑) -- 用户已经给了具体文献清单(直接用,不要二次校验) +## 调用方式 -## 准备 +通过 `run_python` 使用 helper: ```python from skills.research.paper import search, get_paper, fetch_pdf, fetch_xml ``` -(import 路径由 `run_python` 注入的 `PYTHONPATH` 提供,直接写就行,不必折腾 `sys.path`) +- `search(keyword="", year=None, year_gte=None, year_lte=None, doi="", first_author="", publication_name="", has_pdf=None, is_oa=None, limit=10)`:搜索题录,返回类型、题名、作者、年份、期刊或出版物、DOI、摘要及全文可用状态。 +- `get_paper(id_or_doi)`:按 `paper_server` ID 或 DOI 获取单条完整记录。 +- `fetch_xml(id_or_doi, working_dir)` / `fetch_pdf(id_or_doi, working_dir)`:把可用全文下载到当前任务的 `papers/` 目录并返回相对路径。 -> **本 skill 持一把低价值 key**。paper_server 的 GET 接口要 `PAPER_SERVER_API_KEY`(helper 自动以 `?api_key=` 查询参数带上,你不用管);它是唯一刻意放进 sandbox 的凭证 —— `run_python` 的 env 过滤器对它放行,docker 模式由宿主透传进容器 → host / docker 任何模式都能用。`PAPER_SERVER_URL` 可选覆盖(默认 `http://paper.xxhhcty.xyz:8080`)。**别因 documents / pymatgen 报"key 没配"就连带放弃 research**,这俩不可用时它就是降级首选。 +helper 自动使用 `PAPER_SERVER_API_KEY` 和可选的 `PAPER_SERVER_URL`。通过 helper 访问 `paper_server`,由它处理认证、URL 和下载路径。 -## 关键:keyword 优先用英文 +## 工作流 -`search(keyword=...)` 走 paper_server SearchFilter,模糊匹配 **title / first_author / first_author_institution**(目前不含 abstract)。库里 95%+ 文献 title 是英文,中文 keyword 命中率很低。 +1. 将用户概念转换为常用专业术语;英文题名占多数时优先使用英文,并可用中文或同义词补充。 +2. 用主题、年份、作者、出版物或 DOI 搜索并筛选候选;`type` 可帮助识别论文、书籍和章节。 +3. 相关性初筛可使用题名和摘要;精确论断、数据、章节、图表或页码应获取足够正文。 +4. 结构化段落和参考文献通常适合读取 XML;版式、页码、公式和图表通常适合读取 PDF。只获取记录实际提供的格式。 +5. 与 `documents` 并查时合并去重,输出中区分“仅题录”“摘要已核对”“全文已核对”。 -**用户输入中文 → 先转成专业英文术语再 search**: +## 失败与真实性 -| 用户原话 | 不要这样 | 这样 | -|---|---|---| -| 水泥水化 | `search("水泥水化")` | `search("cement hydration")` | -| 钢筋锈蚀 | `search("钢筋锈蚀")` | `search("steel reinforcement corrosion")` | -| 混凝土碳化 | `search("混凝土碳化")` | `search("concrete carbonation")` | -| 锂离子电池电解液 | `search("锂离子电池电解液")` | `search("lithium-ion battery electrolyte")` | - -转译策略: -- 用领域内标准英文术语(查不准就先英文 keyword 试一次看返回 title 是不是相关) -- 多词术语用空格分隔(`SearchFilter` 默认空格视作 AND,要更宽用单词) -- 不确定时同义词都试一遍:`search("CO2 absorption")` 没结果 → 试 `search("carbon dioxide capture")` -- 中文期刊 paper 也可中文 keyword 单独搜一次(`search("水泥") + filter 中文期刊` 命中率不算低,但远不如英文主搜) - -## 四个函数 - -### `search(keyword="", year=None, year_gte=None, year_lte=None, doi="", first_author="", publication_name="", has_pdf=None, is_oa=None, limit=10) -> list[dict]` - -搜文献,返回精简列表(每条含 16 字段:id / doi / title / first_author / first_author_institution / publication_year / publication_date / publication_name / has_fulltext_pdf / has_fulltext_xml / has_abstract / is_oa / type / **abstract** / **pdf_url** / **xml_url**)。 - -- `keyword`: SearchFilter,匹配 title / first_author / first_author_institution(**英文为主**,见上节) -- `year` / `year_gte` / `year_lte`: 精确年份 / 范围(做"近 5 年文献"用 `year_gte=2020`) -- `doi`: 精确 DOI(命中 0 / 1 条) -- `first_author` / `publication_name`: 精确作者 / 期刊 -- `has_pdf=True` 仅返 PDF 已下好的;`False` 仅返没 PDF 的;`None` 都返 -- `is_oa=True` 仅返开放获取(OA);`False` 仅返非 OA;`None` 都返 -- `limit`: 默认 10,上限 50 - -```python -# 找近 5 年水泥水化研究,且 PDF 已下好 -papers = search(keyword="cement hydration", year_gte=2020, has_pdf=True, limit=10) -for p in papers: - print(p["title"], p["publication_year"]) - if p["abstract"]: - print(p["abstract"][:200]) # 看摘要前 200 字判断是否切题 -``` - -### `get_paper(id_or_doi) -> dict` - -取单条完整 metadata + abstract。`id_or_doi` 既接受 paper_server 内部 id,也接受 DOI(自动解析)。 - -**list 端点已带 abstract,正常工作流不需要调本函数** —— 仅在用户给单个 id / DOI 想拿全字段(含 OpenAlex 原始字段如 `o_keywords` 等)时用。 - -```python -paper = get_paper("10.1016/j.cemconres.2020.106156") -print(paper["title"]) -print(paper["abstract"]) -``` - -### `fetch_pdf(id_or_doi, working_dir) -> str` - -下载 PDF 到 `/papers/.pdf`,返回相对路径 `papers/.pdf`(safe_doi 把 `/` 换成 `_`)。**走 paper_server media 静态直链**(从 list/retrieve 返回的 `pdf_url` 字段),跟 `fetch_xml` 同范式。已存在跳过下载直接复用。 - -`has_fulltext_pdf=False` 或 `pdf_url` 空(publication_date 缺失)→ 抛 `RuntimeError`。 - -```python -rel = fetch_pdf("10.1016/j.cemconres.2020.106156", working_dir="") # = system prompt 给的工作目录绝对路径(docker 沙盒里形如 /workspace/) -# rel == "papers/10.1016_j.cemconres.2020.106156.pdf" -``` - -### `fetch_xml(id_or_doi, working_dir) -> str` - -下载 XML 到 `/papers/.xml`,对称 `fetch_pdf`。**走 paper_server 的 media 静态直链**(由 list/retrieve 返回的 `xml_url` 字段提供),paper_pdf_view 只覆盖 PDF,XML 没对应 API。已存在跳过下载直接复用。 - -`has_fulltext_xml=False` 或 `xml_url` 空(publication_date 缺失时会空)→ 抛 `RuntimeError`。 - -**为什么 XML 优先 PDF**:XML 已结构化 —— 章节标题 / 摘要 / 段落 / 参考文献 / 图表 caption 都有标签,LLM 读取无需 OCR 或 PDF 文本抽取的不确定性;文献综述 / 引文清单 / 章节定位场景比 PDF 友好得多。能拿 XML 就别拿 PDF;只有需要看具体公式 / 图表内容 / 表格数据时才下 PDF。 - -## 标准工作流 - -1. **(若用户输入中文)转专业英文术语** -2. **search**:按 keyword + filter(年份范围 / OA / has_pdf 等)缩窄候选,`limit=10` 起 -3. **直接看返回里的 abstract**(list 端点已带): - - abstract 非空 → 看前 200-400 字判断切题 - - abstract 空(`has_abstract=False`)→ 仅凭 title + 期刊 + 年份判断,信号弱时下条候选 -4. **下全文(若需要)** —— **优先级**: - - `has_fulltext_xml=True` → `fetch_xml`(LLM 友好,结构化) - - 仅 `has_fulltext_pdf=True` → `fetch_pdf`(回退,需要 PDF 文本抽取) - - 两者都 False → 仅凭 abstract 写综述,告诉用户哪几篇没全文 -5. **read 全文**:fetch 返回相对路径,用主 agent 的 `read` 工具读取(zcbot 已内置 PDF 文本抽取;XML 直接当文本读) - -## 错误处理 - -- 网络超时 / paper_server 不可达:`httpx.ConnectError` / `httpx.TimeoutException` —— 告诉用户"paper_server 暂时连不上",不要重试堆栈刷屏 -- `paper_server auth failed (HTTP 400/401/403, not_authenticated/...)`:`PAPER_SERVER_API_KEY` 未配置或无效 —— 告诉用户找管理员在 `.env` 配 key,换 keyword 重试没用 -- `doi 未命中` / `doi 命中多条`:`get_paper` / `fetch_pdf` / `fetch_xml` 内部 `_resolve_to_id` 抛 `ValueError` —— DOI 拼写错或库里没收录,改 keyword 重搜 -- `has_fulltext_pdf=False` / `has_fulltext_xml=False`:`fetch_pdf` / `fetch_xml` 抛 `RuntimeError` —— 服务器还没下到对应格式;若另一格式存在则换用,都没就只能用 abstract -- `xml_url` 空(publication_date 缺失,paper 落到 unknown 目录):`fetch_xml` 抛 `RuntimeError(xml_url unavailable...)` —— 改试 `fetch_pdf` -- 文件 disk 缺失(`has_fulltext_pdf=True` 但 paper_server 侧文件丢了 → HTTP 404):helper 透传 `httpx.HTTPStatusError`,告诉用户换一篇 -- `abstract` 字段为空字符串:正常情况,不是错;告诉用户"这篇没收录摘要"即可 -- search 命中 0 条:先尝试同义词 / 缩短 keyword / 放宽 filter,3 次还是 0 条告诉用户库里没覆盖,**不要凭训练数据脑补文献** - -## 反模式 - -- 用任何 HTTP 客户端(`httpx` / `requests` / `urllib` / `aiohttp` / shell `curl`)裸调 paper_server API —— 一律走 helper。裸调跳过本 skill "中文转英文术语" / `has_pdf` / `year_gte` filter 教学,典型坑:`search=cement+based` 字符级模糊匹配返几千条横跨无人机 / 锂电池 / 热界面,LLM 还以为搜对了 -- 用户输中文直接 `search(中文)` —— 转英文术语,见上节 -- `search(limit=50)` 一次拉满后 dump 给 LLM 全文(只 print 前 5-10 条精简就够,要全部让用户自己 `print(papers)`) -- 已经看到 abstract 还 `get_paper` 一遍(list 已带 abstract,重复调白费 roundtrip) -- 没看 abstract 就 `fetch_pdf` / `fetch_xml`(80% 场景 abstract 够用,下载全文慢且费带宽) -- `has_fulltext_xml=True` 时盲走 `fetch_pdf`(XML 对 LLM 更友好,先试 fetch_xml) -- 编造 DOI / title / 作者 —— 不在 paper_server 库里就**明确告诉用户"未命中"**,不要凭训练数据脑补 -- 把 `fetch_pdf` 返回的相对路径当绝对路径用(它是相对 `working_dir` 的) +- 认证或网络失败时,明确说明 `paper_server` 当前不可用;认证失败需要管理员检查 zcbot 的 `PAPER_SERVER_API_KEY` 配置。 +- DOI 未命中、全文格式缺失或服务器文件不存在时,可改查其他候选或使用现有摘要,不把“已收录”写成“已读全文”。 +- 未命中时可调整术语和过滤条件;没有新增检索思路时如实说明覆盖不足。 +- 只引用返回记录中的真实题名、作者、DOI 和正文,不推测缺失的 ISBN、出版社、版本、页码或内容。