内容
# 图学学者
**基于Neo4j的图RAG知识库,用于研究论文,通过MCP协议暴露给AI助手。**
[](https://www.typescriptlang.org)
[](https://neo4j.com)
[](https://modelcontextprotocol.io)
图学学者从ArXiv获取论文,建立作者、引用、概念和嵌入文本块的知识图谱,然后允许Claude、Cursor或任何MCP客户端查询该图谱,而不仅仅依赖于扁平的关键词或向量搜索。
> 有关深入的架构说明、摄取阶段和模式详细信息,请参阅 [DESIGN.md](./DESIGN.md)。
---
## 目录
- [研究论文的RAG问题](#研究论文的RAG问题)
- [什么是图RAG?](#什么是图RAG?)
- [图学学者做什么](#图学学者做什么)
- [工作原理](#工作原理)
- [快速入门](#快速入门)
- [图谱模式](#图谱模式)
- [MCP工具](#MCP工具)
- [配置](#配置)
- [项目结构](#项目结构)
- [技术栈](#技术栈)
- [路线图](#路线图)
- [许可证](#许可证)
---
## 研究论文的RAG问题
大多数RAG教程将文档视为向量数据库中孤立的文本块。这适用于FAQ和内部文档,但对于**研究文献**,含义存在于关系中:
| 您需要 | 简单RAG提供 |
|---|---|
| “图RAG建立在哪些论文之上?” | 提到引用的文本块,可能脱离上下文 |
| “谁还研究过知识图谱**和**大型语言模型?” | 段落的语义相似性 - 错过作者重叠 |
| “该集群中引用最多的论文使用了什么方法?” | 无法排名或遍历引用结构 |
| “该声明是基于论文本身还是参考文献?” | 检索的文本块可能来自错误的章节或论文 |
**具体的失败模式:** 您询问“检索增强生成与知识图谱”。向量搜索返回三篇不同论文的段落。没有一篇解释这些论文如何引用彼此,哪位作者引入了哪个想法,或者哪篇论文是基础性的还是后续的调查。大型语言模型用听起来合理的猜测填补空白。
研究不是一段段的文章。它是一个**图谱**:论文引用论文,作者撰写论文,论文引入和重用概念,章节承载不同类型的证据(摘要 vs. 方法 vs. 参考文献)。
---
## 什么是图RAG?
**图RAG** 将向量搜索与**结构化图谱遍历**相结合,以便检索可以遵循关系,而不仅仅是余弦相似性。
### 简单RAG
```
用户问题
→ 嵌入查询
→ 找到前K个相似文本块
→ 将文本块塞入大型语言模型提示
→ 答案
```
快速、简单,但对结构视而不见。
### 图RAG(图学学者实现)
```
用户问题
→ (:Chunk) 节点的向量搜索 ← 论文文本的语义匹配
→ 遍历到 (:Paper)、(:Author)、(:Concept)
→ 跟随 [:CITES]、[:INTRODUCES]、[:USES]、[:WROTE]
→ 组装多跳上下文
→ 大型语言模型用有根基的、连接的证据回答
```
**这在实践中很重要:**
1. **引用链** - 您检索的论文可能会引用一个基础性工作,该工作与您的查询没有相同的措辞,但通过图谱是一步之遥。图谱遍历揭示了它;纯向量搜索通常会错过它。
2. **概念路由** - 论文与提取的概念(`INTRODUCES`、`USES`)相关联。您可以找到与“图神经网络”相关的所有内容,而不仅仅是碰巧包含这些词的段落。
3. **出处** - 文本块与论文、章节和索引绑定。模型可以区分抽象声明和方法细节。
4. **作者和类别上下文** - 您可以从一篇论文跳转到作者撰写的其他所有内容,或者跳转到ArXiv类别中的所有内容,而无需重新嵌入整个语料库。
图RAG不会取代向量搜索 - 它**扩展**了向量搜索。图学学者在Neo4j中存储`(:Chunk)`和`(:Concept)`节点的嵌入,并使用图谱进行向量搜索无法看到的所有操作。
---
## 图学学者做什么
图学学者是一个端到端的TypeScript管道:
1. **获取** 来自ArXiv API的论文元数据
2. **下载** PDF并将它们分成学术章节(摘要、介绍、方法、结果、结论、参考文献)
3. **建立引用图谱** 通过解析参考文献并将它们解析为ArXiv ID
4. **提取概念** 从摘要中通过大型语言模型(或基于类别的轻量级备用方案)
5. **切分和嵌入** 章节文本,在Neo4j节点上存储向量
6. **暴露图谱** 作为 [MCP](https://modelcontextprotocol.io/) 服务器,以便AI助手可以查询它作为原生工具
默认种子语料库专注于RAG / 图RAG研究线(Self-RAG、RAG调查、注意力、原始RAG、HippoRAG)。摄取一篇论文可以发现引用的论文并自动扩展图谱。
### MCP连接的助手可以很好地回答的示例问题
- *"Self-RAG引用了哪些ArXiv论文,引入了哪些概念?*"
- *"总结论文 `2310.11511` 的方法块。*"
- *"HippoRAG与Self-RAG相比,使用或引入了哪些概念?*"
- *"与RAG调查论文相关的类别和作者是什么?*"
助手调用MCP工具,读取结构化的图谱结果,并对它们进行推理 - 而不是仅凭训练数据进行臆测。
---
## 工作原理
```
ArXiv API ──► 元数据 ──► 论文、作者、类别节点
│
▼
ArXiv PDF ──► 文本提取 ──► 章节分割 ──► 文本块 ──► 嵌入 ──► 文本块节点
│ │
│ └── 参考文献解析 ──► 引用边
│
└── 摘要 ──► 大型语言模型概念提取 ──► 概念节点 + 引入/使用
Neo4j
│
▼
MCP服务器(stdio)
│
▼
Claude Desktop / Cursor / 任意MCP客户端
```
### 摄取管道(每篇论文)
| 阶段 | 发生情况 |
|---|---|
| **1. 元数据** | 从ArXiv获取标题、摘要、作者、类别、日期。创建 `Paper`、`Author`、`Category` 节点。 |
| **2. PDF** | 下载PDF,提取文本,分割成章节。参考文献仅用于引用解析 - 不切分。 |
| **3. 引用** | 解析参考文献部分,解析标题/ID到ArXiv,创建 `CITES` 边(和被引用的作品的存根 `Paper` 节点)。 |
| **4. 概念** | 大型语言模型从摘要中提取引入/使用/相关的概念,或轻量级模式将ArXiv类别映射到概念。 |
| **5. 文本块** | 少于400字的章节 → 一个文本块;较长的章节 → 重叠的段落窗口。每个文本块都有一个嵌入。 |
| **6. MCP** | 工具在对话时查询实时图谱以供助手使用。 |
运行所有种子论文的完整管道:
```bash
npm run seed
```
通过编辑 `src/config/papers.ts` 并重新运行种子来添加更多论文。
---
## 快速入门
### 先决条件
- **Node.js 20+**
- **Docker** (用于本地Neo4j)
- **OpenAI兼容的API** 用于嵌入和概念提取 - [oMLX](https://github.com/ml-explore/mlx) 在Apple Silicon上是默认的,或者在 `.env.example` 中将 `OPENAI_BASE_URL` 指向OpenAI
### 1. 克隆并安装
```bash
git clone https://github.com/iikareem/GraphScholar.git
cd GraphScholar
npm install
```
### 2. 启动Neo4j
```bash
docker compose up -d
```
Neo4j浏览器: [http://localhost:7474](http://localhost:7474) - 使用 `.env` 中的 `neo4j` 和密码登录
### 3. 配置环境
```bash
cp .env.example .env
```
**完整管道** - 设置您的嵌入/大型语言模型端点和模型:
```bash
OPENAI_BASE_URL=http://localhost:8000/v1 # oMLX 或 OpenAI
OPENAI_API_KEY=your_key
CONCEPT_MODEL=mlx-community/Llama-3.2-1B-Instruct-4bit
EMBEDDING_MODEL=mlx-community/bge-m3-mlx-8bit
EMBEDDING_DIMENSIONS=1024
NEO4J_PASSWORD=your_password
```
**轻量级模式(无大型语言模型,无嵌入)** - 在有限RAM上测试图结构非常有用:
```bash
INGESTION_LIGHT_MODE=true
```
轻量级模式使用ArXiv类别作为概念的替代品,并跳过嵌入生成。
### 4. 初始化模式
```bash
npm run schema
```
在 `Chunk.embedding` 和 `Concept.embedding` 上创建唯一性约束、B树索引和向量索引。
### 5. 摄取论文
```bash
npm run seed
```
摄取 `src/config/papers.ts` 中的默认论文列表。预计每篇论文需要几分钟(PDF下载、引用解析、API调用)。
### 6. 启动MCP服务器
```bash
npm run mcp
```
服务器通过 **stdio** 讲话日志输出到stderr;不要将其包装在捕获stdout的工具中。
### 7. 连接到Claude Desktop
在 `claude_desktop_config.json` 中添加:
```json
{
"mcpServers": {
"graph-scholar": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/GraphScholar/src/mcp/server.ts"],
"env": {
"NEO4J_URI": "bolt://localhost:7687",
"NEO4J_USERNAME": "neo4j",
"NEO4J_PASSWORD": "your_password"
}
}
}
}
```
重启Claude Desktop。 `get_paper` 工具应在工具列表中出现。
### 默认种子论文
| ArXiv ID | 论文 |
|---|---|
| `2310.11511` | Self-RAG |
| `2312.10997` | 高级RAG调查 |
| `1706.03762` | 注意力就是你需要的全部 |
| `2005.11401` | 基于检索的增强知识密集型NLP生成 |
| `2405.14831` | HippoRAG |
---
## 图谱模式
### 节点
| 标签 | 关键属性 | 角色 |
|---|---|---|
| `Paper` | `id`、`title`、`abstract`、`published`、`pdfUrl` | 一篇ArXiv论文 |
| `Author` | `name` | 论文作者 |
| `Category` | `name` | ArXiv类别(例如 `cs.CL`) |
| `Concept` | `name`、`embedding` | 从文献中提取的主题或方法 |
| `Chunk` | `id`、`text`、`section`、`chunkIndex`、`embedding` | 可搜索的论文文本片段 |
### 关系
| 类型 | 模式 | 含义 |
|---|---|---|
| `WROTE` | `Author → Paper` | 作者身份 |
| `BELONGS_TO` | `Paper → Category` | ArXiv分类 |
| `HAS_CHUNK` | `Paper → Chunk` | 属于论文的文本段落 |
| `CITES` | `Paper → Paper` | 参考文献引用 |
| `INTRODUCES` | `Paper → Concept` | 论文引入了这个想法 |
| `USES` | `Paper → Concept` | 论文应用了这个方法/概念 |
| `RELATED_TO` | `Concept → Concept` | 相关想法(大型语言模型提取) |
---
## MCP工具
| 工具 | 状态 | 描述 |
|---|---|---|
| `get_paper` | **可用** | 论文元数据加上作者、类别、引用ID、概念和文本块计数 |
| `vector_search` | 搭建中 | 基于文本块嵌入的语义搜索 |
| `get_citation_chain` | 搭建中 | 多跳引用遍历 |
| `get_concept_papers` | 搭建中 | 引入或使用概念的论文 |
| `get_author_papers` | 搭建中 | 作者的所有论文 |
### `get_paper`
```json
{ "paper_id": "2310.11511" }
```
返回:
```json
{
"id": "2310.11511",
"title": "...",
"abstract": "...",
"authors": ["..."],
"categories": ["cs.CL"],
"citedPaperIds": ["..."],
"introduces": ["..."],
"uses": ["..."],
"chunkCount": 42
}
```
其他工具在 `src/mcp/tools/` 下实现,并在 `registerTools.ts` 中注册,随着服务器的成熟。有关完整的预期工具表面,请参见 [DESIGN.md](./DESIGN.md)。
---
## 配置
| 变量 | 默认值 | 目的 |
|---|---|---|
| `NEO4J_URI` | `bolt://localhost:7687` | Neo4j Bolt端点 |
| `NEO4J_USERNAME` | `neo4j` | 数据库用户 |
| `NEO4J_PASSWORD` | — | 数据库密码 |
| `INGESTION_LIGHT_MODE` | `false` | 跳过大型语言模型/嵌入;使用类别作为概念 |
| `OPENAI_BASE_URL` | `http://localhost:8000/v1` | OpenAI兼容的API基准 |
| `OPENAI_API_KEY` | — | 嵌入/大型语言模型服务器的API密钥 |
| `CONCEPT_MODEL` | — | 概念提取模型 |
| `EMBEDDING_MODEL` | — | 文本嵌入模型 |
| `EMBEDDING_DIMENSIONS` | `1024` | 向量大小(必须与模型 + Neo4j索引匹配) |
| `CHUNK_WORD_LIMIT` | `400` | 切分前的最大字数 |
| `CHUNK_OVERLAP_WORDS` | `40` | 连续文本块之间的重叠 |
| `MAX_CITATION_DEPTH` | `2` | 摄取期间的引用跟随深度 |
---
## 项目结构
```
GraphScholar/
├── src/
│ ├── ingestion/ # ArXiv获取、PDF解析、引用、概念、文本块
│ ├── graph/
│ │ ├── model/ # 节点/关系TypeScript类型
│ │ ├── repositories/ # Neo4j持久层
│ │ ├── driver.ts
│ │ └── schema.ts # 约束、索引、向量索引
│ ├── mcp/
│ │ ├── server.ts # MCP入口点(stdio)
│ │ ├── tools/ # MCP工具处理程序
│ │ └── queries/ # Cypher查询帮助程序
│ ├── config/ # 环境、AI模型、种子论文ID
│ ├── pipeline.ts # 协调每篇论文的摄取
│ └── seed.ts # 批次摄取来自配置
├── docker-compose.yml # 本地Neo4j 5
├── DESIGN.md # 详细架构和设计文档
└── .env.example
```
---
## 技术栈
| 层 | 选择 | 为什么 |
|---|---|---|
| 语言 | TypeScript | 从摄取到MCP响应的端到端类型 |
| 图数据库 | Neo4j 5 | 原生图查询 + 内置向量索引 |
| 协议 | MCP (`@modelcontextprotocol/sdk`) | Claude、Cursor等的标准工具接口 |
| PDF | `pdfjs-dist` | 纯JS提取,无系统依赖 |
| ArXiv | ArXiv API + `fast-xml-parser` | 元数据和PDF源 |
| 嵌入/大型语言模型 | OpenAI兼容的API(默认oMLX) | 本地或云;通过环境变量交换模型 |
| 运行时 | Node.js 20+ | 原生获取、ESM、`tsx`用于开发脚本 |
---
## 路线图
- [x] ArXiv元数据摄取
- [x] PDF提取和章节分割
- [x] 引用图构造
- [x] 大型语言模型概念提取(+ 轻量级模式备用)
- [x] 文本块和嵌入管道
- [x] 具有向量索引的Neo4j模式
- [x] 具有`get_paper`的MCP服务器
- [ ] 注册剩余的MCP工具(`vector_search`、`get_citation_chain`,...)
- [ ] 增量摄取(跳过已摄取的论文)
- [ ] 单篇论文CLI摄取命令
- [ ] 图可视化Web UI
- [ ] PDF上传支持(非ArXiv源)
- [ ] 相似名称的概念重复数据消除
---
## 为什么该项目存在
大多数RAG演示停留在“将PDF放入Pinecone”。图学学者展示了当您将研究建模为**知识图谱**时会发生什么:
- 引用成为可遍历的边,而不是埋在文本块中的脚注
- 概念成为您可以查询的顶级节点,跨论文
- 嵌入生活在具有论文/章节元数据的结构化节点上
- AI助手通过MCP作为适当的工具访问图谱,而不是一次性脚本
它是一个您可以运行的参考实现,扩展您自己的论文语料库,并连接到任何MCP客户端。
---
## 许可证
MIT