# HS-Classifier(海关商品智能归类系统)
**Repository Path**: zavay/HS-Classifier
## Basic Information
- **Project Name**: HS-Classifier(海关商品智能归类系统)
- **Description**: 基于 RAG(检索增强生成) 技术的海关商品AI智能归类系统
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-04-01
- **Last Updated**: 2026-04-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# HS-Classifier
海关商品智能归类与申报要素校验系统
---
## 项目简介
HS-Classifier 是一个基于 **RAG(检索增强生成)** 技术的海关商品归类辅助系统。它通过 Embedding 向量检索 + CrossEncoder 重排序 + 大语言模型推理的管道,帮助报关人员快速找到最匹配的 HS 商品编码,并利用 LangGraph 状态机对申报要素进行智能校验。
## 系统展示
### 核心功能
| 功能 | 说明 |
|------|------|
| **智能商品归类** | 输入商品名称和描述,AI 推荐 Top 5 候选 HS 编码及归类理由 |
| **申报要素查询** | 输入 10 位 HS 编码,查看完整的申报要素要求、示例值及必填属性 |
| **申报要素校验** | 基于 LangGraph 四节点状态机,校验要素完整性与填写合理性,输出风险等级 |
| **商品数据库浏览** | 分页浏览 ~1.2 万条 HS 编码数据,支持关键词搜索和编码前缀筛选 |
### 技术亮点
- **RAG 管道**: BAAI/bge-m3 Embedding → Milvus Lite 向量检索 → bge-reranker-v2-m3 精排 → 通义千问 LLM 推理
- **HS 章节预过滤**: 向量检索后根据 top1 候选的 HS 类号分组,Reranker 只对同类候选重排,跨类候选按向量距离排序后补充,避免多义词(如"苹果"→ iPhone vs 鲜苹果)被 Reranker 误判为高相关
- **LangGraph 校验**: retrieve → completeness → ai_validate → report 四节点有向状态机
- **多层降级**: Reranker 不可用跳过精排、LLM 失败返回排序结果、LangGraph 异常降级为规则检查
- **轻量部署**: Milvus Lite 进程内运行,SQLite 文件数据库,Docker Compose 一键部署
---
## 系统架构图
### 整体架构
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ HS-Classifier 系统架构 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌────────────────────────────────┐ │
│ │ │ HTTP API │ │ │
│ │ React SPA │◄──────────────────►│ FastAPI 后端 │ │
│ │ Ant Design 5 │ │ │ │
│ │ │ │ ┌────────────────────────┐ │ │
│ │ • 商品归类页面 │ │ │ RAG Pipeline │ │ │
│ │ • 申报要素查询 │ │ │ (chain.py) │ │ │
│ │ • 要素校验页面 │ │ └────────────────────────┘ │ │
│ │ • 数据库浏览 │ │ │ │
│ │ │ │ ┌────────────────────────┐ │ │
│ └──────────────────┘ │ │ LangGraph 校验 │ │ │
│ │ │ (graph.py) │ │ │
│ │ └────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────┐ ┌───────────┐ │ │
│ │ │ SQLite │ │ Milvus │ │ │
│ │ │ 关系数据 │ │ Lite │ │ │
│ │ │ (~1.2万条) │ │ 向量索引 │ │ │
│ │ └────────────┘ └───────────┘ │ │
│ └────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 外部服务 │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │ │
│ │ │ 阿里云百炼 API │ │ LangSmith │ │ HuggingFace Models │ │ │
│ │ │ (通义千问 LLM) │ │ (LLM Tracing) │ │ bge-m3 / bge-reranker │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### RAG 三阶段流程图
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ RAG 商品归类三阶段流程 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 输入: 商品名称 + 描述 │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ "不锈钢保温杯 500ml 真空保温" │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 阶段一: Embedding 向量化 │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 模型: BAAI/bge-m3 (1024维) │ │ │
│ │ │ 输入: "不锈钢保温杯 500ml 真空保温" │ │ │
│ │ │ 输出: [0.023, -0.145, 0.678, ..., 0.234] (1024维向量) │ │ │
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 阶段二: 向量检索 + HS章节预过滤 + Reranker 重排序 │ │
│ │ │ │
│ │ ┌───────────────────┐ ┌───────────────────┐ ┌───────────────────────┐ │ │
│ │ │ Milvus 向量检索 │ │ HS 章节预过滤 │ │ CrossEncoder Reranker │ │ │
│ │ │ Top 20 候选 │─►│ 按 top1 类号分组 │─►│ 只对同类候选重排 │ │ │
│ │ │ (余弦相似度) │ │ 同类→rerank │ │ bge-reranker-v2-m3 │ │ │
│ │ │ │ │ 跨类→按距离排序 │ │ Top 5 同类候选 │ │ │
│ │ └───────────────────┘ └───────────────────┘ └───────────────────────┘ │ │
│ │ │ │
│ │ 候选示例: │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. 9617001900 | 其他保温瓶(玻璃胆除外) | score: 0.92 │ │ │
│ │ │ 2. 9617001100 | 玻璃内胆制保温瓶 | score: 0.45 │ │ │
│ │ │ 3. 7324100000 | 不锈钢制洗涤槽及脸盆 | score: 0.23 │ │ │
│ │ │ ... │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 阶段三: LLM 推理生成 │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 模型: 通义千问 qwen-plus (阿里云百炼 API) │ │ │
│ │ │ │ │ │
│ │ │ System Prompt: │ │ │
│ │ │ "你是资深海关商品归类专家,精通《商品名称及编码协调制度》..." │ │ │
│ │ │ │ │ │
│ │ │ 输出: │ │ │
│ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ recommended: │ │ │ │
│ │ │ │ hs_code: "9617001900" │ │ │ │
│ │ │ │ confidence: 95 │ │ │ │
│ │ │ │ reason: "商品为500ml不锈钢保温杯,核心功能是保温..." │ │ │ │
│ │ │ └─────────────────────────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 输出: JSON 格式归类结果 │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "primary_result": { "hs_code": "9617001900", "confidence": 95 }, │ │
│ │ "alternatives": [...] │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### LangGraph 四节点校验架构图
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ LangGraph 申报要素校验状态机 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 输入: HS编码 + 已填写要素 │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ { hs_code: "3822190020", filled_elements: {"用途": "新冠检测", ...} } │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ [START] │ ───► │ retrieve │ ───► │ completeness │ │ │
│ │ └──────────────┘ │ 数据库查询 │ │ 完整性检查 │ │ │
│ │ │ │ │ │ │ │
│ │ │ • 查询HS编码 │ │ • 比对必填项 │ │ │
│ │ │ • 获取申报要素│ │ • 计算完整度 │ │ │
│ │ │ • 加载示例值 │ │ • 标记缺失项 │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ │ │ ai_validate │ │ │
│ │ │ │ ───► │ AI智能校验 │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ • LLM分析 │ │ │
│ │ │ │ │ • 语义合理性 │ │ │
│ │ │ │ │ • 逻辑一致性 │ │ │
│ │ │ │ └──────────────┘ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌──────────────┐ │ │ │
│ │ │ │ report │ │ │ │
│ │ │ │ 生成报告 │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ • 综合评分 │ │ │ │
│ │ │ │ • 风险等级 │ │ │ │
│ │ │ │ • 改进建议 │ │ │ │
│ │ │ └──────────────┘ │ │ │
│ │ │ │ │ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌──────────────┐ │ │ │
│ │ │ │ [END] │ │ │ │
│ │ │ └──────────────┘ │ │ │
│ │ │ │ │ │
│ └─────────────────────────────────────────────────────────────────┼───────┘ │
│ │ │
│ ▼ │ │
│ 输出: 校验报告 │
│ ┌──────────────────────────────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "risk_level": "low", │ │
│ │ "overall_score": 92, │ │
│ │ "is_passed": true, │ │
│ │ "suggestions": ["✓ 所有必填要素已填写", ...] │ │
│ │ } │ │
│ └──────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ 风险等级判定规则 │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ high : 存在缺失必填项 │ │ │
│ │ │ medium : 完整度<100% 或 AI校验发现轻微问题 │ │ │
│ │ │ low : 完整度100% 且 AI校验通过 (得分≥85) │ │ │
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ 评分公式: overall_score = 完整度得分(40%) + AI校验得分(60%) │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
---
## 技术栈
| 层级 | 技术 |
|------|------|
| 前端 | React 18 + TypeScript + Ant Design 5 + Vite 5 |
| 后端 | Python 3.11 + FastAPI + SQLAlchemy 2.0 |
| 向量数据库 | Milvus Lite(进程内) |
| 关系数据库 | SQLite |
| Embedding | BAAI/bge-m3 (1024维) |
| Reranker | BAAI/bge-reranker-v2-m3 |
| LLM | 通义千问 qwen-plus(阿里云百炼 API) |
| RAG 框架 | LangChain + LangGraph |
| 部署 | Docker Compose + Nginx |
---
## 快速开始
### 环境要求
- Python 3.10+
- Node.js 18+
- 约 4GB 可用内存(加载 ML 模型)
### 1. 克隆项目
```bash
git clone https://github.com/your-username/HS-Classifier.git
cd HS-Classifier
```
### 2. 配置环境变量
```bash
cp .env.example .env
```
编辑 `.env`,填入你的阿里云百炼 API Key:
```
BAILIAN_API_KEY=sk-your-key-here
```
> API Key 获取: [阿里云百炼平台](https://bailian.console.aliyun.com/)
### 3. 一键启动
```bash
bash start.sh
```
首次启动会自动:
- 安装 Python 和 Node.js 依赖
- 初始化 SQLite 数据库
- 导入 HS 编码数据(需要 `明确商品编码库.xlsx` 在项目根目录)
### 4. 构建向量索引(首次运行)
```bash
cd backend
source venv/bin/activate
python scripts/build_index.py
```
> 首次运行会自动下载 bge-m3 模型(约 2GB)。
### 访问地址
| 服务 | URL |
|------|-----|
| 前端 | http://localhost:3000 |
| 后端 API | http://localhost:8000 |
| API 文档 (Swagger) | http://localhost:8000/docs |
---
## Docker 部署
```bash
# 构建前端
cd frontend && npm install && npm run build && cd ..
# 启动所有服务
docker-compose up -d --build
```
访问 http://localhost 即可使用。
---
## 项目结构
```
HS-Classifier/
├── backend/ # Python 后端
│ ├── app/
│ │ ├── main.py # FastAPI 入口
│ │ ├── config.py # 配置管理
│ │ ├── models/ # ORM 模型 (4张表)
│ │ ├── schemas/ # Pydantic 数据模型
│ │ ├── routers/ # API 路由
│ │ ├── services/ # 业务逻辑 + ML 服务
│ │ └── rag/ # RAG 管道 + LangGraph 工作流
│ ├── scripts/ # 数据库初始化、数据导入、索引构建
│ └── requirements.txt
├── frontend/ # React 前端
│ ├── src/
│ │ ├── pages/ # 6 个页面组件
│ │ ├── services/api.ts # API 服务层
│ │ └── styles/ # 全局样式
│ └── package.json
├── docker-compose.yml
├── nginx.conf
└── start.sh / stop.sh
```
---
## API 概览
| 方法 | 路径 | 说明 |
|------|------|------|
| `POST` | `/api/classification/classify` | 智能商品归类 |
| `GET` | `/api/elements/{hs_code}` | 查询申报要素详情 |
| `GET` | `/api/elements` | 分页浏览商品列表 |
| `POST` | `/api/validation/check` | 申报要素校验 |
| `GET` | `/api/stats` | 系统统计 |
| `GET` | `/api/system/status` | 组件状态 |
---
## 测试集
项目包含医疗相关测试集,用于验证 AI 归类和申报要素校验功能:
```bash
# 运行测试
./test_cases/run_tests.sh
# 查看报告
cat test_cases/test_result_report_v2.md
```
测试集特点:
- **商品归类测试**: 15个用例,覆盖精准输入/模糊输入/歧义输入/错误输入等场景
- **申报要素校验测试**: 12个用例,覆盖完整规范/部分缺失/逻辑矛盾/明显错误等场景
---
## 优化记录
### HS 章节预过滤 — 解决多义词跨类干扰
#### 问题背景
查询 "iPhone" 时,RAG 管道出现跨类干扰:
| 阶段 | 排名 | 商品 | 说明 |
|------|------|------|------|
| 向量检索 Top2 | 2 | 鲜苹果 (08章) | bge-m3 将 iPhone/苹果判定为语义相关 |
| Rerank Top2 | 2 | 鲜苹果 (rerank=0.47) | bge-reranker-v2-m3 也判定为高相关 |
根因:多语言 embedding/reranker 模型学到了 Apple 品牌 ↔ 中文"苹果"水果的语义关联,但无法区分这是两个完全不同的 HS 归类方向(第85章机械电子 vs 第08章水果)。
#### 解决方案
**HS 章节预过滤**:利用 HS 编码前2位(章节号)映射到产品大类(类号),在 Reranker 之前将候选分组:
1. 向量检索 Top 20 后,取 top1 的类号作为主类
2. 同类候选全部进入 Reranker 重排(Top 5)
3. 跨类候选按向量距离排序,最多补充 2 个到最终候选列表末尾
#### 效果对比
```
查询: iPhone (top1 类=15 机械电子)
【无过滤 - Rerank 后】:
1. 智能手机 (rerank=0.8457) ✓
2. 鲜苹果 (rerank=0.4702) ✗ ← 跨类干扰排在第二
3. 微型机 (rerank=0.1015)
...
【章节预过滤后】:
1. 智能手机 (rerank=0.8457) ✓ 同类
2. 微型机 (rerank=0.1015) ✓ 同类
3. 其他电话机 (rerank=0.0221) ✓ 同类
4. 带时钟收音机 (rerank=0.0080) ✓ 同类
5. 无绳加密电话 (rerank=0.0053) ✓ 同类
6. 鲜苹果 (距离排序) ✗ 跨类 ← 排到最后
7. 钥匙 (距离排序) ✗ 跨类
```
#### 代码变更
- `backend/app/rag/chain.py` — 新增 `HS_SECTION_MAP`(97章→20类映射表)、`_get_section()`、`_filter_by_section()`;pipeline 中 Reranker 只对同类候选重排,跨类候选按向量距离排序后补充
#### 设计要点
- 纯规则逻辑,不依赖额外模型,零推理开销
- HS 类号映射基于《协调制度》类注,天然代表产品大类边界
- 同类候选全部保留给 Reranker 精排,保证类内排序质量
- 跨类候选仍保留 2 个,供 LLM 在边缘场景下参考
---
## License
[MIT License](LICENSE)