跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaAIjava算法

SpringAI 通过 Ollama 本地部署 Deepseek 模型实现对话机器人

综述由AI生成SpringAI 集成 Ollama 本地部署 Deepseek 大语言模型,演示了从基础调用到 RAG 检索增强生成、向量数据库(pgvector)配置、PDF 文档读取、Function Call 自定义函数调用及多模态图片识别的完整流程。文章提供了详细的 Maven 依赖引入、配置文件设置及 Java 代码示例,涵盖了 Embedding 模型选择与向量存储的关键步骤,适合希望本地化运行 AI 应用并扩展功能的开发者参考。

无尘发布于 2026/4/8更新于 2026/5/2218 浏览
SpringAI 通过 Ollama 本地部署 Deepseek 模型实现对话机器人

文章配图

Java 调用 Deepseek

本地没有安装 Ollama、Docker、Open WebUI,可先参考相关部署教程。

下载 Deepseek 模型

打开命令行窗口,拉取一下 Deepseek 模型:

ollama run deepseek-r1:7b

文章配图

本地测试

我们打开 Docker Desktop 软件。然后运行一下 Open WebUI。

文章配图

选择 Deepseek-r1 模型,然后进行测试。

文章配图

Java 调用模型

先把以前的 moonshot 依赖注释掉,然后将 moonshot 相关的删除,不然会报错。

引入 ollama 依赖:

<!-- 引入 Ollama 依赖-->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

修改一下模型配置类:

package com.yan.springai;
import lombok.RequiredArgsConstructor;
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.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class Init {
    //要使用的模型
    final OllamaChatModel model2;

    @Bean
    public ChatClient chatClient(ChatMemory chatMemory){
        return ChatClient.builder(model2)
                .defaultSystem("假如你是特朗普,接下来的对话你必须以特朗普的语气来进行?")
                .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))//这里主要负责拼接
                .build();
    }

    @Bean
    public ChatMemory chatMemory(){
        //负责存和读
        return new InMemoryChatMemory();
    }
}

修改配置文件:

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

然后运行文件,看一下输出:

文章配图

构建数据库

增强检索 RAG

Embedding 是一种将对象(如词语、物品、用户等)表示为数值向量的方法。这种方法在深度学习和推荐系统中非常重要,因为它能够捕捉对象之间的相似性和关系。

我们先用 ollama 拉取一个 embedding 模型(我选择的这个模型比较小,适合小项目,不适合企业级项目):

ollama pull all-minilm

文章配图

向量数据库

我们这里讲的 pgvector(你也可以用 redis)。

pgvector 是一个强大的 PostgreSQL 扩展,它为 PostgreSQL 数据库添加了向量相似性搜索功能。这使得我们可以在关系型数据库中执行语义搜索,将结构化数据查询与非结构化数据的语义理解相结合。

我们先使用命令拉取一下 pgvector(建议确保网络连接正常):

docker run -d --name pgvector -p 5433:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres pgvector/pgvector:pg16

文章配图

Springboot 集成 pgvector

首先引入依赖:

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

然后对他进行配置:

spring:
  ai:
    vectorstore:
      pgvector:
        index-type: HNSW
        distance-type: COSINE_DISTANCE
        # 维度,根据选的 embedding 模型所定
        dimensions: 384
        batching-strategy: TOKEN_COUNT
        max-document-batch-size: 1000
    ollama:
      chat:
        options:
          model: deepseek-r1:7b
          embedding:
            enabled: true
            model: all-minilm
          base-url: http://localhost:11434
    datasource:
      url: jdbc:postgresql://localhost:5433/springai
      username: postgres
      password: postgres

然后我们使用 springboot 连一下数据库:

文章配图

然后建立 Spring ai 数据库。接着执行语句建表:

create extension if not exists vector;
create extension if not exists hstore;
create extension if not exists "uuid-ossp";
create TABLE if not exists vector_store(
    id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
    content text,
    metadata json,
    embedding vector(384)
);
create index on vector_store using HNSW(embedding vector_cosine_ops);

然后在 resources 中新建一个 txt 文件:

文章配图

然后建一个 vector 文件夹,创建一个 VectorAPI 类。编写文件:

package com.yan.springai.vector;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

@RestController
@RequiredArgsConstructor
public class VectorAPI {
    final VectorStore store;

    //导入方法
    @GetMapping("/vec/write")
    public String write() throws IOException {
        StringBuffer text = new StringBuffer();//用来存储文件
        ClassLoader classLoader=getClass().getClassLoader();//因为打包后,resource 的文件就放在 class:path 下,我们使用这个获取
        InputStream inputStream=classLoader.getResourceAsStream("ncode.txt");//获取文件
        //把文件一行一行读取出来,放在 text 中去
        try(BufferedReader reader=new BufferedReader(new InputStreamReader(inputStream))){
            String line;
            while ((line=reader.readLine())!=null){
                text.append(line);
            }
        }
        //按照句号,将文本切分
        store.write(Arrays.stream(text.toString().split("。")).map(Document::new).toList());
        return "success";
    }
}

然后运行一下:

文章配图

文章配图

控制台上打印出:

文章配图

表示已经导入完毕,我们查看一下:

文章配图

这时候你会得到,一个和普通模型差不多的答案:

其实我们 RAG 的能力也是通过 advisor 实现的,所以我们需要修改一下 Init 代码:

package com.yan.springai;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class Init {
    //要使用的模型
    final OllamaChatModel model2;
    final VectorStore vectorStore;

    @Bean
    public ChatClient chatClient(ChatMemory chatMemory){
        return ChatClient.builder(model2)
                .defaultSystem("假如你是特朗普,接下来的对话你必须以特朗普的语气来进行?")
                .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory), new QuestionAnswerAdvisor(vectorStore) )//这里主要负责拼接
                .build();
    }

    @Bean
    public ChatMemory chatMemory(){
        //负责存和读
        return new InMemoryChatMemory();
    }
}

