SpringAI整合DeepSeek,阿里百炼大模型

SpringAI整合DeepSeek,阿里百炼大模型

1. DeepSeek账号注册,生成Api-Key

访问DeepSeek开放平台:[https://platform.deepseek.com/usage](https://platform.deepseek.com/usage),注册DS账号,获取Api-Key。

2. 阿里账号注册,生成Api-Key

访问阿里百炼开放平台:[https://www.aliyun.com/product/tongyi](https://www.aliyun.com/product/tongyi),注册阿里账号,获取Api-Key。

3. SpringAI对接大模型

搭建springboot项目,引入相关依赖。
注意:

需要引入springboot 3.x.x版本的依赖

JDK版本需要大于17

使用高版本Idea(低版本无法兼容JDK17)
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.4</version>
        <relativePath/> 
    </parent>

    <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.ai</groupId>
         <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
     </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-M6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

随后需要编写相关配置,例如:baseUrl、Api-key等(DS、阿里百炼均可使用OpenAI协议对接大模型)

spring:
  application:
    name: springai
  #阿里百炼模型配置
  ai:
    openai:
      api-key: xxxx(自己申请的api-key)
      base-url: https://dashscope.aliyuncs.com/compatible-mode
      chat:
        options:
          model: qwen-plus
  #ds模型配置        
  ai:
    openai:
      api-key: xxxx(自己申请的api-key)
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat

基础配置配置完成之后,需要在spring容器中新建一个ChatClient的Bean,用于托管相关固定配置,例如:日志、系统提示词、会话记忆等。

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;

/**
 * @Description:
 * @Param:
 * @Author:
 * @Date:
 */
@Configuration
public class Client {


    @Bean
    public ChatMemory chatMemory(){
        return new InMemoryChatMemory();
    }

    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel){
        return ChatClient.builder(openAiChatModel)
                .defaultSystem("你是一个智能助手,名字叫CJ")
                .build();
    }
}

新增接口,用于实现接口访问,调用远程大模型。

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class TestController {

    private final ChatClient client;
    
	 /**
     * 1.流式响应接口,内容不会一次性返回
     * 2.若要一次性返回,则需要将stream()方法切换为call()方法
     * 3.使用流失返回,需要注明接口返回提字符编码,否则会导致乱码!(produces = "text/html;charset=utf-8")
     * @param prompt 用户提示词
     * @return
     */
    @GetMapping(value = "/chat", produces = "text/html;charset=utf-8")
    public Flux<String> chat(@RequestParam(value = "prompt") String prompt){
        
        return client.prompt()
                .user(prompt)
                .stream()
                .content();
    }

}

至此,大模型会话功能的调用已经初步实现了,但是为了方便开发以及问题定位,我们需要引入相关日志组件,便于排查开发、调试用遇到的问题。
SpringAI给我们提供了多种日志工具,我们使用SimpleLoggerAdvisor组件。该组件是将日志输出在控制台上。
日志配置主要分为两步:
1.在ChatClient中配置Advisor,其原理是在在调用模型前后,利用AOP的原理执行相关动作;
2.配置日志级别。

@Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel){
        return ChatClient.builder(openAiChatModel)
                .defaultSystem("你是一个智能助手,名字叫CJ")
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }
logging:
  level:
    org.springframework.ai.chat.client.advisor: debug
    com.controller: debug

此时在控制台中可以看到相关的日志输出,但是缺乏提示词的记忆。例如:
步骤一:提示词内容为“我的名字叫xx”,发送请求大模型;
步骤二:提示词内容为“我叫什么?”,发送请求大模型;
输出结果:大模型不清楚我的名字是什么。。。
出现当前问题的原因是当前程序中并未开启相关会话记忆功能。

SpringAI给我们提供了相关会话记忆的工具(InMemoryChatMemory),同样是使用Advisor做会话记忆,将每次会话内容存储在内存中,再发送新消息是,默认发送用户之前输入、输出的历史会话内容。由此可见,与大模型对话次数越多,效率则会越差。
我们可以重写InMemoryChatMemory中的方法,来自定义会话内容的存储位置以及存储方式。目前仅介绍使用原生InMemoryChatMemory方法来做会话存储。

    @Bean
    public ChatMemory chatMemory(){
        return new InMemoryChatMemory();
    }

	    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel){
        return ChatClient.builder(openAiChatModel)
                .defaultSystem("你是一个智能助手,名字叫CJ")
                .defaultAdvisors(new SimpleLoggerAdvisor(), new MessageChatMemoryAdvisor(chatMemory()))
                .build();
    }

现在,按照之前的步骤输入内容,大模型已经可以返回我们的名字是什么了。但是在一个成熟的人机会话交互产品中,仍然缺少很多东西。例如:可查询,可见的会话历史、开启新窗口而开启新的会话等;这些需要我们借助前端来实现。例如:前端在每一个用户下的会话窗口提供一个唯一ID,当前ID会传递到后端用于做会话标识存储起来(MySQL等),同时存储不同会话ID下的历史会话记录。

4.实现基于RAG索引实现本地向量知识库

  • RAG
    在我们对接好大模型之后,会发现简单的问题,大模型可以给予我们帮助。但是对待一些专业性比较强的问题,大模型也无法就我们正确的答案,并且有时可能会出现大模型随意乱造结果(幻觉),影响用户的判断。为了解决这一问题,我们引入了RAG以及向量数据库,便于无需二次训练模型即可生成正确回答,减少幻觉发生的概率。

    Retrieval-Augmented Generation,检索、增强、生成。其中检索模块负责从外部知识库中搜索与用户问题最相关的文本内容。生成模块负责将检索到的相关信息整合成自然语言的答案。

  • RAG的工作流程

    1.问题输入
    用户向RAG系统提出一个自然语言问题。

    2.检索相关文档
    RAG系统的检索模块根据用户的问题,从外部知识库中检索出最相关的文档或段落。

    3.信息整合
    检索到的文档或段落被传递给生成模块,生成模块将这些信息与用户的问题结合起来。

    4.生成答案
    生成模块利用预训练的语言模型,生成最终的自然语言答案。

    SpringAI给我们提供了一套实现方式,基于内存的向量数据库,基于Redis的向量数据库等。为了快速上手,我们先通过内存的方式。

