Skip to main content
Glama

PDF-RAG

本地元器件手册检索:对 PDF/Markdown 手册库做语义向量 + 全文(FTS) + 子串三路混合检索 (RRF 融合 → 同文档去重 → 可选重排),支持表格识别与扫描页 OCR 兜底,通过 Web 界面、 MCP 工具、REST API 三种方式对外提供服务。

                     ┌──────────────┐
   浏览器   ──────▶  │  Web UI      │ Vue 3 + naive-ui(打进镜像,由后端托管)
                     ├──────────────┤
  MCP 客户端 ─────▶  │  /mcp        │ 8 个 pdf_rag_* 工具(默认内嵌进后端进程)
  pi 等 REST ─────▶  │  /api/*      │ 与 MCP 共用 backend/library.py 的实体逻辑
                     ├──────────────┤
                     │ LanceDB      │ 向量 + FTS 全文索引
                     └──────────────┘

快速上手

cp .env.example .env        # 至少填 EMBED_API_KEY
uv sync                     # 装依赖(Python 3.13)
uv run run_backend.py       # http://127.0.0.1:8100(含 Web UI 与 MCP)

手册放进 pdf/(或 .env 的 PDF_ROOT),然后在 Web「索引状态」页点增量索引。

文档

内容

docs/ARCHITECTURE.md

架构设计:分层与依赖方向、检索流水线、索引构建、配置边界、关键不变量——改代码前先读

DEPLOY.md

部署指南、REST API 全表、索引与数据包运维(另附内网形态文档 DEPLOY-NAS.md,不入库)

BENCHMARKS.md

检索质量基线、历次参数实验(含否定性结果)、测试方法学——调参/换模型前先读

THIRD-PARTY.md

依赖许可清单与第三方声明

docs/VECTOR-PARTITION.md

设计稿:按模型分区的向量存储(多模型混用、换模型只做增量)

Related MCP server: rag-mcp

目录结构

backend/
  main.py         FastAPI 应用与全部 HTTP 接口
  config.py       配置中心:环境类常量 + 可调参数注册表(Spec,含中文 label)
  library.py      读页、精确检索、元数据缓存的共享实现(MCP 与 HTTP 共用)
  retrieval.py    检索核心:三路召回 + RRF 融合 + 去重 + 重排 + 片段定位
  ingest.py       索引构建(多进程提取 + 批量嵌入)
  doc_utils.py    PDF/Markdown 文本提取、表格 markdown 化
  ocr.py          OCR 后端抽象(local Paddle / remote VLM)+ 调用状态记录
  bundle.py       数据包(.tar.zst)导出/导入
  vecstore.py     向量分区:uid、分区表、覆盖率(见 docs/VECTOR-PARTITION.md)
server.py         MCP 服务(默认内嵌;MCP_INPROC=0 时独立进程)
ocr_service.py    本机 OCR 服务(独立进程,依赖 ocr-env,可选)
run_backend.py    后端守护:崩溃自愈 + 单例锁
eval_retrieval.py 检索质量评测
eval_queries.json 评测集(55 条)
BENCHMARKS.md     评测结果与历次实验记录
DEPLOY.md         部署指南(裸机 / 交付包 / API 参考)
tools/            开发期诊断与维护脚本
web/              前端源码(Vue 3 + Vite + naive-ui)
index.lance/      LanceDB 索引(运行时生成)
data/             运行时配置覆盖值与导出包(运行时生成)

各模块为什么这样分层、彼此依赖方向、哪些约束不能破,见 docs/ARCHITECTURE.md。

环境要求

  • Python 3.13 + uv

  • Node.js(仅前端开发/构建;镜像里已有构建好的 web/dist)

  • 嵌入 / 重排服务:OpenAI 兼容的 /v1/embeddings 与 /v1/rerank

  • OCR(可选):本机 Paddle 需独立 ocr-env(约 4.9GB);也可用远程视觉模型,无需本地环境

配置

配置分两层,边界是密钥只在环境层。

① 环境层(.env,改完需重启):

PDF_ROOT=/path/to/manuals                     # 留空则用 <项目>/pdf
DB_PATH=/path/to/index.lance                  # 留空则用 <项目>/index.lance
EMBED_BASE_URL=https://api.example.com/v1     # OpenAI 兼容 /v1
EMBED_API_KEY=                                # 只从环境读,绝不入库/入包/进前端
EMBED_MODEL=qwen3-embedding-8b                # 与索引强绑定,必须与建库时一致
EMBED_DIMENSIONS=768                          # 与索引维度一致,建库/查询两侧都显式发送
RERANKER_MODEL=rerank-v4.0-pro
OCR_API_KEY=                                  # remote OCR 密钥(同上,只在环境层)
ADMIN_TOKEN=                                  # 留空则 /api/admin/* 一律 403

② 可调参数层(54 项 / 10 组):Web「检索配置」页运行时修改、即时生效,覆盖值持久化到 data/settings.json。OCR 地址/模型/提示词在此层(按 ocr_backend 联动),但 OCR_API_KEY 永远只在环境层;向量维度必须与索引一致(当前 768,随数据包导出),不符时向量通道明确 降级并记日志。

设计约束:系统不以任何方式定时或主动探测嵌入/重排/OCR 服务的可用性;OCR 状态展示 最近一次真实调用的结果。要确认上游可用,跑一次真实检索即可。这类"刻意不做"的决定 见 docs/ARCHITECTURE.md §7。

使用

Web(6 个页面):索引状态(触发索引/实时进度)、资料库(统计与历史)、文件库(筛选与 提取质量体检)、检索测试(三模式/重排开关/命中页预览)、检索配置(54 项)、数据管理 (配置与数据包导入导出)。

MCP:8 个工具,统一 pdf_rag_ 前缀(与客户端自带的 grep/read 区分——后者搜工作区 文件,这里搜手册语料)。

工具

用途

pdf_rag_search(query, category, top_k, file, max_per_doc)

混合检索,返回已定位到答案的片段窗口

pdf_rag_grep(pattern, category, file, context, flex_separator)

字面/正则精确检索,不走向量,不受嵌入服务影响

pdf_rag_read_page(file, page) / pdf_rag_read_pages(file, pages)

读整页原文(扫描页自动 OCR)/ 一次读多页

pdf_rag_get_outline(file)

书签/标题目录,用于大手册导航

pdf_rag_list_categories() / pdf_rag_list_files(category)

类别 / 已索引文件与元数据

pdf_rag_status()

索引与依赖状态(含 OCR 最近一次真实调用)。不探测上游

REST:与 MCP 能力等价,完整端点表见 DEPLOY.md。clients/pi/pdf-rag-pi/ 附带一个 pi 编码 agent 的原生扩展示例(同名 pdf_rag_* 工具 + 用法 SKILL),底层走这套 REST 接口,可作为其它非 MCP 客户端的接入参考。

索引

uv run python -m backend.ingest            # 增量(按 MD5 跳过未变化文件)
uv run python -m backend.ingest --rebuild  # 全量重建(换嵌入模型后必须)

也可在 Web「索引状态」触发,或在「文件库」勾选指定文件重跑(含 OCR)。长期增量会产生 索引碎片,定期用 tools/compact_index.py 整理(见 DEPLOY.md)。

数据包(导出 / 导入)

把索引 + PDF + 配置打成一个 .tar.zst,可在另一台机器完整复原;导入预检会比对包内 与本地的服务配置,模型不一致时明确拒绝,不让新旧向量静默混用。命令与细节见 DEPLOY.md;密钥不入包。

评测

uv run python eval_retrieval.py              # 55 条评测集(hand 10 / topic 4 / mined 41)

两级指标:recall@k(期望文档进没进 top-k)与 snippet@1/@k(片段是否含答案字面值—— 判别指标)。当前基线:recall@5 100% / snippet@1 62% / snippet@5 91%。重排器有固有 随机性(±2pp),改动前后各跑两遍;评测方法、匹配规则与历次实验见 BENCHMARKS.md。

开发

cd web && pnpm install && pnpm dev    # 前端开发(Vite 代理 /api 到 8100)
cd web && pnpm build                  # 构建 → web/dist,Dockerfile 会 COPY 它

测试:关键路径单测在 tests/(纯逻辑,不访问网络与索引,113 个用例):

uv run python -m unittest discover -s tests

覆盖:路径边界防护、分块、版本合并去重、融合排序与平局裁决、缓存失效、file 过滤字面 语义、片段窗口、向量分区(uid 唯一性 / slug 契约区分 / 覆盖率口径 / 索引保真)、 数据包导入判断。改动检索/索引逻辑后跑一遍;端到端质量另用 eval_retrieval.py 对比 snippet@1;改动前端用 pnpm build 的类型检查兜底。

鸣谢

  • 感谢 futureppo 提供了几乎无限的免费向量化/重排序模型, 帮助本项目完成测试与调优。

许可证

本项目以 GNU AGPL v3.0 或更高版本(AGPL-3.0-or-later)发布,见 LICENSE。 这不是偏好而是依赖约束:直接依赖的 PyMuPDF(MuPDF)为 AGPL-3.0 / 商业双许可,传染性 使整体必须按 AGPL 分发。

场景

是否可以

自用 / 内部部署

✅ 可以

修改后对外提供网络服务

✅ 可以,但须按 AGPL §13 向网络用户提供对应源码

分发修改版

✅ 可以,但须同样以 AGPL 开放源码

闭源 SaaS / 闭源分发

❌ 需要 Artifex 商业许可,或替换掉 PyMuPDF

依赖许可核对与第三方声明见 THIRD-PARTY.md。

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Provides read-only MCP tools for hybrid semantic and keyword search over locally indexed PDF documentation, with citations and context retrieval for LLM agents.
      -
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables agents to search a local, fully offline personal document library (Markdown/txt/PDF/docx) via SQLite FTS5 trigram search with subject-terminology expansion, returning every hit with its domain, document title, section path, and page or offset provenance. It also exposes domain statistics, incremental ingestion, and document deprecation as tools, alongside a read-only, runtime-persona-scoped ask/coverage mode.
      -
    • F
      license
      Not graded
      quality
      A
      maintenance
      Enables AI agents and MCP hosts to query locally indexed notes, docs, chat logs, and other files via hybrid vector/BM25 retrieval with section-level citations. Exposes tools, resources, and prompts for searching and asking over the indexed content.
      -