内容
# PubMed 自然语言搜索代理
[](LICENSE)
[](https://www.python.org/downloads/)
[](https://github.com/Dariolex/pubmed-search-agent/actions/workflows/tests.yml)
使用自然语言问题搜索 PubMed,而不是布尔查询语法。该项目将自然语言请求翻译成真正的 PubMed 高级搜索查询,在官方 NCBI E-utilities API 上运行,并根据与您实际问题的**语义相关性**过滤结果 — 而不仅仅是关键词重叠。
```
"查找过去 3 年内关于转移性黑色素瘤的免疫疗法的研究,
仅限随机对照试验,不包括病例报告"
│
▼ 自然语言 → PubMed 查询翻译
("melanoma"[MeSH Terms] OR "melanoma"[tiab]) AND
("immunotherapy"[MeSH Terms] OR "immunotherapy"[tiab]) AND
"metastatic"[tiab] AND "randomized controlled trial"[pt] AND
("2023"[dp] : "2026"[dp])
│
▼ ESearch / EFetch 对 NCBI E-utilities
▼ 语义相关性过滤
▼
排名结果,每个结果都有理由和链接以供您自行验证查询
```
> **语言说明:** 本 README 使用英文以便传播,但代码库、内联注释和 Claude 技能指令均为**意大利语**。如果这对您造成障碍,请参阅 [贡献](#contributing)。
## 为什么存在
布尔型 PubMed 查询精确但不宽容 — 如果一个字段标签错误,您将无声地错过一半的文献。PubMed 自己网站上的自由文本搜索则宽容但嘈杂。该项目试图获得两者的优势:从自然语言到正确 PubMed 语法的**确定性、可审计的翻译步骤**,然后由 LLM 读取实际摘要以判断相关性 — 就像研究人员一样,而不是关键词匹配器。
生成的查询和直接的 PubMed 链接始终显示给您,以便您验证解释并在需要时进行更正 — 该项目是 PubMed 上的翻译和排名层,而不是黑盒。
## 功能
- **自然语言 → PubMed 查询翻译** — 结构化概念提取,然后是发出正确字段标签的确定性序列化器(`[tiab]`、`[MeSH Terms]`、`[pt]`、`[dp]`、`[la]`、`[cois]`)、布尔运算符和日期范围。
- **权威 MeSH 解析** — 验证候选 MeSH 术语与 NCBI 受控词汇(`db=mesh`)而不是猜测,并拉取官方入口术语(同义词)。
- **语义相关性过滤** — LLM 读取标题和摘要,并根据您的实际意图对结果进行排名/丢弃,标记因过于严格的布尔查询而排除的好文章。
- **相关文章和引用链** — 给定 PMID,找到类似的文章或引用它的所有文章,通过 `elink.fcgi`。
- **专利/利益冲突过滤器** — PubMed 不直接索引专利,因此搜索利益冲突声明字段并公开原始披露文本,以便可以将否定声明(“作者不持有专利”)与真正的肯定声明区分开来。
- **MCP 服务器** — 将搜索公开为 MCP 工具(`search_pubmed_papers`),可从 Claude Desktop 或任何 MCP 兼容客户端使用,带有在调用之间存活的速率限制器。
- **速率限制感知** — 显式令牌桶限制器尊重 NCBI 的 10 req/s 限制(使用 API 密钥)并在 429/5xx 上重试。
## 构建方式
每个模块都可以独立测试:
```
src/
├── pubmed_errors.py # 共享异常层次结构
├── pubmed_models.py # 数据类 + 纯 XML 解析(无网络)
├── pubmed_client.py # E-utilities 包装器:速率限制、重试、esearch/efetch/elink/resolve_mesh
├── run_search.py # CLI 入口点:查询 → esearch/efetch → JSON
├── nl_query_translator.py # 确定性序列化器:中间 JSON → PubMed 语法
├── mesh_resolver.py # CLI:自由术语 → 权威 MeSH 描述符
├── related_search.py # CLI:PMID → 相似文章 / 引用文章
└── mcp_server.py # MCP 工具,公开搜索管道
```
`pubmed_client.py` 永远不包含自然语言解释逻辑;`nl_query_translator.py` 永远不进行 HTTP 调用。自然语言理解步骤存在于驱动管道的 Claude 技能(`.claude/skills/pubmed-search/`)中,这是一个刻意的设计选择 — 它使每个确定性步骤都可以在固定 JSON/XML 夹具的情况下离线测试,并将一个非确定性步骤(读取和判断文本)隔离在它所属的位置。
## 入门
**1. 获取免费的 NCBI API 密钥** — [ncbi.nlm.nih.gov/account](https://www.ncbi.nlm.nih.gov/account/) → *设置 → API 密钥管理*。不是严格要求,但将您的速率限制从 3 次/秒提高到 10 次/秒。
**2. 配置 `.env`**(复制 `.env.example`):
```
NCBI_API_KEY=您的密钥
NCBI_TOOL_NAME=pubmed-nl-search-agent
NCBI_EMAIL=您@example.com
```
**3. 安装依赖项:**
```bash
pip install -r requirements.txt
```
## 用法
### 作为 Claude Code 技能(推荐)
在 [Claude Code](https://claude.com/claude-code) 中打开此存储库,并直接用自然语言询问:
> *"查找过去 2 年内关于淋巴瘤的 CAR-T 疗法的研究,仅限临床试验"*
`pubmed-search` 技能(`.claude/skills/pubmed-search/SKILL.md`)端到端处理自然语言到查询的翻译、执行和相关性排名,始终显示生成的查询和 PubMed 链接,然后再呈现结果。
### 作为 MCP 服务器
添加到您的 `claude_desktop_config.json`:
```json
{
"mcpServers": {
"pubmed-search": {
"command": "python",
"args": ["/绝对路径/到/src/mcp_server.py"]
}
}
}
```
这公开了一个单独的细粒度工具,`search_pubmed_papers(term, retmax)`。`term` 必须是有效的 PubMed 语法 — 调用模型负责自然语言到查询的翻译步骤,就像任何其他 MCP 工具消费者一样。
### 从命令行
```bash
# 运行搜索(术语必须是有效的 PubMed 语法)
PYTHONPATH=src python -m run_search --term '"melanoma"[tiab] AND "immunotherapy"[tiab]' --retmax 30
# 将自由术语解析为其官方 MeSH 描述符
PYTHONPATH=src python -m mesh_resolver --termine "melanoma"
# 查找与已知 PMID 相似的文章或引用它的文章
PYTHONPATH=src python -m related_search --pmid 33301246 --tipo simili --max 30
PYTHONPATH=src python -m related_search --pmid 33301246 --tipo citazioni --max 30
# 将结构化 JSON 请求转换为 PubMed 语法(确定性,无网络)
PYTHONPATH=src python -m nl_query_translator --file query.json --link
```
## 测试
```bash
pytest # 离线套件 — 无网络调用,夹具 + 固定 XML
pytest -m live # 在线套件 — 对 NCBI 进行真实调用,需要有效的 .env
```
实时模式夹具不是手写的:`python tests/record_fixtures.py` 将真实的 NCBI 响应记录到 `tests/fixtures/`,在写入磁盘之前剥离 API 密钥 — 因此解析器始终针对真实的 API 输出进行测试,而不是对模式的理想化猜测。
## 路线图状态
| 步骤 | 状态 |
|---|---|
| 核心客户端:ESearch + EFetch,速率限制,类型解析 | ✅ |
| 自然语言到 PubMed 查询翻译 | ✅ |
| 通过 Claude 技能进行端到端搜索 | ✅ |
| 语义相关性过滤 | ✅ |
| 权威 MeSH 解析 | ✅ |
| MCP 服务器(`search_pubmed_papers`) | ✅ |
| 相关文章和引用链(`elink`) | ✅ |
| 专利/利益冲突过滤器 | ✅ |
有关完整的架构细节和设计原理,请参阅 `CLAUDE.md`(项目指南,意大利语)。
## 限制
- **仅限 PubMed。** 没有 Semantic Scholar,没有 Google Scholar,没有跨数据库覆盖。
- **没有系统性审查工作流程。** 没有 PRISMA 支持,没有结构化数据提取到表格中,没有协作筛选 — 如果您需要这些,请改用 [Elicit](https://elicit.com)、Covidence 或 Rayyan。
- **没有 UI。** 这是一个 CLI + 一个 Claude 技能 + 一个 MCP 工具。您需要熟悉终端(或 Claude Code)才能直接使用它。
- **专利过滤器是代理,不是基本事实。** PubMed 不索引专利;过滤器搜索自由文本利益冲突声明,这可能不完整、缺失或表述模糊。
## 贡献
欢迎贡献 — 代码、文档或翻译。现有代码库(注释、文档字符串、`pubmed-search` 技能、`CLAUDE.md`)为**意大利语**;欢迎以英文进行新的贡献,但请不要在与无关更改的同一 PR 中将现有的意大利语内容重写为英文。请参阅 [CONTRIBUTING.md](CONTRIBUTING.md) 以了解设置和约定。
## 许可证
[MIT](LICENSE) — 您可以对其执行任何操作,包括分叉、修改和重新分发,无论是商业还是非商业用途。保留许可证通知是出于礼貌,但不是必需的。
## 致谢
针对 [NCBI E-utilities](https://www.ncbi.nlm.nih.gov/books/NBK25501/) 构建。使用 [Claude Code](https://claude.com/claude-code) 进行端到端开发,使用 TDD 和真实 API 验证每个设计步骤 — 如果您好奇它是如何构建的,请参阅 `docs/superpowers/` 目录以获取设计规格和实现计划。