SpringAI基础对话机器人实现全攻略

基于SpringAI的对话机器人实现指南

本文基于黑马教程,结合个人理解,通过SpringAI框架对接云服务大模型API,实现一个具备对话记忆功能的智能机器人。

引言

使用SpringAI接入AI大模型主要有两种方式:一是部署大模型在本地服务器,二是直接调用云服务商提供的API。本文将采用第二种方式,重点介绍如何配置和使用云服务大模型。

一、引入依赖

首先,在项目的pom.xml中引入SpringAI的OpenAI标准依赖。虽然名为openai,但该starter兼容遵循OpenAI API标准的各类大模型服务。

xml 复制代码
<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

关键步骤说明:

  1. 选择模型服务商 :例如阿里的通义千问、DeepSeek等,并完成注册获取API-KEY
  2. 初始化客户端:通过配置连接至服务商的API地址。
  3. 发送请求:通过客户端向大模型发送HTTP请求并获取响应。

二、配置模型参数

application.yml配置文件中设置连接参数。

yaml 复制代码
spring:
  ai:
    openai:
      # 替换为对应云服务商的API地址(以阿里云为例)
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: ${your-api-key} # 替换为你的真实API-KEY
      chat:
        options:
          model: qwen-max # 指定使用的模型名称
          temperature: 0.8 # 控制生成结果的随机性(0-1,值越大越随机)
  • base-url: 目标大模型服务商的API端点地址。
  • api-key: 用于身份验证的密钥。
  • model: 指定需要调用的具体模型。
  • temperature: 影响AI回答的创造性,通常0.8左右平衡了确定性和创造性。

三、配置客户端与对话记忆 (CommonConfiguration)

​ 为了实现类似ChatGPT的多轮对话能力,需要配置客户端并管理对话历史(上下文)。

java 复制代码
@Configuration
public class CommonConfiguration {

    @Bean
    public ChatMemory chatMemory(){
        // 使用内存存储对话历史,适合开发和短对话场景
        return new InMemoryChatMemory();
    }

    @Bean
    public ChatClient chatClient(OpenAiChatModel model, ChatMemory chatMemory){
        return ChatClient.builder(model)
                .defaultSystem("你是一个热心、可爱的智能助手,你的名字叫小团团。") // 系统提示词,设定AI角色
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(), // 日志记录增强
                        new MessageChatMemoryAdvisor(chatMemory) // 对话记忆增强
                )
                .build();
    }
}

核心组件解析:

  1. ChatMemory :负责存储和管理对话历史。
    • InMemoryChatMemory:基于内存,简单易用,重启后记录丢失,适用于测试。
    • VectorStoreChatMemory:使用向量数据库,能进行智能检索,适用于复杂对话。
    • TokenWindowChatMemory:基于Token数量限制历史记录长度,有助于控制成本。
  2. ChatClient :核心客户端,用于与AI模型交互。
    • prompt().user("问题").call():发送单次请求。
    • prompt().stream():以流式方式接收响应,实现打字机效果。
    • defaultAdvisors():配置拦截器,提供如日志、记忆管理等增强功能。

四、实现对话接口 (ChatController)

​ 创建一个Controller来处理前端发送的聊天请求。

java 复制代码
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {
    private final ChatClient chatClient;

    @RequestMapping(value = "/chat", produces = "text/event-stream;charset=UTF-8")
    public Flux<String> chat(
            @RequestParam String prompt,
            @RequestParam String chatId) { // 前端生成并传递会话ID,用于区分不同对话

        return chatClient.prompt()
                .user(prompt)
                .adviser(a -> a.param(ChatMemory.CONVERSATION_ID_KEY, chatId)) // 关键:将当前会话ID告知记忆管理器
                .stream()
                .content();
    }
}
  • Flux<String>produces = "text/event-stream" 用于支持流式输出,数据一边生成一边返回给前端。
  • chatId 是区分不同对话会话的关键。通过Advisor将其设置到上下文中,MessageChatMemoryAdvisor会自动根据此ID存储和读取对应的历史记录。

五、会话日志与监控

​ 通过配置的SimpleLoggerAdvisor,可以在日志中查看详细的AI请求和响应信息。如需查看,可在application.yml中调整日志级别:

yaml 复制代码
logging:
  level:
    org.springframework.ai.chat.client.advisor: DEBUG
    com.yourpackage.ai: DEBUG

六、解决跨域问题

​ 前端开发服务器(如Vite on port 5173)与后端API(如SpringBoot on port 8080)端口不同,会产生跨域错误。需配置CORS。

