# 上传图片与文字识别实现说明 本文说明平台中 **设计器/预览聊天** 场景下:**图片如何上传、如何随消息发给 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`) | 能力 | 说明 | |------|------| | 选择文件 | 隐藏 ``,回形针触发;`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 等运维说明 | --- 文档版本:与当前仓库实现一致时可随代码迭代更新本文。