# spring-ai-rag-knowledge-app **Repository Path**: weh_coder/spring-ai-rag-knowledge-app ## Basic Information - **Project Name**: spring-ai-rag-knowledge-app - **Description**: 多租户知识库问答(同步 + 流式 SSE) 文档上传 / 更新(发版)/ 软删除 / 列表 / 版本审计 会话历史(增删查、重命名、统计) 基于 JWT + Redis 的登录态鉴权 多租户、按部门 / 全公司的可见性权限(在 Milvus 检索 filter 中生效) - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-08-12 - **Last Updated**: 2026-08-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: SpringAI, RAG, 知识库问答, SpringBoot ## README # RAG 知识库问答平台(后端) > 项目坐标:`com.weh.ai:rag-knowledge-base-app:1.0.0`|包路径:`com.weh.rag`|端口:`8081` ## 1. 项目简介 面向企业的**多租户 RAG(检索增强生成)知识库问答平台**后端。接收用户自然语言提问,结合企业私域文档进行混合检索与重排,再调用大模型生成带引用来源的回答;同时提供文档管理、会话历史、多租户权限等完整能力。内置一套管理前端(Thymeleaf + 原生 JS),启动即可用。 - 业务接口统一挂在 `/api` 前缀下,统一响应壳 `ResultVO`。 - 多租户隔离在 Milvus 检索 `filter` 中生效(召回前过滤),非应用层后过滤。 - 文档写接口(上传/更新/删除/版本)限定 `admin` 角色。 ## 2. 核心特性 - **同步 + 流式问答**:`/api/knowledge/query`(同步 JSON)、`/api/knowledge/stream`(SSE 流式,事件 `retrieving → sources → chunk* → done`)。 - **混合检索 + RRF 融合**:Milvus 原生 `hybridSearch`(`dense_vector` 稠密 + `sparse_vector` BM25 稀疏)服务端 RRF 融合,召回前即按租户/可见性过滤。 - **重排(rerank)**:调用阿里云 rerank API 做 cross-encoder 相关性精排;异常/低于阈值自动 `fallback` 保序,绝不阻断问答。 - **问题重写(Query Rewriting)**:检索前用 LLM 将口语化/带指代的追问改写为独立检索查询,提升召回;最终回答仍用原问题,异常自动回退。 - **文档全生命周期**:上传 / 更新(发版) / 软删除 / 版本审计;软删除仅置 `is_active=false`(分片保留),Redis 注册表丢失可从 Milvus 完整恢复(含版本历史)。 - **鉴权与会话**:JWT + Redis 登录态,多租户按「部门 / 全公司」可见性权限。 - **可观测性**:统一状态码枚举 `StatusCodeEnum` + AOP 统一方法级日志(敏感字段自动脱敏)。 - **内置管理前端**:深色侧边栏 + 浅色内容区设计系统,含文档中心(搜索/过滤/分页/刷新自愈)、聊天(标准/流式双模式)、历史、组织视图。 ## 3. 技术栈 | 领域 | 选型 | |------|------| | 语言 / 框架 | Java 17、Spring Boot 3.2.5(**继承** `spring-boot-starter-parent`) | | AI / RAG | Spring AI 1.1.2(OpenAI 兼容协议 + `transformers` 本地 ONNX 稠密嵌入,维度 768) | | 向量库 | Milvus(`milvus-sdk-java` 2.6.10,Zilliz Cloud serverless),原生 `hybridSearch` + `RRFRanker` + BM25 Function | | 缓存 / 会话 | Redis(`spring-boot-starter-data-redis`) | | 鉴权 | JJWT 0.11.5 + 自定义 `JwtAuthFilter`(无 Spring Security) | | 文档解析 | PDFBox 3.0.1、POI 5.2.5(docx/doc) | | 中文分词 | jieba-analysis 1.0.2(驱动 Milvus BM25 稀疏检索) | | 统一日志 | `spring-boot-starter-aop`(AOP 切面 + `@Loggable`) | | 接口文档 | springdoc-openapi 2.3.0(`/swagger-ui`、`/v3/api-docs`) | | 构建 | Maven(`maven-compiler-plugin` 3.11.0 + Lombok 注解处理器)、JUnit 5 + Mockito + MockMvc 测试 | ## 4. 项目结构 ``` rag-knowledge-base-app/ ├── pom.xml ├── models/dense/ # 本地稠密向量模型(model.onnx + tokenizer.json) ├── storage/ # 上传文档落盘目录(运行时生成) ├── src/main/java/com/weh/rag/ │ ├── RagSearchApplication.java │ ├── config/ # AiConfig / VectorStoreConfig / RerankerConfig(阿里云 rerank) / WebConfig ... │ ├── controller/ # Auth / History / Knowledge / Document / Department / Health / Admin │ ├── service/ (+impl) # Knowledge / VectorStore / Auth / History / Document ... │ ├── dao/ (+impl) # MilvusSchema / VectorStore / Auth / Department / Document ... │ ├── filter/ # JwtAuthFilter(白名单 + Bearer 校验) │ ├── listener/ # HealthCheckerListener(健康检查 + 集合预热) │ ├── model/ │ │ ├── dto/ # 入站/业务流转:ChatDTO / AuthDTO / UserInfoDTO / HistoryAppendDTO ... │ │ ├── pojo/ # 持久化对象(仅 DAO 读写):User / History / DocumentMeta / DocumentChunk / RetrievedChunk ... │ │ ├── vo/ # 出站响应:ResultVO / QueryKnowledgeVO / DocumentVO / HistoryVO ... │ │ └── enums/ # StatusCodeEnum(统一状态码) │ ├── exception/ # MyCustomException / ControllerAdviceHandler │ ├── aspect/ # LoggingAspect(统一日志切面) │ ├── annotation/ # Loggable / LogLevel │ └── util/ # JwtTokenUtils / HashUtils / MilvusFilterBuilder / BeanCopyUtil ... ├── src/main/resources/ │ ├── application.yml / application-dev.yml │ ├── templates/index.html # 内置前端入口 │ └── static/ # css / js / assets(原生 JS 前端) └── src/test/java/com/weh/rag/ # 接口/白盒/集成测试 + JMH 微基准 ``` **分层铁律**:VO 仅出站响应;DTO 入站 + 服务间流转;PO 仅 DAO 层读写。禁止 VO 流入 Service/DAO。 ## 5. 核心接口 | 模块 | 方法 | 路径 | 鉴权 | 说明 | |------|------|------|------|------| | 认证 | POST | `/api/auth/login` | 否 | 登录获取 JWT | | 认证 | GET | `/api/auth/me` | 是 | 当前用户信息 | | 认证 | POST | `/api/auth/session` | 是 | 创建会话,返回 `conversationId` | | 健康 | GET | `/api/health` | 否 | 探测 Milvus / Redis(`UP`/`DEGRADED`) | | 问答 | POST | `/api/knowledge/query` | 是 | 同步问答,返回 `QueryKnowledgeVO` | | 问答 | POST | `/api/knowledge/stream` | 是 | 流式问答(SSE) | | 文档 | GET | `/api/documents/list` | 是 | 文档列表(含 Redis→Milvus 自愈) | | 文档 | POST | `/api/documents/upload` | admin | 上传文档 | | 文档 | PUT | `/api/documents/{id}/update` | admin | 更新文档版本 | | 文档 | DELETE | `/api/documents/{id}/delete` | admin | 软删除文档 | | 文档 | GET | `/api/documents/{id}/versions` | admin | 版本历史 | | 历史 | GET | `/api/history/user` | 是 | 当前用户全部会话 | | 历史 | GET | `/api/history/{id}/session` | 是 | 单会话详情 | | 历史 | DELETE | `/api/history/{id}/delete` | 是 | 删除会话 | | 历史 | DELETE | `/api/history/user/delete` | 是 | 清空全部会话 | | 历史 | PUT | `/api/history/session/{id}/title` | 是 | 重命名会话 | | 历史 | GET | `/api/history/stats` | 是 | 使用统计 | | 部门 | GET | `/api/departments/list` | 是 | 部门列表 | | 运维 | POST | `/api/admin/collection/reset` | admin | 原子重建 Milvus 集合 | | 运维 | POST | `/api/admin/document/redis-recover` | admin | 从 Milvus 全量恢复 Redis 注册表 | 统一响应:`{ "success": true, "code": 200, "message": "...", "data": {...} }`。 错误统一由 `ControllerAdviceHandler` 处理并按异常类型设置 HTTP 状态码(401/403/404/413/500/503)。 ## 6. 核心配置 主配置 `application.yml` 通过 profile 解耦,实际值见 `application-dev.yml`(`spring.profiles.active=dev`): | 配置项 | 说明 | 示例 | |--------|------|------| | `server.port` | 服务端口(与前端代理一致) | 8081 | | `spring.data.redis.*` | Redis 连接 | localhost:6379 | | `spring.ai.openai.*` | LLM 兼容端点(base-url / api-key / model / completions-path) | 阿里云百炼兼容模式 | | `app.milvus.*` | Milvus(Zilliz)uri / token / collection | rag_search_collection | | `app.milvus.dense-dimension` | 稠密向量维度 | 768 | | `rag.chat.*` | 检索 topK / `rrf-top-k` / `rrf-k` / `query-rewrite-enabled` | rrf-top-k=8, rrf-k=60, rewrite=true | | `aliyun.rerank.*` | 阿里云 rerank API(endpoint / token / model / threshold) | 精排 | | `app.logging.*` | 统一日志:`global` / `log-args` / `log-result` | global=true | | `jwt.secret` / `jwt.expiration` | JWT 密钥 / 过期(ms) | 1h | > ⚠️ **JVM 字符集**:BM25 中文稀疏检索依赖 JVM 默认字符集为 **UTF-8**,启动**必须**带 `-Dfile.encoding=UTF-8`,否则中文召回静默失败。 > ⚠️ `application-dev.yml` 含真实 LLM Key 与 Milvus token,**勿提交到公开仓库**。 ## 7. 快速开始 ```bash # 1. 准备外部依赖:Redis(localhost:6379)、Milvus(Zilliz uri+token)、可用 LLM 端点 # 2. 放置本地稠密模型:models/dense/{model.onnx, tokenizer.json} # 3. 配置 application-dev.yml(redis / milvus / ai / jwt) # 4. 构建(Git Bash 下必须用 mvn.cmd,不能用 mvn) export PATH="$PATH:/d/Java/apache-maven-3.6.3/bin" mvn.cmd -B clean package -DskipTests # 5. 启动(固定 8081 + 必带 UTF-8) java -Dfile.encoding=UTF-8 -Dserver.port=8081 -jar target/rag-search-app-1.0.0.jar # 6. 接口文档 # 打开 http://127.0.0.1:8081/swagger-ui/index.html # 内置前端 http://127.0.0.1:8081/ ``` **种子账号(dev)**:`zhangsan/123456`(admin,tenant qiteng)、`lisi/123456`、`wangwu/123456`、`weiliu/123456`(admin,tenant youqu)。 **常用命令**: ```bash mvn.cmd -B clean test # 全量测试(集成测试 RerankTest 默认隔离) mvn.cmd -Pbenchmark clean test-compile exec:java # JMH 微基准 ```