Token导航 LogoToken导航TokenDH.com
Local PDF Contract Q A Privacy First MCP Gateway logo
文档知识未说明官方级别未说明来源级核验

Local PDF Contract Q A Privacy First MCP Gateway

MCP Server

一个隐私优先的单页应用,用户可上传PDF合同,应用本地提取并索引合同文本,通过MCP网关的小型LLM回答自然语言问题,并提供引用片段。

工具数

0

提示词数

0

GitHub Stars

0

资源数

0
PDF处理TypeScript文档处理

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

alexisgrantuza

提供方

alexisgrantuza

最后核验

2026/5/17 20:22

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

详细介绍

本地PDF/合同问答(隐私第一,MCP网关) 项目,这样你就可以在一天内构建一个可用的MVP。我将给出:目标、体系结构、确切的堆栈选择、带有可运行片段的分步实施计划、文件夹布局、API设计、提示模板、隐私/安全说明、测试清单和紧凑的1天时间表。

1) 项目目标(一句话)

一个隐私优先的单页应用程序,用户在本地上传PDF合同,该应用程序提取并索引合同文本(本地),MCP网关后面的一个小型LLM使用检索到的带有引用片段的相关块来回答自然语言问题。

2) 高层架构

  1. 前端(网络) --上传PDF,提问,显示答案+源代码片段。(React或Streamlit)
  2. 摄入服务(本地) --从PDF中提取文本、块、生成嵌入、存储向量索引(FAISS/Chroma)。
  3. 搜索端点(本地) --接受查询、嵌入查询、从向量数据库中检索前k个块。
  4. MCP网关呼叫(托管) --通过MCP网关将检索到的块+用户问题发送给LLM(因此LLM远程运行,但从不接收整个文档;只接收检索到的上下文),获得最终答案。
  5. 返回和显示 --前端通过代码片段引用和置信度元数据显示答案。

3) 技术栈(推荐)

  • 后端/摄取和搜索: python (快速原型化)

- PDF提取: pdfplumberPyMuPDF (fitz) - 组块和嵌入: sentence-transformers (all-MiniLM-L6-v2 或类似) - 矢量数据库: FAISS (本地)或 色度 (文件已备份) - Web服务器: 快速API 或Streamlit(Streamlit用于最快的单文件UI) - 可选: langchain 用于胶水代码(但不是必需的)

  • LLM访问: MCP/托管网关 -简单的HTTP API端点,代理您选择的模型;作为外部法学硕士提供者。
  • 前端:Streamlit(快速)或React+简单获取(如果你喜欢单独的UI)
  • 集装箱化:可选 docker-compose 在本地运行。

4) 隐私模型

  • PDF和矢量的本地存储:本地存储(如果持久,则加密),或在内存中临时存储。
  • 发送到LLM(MCP网关)的内容:仅 _检索到的块_ 与问题+问题相关(永远不是完整的文档)。
  • MCP设置:set log=false 或相当于网关调用,并将网关API密钥限制为此应用程序。
  • 编校:如果文档包含PHI,您可以在嵌入或发送上下文之前添加预检查以编辑敏感字段。

5) 可交付成果

单页应用程序,其中:

  • 用户上传合同(PDF)。
  • 应用程序显示上传的文件名、索引进度。
  • 用户输入问题→ 应用程序返回一个简短的答案+源代码片段(带页码或块id)。
  • 可选地显示“confidence”和top-k支持片段。

6) 实施计划(循序渐进)——一天友好

准备(30-45分钟)

  1. 创建项目文件夹和virtualenv。
  2. 安装软件包: pip install fastapi uvicorn sentence-transformers faiss-cpu pdfplumber requests streamlit (或 chromadb 而不是faiss)。
  3. 获取MCP网关API密钥/端点(或使用任何LLM端点)。

步骤A-PDF→ 文本(30-45分钟)

  • 提取文本 pdfplumberPyMuPDF.
  • 还要记录页码以供引用。

示例(Python)