引入依赖

<!-- 处理PDF文件 -> document文件 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>

新增向量模型相关配置

spring:
  application:
    name: xx
  ai:
    openai:
      api-key: xxxxx
      base-url: https://dashscope.aliyuncs.com/compatible-mode
      chat:
        options:
          model: deepseek-r1
      #向量模型配置    
      embedding:
        options:
          model: text-embedding-v3
logging:
  level:
    org.springframework.ai.chat.client.advisor: debug
    com.chinaunicom.controller: debug

到此,基本的环境已经具备,现在需要我们将本地PDF文件当做资料上传给我们的向量数据库中用作检索(SimpleVectorStore:基于内存存储的向量数据库)。

/**
     * 初始化一个基于内存存储的向量数据库
     * @param embeddingModel
     * @return
     */
    @Bean
    public VectorStore vectorStore(OpenAiEmbeddingModel embeddingModel) {
        return SimpleVectorStore.builder(embeddingModel).build();
    }

    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel, ChatMemory chatMemory, VectorStore vectorStore) {
        return ChatClient
                .builder(openAiChatModel)
                .defaultSystem("你是一个智能助手,名字叫CJ")
                //日志横切面监控
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        new MessageChatMemoryAdvisor(chatMemory),
                        //配置向量搜索
                        new QuestionAnswerAdvisor(vectorStore, SearchRequest.builder().similarityThreshold(0.5f).topK(2).build()))
                .build();
    }

此时,基本的向量数据库已经搭建好了,现在需要我们上传相关资料。

    /**
     * 写入向量库
     */
    @GetMapping(value = "/storePdf", produces = "text/html;charset=utf-8")
    public String storePdf(){

        Resource resource = new FileSystemResource("D:\\1.pdf");

        //创建PDF读取
        PagePdfDocumentReader reader = new PagePdfDocumentReader(
                resource, // 文件
                PdfDocumentReaderConfig.builder()
                        .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
                        .withPagesPerDocument(1) // 每1页PDF作为一个Document
                        .build()
        );

        //转存入向量库
        List<Document> documents = reader.read();
        vectorStore.add(documents);

        return "success";
    }

/**
     * 基于向量库的问答
     * @param question
     * @return
     */
    @GetMapping(value = "/ragChat", produces = "text/html;charset=utf-8")
    public Flux<String> ragChat(@RequestParam(value = "question")String question){
        return client.prompt().user(question).stream().content();
    }
### 整合 SpringAIDeepSeek 框架 为了实现 SpringAIDeepSeek整合,开发者可以利用 Spring 提供的强大生态支持以及其便捷的配置方式来简化这一过程。Spring 官网指出,Spring 框架可以通过 OpenAI API 方式与 DeepSeek 集成[^1]。 具体来说,在项目中引入必要的依赖库之后,主要工作集中在配置文件设置上: #### 添加 Maven 或 Gradle 依赖项 对于基于 Java 的应用程序而言,通常会采用 Maven 或者 Gradle 来管理项目的构建流程。因此,第一步是在 `pom.xml` 文件(Maven)或 `build.gradle` 文件(Gradle)里加入所需的依赖包。 ```xml <!-- pom.xml --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-core</artifactId> <version>${spring-ai.version}</version> </dependency> <dependency> <groupId>com.deepseek.api</groupId> <artifactId>deepseek-client-java</artifactId> <version>${deepseek-api-version}</version> </dependency> ``` ```groovy // build.gradle implementation 'org.springframework.ai:spring-ai-core:${springAiVersion}' implementation 'com.deepseek.api:deepseek-client-java:${deepSeekApiVersion}' ``` #### 创建应用配置类 接着创建一个新的配置类用于定义如何初始化并连接到 DeepSeek 服务端点。这一步骤涉及到读取环境变量中的认证信息和其他必要参数,并将其传递给客户端实例化方法。 ```java @Configuration public class AiConfig { @Value("${deepseek.api.key}") private String apiKey; @Bean public DeepSeekClient deepSeekClient() { return new DeepSeekClient.Builder() .setApiKey(apiKey) .build(); } } ``` #### 使用自动装配功能注入 DeepSeek Client Bean 最后,在任何需要调用 AI 功能的地方都可以直接通过 Spring 自动装配机制获取已经准备好的 `DeepSeekClient` 对象来进行交互操作。 ```java @Service public class MyAIService { private final DeepSeekClient client; @Autowired public MyAIService(DeepSeekClient client) { this.client = client; } // 实现业务逻辑... /** * 调用 DeepSeek 接口处理请求. */ public void processRequest(String inputText){ var response = client.sendQuery(inputText); System.out.println(response.getResult()); } } ``` 上述代码片段展示了基本的应用程序结构和组件之间的关系。当然实际应用场景可能会更加复杂一些,但这提供了一个良好的起点以便进一步探索更多可能性。 Spring AI 解决了 Spring 生态和 AI 的快速集成问题:它能够帮助企业轻松地将内部的数据资源和服务接口同外部的人工智能模型对接起来,从而加速智能化转型的步伐[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值