增强 Word 文档 AI 解析和模板填充功能
This commit is contained in:
354
比赛备赛规划.md
354
比赛备赛规划.md
@@ -50,18 +50,18 @@
|
||||
| `prompt_service.py` | ✅ 已完成 | Prompt 模板管理 |
|
||||
| `text_analysis_service.py` | ✅ 已完成 | 文本分析 |
|
||||
| `chart_generator_service.py` | ✅ 已完成 | 图表生成服务 |
|
||||
| `template_fill_service.py` | ✅ 已完成 | 模板填写服务,支持直接读取源文档进行填表 |
|
||||
| `template_fill_service.py` | ✅ 已完成 | 模板填写服务,支持多行提取、直接从结构化数据提取、JSON容错、Word文档表格处理 |
|
||||
|
||||
### 2.2 API 接口 (`backend/app/api/endpoints/`)
|
||||
|
||||
| 接口文件 | 路由 | 功能状态 |
|
||||
|----------|------|----------|
|
||||
| `upload.py` | `/api/v1/upload/excel` | ✅ Excel 文件上传与解析 |
|
||||
| `upload.py` | `/api/v1/upload/document` | ✅ 文档上传与解析 |
|
||||
| `documents.py` | `/api/v1/documents/*` | ✅ 文档管理(列表、删除、搜索) |
|
||||
| `ai_analyze.py` | `/api/v1/analyze/*` | ✅ AI 分析(Excel、Markdown、流式) |
|
||||
| `rag.py` | `/api/v1/rag/*` | ⚠️ RAG 检索(当前返回空) |
|
||||
| `tasks.py` | `/api/v1/tasks/*` | ✅ 异步任务状态查询 |
|
||||
| `templates.py` | `/api/v1/templates/*` | ✅ 模板管理 (含 Word 导出) |
|
||||
| `templates.py` | `/api/v1/templates/*` | ✅ 模板管理(含多行导出、Word导出、Word结构化字段解析) |
|
||||
| `visualization.py` | `/api/v1/visualization/*` | ✅ 可视化图表 |
|
||||
| `health.py` | `/api/v1/health` | ✅ 健康检查 |
|
||||
|
||||
@@ -70,71 +70,67 @@
|
||||
| 页面文件 | 功能 | 状态 |
|
||||
|----------|------|------|
|
||||
| `Documents.tsx` | 主文档管理页面 | ✅ 已完成 |
|
||||
| `TemplateFill.tsx` | 智能填表页面 | ✅ 已完成 |
|
||||
| `ExcelParse.tsx` | Excel 解析页面 | ✅ 已完成 |
|
||||
|
||||
### 2.4 文档解析能力
|
||||
|
||||
| 格式 | 解析状态 | 说明 |
|
||||
|------|----------|------|
|
||||
| Excel (.xlsx/.xls) | ✅ 已完成 | pandas + XML 回退解析 |
|
||||
| Excel (.xlsx/.xls) | ✅ 已完成 | pandas + XML 回退解析,支持多sheet |
|
||||
| Markdown (.md) | ✅ 已完成 | 正则 + AI 分章节 |
|
||||
| Word (.docx) | ✅ 已完成 | python-docx 解析,支持表格提取和字段识别 |
|
||||
| Text (.txt) | ✅ 已完成 | chardet 编码检测,支持文本清洗和结构化提取 |
|
||||
|
||||
---
|
||||
|
||||
## 三、待完成功能(核心缺块)
|
||||
## 三、核心功能实现详情
|
||||
|
||||
### 3.1 模板填写模块(最优先)
|
||||
|
||||
**当前状态**:✅ 已完成
|
||||
### 3.1 模板填写模块(✅ 已完成)
|
||||
|
||||
**核心流程**:
|
||||
```
|
||||
用户上传模板表格(Word/Excel)
|
||||
上传模板表格(Word/Excel)
|
||||
↓
|
||||
解析模板,提取需要填写的字段和提示词
|
||||
↓
|
||||
根据模板指定的源文档列表读取源数据
|
||||
根据源文档ID列表读取源数据(MongoDB或文件)
|
||||
↓
|
||||
AI 根据字段提示词从源数据中提取信息
|
||||
优先从结构化数据直接提取(Excel rows)
|
||||
↓
|
||||
将提取的数据填入模板对应位置
|
||||
无法直接提取时使用 LLM 从文本中提取
|
||||
↓
|
||||
返回填写完成的表格
|
||||
将提取的数据填入原始模板对应位置(保持模板格式)
|
||||
↓
|
||||
导出填写完成的表格(Excel/Word)
|
||||
```
|
||||
|
||||
**已完成实现**:
|
||||
- [x] `template_fill_service.py` - 模板填写核心服务
|
||||
- [x] Word 模板解析 (`docx_parser.py` - parse_tables_for_template, extract_template_fields_from_docx)
|
||||
- [x] Text 模板解析 (`txt_parser.py` - 已完成)
|
||||
- [x] 模板字段识别与提示词提取
|
||||
- [x] 多文档数据聚合与冲突处理
|
||||
- [x] 结果导出为 Word/Excel
|
||||
**关键特性**:
|
||||
- **原始模板填充**:直接打开原始模板文件,填充数据到原表格/单元格
|
||||
- **多行数据支持**:每个字段可提取多个值,导出时自动扩展行数
|
||||
- **结构化数据优先**:直接从 Excel rows 提取,无需 LLM
|
||||
- **JSON 容错**:支持 LLM 返回的损坏/截断 JSON
|
||||
- **Markdown 清理**:自动清理 LLM 返回的 markdown 格式
|
||||
|
||||
### 3.2 Word 文档解析
|
||||
|
||||
**当前状态**:✅ 已完成
|
||||
### 3.2 Word 文档解析(✅ 已完成)
|
||||
|
||||
**已实现功能**:
|
||||
- [x] `docx_parser.py` - Word 文档解析器
|
||||
- [x] 提取段落文本
|
||||
- [x] 提取表格内容
|
||||
- [x] 提取关键信息(标题、列表等)
|
||||
- [x] 表格模板字段提取 (`parse_tables_for_template`, `extract_template_fields_from_docx`)
|
||||
- [x] 字段类型推断 (`_infer_field_type_from_hint`)
|
||||
- `docx_parser.py` - Word 文档解析器
|
||||
- 提取段落文本
|
||||
- 提取表格内容(支持比赛表格格式:字段名 | 提示词 | 填写值)
|
||||
- `parse_tables_for_template()` - 解析表格模板,提取字段
|
||||
- `extract_template_fields_from_docx()` - 提取模板字段定义
|
||||
- `_infer_field_type_from_hint()` - 从提示词推断字段类型
|
||||
- **API 端点**:`/api/v1/templates/parse-word-structure` - 上传 Word 文档,提取结构化字段并存入 MongoDB
|
||||
- **API 端点**:`/api/v1/templates/word-fields/{doc_id}` - 获取已存文档的模板字段信息
|
||||
|
||||
### 3.3 Text 文档解析
|
||||
|
||||
**当前状态**:✅ 已完成
|
||||
### 3.3 Text 文档解析(✅ 已完成)
|
||||
|
||||
**已实现功能**:
|
||||
- [x] `txt_parser.py` - 文本文件解析器
|
||||
- [x] 编码自动检测 (chardet)
|
||||
- [x] 文本清洗
|
||||
|
||||
### 3.4 文档模板匹配(已有框架)
|
||||
|
||||
根据 Q&A,模板已指定数据文件,不需要算法匹配。当前已有上传功能,需确认模板与数据文件的关联逻辑是否完善。
|
||||
- `txt_parser.py` - 文本文件解析器
|
||||
- 编码自动检测 (chardet)
|
||||
- 文本清洗(去除控制字符、规范化空白)
|
||||
- 结构化数据提取(邮箱、URL、电话、日期、金额)
|
||||
|
||||
---
|
||||
|
||||
@@ -192,20 +188,20 @@ docs/test/
|
||||
|
||||
## 六、工作计划(建议)
|
||||
|
||||
### 第一优先级:模板填写核心功能
|
||||
- 完成 Word 文档解析
|
||||
- 完成模板填写服务
|
||||
- 端到端测试验证
|
||||
### 第一优先级:端到端测试
|
||||
- 使用真实测试数据进行准确率测试
|
||||
- 验证多行数据导出是否正确
|
||||
- 测试 Word 模板解析是否正常
|
||||
|
||||
### 第二优先级:Demo 打包与文档
|
||||
- 制作项目演示 PPT
|
||||
- 录制演示视频
|
||||
- 完善 README 部署文档
|
||||
|
||||
### 第三优先级:测试优化
|
||||
- 使用真实测试数据进行准确率测试
|
||||
### 第三优先级:优化
|
||||
- 优化响应时间
|
||||
- 完善错误处理
|
||||
- 增加更多测试用例
|
||||
|
||||
---
|
||||
|
||||
@@ -215,29 +211,32 @@ docs/test/
|
||||
2. **数据库**:不强制要求数据库存储,可跳过
|
||||
3. **部署**:本地部署即可,不需要公网服务器
|
||||
4. **评测数据**:初赛仅使用目前提供的数据
|
||||
5. **RAG 功能**:当前已临时禁用,不影响核心评测功能
|
||||
5. **RAG 功能**:当前已临时禁用,不影响核心评测功能(因为使用直接文件读取)
|
||||
|
||||
---
|
||||
|
||||
*文档版本: v1.1*
|
||||
*最后更新: 2026-04-08*
|
||||
*文档版本: v1.5*
|
||||
*最后更新: 2026-04-09*
|
||||
|
||||
---
|
||||
|
||||
## 八、技术实现细节
|
||||
|
||||
### 8.1 模板填表流程(已实现)
|
||||
### 8.1 模板填表流程
|
||||
|
||||
#### 流程图
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ 上传模板 │ ──► │ 选择数据源 │ ──► │ AI 智能填表 │
|
||||
│ 上传模板 │ ──► │ 选择数据源 │ ──► │ 智能填表 │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ 导出结果 │
|
||||
└─────────────┘
|
||||
│
|
||||
┌─────────────────────────┼─────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
||||
│ 结构化数据提取 │ │ LLM 提取 │ │ 导出结果 │
|
||||
│ (直接读rows) │ │ (文本理解) │ │ (Excel/Word) │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
```
|
||||
|
||||
#### 核心组件
|
||||
@@ -247,8 +246,10 @@ docs/test/
|
||||
| 模板上传 | `templates.py` `/templates/upload` | 接收模板文件,提取字段 |
|
||||
| 字段提取 | `template_fill_service.py` | 从 Word/Excel 表格提取字段定义 |
|
||||
| 文档解析 | `docx_parser.py`, `xlsx_parser.py`, `txt_parser.py` | 解析源文档内容 |
|
||||
| 智能填表 | `template_fill_service.py` `fill_template()` | 使用 LLM 从源文档提取信息 |
|
||||
| 结果导出 | `templates.py` `/templates/export` | 导出为 Excel 或 Word |
|
||||
| 智能填表 | `template_fill_service.py` `fill_template()` | 结构化提取 + LLM 提取 |
|
||||
| 多行支持 | `template_fill_service.py` `FillResult` | values 数组支持 |
|
||||
| JSON 容错 | `template_fill_service.py` `_fix_json()` | 修复损坏的 JSON |
|
||||
| 结果导出 | `templates.py` `/templates/export` | 多行 Excel + Word 导出 |
|
||||
|
||||
### 8.2 源文档加载方式
|
||||
|
||||
@@ -268,7 +269,9 @@ docs/test/
|
||||
|
||||
```python
|
||||
# 提取表格模板字段
|
||||
fields = docx_parser.extract_template_fields_from_docx(file_path)
|
||||
from docx_parser import DocxParser
|
||||
parser = DocxParser()
|
||||
fields = parser.extract_template_fields_from_docx(file_path)
|
||||
|
||||
# 返回格式
|
||||
# [
|
||||
@@ -295,6 +298,24 @@ fields = docx_parser.extract_template_fields_from_docx(file_path)
|
||||
|
||||
### 8.5 API 接口
|
||||
|
||||
#### POST `/api/v1/templates/upload`
|
||||
|
||||
上传模板文件,提取字段定义。
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"template_id": "/path/to/saved/template.docx",
|
||||
"filename": "模板.docx",
|
||||
"file_type": "docx",
|
||||
"fields": [
|
||||
{"cell": "A1", "name": "姓名", "field_type": "text", "required": true, "hint": "提取人员姓名"}
|
||||
],
|
||||
"field_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
#### POST `/api/v1/templates/fill`
|
||||
|
||||
填写请求:
|
||||
@@ -306,35 +327,232 @@ fields = docx_parser.extract_template_fields_from_docx(file_path)
|
||||
],
|
||||
"source_doc_ids": ["mongodb_doc_id_1", "mongodb_doc_id_2"],
|
||||
"source_file_paths": [],
|
||||
"user_hint": "请从合同文档中提取"
|
||||
"user_hint": "请从xxx文档中提取"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
**响应(含多行支持)**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"filled_data": {"姓名": "张三"},
|
||||
"filled_data": {
|
||||
"姓名": ["张三", "李四", "王五"],
|
||||
"年龄": ["25", "30", "28"]
|
||||
},
|
||||
"fill_details": [
|
||||
{
|
||||
"field": "姓名",
|
||||
"cell": "A1",
|
||||
"values": ["张三", "李四", "王五"],
|
||||
"value": "张三",
|
||||
"source": "来自:合同文档.docx",
|
||||
"confidence": 0.95
|
||||
"source": "结构化数据直接提取",
|
||||
"confidence": 1.0
|
||||
}
|
||||
],
|
||||
"source_doc_count": 2
|
||||
"source_doc_count": 2,
|
||||
"max_rows": 3
|
||||
}
|
||||
```
|
||||
|
||||
#### POST `/api/v1/templates/export`
|
||||
|
||||
导出请求:
|
||||
导出请求(创建新文件):
|
||||
```json
|
||||
{
|
||||
"template_id": "模板ID",
|
||||
"filled_data": {"姓名": "张三", "金额": "10000"},
|
||||
"format": "xlsx" // 或 "docx"
|
||||
"filled_data": {"姓名": ["张三", "李四"], "金额": ["10000", "20000"]},
|
||||
"format": "xlsx"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
#### POST `/api/v1/templates/fill-and-export`
|
||||
|
||||
**填充原始模板并导出**(推荐用于比赛)
|
||||
|
||||
直接打开原始模板文件,将数据填入模板的表格/单元格中,然后导出。**保持原始模板格式不变**。
|
||||
|
||||
**请求**:
|
||||
```json
|
||||
{
|
||||
"template_path": "/path/to/original/template.docx",
|
||||
"filled_data": {
|
||||
"姓名": ["张三", "李四", "王五"],
|
||||
"年龄": ["25", "30", "28"]
|
||||
},
|
||||
"format": "docx"
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:填充后的 Word/Excel 文件(文件流)
|
||||
|
||||
**特点**:
|
||||
- 打开原始模板文件
|
||||
- 根据表头行匹配字段名到列索引
|
||||
- 将数据填入对应列的单元格
|
||||
- 多行数据自动扩展表格行数
|
||||
- 保持原始模板格式和样式
|
||||
|
||||
#### POST `/api/v1/templates/parse-word-structure`
|
||||
|
||||
**上传 Word 文档并提取结构化字段**(比赛专用)
|
||||
|
||||
上传 Word 文档,从表格模板中提取字段定义(字段名、提示词、字段类型)并存入 MongoDB。
|
||||
|
||||
**请求**:multipart/form-data
|
||||
- file: Word 文件
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"doc_id": "mongodb_doc_id",
|
||||
"filename": "模板.docx",
|
||||
"file_path": "/path/to/saved/template.docx",
|
||||
"field_count": 5,
|
||||
"fields": [
|
||||
{
|
||||
"cell": "T0R1",
|
||||
"name": "字段名",
|
||||
"hint": "提示词",
|
||||
"field_type": "text",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"tables": [...],
|
||||
"metadata": {
|
||||
"paragraph_count": 10,
|
||||
"table_count": 1,
|
||||
"word_count": 500,
|
||||
"has_tables": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### GET `/api/v1/templates/word-fields/{doc_id}`
|
||||
|
||||
**获取 Word 文档模板字段信息**
|
||||
|
||||
根据 doc_id 获取已上传的 Word 文档的模板字段信息。
|
||||
|
||||
**响应**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"doc_id": "mongodb_doc_id",
|
||||
"filename": "模板.docx",
|
||||
"fields": [...],
|
||||
"tables": [...],
|
||||
"field_count": 5,
|
||||
"metadata": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.6 多行数据处理
|
||||
|
||||
**FillResult 数据结构**:
|
||||
```python
|
||||
@dataclass
|
||||
class FillResult:
|
||||
field: str
|
||||
values: List[Any] = None # 支持多个值(数组)
|
||||
value: Any = "" # 保留兼容(第一个值)
|
||||
source: str = "" # 来源文档
|
||||
confidence: float = 1.0 # 置信度
|
||||
```
|
||||
|
||||
**导出逻辑**:
|
||||
- 计算所有字段的最大行数
|
||||
- 遍历每一行,取对应索引的值
|
||||
- 不足的行填空字符串
|
||||
|
||||
### 8.7 JSON 容错处理
|
||||
|
||||
当 LLM 返回的 JSON 损坏或被截断时,系统会:
|
||||
|
||||
1. 清理 markdown 代码块标记(```json, ```)
|
||||
2. 尝试配对括号找到完整的 JSON
|
||||
3. 移除末尾多余的逗号
|
||||
4. 使用正则表达式提取 values 数组
|
||||
5. 备选方案:直接提取所有引号内的字符串
|
||||
|
||||
### 8.8 结构化数据优先提取
|
||||
|
||||
对于 Excel 等有 `rows` 结构的文档,系统会:
|
||||
|
||||
1. 直接从 `structured_data.rows` 中查找匹配列
|
||||
2. 使用模糊匹配(字段名包含或被包含)
|
||||
3. 提取该列的所有行值
|
||||
4. 无需调用 LLM,速度更快,准确率更高
|
||||
|
||||
```python
|
||||
# 内部逻辑
|
||||
if structured.get("rows"):
|
||||
columns = structured.get("columns", [])
|
||||
values = _extract_column_values(rows, columns, field_name)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、依赖说明
|
||||
|
||||
### Python 依赖
|
||||
|
||||
```
|
||||
# requirements.txt 中需要包含
|
||||
fastapi>=0.104.0
|
||||
uvicorn>=0.24.0
|
||||
motor>=3.3.0 # MongoDB 异步驱动
|
||||
sqlalchemy>=2.0.0 # MySQL ORM
|
||||
pandas>=2.0.0 # Excel 处理
|
||||
openpyxl>=3.1.0 # Excel 写入
|
||||
python-docx>=0.8.0 # Word 处理
|
||||
chardet>=4.0.0 # 编码检测
|
||||
httpx>=0.25.0 # HTTP 客户端
|
||||
```
|
||||
|
||||
### 前端依赖
|
||||
|
||||
```
|
||||
# package.json 中需要包含
|
||||
react>=18.0.0
|
||||
react-dropzone>=14.0.0
|
||||
lucide-react>=0.300.0
|
||||
sonner>=1.0.0 # toast 通知
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、启动说明
|
||||
|
||||
### 后端启动
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
.\venv\Scripts\Activate.ps1 # 或 Activate.bat
|
||||
pip install -r requirements.txt # 确保依赖完整
|
||||
.\venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
|
||||
```
|
||||
|
||||
### 前端启动
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
在 `backend/.env` 中配置:
|
||||
```
|
||||
MONGODB_URL=mongodb://localhost:27017
|
||||
MONGODB_DB_NAME=document_system
|
||||
MYSQL_HOST=localhost
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_USER=root
|
||||
MYSQL_PASSWORD=your_password
|
||||
MYSQL_DATABASE=document_system
|
||||
LLM_API_KEY=your_api_key
|
||||
LLM_BASE_URL=https://api.minimax.chat
|
||||
LLM_MODEL_NAME=MiniMax-Text-01
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user