欢迎光临
我们一直在努力

大模型学习(Spring AI 集成 Ollama+DeepSeek)

一.全局配置(application.yml)

server:
port: 8001 # Web服务端口
spring:
application:
name: ai-ollama-deepseek # 项目名称(用于Spring生态标识)
ai:
ollama:
base-url: http://localhost:11434 # Ollama服务地址
chat:
model: deepseek-r1:7b # 指定调用的大模型
options:
temperature: 0.7 # 模型生成温度(0-1,越高越随机)

关键参数解读:

  • server.port:Web 服务的 “门牌号”,前端 / 客户端通过 8001 端口访问接口;

  • spring.ai.ollama.base-url:Spring AI 连接 Ollama 的 “通信地址”,必须与本地 Ollama 服务端口一致;

  • spring.ai.ollama.chat.model:指定要调用的模型 “实例”,需与 Ollama 中已拉取的模型名完全匹配;

  • temperature:模型生成文本的 “灵活度旋钮”,0.7 为适中值,数值越高回答越发散,越低越精准。

二.Maven依赖管理(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mingxing.ai</groupId>
<artifactId>jiazhong-ai</artifactId>
<version>3.5.3</version>
<relativePath/>
</parent>

<groupId>com.jiazhong.mingxing.ai.ollama.depseek</groupId>
<artifactId>ai-ollama-deepseek</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!– Spring Boot Web核心依赖:提供HTTP接口、自动配置Web环境 –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!– Spring AI集成Ollama依赖:封装模型调用逻辑 –>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
</dependencies>
</project>

核心依赖作用:

  • spring-boot-starter-web:一站式引入 Web 开发所需组件(Tomcat、Spring MVC、Reactor 等),无需手动引入多个依赖;

  • spring-ai-starter-model-ollama:Spring AI 针对 Ollama 的封装依赖,自动配置OllamaChatModel、ChatClient等核心 Bean;

三.SpringAI核心配置(ChatClientConfig.java)

package jiazhong.mingxing.ai.ollama.depseek.config;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 对话客户端配置类:封装Ollama模型调用的核心Bean
@Configuration
public class ChatClientConfig {
// 注入Spring AI自动配置的OllamaChatModel(由application.yml配置驱动)
@Resource
private OllamaChatModel ollamaChatModel;

// 方式1:基于OllamaChatModel构建ChatClient(基础版)
@Bean
public ChatClient ollamaChatClient() {
return ChatClient.builder(ollamaChatModel).build();
}

// 方式2:基于ChatClient.Builder构建(灵活扩展版,自定义Bean名称)
@Bean("ollamaChatClient2")
public ChatClient ollamaChatClient2(ChatClient.Builder chatClientBuilder) {
return chatClientBuilder.build();
}
}

  • 核心组件解读:

    • @Configuration:标识为配置类,Spring 启动时会扫描并执行其中的@Bean方法,将返回对象注册为 Spring 容器的 Bean;

    • OllamaChatModel:Spring AI 封装的 Ollama 模型核心类,直接对接 Ollama 服务的 HTTP 接口,处理模型调用的底层逻辑(请求发送、响应解析);

    • ChatClient:Spring AI 提供的 “对话客户端”,是OllamaChatModel的上层封装,简化模型调用的 API(链式调用风格);

  • 形象化理解:

    • OllamaChatModel = 模型调用的 “发动机”,负责核心的 AI 推理请求;

    • ChatClient = 发动机的 “操作面板”,提供更简洁、易用的调用方式,无需直接操作发动机的复杂接口。

两种方式对比

对比维度方式 1(基础版)方式 2(灵活扩展版)
依赖注入 手动绑定OllamaChatModel 复用容器中已绑定 Model 的ChatClient.Builder
扩展灵活性 仅影响当前ChatClient,无全局副作用 修改 Builder 会影响全局,需注意隔离
Bean 命名 默认方法名,易冲突 显式命名,避免冲突
核心优势 配置隔离、多模型场景适配性好 代码简洁、复用容器默认配置
核心劣势 需手动关联 Model,代码稍繁琐 全局 Builder 易被污染,不适合多模型场景

四.控制器与接口开发(deepseekController.java)

@Slf4j
@RestController
@RequestMapping("/deepseek")
public class deepseekController {
@Resource
private ChatClient ollamaChatClient;
@Resource
private OllamaChatModel ollamaChatModel;
//流式输出
@GetMapping(value="/stream",produces = "text/html;charset=utf-8")
public Flux<String> stream(@RequestParam("question") String question) {
return ollamaChatClient.prompt()
.user(question)//提交给大模型的问题
.stream().content();//以流的形式返回结果
}
//普通输出
@GetMapping("/call")
public String call(@RequestParam("message") String message) {
return ollamaChatClient.prompt()
.user(message)
.call().content();
}
// 3. OllamaChatModel流式输出(纯文本):直接调用模型底层API
@GetMapping(value = "/stream2", produces = "text/html;charset=utf-8")
public Flux<String> stream2(@RequestParam("question") String question) {
return ollamaChatModel.stream(question);
}

// 4. OllamaChatModel普通输出(纯文本)
@GetMapping(value = "/call2", produces = "text/html;charset=utf-8")
public String call2(@RequestParam("question") String question) {
return ollamaChatModel.call(question);
}

// 5. ChatClient流式输出(完整ChatResponse):返回包含元数据的响应对象
@GetMapping(value = "/stream3", produces = "event/stream;charset=utf-8")
public Flux<ChatResponse> stream3(@RequestParam("question") String question) {
Flux<ChatResponse> responseFlux = ollamaChatClient.prompt().user(question).stream().chatResponse();
log.info("result:{}", responseFlux);
return responseFlux;
}

// 6. ChatClient普通输出(完整ChatResponse)
@GetMapping(value = "/call3", produces = "text/html;charset=utf-8")
public ChatResponse call3(@RequestParam("question") String question) {
ChatResponse chatResponse = ollamaChatClient.prompt().user(question).call().chatResponse();
log.info("chatResponse:{}", chatResponse);
return chatResponse;
}
}

1.核心代码解释

return ollamaChatClient.prompt()
.user(question)
.stream().content();

这部分是核心业务逻辑,调用 Ollama 客户端实现流式对话:

  • ollamaChatClient.prompt():获取 Ollama 客户端的「提示词构建器」,准备构造向大模型发送的请求。

  • .user(question):设置用户的提问内容(即接口接收的 question 参数),相当于告诉大模型 “用户问了这个问题”。

  • .stream():指定以流式响应的方式获取大模型的回答(而非等待完整回答后一次性返回),这是实现 “边生成边返回” 的关键。

  • .content():提取流式响应中的纯文本内容(过滤掉元数据、结束标记等无关信息),最终返回的 Flux<String> 就是一系列文本片段。

  • 2.核心注解解读

    注解作用
    @RestController 标识为 RESTful 控制器,返回值直接写入响应体(JSON / 文本),而非跳转视图
    @RequestMapping 定义接口统一前缀(/deepseek),所有接口需拼接该前缀访问
    @GetMapping 映射 GET 请求,指定接口路径(如 /stream、/call)
    @RequestParam 获取 URL 中传递的参数(如?question = 你好)
    @Resource 注入 Spring 容器中的 Bean(ChatClient、OllamaChatModel)
    @Slf4j Lombok 注解,自动生成日志对象(log),用于日志输出

    3.两种调用方式对比

    调用方式核心类优点缺点适用场景

    ChatClient 封装

    (stream/call/

    stream3/call3)

    ChatClient API 简洁(链式调用)、可扩展配置 封装层多,自定义底层参数稍复杂 大部分业务场景(快速开发)

    直接调用 OllamaChatModel

    (stream2/call2)

    OllamaChatModel 底层可控性强、无额外封装 API 较繁琐,需手动处理请求 / 响应 需自定义模型调用参数的场景

    4. 流式 / 非流式(同步)输出核心差异

    (1)流式方法(stream/stream2/stream3)
    • 输出效果:返回数据是「分段、实时推送」的,前端能逐字 / 逐句接收内容(类似 ChatGPT 的打字机效果),无需等待完整响应;

    • 底层逻辑:基于 Reactor 的Flux响应式流,服务端会持续向客户端推送数据,直到响应完成;

    • 前端体验:无加载等待,实时展示内容,适合大文本、长对话场景。

    (2)同步方法(call/call2/call3)
    • 输出效果:需等待模型完整生成响应后,一次性返回所有内容;

    • 底层逻辑:阻塞式调用,直到模型返回最终结果;

    • 前端体验:有加载等待时间,内容一次性展示,适合短文本、快速响应场景

    5.「输出内容粒度」:纯文本 vs 完整 ChatResponse 对象

    这是最核心的差异,直接决定前端能拿到的数据维度:

    (1)纯文本输出(stream/call/stream2/call2)

    • 输出内容:仅返回大模型生成的「文本内容本身」,无任何额外信息;

    • 示例输出:调用call?message=你好,返回:你好!有什么我能帮助你的吗?调用stream?question=你好,前端逐段接收:你好 → !有什么 → 我能帮助你的吗?

    • 局限性:无法获取响应的元数据(如模型名称、token 数、响应耗时、finish reason 等)。

    (2)完整 ChatResponse 输出(stream3/call3)

    ChatResponse是 Spring AI 的核心响应对象,包含文本内容 + 元数据,输出结构示例:

    {
    "id": "chat-123456",
    "choices": [
    {
    "message": {
    "role": "assistant",
    "content": "你好!有什么我能帮助你的吗?" // 核心文本
    },
    "finishReason": "stop", // 结束原因(正常结束/截断/报错)
    "index": 0
    }
    ],
    "metadata": {
    "model": "deepseek-r1:7b", // 所用模型
    "temperature": 0.7, // 温度参数
    "totalTokens": 28, // 消耗token数
    "responseTime": 500 // 响应耗时(毫秒)
    }
    }

    • stream3:流式返回「分段的 ChatResponse 对象」,每一段包含当前生成的文本片段 + 实时元数据;

    • call3:同步返回「完整的 ChatResponse 对象」,包含全部文本 + 完整元数据;

    • 优势:能获取模型调用的关键信息(如 token 消耗、模型版本),便于监控 / 调试;

    • 前端处理:需解析 JSON 对象,而非直接展示文本。

    关键技术点:Flux是 Reactor 框架的响应式类型,代表 “0 或多个元素的异步序列”,支持流式数据返回,是实现大模型实时输出的核心。

    6.响应编码配置

    • produces = "text/html;charset=utf-8"/produces = "event/stream;charset=utf-8":强制指定响应编码为 UTF-8,解决大模型返回中文时的乱码问题;

    produces 类型选择说明

    类型适用场景前端处理方式
    text/html 纯文本输出(流式 / 同步) 直接解析文本,简单拼接 / 展示
    event/stream 流式输出复杂对象(如 ChatResponse) 用 SSE 监听,解析 JSON 对象获取数据

    五.核心技术流程

    1.启动阶段:

    Spring Boot 启动 → 扫描@Configuration配置类 → 自动配置OllamaChatModel(读取 application.yml) → 构建ChatClient Bean → 扫描@RestController并初始化接口。

    2.接口调用阶段:

    客户端发送 GET 请求(如 /deepseek/stream?question = 你好) → 控制器接收参数 → 调用ChatClient/OllamaChatModel → Spring AI 向 Ollama 服务(localhost:11434)发送请求 → Ollama 调用 DeepSeek-R1 模型推理 → 结果以流式 / 非流式返回给客户端。

    六.技术关键点总结

    • Spring AI 核心价值:封装大模型调用的底层逻辑,提供标准化的ChatClient接口,无需手动编写 HTTP 请求调用 Ollama;

    • Ollama 作用:本地运行大模型的 “容器”,屏蔽模型部署的复杂性,提供简单的 HTTP 接口供上层调用;

    • 响应式编程(Flux):实现大模型流式输出的核心,适配大模型 “边推理边返回” 的特性,提升用户体验;

    • 编码配置:必须指定 UTF-8 编码,否则会出现中文乱码问题;

    • 模型参数匹配:application.yml中的model参数必须与 Ollama 中已拉取的模型名完全一致(如 deepseek-r1:7b),否则调用失败。

    赞(0)
    未经允许不得转载:171主机测评 » 大模型学习(Spring AI 集成 Ollama+DeepSeek)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址