Java RAG 实战专栏导读:从零跑通 Ollama + Qdrant + Spring Boot 知识库

这是一篇写给 Java 初学者的 RAG 导学。不要急着背 Embedding、Chunk、Point 这些名词,本篇先帮你看懂整个系统,再亲手把最终项目跑起来。

完整代码和分篇教程:https://github.com/bysbsh/ai-rag-learning-guide

这篇要解决什么问题

大模型虽然懂很多通用知识,但它通常不知道:

  • 你公司内部的业务规则。
  • 你刚写完的项目文档。
  • 没有出现在训练数据中的最新资料。
  • 某个问题应该引用哪一份真实文档。

如果只把问题交给大模型,它可能凭自身知识回答,也可能编出一个看似合理的答案。

RAG 的做法是:先从你的知识库找资料,再让大模型根据资料回答。

举个例子,知识库中有一段内容:

text 复制代码
Secret 用来保存密码、令牌和证书等敏感数据。

用户提问:

text 复制代码
密码、令牌和证书应该保存在哪里?

RAG 系统会先找到 Secret 这段资料,然后把"资料 + 用户问题"一起交给大模型。这样得到的回答有依据,页面还可以同时显示资料来源和相似度。

先看懂整条 RAG 流程

本项目的完整查询过程如下:

text 复制代码
用户在网页输入问题
        ↓
Spring Boot 接收问题
        ↓
bge-m3 把问题转换成 1024 维向量
        ↓
Qdrant 用问题向量检索相关的知识片段
        ↓
Java 过滤低分结果,选出最相关的资料
        ↓
Java 把资料和用户问题组装成 Prompt
        ↓
qwen3 根据 Prompt 生成回答
        ↓
页面显示答案、资料来源、相似度和 Point ID

这里有一个容易混淆的点:**Qdrant 不负责回答,qwen3 不负责去 Qdrant 搜索。**中间的 Java 程序负责把它们串联起来。

每个组件分别做什么

组件 初学者可以这样理解 本项目中的作用
Ollama 本地模型运行器 下载、加载模型,并提供 HTTP API
qwen3:14b 负责读资料和组织语言的大模型 根据检索到的资料生成最终回答
bge-m3 把文本变成数字坐标的 Embedding 模型 把问题和知识片段转成 1024 维向量
Qdrant 专门保存和检索向量的数据库 存储知识片段,找出与问题语义最接近的内容
Spring Boot Java Web 应用框架 提供查询、入库、删除 API 和浏览器页面
Markdown 容易编辑的文档格式 充当本教程的原始知识文档
RAG 一套"先检索,后生成"的流程 是整个应用的组合方式,不是某个单独软件

学习前需要会什么

不需要先学会 Python,也不需要会训练大模型。你只需要:

  • 看得懂基本 Java 类、方法和集合。
  • 会在终端中进入目录、执行命令。
  • 知道 HTTP 请求和 JSON 是什么即可。

本教程主要在 Apple Silicon Mac 上验证。Java 代码可以在 Windows 和 Linux 上运行,但安装和后台服务命令会有区别。

为什么项目要分成 5 个模块

如果一开始就阅读完整 Spring Boot RAG 代码,你会同时遇到 HTTP、JSON、Prompt、Embedding、向量数据库和 Web API,很难判断每一段代码在解决什么问题。

所以仓库保留了 5 个可独立运行的阶段:

模块 先解决什么 你会学到什么
01-ollama-basics Java 怎样跟大模型说话 HttpClient、JSON、多轮上下文、System Prompt
02-embedding-search 电脑怎样判断两段文字的语义是否接近 Embedding、1024 维向量、余弦相似度
03-markdown-rag 怎样把本地 Markdown 资料交给大模型 Chunk、Top-K、相似度阈值、Prompt 组装
04-qdrant-rag 知识多了以后放在哪里 Qdrant Collection、Point、向量入库和检索
05-spring-rag 怎样让别的程序和用户使用 RAG Spring Boot API、动态入库、知识工作台

学习顺序不是在反复重写同一个程序,而是每次只新增一个概念。


动手:先把最终的 RAG 工作台跑起来

这一部分用于建立直观认识。先看到最终效果,后续再从第 1 篇开始逐层理解代码。

"5 分钟跑通"不包括第一次下载大模型和 Docker 镜像的时间。如果 Java、Ollama 或 Docker 还没有安装,请先阅读下一篇《第 1 篇:macOS 安装和准备 Ollama》。

完成进度

  • 1. 下载项目代码
  • 2. 检查 Java、Maven、Ollama、Docker 和 jq
  • 3. 准备聊天模型和 Embedding 模型
  • 4. 启动 Qdrant 向量数据库
  • 5. 创建 Collection 并写入示例知识
  • 6. 启动 Spring Boot 应用
  • 7. 在浏览器中完成第一次 RAG 问答

