智能文档问答服务

Searchless-ngx是一个基于Agentic RAG和MCP协议的智能文档问答服务,可将Paperless-ngx文档库转变为支持语义搜索和自然语言问答的知识库。

  • by hensing
  • Python
  • 本地部署
  • 4 星标
  • 更新于
在 GitHub 查看 hensing/searchless-ngx

使用说明

🪄 无搜索ngx

停止搜索您的文档。开始问他们。 无纸化ngx的代理RAG MCP服务器。

少搜索。更多发现。 无搜索ngx将您的无纸ngx实例从基于关键字的静态存档转换为智能的会话代理。通过利用模型上下文协议(MCP)和代理RAG,它允许现代LLM原生地理解、搜索、过滤和推理您的文档。

🤔 关于名字

如果 无纸化 把你从纸质纸的负担中解放出来, 无搜索 将您从手动搜索的负担中解放出来。

  • 无服务器 意味着你不管理服务器。
  • 无密码 意味着你不输入密码。
  • 无搜索 意味着您不再点击过滤器或浏览20页的PDF。你只要问你的助手一个问题,它就会帮你完成繁重的工作。这 -ngx 向使这一切成为可能的不可思议的Paperless ngx项目致敬。

(注:在引擎盖下,技术服务被命名为 paperless-mcp-server 为AI提供最佳的上下文基础)。

[!重要] 此项目假设您的文档已正确解析(OCR),并在Paperless ngx中分配了高质量的标签。无搜索ngx是一个检索和推理层,而不是一个组织工具。如果您的库需要更好的元数据或自动标记,请查看 无纸化GPT.

✨ 主要特点

  • RAG代理:为您的法学硕士配备查询、筛选和汇总个人文档的工具。
  • 混合搜索策略:
    • 精确元数据API:利用Paperless ngx强大的过滤功能(标签、通讯员、日期)进行精确检索。
    • 语义向量搜索:使用ChromaDB和Mistral嵌入(Google Gemini可选)基于以下内容查找文档 意义 和 上下文 (例如,“软件订阅”、“食品收据”)。
  • 针对开放式WebUI进行了优化:
    • 严格的JSON模式:零 anyOf 或 null 确保与实验性MCP解析器100%兼容。
    • 交互式卡片:搜索结果以漂亮的Markdown卡片形式呈现,带有可点击的标题和元数据。
  • 只读:零破坏性行动。它使用现有的OCR文本,从不下载二进制PDF。
  • 智能同步:启动同步使用水印在几秒钟内仅从Paperless获取新的/更改的文档。定期后台同步(默认值:每15分钟一次,可配置)使索引保持最新。Webhook支持实时摄取单个文档。通过手动完全同步 POST /sync/all.
  • 搜索弹性:主动回退策略可确保LLM即使在初始过滤器限制过大的情况下也能找到文档。

🏗️ 建筑

graph TD
    User([User]) -->|Chat| OWUI(Open WebUI)
    OWUI -->|MCP Streamable HTTP| MCP(FastAPI MCP Server)
    MCP -->|Mistral / Gemini Embeddings| Chroma[(ChromaDB)]
    MCP -->|"Read-Only API (metadata, content, sync)"| Paperless(Paperless-ngx)
    MCP -->|Paginated Cache| Cache[(In-Memory Metadata)]

    External([Paperless Workflow / External]) -->|POST /webhook/sync| MCP
    Timer([Periodic Sync\nevery 15 min]) -->|bulk_sync_documents| MCP

🚀 设置和安装

1.先决条件

  • Docker&Docker编写
  • 无纸化ngx实例
  • Mistral API密钥(默认提供程序) 或 一个Google Gemini API密钥(备选)

2.环境配置

复制 .env.example 到 .env 并配置:

cp .env.example .env
变量 描述
PAPERLESS_URL 您的无纸ngx基本URL
PAPERLESS_TOKEN 来自无纸设置的API令牌。
LLM_PROVIDER 雨伞供应商: mistral (默认), google, openai 或 ollama.
EMBEDDING_PROVIDER / CHAT_PROVIDER (可选)覆盖任一轴以获得最佳品种。每一个回落到 LLM_PROVIDER.
MISTRAL_API_KEY / GEMINI_API_KEY / OPENAI_API_KEY API密钥-只有实际使用的云提供商才需要(ollama 不需要)。
OLLAMA_BASE_URL / OPENAI_BASE_URL (可选)OpenAI兼容端点。Ollama默认为 http://localhost:11434/v1.
EMBEDDING_MODEL / CHAT_MODEL (可选)覆盖每个轴的默认模型。
PAPERLESS_PUBLIC_URL (可选)聊天中用于可点击链接的URL。默认为 PAPERLESS_URL.
LOG_LEVEL (可选)日志详细程度: INFO (默认)或 DEBUG.
MAX_CHUNKS_PER_DOC (可选)限制每个文档的段数(默认值:100≈25页)。
BULK_SYNC_LIMIT (可选)将初始摄入限制在X个最新文档。
SYNC_INTERVAL_MINUTES (可选)周期性后台同步间隔(分钟)(默认值:15)。设置为 0 禁用。

提供商选择(Mistral/Google/OpenAI/Ollama)