# pdf_extract.py
import pdfplumber

def extract_pages(path):
    pages = []
    with pdfplumber.open(path) as pdf:
        for i, page in enumerate(pdf.pages, start=1):
            text = page.extract_text() or ""
            pages.append({"page": i, "text": text})
    return pages

步骤B——填塞(15-30分钟)

  • 被滑动的窗户挡住。保留chunk_id的映射→ (page_start、page_end、text)。
  • 示例:块大小为800个标记(或约1000个字符),重叠200个字符。

简易切块机

def chunk_pages(pages, chunk_size=1200, overlap=200):
    chunks = []
    for p in pages:
        text = p["text"]
        i = 0
        while i 
Body: {
  "model": "small-llm-1",
  "input": "",
  "max_tokens": 300,
  "logprobs": null,
  "user": "",
  "metadata": {"doc_id": "..."}
}

提示模板(简洁安全)

System: You are a contract assistant. Use ONLY the supplied context to answer. Provide a short answer and list which pages or snippets you used.

Context:
[1] (Page 3) "Lease term is 12 months..."
[2] (Page 5) "Late fee 2% per month..."
...

Question: 

Answer concisely with a 1-2 sentence answer. Then include "SOURCES:" with the chunk/page references used.

重要:总是指示法学硕士引用特定的块/页,如果不回答,就说“我不知道”。

步骤F——前端(流式传输)(30-45分钟)

  • 快速简化用户界面:

- 文件上传→ 触发摄入。 - 问题文本输入→ 点击后端 /query 终点。 - 显示答案,下面显示带有页码和“复制”按钮的支持片段。

流光灯最小

# app.py
import streamlit as st
import requests

uploaded = st.file_uploader("Upload contract (PDF)", type="pdf")
if uploaded:
    # save to temp, call /ingest or ingest inline
    st.write("Indexed. Ask a question:")
    q = st.text_input("Question")
    if q:
        resp = requests.post("http://localhost:8000/query", json={"question": q})
        data = resp.json()
        st.write("Answer:", data["answer"])
        for s in data["sources"]:
            st.markdown(f"**Page {s['page']}**: {s['text'][:300]}...")

步骤G——测试和抛光(30-60分钟)

  • 上传合同样本(保密协议、租赁、雇佣)并尝试提问。
  • 检查引文,确保LLM不会产生幻觉(强制“仅使用提供的上下文”)。
  • 添加用于索引的UI进度指示器。

7) 文件夹结构(建议)

pdf-qna/
├─ backend/
│  ├─ app.py            # FastAPI app: /ingest, /query endpoints
│  ├─ pdf_extract.py
│  ├─ chunker.py
│  ├─ embed_index.py
│  └─ data/             # saved indices and metadata
├─ frontend/
│  └─ app.py            # streamlit single-file UI (or react)
├─ requirements.txt
└─ docker-compose.yml

8) API设计(最低)

  • POST /ingest --多部分上传 {file: pdf} → 回报 {doc_id, status}
  • POST /query{doc_id, question} → 回报 {answer, sources:[{page, snippet, chunk_id}], used_chunks: [...]}

9) 示例流程(端到端)

  1. 用户上传 contract.pdf → 后端提取N个页面,将其分块,计算嵌入,构建FAISS索引,存储元数据→ 回报 doc_id.
  2. 用户提交问题“租约何时结束?”→ 后端嵌入查询,找到前3个块,用这些块构建提示,调用MCP网关获取答案。
  3. Gateway返回:“租期为12个月,从2025年1月1日开始,到2025年12月31日结束。”后端返回此信息以及以下来源 (page 1, chunk 2).

10) 安全和抗幻觉规则

  • 始终包含系统说明: “只使用提供的上下文;如果答案不在上下文中,请说‘我不知道’。”
  • 限制回复长度并要求明确引用。
  • 可选地验证事实声明:对LLM声明的短语的引用进行简单的精确匹配搜索。

11) 快速代码片段(可打包)

FastAPI骨架(非常短)