第 1 步:下载项目

打开终端,执行:

bash 复制代码
git clone https://github.com/bysbsh/ai-rag-learning-guide.git
cd ai-rag-learning-guide

第一条命令把公开仓库下载到本地,第二条命令进入项目根目录。后面所有命令都默认在这个目录中执行。

检查当前位置:

bash 复制代码
pwd
ls

ls 的结果中应该能看到:

text 复制代码
01-ollama-basics
02-embedding-search
03-markdown-rag
04-qdrant-rag
05-spring-rag
pom.xml
README.md

如果看不到这些内容,先不要继续,通常是还没有进入项目根目录。

第 2 步:检查基础环境

bash 复制代码
java -version
mvn -version
ollama --version
docker version
jq --version

不要只看命令有没有输出,还要检查以下内容:

检查项 要求 为什么
Java 17 或更高 项目按 Java 17 编译
Maven 3.9 或更高 负责下载依赖、编译和启动项目
Ollama 能输出版本号 负责在本地运行模型
Docker Client 和 Server 都有版本 Qdrant 在 Docker 容器中运行
jq 能输出版本号 只用来格式化和提取 JSON,不参与 RAG 运行

教程发布时的验证组合是 Java 17、Maven 3.9、Ollama 0.32、Docker 29.6 和 Qdrant 1.19。你不必追求完全相同的小版本。

常见失败信号:

  • command not found:软件还没有安装,或没有加入 PATH
  • Cannot connect to the Docker daemon:Docker Desktop 还没有启动。
  • Java 显示 11:后面可能出现 class file version 61.0 错误,需要切换到 Java 17。
  • 没有 jq:执行 brew install jq。它只影响教程中的 JSON 查看命令,不影响 Java 项目本身。

第 3 步:准备两个模型

bash 复制代码
ollama pull qwen3:14b
ollama pull bge-m3
ollama list

为什么是两个模型?

  • qwen3:14b 负责生成人能读懂的回答。
  • bge-m3 负责把文本转成向量,它不负责聊天。

ollama list 的列表中应该同时出现这两个名称。

24 GB 以下内存的电脑可以先使用 qwen3:8b。这时需要同步修改项目使用的模型名,具体位置参考**《附录:模型切换指南,qwen3 与 bge-m3 怎么换》**。

再检查 Ollama HTTP 服务:

bash 复制代码
curl http://localhost:11434/api/tags

返回 JSON 就说明 Ollama 服务可以被 Java 访问。如果是 Failed to connect,在 macOS Homebrew 安装方式下可以执行:

bash 复制代码
brew services start ollama

第 4 步:启动 Qdrant

第一次启动:

bash 复制代码
docker run -d \
  --name qdrant-study \
  -p 6333:6333 \
  -p 6334:6334 \
  -v qdrant-study-data:/qdrant/storage \
  qdrant/qdrant:v1.19.0

这条命令看起来很长,实际上只做了 5 件事:

参数 意义
-d 让容器在后台运行,关闭终端不会停止
--name qdrant-study 把容器命名为 qdrant-study
-p 6333:6333 映射 HTTP 管理接口
-p 6334:6334 映射 Java SDK 使用的 gRPC 接口
-v qdrant-study-data:/qdrant/storage 使用 Docker Volume 保存数据,重建容器时不至于立即丢失

以后容器已经创建,只需要:

bash 复制代码
docker start qdrant-study

检查容器:

bash 复制代码
docker ps --filter name=qdrant-study

成功标志是 STATUSUp,并能看到 6333-6334 端口映射。

再检查 Qdrant API:

bash 复制代码
curl -s http://localhost:6333/collections

第一次可能返回:

json 复制代码
{
  "result": {
    "collections": []
  },
  "status": "ok"
}

collections 是空数组不是错误,只是还没有创建存放向量的 Collection。

第 5 步:创建 Collection 并写入知识

Collection 可以先粗略理解为关系型数据库中的"表"。本项目的 Collection 名称是 kubernetes_chunks

创建 Collection:

bash 复制代码
curl -X PUT http://localhost:6333/collections/kubernetes_chunks \
  -H 'Content-Type: application/json' \
  -d '{
    "vectors": {
      "size": 1024,
      "distance": "Cosine"
    }
  }'

两个关键配置:

  • size: 1024bge-m3 生成的每个向量有 1024 个数字。
  • distance: Cosine:Qdrant 使用余弦相似度判断两个向量的方向是否接近。

成功时会看到类似:

json 复制代码
{"result":true,"status":"ok"}

如果提示 Collection 已经存在,先不要删除它,直接继续入库即可。

然后执行示例入库程序:

bash 复制代码
mvn -f 04-qdrant-rag/pom.xml compile exec:java \
  -Dexec.args=--index

