【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

相关推荐
lxmyzzs2 小时前
【图像算法 - 28】基于YOLO与PyQt5的多路智能目标检测系统设计与实现
人工智能·算法·yolo·目标检测
golang学习记2 小时前
Qwen Code重大更新: 直接秒了GTP-5
人工智能
ygyqinghuan2 小时前
PyTorch 构建神经网络
人工智能·pytorch·神经网络
SmartBrain2 小时前
华为MindIE 推理引擎:架构解析
人工智能·华为·架构·推荐算法
失散132 小时前
分布式专题——15 ZooKeeper特性与节点数据类型详解
java·分布式·zookeeper·云原生·架构
ThisIsMirror2 小时前
Spring的三级缓存如何解决单例Bean循环依赖
java·spring·缓存
love530love2 小时前
EPGF架构:Python开发的长效稳定之道
开发语言·ide·人工智能·windows·python·架构·pycharm
菠菠萝宝2 小时前
【Java八股文】12-分布式面试篇
java·分布式·zookeeper·面试·seata·redisson
yk100102 小时前
Spring DefaultSingletonBeanRegistry
java·后端·spring