1.什么是Spring AI

Spring AI 是一个用于 AI 工程的应用程序框架。支持例如OpenAI,Google ,Ollama等AI模型供应商

支持跨 AI 提供商对同步和流式处理 API 选项的可移植 API 支持

2.构建支持AI的项目

3.Ollama常用命令

  1. ollama list:列出所有已下载的模型,显示模型名称、ID、大小和修改时间。

  2. ollama ps:列出当前正在运行的模型实例,显示模型 ID 和状态。

  3. ollama pull <model>:从 Ollama 模型库拉取指定模型到本地,未拉取的模型无法使用。

  4. ollama run <model>:运行指定模型并进入交互式命令行模式,可直接与模型对话,按Ctrl+D或输入/exit退出。也可在命令后直接跟提示词,如ollama run llama3 "用中文写一首关于秋天的诗"

  5. ollama rm <model>:删除指定模型,移除本地已下载的模型以释放磁盘空间。

  6. ollama push <model>:将本地模型推送到 Ollama 模型库,适合分享自定义模型,需登录并确保已配置模型库的访问权限。

  7. ollama help:显示所有可用命令和帮助信息,可快速查看命令列表和用法。

  8. ollama show <model>:显示模型的详细信息,包括模型的 Modelfile、参数、系统提示等。

  9. ollama --version:显示 Ollama 的版本号,用于检查是否需要更新。

4.选用模型

测试路径 :http://localhost:11434/api/chat

测试参数:

{
    "model":"deepseek-r1:7b",
    "messages":[
        {
            "role":"system",
            "content":"你是一个非常热心且热情的ai小助手,你叫的名字叫小明,请以小明的身份回答用户的问题"
        },
        {
            "role":"user",
            "content":"你是谁"
        }
    ],
    "stream":false
}
model:指定要使用的模型名称及版本
messages:对话历史数组,按时间顺序排列,包含角色和内容。
stream:是否启用流式响应

5.简单的项目搭建

所需依赖

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring AI 核心依赖 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-core</artifactId>
        <version>1.0.0-M6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-client-chat</artifactId>
        <version>${spring-ai.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-model</artifactId>
        <version>${spring-ai.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
        <version>1.0.0-M6</version>
    </dependency>
    
    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    
    <!-- Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
​

配置文件

spring:
  application:
    name: ZhenGe-ai
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        model: deepseek-r1:7b

配置类

@Configuration
public class SpringAiConfig {
​
    @Bean
    public ChatClient chatClient(OllamaChatModel model) {
        return ChatClient.builder(model)
                .defaultSystem("你现在叫小明,请以小明的身份跟我聊天")//设置默认系统提示
                .defaultAdvisors(            //用于拦截和处理对话流程
                        new SimpleLoggerAdvisor()  //日志记录器,会打印对话的输入和输出
                )
                .build();
    }
}

控制层

@RequestMapping(value = "chat", produces = "text/html;charset=utf-8")
public Flux<String> chat(@RequestParam String message) {
    return chatClient.prompt()//创建一个 AI 对话请求构建器
            .user(message)//将用户输入的消息作为用户角色(User Role)添加到对话中。
            .stream()//启用流式处理模式 
            .content();
            
            // .generate()  // 同步生成完整结果
            //.getContent();
}

6.支持会话记录

配置类

@Configuration
public class SpringAiConfig {
    @Bean
    public ChatMemory chatMemory() {//返回类型是 Spring AI 框架中的聊天记忆接口,用于存储和管理对话历史。
        return new InMemoryChatMemory();
    }
​
    @Bean
    public ChatClient chatClient(OllamaChatModel model,ChatMemory chatMemory) {
        return ChatClient.builder(model)
                .defaultSystem("你现在叫小明,请以小明的身份跟我聊天")
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        new MessageChatMemoryAdvisor(chatMemory)
                )
                .build();
    }
}

7.支持历史记录及查询角色对话历史记录

在repository包下创建

public interface ChatHistoryRepository {
    void save(String type,String chatId);
    List<String> getChatById(String type);
}
@Component
public class InMemoryChatHistoryRepository implements ChatHistoryRepository{
    private static final int MAX_HISTORY_SIZE = 5;
    private final Map<String , List<String>> list = new HashMap<>();
    
    @Override
    public void save(String type, String chatId) {
        if(!list.containsKey(type)){
            list.put(type, new ArrayList<>());
        }
        List<String> chatIds = list.get(type);
        if (chatIds.contains(chatId)){
            return;
        }
        
        // 如果历史记录达到上限,删除最早的一条
        if (chatIds.size() >= MAX_HISTORY_SIZE) {
            chatIds.remove(0);  // 删除列表中第一个元素(最早添加的)
        }
        
        chatIds.add(chatId);
    }
​
    @Override
    public List<String> getChatById(String type) {
        return list.getOrDefault(type,new ArrayList<>());
    }
}

返回类

package cn.zhentao.vo;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.MessageType;

/**
 * @autho:周明震
 * @date 2025/7/14
 */
@NoArgsConstructor
@Data
public class MessageVo {
    private String role;
    private String content;

    public MessageVo(Message message) {
        MessageType messageType = message.getMessageType();
        switch(message.getMessageType()) {
            case USER:
                role = "user";
                break;
            case ASSISTANT:
                role = "assistant";
                break;
            default:
                role = "unknown";
                break;
        }
        this.content = message.getText();
    }
}

控制层

package cn.zhentao.controller;


import cn.zhentao.repository.ChatHistoryRepository;
import cn.zhentao.vo.MessageVo;
import lombok.RequiredArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("ai")
@CrossOrigin(origins = "*")
public class SpringAiController {
    private final ChatClient chatClient;
    private final ChatHistoryRepository chatHistoryRepository;
    private final ChatMemory chatMemory;
    @RequestMapping(value = "chat", produces = "text/html;charset=utf-8")//响应内容类型为 HTML,编码为 UTF-8。
    public Flux<String> chat(@RequestParam String message, @RequestParam String chatId) {//表示异步流式响应
        chatHistoryRepository.save("chat", chatId);
        return chatClient.prompt()//创建一个 AI 对话请求构建器
                .user(message)//将用户输入的消息作为用户角色(User Role)添加到对话中。
                .advisors(a->a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
                .stream()
                .content();
    }
    @RequestMapping("{type}")
    public List<String> getChatId(@PathVariable("type")String type){
        return chatHistoryRepository.getChatById(type);
    }
    @RequestMapping("/{type}/{chatId}")
    public List<MessageVo> getChatHistory(@PathVariable("type")String type,@PathVariable("chatId")String chatId){
        List<Message> messages = chatMemory.get(chatId, 10);
        if(messages==null){
            return List.of();
        }
        return messages.stream().map(MessageVo::new).toList();
    }
}


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