然后我们在测试一下,测试成功!!!

文章配图

chatpdf

引入依赖:

<!-- 将 pdf 引入向量数据库-->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>

然后再编写代码:

package com.yan.springai.Pdf;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class Pdf {
    final VectorStore store;

    @GetMapping("/pdf/read")
    public String getDocsFromPdf() {
        PagePdfDocumentReader pdfReader=new PagePdfDocumentReader("classpath:/baogao.pdf", PdfDocumentReaderConfig.builder()
                .withPageTopMargin(0)
                .withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
                        .withNumberOfTopTextLinesToDelete(0)
                        .build())
                .withPagesPerDocument(1)
                .build() );
        store.write(pdfReader.read());
        return "success";
    }
}

然后运行测试一下,发现可以正常读入向量数据库:

文章配图

然后将 md 文档:

文章配图

function call 调用自定义函数

文章配图

注意:部分 AI 模型还不支持这个功能,比如 Deepseek,然而 Moonshot、OpenAI、Gimini 等是可以的。

首先创建一个逻辑函数,实现 Function 接口:

package com.yan.springai.func;
import java.util.function.Function;

public class OaService implements Function<OaService.Rquest, OaService.Response> {
    public Response apply(Rquest rquest) {
        //实现逻辑,这里是请假逻辑
        System.err.printf("%s is token off%n",rquest.who);
        return new Response(10);
    }
    public record Rquest(String who) { }
    public record Response(int days) { }
}

然后再将 Function 注册到 spring 容器中:

package com.yan.springai.func;
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//将 function 注册到 spring 容器中
@Configuration
public class FunctionRegistry {
    @Bean
    public FunctionCallback askForLeaveCallBack(){
        return FunctionCallback.builder()
                .function("askForLeave",new OaService())//注册的名字和函数
                .description("当有人请假时,返回请假天数")//描述功能
                .build();
    }
}

然后再进行调用:

package com.yan.springai.func;
//使用刚刚定义的函数
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class FuncAPI {
    final ChatClient chatClient;

    @GetMapping("/ai/func")
    public String funcCall(@RequestParam(value = "message")String message){
        return chatClient.prompt(message)
                .functions("askForLeave")//调用名称
                .call().content();
    }
}

然后运行一下,就可以看到输出了。

多模态能力

多模态大语言模型(Multimodal Large Language Models,简称 Multimodal LLMs)是一种能够理解和生成多种类型数据的模型,包括文本、图片、音频和视频等。这些模型可以跨越不同的数据形式,进行信息的交互与生成。例如,传统语言模型只能处理文字,但多模态模型不仅能'读'文字,还能'看'图片、'听'声音,甚至'看'视频,并用文字或其他形式将它们的理解表达出来。

这里我拿图片转文字作为例子给大家介绍一下:

这里提示:Deepseek、Moonshot 等是不支持的,可以下载一下 llava。

文章配图

打开命令行窗口:

ollama run llava

然后进行下载:

文章配图

然后可以在 resources 传入一张图片:

文章配图

文章配图

package com.yan.springai.model;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.model.Media;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaModel;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequiredArgsConstructor
public class ImageAPI {
    final OllamaChatModel model;

    @GetMapping("/ai/chatWithPic")
    public String chatWithPic() {
        ClassPathResource imageData=new ClassPathResource("/cat.png");
        Message userMessage=new UserMessage("请用中文描述一下这张图片是什么东西?", List.of(new Media(MimeTypeUtils.IMAGE_PNG,imageData)));
        return model.call(new Prompt(
                List.of(userMessage),
                ChatOptions.builder()
                        .model(OllamaModel.LLAVA.getName()).build()))
                .getResult().getOutput().getText();
    }
}

然后你就可以看到他的结果了

目录

  1. Java 调用 Deepseek
  2. 下载 Deepseek 模型
  3. 本地测试
  4. Java 调用模型
  5. 构建数据库
  6. 增强检索 RAG
  7. 向量数据库
  8. Springboot 集成 pgvector
  9. chatpdf
  10. function call 调用自定义函数
  11. 多模态能力
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 AI 工具快速生成计算机课题技术路线图
  • Python 调用高德地图 MCP 服务查询天气实战
  • 2025 年 AIGC 六大核心发展趋势
  • 开源浪潮下的中国力量:文心一言大模型本地部署与应用全攻略
  • AIGC 内容创作:AI 文字、图像、音频和视频生成流程
  • 利用 AI 智能体快速生成 C 语言成绩管理与前端博客项目
  • Mac Intel 芯片安卓模拟器安装与使用指南
  • 基于 AI 智能体的 C 语言与前端实训项目快速开发指南
  • TRAE 与 VSCode 的 Git 工作流实战指南
  • 文本生成技术:原理、落地场景与国产工具实践
  • 基于麻雀搜索算法的 LSSVM 回归预测参数优化
  • 解决 GitHub SSH 连接端口 22 超时问题
  • Jenkins Pipeline 自动化构建与部署 Java 项目
  • 深入理解 LRU 与 LFU 缓存算法实现
  • 缓存算法实战:LRU 与 LFU 的 Java 实现与原理解析
  • 无线蜂窝网络原理与演进:从 1G 到 6G
  • YOLO13-C3k2-WDBB 海下垃圾清理机器人环境感知与障碍物识别系统
  • 前端虚拟列表核心原理与 React 实战
  • FPGA 摄像头采集处理显示指南:OV5640 到 HDMI 实时显示
  • C++ 哈希表核心解析:冲突解决与实现细节

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online