# SpringAIRag **Repository Path**: xiaweijin/springairag ## Basic Information - **Project Name**: SpringAIRag - **Description**: 基于电力系统的大模型AI-RAG练手项目 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-09-16 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ai-agent 基于 **RAG(检索增强生成)** 的 AI 电力问答后端,支持文档异步导入、BM25 混合检索、Rerank 精排与知识库体检。 **技术栈**:Spring Boot 3.5.11 · Java 21 · Spring AI 1.1.4 · MyBatis-Plus · MySQL · Redis (RediSearch 向量库) · RabbitMQ · MinIO · DashScope Rerank · Knife4j/OpenAPI --- ## 核心功能 | 链路 | 说明 | 入口 | |---|---|---| | **电力问答** | 用户提问 → 对话记忆 + 查询改写 + 向量/BM25 混合检索 + Rerank 精排 → 大模型生成结构化建议(含引用来源)| `POST /api/power/chat`、`POST /api/power/chat/stream` | | **文档异步导入** | 上传文件 → MinIO + MySQL 任务 + RabbitMQ → 后台解析(含扫描版 PDF 的 OCR)→ 分块 → 写向量库 | `POST /api/document/upload` | | **知识库体检** | 用户说"检查知识库健康"→ AI 调用 tool → 12 项检查 → 返回可执行的修复建议 | AI Tool Calling(`HealthCheckTool`)| --- ## 快速开始 ### 环境要求 - **JDK 21**(全局 `JAVA_HOME` 若是 Java 8,必须显式覆盖) - MySQL 8.x - Redis(需加载 RediSearch 模块) - RabbitMQ - MinIO(可选,也支持本地磁盘存储,`storage.type: local`) ### 构建与运行 ```bash # 设置 JDK 21 export JAVA_HOME=/path/to/jdk-21 # Linux/macOS $env:JAVA_HOME='D:\jdk\jdk-21.0.12.1' # Windows PowerShell # 编译(推荐 wrapper,不要用全局 mvn) ./mvnw.cmd compile # 启动 ./mvnw.cmd spring-boot:run ``` 启动后访问 `http://localhost:8080/api/` ### 配置说明 项目使用 `application.yml` 集中管理配置。敏感信息通过环境变量占位符注入,启动前需确保以下环境变量已设置: | 环境变量 | 用途 | |---|---| | `DOUBAO_API_KEY` | 豆包(火山方舟)API Key,用于对话 + embedding + OCR | | `MYSQL_PASSWORD` | MySQL 密码 | | `REDIS_PASSWORD` | Redis 密码 | | `RABBITMQ_PASSWORD` | RabbitMQ 密码 | | `RERANK_API_KEY` | 阿里云百炼 Rerank API Key | | `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` | MinIO 凭证 | > 所有外部地址硬编码在 `application.yml`,无 `application-dev/prod.yml` 多环境拆分。 ### 数据库初始化 > ⚠️ `schema.sql` 不会自动执行(`spring.sql.init.mode` 默认为 `embedded`,对 MySQL 不生效),新环境必须手工执行: ```bash mysql -u root -p ai_agent < src/main/resources/schema.sql ``` --- ## 运行时架构 ``` ┌──────────────────────────────┐ 浏览器 (static/) ──▶ │ Spring Boot :8080 /api │ index/chat-debug/vector│ controller → service │ └───┬───────┬───────┬──────┬───┘ │ │ │ │ ┌─────────────┘ │ │ └──────────────┐ ▼ ▼ ▼ ▼ MySQL(localhost) Redis(向量库) RabbitMQ MinIO ai_agent 库 43.142.135.114 43.142.135.114 43.142.135.114 · spring_ai_chat_memory :16379 :15690 :19000 · spring_ai_document power_app_index 主队列+DLQ bucket=ai-agent · document_task prefix="power:" ▲ ▲ │ │ │ ▼ └──── LLM(火山方舟 ARK,OpenAI 兼容)──┐ DashScope(百炼) chat doubao-seed-2.0-lite │ qwen3-rerank(Rerank 精排) embed doubao-embedding-vision │ OpenAI 兼容接口 OCR doubao-seed-2.0-lite │ ⚠️ 需配置 rerank.api-key (DocumentService.OCR_MODEL) ``` --- ## 项目结构 ``` src/main/java/com/xwj/aiagent/ ├── controller/ # 接口层 │ ├── PowerController # 问答(同步 + SSE 流式) │ ├── DocumentController # 上传 + 任务查询 │ ├── DocumentAdminController # 删除文档 / 重放失败任务 / 文档列表 │ ├── VectorSearchController # 向量库检索台 │ └── HealthController # 存活探针(GET /api/health) ├── service/ # 业务逻辑 │ ├── PowerChatService # 问答链路核心 │ ├── RerankService # Rerank 精排(DashScope qwen3-rerank) │ ├── DocumentService # 导入链路核心 │ ├── DocumentTaskService # 任务状态机 │ ├── DocumentAdminService # 文档管理 │ ├── VectorSearchService # 纯检索(给检索台用) │ ├── HybridDocumentRetriever # 混合检索:向量 + BM25,RRF 融合 │ ├── KeywordRetriever # BM25 关键词路,直连 RediSearch │ ├── KnowledgeBaseHealthService # 知识库体检(12 项检查,纯只读) │ └── pdf/PdfPageExtractor # PDF 逐页判定 ├── config/ # 配置 │ ├── RedisVectorStoreConfig # 自建向量库 Bean + 可过滤字段 │ ├── RagConfig # RAG Advisor 组装 + ConditionalRagAdvisor │ ├── RagDefaults # 检索参数唯一来源 │ ├── HealthCheckProperties # 体检阈值配置 │ └── ... ├── tool/ │ └── HealthCheckTool # 体检工具入口(@Tool,按意图挂载) ├── support/ │ ├── HealthCheckIntent # 体检意图识别(工具挂载 + RAG 跳过共用) │ ├── ChineseTokenizer # jieba 分词 + 中文二元组 │ ├── ReciprocalRankFusion # RRF 融合算法 │ ├── RagContextFormatter # 上下文格式化与来源提取 │ └── PartialJsonReportReader # 流式半截 JSON 容错读取 ├── mq/ # RabbitMQ 生产者/消费者 ├── storage/ # 对象存储(MinIO / 本地磁盘) ├── entity/ / mapper/ # MyBatis-Plus 数据模型 ├── dto/ # 请求响应体 ├── aop/ / logging/ # 日志、装饰器 ``` --- ## 检索参数 | 参数 | 值 | 说明 | |---|---|---| | 向量相似度阈值 | 0.65 | 低于此值的切片不参与回答 | | Top K | 6 | 最多取回切片数(未启用 Rerank) | | Recall Top K | 20 | 向量检索多召回数(启用 Rerank 时) | | Rerank Top N | 5 | 精排后保留的文档数 | | 精排及格线 | 0.4 | 低于此分的候选直接丢弃 | | BM25 关键词召回 | 20 | 关键词路召回量(`hybrid.keyword-top-k`)| | RRF k | 60 | 融合平滑常数(`hybrid.rrf-k`)| **混合检索**(`hybrid.enabled=true`,默认开启):向量路 + BM25 关键词路各自召回后 RRF 融合。对精确词、专有名词、编号的检索效果显著优于纯向量。详见 `docs/架构总览.md` §4.6。 --- ## API 接口 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/api/power/chat` | 电力问答(同步) | | POST | `/api/power/chat/stream` | 电力问答(SSE 流式) | | POST | `/api/document/upload` | 上传文档(multipart) | | GET | `/api/document/task/{taskId}` | 查询任务状态 | | GET | `/api/document/task/list` | 任务列表 | | GET | `/api/document/list` | 文档列表 | | DELETE | `/api/document/{documentId}` | 删除文档 | | POST | `/api/document/task/{taskId}/retry` | 重放失败任务 | | GET | `/api/vector/defaults` | 检索默认参数 | | POST | `/api/vector/search` | 向量库检索 | | GET | `/api/health` | 健康检查(存活探针) | --- ## 知识库体检 通过 AI Tool Calling 触发,用户说"检查知识库健康"即可。AI 调用 `HealthCheckTool`,返回 12 项检查结果并用自然语言总结。 **12 项检查规则**: | 类别 | 检查项 | |---|---| | A 入库完整性 | A1 部分成功 / A2 整体失败 / A3 卡死任务 | | B 切片质量 | B1 解析不充分 / B2 页码缺口 / B3 空切片 / B4 超短切片 | | C 重复 | C1 同名文档 | | F 一致性对账 | F1 两库不一致 / F2 状态成功无内容 / F3 已删有残留(待实现)/ F4 元数据缺失 | - **纯只读**,不修改任何数据,修复动作复用已有接口 - 意图识别与 RAG 跳过共用 `HealthCheckIntent`,体检时跳过向量检索以节省时间 - 配置项:`health-check.*`(`application.yml`) --- ## 内置前端 - **问答主站**:`http://localhost:8080/api/` — 电力助手问答 + 知识库管理 - **检索台**:`http://localhost:8080/api/vector.html` — 向量库检索调试 - **调试台**:`http://localhost:8080/api/chat-debug.html` — 带原始 JSON 的调试界面 --- ## 日志编号 排查时按 `taskId` grep 即可: | 前缀 | 链路 | |---|---| | `[CHAT-1/5]` ~ `[CHAT-5/5]` | 问答链路 | | `[DOC-1/8]` ~ `[DOC-8/8]` | 文档导入链路 | | `[VEC-1/2]` ~ `[VEC-2/2]` | 向量检索 | | `[BM25]` | 混合检索(两路命中与融合) | | `[HEALTH]` / `[HEALTH-TOOL]` | 知识库体检 | --- ## 数据模型 ### MySQL(库 `ai_agent`) | 表 | 用途 | |---|---| | `spring_ai_chat_memory` | Spring AI 对话记忆(JDBC 持久化) | | `spring_ai_document` | 切片原文副本(仅排查用,不参与检索) | | `document_task` | 文档处理任务状态机 | ### Redis | 键 / 结构 | 说明 | |---|---| | `power_app_index` | RediSearch 向量索引 | | `power:*` | 向量 JSON key 前缀 | ### MinIO 对象键格式:`{yyyy-MM-dd}/{uuid}.{ext}`,bucket = `ai-agent`(应用启动时自动建桶)。 --- ## 注意事项(红线) 1. **不能删 `pom.xml` 中的 `jbig2-imageio` 依赖** — 缺它时 JBIG2 编码的扫描件会渲染成纯白页,OCR 返回 0 字 2. **改可过滤元数据字段需同步改三处** — `RedisVectorStoreConfig.FILTERABLE_FIELDS` + `DocumentService.normalizeMetadata` + 重建 RediSearch 索引 3. **`RedisVectorStoreConfig` 返回类型必须是 `RedisVectorStore`** — 写成 `VectorStore` 会导致过滤静默失效 4. **`schema.sql` 不会自动执行** — 新环境必须手工执行 5. **向量库 `prefix` 必须与现有数据一致** — 否则检索永远返回 0 条且不报错 --- ## 相关文档 | 文档 | 内容 | |---|---| | [架构总览](docs/架构总览.md) | **主要参考**:包结构、链路时序、设计决策、数据模型、接口清单、改动落点 | | [知识库体检方案](docs/2026-09-16-知识库体检方案.md) | 检查项设计、取舍、验收标准 | | [PDF 逐页解析与图区域 OCR](docs/2026-09-15-PDF逐页解析与图区域OCR(方案B).md) | 逐页判定算法与 OCR 改造 | | [RedisVectorStore 索引问题](docs/RedisVectorStore索引未自动创建问题记录.md) | 索引排查过程 | | [RAG 能力进阶](docs/RAG能力进阶-需求与变更记录.md) | RAG 能力演进 | | [服务器资源与模型部署](docs/服务器资源与模型部署方案.md) | 部署方案 |