LLM_PROVIDER 伞是默认设置吗(米斯特拉尔: mistral-embed 嵌入件+ mistral-small-latest 用于模糊匹配)。设置为 google, openai 或 ollama 切换。 openai 和 ollama 共享一个OpenAI兼容客户端,因此任何OpenAI兼容端点 (vLLM、TEI、LM Studio等)通过指向来工作 OPENAI_BASE_URL / OLLAMA_BASE_URL 在它。

最佳品种: 嵌入轴和聊天轴可以通过以下方式独立拆分 EMBEDDING_PROVIDER 和 CHAT_PROVIDER (每个都回落到 LLM_PROVIDER).谷歌的 gemini-embedding-001 领导多语言检索基准测试,因此一个常见的组合是 谷歌嵌入+米斯特拉尔(欧盟)聊天:

EMBEDDING_PROVIDER=google   # stronger retrieval
CHAT_PROVIDER=mistral       # EU-hosted chat
# both MISTRAL_API_KEY and GEMINI_API_KEY required

⚠️ 切换嵌入提供程序需要重建向量数据库。 嵌入来自 不同的模型存在于不同的向量空间中(维度:Mistral=1024,Gemini= 3072),因此现有索引不可用。擦干净 chroma_data 音量和让启动 同步重新嵌入所有内容:

docker compose down
docker volume rm $(docker compose config --volumes | grep chroma)
docker compose up -d

完全本地和私人:Qwen3嵌入+奥利玛的Mistral Small 24B

在您自己的机器上运行所有内容(例如,具有≥32 GB RAM的MacBook Pro M4)。安装 奥拉玛 天生地 在主机上——macOS上的Docker没有GPU访问权限,因此 集装箱应通过以下方式呼叫主机的Ollama host.docker.internal.

# 1. On the host: install Ollama (macOS)
brew install ollama

# 2. Pull the models (pin explicit tags — see table below) and expose Ollama to containers
ollama pull qwen3-embedding:0.6b
ollama pull mistral-small:24b
OLLAMA_HOST=0.0.0.0 ollama serve        # bind so Docker can reach it

# 3. In .env
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://host.docker.internal:11434/v1
EMBEDDING_MODEL=qwen3-embedding:0.6b
CHAT_MODEL=mistral-small:24b

嵌入模型选项 (总是别上标签——裸 qwen3-embedding / :latest =8B):

标签 下载 尺寸 何时使用
qwen3-embedding:0.6b 约0.6 GB 1024 推荐 --快速、精简,非常适合个人档案
qwen3-embedding:4b ~2.5 GB 2560 如果你想要,可以有更多的空间
qwen3-embedding:8b ~4.7 GB 4096 最高质量;更大的索引+更慢的同步,对大多数人来说过于夸张

不需要API密钥 ollama。嵌入物100%保留在设备上——没有任何东西会离开你 机器。(你也可以混合,例如。 EMBEDDING_PROVIDER=ollama 用于私有本地嵌入,同时 保持 CHAT_PROVIDER=mistral 用于云聊天。)

💡 嵌入维度被烘焙到ChromaDB集合中。切换标签(例如。 :0.6b → :8b)更改维度并需要重建向量数据库。

模型加载和内存: Ollama在首次使用时自动将模型加载到内存中 卸载后 5分钟空闲 (OLLAMA_KEEP_ALIVE,默认值 5m)释放RAM。自 周期性同步每15分钟运行一次,嵌入模型在运行之间卸载并重新加载 每次同步 qwen3-embedding:0.6b 重新加载可以忽略不计(不到一秒钟),因此 默认 5m 非常适合,无需更改如果你宁愿让它永远保持温暖, 集 OLLAMA_KEEP_ALIVE=-1 在主机上(0.6B型号的成本约为0.6GB RAM)。

3.Docker编写

启动代理并打开WebUI:

docker compose up -d

4.连接到Open WebUI

  1. 打开 http://localhost:8080.
  2. 首选 设置>连接>MCP服务器.
  3. 首选方法:单击导入按钮并选择 scripts/webui-connection.json.
  4. 手动方法:添加类型为的新服务器 MCP Streamable HTTP 和URL http://mcp-server:8001/mcp.

有关Open WebUI的详细说明,请参阅 WEBUI_SETUP.md.

💡 使用示例

列出文档

  • “列出亚马逊的最后5个文档。” (使用精确的元数据搜索)
  • “显示我最近的发票。” (使用空查询按日期提取)

概念搜索(语义)

  • “查找我拥有的所有软件订阅。” (即使标题中没有“订阅”,也会找到“Netflix”、“Adobe”、“Microsoft”)
  • “我上次去柏林的食物收据在哪里?” (将位置上下文与文档含义相结合)

数据提取

  • “2024年2月,我在出行方面花了多少钱?” (LLM迭代搜索/火车发票并计算总和)
  • “总结一下我的健身房合同的取消条款。” (LLM使用 get_document_details 阅读完整的OCR文本)

🛠️ 开发与测试

诊断工具

使用原始协议检查器验证服务器的输出:

docker exec paperless-mcp-server python scripts/test_mcp_raw.py

测试覆盖率

使用以下命令运行测试套件 uv:

uv run pytest

👤 作者

由开发和维护 Henning Dickten博士 (@伊辛).

⚖️ 许可证

根据GPLv3许可。