实现Agent对话,合格自动提交,不合格补充材料的能力
This commit is contained in:
724
docs/API.md
724
docs/API.md
@@ -1,5 +1,5 @@
|
||||
---
|
||||
last_reviewed: 2026-06-09
|
||||
last_reviewed: 2026-06-13
|
||||
---
|
||||
|
||||
# 财务报销自动化 — API 文档
|
||||
@@ -12,17 +12,25 @@ last_reviewed: 2026-06-09
|
||||
| # | 方法 | 路径 | 说明 |
|
||||
|---|------|------|------|
|
||||
| 1 | GET | `/` | PC 端主页 |
|
||||
| 2 | POST | `/api/session` | 创建会话 |
|
||||
| 3 | POST | `/api/upload/<session_id>` | 上传文件(PDF/图片) |
|
||||
| 4 | GET | `/api/files/<session_id>` | 列出会话目录中的文件 |
|
||||
| 5 | POST | `/api/process/<session_id>` | 启动处理(提取+LLM识别+出库单) |
|
||||
| 6 | GET | `/api/logs/<session_id>` | SSE 日志流 |
|
||||
| 7 | GET | `/api/download/<session_id>/<filename>` | 下载生成的文件 |
|
||||
| 8 | GET | `/api/data/<session_id>` | 获取发票数据(JSON) |
|
||||
| 9 | POST | `/api/save/<session_id>` | 保存编辑后的发票数据 |
|
||||
| 10 | POST | `/api/submit-financial/<session_id>` | 提交到财务系统 |
|
||||
| 11 | GET | `/mobile/<session_id>` | 移动端上传页面 |
|
||||
| 12 | POST | `/api/mobile-upload/<session_id>` | 移动端上传图片 |
|
||||
| 2 | GET | `/mobile/<session_id>` | 移动端上传页面 |
|
||||
| 3 | POST | `/api/session` | 创建会话 |
|
||||
| 4 | POST | `/api/upload/<session_id>` | 上传文件(PDF/图片) |
|
||||
| 5 | GET | `/api/files/<session_id>` | 列出会话目录中的文件 |
|
||||
| 6 | GET | `/api/download/<session_id>/<filename>` | 下载生成的文件 |
|
||||
| 7 | POST | `/api/mobile-upload/<session_id>` | 移动端上传图片 |
|
||||
| 8 | GET | `/api/config/<session_id>` | 获取会话配置 |
|
||||
| 9 | GET | `/api/data/<session_id>` | 获取发票数据(JSON) |
|
||||
| 10 | POST | `/api/save/<session_id>` | 保存编辑后的发票数据 |
|
||||
| 11 | POST | `/api/process/<session_id>` | 启动管道处理(仅发票提取,不自动提交) |
|
||||
| 12 | GET | `/api/logs/<session_id>` | SSE 日志流 |
|
||||
| 13 | POST | `/api/submit-financial/<session_id>` | 提交到财务系统 |
|
||||
| **14** | **GET** | **`/api/agent/state/<session_id>`** | **获取 Agent 会话状态** |
|
||||
| **15** | **POST** | **`/api/agent/process/<session_id>`** | **启动 Agent 多轮处理(主入口)** |
|
||||
| **16** | **POST** | **`/api/agent/supplement/<session_id>`** | **补充文件后重新分析** |
|
||||
| **17** | **POST** | **`/api/agent/user-supplement/<session_id>`** | **通过文字补充信息** |
|
||||
| **18** | **POST** | **`/api/agent/force-submit/<session_id>`** | **强制提交,跳过校验** |
|
||||
|
||||
> 加粗条目为 Agent 多轮校验流程新增接口。推荐使用 `/api/agent/process` 作为主入口,它会在发票提取后自动进行 LLM 校验,校验通过则自动提交到财务系统。
|
||||
|
||||
---
|
||||
|
||||
@@ -30,7 +38,7 @@ last_reviewed: 2026-06-09
|
||||
|
||||
- 调用 `POST /api/session` 获得 `session_id`
|
||||
- 该会话下所有文件存放在 `src/web/uploads/<session_id>/`
|
||||
- 典型产物:`invoice_summary.csv`、`易耗品、出库单.doc`、`config.json`、`session.log`、`result.json`
|
||||
- 典型产物:`invoice_summary.csv`、`payment_records.csv`、`易耗品、出库单.doc`、`config.json`、`session.log`、`result.json`、`agent_state.json`、`agent_events.log`、`file_events.log`、`llm_stream.log`
|
||||
|
||||
---
|
||||
|
||||
@@ -87,6 +95,10 @@ GET /api/files/<session_id>
|
||||
|
||||
```json
|
||||
{
|
||||
"files": [
|
||||
{ "name": "1. 电容一批.pdf", "type": "pdf", "size": 12345 },
|
||||
{ "name": "payment_01.jpg", "type": "image", "size": 67890 }
|
||||
],
|
||||
"pdfs": ["1. 电容一批.pdf"],
|
||||
"images": ["payment_01.jpg"]
|
||||
}
|
||||
@@ -96,130 +108,7 @@ GET /api/files/<session_id>
|
||||
|
||||
---
|
||||
|
||||
### 5. 启动管道处理
|
||||
|
||||
```
|
||||
POST /api/process/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**请求体:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| username | string | 否 | 财务系统工号 |
|
||||
| password | string | 否 | 登录密码 |
|
||||
| default_name | string | 否 | 默认报销人姓名 |
|
||||
| default_card_no | string | 否 | 默认公务卡号 |
|
||||
| default_person_id | string | 否 | 默认人员编号 |
|
||||
| consumable_storage | string | 否 | 出库单存放地点;未填则用 `config.json` 中的值 |
|
||||
|
||||
**处理内容:**
|
||||
|
||||
1. 从会话目录 PDF 提取发票信息 → `invoice_summary.csv`
|
||||
2. 对支付截图多模态 LLM 识别,回填刷卡字段
|
||||
3. 根据发票类型自动分类:差旅发票(高铁票/酒店住宿)不生成出库单;普通发票从模板复制并自动填写
|
||||
|
||||
配置会写入 `src/web/uploads/<session_id>/config.json`。
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
处理在后台线程执行,进度与结果通过 `GET /api/logs/<session_id>`(SSE)获取。
|
||||
|
||||
**SSE 完成时 `result` 示例(成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"elapsed": "45.2s",
|
||||
"invoice_count": 4,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"travel_count": 2,
|
||||
"general_count": 2,
|
||||
"doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc",
|
||||
"doc_ok": true
|
||||
}
|
||||
```
|
||||
|
||||
**纯差旅发票(跳过出库单生成):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"invoice_count": 3,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"travel_count": 3,
|
||||
"general_count": 0,
|
||||
"doc_ok": null,
|
||||
"doc_skipped": true,
|
||||
"doc_message": "差旅发票无需生成易耗品出库单"
|
||||
}
|
||||
```
|
||||
|
||||
**出库单生成失败时(CSV 等仍可能成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"invoice_count": 4,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"travel_count": 2,
|
||||
"general_count": 2,
|
||||
"doc_ok": false,
|
||||
"doc_error": "服务器未安装 pywin32,无法生成 Word 出库单"
|
||||
}
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `travel_count` | int | 差旅发票数量(高铁票/酒店住宿) |
|
||||
| `general_count` | int | 普通发票数量 |
|
||||
| `doc_ok` | bool/null | `true`=成功,`false`=失败,`null`=已跳过(纯差旅发票) |
|
||||
| `doc_skipped` | bool | 是否因纯差旅发票而跳过出库单生成 |
|
||||
| `doc_message` | string | 跳过时的提示信息 |
|
||||
|
||||
---
|
||||
|
||||
### 6. SSE 日志流
|
||||
|
||||
```
|
||||
GET /api/logs/<session_id>
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
**日志行格式:**
|
||||
|
||||
```
|
||||
data: 2026-05-26 12:00:01 [INFO ] extractor: 正在提取发票...
|
||||
```
|
||||
|
||||
**结束消息:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": { }
|
||||
}
|
||||
```
|
||||
|
||||
`result` 结构取决于触发来源:
|
||||
|
||||
| 来源 | 典型字段 |
|
||||
|------|----------|
|
||||
| `/api/process` | `ok`, `elapsed`, `invoice_count`, `csv_url`, `travel_count`, `general_count`, `doc_url`, `doc_ok`, `doc_skipped`, `doc_error` |
|
||||
| `/api/submit-financial` | `ok`, `submit_ok`, `submit_error` |
|
||||
|
||||
> SSE 超时时间为 10 分钟(600 秒)。
|
||||
|
||||
---
|
||||
|
||||
### 7. 下载文件
|
||||
### 4. 下载文件
|
||||
|
||||
```
|
||||
GET /api/download/<session_id>/<filename>
|
||||
@@ -237,8 +126,12 @@ GET /api/download/<session_id>/<filename>
|
||||
|
||||
| 文件名 | 说明 |
|
||||
|--------|------|
|
||||
| `invoice_summary.csv` | 发票汇总(含 LLM 识别结果) |
|
||||
| `invoice_summary.csv` | 发票汇总 |
|
||||
| `payment_records.csv` | 支付记录 |
|
||||
| `易耗品、出库单.doc` | 自动填写的出库单 |
|
||||
| `travel_applications.json` | 差旅申请信息 |
|
||||
| `result.json` | 处理结果 |
|
||||
| `agent_state.json` | Agent 会话状态 |
|
||||
|
||||
**错误:**
|
||||
|
||||
@@ -250,6 +143,56 @@ HTTP `404`。`filename` 仅允许会话目录内的文件名(防止路径穿
|
||||
|
||||
---
|
||||
|
||||
### 5. 移动端上传页面
|
||||
|
||||
```
|
||||
GET /mobile/<session_id>
|
||||
```
|
||||
|
||||
返回移动端 HTML 页面。
|
||||
|
||||
---
|
||||
|
||||
### 6. 移动端上传图片
|
||||
|
||||
```
|
||||
POST /api/mobile-upload/<session_id>
|
||||
Content-Type: multipart/form-data
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| file | File | 图片文件 |
|
||||
|
||||
逻辑与 `POST /api/upload/<session_id>` 相同。
|
||||
|
||||
---
|
||||
|
||||
### 7. 获取会话配置
|
||||
|
||||
```
|
||||
GET /api/config/<session_id>
|
||||
```
|
||||
|
||||
获取当前会话的配置,供前端回填表单。优先读取会话目录下的 `config.json`,未找到则使用项目全局配置。
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "",
|
||||
"password": "",
|
||||
"default_name": "",
|
||||
"default_card_no": "",
|
||||
"default_person_id": "",
|
||||
"consumable_storage": ""
|
||||
}
|
||||
```
|
||||
|
||||
注意:`password` 字段始终返回空字符串。
|
||||
|
||||
---
|
||||
|
||||
### 8. 获取发票数据
|
||||
|
||||
```
|
||||
@@ -260,7 +203,7 @@ GET /api/data/<session_id>
|
||||
|
||||
```json
|
||||
{
|
||||
"csv_filename": "invoice_summary.csv",
|
||||
"csv_filename": "payment_records.csv",
|
||||
"fields": [
|
||||
"序号", "发票号码", "开票日期", "项目名称", "规格型号",
|
||||
"价税合计", "销售方名称", "人员姓名", "刷卡日期",
|
||||
@@ -277,6 +220,8 @@ GET /api/data/<session_id>
|
||||
}
|
||||
```
|
||||
|
||||
读取优先级:`payment_records.csv` → `invoice_summary.csv` → 任意 `.csv` 文件。
|
||||
|
||||
- `fields`:列顺序
|
||||
- `data[].__row`:内部行索引(保存时不需要提交,服务端按数组顺序写回)
|
||||
|
||||
@@ -350,7 +295,82 @@ Content-Type: application/json
|
||||
|
||||
---
|
||||
|
||||
### 10. 提交到财务系统
|
||||
### 10. 启动管道处理(仅发票提取)
|
||||
|
||||
```
|
||||
POST /api/process/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
> 此接口仅执行发票提取和 LLM 识别,**不会**触发 Agent 多轮校验,也**不会**自动提交到财务系统。如需完整的 Agent 校验流程,请使用 `/api/agent/process`。
|
||||
|
||||
**请求体:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| username | string | 否 | 财务系统工号 |
|
||||
| password | string | 否 | 登录密码 |
|
||||
| default_name | string | 否 | 默认报销人姓名 |
|
||||
| default_card_no | string | 否 | 默认公务卡号 |
|
||||
| default_person_id | string | 否 | 默认人员编号 |
|
||||
| consumable_storage | string | 否 | 出库单存放地点 |
|
||||
|
||||
**处理内容:**
|
||||
|
||||
1. 从会话目录 PDF 提取发票信息 → `invoice_summary.csv`
|
||||
2. 对支付截图多模态 LLM 识别,回填刷卡字段
|
||||
3. 根据发票类型自动分类:差旅发票(高铁票/酒店住宿)不生成出库单;普通发票从模板复制并自动填写
|
||||
|
||||
配置会写入 `src/web/uploads/<session_id>/config.json`。
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
处理在后台线程执行,进度与结果通过 `GET /api/logs/<session_id>`(SSE)获取。
|
||||
|
||||
**SSE 完成时 `result` 示例(成功):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"elapsed": "45.2s",
|
||||
"invoice_count": 4,
|
||||
"csv_url": "/api/download/<session_id>/invoice_summary.csv",
|
||||
"travel_count": 2,
|
||||
"general_count": 2,
|
||||
"doc_url": "/api/download/<session_id>/%E6%98%93%E8%80%97%E5%93%81%E3%80%81%E5%87%BA%E5%BA%93%E5%8D%95.doc",
|
||||
"doc_ok": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 11. SSE 日志流
|
||||
|
||||
```
|
||||
GET /api/logs/<session_id>
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
每 0.5 秒轮询 4 个日志文件,通过文件 size 增量检测新内容:
|
||||
|
||||
| 文件 | 内容 |
|
||||
|------|------|
|
||||
| `session.log` | 普通日志(extractor、llm_extractor、matcher、pipeline、bot、agent、validator 等模块) |
|
||||
| `file_events.log` | 文件处理进度事件 |
|
||||
| `llm_stream.log` | LLM 流式输出 |
|
||||
| `agent_events.log` | Agent 调度事件 |
|
||||
|
||||
检测到 `result.json` 存在时,读取后发送 `done` 事件并断开连接。
|
||||
|
||||
**SSE 超时:** 600 秒。
|
||||
|
||||
---
|
||||
|
||||
### 12. 提交到财务系统
|
||||
|
||||
```
|
||||
POST /api/submit-financial/<session_id>
|
||||
@@ -358,13 +378,12 @@ POST /api/submit-financial/<session_id>
|
||||
|
||||
**前置条件:**
|
||||
|
||||
- 会话目录存在 `config.json`(由 `/api/process` 写入),否则返回 `400`
|
||||
- 存在可用的发票 CSV(通常为 `invoice_summary.csv`)
|
||||
- 会话目录存在 `config.json`,否则返回 `400`
|
||||
- 存在可用的发票 CSV(通常为 `invoice_summary.csv` 或 `payment_records.csv`)
|
||||
|
||||
**说明:**
|
||||
|
||||
- 前端一般在提交前调用 `/api/save` 保存表格修改
|
||||
- 本接口**不会**自动执行发票提取或 LLM 识别
|
||||
- 根据发票类型选择填报模式:纯差旅发票走差旅报销流程,含普通发票走普通报销流程
|
||||
|
||||
**响应(立即):**
|
||||
@@ -389,28 +408,322 @@ POST /api/submit-financial/<session_id>
|
||||
|
||||
---
|
||||
|
||||
### 11. 移动端上传页面
|
||||
## Agent 多轮校验流程
|
||||
|
||||
```
|
||||
GET /mobile/<session_id>
|
||||
Agent 是系统的调度中枢,负责编排信息提取、规则校验、补充材料请求的完整流程。推荐使用 `/api/agent/process` 作为主入口。
|
||||
|
||||
### Agent 状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> IDLE
|
||||
IDLE --> EXTRACTING: 启动处理
|
||||
EXTRACTING --> READY: can_submit == true
|
||||
EXTRACTING --> AWAITING_SUPPLEMENT: can_submit == false
|
||||
EXTRACTING --> ERROR: 异常 / 轮次超限
|
||||
READY --> SUBMITTING: _emit_ready_and_submit()
|
||||
SUBMITTING --> DONE: 财务提交完成
|
||||
AWAITING_SUPPLEMENT --> EXTRACTING: 用户补充文件/文字
|
||||
AWAITING_SUPPLEMENT --> READY: 用户强制提交
|
||||
|
||||
note right of EXTRACTING
|
||||
LLM 提取 + validator 校验\n最多 3 次重试
|
||||
end note
|
||||
```
|
||||
|
||||
返回移动端 HTML 页面。扫码上传的图片与 PC 端共用同一会话目录;PC 通过轮询 `GET /api/files/<session_id>` 同步文件列表。
|
||||
### 13. 获取 Agent 会话状态
|
||||
|
||||
```
|
||||
GET /api/agent/state/<session_id>
|
||||
```
|
||||
|
||||
**响应:**
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "a1b2c3d4e5f6",
|
||||
"state": "extracting",
|
||||
"rounds": 1,
|
||||
"max_rounds": 5,
|
||||
"invoice_type": "travel",
|
||||
"extracted_info": { ... },
|
||||
"validation_reports": [ ... ],
|
||||
"user_supplements": [ ... ],
|
||||
"error_message": ""
|
||||
}
|
||||
```
|
||||
|
||||
**状态值:**
|
||||
|
||||
| 状态 | 含义 |
|
||||
|------|------|
|
||||
| `idle` | 初始状态 |
|
||||
| `extracting` | LLM 正在分析文件 |
|
||||
| `awaiting_supplement` | 信息不完整,等待用户补充 |
|
||||
| `ready` | 信息完整,可以提交 |
|
||||
| `submitting` | 正在提交到财务系统 |
|
||||
| `done` | 流程结束 |
|
||||
| `error` | 出错 |
|
||||
|
||||
---
|
||||
|
||||
### 12. 移动端上传图片
|
||||
### 14. 启动 Agent 多轮处理(主入口)
|
||||
|
||||
```
|
||||
POST /api/mobile-upload/<session_id>
|
||||
Content-Type: multipart/form-data
|
||||
POST /api/agent/process/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| file | File | 图片文件 |
|
||||
**请求体:**
|
||||
|
||||
逻辑与 `POST /api/upload/<session_id>` 相同。
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| username | string | 否 | 财务系统工号 |
|
||||
| password | string | 否 | 登录密码 |
|
||||
| default_name | string | 否 | 默认报销人姓名 |
|
||||
| default_card_no | string | 否 | 默认公务卡号 |
|
||||
| default_person_id | string | 否 | 默认人员编号 |
|
||||
| consumable_storage | string | 否 | 出库单存放地点 |
|
||||
|
||||
**处理流程:**
|
||||
|
||||
1. 发票提取(同 `/api/process`)
|
||||
2. Agent 调度 LLM 分析提取结果
|
||||
3. validator 规则校验(最多 3 次校验-修正循环)
|
||||
4. LLM 语义判断信息完整性(`can_submit` 字段)
|
||||
5. 校验通过 → 自动提交到财务系统
|
||||
6. 校验未通过 → 等待用户补充材料
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
**SSE done 事件 - 信息完整(成功提交):**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": true,
|
||||
"agent_ready": true,
|
||||
"submit_ok": true,
|
||||
"round": 1,
|
||||
"message": "信息完整,已自动提交到财务系统"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**SSE done 事件 - 信息完整但提交失败:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": true,
|
||||
"agent_ready": true,
|
||||
"submit_ok": false,
|
||||
"submit_error": "提交失败原因",
|
||||
"round": 1,
|
||||
"message": "校验通过但提交失败"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**SSE done 事件 - 需补充材料:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": true,
|
||||
"agent_ready": false,
|
||||
"agent_state": "awaiting_supplement",
|
||||
"round": 1,
|
||||
"waiting_for_supplement": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**SSE done 事件 - 处理失败:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": "未提取到任何发票数据"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 15. 补充文件后重新分析
|
||||
|
||||
```
|
||||
POST /api/agent/supplement/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
在 Agent 请求补充材料后,用户上传新文件并调用此接口触发重新分析。
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"files": ["补充材料1.pdf", "补充材料2.jpg"]
|
||||
}
|
||||
```
|
||||
|
||||
**处理流程:**
|
||||
|
||||
1. 记录补充文件
|
||||
2. 重新提取所有发票(包含新文件)
|
||||
3. 加载上一轮分析结果作为历史上下文
|
||||
4. 重新执行 Agent 校验
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
**SSE done 事件:** 同上(可能仍需补充或校验通过自动提交)。
|
||||
|
||||
**错误:**
|
||||
|
||||
```json
|
||||
{ "error": "未找到 Agent 状态" }
|
||||
```
|
||||
|
||||
HTTP `404`(未先调用 `/api/agent/process` 或 Agent 状态已丢失)。
|
||||
|
||||
---
|
||||
|
||||
### 16. 通过文字补充信息
|
||||
|
||||
```
|
||||
POST /api/agent/user-supplement/<session_id>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
用户通过对话方式提供补充信息,LLM 解析后更新已提取的信息并重新校验。
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "报销人是张三,公务卡号是 6228480402564890001"
|
||||
}
|
||||
```
|
||||
|
||||
**处理流程:**
|
||||
|
||||
1. LLM 分析用户文字,提取需要更新的字段
|
||||
2. 合并到已提取的信息中
|
||||
3. 保存到缓存
|
||||
4. 重新执行 Agent 校验
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
**SSE done 事件:** 同上(可能仍需补充或校验通过自动提交)。
|
||||
|
||||
**错误:**
|
||||
|
||||
```json
|
||||
{ "error": "请输入补充信息" }
|
||||
```
|
||||
|
||||
HTTP `400`(文本为空)。
|
||||
|
||||
---
|
||||
|
||||
### 17. 强制提交,跳过校验
|
||||
|
||||
```
|
||||
POST /api/agent/force-submit/<session_id>
|
||||
```
|
||||
|
||||
当 Agent 校验未通过或出错时,用户可选择强制提交,跳过所有校验直接提交到财务系统。
|
||||
|
||||
**处理流程:**
|
||||
|
||||
1. 将 Agent 状态设为 `READY`
|
||||
2. 执行财务提交
|
||||
|
||||
**响应(立即):**
|
||||
|
||||
```json
|
||||
{ "status": "started" }
|
||||
```
|
||||
|
||||
**SSE done 事件:**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": {
|
||||
"ok": true,
|
||||
"submit_ok": true,
|
||||
"submit_error": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SSE 事件类型
|
||||
|
||||
### Agent 事件
|
||||
|
||||
通过 `agent_events.log` 轮询推送:
|
||||
|
||||
| 事件类型 | 数据结构 | 触发条件 |
|
||||
|---|---|---|
|
||||
| `agent_state_change` | `{type, state, round, attempt, message}` | 状态切换 |
|
||||
| `agent_ready` | `{type, round, message}` | 双重校验通过 |
|
||||
| `agent_request_supplement` | `{type, round, missing_fields, missing_materials, semantic_issues, suggestion}` | 校验未通过 |
|
||||
| `agent_supplement_received` | `{type, files}` | 收到用户补充 |
|
||||
| `agent_force_submit` | `{type, message}` | 用户强制提交 |
|
||||
| `agent_error` | `{type, message}` | 提取失败 |
|
||||
| `agent_max_rounds` | `{type, message}` | 达到最大轮次 |
|
||||
|
||||
### 文件进度事件
|
||||
|
||||
通过 `file_events.log` 轮询推送:
|
||||
|
||||
| 事件类型 | 数据结构 | 触发条件 |
|
||||
|---|---|---|
|
||||
| `file_progress` | `{type, file, status, summary?, error?}` | 文件处理状态变更 |
|
||||
|
||||
`status` 取值: `processing` / `done` / `cached` / `error`
|
||||
|
||||
### LLM 流式事件
|
||||
|
||||
通过 `llm_stream.log` 轮询推送:
|
||||
|
||||
| 事件类型 | 数据结构 | 触发条件 |
|
||||
|---|---|---|
|
||||
| `llm_stream` | `{type, phase, content?}` | LLM 输出流 |
|
||||
|
||||
`phase` 取值: `start` / `reasoning` / `chunk` / `end` / `error`
|
||||
|
||||
### 完成事件
|
||||
|
||||
SSE 检测到 `result.json` 后直接发送:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "done",
|
||||
"result": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -418,9 +731,9 @@ Content-Type: multipart/form-data
|
||||
|
||||
| HTTP | 场景 |
|
||||
|------|------|
|
||||
| 400 | 参数缺失、未找到配置等 |
|
||||
| 404 | `session_id` 不存在、文件不存在 |
|
||||
| 500 | CSV 读取失败等内部错误 |
|
||||
| 400 | 参数缺失、未找到配置、文本为空等 |
|
||||
| 404 | `session_id` 不存在、文件不存在、Agent 状态丢失 |
|
||||
| 500 | CSV 读取失败、服务未初始化等内部错误 |
|
||||
|
||||
统一错误体:
|
||||
|
||||
@@ -447,38 +760,81 @@ Content-Type: multipart/form-data
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PC as PC 端
|
||||
participant Server as Server
|
||||
participant Mobile as 移动端
|
||||
participant Word as Word COM
|
||||
participant F as 前端
|
||||
participant S as SSE连接
|
||||
participant B as 后端线程
|
||||
participant A as Agent调度器
|
||||
|
||||
PC->>Server: POST /api/session
|
||||
Server-->>PC: session_id
|
||||
F->>B: POST /api/session
|
||||
B-->>F: session_id
|
||||
|
||||
PC->>Server: POST /api/upload/{sid}
|
||||
PC->>Server: POST /api/process/{sid}
|
||||
Note over Server: PDF 提取 + LLM 识别 + 写 config.json
|
||||
alt 含普通发票
|
||||
Server->>Word: 从模板复制并填写出库单
|
||||
else 纯差旅发票
|
||||
Note over Server: 跳过出库单生成
|
||||
F->>B: POST /api/upload/{sid} (多次)
|
||||
F->>B: POST /api/agent/process/{sid}
|
||||
B-->>F: {status: "started"}
|
||||
|
||||
F->>S: GET /api/logs/{sid}
|
||||
|
||||
Note over B,A: 后台线程启动
|
||||
B->>A: extract_invoices()
|
||||
S-->>F: file_progress (processing/done)
|
||||
S-->>F: llm_stream (start/chunk/end)
|
||||
S-->>F: agent_state_change (extracting)
|
||||
|
||||
Note over A: LLM 提取 + validator 校验<br/>最多 3 次重试
|
||||
|
||||
alt 信息完整
|
||||
A->>A: state → READY
|
||||
A->>A: _emit_ready_and_submit()
|
||||
S-->>F: agent_ready
|
||||
S-->>F: done (submit_ok=true)
|
||||
F->>F: es.close()
|
||||
else 信息不完整
|
||||
A->>A: state → AWAITING_SUPPLEMENT
|
||||
S-->>F: agent_request_supplement
|
||||
S-->>F: done (waiting_for_supplement=true)
|
||||
F->>F: es.close()
|
||||
|
||||
F->>B: 上传补充文件或输入文字
|
||||
alt 文件补充
|
||||
F->>B: POST /api/agent/supplement/{sid}
|
||||
else 文字补充
|
||||
F->>B: POST /api/agent/user-supplement/{sid}
|
||||
end
|
||||
B-->>F: {status: "started"}
|
||||
F->>S: GET /api/logs/{sid}
|
||||
|
||||
Note over A: 重新分析 + 校验
|
||||
|
||||
alt 仍不完整
|
||||
S-->>F: agent_request_supplement
|
||||
S-->>F: done (waiting=true)
|
||||
F->>F: es.close()
|
||||
Note over F: 可继续补充或强制提交
|
||||
else 完整
|
||||
A->>A: state → READY
|
||||
A->>A: _emit_ready_and_submit()
|
||||
S-->>F: agent_ready
|
||||
S-->>F: done (submit_ok=true)
|
||||
F->>F: es.close()
|
||||
end
|
||||
|
||||
alt 强制提交
|
||||
F->>B: POST /api/agent/force-submit/{sid}
|
||||
B-->>F: {status: "started"}
|
||||
F->>S: GET /api/logs/{sid}
|
||||
S-->>F: agent_force_submit
|
||||
S-->>F: done
|
||||
F->>F: es.close()
|
||||
end
|
||||
end
|
||||
Server-->>PC: SSE done (csv_url, doc_url, ...)
|
||||
|
||||
PC->>Server: GET /api/data/{sid}
|
||||
Server-->>PC: fields + data
|
||||
PC->>Server: POST /api/save/{sid}
|
||||
Note over Server: 更新 CSV,重新生成出库单
|
||||
Server-->>PC: doc_url
|
||||
F->>B: GET /api/data/{sid}
|
||||
B-->>F: fields + data
|
||||
F->>B: POST /api/save/{sid}
|
||||
Note over B: 更新 CSV,重新生成出库单
|
||||
B-->>F: doc_url
|
||||
|
||||
PC->>Server: GET /api/download/{sid}/易耗品、出库单.doc
|
||||
|
||||
PC->>Server: POST /api/submit-financial/{sid}
|
||||
Note over Server: Playwright 浏览器填报
|
||||
Server-->>PC: SSE done (submit_ok)
|
||||
|
||||
Mobile->>Server: POST /api/mobile-upload/{sid}
|
||||
PC->>Server: GET /api/files/{sid} (轮询)
|
||||
F->>B: GET /api/download/{sid}/易耗品、出库单.doc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -143,7 +143,7 @@ uv run python src/web/app.py
|
||||
|
||||
### 4.7 提交到财务系统
|
||||
|
||||
确认数据无误后,点击"🚀 提交到财务系统"按钮,系统自动:
|
||||
确认数据无误后,点击"提交到财务系统"按钮,系统自动:
|
||||
|
||||
1. 登录信息门户
|
||||
2. 进入财务系统
|
||||
|
||||
Reference in New Issue
Block a user