一、什么是RAG?

检索增强生成(RAG,Retrieval-Augmented Generation)

本地知识库

RAG 的中文名称是检索增强生成,从字面意思来理解,包含三个检索、增强和生成三个过程。

解释:大语言模型(LLM)与外部知识源结合(文档、数据库、向量数据库、ES...),使查询结果,更加符合自身业务要求。

image-20250910101722090image-20250910101749538

把我们的文档里的文字进行向量化处理处理

狗=[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°完全相反。

image-20250910222904806

余弦公式简洁高效:余弦相似度依赖于点积模长 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查询的流程

image-20250910224805320

文本->chunks方法?

word2Vec ,cnn,bear

1、大文件转chunks文本块

2、通过Embedding模型把chunks向量化

3、存储向量数据到数据库

4、查询条件也需要向量化

5、通过余弦相似度查询

6、返回相似的结果列表

7、通过rerank排序模型排序

8、传给大模型让LLM学习后组织语言输出

二、接入阿里云千问

  • 官网进入大模型

image-20250909162010703

  • 模型平台

    image-20250909162138570

  • 创建密钥

image-20250909162227181

记录key

sk-ws-H.RXELRHM.mUuS.MEQCIBRpRl5lzLZdg86Cf9Lp7eQKTHZjmU539gVCw1tmWSUuAiBbEekjQNDuADTO4_busZas8CFnYfXKBRXoLlz6DAGmUw

image-20250909162244881

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

image-20250909162546643

三、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 代码都在这里

image-20251121153057233

各种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、加入嵌入向量模型

image-20251121152720049

image-20251121152737971

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 代码都在这里

image-20260701205914568

image-20251127095005725

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(练习)