认识RAG原理
RAG(Retrieval-Augmented Generation)(本地知识库)是一种结合信息检索和大语言模型(LLM)的技术,目的是在解决传统生成模型的局限性。
- 传统大语言模型(如 GPT-4、Llama 3)依赖训练时的数据,无法动态获取最新信息,有了RAG在生成答案前,先从外部知识库(如数据库、文档、网页)检索最新信息,确保答案的时效性
- LLM 可能会生成看似合理但实际错误的答案(即“幻觉”),基于检索到的可信数据生成答案可以减少编造信息的风险
- 通用 LLM 可能缺乏特定行业(如医疗、法律)或企业内部数据(如公司文档)的知识。RAG 允许接入自定义知识库(如企业文档、科研论文),提供更精准的回答。
RAG 的核心价值在于让 LLM 的生成能力与外部知识库的动态检索相结合,既保留了 LLM 的语言理解能力,又弥补了其在时效性、准确性和专业性上的不足。对于需要实时数据、私有知识或可解释性的应用,RAG 是目前最有效的解决方案之一
RAG的工作原理
RAG 流程分为两个不同的阶段:索引(创建RAG)和检索(搜索RAG),LangChain4j 为这两个阶段提供了工具。索引阶段指的是把提前准备好的数据给LLM建立RAG知识库,这些数据可以是公司的内部数据,某在线文档,或者用户上传的文档等。以下是索引阶段的简化图
- Document : 我们准备用来建立知识库的数据
- TextSplitter : 文本切割器,用于把一段大文本按照某种规则切成多个小段,以方便创建向量,因为每个模型处理的文本都是有长度限制的。
- Segments : 代表文本切割后的每个分段
- EmbeddingModel : 向量模型,创建RAG索引的过程需要通过 向量模型 为文本创建向量并存储到向量数据库中。向量是数学中的一个定义,这里的意思是文本向量化:将单词、句子或文档转换为数值向量(如 [0.2, -0.7, 0.5, …])
- EmbeddingStore :向量存储,需要准备向量数据库用于存储文本转换后的向量
检索阶段通常发生在线,当用户提交需要使用索引文档来回答的问题时,LLM根据用户的提问去RAG中进行搜索。以下是检索阶段的简化图
用户的提问会被EmbeddingModel向量模型转化为向量去向量数据库中进行查找,检索到的相关数据会通过LanguageModel对话模型处理后响应给用户。
Docker安装Pgvector
可以支持向量存储的数据库很多,比如:Redis,ES都可以,我这里选择使用PGVector,参考官网文档:https://docs.spring.io/spring-ai/reference/api/vectordbs/pgvector.html#page-title
1. 安装DockerDesk
因为没有服务器,我就在windows电脑上通过DockerDesk来安装了,首先需要下载docker-desktop:https://www.docker.com/products/docker-desktop/,根据引导安装好DockerDesktop,可以参考《Ollama+WebUI+DeepSeek部署自己的本地大模型》docker-desktop安装部分。
2. 安装Pgvector
通过终端执行docker命令创建pgvecor容器
docker run --name pgvector -v c:/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5433:5432 -d ankane/pgvector
- POSTGRES_PASSWORD : 密码
- -p 5433:5432 :端口是5433
使用navcat新建连接选择:postgressql ,数据库和用户名默认写postgres
选中数据 - 编辑数据库 - 扩展 - 找到vector - 移动到后边代表已安装该插件
PS:也可以通过CREATE EXTENSION vector;
来创建插件
执行下面SQL测试向量数据库
-- 创建测试向量表
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
-- 插入向量数据
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
效果如下
Windows安装Pgvector
1.安装PgSql
首先需要先安装PGSql ,下载路径 : https://www.enterprisedb.com/downloads/postgres-postgresql-downloads , 安装参考文档:https://www.enterprisedb.com/docs/supported-open-source/postgresql/installing/windows/,
2.开启Pgector
开启Pgector 需要有C++环境,所以先在电脑上安装 Visual Studio 下载路径:https://learn.microsoft.com/en-us/visualstudio/releases/2022/system-requirements ,下载执行安装,选择使用c++桌面开发
确保安装了Visual Studio中的C++支持,并运行:
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
注意:具体路径将根据 Visual Studio 版本而有所不同,然后使用nmake来构建:
set "PGROOT=C:\Program Files\PostgreSQL\16"
cd %TEMP%
git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
cd pgvector
nmake /F Makefile.win
nmake /F Makefile.win install
其他注意事项
-
缺少标头 :如果编译失败Cannot open include file: ‘postgres.h’: No such file or directory,请确保PGROOT正确。
-
不匹配的架构 :如果编译失败error C2196: case value ‘4’ already used,请确保vcvars64.bat已调用。然后运行nmake /F Makefile.win clean并重新运行安装说明。
-
缺少符号 :如果unresolved external symbol float_to_shortest_decimal_bufn与 Postgres 17.0-17.2 链接失败,请升级到 Postgres 17.3+。
-
权限 :如果安装失败Access is denied,请以管理员身份重新运行安装说明。
RAG实战
1.导入依赖
- spring-ai-starter-vector-store-pgvector 是用于支撑pgvector向量存储的基础依赖
- spring-ai-advisors-vector-store : 是支撑向量数据库检索的基础依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
2.修改yml配置
在之前的yml基础上做一些修改
- 数据源我修改为了pgsql数据库
- 增加spring.ai.vectorstore 向量存储相关配置
- 增加ollama本地向量模型配置
spring:
datasource:
# datasourcedriver-class-name: com.mysql.cj.jdbc.Driver
# username: root
# password: 123456
# url: jdbc:mysql://127.0.0.1/ai-girl
url: jdbc:postgresql://localhost:5433/postgres
username: postgres
password: 123456
ai:
vectorstore: #向量存储相关
pgvector:
initialize-schema: true #自动创建表
index-type: HNSW #索引的算法
distance-type: COSINE_DISTANCE #使用 余弦距离 作为度量标准
dimensions: 384 #向量模型 all-minilm:latest 的维度
openai:
api-key: ${API_KEY}
base-url: https://dashscope.aliyuncs.com/compatible-mode
chat:
options:
model: qwen-max-latest
temperature: 1
chat:
memory:
repository:
jdbc:
initialize-schema: never #不要初始化表,不然会报错
model:
embedding: ollama #启用ollama
ollama:
embedding: #ollama本地向量模型配置
options:
model: all-minilm:latest #向量模型
truncate: true
base-url: http://localhost:11434
server:
port: 8888
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
logging:
level:
org.springframework.ai: debug
org.ai.agent: debug
在SpringAI中当我们导入了 vector 相关依赖,并在yml做了相关配置后,SpringAI会自动帮我们装配好VectorStore Bean,直接使用即可。且启动查询SpringAI会自动创建 vector_store 表
注意:我这里使用的是Ollama本地向量模型,如果要使用远程的可以参考Spring官网的配置:https://docs.spring.io/spring-ai/reference/api/embeddings/openai-embeddings.html
3.定义一个RAG Client
定义一个专门用于RAG检索的client,当然也可以使用之前的client
@Bean
public ChatClient ragClient(OpenAiChatModel model){
return ChatClient.builder(model)
//日志打印的增强器
.defaultAdvisors(new SimpleLoggerAdvisor()).build();
}
4.基于TXT创建知识库
现在我们需要把PDF,或者TXT文档作为知识库源文件Load到知识库,这里以txt文本为例
@RequestMapping(value = "/ai/rag/load")
public String ragLoad(@RequestParam("file") MultipartFile file){
//把上传的txt文件转化为Document
DocumentReader txtReader = new TextReader(file.getResource());
List<Document> documents = txtReader.read();
//文档切块
//chunkSize :表示每个文本块的目标大小,通常以token数量为单位
//minChunkSizeChars :每个块必须包含的最小字符数,用于确保块不会太小
//minChunkLengthToEmbed:只有达到这个长度的块才会被处理/嵌入
//maxNumChunks:从单个文档生成的最大块数限制 防止单个文档产生过多的块
//keepSeparator (保留分隔符)
DocumentTransformer textSplitter = new TokenTextSplitter(200,20,5,10000,true);
List<Document> transformDocuments = textSplitter.transform(documents);
//Load
vectorStore.write(transformDocuments);
return "success";
}
定义一个RAG检索的Controller
private final VectorStore vectorStore;
private final ChatClient ragClient;
@RequestMapping(value = "/ai/rag/search")
public Flux<String> ragSearch(@RequestParam String prompt){
//配置向量检索增强器
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
//设置答案的准确度 和 前N条数据。准确率越高答案越准确,同时也有可能无法找到内容
.searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(6).build())
.build();
return ragClient
.prompt("请基于知识库检索到的内容来回答").user(prompt)
.advisors(qaAdvisor)
.stream().content();
}
- 首先需要通过prompt指定系统提示词,明确的告诉大模型需要去知识库来检索内容
- 通过QuestionAnswerAdvisor去构建RAG检索增强,可以指定准确率和前N条数据作为参考
5.RAG测试
首先需要准备一个TXT文档,通过上传接口上传RAG知识库文档,上传成功后 观察 vector_store 表中的数据。然后调用RAG检索接口,观察是不是从RAG知识库中检索到的档案
6.基于PDF创建RAG
如果要使用PDF作为知识库上传,那么需要导入如下依赖
PDF加载到知识库代码如下
// 1.创建PDF的读取器
PagePdfDocumentReader reader = new PagePdfDocumentReader(
file.getResource(), // 文件源
PdfDocumentReaderConfig.builder()
.withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
.withPagesPerDocument(1) // 每1页PDF作为一个Document
.build()
);
...省略...
总结
本片文章到这里就结束了,我们学习了什么是RAG知识库以及它的原理,然后基于Ollama本地模型all-minilm:latest完成了RAG的创建和检索,这个过程并不复杂,麻烦的是SpringAI 1.0.0和之前的版本的API差异很大,无法完全复用,所以需要多参考官方文档。本文知识使用其中一种方式来实现RAG知识库,你可以自己尝试更多的向量模型,或者向量数据库。如果文章对你有帮助不要吝啬你的三连,你的鼓励是我最大的动力哦!!!