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>
This commit is contained in:
renjianbo
2026-05-06 01:37:13 +08:00
parent f33bc461ff
commit eabf90c496
171 changed files with 4906 additions and 445 deletions

View File

@@ -0,0 +1,137 @@
# 上传图片与文字识别实现说明
本文说明平台中 **设计器/预览聊天** 场景下:**图片如何上传、如何随消息发给 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 等运维说明 |
---
文档版本:与当前仓库实现一致时可随代码迭代更新本文。