feat: v4 multimodal chat input, multi-format support, and annotation detection
- Replace st.chat_input with st-multimodal-chatinput (Ctrl+V paste, drag-drop, file button) - Extract _process_uploaded_file() shared handler (eliminates ~70 duplicated lines) - Add XLSX (openpyxl), XLS (xlrd), DOC (olefile) parsers to file_parser.py - Add backend/annotation_detector.py: circle detection (HoughCircles) + arrow detection (HoughLinesP clustering) + OCR correlation + LLM context formatting - Add annotation_result field to AgentState with session persistence - Wire annotation detection into process_input and _format_ocr_context - Add 11 new tests: 7 annotation detector + 4 multi-format parser - Update all docs: CLAUDE.md, README.md, CODE_GUIDE.md, ROADMAP.md
This commit is contained in:
@@ -20,7 +20,7 @@ STREAMLIT_SERVER_HEADLESS=true streamlit run app.py --server.port 8501
|
||||
|
||||
## 当前配置(.env)
|
||||
|
||||
- **OCR**: EasyOCR(优先,ch_sim+en)→ PaddleOCR(回退),两者均未安装时仅返回图片元信息
|
||||
- **OCR**: PaddleOCR(精确识别首选,ppocr-v4)→ EasyOCR(回退,ch_sim+en),两者均未安装时仅返回图片元信息
|
||||
- **LLM**: `cloud` / `anthropic` → MiniMax Anthropic 兼容 API (`MiniMax-M2.7`)
|
||||
- Base URL: `https://api.minimaxi.com/anthropic`
|
||||
- 认证: Anthropic SDK 自动读取 `ANTHROPIC_API_KEY`(fallback `OPENAI_API_KEY`)
|
||||
@@ -55,8 +55,10 @@ agent/graph.py (LangGraph 状态机)
|
||||
├──► backend/logger.py 集中日志: JSON + trace_id + llm.log/app.log 分离
|
||||
├──► backend/rag_adapter.py 语义搜索: ChromaDB + SentenceTransformer
|
||||
├──► backend/error_kb.py 错误知识库: 指纹去重 + ChromaDB 持久化
|
||||
├──► backend/file_parser.py 文件解析: PDF/DOCX/图片/文本
|
||||
├──► backend/file_parser.py 文件解析: PDF/DOCX/XLSX/XLS/DOC/图片/文本
|
||||
├──► backend/layout_analyzer.py A4布局分析: OCR + 行分组 + JRXML行匹配
|
||||
├──► backend/ocr_extractor.py OCR字段精确提取: 4策略优先级 + 置信度
|
||||
├──► backend/annotation_detector.py 批注检测: 圈选(HoughCircles) + 箭头(HoughLinesP) + OCR关联
|
||||
├──► backend/validation.py HTTP 客户端: POST /validate
|
||||
├──► backend/session.py 会话持久化: JSON 文件 CRUD
|
||||
└──► validation_service/ 独立 FastAPI: 结构检查 + XSD 校验
|
||||
@@ -67,7 +69,7 @@ agent/graph.py (LangGraph 状态机)
|
||||
| 文件 | 职责 | 修改频率 |
|
||||
|------|------|---------|
|
||||
| `app.py` | Streamlit UI 入口,聊天界面 + 侧边栏 + 下载 + 文件上传 | **高** |
|
||||
| `agent/state.py` | AgentState 类型定义(~24 字段,含 pending_failure_context) | 低 |
|
||||
| `agent/state.py` | AgentState 类型定义(~26 字段,含 pending_failure_context / annotation_result) | 低 |
|
||||
| `agent/nodes.py` | 14 个工作流节点 + 流式生成 + 错误记录 | **高** |
|
||||
| `agent/graph.py` | 状态图编译 + 路由函数(预览跳过验证) | 中 |
|
||||
| `prompts/loader.py` | Prompt 加载器(从 .md 文件热重载) | 低 |
|
||||
@@ -76,8 +78,10 @@ agent/graph.py (LangGraph 状态机)
|
||||
| `backend/logger.py` | 集中日志模块:JSON 格式化 + trace_id + 独立 llm.log | 低 |
|
||||
| `backend/rag_adapter.py` | RAGSearcher 单例,语义搜索接口 | 中 |
|
||||
| `backend/error_kb.py` | ErrorKB — 错误指纹去重 + ChromaDB 持久化 + 语义检索 | 中 |
|
||||
| `backend/file_parser.py` | 文件解析: PDF/DOCX/图片(EasyOCR→PaddleOCR回退)/文本 | 中 |
|
||||
| `backend/file_parser.py` | 文件解析: PDF/DOCX/XLSX/XLS/DOC/图片(EasyOCR→PaddleOCR回退)/文本 | 中 |
|
||||
| `backend/layout_analyzer.py` | A4模板分析: 比例检测/EasyOCR→PaddleOCR元素提取/行分组/JRXML行匹配 | 中 |
|
||||
| `backend/ocr_extractor.py` | OCR字段精确提取: 4策略(exact→kv_pair→regex→table_match) + 置信度 | 中 |
|
||||
| `backend/annotation_detector.py` | 批注检测: 圈选(cv2 HoughCircles) + 箭头(HoughLinesP聚类) + OCR关联 + LLM格式化 | 中 |
|
||||
| `backend/embeddings.py` | 嵌入模型工厂 (HuggingFace/OpenAI) | 低 |
|
||||
| `backend/validation.py` | 验证服务 HTTP 客户端 | 低 |
|
||||
| `backend/session.py` | 会话 JSON 文件 CRUD | 低 |
|
||||
@@ -156,6 +160,37 @@ agent/graph.py (LangGraph 状态机)
|
||||
- `@log_node` / `@_log_route` — 装饰器自动记录节点和路由
|
||||
- 日志分离: `logs/app.log` (业务) + `logs/llm.log` (AI 调用)
|
||||
|
||||
## 新增功能 (v3/v4)
|
||||
|
||||
### OCR 单据字段精确提取 (v3)
|
||||
- `backend/ocr_extractor.py` — 4 策略优先级提取: exact_match → kv_pair → regex → table_match
|
||||
- PaddleOCR 首次识别后将原始结果(含所有文本元素 + bbox坐标)持久化
|
||||
- `_format_ocr_context()` — 将 OCR 结果(字段 + 原始元素坐标)格式化为 LLM prompt 注入
|
||||
- OCR 结果在 `modify_jrxml` 和 `generate` 节点中自动注入 prompt
|
||||
- `process_input` 节点在上传图片时自动触发 OCR 字段提取
|
||||
- 结果持久化到会话文件(`save_session_node` / `load_session_node`)
|
||||
|
||||
### 多模态聊天输入 + 多格式文件 (v4)
|
||||
- `app.py` — `st.chat_input` 替换为 `st_multimodal_chatinput`(支持 Ctrl+V 粘贴 + 拖拽 + 文件按钮)
|
||||
- `_process_uploaded_file()` — 提取共享文件处理逻辑(侧边栏 + 聊天共用,消除 ~70 行重复代码)
|
||||
- 新增文件格式支持: XLSX (openpyxl)、XLS (xlrd)、DOC (olefile)
|
||||
- 剪贴板粘贴文件通过 base64 解码 + MIME type → 扩展名推断
|
||||
- 侧边栏上传器类型列表中新增 xlsx/xls/doc
|
||||
|
||||
### 批注检测 (v4)
|
||||
- `backend/annotation_detector.py` — 识别用户在手写单据上的圈选和箭头标记
|
||||
- **圆圈检测**: 红色通道增强 → HoughCircles → 圆形度验证
|
||||
- **箭头检测**: Canny边缘 → HoughLinesP → 线段方向聚类 → 端点边缘密度判定方向
|
||||
- **OCR 关联**: 批注与附近 OCR 文本元素关联(15% 图片尺寸内)
|
||||
- **LLM 注入**: `format_annotation_context()` 将批注结果格式化为中文提示
|
||||
- `process_input` 节点在 OCR 提取后自动运行批注检测
|
||||
- `annotation_result` 字段持久化到 AgentState + 会话文件
|
||||
|
||||
### OCR 上下文提示增强 (v3/v4)
|
||||
- `prompts/modification.md` — 新增 `{ocr_context}` 占位符
|
||||
- `modify_jrxml` 节点 — 将 OCR 上下文注入 modification prompt
|
||||
- OCR 上下文包含: 结构化字段、全部文本元素(含坐标)、批注检测结果
|
||||
|
||||
## 已知注意点
|
||||
|
||||
- **Anthropic SDK**: 使用原始 `anthropic` 包(非 `langchain-anthropic`),因为需要直连 MiniMax 兼容端点。API Key 优先读 `ANTHROPIC_API_KEY`,fallback `OPENAI_API_KEY`。Anthropic SDK 会自动将 key 放入 `x-api-key` header。
|
||||
@@ -165,7 +200,10 @@ agent/graph.py (LangGraph 状态机)
|
||||
- **验证服务结构检查**: 字段引用一致性 (`$F{field}` vs `<field>` 声明)、SQL SELECT 存在性、pageWidth/pageHeight/name 属性。
|
||||
- **XSD 校验可选**: 需要 `validation_service/schemas/jasperreport_7_0_6.xsd` 存在。
|
||||
- **rag 子模块**: 内部有独立的管线脚本(`batch_chunker.py` → `embed_chunks.py` → `import_to_chroma.py`),通常不需要在主项目中运行。
|
||||
- **OCR 引擎**: 优先使用 EasyOCR(Windows 兼容性更好,`pip install easyocr`),回退 PaddleOCR。两者均未安装时仅返回图片元信息,建议至少安装 EasyOCR。
|
||||
- **OCR 引擎**: 优先 PaddleOCR 2.9.x(精确识别,`pip install paddleocr`),回退 EasyOCR 1.7+。两者均未安装时仅返回图片元信息。PaddlePaddle 3.x 在 Windows 上有 ONEDNN bug,固定在 2.6.x。
|
||||
- **MAX_RETRY**: 默认 3 次。重试耗尽后 `pending_failure_context` 记录失败信息,下次用户输入时自动注入。
|
||||
- **验证最小内容检查**: 验证服务额外检查至少 1 个 `<band>` + 1 个 `<textField>` 或 `<staticText>`,拦截空壳 JRXML。
|
||||
- **torchvision**: `transformers` 库的懒加载需要 `torchvision`,已作为依赖安装。
|
||||
- **opencv-python-headless**: 批注检测(圈选/箭头)依赖,通过 `pip install -r requirements.txt` 安装。
|
||||
- **st-multimodal-chatinput**: Streamlit 聊天输入增强组件,替代 `st.chat_input`,支持粘贴/拖拽文件。返回 base64 编码文件内容。
|
||||
- **xlwt**: 仅在测试中使用(生成 .xls 测试文件)。
|
||||
|
||||
Reference in New Issue
Block a user