# LaodingBot WebUI 开发技术与需求说明 > 版本: v1.0 > 目标读者: 下一个执行 WebUI 开发任务的 LLM / 前端工程师 > 依据: 当前后端已落地代码(`internal/transport/webui/bot.go`、`cmd/bot/main.go`、`internal/agent/orchestrator.go`) --- ## 1. 文档目标与范围 本说明用于指导“仅 WebUI 页面层/前端层”的开发,确保严格对接当前 LaodingBot 已开放的 WebUI 后端能力。 本期范围: - 支持纯文本对话 - 支持独立文档上传(上传后立即返回 `file_id`) - 支持“先上传文档,再发送文本提问”的两阶段交互 非本期范围: - 不改动后端接口语义 - 不引入新的后端路由 - 不实现复杂权限系统(当前后端无鉴权) - 不实现流式输出(当前为一次性响应) --- ## 2. 当前后端能力总览 ### 2.1 消息通道 后端已支持 `MESSAGE_CHANNEL=webui`,入口在 `cmd/bot/main.go`。 当通道为 `webui` 时: - 启动 HTTP 服务 - 暴露两个接口: - `POST /api/upload` - `POST /api/chat` ### 2.2 运行配置 关键环境变量(`configs/env.sample`): - `MESSAGE_CHANNEL=webui` - `WEBUI_LISTEN_ADDR=:8090` - `WEBUI_MAX_UPLOAD_MB=20` - `LLM_*` 相关配置(含文件模型切换) ### 2.3 文件上下文机制(非常关键) 当前后端使用 `chat_id + user_id` 作为会话键缓存 `file_id`: - 上传接口会把文件上传到 LLM,并把 `file_id` 缓存到该键 - 后续 `chat` 接口只要带同一组 `session_id`/`user_id`,就会自动消费缓存文件上下文 结论: - 前端必须稳定维护并复用 `session_id` 与 `user_id` - 两者变化会导致上传文件上下文丢失(从后端视角是新会话) --- ## 3. 后端 API 契约(以代码为准) ## 3.1 `POST /api/upload` 用途: - 独立上传文档 - 后端立即调用 LLM 文件上传并返回 `file_id` - 同时缓存到当前会话,供下一次聊天使用 请求: - Method: `POST` - Content-Type: `multipart/form-data` - Form 字段: - `file` (required) - `session_id` (optional,建议前端始终传) - `user_id` (optional,建议前端始终传) 响应 `200`: ```json { "file_id": "file-xxx", "file_ids": ["file-xxx"], "file_name": "report.pdf", "mime_type": "application/pdf", "size_bytes": 12345, "session_id": "sess_xxx", "user_id": "user_xxx" } ``` 错误响应: - `400`: - `{"error":"file is required"}` - `{"error":"invalid multipart form"}` - `{"error":"invalid file name"}` - `{"error":"empty file"}` - `{"error":"read file failed"}` - `413`: - `{"error":"file too large"}` - `500`: - `{"error":"upload failed"}` - `{"error":"upload succeeded but file_id is empty"}` --- ## 3.2 `POST /api/chat` 用途: - 发送纯文本消息 - 若该 `session_id + user_id` 下已有上传文件,会自动携带文件上下文进行问答 请求: - Method: `POST` - Content-Type: `application/json` - Body: ```json { "text": "请总结我上传的文档", "session_id": "sess_xxx", "user_id": "user_xxx" } ``` 响应 `200`: ```json { "reply": "...", "session_id": "sess_xxx", "user_id": "user_xxx" } ``` 错误响应: - `400`: - `{"error":"content-type must be application/json"}` - `{"error":"invalid json body"}` - `{"error":"text is required"}` - `405`: - `{"error":"method not allowed"}` - `500`: - `{"error":"chat failed"}` --- ## 4. WebUI 功能需求(给前端实现) ### 4.1 页面最小能力 必须实现: 1. 聊天消息列表 2. 文本输入框 + 发送按钮 3. 文件选择器 + 上传按钮 4. 当前会话标识展示(`session_id`、`user_id`) 5. 上传结果区(展示 `file_id`、文件名、大小、时间) 6. 错误提示区(接口失败、文件超限、网络错误) ### 4.2 会话策略 必须: - 首次进入页面时生成并持久化 `session_id`、`user_id`(例如 LocalStorage) - 每次请求都携带这两个字段 - 提供“重置会话”操作(清空本地 session/user 并重新生成) 建议 ID 规则: - `session_id`: `sess_` - `user_id`: `user_` ### 4.3 文件上传交互 必须: - 文件选择后显示基本信息(名称、大小、类型) - 点击上传后调用 `/api/upload` - 上传成功后将返回的 `file_id` 加入“已上传文件列表” - 上传失败时给出明确错误提示 建议: - 前端先做大小校验(默认 20MB,可配置) - 上传中禁用重复点击 ### 4.4 聊天交互 必须: - 发送前校验 `text` 非空 - 调用 `/api/chat` - 成功后追加机器人消息 - 失败后展示错误并保留用户输入 建议: - 支持回车发送(Shift+Enter 换行) - 增加“请求中”状态,避免并发多发 --- ## 5. 前端状态模型(建议) ```ts type UploadedFile = { fileId: string; fileName: string; mimeType: string; sizeBytes: number; uploadedAt: number; }; type ChatMessage = { id: string; role: "user" | "assistant" | "system"; content: string; createdAt: number; status?: "sending" | "sent" | "failed"; }; type AppState = { sessionId: string; userId: string; messages: ChatMessage[]; uploadedFiles: UploadedFile[]; uploading: boolean; chatting: boolean; lastError?: string; }; ``` 状态约束: - `uploading=true` 时不应再次触发上传 - `chatting=true` 时可选禁用发送(或允许排队) - 任何失败都要更新 `lastError` --- ## 6. 接口调用示例 ### 6.1 上传 ```bash curl -X POST http://localhost:8090/api/upload \ -F "session_id=sess_demo" \ -F "user_id=user_demo" \ -F "file=@./demo.pdf" ``` ### 6.2 聊天 ```bash curl -X POST http://localhost:8090/api/chat \ -H "Content-Type: application/json" \ -d '{"text":"这份文档主要讲了什么?","session_id":"sess_demo","user_id":"user_demo"}' ``` --- ## 7. 开发任务拆解(给下一个 LLM) 1. 初始化 WebUI 工程(技术栈自选,建议 React + TypeScript)。 2. 实现全局状态管理(至少管理 session/user/messages/uploads)。 3. 实现 API Client 层: - `uploadFile(formData)` - `sendChat(payload)` - 统一错误解析 4. 实现页面组件: - `ChatPanel` - `Composer` - `UploadPanel` - `SessionBadge` 5. 实现本地持久化: - 启动时恢复 `session_id`、`user_id` - 重置会话功能 6. 完成联调与自测。 --- ## 8. 验收标准 必须全部满足: 1. 纯文本聊天可用(无文件也能正常回复)。 2. 文档上传可用,返回并展示 `file_id`。 3. 上传后同会话提问能基于文档回答。 4. 刷新页面后会话 ID 不丢失(可继续提问)。 5. 文件超限、空消息、网络失败均有可见错误反馈。 6. 同一会话多文件上传后,后续问答仍可使用文件上下文。 --- ## 9. 已知限制与后续建议 当前后端限制(前端需知晓): - 无鉴权机制 - 无流式输出 - 上传 MIME 未做白名单限制 - 无会话文件列表接口(前端只能依赖本地记录) 后续建议(非本期必做): 1. 新增后端 `GET /api/session/files` 以便页面恢复历史上传列表。 2. 增加鉴权中间件(Bearer Token/JWT)。 3. 增加流式聊天接口(SSE/WebSocket)。 4. 增加上传文件类型白名单和病毒扫描。 --- ## 10. 对下一个 LLM 的执行指令模板 可直接复制给下一个 LLM: ```text 请基于 `doc/WebUI开发技术与需求说明.md` 实现 WebUI 前端,严格对接现有后端接口: - POST /api/upload - POST /api/chat 必须满足: 1) 纯文本聊天 2) 独立文档上传 3) 上传后同会话提问可利用文档上下文 4) session_id/user_id 持久化 5) 完整错误处理和可视化反馈 不允许修改后端接口语义;若需新增接口,请先输出变更提案,不直接改。 ```