# chat-bot **Repository Path**: ctllin/chat-bot ## Basic Information - **Project Name**: chat-bot - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-10 - **Last Updated**: 2026-08-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ChatBot — AI 助手 类似 [nanobot](https://github.com/HKUDS/nanobot) 的轻量级 AI Agent,使用 Spring Boot 3 + Vue 3 全栈构建,通过 OpenAI 兼容代理接入**智谱 GLM-5.2 与通义千问 Qwen3.6-Flash** 多模型。 参考 [java2ai.com (Spring AI Alibaba)](https://java2ai.com/docs/quick-start) 的架构风格。 ## 功能特性 - ✅ **对话聊天** — 同步 + SSE 流式响应,会话隔离,多模型随时切换 - ✅ **会话记忆** — `MessageWindowChatMemory`(窗口 20 条),多会话独立 - ✅ **工具调用** — Spring AI `@Tool` 注解,内置天气、时间工具,可自行扩展 - ✅ **多模型** — GLM-5.2 / Qwen3.6-Flash 自动注册为独立 `ChatClient`,前端一键切换 - ✅ **文件提取** — 上传文件自动提取文本内联为上下文(Apache Tika,PDF/DOCX/XLSX/PPTX/HTML/代码) - ✅ **OCR 增强** — PaddleOCR 识别图片与扫描版 PDF(仅空白页触发,服务不可用时优雅降级) - ✅ **文档转换** — .doc/.docx 批量转换为 PDF(LibreOffice),ZIP 打包下载 - ✅ **PDF 提取** — PDF 文本提取、OCR 增强与手动排版,前端可视化编辑器 + TTS 朗读 - ✅ **文本转语音** — `edge`(在线)/ `qwen3`(离线语音克隆)/ `melo`(中英混音 ONNX)三引擎 - ✅ **TTS 缓存** — Caffeine 内存 + 磁盘两层缓存,相同文本复用音频 - ✅ **Markdown 渲染** — 前端实时渲染 AI 回复 - ✅ **OpenAPI 文档** — 内置 Swagger UI ## 技术栈 | 层级 | 技术 | |---|---| | Backend | Spring Boot 3.5.13 + Spring AI 1.1.1 + JDK 17 | | LLM | 智谱 GLM-5.2 + 通义千问 Qwen3.6-Flash(OpenAI 兼容代理) | | Frontend | Vue 3.5 + TypeScript 5.7 + Vite 6 + Element Plus 2.9 + Pinia 2.3 | | 文档处理 | Apache Tika 3.1(提取)、PaddleOCR(OCR)、LibreOffice(转 PDF) | | TTS | edge-tts、Qwen3-TTS-12Hz-0.6B-Base、MeloTTS(ONNX) | | 接口文档 | SpringDoc OpenAPI(Swagger UI) | ## 系统依赖 | 依赖 | 用途 | 服务端口 | |---|---|---| | `edge-tts`(pip) | 默认 TTS 引擎,Microsoft 神经语音 | —(在线调用) | | `Qwen3-TTS-12Hz-0.6B-Base` | 本地离线 TTS,支持语音克隆 | `http://127.0.0.1:18081` | | `MeloTTS`(ONNX) | 中英混音 TTS | `http://127.0.0.1:18083` | | `PaddleOCR`(paddlepaddle) | 图片 / 扫描版 PDF 文字识别 | `http://127.0.0.1:18084` | | LibreOffice(系统包) | .doc/.docx → PDF 转换 | — | > TTS/OCR Python 依赖由 `uv` 管理(见 `scripts/pyproject.toml`)。安装 `uv`: > `curl -LsSf https://astral.sh/uv/install.sh | sh`;依赖重装可用 `FORCE_SYNC=1 bash scripts/start-tts-uv.sh`。 ## 快速开始 ### 1. 配置 API Key 从 [open.bigmodel.cn](https://open.bigmodel.cn) 获取智谱 API Key: ```bash export ZHIPU_API_KEY=your-api-key-here export HS_API_KEY=your-qwen-key-here # 可选,仅在代理未内置时用于 Qwen 模型 ``` 或直接编辑 `backend/src/main/resources/application-{dev|work}.yml`(按运行 profile 选择)。 ### 2. 启动后端 ```bash mvn spring-boot:run -pl backend -Dspring-boot.run.profiles=dev ``` 后端运行在 `http://localhost:8080`,接口文档:`http://localhost:8080/swagger-ui.html`。 ### 3. 启动前端 ```bash cd frontend npm install npm run dev ``` 前端运行在 `http://localhost:5173`,API 请求自动代理到后端(可用 `VITE_API_TARGET` 覆盖代理目标)。 ### 4. 启动本地 AI 服务(TTS / OCR,可选) 按需启动,`uv` 方式: ```bash bash scripts/start-tts-uv.sh qwen3 # Qwen3-TTS 语音克隆服务 :18081 bash scripts/start-tts-uv.sh melo # MeloTTS 中英混音服务 :18083 bash scripts/start-paddleocr.sh # PaddleOCR 识别服务 :18084 ``` 使用 conda 环境时亦可: ```bash conda run -n python3.12 --no-capture-output bash scripts/start-qwen3-tts.sh conda run -n python3.12 --no-capture-output bash scripts/start-melo-tts.sh conda run -n python3.12 --no-capture-output bash scripts/start-paddleocr.sh ``` 三个服务均可随时停用:未启动时 TTS 自动回退 `edge` 引擎,OCR 自动跳过并降级。 ## 多模型配置 在 `backend/src/main/resources/application.yml` 的 `spring.ai.openais.models[]` 中配置。每个模型包含: ```yaml spring: ai: openais: default-model-id: glm-5 models: - id: glm-5 # 唯一 ID,会话切换时引用 name: GLM-5.2 # 显示名称 description: 智谱大模型,综合能力最强 icon: "🧠" tags: [高质量, 推荐] base-url: http://172.16.51.83:9081 api-key: ${ZHIPU_API_KEY:} completions-path: /bigmodel/v4/chat/completions model: glm-5.2 temperature: 0.7 ``` 模型由 `ModelRegistry` 自动注册为独立 `ChatClient` Bean,前端通过 `GET /api/v1/models` 获取列表,`PUT /api/v1/conversations/{id}/model` 切换。 > 运行 `dev`/`work` profile 时,配置写在对应的 `application-dev.yml` / `application-work.yml`,编辑 profile 文件而非 `application.yml`。 ## 项目结构 ``` chat-bot/ ├── pom.xml # Parent POM(聚合 backend 模块) ├── backend/ # Spring Boot 3 后端 │ └── src/main/java/com/ctl/chatbot/ │ ├── config/ # ModelRegistry / ChatClient / WebConfig / TTS 配置 │ ├── controller/ # REST API:chat/ convert/ pdf/ file/ tts/ │ ├── service/ # 业务逻辑(接口 + XxxServiceImpl 按功能域分包) │ ├── model/ # DTO records │ ├── tool/ # AI 工具(WeatherTool、DateTimeTool) │ ├── common/exception/ # BusinessException / ErrorResponse / 全局异常处理 │ ├── ocr/ # PaddleOCR 客户端 │ ├── extract/ # 文件内容提取(Tika) │ └── tts/ # TTS 引擎适配与缓存 │ └── src/main/resources/ │ ├── application.yml # 多模型 + 各功能配置 │ ├── application-dev.yml # dev profile 覆盖 │ └── application-work.yml # work profile 覆盖 ├── frontend/ # Vue 3 前端 │ └── src/ │ ├── api/ # ApiClient + 各模块 API(fetch 实现) │ ├── components/ # chat/ layout/ pdf-extract/ 组件 │ ├── composables/ # useChat / useAutoScroll / usePdfExtract / useTTS │ ├── stores/ # Pinia chatStore │ ├── types/ # TypeScript 类型定义 │ ├── pages/ # 页面级组件 │ └── router/ # Hash 路由 └── scripts/ # 本地 TTS / OCR Python 服务 ├── qwen3-tts-server.py # Qwen3-TTS FastAPI 服务 :18081 ├── melo-tts-server.py # MeloTTS FastAPI 服务 :18083 ├── paddleocr-server.py # PaddleOCR FastAPI 服务 :18084 ├── ...-server.sh / start-tts-uv.sh └── pyproject.toml # uv 依赖管理(extras: qwen3/melo/ocr) ``` ## API 接口 所有接口前缀 `/api/v1`。 ### 会话管理 & 模型 | 方法 | 路径 | 说明 | |---|---|---| | GET | `/conversations` | 列出所有会话 | | POST | `/conversations` | 创建新会话 | | DELETE | `/conversations/{id}` | 删除会话 | | PUT | `/conversations/{id}/model` | 切换会话使用的模型 | | GET | `/models` | 列出所有可用模型 | | GET | `/models/default` | 获取默认模型 | ### 聊天 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/conversations/{conversationId}/messages` | 同步聊天 | | POST | `/conversations/{conversationId}/messages/stream` | SSE 流式聊天(`event: done` 结束) | 请求体: ```json { "message": "你好", "modelId": "glm-5", "files": [{ "id": "xxx", "name": "readme.md", "mimeType": "text/markdown" }] } ``` ### 文件 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/files` | 上传单文件(form-data `file`),返回文件 ID | ### 文档转换(.doc/.docx → PDF) | 方法 | 路径 | 说明 | |---|---|---| | POST | `/conversions/files` | 上传待转换文档(form-data `files`,仅 .doc/.docx) | | POST | `/conversions` | 启动批量转换任务 | | GET | `/conversions/{batchId}` | 查询批量转换状态 | | GET | `/conversions/{batchId}/download` | 下载转换结果 ZIP | ### PDF 提取 | 方法 | 路径 | 说明 | |---|---|---| | GET | `/documents` | 列出已上传的 PDF | | POST | `/documents` | 批量上传 PDF(form-data `files`) | | GET | `/documents/{id}` | 获取文档信息与页面内容 | | DELETE | `/documents/{id}` | 删除单个文档 | | DELETE | `/documents/batch` | 批量删除(请求体为 id 列表) | | GET | `/documents/{id}/file` | 下载原始 PDF | | GET | `/documents/{id}/pages/{pageNum}` | 获取指定页内容 | | PUT | `/documents/{id}/pages/{pageNum}` | 保存指定页手动排版 | | POST | `/documents/{id}/ocr` | 整本 OCR 增强 | | POST | `/documents/{id}/pages/{pageNum}/ocr` | 单页 OCR 增强 | ### TTS | 方法 | 路径 | 说明 | |---|---|---| | POST | `/tts/speak` | 文本转语音,返回音频流 | | DELETE | `/tts/cache` | 清除 TTS 缓存 | | GET | `/tts/cache/stats` | TTS 缓存统计 | 请求体:`{ "text": "你好", "engine": "edge" }`,`engine` 取 `edge`(默认)/ `qwen3` / `melo`,`text` 最长 500 字符。 ## 自定义工具 在 `backend/src/main/java/com/ctl/chatbot/tool/` 下添加新的工具类,会被自动注册到 ChatClient: ```java @Component public class MyTool { @Tool(description = "工具描述") public String doSomething(@ToolParam(description = "参数说明") String param) { return "结果"; } } ``` ## 错误响应格式 所有错误统一由 `GlobalExceptionHandler` 返回: ```json { "code": 400, "message": "请求参数验证失败", "details": "message: 消息内容不能为空", "timestamp": 1732032000000 } ``` --- # 项目重构记录 ## 重构概述 本次重构主要聚焦于**接口规范化**和**代码结构优化**,成功完成了前后端的全面改进。 ## 完成的工作 ### 第一阶段:后端接口规范化 #### 1. 全局异常处理 - ✅ 创建 `common/exception/ErrorResponse.java` — 统一错误响应格式 - ✅ 创建 `common/exception/BusinessException.java` — 业务异常类 - ✅ 创建 `common/exception/GlobalExceptionHandler.java` — 全局异常处理器 - 所有错误现在返回统一格式:`{code, message, details, timestamp}` #### 2. 统一 API 路径 - ✅ 所有 API 路径更新为 `/api/v1/*` 格式 #### 3. 请求验证 - ✅ `ChatRequest` 添加验证注解(@NotBlank, @Size, @Valid) - ✅ Controller 方法添加 `@Valid` 注解 - ✅ 验证失败时返回清晰的错误信息 #### 4. Swagger / OpenAPI 文档 - ✅ 添加 `springdoc-openapi-starter-webmvc-ui` 依赖 - ✅ 创建 `OpenApiConfig.java` 配置类 - ✅ 所有 Controller 添加 `@Tag` 注解、`@Operation` 和 `@ApiResponses` 注解 - 访问地址:`http://localhost:8080/swagger-ui.html` ### 第二阶段:前端重构 #### 1. 统一 API 客户端 - ✅ 创建 `api/client.ts` — 统一的 API 客户端类 - 统一的错误处理、自动解析后端错误格式 - 支持 GET / POST / PUT / DELETE / upload 方法 #### 2. API 层重构 - ✅ 重构 `api/chat.ts`、`api/conversation.ts`、`api/models.ts` 使用新的 API 客户端 - ✅ 所有 API 路径更新为 `/api/v1/*` #### 3. 类型对齐 - ✅ 创建 `types/common.ts` — 通用类型定义(ApiError) - ✅ 前后端类型完全对齐 #### 4. Store 更新 - ✅ 更新 `chatStore.ts` 使用新的 API 结构 ## 验证结果 ```bash # 后端 mvn clean compile # ✅ 成功,无编译错误 # 前端 npm run build # ✅ TypeScript 类型检查 + Vite 构建通过 ``` ## 错误处理示例 ### 成功响应 ```json { "conversationId": "abc-123", "content": "你好!" } ``` ### 错误响应 ```json { "code": 400, "message": "请求参数验证失败", "details": "message: 消息内容不能为空", "timestamp": 1732032000000 } ``` ## 代码质量改进 ### 后端 - ✅ 统一的异常处理机制 - ✅ 请求参数自动验证 - ✅ 完整的 API 文档 - ✅ 清晰的错误信息 ### 前端 - ✅ 统一的 API 客户端 - ✅ 一致的错误处理 - ✅ 类型安全 - ✅ 代码更简洁 ## 总结 - ✅ **接口规范化** — 统一的 API 路径、错误格式、请求验证 - ✅ **代码可维护性提升** — 清晰的代码结构、统一的错误处理 - ✅ **便于扩展** — 模块化设计、清晰的接口定义 - ✅ **前后端协作改善** — 类型对齐、统一的错误格式 所有改动已经过编译验证,可以安全部署。