Spring AI学习

spring 的ai是一个应用框架,它可以帮助开发者快速构建智能应用。

模型(models)

一种算法,用于生成信息,常见模型有:

  • LLM(Large Language Model)
  • Embedding
  • image generation
  • text-to-voice / voice-to-text

提示符(prompt)

一种文本,用于指导模型生成信息

有多种文本输入,每种都被指派一个角色,例如:

  • system:系统角色,用于指导模型的行为
  • user:用户角色,来自用户的输入

token

AI模型处理的最小单位

在英文中,一个token相当于已给单词的75%

举个例子,莎士比亚的作品,大概90万个单词,大约需要120万个token

实践

接入deepseek聊天模型

环境准备

  • 版本选择
    Spring AI 支持 Spring Boot 3.4.x and 3.5.x.
    jdk 17+
  • API key
    在deepseek官网注册账号,获取API key

添加依赖

xml 复制代码
<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>

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>

<!-- 引入webflux -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

配置参数

配置参数详见:chat_properties

示例:

properties 复制代码
spring.ai.deepseek.api-key=YOUR_API_KEY
spring.ai.deepseek.chat.options.model=deepseek-chat
spring.ai.deepseek.chat.options.temperature=0.8

编写代码

java 复制代码
package com.example.demo.conroller;

import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.deepseek.DeepSeekAssistantMessage;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.ai.deepseek.DeepSeekChatOptions;
import org.springframework.ai.deepseek.api.DeepSeekApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@RestController
public class ChatController {

    private final DeepSeekChatModel chatModel;
    // 存储对话历史
    private final Map<String, List<Message>> conversationMap = new ConcurrentHashMap<>();

    @Autowired
    public ChatController(DeepSeekChatModel chatModel) {
        this.chatModel = chatModel;
    }

    // 单轮对话
    @GetMapping("/ai/generate")
    public Flux<String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return chatModel.stream(message);
    }

    @GetMapping("/ai/generateStream")
    public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        var prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }

    // 多轮对话
    @GetMapping("/ai/generateMultiRoundStream")
    public Flux<String> generateMultiRoundStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message,String conversationId) {
        if(!StringUtils.hasText(conversationId)){
            conversationId = System.currentTimeMillis()+"";
        }
        // 获取当前对话的历史对话
        List<Message> messages = getMessage(conversationId);
        // 添加用户消息
        messages.add(new UserMessage(message));

        // 设置模型类型 DEEPSEEK_REASONER 推导模型
        DeepSeekChatOptions promptOptions = DeepSeekChatOptions.builder()
                .model(DeepSeekApi.ChatModel.DEEPSEEK_REASONER.getValue())
                .build();

        // 创建提示符
        var prompt = new Prompt(messages, promptOptions);
        StringBuffer sb = new StringBuffer();
        return chatModel.stream(prompt).map(chatResponse -> {
            // 获取响应中的文本
            DeepSeekAssistantMessage deepSeekAssistantMessage = (DeepSeekAssistantMessage) chatResponse.getResult().getOutput();
            String text = deepSeekAssistantMessage.getText();
            if(StringUtils.hasText(text)){
                sb.append(text);
            }else{
                text = "";
            }
            return text;
        }).doAfterTerminate(() -> {
            // 把返回的消息添加到对话历史中
            messages.add(new AssistantMessage(sb.toString()));});
    }

    private List<Message> getMessage(String conversationId) {
        List<Message> messages = conversationMap.get(conversationId);
        if(CollectionUtils.isEmpty(messages)){
            ArrayList<Message> list = new ArrayList<>();
            conversationMap.put(conversationId, list);
            return list;
        }else{
            return messages;
        }
    }
}
相关推荐
海石5 小时前
📱随时随地大小编:TraeSolo 移动端初体验
前端·ai编程·trae
mCell5 小时前
批判性思维:AI 时代程序员最容易忽视的能力
ai编程·claude·vibecoding
庞轩px8 小时前
第七篇:Spring扩展点——如何优雅地介入Bean的创建流程
java·后端·spring·bean·aware·扩展点
ltl8 小时前
Q/K/V 三件套:把 Bahdanau 抽象成一个公式
后端
千叶风行10 小时前
Text-to-SQL 技术设计与注意事项
前端·人工智能·后端
阿kun要赚马内10 小时前
后端数据操作组合:Pydantic与ORM
后端·python·orm·sqlalchemy
kyriewen11 小时前
坏了,黑客学会用AI写外挂了
前端·程序员·ai编程
爱吃的小肥羊11 小时前
Claude Code 推出Agent View,一个人同时指挥十个 AI 写代码!
aigc·ai编程
花米徐11 小时前
技术洞察精选 | 2026年4月28日 — 5月4日
后端·python·flask
达达尼昂11 小时前
Claude 多 Agent 系统:从零搭建一个 4 Agent 团队
前端·架构·ai编程