专业的编程技术博客社区

网站首页 > 博客文章 正文

使用 Spring AI 和 DeepSeek 快速构建本地 AI 对话系统

baijin 2025-04-05 16:45:12 博客文章 25 ℃ 0 评论

在当今数字化转型的浪潮中,AI 技术的应用变得越来越广泛。对于开发者来说,能够快速构建一个本地化的 AI 对话系统,不仅可以提升工作效率,还能满足特定场景下的定制化需求。今天,我就来为大家分享如何利用 Spring AI 和 DeepSeek,在 10 分钟内搭建一个支持连续对话的 AI 应用。


一、环境准备

1. 操作系统与 Java 版本

确保你的操作系统为 Windows 11,并且已安装 JDK 17 或更高版本。这是运行 Spring AI 和相关组件的基本要求。


2. 依赖管理工具

安装 Maven 3.8.3 或更高版本,用于项目的依赖管理和构建。

二、环境搭建

1. 安装 Docker

访问 Docker 官方网站,根据你的系统选择合适的版本进行下载和安装。安装完成后,在 PowerShell 中输入 docker ps,若能正常显示容器列表,则说明 Docker 安装成功。

2. 部署 Redis

从 Docker Hub 拉取 Redis 镜像:

bash复制

docker pull redis:7.4.2

在本地创建文件夹 C:\docker\redis\conf 和 C:\docker\redis\data,并在 conf 文件夹下创建 redis.conf 文件,内容如下:

复制

bind 0.0.0.0
port 6379
requirepass 123123
dir /data
appendonly yes

通过以下命令启动 Redis 容器:

bash复制

docker run -d \
-p 6579:6379 \
-v C:/docker/redis/data:/data \
-v C:/docker/redis/conf:/usr/local/etc/redis \
--name redis \
redis:7.4.2 redis-server /usr/local/etc/redis/redis.conf

3. 安装 Ollama

拉取 Ollama 镜像:

bash复制

docker pull ollama/ollama:0.6.2

创建本地文件夹 C:\docker\ollama,并运行以下命令启动 Ollama 容器:

bash复制

docker run -d \
-v C:\docker\ollama:/root/.ollama \
-p 11434:11434 \
--name ollama \
ollama/ollama:0.6.2

4. 安装 DeepSeek

在已启动的 Ollama 容器中执行模型拉取操作,拉取 DeepSeek-R1 的 7b 版本模型:

bash复制

docker exec -it ollama ollama pull deepseek-r1:7b

三、Spring AI 集成与代码实现

1. Maven 依赖配置

在项目的 pom.xml 文件中,添加以下依赖配置:

xml复制


    23
    3.4.3
    1.0.0-M6



    
        org.springframework.boot
        spring-boot-starter-data-redis
        ${spring-boot.version}
    
    
        org.springframework.boot
        spring-boot-starter-web
        ${spring-boot.version}
    
    
        org.springframework.ai
        spring-ai-ollama-spring-boot-starter
    
    
        org.projectlombok
        lombok
        1.18.32
        true
    



    
        
            org.apache.maven.plugins
            maven-compiler-plugin
            3.11.0
            
                ${java.version}
            
        
        
            org.springframework.boot
            spring-boot-maven-plugin
        
    

2. 核心配置

在 application.yml 文件中,添加以下配置:

yaml复制

server:
  port: 8083

spring:
  application:
    name: Ollama-AI
  data:
    redis:
      host: 127.0.0.1
      port: 6579
      password: 123123
      database: 0

ai:
  ollama:
    base-url: http://127.0.0.1:11434
    chat:
      model: deepseek-r1:7b

3. 实现连续对话功能

控制器层

创建 OllamaChatController.java 文件,添加以下代码:

java复制

@RestController
@RequestMapping("/ai/v1")
public class OllamaChatController {

    private final ChatClient chatClient;
    private final ChatMemory chatMemory;

    public OllamaChatController(ChatClient.Builder builder, ChatMemory chatMemory) {
        this.chatClient = builder
                .defaultSystem("只回答问题,不进行解释")
                .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
                .build();
        this.chatMemory = chatMemory;
    }

