一、什么是RAG?
检索增强生成(RAG,Retrieval-Augmented Generation)
本地知识库
RAG 的中文名称是检索增强生成,从字面意思来理解,包含三个检索、增强和生成三个过程。
解释:大语言模型(LLM)与外部知识源结合(文档、数据库、向量数据库、ES...),使查询结果,更加符合自身业务要求。


把我们的文档里的文字进行向量化处理处理
狗=[0.77,0.31,0.12,..] 768 10
猫=[0.76,0.29,0.11...]
苹果=[0.11,0.88,0.55...]
如何距离计算?
欧氏距离:两点之间的距离
余弦相似度
cosθ (θ=0) = 1
cosθ (θ=90) = 0
cosθ (θ=180) = -1
1、通过余弦相似度计算,夹角越小,接近0°,越相似。
2、如果垂直90°不相干。
3、如果方向相反180°完全相反。

余弦公式简洁高效:余弦相似度依赖于点积和模长 cos(θ) = (A·B) / (||A|| * ||B||) √
狗=[0.77,0.31,0.12,..] a1 a2 a3 a4...
猫=[0.76,0.29,0.11...] b1 b2 b3 b4
点积 x =a1b1+a2b2
模长y = (√a1a1 + a2b2 +.....anan) *√b1b1+b2b2+...bnbn)
cos(θ) = x/y;
为什么不用正弦?
1、因为cos(θ)可以用向量直接表示出来;而需要计算正弦,必须先计算余弦sin(θ) = √(1 - cos²(θ)),多一个步骤
2、cos(θ)的 更符合事物相关性的理解
θ=180, cos(θ)=-1 相反
θ=90, cos(θ)=0 不相干
θ=0 , cos(θ)=1 相似度一样
距离越近,相似度越高,理解一致
如何查询?
RAG查询的流程

文本->chunks方法?
word2Vec ,cnn,bear
1、大文件转chunks文本块
2、通过Embedding模型把chunks向量化
3、存储向量数据到数据库
4、查询条件也需要向量化
5、通过余弦相似度查询
6、返回相似的结果列表
7、通过rerank排序模型排序
8、传给大模型让LLM学习后组织语言输出
二、接入阿里云千问
- 官网进入大模型

-
模型平台

-
创建密钥


记录key
sk-ws-H.RXELRHM.mUuS.MEQCIBRpRl5lzLZdg86Cf9Lp7eQKTHZjmU539gVCw1tmWSUuAiBbEekjQNDuADTO4_busZas8CFnYfXKBRXoLlz6DAGmUw

进入模型广场,找到自己想要的模型,记录Code,程序中需要使用

三、spring-ai-alibaba集成
https://java2ai.com/docs/1.0.0.2/get-started/chatbot/?spm=5176.29160081.0.0.2856aa5cy1hqcy
1、集成chatclient
1、引入依赖
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.0.0.2</version>
</dependency>
版本管理的依赖:spring-ai-alibaba-bom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>1.0.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、加配置
server:
port: 9090
spring:
ai:
dashscope:
api-key: sk-4767fcc8e0c54f319f0b30e4cb3473cd
chat:
options:
model: qwen-plus
3、ChatClient 配置
https://github.com/alibaba/spring-ai-alibaba/blob/main/README.md 代码都在这里

各种Demo可以学习:

package com.dw.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* @author daiwei
* @Description:
*/
@Configuration
public class RagConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
//定义一个ai角色描述,作为ai的初始角色描述
return builder.defaultSystem("你将作为一名房东,回复租客要求")
.build();
}
}
4、Controller
package com.dw.controller;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel;
import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@RestController
@RequestMapping("/api")
public class AiController {
//调用ai对话的客户端对象
@Autowired
private ChatClient chatClient;
@GetMapping("/hello")
public String hello(@RequestParam("chat") String chat) {
String content = chatClient.prompt()
.user(chat)
.call().content();
return content;
}
}
流式处理
@GetMapping("/stream/chat")
public Flux<String> streamChat(@RequestParam(value = "chat") String chat, HttpServletResponse response) {
response.setCharacterEncoding("UTF-8");
return chatClient.prompt(chat).stream().content();
}
或者
@GetMapping("/streamhello")
public void streamhello(@RequestParam("chat") String chat) {
// 调用AI模型的流式处理方法,传入初始提示词"你好",返回一个Flux流
Flux<String> stream = chatClient.prompt().user(chat)
.stream().content();
stream.toIterable().forEach(System.out::println);
}
2、加入嵌入向量模型


