# md-analyzer **Repository Path**: xuting/md-analyzer ## Basic Information - **Project Name**: md-analyzer - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-22 - **Last Updated**: 2026-05-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MD Analyzer - 投标文件智能比对平台 ## 项目简介 一个用于分析投标文件和公司关联关系的 Web 应用平台,提供四大核心功能: - **投标文件智能比对** — PDF/DOC/DOCX 文本相似度检测、内容差异分析、PDF 溯源 - **投标文件全景比对** — 自动识别投标人 + 工商实体信息跨文件比对 - **公司关联关系比较** — 天眼查/启信宝 API 查询公司工商信息并交叉比对 - **企业多层关联穿透** — 多层投资/任职/分支等关联关系可视化分析 ### 品牌 Logo 应用使用自定义 SVG Logo(盾形 + 松枝 + AI 芯片),体现"东煊 AI 慧眼"品牌形象: - **盾形外框** — 象征安全可信,契合招标分析场景 - **三层松枝** — 呼应"东煊"品牌名称(松 = 松树) - **AI 芯片** — 底部芯片 + 电路纹路,体现 AI 技术属性 Logo 应用于登录页、首页顶栏、MDAnalyzerPage、CompanyRelationPage,统一使用 cyan→blue 渐变背景容器。 ### 用户认证 - **登录保护** — 所有功能页面需要登录后才能访问,未登录自动跳转登录页 - **JWT Token 认证** — 基于 JWT 的无状态认证,token 默认 30 分钟过期 - **密码安全** — 密码使用 bcrypt 哈希存储 - **自动退出** — token 过期或无效时自动跳转登录页,axios 拦截器全局处理 401 ### 用户配置系统 每个用户拥有独立的系统配置,登录后自动加载,切换即自动保存,全局生效。配置通过模态框呈现,可在首页底部"系统设置"按钮或各功能页面顶栏齿轮图标打开。 **功能显示配置:** - **投标文件智能比对/全景比对 — 企业内部API** — 控制两个投标分析页面"企业内部API(可选)"区域的显隐,默认显示 - **公司关联关系比较 — 企业内部API** — 控制该页面"企业内部API(可选)"区域的显隐,默认显示 **分析默认配置:** - **缓存策略** — 使用/不使用本地 MinerU 解析缓存,默认使用缓存 - **MinerU 数据源** — 本地 MinerU / 官网 API,默认本地 - **排除相似度阈值** — 滑块调节 50%–100%,默认 85% - **AI 智能解读分析结果** — 开关控制,默认关闭。开启后普通分析自动附加 AI 总结(发送 `both` 模式),关闭则仅普通分析(发送 `code` 模式) 后端 API:`GET /api/user/settings`、`PUT /api/user/settings`,数据持久化到 `backend/data/user_settings.json`。 ### 白名单库 用于过滤分析中不需要的项目——既包括从 PDF 提取的不准确实体,也包括连续相同字符(LCS)中常见的模板套话。用户可将这些内容加入白名单,后续比对时自动过滤。 **工作流程:** 1. 在比对结果页面的矩阵表格中,hover 任意单元格 → 点击琥珀色"加入白名单"按钮 2. 右上角 toast 提示"已将 xxx 加入白名单" 3. 该内容被记录到用户白名单中,下次分析时自动过滤 4. 可在菜单 → 白名单库 中查看、搜索、删除已屏蔽的内容 **支持的类型:** 邮箱、电话、地址、人名、机构、身份证、统一信用代码、连续相同字符 **过滤机制:** - **实体类型**:在 PDF 实体提取后、构建比对矩阵前,对 PDF 原文和公司 API 来源的实体统一过滤 - **连续相同字符**:在 LCS 匹配循环中优先过滤,匹配文本包含任一白名单子串即跳过 **后端 API:** - `GET /api/whitelist?entity_type=&search=` — 查询白名单(支持类型筛选和模糊搜索) - `POST /api/whitelist` — 添加白名单条目(`{ entity_type, value }`),已存在则忽略 - `DELETE /api/whitelist/{item_id}` — 删除白名单条目 数据持久化到 `backend/data/whitelist_{username}.json`,每个用户独立存储。 ## 功能特性 功能中心提供三个入口,用户可按需选择: ### 投标文件智能比对(`?mode=file`)— 纯文件内容比对 - 文本相似度检测、内容差异分析、PDF 溯源 - 不自动识别投标人,不进行公司实体比对 - 适合仅需对比文件内容差异的场景 ### 投标文件全景比对(`?mode=bidder`)— 文件 + 投标人综合分析 - 上传后自动从文件名和 PDF 内容提取投标人名称 - 通知横幅汇总"系统已自动识别 X 位投标人",青色 AI 识别标签,点击可修改 - 查询投标人工商信息(法人、股东、地址、电话等)作为跨文件比对维度 - 适合需要全面分析投标人和文件内容的场景 两个模式共用同一组件和后端 API,后台逻辑不变。 ### 通用文件分析能力 以下能力两个模式共享: - **多格式文件上传** — 支持 PDF、DOC、DOCX 格式文件上传 - **DOC/DOCX 自动转 PDF** — 上传 DOC/DOCX 文件后在分析时自动转换为 PDF(优先 LibreOffice headless,回退 Microsoft Word COM),转换结果按文件内容 SHA-256 哈希缓存,同文件不重复转换 - **多文件并发上传** — 支持同时上传多个文件,自动从文件名提取公司名 - **排除文件** — 可指定排除文件,排除文件中的内容不会报告为异常 - **排除相似度阈值** — 滑块调节(50%–100%,默认 95%),控制排除过滤敏感度 - **PDF 元数据比较** — 对比 PDF 作者、制作程序、创建日期等元数据是否一致 - **文本相似度检测(LCS)** - 连续相同字符检测(≥13 字符) - teal 色高亮所有匹配出现,与浏览器搜索黄色区分 - LCS 来源筛选(全部 / 来自段落 / 来自表格) - SimilarityModal 详情弹窗同步高亮 - **实体重复检测** — 邮箱、电话、地址、人名、组织名 - **电话号码标准化** — 去除格式差异(空格、分隔符、国家码)后精确比对 - **排除文件智能过滤** — 子串匹配 + 中文实体渐进缩短 + LCS 字符集相似度过滤 - **投标人公司名称提取** — 自动从文件名提取,支持手动编辑 - **公司数据优先标记** — 工商数据来源实体以绿色标记优先展示 - **PDF 原文溯源** — 点击定位到 PDF 原文页面并高亮匹配位置 - **MinerU JSON 下载** — 每个文件可下载 MinerU 原始解析 JSON - **矩阵表格可视化** — 直观展示各文件匹配关系,区分 PDF 来源和公司数据来源 - **PDF 导出** — 分析结果导出为 PDF 文件 ### 公司关联关系比较 - 输入多家公司名称进行关联分析 - 通过天眼查/启信宝 API 查询公司工商信息 - 支持企业内部 API — 项目编号和包号查询相关公司数据 - 比较法人、股东、联系电话、注册地址重叠关系 - API 调用日志查看 - 矩阵表格可视化展示重叠结果 ### 企业多层关联穿透 - 输入多家公司名称,穿透查询企业间多层投资/任职/分支等关联关系 - 支持自定义关系类型(股东、法人、高管、历史股东/法人/高管、分支机构、供应商等) - 穿透层级 1–15 层可调,默认 6 层 - 持股比例阈值 0%–100% 可调,默认 33%,**路径中任一段持股达标即保留整条路径** - 结果提供两种视图:**路径列表**(展示每层节点 + 持股比例 + 投资金额)+ **关系图**(vis-network 力导向图,边标签显示中文关系名和持股比例) - 所有关系类型和节点类型均以中文显示(SH→股东、LR→法人、E→企业、P→个人 等) - API 返回的持股比例为比值(1=100%),后端自动转换为百分比后输出 - 支持导出 PDF / Excel / 图片 ### 邮箱报告发送 - 配置 SMTP 邮箱信息,发送分析结果 ### 白名单管理 1. 在比对结果单元格 hover → 点击琥珀色按钮 → 将误识别实体或常见模板文字加入白名单 2. 菜单 → 白名单库 → 查看所有已屏蔽内容 3. 支持按类型筛选(邮箱/电话/地址/人名/机构/身份证/信用代码/连续相同字符) 4. 支持模糊搜索 5. 点击删除可移除白名单条目,恢复该内容的检测 ### 任务历史记录 - 保存历史分析任务,支持查看详情和删除 ## 分析方法说明 ### 文本相似度检测(LCS) 使用最长公共子串(Longest Common Substring)算法,动态规划复杂度 O(m×n)。 - **段落提取**:从 MinerU content_list 提取 text(段落)和 table(表格),支持提取完整表格行 - **两两比对**:所有文件两两配对,比较所有段落组合,找到 ≥13 字符的公共子串 - **块边界收集**:仅在公共块末尾收集匹配,避免嵌套子串产生冗余行 - **两阶段去重**: 1. 空格归一化后相同的结果只保留最长的,合并文件列表、页码、位置、来源 2. 子串过滤:较短匹配被较长匹配包含时合并,**保留所有文件列表** - **Per-file 匹配**:每个文件单元格独立计算实际存在于其源文本中的最长匹配子串,确保高亮在每个单元格都正确 - **高亮显示**:前端 `text.split(match)` 高亮全部出现次数,teal 色区分浏览器搜索 ### LaTeX 公式归一化 投标文件中常见的 LaTeX 数学公式自动转换为统一中文符号: | LaTeX 形式 | 转换后 | |------------|--------| | `$\geqslant$` / `\geqslant` | `≥` | | `$\leqslant$` / `\leqslant` | `≤` | | `\times` | `×` | | `\div` | `÷` | | `\pm` | `±` | | `\alpha` / `\beta` / `\gamma` / `\delta` | `α` / `β` / `γ` / `δ` | ### 实体检测 | 类型 | 方法 | 说明 | |------|------|------| | 邮箱 | 正则匹配 | `[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}` | | 电话 | 正则匹配 + 标准化比对 | 支持手机号、固话、国家码,去除格式差异后精确比较 | | 地址 | 正则 + 中文地址关键词 | 识别省市区街道等标记词 | | 人名/组织名 | 中文 NER 模型 | 提取 PERSON 和 ORG 实体 | ### 排除文件过滤机制 三种过滤方式协同工作: 1. **子串匹配**:实体文本在排除文件中出现则过滤 2. **中文渐进缩短**:从末尾缩短中文实体(最少2字符),检查变体 3. **LCS 字符集相似度**:Jaccard 相似度 ≥ 阈值的 LCS 匹配被过滤,阈值可滑块调节 ### PDF 元数据比较 提取 PDF 文件的元数据进行一致性比对:作者(Author)、制作程序(Producer)、创建程序(Creator)、创建日期、修改日期、文件大小。完全相同项单行展示。 ### LLM 直接分析 在代码比对外,新增基于大模型(DeepSeek)直接阅读 MinerU 提取的 Markdown 原文进行比对分析的能力。前端点击"开始比对"默认使用普通分析(code),用户可在系统设置中开启"AI 智能解读分析结果"后自动附加 AI 总结(both 模式)。后端支持三种模式: - **代码比对(code)** — 使用 LCS + 正则 + NER 的传统分析方法 - **AI 智能分析(llm)** — 仅使用 LLM 直接分析(前端已隐藏入口,后端保留) - **两者都做(both)** — 并发执行,结果页通过 Tab 切换查看 **文件预处理:** 大文件会进行智能截断以适应 DeepSeek 128K token 上下文窗口(保守控制在 ~100K tokens)。截断策略为**头 40% + 中间采样 20% + 尾 40%**,单文件上限 = 250,000 / 文件总数 字符。 **调用参数:** | 参数 | 值 | |------|-----| | 模型 | `deepseek-chat` | | Temperature | `0.3` | | Max Tokens | `4000` | | 超时 | 120s | **System Prompt:** ``` 你是招投标文件分析专家,擅长通过直接阅读和分析投标文件原文来识别围标串标风险。 你能够发现不同文件间的相似段落、共享实体信息、异常模式, 并基于《招标投标法实施条例》和《政府采购法实施条例》进行风险评估。 请始终以结构化 Markdown 格式输出分析结果。 ``` **User Prompt 结构:** 1. **角色设定** — "你是一名专业的招投标文件分析专家。请仔细阅读以下文档内容,并进行全面的比对分析。" 2. **待分析文件列表** — 列出所有参与比对的文件名 3. **排除文件标记**(如有)— 标注不参与比对的参考文件 4. **文件内容** — 每个文件经智能截断后的 Markdown 原文 5. **分析要求** — 四个维度: - 文档概览:各文件的主要内容、结构、页数规模 - 相似内容发现:查找不同文件间的相同或高度相似的段落、表格、数据 - 关键实体比对:比对文件中的公司名称、人员姓名、联系方式(电话/邮箱/地址)、统一信用代码等 - 异常模式识别:识别可能的异常(相同联系信息、相同格式模板、相同错误等) 6. **输出格式** — 严格四段式 Markdown 结构: - `### 一、文档概览` → 表格(文件名 / 主要内容 / 规模评估) - `### 二、相似内容发现` → 逐条列出,含涉及文件、内容摘要、相似程度 - `### 三、关键实体比对` → 表格列出各文件实体,标注跨文件出现 - `### 四、异常模式与风险评估` → 风险等级(高/中/低)+ 理由 7. **字数限制** — 控制在 2000 字以内 提示词定义见 `backend/llm_analyzer.py` 中的 `_build_llm_prompt()` 函数。 ## 技术栈 - **后端**:Python 3.10+ / FastAPI / asyncio / httpx / pypdf / PyMuPDF / python-jose (JWT) / bcrypt - **前端**:React 18 / Vite / TailwindCSS / TypeScript / axios / jsPDF / react-router-dom / xlsx / react-pdf / vis-network / html2canvas - **PDF 解析**:MinerU(支持云服务 API 和本地部署) - **DOC/DOCX 转换**:LibreOffice headless(优先)/ Microsoft Word COM(Windows 回退) - **安全**:JWT 无状态认证、bcrypt 密码哈希、全局路由保护 ## 快速启动 ### 1. 安装后端依赖 ```bash cd backend pip install -r requirements.txt ``` **Python 依赖包:** | 包名 | 用途 | |------|------| | `fastapi` + `uvicorn` | Web 框架和 ASGI 服务器 | | `python-multipart` | 文件上传支持 | | `aiofiles` | 异步文件读写 | | `scikit-learn` + `numpy` | 文本相似度计算 | | `pydantic` | 数据模型校验 | | `chardet` | 文件编码检测 | | `httpx` | 异步 HTTP 客户端(天眼查/启信宝 API) | | `pypdf` | PDF 元数据提取 | | `PyMuPDF` (fitz) | PDF 页面渲染和文本搜索 | | `python-jose` + `cryptography` | JWT token 签发和验证 | | `bcrypt` + `passlib` | 密码哈希 | | `jieba` | 中文分词 | | `comtypes` | Windows COM 自动化(Word 回退转换) | | `pywin32` | Windows COM 线程初始化(pythoncom) | ### 2. 安装 DOC/DOCX 转换工具(可选但推荐) 如需上传 `.doc` / `.docx` 文件,需安装以下任一工具: - **LibreOffice**(推荐):下载安装 [LibreOffice](https://www.libreoffice.org/download/),默认路径 `C:\Program Files\LibreOffice\program\soffice.exe` - **Microsoft Word**(Windows 回退):如已安装 Office,系统会自动通过 Word COM 转换 未安装时仅支持 PDF 文件上传。 ### 3. 配置 API 密钥 在 `backend/config.py` 中配置天眼查/启信宝 API 密钥: ```python TIANYAN_KEY = "your-tianyancha-api-key" QIXINBAO_APPKEY = "your-qixinbao-appkey" QIXINBAO_SECRET_KEY = "your-qixinbao-secret-key" ``` ### 3. 启动后端服务 ```bash cd backend uvicorn main:app --reload --host 0.0.0.0 --port 8000 ``` ### 4. 启动前端服务 ```bash cd frontend npm install npm run dev ``` ### 5. 访问应用 打开浏览器访问 http://localhost:3000 首次使用需要登录,默认账号: - **用户名**:`admin` - **密码**:`dongsong` 登录成功后 token 有效期 30 分钟,过期后自动跳转登录页重新登录。 ## 使用说明 ### 登录认证 1. 打开应用后自动跳转登录页(深色科技风界面,粒子神经网络动态背景) 2. 输入用户名和密码,点击"登录" 3. 登录成功后进入首页(Dashboard),顶部显示当前用户信息和退出按钮 4. token 默认 30 分钟过期,过期后 axios 拦截器自动跳转登录页 5. 点击顶部"退出登录"可主动退出 6. 可通过 API 修改密码:`POST /api/auth/change-password` ### 投标文件分析 首页提供两个投标分析入口: 1. **投标文件智能比对** — 点击后进入纯文件内容比对页面(蓝色主题),支持 PDF/DOC/DOCX 文件上传比对,不涉及投标人识别 2. **投标文件全景比对** — 点击后进入全景比对页面(青色主题),支持 PDF/DOC/DOCX 文件上传,自动识别投标人并汇总展示,用户核对后可进行实体信息跨文件比对 通用操作步骤: 1. 上传待分析的文件(支持 PDF、DOC、DOCX,可多选,DOC/DOCX 自动转换为 PDF) 2. (全景比对模式)核对系统自动识别的投标人名称,点击可修改 3. 可选择性上传排除文件,滑条调节排除相似度阈值 4. 点击"开始分析"(全景比对模式显示"开始综合比对") 5. 切换 Tab 查看各类型结果: - LCS Tab 支持来源筛选(全部 / 来自段落 / 来自表格),teal 色高亮匹配文本 - 点击文档图标下载 MinerU JSON,点击 PDF 图标下载原文件 6. 点击"导出 PDF"保存结果 ### 公司关联关系比较 1. 点击"公司关联关系比较" 2. 输入 API 密钥和公司名称(至少2家) 3. 可选企业内部 API 查询(项目编号 + 包号) 4. 点击"开始分析",查看关联结果 ## API 密钥说明 公司关联关系比较功能需要使用第三方 API: - **天眼查 API**:https://www.tianyancha.com/ - **启信宝 API**:https://www.qixinbao.com/ 系统优先使用天眼查 API,失败时自动尝试启信宝。至少配置一个。 ## 项目结构 ``` md-analyzer/ ├── backend/ │ ├── main.py # FastAPI 入口(路由、认证保护) │ ├── auth.py # JWT 认证(token签发/验证、密码bcrypt哈希、用户管理) │ ├── data/ │ │ ├── users.json # 用户数据文件(JSON存储) │ │ ├── user_settings.json # 用户配置数据(JSON存储,按用户名索引) │ │ └── whitelist_{username}.json # 白名单(每用户独立文件,支持实体和LCS类型) │ ├── analyzer.py # PDF文本分析(LCS、实体提取、电话标准化) │ ├── deep_relation_api.py # 多层关联穿透 API 调用(启信宝 getTwoByName) │ ├── deep_relation_analyzer.py # 多层穿透结果组装、持股比例归一化、阈值过滤 │ ├── company_analyzer.py # 公司关联分析 │ ├── company_api.py # 天眼查/启信宝 API 调用 │ ├── storage.py # 文件存储、PDF元数据提取、MinerU缓存管理、DOC/DOCX转PDF调度 │ ├── docx_converter.py # DOC/DOCX→PDF 转换(LibreOffice优先 + Word COM回退) │ ├── mineru_api.py # MinerU 云服务 API │ ├── mineru_local.py # MinerU 本地部署 API │ ├── email_service.py # 邮箱服务 │ ├── task_history.py # 任务历史记录 │ ├── nlp_extractor.py # NLP 实体提取器 │ ├── models.py # Pydantic 数据模型(含认证模型) │ └── config.py # API密钥、SMTP、JWT配置 ├── frontend/ │ └── src/ │ ├── contexts/ │ │ └── AuthContext.tsx # 全局认证状态管理 + axios拦截器 │ ├── pages/ # 页面组件(MDAnalyzerPage、CompanyRelationPage、DeepRelationPage、HistoryPage、WhitelistPage) │ ├── components/ # 通用组件 │ │ ├── LoginPage.tsx # 登录页面(科技风粒子背景) │ │ ├── ProtectedRoute.tsx # 路由守卫(未登录拦截) │ │ ├── MatrixTable.tsx # 矩阵表格(LCS来源筛选、teal高亮) │ │ ├── PdfTraceModal.tsx # PDF 原文溯源查看器 │ │ ├── SimilarityModal.tsx # 相似文字详情弹窗(支持高亮) │ │ ├── TechBackground.tsx # 科技感动态粒子神经网络背景 │ │ ├── SettingsModal.tsx # 系统设置模态框(用户配置,紧凑布局) │ │ ├── Menu.tsx # 首页(Dashboard + 用户顶栏) │ │ ├── DeepRelation/ # 多层关联穿透组件(CompanyInput、PathListView、GraphView、ExportButton) │ │ └── FileUploader.tsx # 文件上传组件(mode感知、投标人识别、通知横幅) │ └── types/ # TypeScript 类型定义 ├── uploads/ # 上传文件目录 │ └── mineru_cache/ # MinerU 解析缓存(SHA256命名目录) └── docs/ # 项目文档 ```