    @GetMapping("/ollama/redis/chat")
    public String chat(@RequestParam String userId, @RequestParam String input) {
        String text = chatClient.prompt()
                .user(input)
                .advisors(spec -> spec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, userId)
                        .param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .call()
                .content();

        return text.split("")[1].trim();
    }
}

Redis 持久化

创建 ChatRedisMemory.java 文件,添加以下代码:

java复制

@Component
public class ChatRedisMemory implements ChatMemory {

    private static final String KEY_PREFIX = "chat:history:";
    private final RedisTemplate redisTemplate;

    public ChatRedisMemory(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void add(String conversationId, List messages) {
        String key = KEY_PREFIX + conversationId;
        List listIn = new ArrayList<>();
        for (Message msg : messages) {
            String[] strs = msg.getText().split("");
            String text = strs.length == 2 ? strs[1] : strs[0];

            ChatEntity ent = new ChatEntity();
            ent.setChatId(conversationId);
            ent.setType(msg.getMessageType().getValue());
            ent.setText(text);
            listIn.add(ent);
        }
        redisTemplate.opsForList().rightPushAll(key, listIn.toArray());
        redisTemplate.expire(key, 30, TimeUnit.MINUTES);
    }

    @Override
    public List get(String conversationId, int lastN) {
        String key = KEY_PREFIX + conversationId;
        Long size = redisTemplate.opsForList().size(key);
        if (size == null || size == 0) {
            return Collections.emptyList();
        }

        int start = Math.max(0, (int) (size - lastN));
        List<Object> listTmp = redisTemplate.opsForList().range(key, start, -1);
        List listOut = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for (Object obj : listTmp) {
            ChatEntity chat = objectMapper.convertValue(obj, ChatEntity.class);
            if (MessageType.USER.getValue().equals(chat.getType())) {
                listOut.add(new UserMessage(chat.getText()));
            } else if (MessageType.ASSISTANT.getValue().equals(chat.getType())) {
                listOut.add(new AssistantMessage(chat.getText()));
            } else if (MessageType.SYSTEM.getValue().equals(chat.getType())) {
                listOut.add(new SystemMessage(chat.getText()));
            }
        }
        return listOut;
    }

    @Override
    public void clear(String conversationId) {
        redisTemplate.delete(KEY_PREFIX + conversationId);
    }
}

配置类与序列化

创建 RedisConfig.java 文件,添加以下代码:

java复制

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

实体类

创建 ChatEntity.java 文件,添加以下代码:

java复制

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatEntity implements Serializable {
    private String chatId;
    private String type;
    private String text;
}

启动类

创建
OllamaChatDemoApplication.java 文件,添加以下代码:

java复制

@EnableCaching
@SpringBootApplication
public class OllamaChatDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(OllamaChatDemoApplication.class, args);
    }
}

四、测试与验证

环境启动

确保 Docker 部署的 Redis 和 Ollama 服务正常运行,通过 docker ps 查看容器状态。如果未运行,可通过 docker start redis 和 docker start ollama 命令启动。

测试接口

启动 Spring 应用后,访问以下接口进行测试:

http://127.0.0.1:8083/ai/v1/ollama/redis/chat

可以使用 Postman 或 curl 工具发送请求,例如:

bash复制

curl "http://127.0.0.1:8083/ai/v1/ollama/redis/chat?userId=user1&input=你是谁"

查看 Redis 存储

通过 Redis 客户端工具或命令行,查看 Redis 中的对话历史记录,确保数据正确存储。

通过以上步骤,你已经成功使用 Spring AI 和 DeepSeek 构建了一个支持连续对话的本地 AI 对话系统。这一系统不仅能够满足数据安全和隐私保护的需求,还能为各种应用场景提供强大的 AI 支持。希望这篇教程能够帮助你快速上手,开启 AI 开发之旅。

至此你已经在本地成功的安装了属于自己的本地人工智能对话模型,相关教程请点击「链接」 查看

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表