【Spring AI】简单入门(一)

【Spring AI】

  • [1. Spring AI简介](#1. Spring AI简介)
    • [1.1 Spring AI是什么](#1.1 Spring AI是什么)
      • [1.1.1 概述](#1.1.1 概述)
    • [1.2 发布版本](#1.2 发布版本)
    • [1.3 Spring AI的主要功能](#1.3 Spring AI的主要功能)
  • [2. 结合DeepSeek上手使用](#2. 结合DeepSeek上手使用)
    • [2.1 准备工作](#2.1 准备工作)
    • [2.2 DeepSeek开放平台创建API KEY](#2.2 DeepSeek开放平台创建API KEY)
    • [2.3 实现简单对话](#2.3 实现简单对话)
  • [3. Spring AI的聊天模型](#3. Spring AI的聊天模型)
    • [3.1 概述](#3.1 概述)
    • [3.2 ChatClient接口](#3.2 ChatClient接口)
      • [3.2.1 ChatClient接口定位与作用](#3.2.1 ChatClient接口定位与作用)
      • [3.2.2 ChatClient接口核心特点](#3.2.2 ChatClient接口核心特点)
      • [3.2.3 核心接口与用法](#3.2.3 核心接口与用法)
    • [3.3 最佳实践](#3.3 最佳实践)
    • [3.4 流式输出](#3.4 流式输出)
  • [4. 一个接口使用不同的大模型](#4. 一个接口使用不同的大模型)
    • [4.1 多厂商模型的调用方式](#4.1 多厂商模型的调用方式)
  • [5. 提示词](#5. 提示词)
  • [6. Spring AI的函数调用](#6. Spring AI的函数调用)
    • [6.1 函数调用实现](#6.1 函数调用实现)
      • [6.1.1 创建自定义的Function](#6.1.1 创建自定义的Function)
      • [6.1.2 编写Controller](#6.1.2 编写Controller)
      • [6.1.3 测试](#6.1.3 测试)
  • [7. SpringAI调用Ollama](#7. SpringAI调用Ollama)
    • [7.1 什么是Ollama](#7.1 什么是Ollama)
    • [7.2 使用Docker安装](#7.2 使用Docker安装)
    • [7.3 SpringAI结合Ollama](#7.3 SpringAI结合Ollama)
  • [8. 图像模型](#8. 图像模型)
    • [8.1 Image Model API概述](#8.1 Image Model API概述)
    • [8.2 Image Model API接口及相关类](#8.2 Image Model API接口及相关类)
      • [8.2.1 ImageModel(图像模型)](#8.2.1 ImageModel(图像模型))
      • [8.2.2 ImagePrompt(图像提示)](#8.2.2 ImagePrompt(图像提示))
      • [8.2.3 ImageMessage(图像消息)](#8.2.3 ImageMessage(图像消息))
      • [8.2.4 ImageOptions(图像选项)](#8.2.4 ImageOptions(图像选项))
      • [8.2.5 ImageResponse(图像响应)](#8.2.5 ImageResponse(图像响应))
      • [8.2.6 ImageGeneration(图像生成)](#8.2.6 ImageGeneration(图像生成))
  • 附录

1. Spring AI简介

在当今这样一个快速发展的技术时代,人工智能(AI)已经成为各行各业的一种标配。而作为一款主流的Java应用开发框架Spring,肯定会紧跟时代的潮流,所以,推出了Spring AI框架。

1.1 Spring AI是什么

官网 https://spring.io/projects/spring-ai

1.1.1 概述

Spring AI 是一个面向 AI 工程的应用框架。它的目标是把 Spring 生态系统中的设计原则(例如可移植性、模块化设计等)应用到 AI 领域,并推动在 AI 应用中使用 POJO(普通 Java 对象)作为应用的构建模块。

其核心在于解决 AI 集成的基础性挑战:将你的企业数据(Data)和 API 与 AI 模型连接起来。

特性(Features)

Spring AI 提供以下功能:

  • 支持所有主要的 AI 模型供应商(Model providers),包括 Anthropic、OpenAI、Microsoft、Amazon、Google,以及 Ollama。支持的模型类型有:

    • 聊天补全(Chat Completion)
    • 嵌入(Embedding)
    • 文本生成图像(Text to Image)
    • 音频转录(Audio Transcription)
    • 文本转语音(Text to Speech)
    • 内容审核 / Moderation(Moderation)
  • 对不同 AI 提供商的 API,支持同步(synchronous)和流式(streaming)调用方式,同时也可以访问特定模型(model-specific)的特性。

  • 结构化输出(Structured Outputs) ------ 将 AI 模型的输出映射为 POJOs(方便在 Java 环境中处理)

  • 支持主要的向量数据库(Vector Database)提供商(Providers),例如 Apache Cassandra、Azure Vector Search、 Chroma、Milvus、MongoDB Atlas、Neo4j、Oracle、PostgreSQL/PGVector、PineCone、Qdrant、Redis、Weaviate 等等。

  • 在向量存储提供商之间提供可移植 API(Portable API),包括一个类 SQL 的元数据过滤 API(metadata filter API)。

  • 支持工具 / 函数调用(Tools / Function Calling)------即模型可以请求执行客户端的工具或函数,以便在必要时访问实时的信息。

  • 可观测性(Observability) --- 提供 AI 相关操作的可监控、可视化洞见。

  • 文档注入(Document injection)以及用于数据工程的 ETL 框架。

  • AI 模型评估(AI Model Evaluation) --- 包括用于评估生成内容的工具,并帮助防止"幻觉"(hallucinated responses)的问题。

  • ChatClient API --- 用于与 AI 聊天模型通信的 Fluent API,其风格类似于 Spring 的 WebClient 和 RestClient。

  • Advisors API --- 封装了常用的生成式 AI 模式,负责变换语言模型(LLM)之间或发送/接收的内容,并为不同模型和用例提供可移植性。

  • 支持聊天对话记忆(Chat Conversation Memory)和检索增强生成(Retrieval Augmented Generation, RAG)等功能。

  • Spring Boot 的自动配置(Auto Configuration)和 Starter(启动器)支持所有 AI 模型和向量存储 ------ 你可以用 Spring Initializr 来选择你想用的模型或向量存储。

这些功能组合起来,使你可以实现诸如 "在你的文档上做问答 (Q&A over your documentation)" 或 "与你的文档进行聊天 (Chat with your documentation)" 这样的常见用例。

1.2 发布版本

写这篇文章的时间是2025年09月20日,可以看到已经有了

  • 1.0.1 Current (当前稳定版)
  • 1.1.0-SNAPSHOT(开发中的快照版本)
  • 1.1.0-M1(预发布版本 Milestone 1)

1.3 Spring AI的主要功能

  • 第一、 对主流 AI 大模型供应商提供了支持,比如:OpenAI、DeepSeek、Microsoft、Ollama、Amazon、Google HuggingFace等。
  • 第二、 支持AI大模型类型包括:聊天、文本到图像、文本到声音等。
  • 第三、 支持主流的Embedding Models(嵌入模型)和向量数据库,比如:Azure Vector Search、Chroma、Milvus、Neo4j、Redis、PineCone、PostgreSQL/PGVector 等。
  • 第四、 把 AI 大模型输出映射到简单的 Java 对象(POJOs)上。
  • 第五、 支持了函数调用(Function calling)功能。
  • 第六、 为数据工程提供 ETL(数据抽取、转换和加载)框架。
  • 第七、 支持 Spring Boot 自动配置和快速启动,便于运行 AI 模型和管理向量库。

2. 结合DeepSeek上手使用

2.1 准备工作

DeepSeek 是一款由深度求索所开发的 AI 人工智能大模型,其基于深度学习和多模态数据融合技术,采用先进的 Transformer 架构和跨模态协同算法,可实现对复杂文档和图像的自动化解析与结构化信息提取。

依托于最新推出的"深度思考"模式(R1),这款AI大模型在极低成本下实现了与国际顶尖模型ChatGPT-o1相媲美的性能表现,其中文理解与输出能力更是远超ChatGPT、Claude等顶尖模型。再加上极具竞争力的API定价和全面开源的策略,让这款AI大模型成功在国际上火爆出圈

如果说AI是一个广泛的概念,那么DeepSeek就是是AI领域中的一个具体产品。

DeepSeek的特点‌:

  • 成本‌:DeepSeek致力于降低AI应用的成本。通过采用先进的技术和独特的模型架构,DeepSeek在保持高性能的同时,显著降低了推理和训练的成本。
  • 性能‌:DeepSeek在性能上表现出色。它使用强化学习技术训练,推理过程中包含大量反思与验证,能够处理更加复杂的数据和任务。在一些benchmark测试中,其性能与OpenAI的模型相当,但推理成本远低于同类产品。
  • 功能‌:DeepSeek擅长处理数学、编程和复杂逻辑推理等任务。它的推理能力源于深度思考特性,推理长度与准确率呈正相关。此外,DeepSeek还支持多模态信息处理,能够应对更加多样化的应用场景。
  • 应用领域‌:DeepSeek在多个领域展现出巨大的应用潜力。无论是在医疗、教育、交通等传统领域,还是在智能制造、智慧城市等新兴领域,DeepSeek都有望发挥重要作用。

综上所述,AI是一个广泛的概念,涵盖了人工智能领域的所有技术和应用。而DeepSeek则是AI领域中的一个具体产品,它在成本、性能、功能和应用领域等方面都有着独特的特点和优势。两者之间的关系可以理解为:DeepSeek是AI领域中的一个具体实现和优秀代表。

如何使用Java集成DeepSeek:

DeepSeek 作为一款卓越的国产 AI 模型,越来越多的公司考虑在自己的应用中集成。对于 Java 应用来说,我们可以借助 Spring AI 集成 DeepSeek,非常简单方便!

2.2 DeepSeek开放平台创建API KEY

DeepSeek官网 https://www.deepseek.com/

接口文档 https://api-docs.deepseek.com/zh-cn/

在官网上创建api key 注意是需要充值的!

使用curl调用

bash 复制代码
(base) ➜  ~ curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-8c780d3293d94b799d7b8000972xxxxx" \
  -d '{
        "model": "deepseek-chat",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Hello!"}
        ],
        "stream": false
      }'
bash 复制代码
{
    "id": "3ec31844-c3da-466b-b286-xxx0b90bcf83",
    "object": "chat.completion",
    "created": 1758340902,
    "model": "deepseek-chat",
    "choices": [
        {
            "index": 0,
            "message": {},
            "logprobs": null,
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 12,
        "completion_tokens": 11,
        "total_tokens": 23,
        "prompt_tokens_details": {},
        "prompt_cache_hit_tokens": 0,
        "prompt_cache_miss_tokens": 12
    },
    "system_fingerprint": "fp_08f168e49b_xxxxxx_fp8_kvcache"
}

2.3 实现简单对话

新建一个Maven项目

其中父类的pom依赖

bash 复制代码
<?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>

    <groupId>com.beijing</groupId>
    <artifactId>SpringAi</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!-- 子模块 -->
    <modules>
        <module>springai_hello</module>
    </modules>

    <properties>
        <spring-boot.version>3.3.8</spring-boot.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-ai.version>1.0.1</spring-ai.version>
    </properties>

    <!-- 版本管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot 依赖版本管理 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Spring AI 依赖版本管理 -->
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 公共依赖(子模块都会继承) -->
    <dependencies>
        <!-- Web Starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai</artifactId>
        </dependency>

        <!-- Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

子类springai_hello
application.yml

bash 复制代码
server:
  port: 18888

spring:
  application:
    name: springai_hello
  ai:
    openai:
      api-key: sk-8cxxxd3293d94b799d7b8000972xxxx
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat
          temperature: 0.7

temperature参数用于控制生成文本的多样性。具体来说:

‌值越高‌,生成的文本越多样化,但也可能包含更多的随机性和不可预测的内容。 ‌值越低‌,生成的文本越接近于确定性的结果,即生成的文本会更加一致和可预测。

子类的pom

bash 复制代码
<?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.beijing</groupId>
        <artifactId>SpringAi</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>springai_hello</artifactId>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.5.0</version>
        </dependency>

    </dependencies>

</project>

配置文件
ChatModelConfig

java 复制代码
package com.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatModelConfig {
    /**
     * 配置 ChatClient(用于对话调用)
     */
    @Bean
    public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
        return ChatClient.builder(openAiChatModel).build();
    }
}

Controller

java 复制代码
package com.controller;
package com.controller;

import jakarta.annotation.Resource;
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
public class ChatController {

    @Resource
    private ChatClient chatClient;

    @GetMapping("/hello")
    public String generate(@RequestParam(value = "message") String message) {
        String call = chatClient
                .prompt()
                .system("你是一个无所不能的机器人")
                .user(message)
                .call()
                .content();

        return call;
    }
}
方法 作用
prompt() 提示词
user(message) 设置用户消息
call() 发送请求给模型,获取响应
content() 获取模型生成的文本内容

3. Spring AI的聊天模型

3.1 概述

Spring AI的聊天模型API为开发者提供了一条便捷通道,能够将强大的AI驱动的聊天完成功能无缝集成到各类应用中。借助预先训练的语言模型,如广为人知的GPT,它能够依据用户输入生成自然流畅、类人化的回复。这一API不仅工作机制高效,而且设计理念极为先进,旨在实现简单易用与高度可移植性,让开发者能以极少的代码改动在不同AI模型间自由切换,充分契合Spring框架一贯秉持的模块化与可互换性原则。

3.2 ChatClient接口

Spring AI 的 ChatClient 是一个面向开发者的无状态 AI 对话客户端,提供了基于流式/非流式调用的统一 API,用于和不同的 大语言模型(LLM)(如 OpenAI、Ollama、Azure OpenAI、Anthropic 等)交互。

3.2.1 ChatClient接口定位与作用

  • ChatClient 是 Spring AI 提供的统一客户端接口,用来调用各种大语言模型(LLM)。

  • 目标类似:

    • RestTemplate(同步 HTTP 调用)
    • WebClient(响应式 HTTP 调用)
  • 作用是:对接底层模型(OpenAI、Azure、Ollama、Anthropic...)时,开发者不需要关心底层 SDK,直接用统一 API 就能发请求、收响应。

换句话说:ChatClient 是 AI 领域的统一编程入口。

3.2.2 ChatClient接口核心特点

  1. 统一 API:不管调用哪个模型,写法都一致。

  2. Prompt 构建:支持 system / user / 多消息角色。

  3. 调用模式:

    • 同步调用(一次性返回完整答案)
    • 流式调用(逐 Token 实时输出,基于 Reactor Flux)
  4. 扩展能力:

    • Advisor:对话增强器(类似拦截器/AOP)
    • Tool / Function Calling:让 AI 调用外部函数或服务
    • Structured Output:LLM 输出直接转为 Java 对象
  5. 监控集成:支持 Micrometer / Tracing

3.2.3 核心接口与用法

① 创建 ChatClient

java 复制代码
// 快速工厂方法
ChatClient client = ChatClient.create(chatModel);

// Builder 模式(带默认配置)
ChatClient client = ChatClient.builder(chatModel)
    .defaultSystem("你是一个专业的Java导师")
    .defaultUser("你好")
    .build();

② 构建 Prompt

java 复制代码
String reply = client.prompt("你是一个乐于助人的助手")
    .system()
    .user("帮我解释一下 FutureTask 是什么") // User role
    .call()
    .content();

支持从文件、模板、参数化:

java 复制代码
chatClient.prompt()
    .user(u -> u.text("请写一首关于 {topic} 的诗").param("topic", "AI"))
    .call()
    .content();

③ 调用方式

  • 同步调用
java 复制代码
String answer = client.prompt().user("讲个笑话").call().content();
  • 流式调用
java 复制代码
client.prompt("写一首诗")
    .stream()
    .content()
    .subscribe(System.out::print);

④ Advisor(对话增强器)

Advisor = 对话拦截器,可以在请求前/响应后增强。

例如:追加上下文、敏感词过滤、打日志。

java 复制代码
chatClient.prompt("帮我写一份简历")
    .advisors(new LoggingAdvisor(), new RedactSensitiveDataAdvisor())
    .call();

⑤ 工具调用(Function Calling)

AI 可以自动触发你的函数:

java 复制代码
class WeatherTool {
    public String getWeather(String city) {
        return city + " 今天天气晴朗 25℃";
    }
}

chatClient.prompt("北京天气怎么样?")
    .tools(new WeatherTool())
    .call()
    .content();

⑥ 结构化输出

让模型返回 JSON → 自动转为对象:

java 复制代码
record Person(String name, int age) {}

Person person = chatClient.prompt("输出一个人: {\"name\":\"小明\",\"age\":16}")
    .call()
    .entity(Person.class);

System.out.println(person.name()); // 小明

⑦ 完整响应对象

java 复制代码
ChatResponse response = chatClient.prompt("讲个冷笑话").call().chatResponse();

System.out.println(response.getResult().getOutputText());
System.out.println(response.getMetadata().getUsage()); // token 使用情况
System.out.println(response.getMetadata().getFinishReason());

3.3 最佳实践

  1. 在配置类统一定义 ChatClient Bean,避免重复创建。
  2. 同步调用适合短回答,流式调用适合长文本。
  3. Advisor 可以做安全过滤/上下文增强。
  4. 工具调用要加参数验证/Schema,减少错误调用。
  5. 结合 Micrometer 做监控,分析 token 消耗与调用时延。

3.4 流式输出

java 复制代码
package com.controller;

import jakarta.annotation.Resource;
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;
import reactor.core.publisher.Flux;

@RestController
public class ChatController {

    @Resource
    private ChatClient chatClient;

    @GetMapping(value = "/hello",produces = "text/html; charset = UTF-8")
    public Flux<String> generate(@RequestParam(value = "message") String message) {
        Flux<String> stream = chatClient
                .prompt()
                .system("你是一个阿里巴巴的Java专家")
                .user(message)
                .stream()
                .content();

        return stream;
    }
}

4. 一个接口使用不同的大模型

4.1 多厂商模型的调用方式

Spring AI 的关键类是 ChatClient,其调用流程大概如下:

java 复制代码
String response = chatClient
        .prompt()
        .user("你好,请解释量子力学")
        .call()
        .content();

这里 chatClient 可以通过配置绑定不同厂商:

  • OpenAI
  • Azure OpenAI
  • Anthropic
  • 自定义大模型(DeepSeek、千问等)

Spring AI 的 核心扩展点是 ChatModel 和 ChatClient 的实现:

java 复制代码
@Bean
public ChatClient chatClient(List<ChatModel> chatModels) {
    return new DefaultChatClient(chatModels);
}
  • chatModels 是你可以注入的所有模型。
  • Spring AI 内部会根据模型 id 或 type 决定使用哪个厂商。

配置不同厂商的模型

Spring AI 允许你在配置文件或代码中声明多个模型:

java 复制代码
spring:
  ai:
    chat:
      models:
        openai:
          type: openai
          api-key: YOUR_OPENAI_KEY
        deepSeek:
          type: custom
          endpoint: https://api.deepseek.com/v1/chat
          api-key: YOUR_DEEPSEEK_KEY
        qianwen:
          type: custom
          endpoint: https://api.qianwen.ai/v1/chat
          api-key: YOUR_QIANWEN_KEY

然后在代码里通过 ChatClient 调用时选择模型:

java 复制代码
String answer = chatClient
        .model("deepSeek")  // 指定调用 DeepSeek
        .prompt()
        .user("帮我写一篇 AI 概念介绍")
        .call()
        .content();

⚡ 关键点:model("模型名") 就是多厂商支持的入口。

如果 Spring AI 还没有内置 DeepSeek 或千问模型,你可以自定义实现 ChatModel:
然后 Spring AI 就能像调用内置模型一样调用你的自定义模型。

java 复制代码
@Component("deepSeek")
public class DeepSeekChatModel implements ChatModel {

    @Override
    public ChatResponse sendMessage(ChatMessage message) {
        // 调用 DeepSeek 的 REST API
        String result = callDeepSeekApi(message.getContent());
        return ChatResponse.of(result);
    }
}

5. 提示词

  • 提示词是引导大模型生成特定输出的输入,提示词的设计和措辞会极大地影响模型的响应结果。

  • Prompt 提示词是与模型交互的一种输入数据组织方式,本质上是一种复合结构的输入,在 prompt 我们是可以包含多组不同角色(System、User、Aissistant等)的信息。如何管理好 Prompt 是简化 AI 应用开发的关键环节。

  • Spring AI 提供了 Prompt Template 提示词模板管理抽象,开发者可以预先定义好模板,并在运行时替换模板中的关键词。在 Spring AI 与大模型交互的过程中,处理提示词首先要创建包含动态内容占位符 {占位符} 的模板,然后,这些占位符会根据用户请求或应用程序中的其他代码进行替换。在提示词模板中,{占位符} 可以用 Map 中的变量动态替换。

java 复制代码
@GetMapping("/prompt")
public String prompt(@RequestParam("name") String name, @RequestParam("voice") String voice){
    
    String userText= """
            给我推荐北京的至少三种美食
            """;
    // 用户信息        
    UserMessage userMessage = new UserMessage(userText);
    
    // 系统信息
    String systemText= """
            你是一个美食咨询助手,可以帮助人们查询美食信息。
            你的名字是{name},
            你应该用你的名字和{voice}的饮食习惯回复用户的请求。
            """;
    
    // PromptTemplate      
    SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
    
    // 替换占位符
    Message systemMessage = systemPromptTemplate
            .createMessage(Map.of("name", name, "voice", voice));
            
    Prompt prompt = new Prompt(List.of(userMessage, systemMessage));
    
    List<Generation> results = chatModel.call(prompt).getResults();
    
    return results.stream()
                   .map(x->x.getOutput().getContent())
                   .collect(Collectors.joining(""));
}

6. Spring AI的函数调用

  • Spring AI 的函数调用(Function Calling)功能允许大语言模型在生成回答时触发预定义的外部函数,从而实现动态数据获取或业务逻辑操作(如查询数据库、调用 API 等)。

  • SpringAI 帮我们规范了函数定义、注册等过程,并在发起模型请求之前自动将函数注入到 Prompt 中,而当模型决策在合适的时候去调用某个函数时,Spring AI 完成函数调用动作,最终将函数执行结果与原始问题再一并发送给模型,模型根据新的输入决策下一步动作。这其中涉及与大模型的多次交互过程,一次函数调用就是一次完成的交互过程。

  • 函数调用的核心流程

  • 第一步,定义函数:声明可供模型调用的函数(名称、描述、参数结构)。

  • 第二步,模型交互:将函数信息与用户输入一起发送给模型,模型决定是否需要调用函数。

  • 第三步,执行函数:解析模型的函数调用请求,执行对应的业务逻辑。

  • 第四步,返回结果:将函数执行结果返回给模型,生成最终回答。

6.1 函数调用实现

6.1.1 创建自定义的Function

  • 下面CalculatorService类自定义了加法和乘法运算的函数
java 复制代码
@Configuration
public class CalculatorService {

    public record AddOperation(int a, int b) {

    }

    public record MulOperation(int m, int n) {

    }

    @Bean
    @Description("加法运算")
    public Function<AddOperation, Integer> addOperation() {
        return request -> {
            return request.a + request.b;
        };
    }

    @Bean
    @Description("乘法运算")
    public Function<MulOperation, Integer> mulOperation() {
        return request -> {
            return request.m * request.n;
        };
    }
}

总结:
Spring AI 使自定义函数这个过程变得简单,只需定义一个返回 java.util.Function 的 @Bean 定义,并在调用 ChatModel 时将 bean 名称作为选项进行注册即可。在底层,Spring 会用适当的适配器代码包装你的函数,以便与 AI 模型进行交互,免去了编写繁琐的代码。

6.1.2 编写Controller

java 复制代码
    @GetMapping(value = "/chat", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public String ragJsonText(@RequestParam(value = "userMessage") String userMessage){
        return ChatClient.builder(chatModel)
                .build()
                .prompt()
                .system("""
						您是算术计算器的代理。
						您能够支持加法运算、乘法运算等操作,其余功能将在后续版本中添加,如果用户问的问题不支持请告知详情。
						在提供加法运算、乘法运算等操作之前,您必须从用户处获取如下信息:两个数字,运算类型。
						请调用自定义函数执行加法运算、乘法运算。
						请讲中文。
						""")
                .user(userMessage)
                .functions("addOperation", "mulOperation")
                .call()
                .content();
    }
  • 为了让模型知道并调用你的自定义函数,您需要在 Prompt 请求中启用它,如上述代码,在functions("addOperation", "mulOperation")中告知ChatClient要使用这两个自定义函数。
  • 另外指定了System Prompt:要求AI 模型被设定为一个算术计算器代理,能够执行加法和乘法运算,并且要求用户提供两个数字和运算类型。这个提示词内容很关键,如何让AI按照自己的意图去执行,要不断测试提示词内容。

6.1.3 测试

7. SpringAI调用Ollama

7.1 什么是Ollama

Ollama官方地址 https://ollama.com/

Ollama 是一个 在本地运行大模型(LLM) 的工具和平台。

它的核心目标是:

👉 让你在 自己的电脑上(Mac、Linux、Windows)非常方便地下载、运行和管理大语言模型(类似 OpenAI 的 GPT、Meta 的 LLaMA、Mistral 等)。

换句话说:

  • 如果 Hugging Face 更像是"模型超市",
  • 那么 Ollama 就是"本地模型的运行时 + 包管理器"。

🚀 Ollama 的主要特点

  1. 开箱即用

安装 Ollama 后,只需要一条命令就能启动一个大模型:
ollama run llama2

它会自动下载模型文件并运行,无需自己折腾复杂的依赖。

  1. 支持多种模型
  • 内置支持:LLaMA 2、Mistral、Phi-3、CodeLLaMA、Gemma 等

  • 也可以加载自定义模型(通过 Modelfile 配置)。

  1. 轻量化 & 本地推理
  • 针对消费级电脑优化,能在 MacBook 或普通 PC 上跑小规模 LLM。
  • 底层用的是 GGUF 格式的量化模型文件,显存/内存占用更低。
  1. 简单的 API 调用

提供一个类似 OpenAI API 的接口:

bash 复制代码
curl http://localhost:11434/api/generate -d '{
  "model": "llama2",
  "prompt": "Hello, Ollama!"
}'

这让它可以无缝接入到各种应用里(比如 LangChain、Spring AI)。

  1. 跨平台

最初只支持 macOS,现在已经支持 Linux 和 Windows。

  1. 隐私和安全

所有数据和模型都在本地运行,不会上传到云端 → 适合对数据安全要求高的场景。

7.2 使用Docker安装

bash 复制代码
docker pull ollama/ollama
bash 复制代码
(base) ➜  ~ docker run -d \
  --name ollama \
  -v ollama:/root/.ollama \
  -p 11434:11434 \
  ollama/ollama

-v ollama:/root/.ollama

数据卷映射,把宿主机的 ollama 数据卷挂载到容器内的 /root/.ollama 目录。
/root/.ollama 是 Ollama 存储模型文件、配置文件 的地方。

好处:即使容器删除,模型文件也会保留,不需要每次重新下载。

bash 复制代码
(base) ➜  ~ curl http://localhost:11434/api/tags
{"models":[]}

进入容器跑大模型

bash 复制代码
# 进入docker
docker exec -it ollama /bin/bash
# 运行1.5b模型
ollama run deepseek-r1:1.5b

启动大模型

7.3 SpringAI结合Ollama

java 复制代码
package com.beijing.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OllamaController {

    @Resource
    private OllamaChatModel ollamaChatModel;

    @GetMapping("/ollama")
    public String ollama(@RequestParam(value = "message") String message){
        return ollamaChatModel.call(message);
    }

}
java 复制代码
package com.beijing;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MoreLlmApplication {
    public static void main(String[] args) {
        SpringApplication.run(MoreLlmApplication.class, args);
    }
}
xml 复制代码
server:
  port: 16888

spring:
  application:
    name: moreLLM
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: deepseek-r1:1.5b
          temperature: 0.7
java 复制代码
<?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.beijing</groupId>
        <artifactId>SpringAi</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>moreLLM</artifactId>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-ollama</artifactId>
        </dependency>
    </dependencies>

</project>

8. 图像模型

8.1 Image Model API概述

  • 在Spring AI框架中,Image Model API旨在为与专注于图像生成的各种AI模型进行交互提供一个简单且可移植的接口,使开发者能够以最小的代码改动切换不同的图像相关模型。这一设计符合Spring模块化和互换性的理念,确保开发者可以快速调整其应用程序以适应不同的图像处理相关的AI能力。

  • 此外,通过支持像ImagePrompt这样的辅助类来进行输入封装以及使用ImageResponse来处理输出,图像模型API统一了与致力于图像生成的AI模型之间的通信。它管理请求准备和响应解析的复杂性,为图像生成功能提供直接而简化的API交互。

  • Image Model API建立在Spring AI通用模型API之上,提供了特定于图像的抽象和实现。

8.2 Image Model API接口及相关类

8.2.1 ImageModel(图像模型)

这里展示的是ImageModel接口定义:

java 复制代码
@FunctionalInterface
public interface ImageModel extends Model<ImagePrompt, ImageResponse> {
	ImageResponse call(ImagePrompt request);
}

8.2.2 ImagePrompt(图像提示)

ImagePrompt是一个封装了ImageMessage对象列表及可选模型请求选项的ModelRequest。下面显示的是ImagePrompt类的一个简化版本,省略了构造函数和其他工具方法:

java 复制代码
public class ImagePrompt implements ModelRequest<List<ImageMessage>> {
    private final List<ImageMessage> messages;
    private ImageOptions imageModelOptions;
    @Override
    public List<ImageMessage> getInstructions() {...}
	@Override
	public ImageOptions getOptions() {...}
}

8.2.3 ImageMessage(图像消息)

ImageMessage类封装了用于影响生成图像的文本及其权重。对于支持权重的模型,它们可以是正数或负数。

java 复制代码
public class ImageMessage {
	private String text; 
	private Float weight;
    public String getText() {...}
	public Float getWeight() {...}
}

8.2.4 ImageOptions(图像选项)

表示可以传递给图像生成模型的选项。ImageOptions接口扩展了ModelOptions接口,并用于定义可以传递给AI模型的一些可移植选项。

java 复制代码
public interface ImageOptions extends ModelOptions {
	Integer getN();
	String getModel();
	Integer getWidth();
	Integer getHeight();
	String getResponseFormat(); // openai - url or base64 : stability ai byte[] or base64
}

8.2.5 ImageResponse(图像响应)

持有AI模型的输出,每个ImageGeneration实例包含来自单一提示的可能多个输出结果之一。

java 复制代码
public class ImageResponse implements ModelResponse<ImageGeneration> {
	private final ImageResponseMetadata imageResponseMetadata;
	private final List<ImageGeneration> imageGenerations;
	@Override
	public ImageGeneration getResult() {
		// get the first result
	}
	@Override
	public List<ImageGeneration> getResults() {...}
	@Override
	public ImageResponseMetadata getMetadata() {...}
}

8.2.6 ImageGeneration(图像生成)

最终,ImageGeneration类扩展自ModelResult,代表输出响应及有关此结果的元数据。

java 复制代码
public class ImageGeneration implements ModelResult<Image> {
	private ImageGenerationMetadata imageGenerationMetadata;
	private Image image;
    @Override
	public Image getOutput() {...}
	@Override
	public ImageGenerationMetadata getMetadata() {...}
}

P13 TODO

附录

1.炸裂!Spring AI 1.0 正式发布 https://zhuanlan.zhihu.com/p/1909928795659567609

2.【尚硅谷SpringAI实战教程,springai轻松上手大模型应用开发】 https://www.bilibili.com/video/BV1Cxj7zjEng/?p=9&share_source=copy_web&vd_source=6888e998072955ff0cd273996df291f5

3.【2025吃透Spring AI 1.0全套教程(入门+实战+原理&源码;大模型+tools+mcp+Agent全流程落地),7天学完,让你少走99%弯路!!】https://www.bilibili.com/video/BV1z7h3zbEd2/?share_source=copy_web&vd_source=6888e998072955ff0cd273996df291f5

相关推荐
JQLvopkk1 小时前
机器视觉为何不用普通相机
人工智能·数码相机
AI航向标1 小时前
OpenClaw 完整本地部署安装(接入飞书)
人工智能·飞书·openclaw
接着奏乐接着舞。1 小时前
机器学习经验总结整理
人工智能·机器学习
Sim14801 小时前
iPhone将内置本地大模型,手机端AI实现0 token成本时代来临?
人工智能·ios·智能手机·iphone
AI航向标1 小时前
Openclaw一键本地部署接入豆包
人工智能·openclaw
蜡台1 小时前
JetBrains IDEA 安装 卸载相关总结
java·ide·intellij-idea·注册码
WJLSH1231 小时前
TomCat
java·tomcat
就是这么拽呢1 小时前
论文查重低但AIGC率高,如何补救?
论文阅读·人工智能·ai·aigc
supericeice1 小时前
创邻科技 AI智算一体机:支持 DeepSeek 671B 与 Qwen3 单机部署,覆盖纯CPU到多GPU多机扩展
大数据·人工智能·科技
لا معنى له2 小时前
Var-JEPA:联合嵌入预测架构的变分形式 —— 连接预测式与生成式自监督学习 ----论文翻译
人工智能·笔记·学习·语言模型