# Gmp Compliance Check

> 药品行业 GMP（生产质量管理规范）合规自检工具。基于通用 GMP 合规基线（中国 GMP / FDA 21 CFR Part 11 / EU GMP Annex 11 / WHO TRS 996 / ALCOA+ / CSV），对药企的质量管理文档、信息化方案做关键词+规则化自检，输出合规覆盖度报告与整改建议；含零依赖 HTML 体检报告生成器与 Web 自助提交页（留资+自动发邮件+推线索+存线索 CSV）。当用户需要审查药企 GMP 合规资料、做 GMP 合规体检、把 GMP 合规审查封装成可售卖/获客的 AI 功能，或在医药行业打单/方案侧用 GMP 合规作为差异化切入点、把报告整改建议转化为可售卖的服务清单/打单弹药、开箱即用（对话式/点击式/命令行三入口）时使用。

- Skill: `cslawyer1985/gmp-compliance-check` (Agent Skill, multi-file: 11 files)
- Install (CLI): `npx skillmds@latest add cslawyer1985/gmp-compliance-check`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cslawyer1985/gmp-compliance-check/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: cslawyer1985 (https://skillmd.com/u/cslawyer1985)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cslawyer1985/gmp-compliance-check

---


# 药品行业 GMP 合规自检

## Overview

为药企 / 医药行业方案商 / GMP 咨询机构提供一套**零依赖**的 GMP 合规自检能力：基于通用 GMP 合规基线（中国 GMP / FDA 21 CFR Part 11 / EU GMP Annex 11 / WHO 数据完整性 / ALCOA+ / CSV），对药企的**质量管理文档或信息化方案**做关键词+规则化扫描，自动产出合规覆盖度报告、风险等级与整改建议；既可作为日常方案合规自查工具，也可作为**对外获客钩子**（自助提交页→自动出报告→留资→发报告→推线索）。

## When to use

- 审查一份药企的 GMP 质量管理 / 信息化方案是否覆盖关键合规点
- 评估 ERP / MES / LIMS / WMS 系统的 GMP 合规覆盖度（ALCOA+、审计追踪、电子签名、CSV 等）
- 排查某个 GMP 条款（如数据完整性 / 偏差与 CAPA / 批次追溯）在方案中的覆盖情况
- 把 GMP 合规审查封装成可对客户交付的"AI 合规体检"服务
- 医药行业打单 / 方案侧：用 GMP 自检报告作为客户教育与方案价值具象化工具
- 围绕 GMP 合规做"获客钩子"（客户上传资料→自动出报告→留邮箱→跟进）

## 内置 demo 数据（开箱即用）

本 skill 自带一套可运行的示例数据，无需自备资料即可体验完整流程：

- 路径：`sample_data/demo_client/`
  - `gmp_requirements.md`：示例 GMP 合规基线（10 个域、20 个检查项，覆盖 ALCOA+、CSV、审计追踪、电子签名/权限、批次追溯、变更控制、偏差/CAPA、备份容灾、时间同步、培训/资质）
- 路径：`sample_data/demo_docs/`
  - `sample_plan.txt`：示例某药企信息化方案（中等覆盖度，可直接试跑出"高风险缺失"报告）

直接运行即可看到效果：

```bash
python scripts/review.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --name "示例药企"
```

预期会跑出"整体风险=高（数据完整性域缺失）" + 各域覆盖度明细 + 整改建议。

## Core workflow

1. **准备基线目录**：在 `<客户目录>/` 放一份 `gmp_requirements.md`，按脚本约定的格式（`## 域 weight=N` + `- 检查项：xxx risk=高` + `keywords:...` + `advice:...`）。内置 demo 可直接用。
2. **选择审查方式**：
   - `review.py`：命令行交互 / 集成，结构化输出（文本 / JSON）
   - `generate_report.py`：批量生成可发客户的 HTML 合规体检报告（带打印/PDF 按钮）
   - `webapp.py`：零依赖 Web 服务，给客户自助提交，做获客
3. **解读报告**：报告含综合覆盖度（0-100）、整体风险等级（高/中/低）、各域覆盖度、缺失/部分覆盖项的整改建议。
4. **（可选）启用大模型语义评估**：传 `--config config.json`（含 OpenAI 兼容 `api_key`），对"缺失/部分覆盖"项做语义确认。
5. **（可选）AI 解读**：把基线 + 报告交给本 skill 加载的 `references/gmp_kb.md`（GMP 知识库），让 AI 给出"为什么缺失 / 怎么补 / 对应信息化能力"的解读与方案建议。

## 三种使用方式（速览）

本能力不只有"敲命令"一种用法。普通人也有两条零命令行的路，按角色选：

| 方式 | 谁用 | 怎么用 | 要懂命令行？ |
|------|------|--------|--------------|
| ① 对话式（推荐非技术用户） | 任何人直接对 WorkBuddy 说话 | 中文说「帮我用 GMP 自检这份方案」或「给这客户资料做份 GMP 合规体检」，AI 自动调用本能力出报告 | **不需要** |
| ② 点击式（Web 自助页） | 客户自助 / 业务员演示 | 把 SKILL.md 里的 `.bat`/`.sh` 启动器代码保存到桌面，双击运行，自动开浏览器填表即可 | **不需要**（部署人双击一次） |
| ③ 命令行（脚本） | 开发者 / 集成 / 批量 | 直接跑 `review.py` / `generate_report.py` / `webapp.py`，见下方 Quick start | 需要 |

> 普通人首选 **① 对话式**：把文件丢给 WorkBuddy 或说一句需求，找脚本、拼参数、读报告都由 AI 完成。
> 对外获客用 **②**：双击启动器、把网址发给客户，客户自己填、自己看报告、自动留资——全程不碰命令行。
> 嵌入自己系统或批量跑用 **③**。完整机制见下方「触发方式（4.6）」。

## Quick start（脚本）

`scripts/review.py` 零依赖、纯标准库：

```bash
# 基本自检（返回文本报告）
python scripts/review.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --name "示例药企"

# 输出 JSON（便于集成到系统）
python scripts/review.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --json

# 启用大模型语义评估（对"缺失/部分覆盖"项做语义确认）
python scripts/review.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --config config.json

# 直接粘贴待检文本（不依赖文件）
python scripts/review.py \
  --client sample_data/demo_client \
  --copy "$(cat sample_data/demo_docs/sample_plan.txt)"
```

`config.json`（可选）：

```json
{
  "api_key": "sk-xxx",
  "api_base": "https://api.openai.com/v1",
  "model": "gpt-4o-mini"
}
```

脚本对大模型错误会按 401/403/404/429/网络异常给出明确人话提示。

## 风险等级判定

- **高**：存在 `risk=高` 的检查项处于"缺失"——任一缺失即整体=高
- **中**：无高风险缺失，但存在中风险缺失或任意项部分覆盖
- **低 / 通过**：所有检查项都覆盖

## 给客户的卖点话术（打单/方案侧）

> 很多药企方案"上线"了但没"合规"——审计追踪默认关、共享账号、CSV 报告缺失、CAPA 没闭环、备份没演练。我们交付的不只是系统，还有一道 **GMP 合规体检闸**——上线前自动比对 ALCOA+ / 21 CFR Part 11 / EU Annex 11 / 中国 GMP 的关键条款，把高风险合规缺陷挡在发布之前。

> 把自检报告中的整改建议直接转化为我们的实施服务清单与产品配置——**客户的自检清单，就是我们的交付清单**。（怎么把报告缺口一步步接成打单弹药，见「创造力与增值（4.7）」）

## 合规体检报告生成器（获客钩子）

`scripts/generate_report.py` 可批量扫描客户方案目录，生成**可发给客户的 HTML 合规体检报告**——含综合覆盖度大数字、整体风险徽章、各域覆盖度条形、待整改项明细表、整改建议，并带「打印 / 另存为 PDF」按钮，零依赖、可在任意机器生成。

```bash
python scripts/generate_report.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --name "示例药企" \
  --out report.html
```

- `--client`：基线目录（含 gmp_requirements.md）
- `--docs`：待检文档/目录
- `--name`：报告抬头客户名
- `--out`：输出 HTML（浏览器打开后可打印为 PDF）

把 `report.html` 发给客户/老板，就是天然的"我们看得到风险、我们能解决"对话起点。

## 在线自助提交页（完全自助获客）

`scripts/webapp.py` 是一个零依赖的 Web 服务：把 skill 部署到一台机器（或内网/云主机），把网址发给客户，客户自己打开网页、**填公司名+邮箱**、上传方案资料或粘贴文本，**自动生成 GMP 合规体检报告、把报告发到客户邮箱、把线索写入本地 CSV**——全程无需人工介入，是成本趋近于零的获客钩子。

```bash
# 启动在线提交页（默认 8000 端口）
python scripts/webapp.py --port 8000
# 浏览器打开 http://127.0.0.1:8000
```

> **不想敲命令？** 把 `SKILL.md` 里「触发方式（4.6.2）」的 `.bat`/`.sh` 启动器代码复制保存到桌面，双击即可自动找 Python、起服务并打开浏览器——适合部署人给客户演示或常驻。Skill 包内不能含 `.bat`/`.sh` 文件，因此启动器以代码片段形式放在文档里。

- 客户填邮箱后，报告自动发到该邮箱（HTML 邮件）
- 每次留有效邮箱的提交会把「时间 / 公司 / 邮箱 / 扫描字数 / 缺失项 / 高风险 / 来源」追加写入 `leads/leads.csv`，供销售跟进
- 默认使用内置通用 GMP 基线（`sample_data/demo_client`）做审查；报告含"打印 / 另存为 PDF"按钮
- 复用 `review.py` + `generate_report.py` 的逻辑，零第三方依赖
- 邮箱做了格式校验与**头部注入防护**；邮件发送用标准库 smtplib，未配置 SMTP 时优雅降级
- 部署建议：放一台常驻小服务器，把链接放进官网"免费 GMP 体检"入口或销售邮件

> 注意：`webapp.py` 固定使用内置通用基线（`sample_data/demo_client`）做审查，**不含大模型改写**。它定位是"免费通用体检 / 获客钩子"。真正的客户专属基线审查请用 `review.py --client <客户目录>`。

## 留资与自动发邮件（获客闭环）

在线提交页在生成报告的同时完成「留资 → 发信 → 存线索」三步。

**开启自动发邮件（可选）**：在 skill 根目录放一份 `mail.json`（参考 `mail.example.json`）：

```json
{
  "smtp_host": "smtp.example.com",
  "smtp_port": 465,
  "smtp_user": "noreply@yourcompany.com",
  "smtp_pass": "YOUR_SMTP_PASSWORD",
  "from": "noreply@yourcompany.com",
  "notify_to": "sales@yourcompany.com"
}
```

| 字段 | 说明 |
|------|------|
| `smtp_host` / `smtp_port` | 邮件服务商 SMTP 地址；`465` 走 SSL，`587` 走 STARTTLS |
| `smtp_user` / `smtp_pass` | 发信账号与密码（或用授权码） |
| `from` | 发件人地址（建议与 smtp_user 一致） |
| `notify_to` | 销售接收「新线索」通知的邮箱（可省略） |

**行为说明**：
- 配了 `mail.json`：报告邮件发到客户邮箱，并行给 `notify_to` 发一条线索通知；页面提示"报告已发送至 xxx"
- **没配 `mail.json`**：不报错，降级为"页面出报告 + 本地存线索"，页面提示"已记录为跟进线索，顾问会尽快联系"——后续人工发报告或跟进
- 邮箱无效（格式错 / 含注入字符）会被拦截并提示修正；留空则只出报告、不存线索

**查看线索**：`leads/leads.csv`（首次自动建表头）。定期导入 CRM 或分给销售即可。

> 隐私与合规：线索含客户邮箱，属个人数据。公网部署请加 HTTPS、并在页面明示"提交即同意接收报告邮件与后续联系"；高并发场景另加限流 / 验证码防滥用。

## 线索自动推送至 CRM / 企微（销售即时跟进）

自助体检产生线索后，与其靠人工定期打开 CSV，不如让新线索**实时推送到销售系统**——销售在企微群里立刻看到、或 CRM 里直接建跟进任务。本能力零依赖（标准库 `urllib`）。

**开启推送（可选）**：在 skill 根目录放一份 `leads_push.json`（参考两个示例）：

**企微群机器人（推荐）**——`leads_push.wecom.example.json` 复制为 `leads_push.json`：

```json
{
  "type": "wecom",
  "url": "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的群机器人Key",
  "headers": {}
}
```

**通用 CRM / 业务系统**——`leads_push.generic.example.json` 复制为 `leads_push.json`：

```json
{
  "type": "generic",
  "url": "https://crm.yourcompany.com/api/leads",
  "headers": {
    "Authorization": "Bearer YOUR_TOKEN"
  }
}
```

| 字段 | 说明 |
|------|------|
| `url` | 推送目标地址；企微为群机器人 webhook，generic 为你们的 CRM/系统接收接口 |
| `headers` | 可选，附加请求头（如鉴权 `Authorization`），会被原样带到请求里 |

**行为说明**：
- 配了 `leads_push.json`：每次留有效邮箱的提交，除本地 CSV 留痕外，还会**实时把线索推送到该地址**；页面提示"已推送至我们的销售系统"
- **推送失败不丢线索**：推送走 best-effort——连不上 / 被拒绝 / 超时，只在服务端日志打印原因，**报告照常出、CSV 照常存**。即"推送是增强，CSV 才是兜底"
- **没配 `leads_push.json`**：仅本地 CSV 留痕，不影响其它功能
- 若同时配了 `mail.json`，则"发邮件给客户 + 推送线索给销售系统 + 本地存 CSV"三件并发，互不阻塞

> 安全提示：`leads_push.json` 可能含 webhook Key / 令牌，请**不要**提交进公开仓库；模板见 `*.example.json`，真实文件放本地即可（本包不含真实凭据）。

## 打包为可售卖功能

1. 把 `review.py` 接入客户投稿 / 审核系统（Web 表单或 API）；`generate_report.py` 接入客户交付物管理；`webapp.py` 直接当对外获客页
2. 每份客户资料独立成租户：基线目录隔离（参考 `review.py --client <客户目录>`），词表与基线互不串味
3. 输出报告可导出为 PDF（HTML 自带打印按钮）/ 工单，作为交付物向客户收费
4. 配合 `references/gmp_kb.md`（GMP 知识库）做"报告 + AI 解读"增值服务

## 异常处理（4.3）

本能力在「输入校验」和「降级」两件事上做了中文友好处理，目标是：**输入错了一定告诉你哪里错（而且是中文），配置不全 / 发送失败也绝不让你干等——永远先出报告，再说明原因**。

### 4.3.1 输入校验：错了给中文提示，并指明位置

缺参数、路径不存在、内容为空、邮箱格式错，脚本都会用中文报错并说明怎么改：

- **缺必填参数**（漏 `--client` / `--docs`）：原英文 `the following arguments are required: --client` → 现提示 `参数错误：缺少必填参数：--client（用 --help 查看必填项）`，并打印用法。
- **基线目录不存在 / 不是文件夹**：`错误：基线目录不存在：xxx（请确认 --client 指向一个【文件夹】，且其中包含 gmp_requirements.md。）`
- **目录里没有 gmp_requirements.md**：`错误：基线目录 xxx 中未找到 gmp_requirements.md。`
- **待检路径不存在**：不中断，仅 stderr 提示 `提示：以下待检路径不存在，已忽略：...`（其余文件照常跑）。
- **待检资料为空**：`错误：待检资料为空（仅支持 .txt/.md；Word/PDF 需先导出纯文本）`
- **邮箱格式错 / 含注入字符**（Web 页）：`邮箱格式不正确，请检查后重试；您仍可在本页查看报告。`
- **提交内容过大（>3MB）**：`提交内容过大：单次上传请控制在 3MB 以内，可分批次提交。`

> 说明：自检引擎本身是「关键词 / 子串规则匹配」，不是大模型。换说法的合规词若不在基线词表里会「漏检」——这是匹配方式决定的，不是报错，详见下节「反模式与 FAQ」。

### 4.3.2 优雅降级：先出报告，再想办法

无论配置是否齐全、外部服务是否可用，**报告永远先生成并展示**。各类失败只在提示里说明原因，不阻塞、不丢数据：

| 场景 | 行为 | 用户看到 |
|------|------|----------|
| 没放 `mail.json` | 不发邮件，仅本地存线索 | 「已记录为跟进线索，顾问会尽快与您联系。」 |
| `mail.json` 配错 / SMTP 连不上 / 鉴权失败 | 报告照出，邮件失败 | `报告发送失败：<中文原因>`（如「邮箱账号或密码/授权码错误」「连不上邮件服务器，请检查 smtp_host/port 与网络」「SSL/TLS 加密方式不匹配（465 用 SSL，587 用 STARTTLS）」） |
| `leads_push.json` 没配 | 仅本地 CSV 留痕 | （无推送提示） |
| 推送失败（连不上 / 被拒 / 超时 / 404） | 报告照出、CSV 照常存；失败仅服务端日志留因 | `线索推送提示：<中文原因>`（如「连不上推送地址，请检查 url 与网络」「推送被拒绝（鉴权/权限问题）」） |
| 接大模型（`--config`）失败 | 自动回退纯规则评估，报告照出 | stderr 提示 `提示：大模型配置加载/调用失败，已回退纯规则评估：<原因>` |
| 大模型返回 401/403/404/429 | 该 item 保持原规则判定 | stderr 按错误类型给中文提示 |

> 设计原则：**CSV 才是兜底，推送 / 邮件是增强**。即使所有外部链路都挂了，本地 `leads/leads.csv` 仍记录了线索，线索永不丢。

### 4.3.3 常见英文报错 → 中文对照（速查）

绝大多数用户可见报错已经是中文；下列仅出现在「外部系统返回的底层异常」里，工具已自动翻译：

| 原英文（底层） | 你现在看到的 |
|------|------|
| `smtplib.SMTPAuthenticationError` / 535 | 邮箱账号或密码/授权码错误 |
| `[SSL: WRONG_VERSION_NUMBER]` / STARTTLS 失败 | SSL/TLS 加密方式不匹配（核对 465/587 与 smtp_port） |
| `Connection refused` / `getaddrinfo failed` | 连不上邮件服务器，请检查 smtp_host/port 与网络 |
| `timed out` | 连接邮件服务器超时 |
| `urllib` 推送返回 401/403 | 推送被拒绝（鉴权/权限问题，请检查 headers） |
| 推送 `Connection refused` / 404 | 连不上推送地址 / 推送地址不存在 |

## 内容完整度（4.4）

内置基线已经把药企 GMP 合规的「主要方面」铺好了；它不追求一次穷尽所有条款，而是给你一个**可生长**的检查骨架——哪里不够补哪里，或更省事地开大模型帮你「读」出来。

### 4.4.1 内置已经覆盖的主要方面

内置 `sample_data/demo_client/gmp_requirements.md` 含 **10 个合规域 / 20 个检查项**（权重和=100），基本对应药企信息化/质量体系最常被审计、最容易掉坑的地方，并与 中国GMP2010、FDA 21 CFR Part 11、EU GMP Annex 11、WHO 数据完整性 的要点对齐：

| 合规域（内置权重） | 覆盖的关键检查点 |
|------|------|
| 数据完整性 ALCOA+（18） | ALCOA+ 9 原则落地、防篡改与原始数据、数据可读性与留痕 |
| 计算机化系统验证 CSV（14） | URS 与验证生命周期、IQ/OQ/PQ 三阶段、风险评估与供应商审计 |
| 审计追踪（12） | 关键操作审计追踪、定期审计审核 |
| 电子签名与权限（12） | 唯一身份与密码策略、角色权限矩阵 |
| 批次与物料追溯（10） | 批次主数据与谱系、正反向追溯 |
| 变更控制（8） | 变更闭环、变更对验证与培训的影响 |
| 偏差与 CAPA（8） | 偏差识别与调查、CAPA 闭环 |
| 备份与容灾（8） | 备份策略与可恢复性、容灾与业务连续性 |
| 时间同步（5） | NTP 统一时钟 |
| 培训与资质（5） | 培训矩阵与上岗资格、复训与再认证 |

> 你提到的「常用的数据完整性、审计追踪、批次追溯都有」——对，这三项分别占 18/12/10 权重，是内置基线里最重的三块，也是药企 GMP 检查的高频雷区。

### 4.4.2 不够的地方：自己加检查项（扩展基线）

基线就是一个 **`gmp_requirements.md` 文本文件**，格式极简，照猫画虎加域、加项即可，**无需改任何代码**：

```
## 域名称  weight=6
- 检查项：检查项名称  risk=高|中|低
  keywords: 词1、词2、词3
  advice: 一句话整改建议
```

- `## 域 ... weight=N`：一个合规域，权重用于覆盖度加权（脚本会自动归一化，权重和不必恰好=100，但建议=100 便于解读）。
- 每个 `- 检查项：` 下跟 `keywords:`（用 `、` 或 `,` 分隔）和 `advice:`（单行）。
- 关键词命中率 ≥50% 判「覆盖」，>0 判「部分覆盖」，0 命中判「缺失」。

**举例：想加「供应商与物料管理」「环境监测与厂房设施」两块**（药企常见、内置没单列的领域），在基线文件末尾追加：

```
## 供应商与物料管理  weight=6
- 检查项：供应商准入与质量协议  risk=中
  keywords: 供应商准入、质量协议、供应商资质、主文件
  advice: 建立供应商准入标准，签订质量协议，留存供应商主文件与定期评估。
- 检查项：物料放行与留样  risk=中
  keywords: 物料放行、留样、合格供应商
  advice: 物料经 QC 检验合格并由授权人放行后方可使用，按规定留样。

## 环境监测与厂房设施  weight=4
- 检查项：洁净区环境监测  risk=中
  keywords: 环境监测、悬浮粒子、浮游菌、压差、温湿度
  advice: 按品种/洁净级别制定环境监测计划，监测悬浮粒子、微生物、压差、温湿度并趋势分析。
```

加完后 `review.py --client <你的目录>` 即用新基线跑。每个客户可建独立基线目录，互不串味。

> 提示：基线不是一次性的。法规、监管期望、客户品种（生物药/中药/器械）不同，检查项要持续维护——这本身也是「持续收费/维护」的钩子。

### 4.4.3 更省事：开大模型来帮忙判断

不想逐条补关键词、或文档用了换说法的表述，可让大模型对「缺失/部分覆盖」项做**语义级确认**，把规则漏判的拉回来：

```bash
python scripts/review.py \
  --client sample_data/demo_client \
  --docs sample_data/demo_docs/sample_plan.txt \
  --config config.json
```

`config.json`：

```json
{
  "api_key": "sk-xxx",
  "api_base": "https://api.openai.com/v1",
  "model": "gpt-4o-mini"
}
```

- **只判「缺失/部分覆盖」项**：已明确「覆盖」的不浪费 token。
- **可调 status 并重算整体风险**：大模型若判定实际已满足，会把「缺失」改为「覆盖/部分覆盖」，并附 `语义评估：一句话理由`。
- **失败自动回退纯规则**：配置错 / 网络不通 / 限流（401/403/404/429）都不阻塞——报告照出，只在 stderr 提示 `提示：大模型配置加载/调用失败，已回退纯规则评估：<原因>`（或按错误类型给中文提示）。
- **大模型是「确认/补漏」，不是替代扫描**：关键词命中仍是最快路径；大模型解决「换说法漏检」。`--no-semantic` 可强制只用规则。

> 适用场景：客户方案写得绕、术语不一致，或对某域想做「人工级」复核时开大模型；日常快筛用纯规则即可。

## 运行稳定性（4.5）

脚本本身运行稳定、报告生成可靠；网页端此前有个明确短板——**提交的数据不落盘、重启即丢**。本轮已补上自动存盘，但 webapp 仍是无数据库/无登录的轻量服务，重要数据仍需你手动备份。

### 4.5.1 脚本稳定，报告可靠

- `review.py` / `generate_report.py`：纯标准库、零第三方依赖，跨平台可跑；自检与 HTML 报告生成稳定，多次跑结果一致。
- `webapp.py`：零依赖 `http.server`，启动即用；自检、出报告、发邮件、推线索、存线索均已端到端验证。

### 4.5.2 网页端已自动存盘（本轮改进）

每次成功提交，webapp 会把以下内容落盘到 skill 目录，**进程重启不再丢失**：

| 内容 | 落盘位置 | 说明 |
|------|----------|------|
| 生成的合规体检报告（HTML） | `reports/<时间戳>_<公司>.html` | 含完整报告，可用浏览器打开 / 打印 PDF |
| 上传的资料文件 | `uploads/<时间戳>_<文件名>` | 原样保存，便于回溯原文 |
| 线索摘要 | `leads/leads.csv` | 时间/公司/邮箱/扫描字数/缺失项/高风险/来源 |

返回页会提示「本次报告与上传资料已自动存盘（重启不丢失）：reports/...、uploads/...」，你不必再手动另存。

> 存盘是 best-effort：磁盘满/权限不足等极端情况会跳过并仅在页面提示原因，不影响本次出报告。

### 4.5.3 仍需手动备份（重要）

自动存盘只解决「进程重启不丢」，**不解决「机器/介质层面丢失」**。以下情况数据仍会没：

- 删除/误清 skill 目录（含 `leads/`、`reports/`、`uploads/`）
- 服务器磁盘损坏、重装系统、换机器部署
- 把 skill 整个目录移动/打包时漏掉上述三个子目录

**所以请定期手动备份**，二选一或都做：

1. **备份整个 skill 目录**（最简）：把 `gmp-compliance-check/` 整体拷到网盘/NAS/备份机，重点保住 `leads/ reports/ uploads/` 三个文件夹。
2. **把线索导入 CRM**：`leads/leads.csv` 定期导入销售易/企微/表格，作为系统级留痕（推荐——比本地文件更抗丢失）。

> 公网部署额外提醒：webapp 仍无登录、无数据库、无鉴权。除手动备份外，还需自行加反向代理 / HTTPS / 访问鉴权 / 限流，并遵守隐私合规（页面明示授权、保护客户邮箱）。

### 4.5.4 常驻与重启建议

- **常驻运行**：生产环境用 `nohup python scripts/webapp.py --port 8000 > webapp.log 2>&1 &`，或注册为 systemd 服务，避免关终端即停。
- **重启无损**：因为有 4.5.2 的自动存盘，重启进程后历史报告/上传/线索都还在；仅「内存中未提交完的请求」会中断（可重试）。
- **日志**：`webapp.log` 记录了访问与推送/发信失败原因，排查问题时看它。

## 触发方式（4.6）

本能力不是"只有会敲命令的人才能用"。它支持三条触发路径，按你的角色选——其中两条**完全不碰命令行**。

### 4.6.1 对话式（推荐给非技术用户）：对 AI 说一句话就行

最省事的方式：你根本不用找脚本、拼参数。**直接对 WorkBuddy 说需求**，AI 会加载本 skill、自动定位脚本、跑出自检报告并解读。照着下面的说法说即可：

- 「帮我用 GMP 合规自检一下这份方案：C:/客户资料/XX制药_信息化方案.txt」
- 「给这个客户资料做个 GMP 合规体检，客户叫 XX 药业」
- 「跑一下 sample_data/demo_docs/sample_plan.txt，看看覆盖度」
- 「上传/粘贴的这份药企资料，对照 GMP 查漏，给我一份整改清单」
- 「用我自己的基线 C:/基线/XX客户_gmp_requirements.md 审这份方案」

AI 会：① 选 `review.py`（要结构化 / JSON）还是 `generate_report.py`（要可发客户的 HTML 报告）；② 拼好参数跑；③ 把报告里的「缺失域 / 高风险项 / 整改建议」用大白话讲给你，必要时再结合 `references/gmp_kb.md` 给方案/打单建议。

> 这就是"对话式触发"——门槛最低，适合顾问本人、销售、客户成功等非技术角色日常用。
> 注意：对话式由 AI 代为执行脚本，受 AI 运行环境限制（如读本地文件需文件在 AI 可访问路径上）。**公网客户自助请用 ② 点击式**。

### 4.6.2 点击式（Web 自助页）：双击启动器，客户自己填

给**客户自助**或**业务员现场演示**用。无需任何人敲命令——部署人只需把下面的启动器代码保存到桌面，双击一次即可。

> **为什么不在 skill 包里放 `.bat`/`.sh`？** WorkBuddy 的 Skill 加载器对文件类型有白名单，`.bat`、`.sh`、`.gitignore` 等无标准扩展名或可执行脚本会被拦截为「不允许的文件类型」。因此启动器以代码片段形式放在本页，你复制出去保存成文件即可使用。

#### Windows：保存为 `start_webapp.bat`

把下面代码复制 → 在 skill 目录（`gmp-compliance-check`）下新建 `start_webapp.bat` → 双击运行。

```batch
@echo off
chcp 65001 >nul
setlocal

REM === GMP 合规自助体检 Web 启动器 ===
REM 把本文件放到 skill 目录（gmp-compliance-check）里，双击即可

set PORT=8000
if not "%~1"=="" set PORT=%~1

set "PYTHON="
for %%P in (python python3 py) do (
    where /q %%P
    if not errorlevel 1 (
        set "PYTHON=%%P"
        goto :found
    )
)
REM 常见安装路径兜底
for %%D in (
    "%LOCALAPPDATA%\Programs\Python\Python313\python.exe"
    "%LOCALAPPDATA%\Programs\Python\Python312\python.exe"
    "%LOCALAPPDATA%\Programs\Python\Python311\python.exe"
    "C:\Python313\python.exe"
    "C:\Python312\python.exe"
    "C:\Python311\python.exe"
) do (
    if exist %%D (
        set "PYTHON=%%D"
        goto :found
    )
)

echo 未找到 Python。请先安装 Python 3.10+ 并勾选"Add Python to PATH"。
echo 下载地址：https://www.python.org/downloads/
pause
exit /b 1

:found
echo 使用 Python：%PYTHON%
cd /d "%~dp0.."
"%PYTHON%" scripts\webapp.py --port %PORT% --open-browser
pause
```

- 默认端口 `8000`；想换端口创建快捷方式并在目标后加 ` 9000`，或编辑文件里的 `set PORT=8000`。
- 找不到 Python 时会中文提示下载地址，不黑屏退出。

#### macOS / Linux：保存为 `start_webapp.sh`

把下面代码复制 → 在 skill 目录下新建 `start_webapp.sh` → 终端执行 `chmod +x start_webapp.sh` → 双击或运行 `./start_webapp.sh`。

```bash
#!/usr/bin/env bash
# GMP 合规自助体检 Web 启动器
# 放到 skill 目录里，chmod +x start_webapp.sh 后双击或运行

PORT="${1:-8000}"

PYTHON=""
for p in python3 python py3; do
    if command -v "$p" >/dev/null 2>&1; then
        PYTHON="$p"
        break
    fi
done

if [ -z "$PYTHON" ]; then
    echo "未找到 Python。请先安装 Python 3.10+。"
    echo "macOS: brew install python3"
    echo "Ubuntu/Debian: sudo apt install python3"
    exit 1
fi

cd "$(dirname "$0")/.."
exec "$PYTHON" scripts/webapp.py --port "$PORT" --open-browser
```

- 默认端口 `8000`；运行 `./start_webapp.sh 9000` 可换端口。

启动后把网址发给客户：客户填公司名+邮箱、上传/粘贴资料，**自动出报告、自动存盘（reports/uploads/leads，见 4.5）、留资发信推线索**。这是获客钩子的标准用法。

> 普通客户全程不碰命令行：他只看到一个网页、填两张框、点一下「生成报告」。命令行只在「你部署时双击一次」出现。

### 4.6.3 命令行（脚本）：开发者 / 集成 / 批量

需要嵌入你自己的系统、做批量审查、或要 JSON 输出时，直接跑脚本（详见上方 Quick start 与各节）。三条核心命令：

```bash
python scripts/review.py --client sample_data/demo_client --docs <待检文件> --name "客户名"        # 文本/JSON 报告
python scripts/generate_report.py --client sample_data/demo_client --docs <待检文件> --name "客户名" --out report.html  # 客户 HTML 报告
python scripts/webapp.py --port 8000 --open-browser                                                  # 起 Web 服务（等价于双击启动器）
```

### 4.6.4 怎么选

| 你是…… | 推荐方式 | 理由 |
|--------|----------|------|
| 顾问 / 销售 / 客户成功（非技术） | ① 对话式 | 一句话触发，AI 代跑代解读，零门槛 |
| 想对外获客、让客户自助 | ② 点击式 | 复制 SKILL.md 里的启动器代码保存到桌面，双击运行，发链接，客户自己填 |
| 开发者 / 要集成 / 要批量 / 要 JSON | ③ 命令行 | 参数可控、可编排 |

## 创造力与增值（4.7，对应 SOP 4.5）：不止出份报告，更是获客与打单的弹药

本能力真正值钱的地方，不是"出一份合规报告"本身，而是它把「体检 → 留资 → 触达 → 转化」串成了一个**低成本的获客与打单闭环**——而且开箱即用，不用你额外搭系统。

### 4.7.1 报告之外的四件套（获客闭环）

| 能力 | 怎么来的 | 对谁有用 |
|------|----------|----------|
| ① 自动出报告 | `review.py` / `generate_report.py` / `webapp.py` 三件套 | 顾问 / 销售 / 客户 |
| ② 自动收线索 | 客户在 Web 页填公司名+邮箱，写进 `leads/leads.csv`，可实时推 CRM / 企微 | 销售跟进 |
| ③ 自动发邮件 | 配 `mail.json` 后，报告自动发到客户邮箱 + 抄送销售 | 客户触达 |
| ④ 自动存盘 | 每次提交的报告 / 上传 / 线索落 `reports/`/`uploads/`/`leads/`，重启不丢（见 4.5） | 留底 / 复盘 |

> 也就是说：客户**免费**做一次 GMP 体检，你**自动**拿到他的联系方式、他的方案缺陷、他的整改需求——这三者合起来，就是一条高质量的获客线索，且零人工成本。

### 4.7.2 整改建议 = 服务清单（打单最有说服力的弹药）

报告里的「整改建议」列，不是给人"看看就好"的——它**直接就是你的实施服务清单 / 产品配置清单**。把客户的自检缺口翻译成"我们能补什么"，打单时一句"你这份方案缺的 14 项，每一项都对应我们的能力"，说服力极强。

**转化工作流（建议照做）：**

1. 给潜在客户跑一份免费 GMP 自检（用 `webapp.py` 自助页，或 `review.py --client` 客户专属基线）。
2. 报告自动列出「缺失 / 部分覆盖」项及整改建议 → 这就是客户的合规短板清单。
3. 把每个短板映射到 用友BIP / 你的方案能提供的模块、实施服务或配置项（见下方映射模板）。
4. 输出成《GMP 合规补齐服务清单》→ 作为方案附件 / 报价依据 / 投标应答。

**合规域 → 服务清单 映射模板（示例，按你实际产品能力填）：**

| 报告里的缺失域 | 整改建议（报告自动给） | 可对应的服务 / 产品能力（你来填） |
|------|------|------|
| 数据完整性 ALCOA+ | 落实 ALCOA+、防篡改、原始数据留痕 | XX 模块 · 数据治理 / 审计配置服务 |
| 计算机化系统验证 CSV | 建 URS、IQ/OQ/PQ、供应商审计 | CSV 验证实施服务包 |
| 审计追踪 | 关键操作审计追踪、定期审核 | XX · 审计追踪开关与审核流程配置 |
| 电子签名与权限 | 唯一身份、密码策略、角色矩阵 | 统一身份 / 权限实施服务 |
| 批次与物料追溯 | 批次主数据、正反向追溯 | MES/WMS 追溯模块实施 |
| 变更控制 | 变更闭环、影响评估 | 变更管理流程落地服务 |
| 偏差与 CAPA | 偏差调查、CAPA 闭环 | 质量事件管理实施服务 |
| 备份与容灾 | 备份策略、RTO/RPO、演练 | 容灾备份方案实施 |

> 模板里"可对应的服务 / 产品能力"一列是你（用友生态侧）凭产品知识填的——工具只负责把"缺什么"挖出来，你把"补什么"接上，打单弹药就齐了。**客户的自检清单，就是我们的交付清单。**

### 4.7.3 从「体检」到「赢单」的漏斗

```
免费 GMP 体检（获客钩子）
   ↓ 客户自助提交，自动留资
高质量线索（公司 + 邮箱 + 方案缺陷）
   ↓ 顾问跟进，发报告 + 解读
客户意识到合规缺口（"原来我们这么多坑"）
   ↓ 用 4.7.2 的服务清单对应能力
方案 / 报价 / 投标（赢单）
```

> 这套漏斗的核心：**用"免费体检"降低客户防御，用"报告里的真实缺口"制造紧迫感，用"整改建议=服务清单"把缺口直接接成商机**。比单纯发产品白皮书有效得多。

## 开箱即用度（4.8，对应 SOP 4.5）：普通人直接说话就能用

本能力刻意做成"三入口 + 自带示例 + 详尽文档"，让不同角色都能零门槛上手，不必先读源码。

### 4.8.1 内置示例即跑即看

- 自带 `sample_data/demo_client/`（通用 GMP 基线，10 域 20 项）与 `sample_data/demo_docs/sample_plan.txt`（中等覆盖度示例方案）。
- 不备任何资料也能跑出"高风险缺失"的完整报告（见上文 Quick start），先看到效果再换成自己的资料。

### 4.8.2 三个入口覆盖不同角色

| 入口 | 谁用 | 上手成本 |
|------|------|----------|
| ① 对话式 | 任何人，对 WorkBuddy 说一句需求 | 零（AI 代跑） |
| ② 点击式 | 客户自助 / 业务员演示（双击启动器） | 几乎零（部署人双击一次） |
| ③ 命令行 | 开发者 / 集成 / 批量 | 需会基础命令 |

> 对外给客户用：把 Web 自助页网址一发，客户自己填、自己看报告、自动留资——你不用在场。

### 4.8.3 文档与 FAQ 自助排查

- 异常处理（4.3）/ 内容完整度（4.4）/ 运行稳定性（4.5）/ 触发方式（4.6）/ 创造力与增值（4.7）分章讲清"遇到什么、怎么解决"。
- FAQ 覆盖了漏检、部分覆盖、路径错、文件格式、超 3MB、连接失败、大模型报错、线索去哪看、推送失败等**最常见的十几类问题**，基本都能自查找到答案。
- 所有报错已中文化，输入错了直接告诉你哪里错。

### 4.8.4 部署前检查清单（开箱即用收尾）

把本能力真正跑起来前，确认这几项：

- [ ] 已装 Python 3.10+（点击式启动器会自动探测，找不到会提示下载）
- [ ] 想对外获客：准备一台常驻机器，按 4.6.2 保存启动器并运行 `webapp.py`
- [ ] 想自动发报告邮件：复制 `mail.example.json` → `mail.json` 并填 SMTP
- [ ] 想实时推线索到 CRM / 企微：复制 `leads_push.*.example.json` → `leads_push.json` 并填 webhook
- [ ] 想用客户专属基线：复制 `sample_data/demo_client/` 为自己的客户目录，改 `gmp_requirements.md`（见 4.4.2）
- [ ] 公网部署：加反向代理 / HTTPS / 鉴权 / 限流，页面明示授权（见 4.5.3）
- [ ] 定期手动备份 `leads/ reports/ uploads/`（自动存盘只防重启，不防介质丢失）

## 反模式与 FAQ（遇到麻烦先看这节）

> 本能力默认是**关键词 + 子串匹配的规则匹配**（零依赖、纯标准库），不是大模型语义理解。下列每一条都对应脚本的真实行为。

### 反模式（别这样用）

1. **别指望它会"读懂"语义** —— 默认扫描是关键词命中。换说法的合规（如用"原数据完整性"代替"ALCOA+"）会漏。要语义级确认须加 `--config` 接入大模型（但扫描本身仍基于关键词，不会变语义）。
2. **别把 `--client` 指错路径或指成文件** —— `review.py` 的 `--client` 必须是**含 `gmp_requirements.md` 的目录**。指错/不存在时**会报错退出**（不像广告审查那样静默回退，因为基线缺失比基线弱更危险）。
3. **别把整篇长文当一条独立语料** —— 默认 `review.py --docs` 把所有文件拼接为一篇语料；`webapp.py` 也是拼接所有上传 + 粘贴。如果你希望"按文件分别评估"请先拆分文件再分别跑。
4. **别把 `.docx` / `.pdf` / 图片 直接丢进来** —— 只认 `.txt` / `.md`（webapp 也只收这两类）。Word / PDF 需先导出为纯文本，否则会报"待检资料为空"。
5. **别把 `keywords` 写在没含"keywords"字样的行** —— `gmp_requirements.md` 只解析以 `keywords:` 开头行的词条；放别处会被忽略。同理 `advice:`。
6. **别把违禁词写成"孤行无分隔符"** —— `keywords:` 行要用 `、` 或 `,` 分隔多个词；空行或只写一个词没问题（仍按一个词处理），但多个词堆一起（如 `ALCOA 数据完整性` 用空格）只会被当成一个词。
7. **别以为报告能替代人工终审 / 监管审计意见** —— 工具是辅助闸；法规持续演进，基线需持续维护；高风险项仍需专业审计师确认。
8. **别把 webapp 当数据库用** —— 它无登录、无数据库、无鉴权；每次提交会**自动存盘**（报告→`reports/`、上传→`uploads/`、线索→`leads/leads.csv`，重启不丢），但这只防「进程重启」，不防「机器/介质丢失」。务必按 4.5.3 手动备份，公网部署另加反向代理 / 鉴权 / HTTPS / 限流。
9. **别把基线 `weight` 加起来≠100** —— 脚本会照常算（用总和归一化），但人看着别扭。建议权重和=100 便于解读。
10. **别用 `webapp.py` 做客户专属基线审查** —— webapp 固定用内置 demo_client 基线。客户专属基线请用 `review.py --client <客户目录>`。

### FAQ（常见问题）

| 问题 | 原因 | 解决 |
|------|------|------|
| 为什么有些明显合规没查出来？ | 默认是关键词/子串匹配，换说法的词库里没有就会漏 | 把漏的说法补进基线 `keywords`；或接大模型做语义确认（仅对缺失/部分项） |
| 报告显示"部分覆盖"但文档里其实写得很细？ | 关键词命中率 < 50% | 调高该 item 的关键词覆盖度（把文档里实际用的同义词加进 keywords）；或启用 --config 语义评估 |
| 为什么配了基线，审查结果却跑不通？ | `--client` 路径指错（指向不存在的目录/文件） | 用绝对路径，确认目录里有 `gmp_requirements.md`；脚本会直接报错退出 |
| 上传文件夹后报"待检资料为空"？ | 文件夹里只有 `.docx`/`.pdf` 等非文本 | 导出成 `.txt` 再传，或直接粘贴文本 |
| 报告里出现"未知"状态？ | 该 item 的 keywords 为空 | 在基线里给该 item 补 keywords |
| 提交时报"提交内容过大"？ | 单次上传超 3MB | 分批次上传 |
| 点"生成报告"一直转圈 / 报"无法连接到服务"？ | 后端 `webapp.py` 没在运行 | 最省事：按「4.6.2」把启动器代码保存为 `.bat`/`.sh` 后双击启动；或确认已执行 `python scripts/webapp.py --port 8000` 且无报错；公网需端口转发或反向代理 |
| 接大模型报 401/403/404/429？ | 鉴权/地址/限流问题 | 核对 `config.json`；脚本会按错误类型给出人话提示 |
| 想让不同客户基线完全隔离？ | webapp 是通用版不隔离 | 每个客户用独立 `<客户目录>/gmp_requirements.md`；用 `review.py --client <客户目录>` 跑客户专属审查 |
| 基线要一直维护吗？ | 法规、平台规则、监管期望会变 | 要定期更新；这也是持续收费/维护的钩子 |
| 客户留了邮箱，报告没发到他邮箱？ | 未放 `mail.json` 会降级为"页面出报告 + 存线索"，不发信；或 `mail.json` 配错导致发送失败 | 放 `mail.json` 并核对 SMTP；页面会提示具体原因 |
| 提交过的线索在哪里看？ | 留了有效邮箱的提交会记录 | 打开 `leads/leads.csv`（时间/公司/邮箱/扫描/缺失/高风险/来源） |
| 怎么让新线索自动进 CRM / 企微？ | 默认只存本地 CSV | 在 skill 根目录放 `leads_push.json`（参考 `leads_push.wecom.example.json` / `leads_push.generic.example.json`） |
| 推送失败了线索会丢吗？ | 推送是 best-effort | 不会丢。报告照常出、CSV 照常存，失败的推送只在服务端日志留原因 |

## Resources

### scripts/
- `review.py`：核心自检脚本，零依赖，支持 `--client / --docs / --copy / --json / --config`（启用大模型语义评估）。模型调用失败时按错误类型给出人话提示（401/403 鉴权、404 地址、429 限流、网络不可达）。
- `generate_report.py`：HTML 合规体检报告生成器，零依赖，输出可打印 PDF 的体检报告。
- `webapp.py`：零依赖 Web 提交页（`http.server`），客户自助上传资料生成报告；支持**留邮箱 → 自动发报告到客户邮箱 + 实时推送线索至 CRM/企微（leads_push.json）+ 本地存线索（leads/leads.csv）**；**每次提交还会把报告自动存 `reports/`、上传文件存 `uploads/`（重启不丢，见 4.5）**；邮箱做了格式校验与头部注入防护；SMTP / 推送未配置时均优雅降级；multipart/form-data 解析用 `email` 模块（兼容 Python 3.13 已移除 `cgi`）。

- **点击式启动器代码**：`SKILL.md` 的「触发方式（4.6.2）」提供可直接复制保存为 `.bat`（Win）/ `.sh`（Mac/Linux）的启动器代码，双击即自动找 Python、起服务、开浏览器，普通人无需命令行。Skill 包内不能包含 `.bat`/`.sh` 文件，故以代码片段形式放在文档里。

### references/
- `gmp_kb.md`：GMP 合规知识库——核心法规速查、ALCOA+ 9 项原则、CSV 生命周期、自检报告解读、整改最佳实践、合规→信息化能力映射思路（打单/方案侧）、常见误区与快速行动表。供 AI 在解读报告、生成整改建议、做方案/投标应答时按需加载。

### sample_data/
- `demo_client/gmp_requirements.md`：示例 GMP 合规基线（10 个域、20 个检查项，权重和=100），可开箱即用试跑
- `demo_docs/sample_plan.txt`：示例药企信息化方案（中等覆盖度），可跑出"高风险缺失"演示报告

### 配置示例
- `mail.example.json`：SMTP 发邮件配置示例（自动发报告到客户邮箱 + 抄送销售）
- `leads_push.wecom.example.json`：企微群机器人推送示例
- `leads_push.generic.example.json`：通用 CRM webhook 推送示例

> 以上配置示例需复制为 `mail.json` / `leads_push.json` 才生效（脚本按固定文件名读取）。请勿把真实凭据提交进版本库。

