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

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

介绍如何使用 Spring AI 结合 Ollama 本地部署 Deepseek 模型构建对话机器人。内容包括模型下载与 Java 调用配置,基于 pgvector 向量数据库实现 RAG 增强检索,集成 PDF 文档读取功能,以及 Function Call 自定义函数调用和多模态图片识别能力的实现方案。

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

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

Java 调用 Deepseek

本地没有安装 Ollama、Docker,Open WebUI,可以参考相关文档进行环境搭建。

下载 Deepseek 模型

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

ollama run deepseek-r1:7b

本地测试

运行 Open WebUI 后,选择 Deepseek-r1 模型进行测试。

Java 调用模型

将之前的 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.builder(model2)
                .defaultSystem()
                .defaultAdvisors( (chatMemory))
                .build();
    }

    
     ChatMemory {
        
          ();
    }
}
chatClient
(ChatMemory chatMemory)
return
"假如你是特朗普,接下来的对话你必须以特朗普的语气来进行?"
new
MessageChatMemoryAdvisor
@Bean
public
chatMemory
()
//负责存和读
return
new
InMemoryChatMemory

修改配置文件 application.yml:

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
        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

连接数据库并执行建表语句:

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 文件。

创建 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();
        InputStream inputStream = classLoader.getResourceAsStream("ncode.txt");
        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();
    }
}

再次测试,验证 RAG 效果。

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";
    }
}

运行测试,确认 PDF 内容可正常读入向量数据库。

Function Call 调用自定义函数

注意:部分 AI 模型(如 Deepseek)可能不支持此功能,Moonshot、OpenAI、Gimini 等支持较好。

首先创建一个逻辑函数:

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;

@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)能够理解和生成多种类型的数据,包括文本、图片、音频和视频等。

以图片转文字为例: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. SpringAI 通过 Ollama 本地部署 Deepseek 模型实现对话机器人
  2. Java 调用 Deepseek
  3. 下载 Deepseek 模型
  4. 本地测试
  5. Java 调用模型
  6. 构建数据库
  7. 增强检索 RAG
  8. 向量数据库
  9. Springboot 集成 pgvector
  10. ChatPDF
  11. Function Call 调用自定义函数
  12. 多模态能力
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 基于 JSP 的志愿者管理系统设计与实现
  • CentOS 升级 GCC 至 10.1.0 源码编译指南
  • Android Framework 源码开发揭秘:系统启动与核心组件深度解析
  • 教育权益验证自动化流程说明
  • 网络安全入门学习路径指南
  • AI 领域必读精选:6 部名家名作
  • cxx-qt 底层机制:实现 C++ 与 Rust 无缝通信及开发效率提升
  • 网络安全专业就业前景与职业发展分析
  • 在 Windows 10/11 上使用 VMware 17 Pro 安装 macOS 官方镜像虚拟机
  • 阿里云发布通义听悟:音视频内容 AI 处理新工具评测
  • AI 大模型冲击下,职场人如何保持竞争力?
  • Agent 为何成为下一个 AI 应用爆发点及企业盈利路径
  • 网络安全行业现状、薪资前景及学习路径规划
  • Vivado 与 ModelSim 联合仿真环境配置与实战调试
  • 微信小程序 AR 开发:5 步实现增强现实应用
  • LLM 大模型学习路线图详解与技术指南
  • 百度否认大模型泡沫论,AI 业务持续盈利
  • GitHub 黑客成长技术清单与安全工具资源汇总
  • 10 个 Python 自动化探索性数据分析库推荐
  • 中文类 LLaMA 大语言模型资源整理与对比

相关免费在线工具

  • 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

  • RSA密钥对生成器

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

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online