Files
aiagent/docs/image-ocr/(红头)上传图片和识别的实现文档.md
renjianbo eabf90c496 feat: add AI学习助手 agent (KG+RAG ideal) and renshenguo feishu bot
- Add AI学习助手 agent creation script with all 39 tools, 3-layer KG+RAG memory
- Add renshenguo (人参果) feishu bot integration (app_service + ws_handler)
- Register renshenguo WS client in main.py startup
- Add RENSHENGUO_APP_ID / RENSHENGUO_APP_SECRET / RENSHENGUO_AGENT_ID config
- Reorganize docs from root into docs/ subdirectories
- Move startup scripts to scripts/startup/
- Various backend optimizations and tool improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-06 01:37:13 +08:00

138 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 上传图片与文字识别实现说明
本文说明平台中 **设计器/预览聊天** 场景下:**图片如何上传、如何随消息发给 Agent、后端如何读出图中文字(OCR)**,以及涉及的主要文件与配置。
---
## 1. 总体流程
```mermaid
sequenceDiagram
participant U as 浏览器
participant API as 后端 API
participant FS as 工作区磁盘
participant Q as消息队列
participant W as Worker
U->>API: POST /api/v1/uploads/preview (multipart, JWT)
API->>FS: 写入 uploads/preview/{user_id}/{uuid}_{safe_name}
API-->>U: relative_path, filename, content_type
U->>API: POST /api/v1/executions (input_data 含 query/USER_INPUT/attachments)
API->>Q: 入队执行任务
Q->>W: 执行 Agent 工作流
W->>W: LLM 可调用 file_read(relative_path)
W->>FS: 读同一工作区下文件
W-->>W: 图片走 OCR,返回 JSON content
```
要点:
1. **上传**只负责把文件落到 **与工作区根一致** 的目录,并返回 **相对路径**。
2. **识别**不发生在上传接口里,而是由工作流中的 **`file_read` 工具** 在读文件时,对图片扩展名走 **Tesseract OCR**。
3. **Agent 是否真的会去 `file_read`** 取决于提示词与工作流设计;前端会把路径写进 `USER_INPUT` / `query` 便于模型使用。
---
## 2. 前端实现(`frontend/src/components/AgentChatPreview.vue`)
| 能力 | 说明 |
|------|------|
| 选择文件 | 隐藏 `<input type="file">`,回形针触发;`accept` 含常见图片与文档扩展名。 |
| 拖放图片 | 在 `chat-input-area` 上监听 `dragenter/dragover/drop`;**仅处理图片**(与 `isImageFile` 一致),非图片可提示忽略。 |
| 上传 | `uploadPreviewFiles`:`FormData` + `POST /api/v1/uploads/preview`,需登录(JWT)。 |
| 本地缩略图 | 图片用 `URL.createObjectURL(file)` 作为 `thumbUrl`;发送成功且消息仍引用时延迟 `revoke`,避免 blob 提前失效。 |
| 随消息发送 | `POST /api/v1/executions`,`input_data` 包含:`USER_INPUT`、`query`(合并用户话 +附件路径说明)、`user_id`(预览会话)、`attachments`(含 `relative_path`、`filename`、`content_type` 等)。 |
| 历史回显 | `GET /api/v1/agents/{id}/preview-chat-history` 返回轮次中的 `attachments`;图片再通过 `GET /api/v1/uploads/preview/file?file_path=...` 拉 blob 生成缩略图。 |
| 交互 | 消息内多图横向滚动、缩略图点击放大(对话框)。 |
---
## 3. 后端:上传与下载
**文件**:`backend/app/api/uploads.py`
| 接口 | 方法 | 作用 |
|------|------|------|
| `/api/v1/uploads/preview` | `POST` | 单文件上传;需 JWT。保存目录:`{LOCAL_FILE_TOOLS_ROOT}/uploads/preview/{当前用户 id}/`。文件名经 `_safe_filename` 处理,前缀短 UUID 防冲突。响应:`relative_path`(相对工作区根)、`filename`、`size`、`content_type`。超大返回413,上限见 `LOCAL_FILE_WRITE_MAX_BYTES`。 |
| `/api/v1/uploads/preview/file` | `GET` | 按 `file_path`(即 `relative_path`)读文件;**仅允许** `uploads/preview/{当前用户 id}/` 前缀,防止越权。用于历史消息图片回显。 |
**工作区根**:与 `file_read` / `file_write` 一致,由 `LOCAL_FILE_TOOLS_ROOT` 配置;未配置时默认为 **仓库根目录**(见 `builtin_tools._local_file_workspace_root`)。
---
## 4. 后端:图片识别(OCR)
**文件**:`backend/app/services/builtin_tools.py`
| 项目 | 说明 |
|------|------|
| 工具名 | `file_read`(异步,返回 JSON 字符串) |
| 图片扩展名 | `.png` `.jpg` `.jpeg` `.webp` `.gif` `.bmp` `.tif` `.tiff` |
| 识别实现 | `_read_image_ocr_sync`:`PIL.Image` 打开图片,`pytesseract.image_to_string`,语言依次尝试 **`chi_sim+eng`**、**`eng`**。 |
| Tesseract 路径 | `settings.TESSERACT_CMD` 非空时赋值给 `pytesseract.pytesseract.tesseract_cmd`。 |
| 语言包目录 | `settings.TESSERACT_TESSDATA_DIR`;若为空且仓库根下存在 `tessdata/*.traineddata`,会自动使用该目录(`_tessdata_dir_for_ocr`)。 |
| 返回 | 成功:`extract_mode` 为 `image_ocr`,`content` 为识别文本(有 UTF-8 字节上限截断)。失败:JSON 内 `error` 字段说明原因(缺 Pillow/pytesseract、未找到 Tesseract、其它 OCR 异常)。 |
**依赖**(需安装在与 **Celery Worker** 相同的 Python 环境中):
- `Pillow`、`pytesseract`(见 `backend/requirements.txt`)
- 本机安装 **Tesseract 可执行文件**(Windows 常见路径:`C:/Program Files/Tesseract-OCR/tesseract.exe`)
**环境变量**(`backend/.env` / `env.example`):
- `TESSERACT_CMD`:指向 `tesseract.exe`
- `TESSERACT_TESSDATA_DIR`:可选,指向含 `chi_sim.traineddata` 的目录,中文效果更好
自检脚本:`backend/scripts/check_ocr_env.py`
---
## 5. 历史记录中的附件
**文件**:`backend/app/services/agent_workspace_chat_log.py`
- `fetch_agent_preview_chat_turns` 从已完成执行的 `input_data` 中解析 **`attachments`** 列表(`relative_path`、`filename`、`content_type`),随每轮 `user_text` / `agent_text` 返回给前端。
**文件**:`backend/app/api/agents.py`
- 响应模型 `PreviewChatTurnResponse` 含 **`attachments`** 字段。
---
## 6. 与 Agent / 工作流的关系
- 前端把附件路径写进 **`USER_INPUT` / `query`**,并保留结构化 **`attachments`**,便于工作流引擎提取 `user_query`及工具参数。
- **真正执行 OCR** 的时机是:工作流中 LLM(或工具节点)调用 **`file_read`**且传入上传返回的 **`relative_path`**。
- 若 Agent 未配置调用 `file_read` 或提示词未引导使用路径,则可能出现「已上传但助手仍说读不了」——需改 Agent 配置或提示词,而非仅改上传代码。
---
## 7. 常见问题
| 现象 | 可能原因 | 处理方向 |
|------|----------|----------|
| 上传 401 | 未登录或 token 过期 | 重新登录 |
| 上传 413 | 超过 `LOCAL_FILE_WRITE_MAX_BYTES` | 压缩图片或调大配置(需评估安全) |
| 助手仍提示缺 Pillow/pytesseract | Worker 使用的 venv 未安装依赖 | 在 `backend\venv` 执行 `pip install -r requirements.txt` 并 **重启 Celery** |
| 提示未找到 Tesseract | 未安装或未配置 PATH / `TESSERACT_CMD` | 安装 Tesseract 并配置 `.env` |
| 中文识别差 | 缺少 `chi_sim.traineddata` | 配置 `TESSERACT_TESSDATA_DIR` 或放置语言包到自动探测的 `tessdata/` |
| OpenAPI 无 uploads | 后端为旧进程 | 重启 API |
---
## 8. 相关文件索引
| 路径 | 作用 |
|------|------|
| `frontend/src/components/AgentChatPreview.vue` | 上传、拖放、发送、缩略图、历史回显 |
| `backend/app/api/uploads.py` | 预览上传、预览文件只读下载 |
| `backend/app/services/builtin_tools.py` | `file_read`、图片 OCR |
| `backend/app/services/agent_workspace_chat_log.py` | 历史轮次附带 `attachments` |
| `backend/app/api/agents.py` | `preview-chat-history` 响应模型 |
| `backend/scripts/check_ocr_env.py` | OCR 环境自检 |
| `启动的注意事项.md` | Redis、venv、重启 Celery 等运维说明 |
---
文档版本:与当前仓库实现一致时可随代码迭代更新本文。