4.6 KiB
4.6 KiB
| name | description |
|---|---|
| research | 查 paper_server 文献库(基于 OpenAlex 元数据 + Sci-Hub 下载的内部部署)。用户要查文献、找 DOI、拉 PDF、做文献综述、写带引文的申报书 / 研究方案 / 调研报告时使用。 |
Research
paper_server 是内部部署的 Django 文献库:元数据来自 OpenAlex,PDF 由 Sci-Hub 异步抓取。本 skill 给你三个 helper(search / get_paper / fetch_pdf),用 run_python 调用,不要自己 httpx 裸调 API。
何时用
- 用户要查 / 找 / 看 / 推荐文献
- 要 DOI、要某篇 PDF、要 abstract
- 写申报书 / 研究方案 / 调研报告的"国内外现状"段需要真实文献支撑
- 配合
proposalskill 的「立项依据」起草 —— 先search拿候选,get_paper看 abstract 决定要不要引
何时不用
- 用户只问通识(直接答即可,不需要文献支撑)
- 用户已经给了具体文献清单(直接用,不要二次校验)
- paper_server 没覆盖的领域(本库主打中文工程 / 材料 / 土木 / 化学;前沿 AI / 数学 / 纯理论 paper 命中率低 —— 命中 0 条直接告诉用户,不要瞎编)
准备
from skills.research.paper import search, get_paper, fetch_pdf
(import 路径由 run_python 注入的 PYTHONPATH 提供,直接写就行,不必折腾 sys.path)
三个函数
search(keyword="", year=None, doi="", has_pdf=None, limit=10) -> list[dict]
搜文献,返回精简列表(每条只含 id / doi / title / first_author / publication_year / publication_name / has_fulltext_pdf / has_abstract / type)。
keyword: paper_server 的 search 字段,匹配 title / first_author / first_author_institutionyear: 精确年份(目前只支持 exact)doi: 精确 DOI(命中 0 / 1 条)has_pdf=True仅返已下好 PDF 的;False仅返没 PDF 的;None都返limit: 默认 10,上限 50
# 找最近 5 篇关于"水泥水化"且已下好 PDF 的
papers = search(keyword="水泥水化", has_pdf=True, limit=5)
for p in papers:
print(p["title"], p["doi"], p["publication_year"])
get_paper(id_or_doi) -> dict
取单条完整 metadata + abstract。id_or_doi 既接受 paper_server 内部 id,也接受 DOI(自动解析)。
paper = get_paper("10.1016/j.cemconres.2020.106156")
print(paper["title"])
print(paper["abstract"]) # 没 abstract 时是空串,不会抛
fetch_pdf(id_or_doi, working_dir) -> str
下载 PDF 到 <working_dir>/papers/<safe_doi>.pdf,返回相对路径 papers/<safe_doi>.pdf(safe_doi 把 / 换成 _)。已存在跳过下载直接复用。
rel = fetch_pdf("10.1016/j.cemconres.2020.106156", working_dir=r"D:/projects/zcbot/workspace/users/<uid>/<wd>")
# rel == "papers/10.1016_j.cemconres.2020.106156.pdf"
has_fulltext_pdf=False 时抛 RuntimeError —— 这时该 paper 服务器侧还没下到 PDF,告诉用户不要硬等。
标准工作流
- search:按关键词 / 年份缩窄候选(
limit=10起,不够再扩) - 筛选:扫返回列表,挑相关的(看 title + first_author + year),
has_fulltext_pdf=True的优先 - get_paper:对每篇候选拿 abstract,确认确实切题再继续
- fetch_pdf:确定要全文细读时才下载(用户没说要全文就别下,abstract 已足够覆盖大多数引用场景)
- read PDF:
fetch_pdf返回相对路径,用主 agent 的read工具读 PDF 提取关键段(zcbot 已内置 PDF 文本提取)
错误处理
- 网络超时 / paper_server 不可达:
httpx.ConnectError/httpx.TimeoutException—— 直接告诉用户"paper_server 暂时连不上",不要重试堆栈刷屏 doi 未命中/doi 命中多条:get_paper/fetch_pdf内部_resolve_to_id抛ValueError—— DOI 拼写错或库里真没收录,改 keyword 重搜has_fulltext_pdf=False:fetch_pdf抛RuntimeError(reason=...)—— 服务器还没下到 PDF;告诉用户"这篇 paper_server 还没下到 PDF,可读 abstract 或换一篇"abstract字段为空字符串:正常情况,不是错;告诉用户"这篇没收录摘要"即可
反模式
- 用
httpx/requests裸调 paper_server API(走 helper,免得 base_url / auth / 字段名漂移时四处改) search(limit=50)一次拉满后扔给 LLM 全文 dump(只 print 前 5-10 条精简就够,要全部让用户自己print(papers))- 没看 abstract 就
fetch_pdf(80% 场景 abstract 够用,下载 PDF 慢且费带宽) - 编造 DOI / title / 作者 —— 不在 paper_server 库里就明确告诉用户"未命中",不要凭训练数据脑补
- 把
fetch_pdf返回的相对路径当绝对路径用(它是相对working_dir的)