基于 Spring AI 2.0.1 + GLM-5.3 + PostgreSQL(pgvector) + qwen3-embedding 的企业知识库系统,提供资料入库(Word / PPT / PDF)与 RAG 检索问答能力,前端为 Vue 3。
- 资料入库:上传 Word(.doc/.docx)、PowerPoint(.ppt/.pptx)、PDF,自动完成文本提取(Apache Tika)→ 切分(TokenTextSplitter,中文标点友好)→ 向量化(qwen3-embedding:4b)→ 入库(pgvector,HNSW + 余弦距离)。异步处理,前端实时轮询状态;支持删除(级联清理向量切片)。扫描件 PDF 自动 OCR(tess4j 内嵌 Tesseract,本地 CPU,见常见问题)。
- 知识检索:两阶段检索——向量语义粗召回 + Qwen3-Reranker 重排序精排,展示来源文档与相关度。
- 智能问答(RAG):检索 Top-K 切片作为上下文交给 GLM-5.3 流式生成(SSE),回答标注引用来源,资料不足时如实告知。
| 层 | 选型 |
|---|---|
| 前端 | Vue 3 + Vite + Element Plus + marked |
| 后端 | Spring Boot 4.1.1 + Spring AI 2.0.1(Java 21) |
| 大模型 | 智谱 GLM-5.3(OpenAI 兼容端点 https://open.bigmodel.cn/api/paas/v4) |
| 向量模型 | qwen3-embedding:4b-q4_K_M(Ollama 本地,1024 维;任意 OpenAI 兼容 /embeddings 服务均可) |
| 重排序模型 | Qwen3-Reranker-4B(Q4_K_M;Ollama 无原生 rerank 端点,由 llama.cpp / vLLM / SiliconFlow 承载) |
| 数据库 | PostgreSQL 16 + pgvector(HNSW 索引、COSINE 距离) |
| 文档解析 | Spring AI Tika Document Reader(PDF / Word / PPT) |
| 扫描件 OCR | tess4j 内嵌 Tesseract(PDFBox 逐页渲染,chi_sim+eng 语言包) |
┌─────────────┐ /api ┌───────────────────────────────────────────┐
│ Vue 3 前端 │ ────────▶ │ Spring Boot + Spring AI 2.0.1 │
│ (5173) │ ◀──────── │ │
└─────────────┘ SSE/JSON │ 入库:Tika 解析 → Token 切分 → qwen3 向量化 │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────┐ ┌──────────────┐ │
│ │ PgVector │ │ qwen3 嵌入服务│ │
│ │ Store │ │ (OpenAI 兼容) │ │
│ └─────┬─────┘ └──────────────┘ │
│ ▼ │
│ 问答:向量检索 Top-K → 重排序精排 → GLM-5.3 │
└────────┬───────────────────┬──────────────┘
▼ ▼
PostgreSQL + pgvector 智谱开放平台 (GLM-5.3)
RAG-Knowledge/
├── backend/ # Spring Boot 后端
│ ├── pom.xml
│ └── src/main/java/com/ragknowledge/
│ ├── config/AiConfig.java # GLM-5.3 / qwen3-embedding / Qwen3-Reranker 客户端与切分器配置
│ ├── document/ # 资料入库(上传/解析/切分/向量化/删除)
│ ├── rag/ # RAG 检索(向量召回+重排序)、流式问答、知识检索 API
│ └── common/ # 统一响应与异常处理
├── frontend/ # Vue 3 前端(知识库管理 / 知识检索 / 智能问答)
├── docker/docker-compose.yml # PostgreSQL 16 + pgvector
├── scripts/mock-embedding-server.mjs # 离线调试用的 /embeddings 与 /rerank 模拟服务
├── scripts/download-tessdata.mjs # OCR 语言包下载(扫描件 PDF 识别需要,一次性)
└── .env.example # 环境变量模板
- JDK 21+、Maven 3.9+(后端)
- Node.js 20.19+(前端)
- PostgreSQL 16+(本机安装;无本机库时可用 Docker Compose 容器化方案,见第 1 步)
- 智谱开放平台 API Key(https://open.bigmodel.cn)
- 一个向量模型服务:
qwen3-embedding:4b-q4_K_M(本地 Ollama,见第 2 步) - 一个重排序模型服务:
Qwen3-Reranker-4B(可选,见第 3 步;未启用时退回向量排序) - (可选)扫描件 PDF 识别:
node scripts/download-tessdata.mjs下载 OCR 语言包(一次性,约 7MB)
默认配置直连本机已安装的 PostgreSQL(localhost:5432,用户/口令按实际安装通过 .env 或环境变量调整),需先建库 ragknowledge 并启用 vector 扩展:
CREATE DATABASE ragknowledge;
\c ragknowledge
CREATE EXTENSION IF NOT EXISTS vector;没有本机库时,可选用 Docker Compose 容器化方案(宿主机端口 5433):
cd docker
docker compose up -d
# 首次启动会自动创建数据库 ragknowledge(用户 rag / 密码 rag123456)并启用 vector 扩展使用容器化方案时,在 .env 中把 DB_PORT 改为 5433、DB_USER=rag、DB_PASSWORD=rag123456。向量表 vector_store 由 Spring AI 首次启动时自动建表建索引。
| 方式 | 说明 | EMBEDDING_BASE_URL |
|---|---|---|
| Ollama(推荐) | ollama pull qwen3-embedding:4b-q4_K_M |
http://localhost:11434/v1(默认) |
| SiliconFlow 云端 | 控制台获取 API Key | https://api.siliconflow.cn/v1 |
| vLLM / Xinference 自建 | 以 OpenAI 兼容模式部署向量模型(需支持 dimensions 参数) | http://<host>:<port>/v1 |
| 离线调试 | node scripts/mock-embedding-server.mjs(伪向量,无语义,仅验证链路) |
http://localhost:9999/v1 |
检索采用两阶段:先向量粗召回,再由 Qwen3-Reranker 精排。Ollama 没有原生 rerank 端点,Qwen3-Reranker 需用以下任一方式承载(Jina/Cohere 风格 /rerank 协议):
| 方式 | 说明 | RERANK_BASE_URL |
|---|---|---|
| llama.cpp(推荐) | llama-server -m Qwen3-Reranker-4B-Q4_K_M.gguf --embedding --pooling rank --rerank --port 8900 |
http://localhost:8900/v1(默认) |
| SiliconFlow 云端 | 控制台获取 API Key,模型名如 Qwen/Qwen3-Reranker-4B |
https://api.siliconflow.cn/v1 |
| vLLM / Xinference 自建 | 以 rerank 模式部署 | http://<host>:<port>/v1 |
| 离线调试 | node scripts/mock-embedding-server.mjs(词项重叠伪分值,仅验证链路) |
http://localhost:9999/v1 |
未启用(RERANK_ENABLED=false)或服务不可用时自动退回向量排序,仅影响引用排序质量,不影响问答可用性。
cd backend
export ZHIPUAI_API_KEY=你的智谱APIKey # Windows: set 或 IDEA 环境变量
mvn spring-boot:run
# 或打包运行:mvn package && java -jar target/rag-knowledge-backend-1.0.0.jar后端默认 http://localhost:8080。完整可配置项见 .env.example(LLM 端点、向量服务、重排序服务、检索参数 Top-K / 召回候选数 / 相似度阈值、切分大小等)。
cd frontend
npm install
npm run dev打开 http://localhost:5173:先在「知识库管理」上传资料,入库完成后即可使用「知识检索」与「智能问答」。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/documents/upload |
multipart 上传资料(file 字段),返回文档元信息,入库异步进行 |
| GET | /api/documents |
文档列表(含入库状态 PROCESSING / COMPLETED / FAILED) |
| DELETE | /api/documents/{id} |
删除文档(同时删除其全部向量切片与源文件) |
| POST | /api/search |
知识检索,body:{"query":"...","topK":5} |
| POST | /api/chat/stream |
RAG 流式问答(SSE),body:{"query":"..."} |
SSE 事件协议(每条 data 为单行 JSON):
data: {"type":"sources","payload":[{"index":1,"docName":"xx.pdf","score":0.83,"content":"..."}]}
data: {"type":"message","payload":"根据"}
data: {"type":"message","payload":"资料[1]……"}
data: {"type":"done","payload":"ok"}
- 扫描件 PDF 怎么处理:纯图片扫描件无文本层,Tika 提取文本少于
OCR_MIN_TEXT_LENGTH(默认 100 字符)时自动用 tess4j 内嵌 Tesseract 逐页 OCR(本地 CPU,进度按"页"展示在原进度条)。首次使用需node scripts/download-tessdata.mjs下载语言包到backend/data/tessdata/(默认OCR_TESSDATA_PATH,可用 tessdata_best 同名文件替换提升精度);Word/PPT 内嵌的扫描图不做 OCR。 - 检索不到 / 命中过多:调整
RAG_SIMILARITY_THRESHOLD(默认 0.45,调高更严格)与RAG_TOP_K(默认 5)。 - 重排序未生效:后端日志出现「重排序失败,退回向量排序」即说明重排序服务不可达,检查
RERANK_BASE_URL与服务是否启动;召回候选数与最终返回条数由RAG_CANDIDATE_TOP_K(默认 10)与RAG_TOP_K(默认 5)控制。 - 更换向量服务:任何 OpenAI 兼容
/embeddings服务均可,通过EMBEDDING_BASE_URL / EMBEDDING_API_KEY / EMBEDDING_MODEL配置;向量输出维度必须保持 1024(后端请求带dimensions=1024;qwen3-embedding:4b 原生 2560 维由该参数截断)。换不识别dimensions参数的模型或改维度,需清空vector_store表并重新入库。 - 两个模型为什么不用 starter 自动装配:对话(智谱)与向量(本地 Ollama qwen3-embedding:4b)使用不同 baseUrl,Spring AI 2.0 的 OpenAI 模块基于官方 OpenAI Java SDK,因此在
AiConfig中手工构建两套OpenAIOkHttpClient。 - Spring AI 版本要求:Spring AI 2.0.x 需搭配 Spring Boot 4.x 与 Java 17+(本项目使用 Boot 4.1.1 + Java 21)。
- 后端
mvn package编译打包通过(Spring Boot 4.1.1 + Spring AI 2.0.1,适配 2.0 的官方 OpenAI SDK 客户端 API 与 TokenTextSplitter 新签名)。 - 前端
npm run build构建通过(Vite 7 + Vue 3.5 + Element Plus)。 - 端到端联调(入库 → 检索 → 问答)需要数据库、向量服务与 API Key,请按「快速开始」在本机环境执行。
- 扫描件 OCR:tess4j 5.16.0(内嵌原生库)+ chi_sim/eng 语言包本机冒烟通过——无文本层的伪扫描件 PDF 逐页识别成功,300 DPI 单页约 2s。