1、加依赖
要想AI使用RAG增强后回答问题,必须要加入spring-ai-advisors-vector-store依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>
同时需要加入对向量的版本管理spring-ai-bom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2、增加向量模型
向量模型:text-embedding-v4
spring:
ai:
dashscope:
api-key: sk-4767fcc8e0c54f319f0b30e4cb3473cd
chat:
options:
model: qwen-plus
embedding:
options:
model: text-embedding-v4
dimensions: 2048
3、controller
https://github.com/alibaba/spring-ai-alibaba/blob/main/README.md 代码都在这里


RAG增强关键代码如下:
.advisors(new QuestionAnswerAdvisor(simpleVectorStore))
说明:
1、接收用户问题
2、advisors插入逻辑
3、通过QuestionAnswerAdvisor进行向量检索(检索)
4、检索出的结果,附加在用户的提示词里,变成新的提示词(增强)
5、新提示词给AI大模型回答(生成)
完整方法代码:
@Autowired
DashScopeEmbeddingModel embeddingModel;
/**
* 向量化
* @param chat
* @return
*/
@GetMapping(value = "/ragchat", produces = "text/plain; charset=UTF-8")
public String ragchat(@RequestParam("chat") String chat) {
SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel)
.build();
List<Document> documents = List.of(
new Document("房屋出租协议:租房协议\n" +
"租期內房租为每月人民币 9999 元整,(大写人民币贰任会佰元整。\n" +
"1.租金按季度结算, 乙方于 2025年4月3日前向甲方支付首季度房租, 。\n" +
"2.租期内物业,水电、天然气、宽带等一切费用由乙方支付, 按时交纳,如按时不交拖欠,拖欠1个月,甲方有权终止合同后收回房子并扣押金,如因约定支付未能及时交纳以上费用发生的滞纳金也应由其支付。\n" +
"3.在租用期內, 不得转租、 转借, 转让他人租用, 或另做它用, 乙方不得利用所租房屋从事非法活动 (含传销), 则甲方有权解除租约,收回住房使用权并扣押金。\n"));
simpleVectorStore.add(documents);
// 发起聊天请求并处理响应
return chatClient.prompt()
.user(chat)
.advisors(new QuestionAnswerAdvisor(simpleVectorStore))
.call()
.content();
}
4、测试一下
看看怎么回答
http://localhost:9999/api/ragchat?chat=我要租房
3、单独向量化
直接使用embeddingModel向量化内容
@GetMapping("/embedding_hello")
public void embedding_hello(@RequestParam("chat") String chat) {
float[] embedding = embeddingModel.embed(new Document(chat));
System.out.println(embedding);
}
4、问答记忆
1、增依赖
!--记忆依赖-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-autoconfigure-model-chat-memory</artifactId>
</dependency>
2、配置类增加 ChatMemory bean和ChatClient使用这个advisors
@Autowired
ChatMemory chatMemory; //注入一个对话的上下文记忆
@Bean
ChatClient chatClient(ChatClient.Builder builder) {
//定义一个ai角色描述,作为ai的初始角色描述
return builder
.defaultAdvisors(PromptChatMemoryAdvisor.builder(
chatMemory).build()) //builder的时候加入上下文记忆功能
.defaultSystem("你将作为一名房东,回复租客要求")
.build();
}
5、图片生成
图片生成同样也需要,图面的模型对象
注入图片模型bean入下:
@Autowired
DashScopeImageModel dashScopeImageModel;
添加请求方法
@GetMapping("/txt2img")
public String txt2img(@RequestParam("chat") String chat) {
DashScopeImageOptions imageOptions =DashScopeImageOptions.builder().withModel("qwen-image-plus").build();
ImageResponse imageResponse = dashScopeImageModel.call(new ImagePrompt(chat,imageOptions));
String url = imageResponse.getResult().getOutput().getUrl();
System.out.println(imageResponse.getResult().getOutput().getB64Json());
return url;
}
6、TTS(练习)
29-3阶内容-2.2.5-接入千问与RAG
https://xiaochenblog.icu/archives/29-3jie-nei-rong-2.2.5-jie-ru-qian-wen-yu-rag
评论