这条命令的含义是:

  • mvn:运行 Maven。
  • -f 04-qdrant-rag/pom.xml:使用第 4 个模块的 Maven 配置。
  • compile:编译 Java 代码。
  • exec:java:运行该模块的默认主类。
  • -Dexec.args=--index:把 --index 传给主类,表示这次要入库,而不是查询。

程序会读取 Markdown,按标题拆成 Chunk,调用 bge-m3 生成向量,最后写入 Qdrant。

检查入库结果:

bash 复制代码
curl -s http://localhost:6333/collections/kubernetes_chunks | \
  jq '.result.points_count'

示例知识库应该输出:

text 复制代码
4

这个 4 不是"4 个向量维度",而是 Qdrant 中有 4 个 Point。每个 Point 代表一个知识 Chunk,它内部的向量仍然是 1024 维。

第 6 步:启动 Spring Boot 应用

bash 复制代码
mvn -f 05-spring-rag/pom.xml spring-boot:run

第一次运行时 Maven 需要下载依赖,速度取决于网络。当终端出现类似下面的日志时,才表示启动完成:

text 复制代码
Started SpringRagApplication

保持这个终端窗口运行,然后在浏览器打开:

text 复制代码
http://localhost:8080

注意:这里的 Spring Boot 默认在前台运行。如果关闭终端或按 Control + C,页面就会无法访问,这是正常现象。

第 7 步:完成第一次 RAG 问答

在页面右侧的问题输入框中输入:

text 复制代码
密码、令牌和证书应该保存在哪里?

成功时应该同时看到:

  1. AI 回答中出现 Secret
  2. 来源标题中出现 Secret
  3. 来源文件是 kubernetes.md
  4. 来源旁边显示相似度和 Point ID。

这 4 个结果同时出现,才说明不只是"大模型会聊天",而是整条 RAG 链路已经跑通。

你刚才的一次提问,后台发生了什么

阶段 实际动作 由谁完成
1 浏览器把问题发送给 /api/rag/ask 网页
2 调用 /api/embed 把问题变成 1024 维向量 Java + bge-m3
3 使用问题向量在 kubernetes_chunks 中搜索 Java + Qdrant
4 只保留达到相似度阈值的前几个 Chunk Java
5 把 System Prompt、知识 Chunk 和用户问题组装起来 Java
6 调用 /api/chat 生成最终文字 Java + qwen3:14b
7 answersources 返回页面 Spring Boot

answersources 不是模型自带的固定参数,而是这个 Java 项目自己设计的 API 返回结构:

  • answer 来自 qwen3 生成的回答。
  • sources 由 Java 根据 Qdrant 的真实检索结果生成。

这样设计的好处是,来源不需要让大模型凭空生成。

快速看懂代码从哪里开始

第一次不需要阅读所有类。先按下面的顺序找入口:

  1. RagController:查看浏览器的问题如何进入 Java。
  2. RagService:查看检索、过滤、Prompt 组装和模型调用如何串联。
  3. QdrantKnowledgeRetrieverQdrantSearchGateway:查看问题向量如何交给 Qdrant。
  4. RagPromptBuilder:查看检索资料如何变成 Prompt。
  5. OllamaAnswerGenerator:查看 Java 如何调用 qwen3。

后续章节会把这些类拆开讲解,所以本篇只需要知道它们在整条链路中的位置。

常见问题与排查顺序

现象 常见原因 先执行什么
localhost:11434 无法访问 Ollama 服务未启动 curl http://localhost:11434/api/tags
提示模型不存在 模型未下载或名称不一致 ollama list
localhost:6333 无法访问 Qdrant 容器未运行 docker ps --filter name=qdrant-study
Collection not found 没有创建 kubernetes_chunks 重新执行创建 Collection 的 PUT 命令
页面一直回答"资料不足" 没有入库,或检索结果低于阈值 检查 points_count 是否大于 0
页面返回 503 Ollama、Qdrant 或模型不可用 依次检查 114346333ollama list
Port 8080 was already in use 已有程序占用 8080 停止旧服务,或临时更换端口
class file version 61.0 Maven 实际使用了 Java 11 检查 mvn -version 中的 Java version

排查时不要一次猜所有环节,按下面顺序逐层检查:

text 复制代码
Ollama 服务
  → 两个模型
  → Qdrant 容器
  → Collection
  → points_count
  → Spring Boot
  → 浏览器

初学者最容易混淆的 6 件事

1. RAG 不是一个需要安装的软件

RAG 是一套流程。本项目用 Java 把 Ollama、bge-m3、Qdrant 和 qwen3 组合成了这套流程。

2. Embedding 模型不会给你生成答案

bge-m3 的任务是输出向量。最终的中文回答由 qwen3:14b 生成。