java 复制代码
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 拦截所有请求
                .allowedOriginPatterns("*") // 允许所有来源(生产环境应指定具体域名)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(false);
    }
}

七、实现会话历史记录功能

​ 大模型本身无状态,要实现"历史记录"功能,需要我们将过去的对话数据持久化,并在查询时提供。

1. 定义历史记录存储接口

java 复制代码
public interface ChatHistoryRepository {
    void save(String type, String chatId); // 保存会话ID,按业务类型分类(如'chat')
    List<String> getChatIds(String type); // 获取某类型下的所有会话ID列表
}

2. 实现历史记录查询接口

java 复制代码
@RequiredArgsConstructor
@RestController
@RequestMapping("/ai/history")
public class ChatHistoryController {

    private final ChatHistoryRepository chatHistoryRepository;
    private final ChatMemory chatMemory;

    // 1. 获取某个类型下的所有会话ID列表
    @GetMapping("/{type}")
    public List<String> getChatIds(@PathVariable("type") String type) {
        return chatHistoryRepository.getChatIds(type);
    }

    // 2. 根据会话ID获取具体的对话内容
    @GetMapping("/{type}/{chatId}")
    public List<MessageVO> getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId) {
        // 从ChatMemory中获取该会话ID下的完整历史消息
        List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);
        if (messages == null) {
            return List.of(); // 返回空列表
        }
        // 将Spring AI的Message对象转换为前端需要的VO对象
        return messages.stream().map(MessageVO::new).toList();
    }
}

// 前端需要的消息视图对象
@Data
@NoArgsConstructor
public class MessageVO {
    private String role; // "user", "assistant", "system"
    private String content;

    public MessageVO(Message message) {
        this.role = message.getMessageType().name().toLowerCase();
        this.content = message.getText();
    }
}

3. 在对话接口中保存会话ID

​ 修改之前的ChatController,在开始对话前保存会话ID。

java 复制代码
public Flux<String> chat(...) {
    // 在对话开始前,保存本次会话的ID
    chatHistoryRepository.save("chat", chatId);

    return chatClient.prompt()
            .user(prompt)
            .adviser(a -> a.param(ChatMemory.CONVERSATION_ID_KEY, chatId))
            .stream()
            .content();
}

实现总结

通过以上步骤,我们实现了一个功能相对完整的对话机器人后端服务。它支持:

  1. 流式对话:与前端实现打字机效果。
  2. 多轮对话记忆:基于会话ID管理上下文。
  3. 会话历史记录:可查看过往对话列表和详情。
  4. 跨域支持:方便前后端分离开发。

待改进点

  • 当前的InMemoryChatMemory和简易ChatHistoryRepository在应用重启后数据会丢失。生产环境应集成Redis或数据库进行持久化。
  • 可进一步扩展文件上传、多模态对话等功能。

希望这篇博客对你巩固知识有帮助!新手书写难免有错,如果有错麻烦告知🙏

相关推荐
IT WorryFree1 小时前
肺癌机器人专用技能定制(OpenClaw-Medical-Skills 适配版)
机器人
-许平安-1 小时前
MCP项目笔记九(插件 bacio-quote)
c++·笔记·ai·plugin·mcp
程序员鱼皮2 小时前
AI 时代,满分的程序员简历是怎么样的?附简历模板
ai·程序员·编程·求职·简历
刘佬GEO2 小时前
【无标题】
网络·人工智能·搜索引擎·ai·语言模型
熊猫钓鱼>_>3 小时前
AI驱动的Web应用智能化:WebMCP、WebSkills与WebAgent的融合实践
前端·人工智能·ai·skill·webagent·webmcp·webskills
小真zzz4 小时前
2026年免费AI PPT工具深度评测:多款实用工具推荐
人工智能·搜索引擎·ai·powerpoint·ppt
beyond阿亮4 小时前
Claude Code零基础入门安装使用指南
人工智能·ai·claude code
Agent产品评测局5 小时前
企业预算管理自动化落地,编制管控全流程实现方案 —— 2026企业级智能体选型与架构深度解析
运维·人工智能·ai·架构·自动化
鲁邦通物联网5 小时前
酒店与园区梯控安装架构设计:非侵入式物理隔离与状态机实现
机器人·巡检机器人·机器人梯控·agv梯控·机器人乘梯·机器人自主乘梯·agv机器人梯控
kobesdu5 小时前
FAST-LIO2 + 蓝海M300激光雷达:从建图到实时栅格图的完整流程
算法·机器人·ros·slam·fast lio