from fastapi import FastAPI, UploadFile, File
from pydantic import BaseModel
app = FastAPI()

@app.post("/ingest")
async def ingest(file: UploadFile = File(...)):
    # save file, extract pages, chunk, embed, index
    return {"doc_id": "doc123", "status":"indexed"}

class Q(BaseModel):
    doc_id: str
    question: str

@app.post("/query")
def query(q: Q):
    # embed question, search index, call MCP gateway, return answer + sources
    return {"answer":"...", "sources":[...]}

MCP网关呼叫(请求)

import requests, os
MCP_URL = "https://mcp-gateway.example/v1/generate"
API_KEY = os.environ.get("MCP_API_KEY")

def call_mcp(prompt):
    payload = {"model":"small-llm-1","input":prompt,"max_tokens":300}
    r = requests.post(MCP_URL, json=payload, headers={"Authorization":f"Bearer {API_KEY}"})
    return r.json()["text"]

12) 1天时间表(逐小时现实)

  • 00:00–00:30--脚手架仓库,安装deps,创建virtualenv。
  • 00:30–01:15--对样本进行PDF提取+测试。
  • 01:15–02:00——实现分块器+元数据映射。
  • 02:00–03:00——整合句子转换+构建FAISS索引;保存索引。
  • 03:00–03:30——添加搜索端点以加载索引并返回前k个块。
  • 03:30–04:00——制作简单提示模板,集成MCP网关调用。
  • 04:00–05:00--构建Streamlit UI+连接到后端端点。
  • 05:00–05:30——测试样本合约,调整区块大小和系统提示。
  • 05:30–06:00--添加小润色:引用显示、索引进度、环境变量、README。

(如果使用单文件Streamlit方法,您可以缩短时间——在进程中进行摄取,这样就可以避免单独的FastAPI连接。)

13) 测试和验证检查表

  • \[\]索引适用于多页PDF,并保留页码。
  • \[\]查询返回前k个支持代码段和页码。
  • \[\]当上下文不包含答案(或说“我不知道”)时,LLM拒绝回答。
  • \[\]没有完整的文档被发送到MCP网关,只有检索到的块。
  • \[\]通过env vars设置的API密钥,未提交。
  • \[\]如果将索引保存到磁盘、加密或带TTL的临时文件夹中。

14) 可选改进(MVP后)

  • 添加 语义搜索重新排序:调用LLM对检索到的块进行跨编码器重新排序(提高准确性)。
  • 整合 文档OCR (Tesseract)用于扫描PDF。
  • 添加 访问控制 /每用户隔离。
  • 添加 可解释性:通过页面坐标在原始PDF查看器中突出显示短语。
  • 添加 浏览器扩展 在浏览器中查看PDF时提问。

15) 快速陷阱以及如何避免它们

  • 幻觉 --通过严格的系统提示+要求引用进行修复。
  • 检索不良 --调整块大小和重叠;存储页码;考虑法律文档的句子级组块。
  • 嵌入速度慢 --每个文档的缓存嵌入;运行离线批处理。
  • 大PDF --限制MVP的文件大小(例如低于10MB)。

16) 最终清单,为您提供一个可用的仓库

如果你愿意,我会立即脚手架准备逃跑 单文件Streamlit应用程序 或者一个小型的FastAPI+Streamlit仓库:

  • 摄取PDF,
  • 在本地构建FAISS索引 sentence-transformers,
  • 运行查询并调用可配置的MCP网关,
  • 显示带有来源的答案。

你现在更喜欢哪一个-- 流式传输单个文件 (最快)或 FastAPI后端+React前端 (更多生产)?我将立即生成启动器回购代码。

目录标签

目录标签

PDF处理TypeScript文档处理本地部署合同分析隐私优先本地索引MCP网关

接入字段

传输方式(transport,传输协议)

未说明

鉴权方式(authType,认证方式)

token

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

未说明token部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

仍需确认:installCommand

来源信息

继续浏览同类 MCP