面向企业内部知识库的极简 RAG 项目:可上传文档入库,并进行流式问答。
技术栈:Spring Boot + Spring AI + Milvus + DashScope(Qwen)。
- 基于
SseEmitter的流式回答(非 Flux 接口) - 问题改写(Rewrite)→ 向量检索(Milvus)→ 重排(Rerank)→ 生成回答(Qwen3-Max)
- Rerank 走百炼原生接口,兼容
qwen3-rerank实际参数格式 - 上传接口支持
DOC/DOCX/PDF/MD,解析使用Apache Tika - 内置前端页面,跟随后端一起启动,无需单独前端工程
- 控制器保持轻量:核心流程集中在 Service 层
flowchart LR
U["用户/前端页面"] --> C["/api/rag/chat/stream"]
C --> RW[问题改写]
RW --> VS[Milvus 向量检索]
VS --> RR[DashScope Rerank]
RR --> A[Qwen3-Max 生成回答]
A --> SSE[SSE 流式返回]
SSE --> U
F[上传文件] --> I["/api/rag/knowledge/upload"]
I --> T[Tika 文本提取]
T --> S[TokenTextSplitter 切分]
S --> E[Embedding 向量化]
E --> M[(Milvus)]
- Java
17 - Spring Boot
3.5.7 - Spring AI
1.1.2 - Milvus(向量数据库)
- DashScope(百炼)
- OpenAI 兼容接口:聊天与向量模型
- 原生 Rerank 接口:
qwen3-rerank
- Apache Tika
2.9.2
- 已启动 Milvus(默认
localhost:19530) - 可用 DashScope API Key
- JDK 17+
export DASHSCOPE_API_KEY=你的真实Key
export MILVUS_HOST=localhost
export MILVUS_PORT=19530./mvnw spring-boot:run浏览器访问:http://localhost:8080/
- 左侧菜单「上传文件」:文档入库与向量化
- 左侧菜单「流式问答」:企业知识库问答
POST /api/rag/knowledge/upload
Content-Type:multipart/form-data- 参数:
file(必填):仅支持DOC/DOCX/PDF/MD/MARKDOWNkb(可选):知识库标识,默认default
- 文件大小限制:默认
20MB
curl -X POST 'http://localhost:8080/api/rag/knowledge/upload' \
-F 'file=@./docs/employee-handbook.md' \
-F 'kb=hr'示例返回:
{
"fileName": "employee-handbook.md",
"kb": "hr",
"chunkCount": 12
}POST /api/rag/chat/stream
Content-Type:application/json- 返回类型:
text/event-stream
请求示例:
{
"question": "年假最多可以累计多少天?",
"kb": "hr"
}curl -N -X POST 'http://localhost:8080/api/rag/chat/stream' \
-H 'Content-Type: application/json' \
-d '{"question":"年假最多可以累计多少天?","kb":"hr"}'SSE 事件:
meta:改写后的问题refs:命中的片段来源token:模型流式输出done:回答完成error:异常信息
配置文件:src/main/resources/application.yaml
spring.ai.openai.base-url(默认https://dashscope.aliyuncs.com/compatible-mode)spring.ai.openai.api-keyspring.ai.openai.chat.options.model(默认qwen3-max)spring.ai.openai.embedding.options.model(默认text-embedding-v4)
app.rag.rewrite-modelapp.rag.answer-modelapp.rag.rerank-model(默认qwen3-rerank)app.rag.rerank-endpoint(默认百炼 Rerank 地址)app.rag.retrieve-top-kapp.rag.rerank-top-napp.rag.rerank-max-document-chars
app.rag.chunk-sizeapp.rag.min-chunk-size-charsapp.rag.min-chunk-length-to-embedapp.rag.max-num-chunks
spring.servlet.multipart.max-file-size(默认20MB)spring.servlet.multipart.max-request-size(默认20MB)
qwen3-rerank 不走 OpenAI Chat 兼容接口,而是调用百炼原生 Rerank API。
当前主请求结构:
{
"model": "qwen3-rerank",
"query": "用户问题",
"documents": ["候选文本1", "候选文本2"],
"top_n": 4
}实现策略:
- 优先使用 qwen3-rerank 原生结构
- 若返回格式不兼容,自动尝试兼容结构
- 若 Rerank 整体失败,回退到向量分数排序
提示词已模板化,不写死在 Java 代码中:
src/main/resources/prompts/rewrite-system.stsrc/main/resources/prompts/rewrite-user.stsrc/main/resources/prompts/answer-system.stsrc/main/resources/prompts/answer-user.st
你可以直接调整模板来迭代效果,不需要改业务代码。
src/main/java/com/nageoffer/ai/tinyrag
├── config
│ ├── RAGConfiguration.java
│ └── RAGProperties.java
├── controller
│ ├── GlobalExceptionHandler.java
│ └── RAGController.java
├── model
│ ├── RAGRequest.java
│ └── UploadResponse.java
└── service
├── DashscopeRerankService.java
├── KnowledgeIngestionService.java
└── RAGService.java
内置前端页面:
src/main/resources/static/index.html
- 流式 RAG 问答(SSE)
- 文档上传、解析、切分、向量化入库
- 问题改写 + Milvus 检索 + Rerank 重排
- 基于模板文件的提示词管理
- 引入混合检索(向量 + 关键词/BM25)
- 增加引用片段高亮与答案可解释性增强
- 增加离线评测脚本(召回率/准确率)
- 增加多知识库权限隔离(企业多租户)
欢迎通过 PR 与问题单参与改进。
- 在代码托管平台 Fork 本仓库并创建功能分支
- 本地开发并保证编译通过:
./mvnw -DskipTests compile- 提交前自查:
- 接口行为未破坏现有功能
- 配置项和 README 一致
- 新增能力有最小可复现说明
- 发起 PR,描述变更背景、方案与测试方式
- 问题现象与日志
- 复现步骤
- 期望行为
- 运行环境(JDK、Milvus、模型配置)
- 统一类命名为
RAG*(如RAGController、RAGService、RAGConfiguration) - 精简 Controller,流式编排逻辑下沉到
RAGService - 修复
TaskExecutor多 Bean 注入歧义,使用RAGTaskExecutor - 上传链路改为仅文档类型(
DOC/DOCX/PDF/MD)并使用Tika解析 - 前端拆分为「上传文件 / 流式问答」双页签,优化交互与视觉
- Rerank 对齐百炼原生接口参数,规避
qwen3-rerank兼容模式报错
本项目基于 Apache License 2.0 开源,详见 LICENSE。