swati-yelamanchili/normlens
GitHub: swati-yelamanchili/normlens
基于 Legal‑BERT 和语义检索的合同智能分析平台,提供条款分类、风险检测和异常标记等自动化合同审查能力。
Stars: 0 | Forks: 0
# NormLens
一个合同智能平台,支持导入合同(PDF/DOCX)、提取条款、
使用微调的 Legal‑BERT 条款分类器进行分类、检测风险模式、
将条款与市场规范进行基准对比,并标记统计学异常值 —— 所有功能均通过
REST API 和 Next.js 仪表盘提供。
## 架构
```
┌────────────────────────────────────────────────────────────┐
│ Frontend (Next.js 16 preview, React 18, Tailwind, Recharts) │
│ :3000 │
└──────────────────────┬─────────────────────────────────────┘
│ HTTP / JSON
┌──────────────────────▼─────────────────────────────────────┐
│ Backend (FastAPI, SQLAlchemy, uvicorn) │
│ :8000 │
│ ┌───────────── ──────────── ──────────── ──────────┐ │
│ │ routers/ │ services/ │ models/ │ │
│ │ contracts │ extraction │ Contract │ │
│ │ analysis │ embeddings │ Clause │ │
│ │ reports │ classification │ RiskFinding │ │
│ │ search │ benchmarking │ RiskRule │ │
│ │ │ outlier │ Benchmark │ │
│ │ │ reporting │ Report │ │
│ └───────────── ──────────── ──────────── ──────────┘ │
│ │
│ ┌────────────────── ML Inference ──────────────────────┐ │
│ │ Clause │ Attribute │ Risk │ CT │ │
│ │ Classifier │ NER │ Scorer │ Type │ │
│ │ (Legal‑BERT) │ (spaCy) │ (GBM) │(TfIdf)│ │
│ └─────────────────────────────────────────────────────┘ │
└──────┬──────────────────────────┬──────────────────────────┘
│ │
┌──────▼──────┐ ┌───────▼────────┐
│ PostgreSQL │ │ ChromaDB │
│ (metadata, │ │ (embeddings, │
│ findings) │ │ similarity) │
└─────────────┘ └────────────────┘
```
### 技术栈
| 层级 | 技术 |
|------------|----------------------------------------------|
| 后端 | Python 3.11, FastAPI, SQLAlchemy |
| 前端 | Next.js 16 预览版, React 18, Tailwind CSS |
| 数据库 | PostgreSQL 16 (Alembic 迁移) |
| 向量数据库 | ChromaDB 0.5.3 |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2) |
| 条款分类 | Legal‑BERT (nlpaueb/legal-bert-base-uncased) |
| NER | spaCy (en_core_web_sm + 自定义实体) |
| 机器学习 | scikit-learn, transformers, torch, datasets |
| PDF | PyMuPDF, pdfplumber |
## 数据模型
```
┌──────────────┐ ┌─────────────────┐
│ Contract │1───many│ Clause │
│──────────────│ │─────────────────│
│ id │ │ id │
│ filename │ │ contract_id (FK)│
│ status │ │ clause_index │
│ text_content │ │ clause_title │
│ file_type │ │ clause_text │
│ page_count │ │ clause_type │
│ error_msg │ │ confidence │
│ created_at │ │ embedding_id │
└──────┬───────┘ └────────┬────────┘
│ │
│ 1 │ 0..1
┌──────▼───────┐ ┌───────▼────────────┐
│ RiskFinding │ │ BenchmarkResult │
│──────────────│ │────────────────────│
│ id │ │ id │
│ contract_id │ │ contract_id (FK) │
│ clause_id │ │ clause_id (FK) │
│ risk_name │ │ clause_type │
│ severity │ │ attribute │
│ points │ │ market_median │
│ percentile │ │ percentile_rank │
└──────────────┘ │ z_score │
└────────────────────┘
▲ ▲
┌──────┴───────┐ ┌────────┴──────────┐
│ RiskRule │ │ AnalysisReport │
│──────────────│ │───────────────────│
│ rule_id │ │ contract_id (FK) │
│ name │ │ total_risk_score │
│ category │ │ risk_level │
│ severity │ │ clause_count │
│ points │ │ finding_count │
│ conditions │ │ report_data (JSON)│
│ enabled │ └───────────────────┘
└──────────────┘
```
## API 接口
| 方法 | 路径 | 描述 |
|--------|------------------------------|-------------------------------|
| GET | `/api/health` | 健康检查 |
| POST | `/api/contracts/upload` | 上传 PDF/DOCX |
| GET | `/api/contracts/` | 列出所有合同 |
| GET | `/api/contracts/{id}` | 获取合同详情 |
| GET | `/api/contracts/{id}/download` | 下载原始文件 |
| DELETE | `/api/contracts/{id}` | 删除合同 |
| POST | `/api/analysis/analyze/{id}` | 运行全量分析流水线 |
| GET | `/api/analysis/status/{id}` | 获取分析状态 |
| GET | `/api/reports/{id}` | 获取完整报告 |
| GET | `/api/reports/{id}/summary` | 获取报告摘要 |
| GET | `/api/search/` | 语义条款搜索 |
### ML 推理服务器(可选,端口 8001)
| 方法 | 路径 | 描述 |
|--------|------------------------------|-----------------------------------|
| GET | `/health` | 模型健康状态与可用性 |
| POST | `/predict/clause-type` | Legal‑BERT 条款预测 |
| POST | `/predict/entities` | spaCy NER 实体提取 |
| POST | `/predict/risk-score` | 梯度提升风险评分 |
| POST | `/predict/contract-type` | TF‑IDF + LR 类型预测 |
| GET | `/models` | 列出已加载的模型路径 |
## 分析流水线
```
Upload ──► Parse ──► Segment ──► Embed ──► Classify ──► Extract ──► Risk ──► Benchmark ──► Outlier ──► Report
│ │ │ │ │ │ │ │
text/PDF clause vector Legal‑BERT regex/ rule peer z-score/
extraction splitting storage + k‑NN pattern engine comparison percentile
fusion
```
1. **解析** — 从 PDF (PyMuPDF + pdfplumber) 或 DOCX (python-docx) 中提取原始文本
2. **分段** — 使用 NLP + regex 边界检测将文本拆分为条款
3. **向量化** — 通过 sentence-transformers 生成向量 embeddings;存储在 ChromaDB 中
4. **分类** — 分配 CUAD 条款类型(Legal‑BERT 微调模型 + embedding k‑NN 融合)
5. **提取** — 通过 regex + spaCy NER 提取属性(日期、金额、期限)
6. **风险** — 根据 22 条可配置的风险规则评估条款(严重性、条件、分值)
7. **基准对比** — 将提取的属性与市场规范进行比较(百分位数、z‑score)
8. **异常检测** — 标记具有统计学异常的条款(语义 + 基于属性的异常检测)
9. **报告** — 生成包含风险摘要、发现的问题、异常项和建议的结构化报告
## 项目结构
```
normlens/
├── backend/
│ ├── app/ # FastAPI application
│ │ ├── benchmarking/ # Market norm comparison engine
│ │ ├── classification/ # Clause classifier (keyword + embedding fusion)
│ │ ├── embeddings/ # Vector embeddings + ChromaDB interface
│ │ ├── extraction/ # Attribute extraction (regex + spaCy NER)
│ │ ├── models/ # SQLAlchemy ORM models
│ │ ├── outlier/ # Statistical outlier detection
│ │ ├── parsers/ # PDF/DOCX text extraction
│ │ ├── reporting/ # Report generation
│ │ ├── risk/ # Risk engine + rules + contract type detector
│ │ ├── routers/ # API endpoint definitions
│ │ ├── search/ # Semantic search
│ │ ├── segmentation/ # Clause segmentation
│ │ ├── services/ # Task manager, NLP service
│ │ ├── config.py
│ │ ├── database.py
│ │ └── main.py
│ │
│ ├── training/ # 🆕 ML model training scripts
│ │ ├── train_classifier.py # Legal‑BERT fine-tuning on CUAD + LEDGAR
│ │ ├── train_ner.py # spaCy NER from noisy regex labels
│ │ ├── train_risk_scorer.py # Gradient‑boosted risk severity model
│ │ └── train_contract_type.py # TF‑IDF + Logistic Regression
│ │
│ ├── evaluation/ # 🆕 Model evaluation & benchmarking
│ │ ├── eval_classifier.py # Clause classifier vs baseline
│ │ ├── eval_ner.py # NER model vs regex baseline
│ │ └── benchmark.py # Full pipeline benchmark
│ │
│ ├── inference/ # 🆕 ML inference server
│ │ └── model_server.py # FastAPI wrapper for all trained models
│ │
│ ├── models/ # 🆕 Trained model artifacts
│ │ ├── clause_classifier/ # Legal‑BERT fine-tuned
│ │ ├── attribute_ner/ # spaCy NER with custom entities
│ │ ├── risk_scorer/ # GradientBoostingClassifier.pkl
│ │ └── contract_type/ # TF‑IDF vectorizer + LR model
│ │
│ ├── data/
│ │ ├── market_norms.json # Market comparison distributions
│ │ ├── raw/ # CUAD, LEDGAR, custom contracts
│ │ ├── processed/ # Tokenized, split datasets
│ │ └── labels/ # Human annotations
│ │
│ ├── tests/ # Test suite (68+ tests)
│ ├── requirements.txt
│ ├── requirements-ml.txt
│ └── Dockerfile
│
├── frontend/ # Next.js dashboard
├── docker-compose.yml
└── README.md
```
## ML 组件概览
| 组件 | 启发式基线 | ML 模型 | 状态 |
|-------------------------|--------------------------------------------|-----------------------------------------------|----------------|
| 条款分类 | Embedding k‑NN + 关键词融合 | Legal‑BERT 微调 (CUAD + LEDGAR) | 已训练 / v0 |
| 属性提取 | 50+ regex 模式 | 带有自定义实体标签的 spaCy NER | 已训练 / v0 |
| 风险严重性评分 | 22 条手写规则(if‑then 阈值) | 梯度提升树 (sklearn) | 已训练 / v0 |
| 合同类型检测 | 加权关键词评分 | TF‑IDF + 逻辑回归 | 已训练 / v0 |
| 缺失条款检测 | 布尔检查(标题 regex) | 保留规则(无需 ML) | — |
| 异常检测 | 百分位数 / z‑score | 保留统计方法(已足够) | — |
| 报告生成 | 基于模板 | 保留模板(无需 ML) | — |
### 模型性能
| 模型 | 准确率 | 备注 |
|---------------------------|-------------|-----------------------------------------|
| 条款分类器 | 进行中 | 32 种 CUAD 条款类型,多分类 |
| 合同类型分类器 | **92.3%** | 9 种合同类型,516 个合成样本 |
| 风险评分器 | **95.5%** | 4 个严重性级别,2200 个样本 |
| 属性 NER | 100% 评估 | 7 个自定义实体,80 个训练样本 |
## 训练
每个模型都可以独立训练。所有脚本都接受 `--output-dir` 参数,用于
指定训练产物(artifact)的保存位置。
### 前置条件
```
cd backend
pip install -r requirements.txt -r requirements-ml.txt
```
### 1. 条款分类器 (Legal‑BERT)
在 CUAD 数据集和来自 HuggingFace Datasets 的 LEDGAR 条款标签上
微调 `nlpaueb/legal-bert-base-uncased`,并包含合成兜底数据。
```
# 使用 CUAD + LEDGAR + synthetic 进行完整训练(推荐使用 GPU)
python -m training.train_classifier --epochs 5 --batch_size 8
# 仅使用 synthetic 数据进行快速测试(适用于 CPU)
python -m training.train_classifier --use_synthetic --epochs 3 --batch_size 4
# 自定义输出目录
python -m training.train_classifier --output-dir /app/models/clause_classifier
```
**数据源:**
- [CUAD](https://huggingface.co/datasets/cuad) — 关于合同条款的 41 个是/否问题
- [LEDGAR](https://huggingface.co/datasets/lex_glue) — 60,000+ 标注的合同条款
- 合成数据 — 从领域模板生成的 1700 个条款样本(兜底方案)
**标签映射:** 与模型一起保存为 `label_map.json`。
### 2. 属性 NER (spaCy)
利用属性提取器中现有的 regex 模式作为引导数据,训练带有自定义实体类型的
spaCy NER 流水线。
```
python -m training.train_ner --epochs 30 --output-dir models/attribute_ner
```
**自定义实体类型:** `NOTICE_DAYS`, `LIABILITY_AMOUNT`, `PAYMENT_DEADLINE`,
`DURATION`, `MONEY`, `PERCENT`, `LAW`, `ORG`
### 3. 风险严重性评分器(梯度提升)
从具有真实 z‑score 严重性标签的市场规范分布中生成 2200 个合成样本,
然后训练一个 `GradientBoostingClassifier`。
```
python -m training.train_risk_scorer --epochs 200 --output-dir models/risk_scorer
```
**特征向量(29 维):**
- 25 个市场属性 z‑score(跨所有条款类型进行填充)
- 缺失属性计数
- 总属性计数
- 条款类型索引
- 随机噪声特征
### 4. 合同类型分类器 (TF‑IDF + LR)
跨 9 种类型生成 516 个合成合同文本,使用
TF‑IDF(一元语法 + 二元语法 + 三元语法)进行向量化,并训练一个多项式
逻辑回归模型。
```
python -m training.train_contract_type --output-dir models/contract_type
```
**合同类型:** SaaS 协议、NDA、MSA、咨询协议、专业
服务协议、雇佣协议、供应商协议、许可协议、
政府合同。
## 评估
### 条款分类器评估
在留出测试集上,将微调后的 Legal‑BERT 模型与启发式关键词 +
embedding 融合基线进行比较。
```
python -m evaluation.eval_classifier
python -m evaluation.eval_classifier --model-path models/clause_classifier/final
```
### NER 评估
在带有标准(gold)实体跨度的 8 个测试句上,将训练好的 spaCy 模型与 regex 基线
进行比较。
```
python -m evaluation.eval_ner
python -m evaluation.eval_ner --model-path models/attribute_ner
```
### 全流水线基准测试
针对测试合同运行每一个分析组件(分段、分类、提取、
异常检测、风险评分、合同类型检测),并报告耗时。
```
python -m evaluation.benchmark
python -m evaluation.benchmark --quick # skip embedding benchmark
```
结果保存到 `models/benchmark_results.json`。
## 推理服务器
一个独立的 FastAPI 服务器封装了所有训练好的模型,用于生产环境推理。
```
# 在端口 8001 上启动
python -m inference.model_server
# 或
uvicorn inference.model_server:app --host 0.0.0.0 --port 8001
```
**接口:**
```
# 条款分类
curl -X POST http://localhost:8001/predict/clause-type \
-H "Content-Type: application/json" \
-d '{"text": "Either party may terminate upon 90 days notice.", "top_k": 3}'
# 实体抽取
curl -X POST http://localhost:8001/predict/entities \
-H "Content-Type: application/json" \
-d '{"text": "The liability cap is $5,000,000."}'
# 风险评分
curl -X POST http://localhost:8001/predict/risk-score \
-H "Content-Type: application/json" \
-d '{"features": [0.5, 1.2, -0.3, 0.0, 2]}'
# 合同类型分类
curl -X POST http://localhost:8001/predict/contract-type \
-H "Content-Type: application/json" \
-d '{"text": "This Software as a Service Agreement is entered into..."}'
```
## 核心组件
### 后端 (`backend/app/`)
| 模块 | 路径 | 职责 |
|----------------------|---------------------------------|-------------------------------------|
| Contracts | `routers/contracts.py` | 上传、列出、下载、删除合同 |
| Analysis | `routers/analysis.py` | 编排全量分析流水线 |
| Reports | `routers/reports.py` | 检索分析报告 |
| Search | `routers/search.py` | 跨条款的语义搜索 |
| Extraction | `extraction/attribute_extractor.py` | regex + NER 属性提取 |
| Embeddings | `embeddings/embedding_service.py` | 向量生成 + ChromaDB |
| Classification | `classification/classifier.py` | CUAD 条款类型分类器 |
| Risk | `risk/risk_engine.py` | 确定性风险规则评估 |
| Benchmarking | `benchmarking/benchmarking_engine.py` | 市场规范对比 |
| Outlier | `outlier/outlier_detector.py` | 统计异常检测 |
| Reporting | `reporting/report_generator.py` | 结构化报告组装 |
### 前端 (`frontend/`)
- Next.js 16 预览版 App Router 和 TypeScript
- Tailwind CSS 样式及响应式布局
- 基于 Recharts 的风险可视化(严重性细分、评分)
- 分析过程中的实时进度跟踪
- 带有分类详情的条款级深入分析
## 快速开始
### 前置条件
- Docker 和 Docker Compose(推荐)
- Python 3.11+ 和 Node.js 20+(用于本地开发)
### Docker(全栈)
```
docker compose up --build
```
| 服务 | URL |
|-----------|----------------------|
| Frontend | http://localhost:3000 |
| Backend | http://localhost:8000 |
| ChromaDB | http://localhost:8001 |
| PostgreSQL| localhost:5432 |
### 本地开发
**后端:**
```
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt -r requirements-ml.txt
# 分别启动 PostgreSQL 和 ChromaDB。
# 对于现有的数据库,在启动 API 之前应用 migrations:
alembic upgrade head
uvicorn app.main:app --reload --port 8000
```
**前端:**
```
cd frontend
npm ci
npm run dev
```
### 运行 ML 推理服务器
```
cd backend
pip install -r requirements.txt -r requirements-ml.txt
python -m training.train_contract_type
python -m training.train_risk_scorer
python -m training.train_ner
python -m training.train_classifier --use_synthetic --epochs 3 --batch_size 4
python -m inference.model_server
```
## 配置
环境变量(位于 `backend/` 根目录的 `.env` 文件):
| 变量 | 默认值 | 描述 |
|----------------------|--------------------------------------------------|-----------------------------------|
| `DATABASE_URL` | `postgresql://normlens:normlens@localhost:5432/normlens` | PostgreSQL DSN |
| `CHROMA_HOST` | `localhost` | ChromaDB 主机 |
| `CHROMA_PORT` | `8001` | ChromaDB 端口 |
| `EMBEDDING_MODEL` | `all-MiniLM-L6-v2` | Sentence-transformers 模型 |
| `EMBEDDING_BACKEND` | `auto` | auto, sentence-transformers, hashing |
| `UPLOAD_DIR` | `/tmp/normlens/uploads` | 上传存储路径 |
| `LOG_LEVEL` | `INFO` | 日志级别 |
| `ML_SERVER_PORT` | `8001` | ML 推理服务器端口 |
## 测试
```
cd backend
python -m pytest
```
测试套件涵盖:
- 条款分类(关键词 + embedding)
- 属性提取(全部 50+ 种属性类型)
- 基准对比引擎(市场规范、百分位数)
- 异常检测(统计标记)
- 风险引擎(规则评估、去重)
- 报告生成(结构、严重性细分)
- 搜索(语义、精确匹配、意图过滤)
- 任务管理器(后台分析)
- 向量存储(ChromaDB 操作)
- NLP 服务(spaCy 集成)
## 参考
- [CUAD — Contract Understanding Atticus Dataset](https://www.atticusprojectai.org/cuad)
- [LEDGAR Labeled Contract Provision Dataset](https://zenodo.org/records/7930762)
- [Legal‑BERT](https://huggingface.co/nlpaueb/legal-bert-base-uncased)
- [LexGLUE benchmark](https://huggingface.co/datasets/lex_glue)
标签:AV绕过, FastAPI, 人工智能, 凭据扫描, 文本分类, 法律科技, 测试用例, 用户模式Hook绕过, 逆向工具, 风险分析