Skip to main content
Glama
README.md
# LawAgent · 招投标法规问答 Agent

[![ci](https://github.com/haohao66996/lawagent/actions/workflows/ci.yml/badge.svg)](https://github.com/haohao66996/lawagent/actions/workflows/ci.yml) ![python](https://img.shields.io/badge/python-3.11+-blue) ![license](https://img.shields.io/badge/license-MIT-green)

> **开源说明**:本仓库为项目结项后的整理开源版,保留核心实现、评测脚本与数据集。完整开发在 GPU 服务器环境完成,业务语料与逐题轨迹不便公开,汇总口径见 `eval/results/`。

基于 **LangGraph** 的 Agentic RAG(Corrective RAG)系统。解决前一个 RAG 系统上线后暴露的两类问题:

1. **多法规对比题**容易只检索到单侧("招标法第七条和采购法第二十三条有什么区别")
2. **答案幻觉**与**不当拒答**

核心目标:不只是"查得准",而是**"答得可信"**。

知识库规模:**173 部法规 / 4787 个 chunk**。

> **项目矩阵**(作者三个 LLM 应用项目,建议按顺序看):[bidding-rag-system · RAG 检索](https://github.com/haohao66996/bidding-rag-system) | [lawagent · Agentic RAG](https://github.com/haohao66996/lawagent) | [shop-agent · Code Interpreter](https://github.com/haohao66996/shop-agent)
>
> **一句话**:一期 RAG 上线后的 Agentic 升级版,用 Corrective RAG 闭环解决「多法规对比只检索到单侧、幻觉引用、不当拒答」三类问题。
> **三个数字**:拒答率 41% → 9.1%(最好轮 4.5%);幻觉条号率 0.9 条/题 → 0;端到端延迟 204s → 17.5s。
> **技术栈**:LangGraph(StateGraph) · fastmcp(MCP) · Function Calling · FAISS · BM25 · bge-reranker
>
## 效果数据

22 题分层评测集、4 轮消融(代表轮):

| 指标 | run1 基线 | run4 终版 |
|---|---|---|
| 总体拒答率 | 41% | **9.1%**(最好轮 4.5%) |
| 双侧覆盖率 | 60% | **95.5%** |
| 幻觉条号率(题均) | 0.9 条/题 | **0** |
| 端到端延迟 | 204s | **17.5s** |
| 跨部门条款对比题拒答率 | 88% | **0%** |

> 复现:`python eval/make_testset.py && python eval/run_eval.py`(22 题分层评测集可从仓库语料确定性重建;结果记录见 `eval/results/run4_final.json`)

> 诚实口径:这是小规模评测集上的代表轮。因 LLM 非确定性,复跑会有波动(如拒答率回到 9.1%),但**幻觉核验稳定为 0**。不夸大为大规模生产指标。

## 架构:Corrective RAG 闭环

```
意图分析
   ↓
Function Calling 工具路由
   ↓
混合检索(FAISS + BM25 + bge-reranker)
   ↓
相关性自反思 ── 不相关 ──→ 查询重写 ──┐
   ↓ 相关                              │
带引用生成                              │
   ↓                                    │
幻觉核验 ── 不通过 ──→ 带提示重生成 ─────┘
   ↓ 通过
输出答案
```

按问题类型动态选路:条号精确检索 / 语义混合检索 / 多法规双路检索。

## 三个关键设计

### 1. 用规则替代 LLM 路由

多跳对比题的根因不是检索能力差,而是**「复合 query 语义漂移」+「LLM 工具路由参数方差」**——同一个问题两次调用,路由到的检索参数不一样。

解法:**法规白名单抽取 + 子集过滤检索 + 公平配额**。用确定性规则替代 LLM 路由,双侧覆盖率从 63.6% 提到 95.5%。

### 2. 三层幻觉治理

| 层 | 做法 | 特点 |
|---|---|---|
| 程序化引用比对 | 全文「《法规名》第X条」与检索集确定性比对 | **零 LLM 方差** |
| LLM 内容支撑判定 | 判断答案每个结论是否被检索内容支撑 | 覆盖改写式幻觉 |
| 拒答质量检查 | 检查是否不该拒答而拒答 | 治理"保守性拒答" |

### 3. MCP 工具化

检索能力封装为 MCP Server(fastmcp),暴露 `hybrid_search`、`lookup_article` 两个 tool,可被 Claude Code / Cursor 直接调用。

## 目录结构

```
graph.py        LangGraph StateGraph 主流程(自反思闭环)
retriever.py    混合检索实现
tools.py        Function Calling 工具定义
state.py        状态定义
article_utils.py 条号解析与引用核验工具
mcp_server.py   MCP Server(fastmcp)
project/        e2e / perf / smoke 测试脚本、构建索引脚本
eval/           评测集生成、评测运行器、结果记录(复现入口)
tests/          单元测试(条号解析纯逻辑,CI 运行)
data/           清洗后的法规条文数据
```

## 本地运行

```bash
pip install -r requirements.txt
cp .env.example .env                    # 填 API key 与模型路径
python project/scripts/build_index.py --src data --out data/index  # 构建索引
python project/smoke_test.py            # 检索冒烟
python project/e2e_test.py              # 端到端测试
make eval                               # 评测(生成评测集 + 全量跑分)
```

## 与前一个项目的关系

[bidding-rag-system](https://github.com/haohao66996/bidding-rag-system) 解决"查得准"(检索管线优化到生产标准),本项目解决"答得可信"(幻觉治理 + 拒答质量)。

## 已知问题与局限(诚实清单)

- **评测集规模偏小**:22 题分层评测集,统计显著性有限,结论应视作趋势而非精确值。
- **规则路由有边界**:多法规检索依赖法规名白名单抽取,法规名未出现在白名单时会退化为语义检索,双侧覆盖率下降。
- **延迟优化依赖硬件**:205s → 18s 的改善主要来自把重排模型迁移到 GPU,CPU 环境下该结论不成立。
- **4 轮消融非完整网格搜索**,超参与提示词为手工迭代,未做自动化调参。
- **评测轨迹在服务器环境产出**:仓库记录汇总口径(`eval/results/`),逐题轨迹与业务语料未公开,本地复跑指标会因 LLM 非确定性波动。