3. 1024 维不等于有 1024 条知识

1024 维表示一个向量内含 1024 个数字。points_count: 4 才表示 Collection 中有 4 条 Point。

4. Prompt 不是模型中的固定参数

Prompt 是每次调用模型时发给它的指令和上下文。本项目中由 Java 动态组装。

5. Qdrant 中的 ID 不是靠内容相似度自动猜出来的

Point ID 由入库程序生成,用来唯一标识一条数据。相似度用于检索排名,两者用途不同。

6. 向量数据库不是为了让大模型省掉所有 Token

它的核心价值是从大量资料中找到语义相关的少量片段。这会减少不必要的上下文 Token,但"可检索、可扩展、可返回来源"才是更重要的价值。

本篇自测

先不要往下看,尝试自己回答:

  1. qwen3:14bbge-m3 分别负责什么?
  2. 为什么不能只把整个知识库都塞给大模型?
  3. Qdrant 返回的是最终答案,还是相关知识?
  4. points_count 和向量维度有什么区别?
  5. 页面显示的 sources 是谁生成的?

参考答案:

  1. qwen3 生成答案,bge-m3 生成向量。
  2. 整库内容可能超出上下文限制,增加 Token 和噪声,也不利于提供精确来源。
  3. Qdrant 返回相关知识,最终答案由 qwen3 生成。
  4. points_count 是数据条数,向量维度是每条向量内数字的个数。
  5. Java 程序根据 Qdrant 的真实检索结果组装 sources

后续学习路线

不要试图一次记住全部概念,按这个顺序学习即可:

  1. 第 1 篇:安装 Ollama,先学会在本地运行模型。
  2. 第 2 篇:用 Java HTTP 调用模型,并解析 JSON 结果。
  3. 第 3-4 篇:实现交互式多轮聊天,理解上下文和 System Prompt。
  4. 第 5 篇:学习 Embedding 和余弦相似度。
  5. 第 6-7 篇:先跑通 Markdown RAG,再把向量迁移到 Qdrant。
  6. 第 8-11 篇:把 RAG 封装成 Spring Boot API,加入动态知识管理和网页。
  7. 遇到陌生名词时,随时查看第 12 篇术语索引。

模型切换不在主线学习路径中。只有在内存不足、需要提高速度或更换 Embedding 模型时,再查看模型切换附录。

本篇小结

  • RAG 是"检索增强生成",核心顺序是先检索、后生成。
  • Ollama 运行模型,bge-m3 生成向量,Qdrant 检索知识,qwen3 生成回答,Java 串联整个流程。
  • 判断 RAG 是否真正跑通,不能只看到一段 AI 回答,还要能看到真实来源和相似度。
  • 本仓库用 5 个独立模块把完整系统逐层拆开,你可以按章节一步步学,不需要一次理解全部代码。

下一篇

本专栏下一篇:《第1篇:macOS 安装和准备 Ollama》

完整代码和后续更新

本专栏的所有示例代码、自动化测试和更细的分篇文档都已开源:

https://github.com/bysbsh/ai-rag-learning-guide

建议 Clone 到本地边读边运行。如果教程对你有帮助,可以点一个 Star;遇到问题可以提交 Issue,发现错误也欢迎提交 PR。

安全提醒:这是本地学习项目,默认没有登录、权限控制、限流和 HTTPS。不要把 80806333633411434 直接暴露到公网,也不要提交真实密码、令牌、证书或私有文档。

相关推荐
Are_you_kidding_3 小时前
codeX集成deepSeek的API key步骤教程
ai·oneapi
xiaohaiAIgeo3 小时前
【2026年】ASHRAE 110与EN 14175通风柜测试标准对比:进口与国产品牌性能差距
java·前端·数据库·科普知识
武汉星际互动3 小时前
政务智能体进入大厅,需要理解哪些核心问题?
人工智能·政务
别动我齐刘海3 小时前
机器学习基础2——C++、OpenCV、点云、Open3D
c++·人工智能·opencv·机器学习·计算机视觉·机器人·ros2
DeepIntelli3 小时前
品牌内容AI友好化改造:从被搜索引擎收录到被AI引擎引用的技术路径
人工智能·chatgpt
测试_AI_一辰3 小时前
AI Agent 评测最隐蔽的坑-记忆
人工智能·算法·ai·自动化·ai编程
csdn_aspnet3 小时前
Copilot能换成本地吗?VSCode接本地大模型本地化接入方案
ide·vscode·ai·ollama
Hotchip_MEMS3 小时前
TWS耳机微米级较量:超薄LGA封装如何助力MEMS麦克风小型化?
人工智能·笔记·物联网·电脑
lucas_AI3 小时前
给YOLO检测器插 LoRA,'插对地方'比'插什么'更要命
人工智能·算法