内容
# 文档查询系统 Docs-to-AI —— 基于MCP的文档查询系统
一款可投入生产的 RAG(检索增强生成),作为Model Context Protocol(MCP)服务器运行,支持LLM(如Claude Desktop或其他支持MCP的LLM)使用语义搜索查询您的文档。根据文件夹结构按主题组织文档。
支持的文件格式:PDF,Word,Excel,Markdown,PowerPoint,HTML,TXT,CSV。
支持的文件扩展名:.pdf,.docx,.doc,.xlsx,.xls,.xlsam,.xlsb,.md,.pptx,.html,.htm,.txt,.csv
用于文档检索的模型是all-MiniLM-L6-v2,嵌入维度为384。
## 功能特点
- 从PDF、Word、Excel、Markdown、PowerPoint、HTML、TXT和CSV文档中提取文本
- 根据主题(使用文件夹结构)组织文档
- 为语义搜索生成嵌入向量
- 将文档存储在向量数据库(chromadb)中
- 为Claude暴露MCP工具,用于搜索和检索文档
- 按主题/类别筛选搜索
- 处理具有相同文件名的多个文档,跨不同主题
- **高级搜索**:短语匹配、日期范围筛选、正则表达式模式匹配
- **智能分块**:固定大小、按段落、基于语义标题或基于令牌的分块
- 为更智能的检索保留标题/章节结构
- 可选的重新排序模型,以提高搜索质量
## 系统架构
```
文档(PDF、Word、Excel、Markdown、PowerPoint、HTML、TXT、CSV)
→ 文本提取
→ 分块(固定/段落/标题/令牌)
→ 嵌入向量
→ chromadb(带有主题标签)
↓
MCP服务器工具
↓
Claude
```
## 文档组织
该系统设计用于处理以文件夹结构组织的PDF文档,其中:
- 每个文件夹代表一个**主题**或**类别**
- 该文件夹中的PDF文档自动标记为主题名称
- 不同文件夹中具有相同文件名的文档正确处理
示例结构:
```
pdfs/
├── 机器学习/
│ ├── 神经网络.pdf
│ ├── 深度学习.pdf
│ └── 介绍.pdf
├── Python编程/
│ ├── 基础知识.pdf
│ ├── 高级.pdf
│ └── 介绍.pdf # 与ML的介绍.pdf不同
└── 数据科学/
├── 统计学.pdf
└── 可视化.pdf
```
## 1. 使用本地Python安装
该项目使用`uv`进行快速、可靠的Python包管理。
### 安装uv(如果尚未安装)
```bash
# 在macOS/Linux上
curl -LsSf https://astral.sh/uv/install.sh | sh
# 在Windows上
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
```
### 安装和运行
```bash
uv sync # 从pyproject.toml安装依赖项
python -m app.scan_all_my_documents # 导入文档
python mcp_server.py # 启动MCP服务器
```
### 双重传输模式
MCP服务器现在同时运行**两种传输方式**(感谢FastMCP):
- **stdio模式** - 用于通过Claude Desktop进行本地连接
- **HTTP/SSE模式** - 用于通过HTTP进行远程连接
两者默认情况下同时激活。服务器自动暴露:
- SSE端点:`http://localhost:38777/sse`(用于建立连接)
- 消息端点:`http://localhost:38777/messages/`(用于发送请求)
您可以使用命令行参数或环境变量自定义HTTP传输:
```bash
# 使用命令行参数
python mcp_server.py --host 0.0.0.0 --port 38777
# 或使用环境变量
export MCP_HOST=0.0.0.0
export MCP_PORT=38777
python mcp_server.py
```
脚本将:
- 递归扫描目录
- 从文件夹名称检测主题
- 从每个PDF/Word/Markdown/Excel中提取和分块文本
- 用主题标记块
- 将所有内容存储在chromadb中
示例输出:
```
找到15个PDF文件
基准目录:/path/to/pdfs
检测到的主题:数据科学,机器学习,Python编程
[1/15] 处理中:neural_networks.pdf
主题:机器学习
✓ 添加了45个块
...
导入总结
==================
处理的PDF总数:15
成功:15
失败:0
添加的块总数:523
每个主题的文档:
数据科学:4个文档,156个块
机器学习:6个文档,234个块
Python编程:5个文档,133个块
```
将以下内容添加到您的Claude Desktop配置(`%APPDATA%/Claude/claude_desktop_config.json`):
**用于stdio模式(本地):**
```json
{
"mcpServers": {
"docs-to-ai": {
"command": "python",
"args": ["C:/[UPDATE_PATH_TO_DOCS-TO-AI]/docs-to-ai/mcp_server.py"]
}
}
}
```
**用于HTTP/SSE模式(远程):**
```json
{
"mcpServers": {
"docs-to-ai": {
"url": "http://localhost:38777/sse",
"transport": "sse"
}
}
}
```
## 2. 使用Docker安装
您需要Docker Desktop或Docker Engine运行。然后只需将以下内容写入名为“docker-compose.yaml”的文件中,它将从Docker Hub拉取并运行镜像(镜像:https://hub.docker.com/r/dmeric/docs-to-ai ):
````yaml
services:
docs-to-ai:
image: dmeric/docs-to-ai
container_name: docs-to-ai
volumes:
- ./cache/chromadb:/app/chromadb # chromadb数据库(持久化向量存储)
- ./cache/doc_cache:/app/doc_cache # 文档缓存(持久化提取的文本)
- ./my-docs:/app/my-docs:ro # 文档目录(您的PDF和Word文档)。只读以防止意外修改
# Stdin/stdout - stdio模式下MCP协议所需
stdin_open: true
tty: true
ports:
- "${MCP_PORT:-38777}:38777" # 用于http/sse传输,位于http://localhost:38777/sse
# 重启策略
restart: unless-stopped
# # 资源限制(可选 - 根据您的需求调整)
# deploy:
# resources:
# limits:
# cpus: '2'
# memory: 4G
# reservations:
# cpus: '1'
# memory: 2G
````
然后在bash或Powershell中运行:
```bash
docker compose up -d
````
### Docker配置
`docker-compose.yml`配置:
**卷:**
- `./cache/chromadb:/app/cache/chromadb` - 向量存储数据库(持久化)
- `./cache/doc_cache:/app/cache/doc_cache` - 文档缓存(持久化)
- `./my-docs:/app/my-docs:ro` - 您的文档目录(只读)
**端口:**
- `38777` - HTTP/SSE端点,用于远程MCP连接
**环境变量:**
- `FULL_SCAN_ON_BOOT` - 设置为`True`以在启动时扫描文档(默认:`False`)
- `FOLDER_WATCHER_ACTIVE_ON_BOOT` - 设置为`True`以在启动时启动文件夹监视器(默认:`True`)
- `MCP_PORT` - 自定义HTTP端口(默认:`38777`)
示例,使用自定义环境变量:
```bash
# 创建一个.env文件
echo "FULL_SCAN_ON_BOOT=True" > .env
echo "FOLDER_WATCHER_ACTIVE_ON_BOOT=True" >> .env
echo "MCP_PORT=38777" >> .env
# 使用环境变量启动
docker compose up -d
```
将以下内容添加到您的Claude Desktop配置(`%APPDATA%/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"docs-to-ai": {
"command": "docker",
"args": [
"exec",
"-i",
"docs-to-ai",
"python",
"mcp_server.py"
]
}
}
}
```
最后,将您的文档放入`/my-docs`文件夹,并要求服务器扫描文档,可选地启动文件夹监视器。
您现在应该能够向LLM询问有关文档的问题。
## 项目结构
- `mcp_server.py` - 主要的MCP服务器实现(基于FastMCP)
- `app/document_processor.py` - 文档文本提取和分块(PDF,Word,Excel,Markdown)
- `app/vector_store.py` - 向量数据库操作(ChromaDB)
- `app/scan_all_my_documents.py` - 批量文档导入脚本
- `app/incremental_updater.py` - 增量文档更新逻辑
- `app/folder_watcher.py` - 自动文件夹监控和变更检测
- `app/config.py` - 配置设置
- `pyproject.toml` - Python依赖和项目元数据(使用`uv`)
- `Dockerfile` - Docker容器配置
- `docker-compose.yml` - Docker Compose配置
## MCP工具
服务器为LLM暴露了以下工具:
**搜索和发现:**
- `search_documents` - 跨所有文档的语义搜索,带有可选筛选器:
- `topic` - 按主题/类别筛选
- `phrase_search` - 精确短语匹配
- `date_from` / `date_to` - 按最后修改时间戳(Unix)筛选
- `regex_pattern` - 按文本中的正则表达式模式筛选
- `list_documents` - 列出所有可用文档(带有可选主题筛选)
- `list_topics` - 列出所有主题/类别
- `get_collection_stats` - 获取集合统计信息(文件类型、大小、计数)
**文档管理:**
- `scan_all_my_documents` - 手动触发完整文档扫描和重新索引
- `start_watching_folder` - 启动自动文件夹监控和增量更新
- `stop_watching_folder` - 停止文件夹监视器
- `get_time_of_last_folder_scan` - 检查上次扫描的时间和状态
### Claude示例查询
配置完成后,您可以询问Claude:
**一般查询:**
- "您有权访问哪些文档?"
- "有哪些主题可用?"
- "搜索有关神经网络的信息"
- "显示我集合统计信息"
**特定主题查询:**
- "在Python编程主题中搜索Python编程概念"
- "显示所有关于机器学习的文档"
- "在数据科学主题中找到有关数据可视化的信息"
**复杂查询:**
- "比较不同文档关于深度学习的内容"
- "在所有文档中找到所有提及pandas的内容"
- "机器学习文档中的关键概念是什么?"
**高级搜索(带有筛选器):**
- "搜索'神经网络'作为精确短语" - 短语搜索
- "查找2024-01-01之后修改的关于Python的文档" - 日期筛选
- "搜索匹配模式\d{3}-\d{4}" - 正则表达式模式搜索
**文档管理:**
- "扫描我所有的文档" - 触发完整重新索引
- "启动监控我的文档文件夹" - 启用自动更新
- "上次扫描是什么时候?" - 检查文件夹监控状态
- "停止监控文件夹" - 禁用自动更新
## 配置
编辑[app/config.py](app/config.py)以自定义:
**文档处理:**
- `SUPPORTED_EXTENSIONS` - 要处理的 文件类型(默认:`.pdf`, `.docx`, `.doc`, `.md`, `.xlsx`, `.xls`, `.xlsam`, `.xlsb`, `.pptx`, `.html`, `.htm`, `.txt`, `.csv`)
- `CHUNKING_STRATEGY` - 分块策略:`fixed_size`,`by_paragraph`,`semantic_heading`或`by_token`(默认:`by_paragraph`)
- `CHUNK_SIZE` - 每个块的字符数(或如果`CHUNK_BY_TOKEN=true`则为令牌数)(默认:`1000`)
- `CHUNK_OVERLAP` - 块之间的重叠(默认:`200`)
- `CHUNK_BY_TOKEN` - 使用基于令牌的分块代替基于字符的分块(环境变量,默认:`False`)
- `TOKENIZER_MODEL` - 用于令牌分块的TikToken分词器(默认:`cl100k_base`)
- `PRESERVE_HEADINGS` - 在块中保留标题结构(环境变量,默认:`True`)
- `MAX_HEADING_CHUNK_SIZE` - 基于标题的最大块字符数(默认:`2000`)
**搜索配置:**
- `DEFAULT_SEARCH_RESULTS` - 默认结果数(默认:`10`)
- `MAX_SEARCH_RESULTS` - 允许的最大结果数(默认:`20`)
- `USE_RERANKER` - 启用重新排序模型以提高结果质量(环境变量,默认:`True`)
- `RERANKER_MODEL` - 重新排序模型名称(默认:`cross-encoder/ms-marco-MiniLM-L-6-v2`)
- `RERANKER_TOP_N` - 要重新排序的结果数(默认:`50`)
- `USE_BM25` - 启用混合搜索与BM25(环境变量,默认:`False`)
**嵌入模型:**
- `EMBEDDING_MODEL` - 句子转换器模型(默认:`all-MiniLM-L6-v2`)
- `EMBEDDING_DIMENSION` - 向量维度(默认:`384`)
**主题配置:**
- `USE_FOLDER_AS_TOPIC` - 使用文件夹层次结构作为主题(默认:`True`)
- `DEFAULT_TOPIC` - 未分类文档的默认主题(默认:`uncategorized`)
- `TOPIC_SEPARATOR` - 分层主题的显示分隔符(默认:` > `)
**存储:**
- `CHROMADB_DIR` - 向量数据库位置(默认:`cache/chromadb`)
- `DOC_CACHE_DIR` - 文档缓存位置(默认:`cache/doc_cache`)
- `DOCS_DIR` - 文档目录(默认:`my-docs`,可通过`DOCS_DIR`环境变量配置)
- `CHROMA_COLLECTION_NAME` - 集合名称(默认:`my-documents`)
**启动行为:**
- `FULL_SCAN_ON_BOOT` - 在服务器启动时扫描文档(环境变量,默认:`False`)
- `FOLDER_WATCHER_ACTIVE_ON_BOOT` - 在启动时启动文件夹监视器(环境变量,默认:`True`)
**服务器传输:**
- `MCP_HOST` - HTTP服务器主机(环境变量,默认:`0.0.0.0`)
- `MCP_PORT` - HTTP服务器端口(环境变量,默认:`38777`)
## 许可证
MIT