Spring AI技术分享

Spring 7 - Spring AI 技术分享报告

一、引言

1.1 背景介绍

​ 在软件开发领域,Java 长期以来一直是企业级应用开发的核心语言,而 Spring 框架(尤其是 Spring Boot)凭借其强大的生态体系和便捷的开发模式,已成为构建云原生与分布式系统的首选方案。

​ 随着 大语言模型(LLM)人工智能(AI) 技术的飞速发展,软件系统正从传统的“功能驱动”走向“智能驱动”。开发者对 AI 能力的需求日益增长,但 AI 开发生态长期以来偏向于 Python 语言,这在一定程度上限制了 Java 开发者 的参与与创新。

​ 为此,Spring 官方推出了 Spring AI 项目,旨在让 Java 开发者能够在熟悉的 Spring 框架体系中,便捷地使用主流大模型和 AI 服务。Spring AI 的出现,标志着 Spring 生态正式迈入人工智能时代。它为 Java 开发者提供了统一的 AI 接口抽象层,兼容包括 OpenAI、Azure、Ollama 等主流模型服务商,并支持多种模型类型(如文本生成、聊天对话、文本转图像等)。通过 可移植 API、POJO 数据映射、矢量数据库支持 以及 Spring Boot 自动装配机制,Spring AI 大幅降低了 AI 集成的复杂度,让开发者能够以更低的学习成本实现智能化应用开发。

​ 在此基础上,阿里云(Alibaba Cloud) 进一步推出了 Spring AI Alibaba —— 面向 Java 开发者的首个开源 AI 应用开发框架。该框架基于 Spring AI 构建,是在 Java 生态中集成 阿里云通义大模型 及 AI 服务的最佳实践。Spring AI Alibaba 不仅延续了 Spring AI 的统一接口设计思想,还在云原生环境中深度优化了性能与扩展性,提供了更加本地化、场景化的 AI 应用解决方案。

​ 通过 Spring AI Alibaba,Java 开发者可以轻松将通义大模型的自然语言处理、知识问答、文本生成、RAG 检索增强等能力融入到企业级系统中。该框架提供了高层次的 AI 驱动 API 抽象与云原生集成方案,使 AI 能力能够像数据库、消息队列等基础组件一样无缝嵌入业务系统。

​ 综上所述,Spring AI 与 Spring AI Alibaba 的相继推出,标志着 Java 开发者正式进入 AI 应用开发的新纪元。它们共同构建了一个开放、统一、可扩展的 AI 开发生态,打通了从模型调用到应用落地的全链路。这一创新不仅让 AI 技术真正走进企业级 Java 开发者的世界,也为推动 AI 技术的普惠化与产业化落地 奠定了坚实基础。

二、Spring AI 核心概念与架构

2.1 架构概览

​ Spring AI 是一个面向人工智能工程的应用框架,旨在解决 AI 集成过程中的核心挑战。它能够将企业的数据API与生成式 AI 模型(Generative AI)无缝连接,实现双向交互:一方面,AI 可以访问企业应用中的数据和功能接口,以生成智能化的分析、推荐或响应;另一方面,企业应用也可以利用 AI 的生成能力,将结果返回到业务系统中,丰富用户体验或辅助决策。通过这种“To There / To Here”的闭环机制,Spring AI 构建了一个企业级的 AI 应用开发桥梁,让 AI 能力可以像普通服务组件一样嵌入到业务系统中,降低开发复杂度并加速落地。

在这里插入图片描述

特性:
提示词(Prompts):

Prompt(提示词) 是引导 AI 模型生成特定输出的输入内容。它的设计和表达方式会直接影响模型的回答质量。

Spring AI 中,Prompt 的作用类似于 Spring MVC 的 View:你可以在文本中定义占位符,根据用户输入或程序逻辑动态填充内容,从而灵活控制模型输出。

随着 Spring AI 的发展,Prompt 的使用也会逐渐抽象化,例如结合历史对话、上下文文档或代理行为,以获得更智能的响应。

最初的 Prompt 只是简单字符串,如今已经演变为带有角色(如 “USER”、“SYSTEM”)和结构化信息的复杂输入格式,用于更精确地引导模型生成内容。

对话拦截器(Advisors):

Advisors API包括CallAdvisorCallAdvisorChain对于非流式处理方案,以及StreamAdvisorStreamAdvisorChain用于流式处理方案。 它还包括ChatClientRequest表示未密封的 Prompt 请求,ChatClientResponse用于聊天补全响应。两者都持有advise-context在整个顾问链中共享状态。

在这里插入图片描述

Advisor作用流程如下:

  1. 一个 AdvisedRequest先通过第一个 AdvisoraroundCall方法,在这里你可以对基于 AdvisedRequest做定制。例如记录log,修改其内容等。
  2. 调用 CallAroundAdvisorChainnextAroundCall(AdvisedRequest advisedRequest)方法,去调用下一个 AdvisoraroundCall方法。就这样一直执行完所有需要执行的 Advisor(也有可能执行到某个Advisor后,其不满足继续执行的条件,后面的就不执行了)
  3. 调用LLM的API,返回 AdvisedResponse
  4. AdvisedResponse就会以与 AdvisedRequest执行顺序相反的方向依次通过 Advisor,request最先到达第一个Advisor,response最后从其返回。 如下图所示

在这里插入图片描述

需特别说明的是,AdvisedRequestAdvisedResponse 均内置 AdvisorContext(数据类型为 Map<String, Object>),存入该 Map 的数据会在整个 Advisor 执行链中全程流转;所有 Advisor 均需实现 Ordered 接口,其定义的排序序号决定执行优先级 —— 序号越小的 Advisor 越先处理请求(如 3 个 Advisor 场景下,Request 流向为 Advisor1→Advisor2→Advisor3),而响应(Response)流向则相反,即最早处理请求的 Advisor 会最后处理响应(Response 流向为 Advisor3→Advisor2→Advisor1)。

对话记忆(Chat Memory):

​ 大模型的对话记忆并非人类那样的自主记忆,而是通过技术手段模拟实现,核心目的是保障多轮对话的连贯性,主要分为短期记忆与长期记忆两类基础形态,同时搭配优化策略解决存储与效率问题。

​ 短期记忆是最基础的实现方式,依赖大模型的上下文窗口(即单次可处理的 Token 上限)。多轮对话时,系统会将历史对话内容与当前用户提问拼接成完整提示词输入模型,使其能基于上下文 “记住” 此前的对话信息,比如用户告知身份后,模型后续回复会贴合该身份需求。但这种记忆存在明显局限,一旦对话长度超出窗口上限,早期内容会被丢弃,导致记忆断裂。

​ 长期记忆则通过外挂系统弥补短期记忆的不足,利用向量数据库、Redis 缓存等存储用户偏好、核心需求等关键信息,再借助 RAG 等技术,在对话时从外部存储中调取相关内容补充到上下文,实现长期信息留存,比如智能助手长期记住用户 “偏好简洁回答” 的需求。

​ 为解决全量存储导致的 Token 消耗过高、窗口溢出等问题,开发中会采用优化策略:比如会话缓存窗口记忆仅保留最近几轮对话,总结式记忆则提炼核心信息生成精简摘要,在控制内容长度的同时保留关键上下文,避免对话逻辑断裂。

工具调用(Tool Calling):

在这里插入图片描述

让大模型可以与企业业务进行互联。

检索增强生成(RAG):

在这里插入图片描述

让大模型可以跟企业业务数据进行互联(包括读取文件、分割文件、向量化),向量数据库支持,目前支持20+种向量数据库的集成。

模型上下文协议(MCP):

模型上下文协议(Model Context Protocol, MCP) 是一种标准化协议,用于使 AI 模型能够以结构化方式与外部工具和资源进行交互。它支持多种传输机制,以在不同环境下提供更大的灵活性。

MCP Java SDK 提供了模型上下文协议的 Java 实现,使开发者能够通过同步和异步通信模式,与 AI 模型和工具进行标准化交互。

Spring AI MCP 在 MCP Java SDK 的基础上进行了扩展,集成了 Spring Boot,提供了客户端和服务端的启动器(Starter)。开发者可以通过 Spring Initializer 快速启动并构建支持 MCP 的 AI 应用。

Java MCP 实现遵循三层架构:

在这里插入图片描述

结构化输出(Structured Output)

如果想从 LLM 接收结构化输出,Structured Output 可以协助将 ChatModel/ChatClient 方法的返回类型从 String 更改为其他类型。

LLM 生成结构化输出的能力对于依赖可靠解析输出值的下游应用程序非常重要。

开发人员希望快速将 AI 模型的结果转换为可以传递给其他应用程序函数和方法的数据类型,例如 JSON、XML 或 Java 类。Spring AI 结构化输出转换器有助于将 LLM 输出转换为结构化格式。

在这里插入图片描述

2.2 核心组件与接口

ChatClient:

ChatClient通过 Fluent API 与 AI 模型交互,同时支持同步和流式编程模型。

Fluent API 提供构建 Prompt组件的方法,这些组件将作为输入传递给 AI 模型。Prompt 包含指导 AI 模型输出和行为的指令文本。从 API 角度看,提示词由消息集合构成。

AI 模型处理两类主要消息:用户消息(直接来自用户的输入)和系统消息(由系统生成以引导对话)。

这些消息通常包含占位符,运行时根据用户输入进行替换,从而定制 AI 模型对用户输入的响应。

还可以指定一些 Prompt 选项,如要使用的 AI 模型名称,以及控制生成输出随机性/创造性的 temperature 参数。

ChatClient包括的一些基础功能,如:

  • 定制和组装模型的输入(Prompt)
  • 格式化解析模型的输出(Structured Output)
  • 调整模型交互参数(ChatOptions)

还支持更多高级功能:

  • 聊天记忆(Chat Memory)
  • 工具/函数调用(Function Calling)
  • RAG
创建ChatClient

使用 ChatClient.Builder 对象创建 ChatClient 实例,可以自动注入由Spring Boot 自动配置创建的默认 ChatClient.Builder 实例,也可以通过编程方式自行创建一个 ChatClient.Builder 实例并用它来得到 ChatClient 实例。

单一模型类型下的多ChatClient实例
@RestController
@RequestMapping("/ai")
public class ChatController {
    private static final Logger log = LoggerFactory.getLogger(ChatController.class);
    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }
    @GetMapping("/chat")
    public String chat(String input) {
        log.info("人工提问:"+input);

        String reply = this.chatClient.prompt()
                .user(input)
                .call()
                .content();

        return reply;
    }
}

application.yml配置文件(以调用阿里百炼大模型api key 为例)。注意:Spring AI 默认自动配置单个 ChatClient.Builder Bean,但应用中可能需要使用多个聊天模型。处理方法如下:

所有场景均需通过设置属性 spring.ai.chat.client.enabled=false 来禁用 ChatClient.Builder 自动配置。

该设置允许手动创建多个 ChatClient 实例。

server:
  port: 8080

spring:
  application:
    name: spring-ai-helloworld
  ai:
    dashscope:
      api-key: # xxx API
    chat:
      client:
        enabled: true

需要在项目中添加 spring-ai-alibaba-starter依赖:

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter</artifactId>
    <version>1.0.0-M3.2</version>
</dependency>

由于 spring-ai 相关依赖包还没有发布到中央仓库,如出现 spring-ai-core 等相关依赖解析问题,请在项目的 pom.xml 依赖中加入如下仓库配置。

<repositories>
    <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
    <snapshots>
    <enabled>false</enabled>
    </snapshots>
    </repository>
</repositories>

多平台多模型的ChatClient的实例:

@RestController
@RequestMapping("/more-platform-chat-client")
public class MorePlatformChatClientController {
    private final ChatModel dashScopeChatModel;

    private final ChatModel openAIChatModel;
    /**
     * @Description: @Qualifier注解是用来指定注入的bean的名字,value值需要到源码中查看,如不对应会报错:NoSuchBeanDefinitionException
     * 如openAiChatModel的路径见:org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration.java
     */
    public MorePlatformChatClientController(
            @Qualifier("dashscopeChatModel") ChatModel dashScopeChatModel,
            @Qualifier("openAiChatModel") ChatModel openAIChatModel
    ) {
        this.dashScopeChatModel = dashScopeChatModel;
        this.openAIChatModel = openAIChatModel;
    }

    @GetMapping("/{platform}/{prompt}")
    public String chat(
            @PathVariable("platform") String model,
            @PathVariable("prompt") String prompt
    ) {

        System.out.println("===============================================");
        System.out.println("DashScope Model:" + dashScopeChatModel.toString());
        System.out.println("OpenAI Model:" + openAIChatModel.toString());
        System.out.println("===============================================");

        if ("dashscope".equals(model)) {
            return dashScopeChatModel.call(new Prompt(prompt))
                    .getResult().getOutput().getContent();
        }

        if ("openAI".equals(model)) {
            return openAIChatModel.call(new Prompt(prompt))
                    .getResult().getOutput().getContent();
        }
        return "Error ...";
    }
}

调用多平台模型时对应的yml文件配置:
server:
  port: 8080

spring:
  application:
    name: spring-ai-helloworld
  ai:
    dashscope:
      api-key:  # xxx API
    chat:
      client:
        enabled: false

    openai:
      api-key: # xxx API
      base-url: https://xxx
依赖导入:
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter</artifactId>
        <version>1.0.0-M3.2</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
        <version>1.0.0-M2</version>
    </dependency>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>1.0.0-M2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
        <repository>
            <id>sonatype</id>
            <name>OSS Sonatype</name>
            <url>https://oss.sonatype.org/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>aliyunmaven</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>
对话模型(ChatModel):

​ 在 Spring AI 框架中,ChatModel 是面向文本对话任务的核心模型接口,用于实现应用与大语言模型(LLM)之间的自然语言交互。它接收一系列消息(Message)作为输入,这些消息不仅可以是纯文本内容,还支持包含多模态信息,如语音、图片、视频等。相比于传统的字符串输入输出方式,ChatModel 对消息格式进行了抽象与扩展,使开发者能够以更自然、更灵活的方式与 AI 模型进行对话。

​ 在 Spring AI Alibaba 中,ChatModel 复用了 Spring AI 的统一模型抽象 API,并与阿里巴巴的通义系列大模型服务(如通义千问、通义万相等)进行了深度适配。它通过统一的接口屏蔽了底层模型差异,让开发者在同一套编程模型下即可实现多种 AI 能力调用,如纯文本对话(ChatModel)、文生图(ImageModel)、文生语音(AudioModel)和语音转文本(ASR Model)等。

​ ChatModel 的交互过程基于 PromptChatResponse 两个关键概念:应用将用户输入或上下文信息封装为 Prompt 请求,通过 ChatModel 发送至后端模型;模型则根据输入内容和上下文语义生成响应消息(ChatResponse),返回给应用进行展示或后续处理。Spring AI Alibaba 提供了自动配置机制(spring-ai-alibaba-starter),开发者无需显式创建实例即可直接注入 ChatModel Bean,从而快速构建具备智能对话能力的业务应用。

​ 总体而言,ChatModel 的出现让开发者可以以标准化、模块化的方式将大模型对话能力嵌入到 Spring 应用中,实现从“程序调用模型”到“模型参与业务逻辑”的自然过渡,为企业级 AI 应用的快速集成和扩展提供了统一入口。

下面是对话模型的示例:

@RestController
public class ChatModelController {
  private final ChatModel chatModel;

  public ChatModelController(ChatModel chatModel) {
    this.chatModel = chatModel;
  }

  @RequestMapping("/chat")
  public String chat(String input) {
    ChatResponse response = chatModel.call(new Prompt(input));
    return response.getResult().getOutput().getContent();
  }
}
提示词(Prompt):

在 Spring AI 中,Prompt(提示词) 是引导 AI 模型生成特定输出的输入内容,是应用与大模型(LLM)进行交互的核心组件。Prompt 的设计方式和措辞对模型的响应效果有着显著影响——一个精心设计的 Prompt 能够让模型更好地理解上下文、执行指令,并生成更符合预期的结果。

在最初的阶段,Prompt 只是简单的字符串输入。然而,随着 AI 技术的发展,Prompt 的结构逐渐演化为可包含占位符和多角色信息的复杂输入格式。例如,在 Spring AI 与阿里云通义系列模型的适配中,Prompt 不仅包含用户输入,还可以包含系统指令、模型历史对话及工具调用信息,从而为模型提供更丰富的语义上下文。这种结构化的设计方式,使模型能够清楚地区分不同来源的信息并作出更有针对性的响应。

Prompt 中的消息通常按照“角色(Role)”进行分类,每个角色代表不同的语义层次:

  • 系统角色(System Role):定义 AI 的行为准则与响应方式,类似于对模型下达的“指令”或规则设定;
  • 用户角色(User Role):表示用户的提问、命令或输入,是 AI 生成回答的直接依据;
  • 助手角色(Assistant Role):代表模型自身的输出,即 AI 对用户输入的响应。通过记录助手角色的历史消息,系统能够保持对话的连贯性与上下文一致;
  • 工具/功能角色(Tool/Function Role):当模型需要调用外部功能(如执行计算或查询数据)时,该角色用于承载功能调用请求及返回信息。

在实现层面,Spring AI 将 Prompt 的处理过程抽象为类似 Spring MVC 中“视图(View)”的概念。开发者可以创建包含动态占位符的 Prompt 模板,并在运行时根据用户请求或应用逻辑填充具体内容。这种设计方式类似于 SQL 语句中带参数占位符的写法,使 Prompt 的生成更加灵活、可复用。

随着 Spring AI 的不断发展,框架也在引入更高层次的抽象来简化与 AI 模型的交互。例如,ChatModel 类可视为底层核心 API,负责与大模型进行基础通信;而 ChatClient 则构建在其之上,提供了更智能的交互方式——包括结合历史对话上下文、增强 Prompt 的知识信息(RAG)、以及实现具备“智能体”特征的行为逻辑。

总体而言,Prompt 在 Spring AI 中不仅是模型输入的载体,更是连接业务逻辑与智能推理的关键枢纽。通过结构化 Prompt 与多角色机制,Spring AI 为企业级应用提供了灵活、可扩展、可控的模型交互能力。

拦截器Advisors

Advisors API提供了一种灵活而强大的方式来拦截、修改和增强Spring 应用程序中的AI驱动交互。使用用户文本调用AI模型时的一种常见模式是使用上下文数据附加或增强提示。

此上下文数据可以是不同的类型。常见类型包括:

  • 您自己的数据:这是 AI 模型尚未训练过的数据,如特定领域知识、产品文档等,即使模型已经看到过类似的数据,附加的上下文数据也会优先生成响应。
  • 对话历史记录:聊天模型的 API 是无状态的,如果你告诉 AI 模型你的名字,它不会在后续交互中记住它,每次请求都必须发送对话历史记录,以确保在生成响应时考虑到先前的交互。
日志记录

SimpleLoggerAdvisor 是一个用于记录 ChatClient 的 requestresponse 数据 Advisor,这对于调试和监控您的 AI 交互非常有用。

要启用日志记录,请在创建 ChatClient 时将 SimpleLoggerAdvisor 添加到 Advisor 链中。建议将其添加到链的末尾:

    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }

要查看日志,需将 Advisor 包的日志记录级别设置为 DEBUG

logging:
  level:
    org.springframework.ai.chat.client.advisor: DEBUG

比如提问:“相似三角形怎么用?”,可看到日志输出中request和response的信息:

o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='相似三角形怎么用', metadata={messageType=USER}, messageType=USER}], modelOptions=DashScopeChatOptions: {"model":"qwen-plus","temperature":0.8,"enable_search":false,"incremental_output":true,"enable_thinking":false,"multi_model":false}}, context={}]

o.s.a.c.c.advisor.SimpleLoggerAdvisor    : response: {
  "result" : {
    "metadata" : {
      "finishReason" : "STOP",
      "contentFilters" : [ ],
      "empty" : true
    },
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "finishReason" : "STOP",
        "search_info" : "",
        "id" : "8de937d2-1a83-4613-8b04-c1518739b85d",
        "role" : "ASSISTANT",
        "messageType" : "ASSISTANT",
        "reasoningContent" : ""
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "相似三角形”是..."
    }
  },
  "metadata" : {
    "id" : "8de937d2-1a83-4613-8b04-c1518739b85d",
    "model" : "",
    "rateLimit" : {
      "requestsRemaining" : 0,
      "requestsReset" : 0.0,
      "tokensLimit" : 0,
      "requestsLimit" : 0,
      "tokensRemaining" : 0,
      "tokensReset" : 0.0
    },
    "usage" : {
      "promptTokens" : 12,
      "completionTokens" : 826,
      "totalTokens" : 838,
      "nativeUsage" : {
        "output_tokens" : 826,
        "input_tokens" : 12,
        "total_tokens" : 838,
        "prompt_tokens_details" : {
          "cached_tokens" : 0
        }
      }
    },
    "promptMetadata" : [ ],
    "empty" : true
  },
  "results" : [ {
    "metadata" : {
      "finishReason" : "STOP",
      "contentFilters" : [ ],
      "empty" : true
    },
    "output" : {
      "messageType" : "ASSISTANT",
      "metadata" : {
        "finishReason" : "STOP",
        "search_info" : "",
        "id" : "8de937d2-1a83-4613-8b04-c1518739b85d",
        "role" : "ASSISTANT",
        "messageType" : "ASSISTANT",
        "reasoningContent" : ""
      },
      "toolCalls" : [ ],
      "media" : [ ],
      "text" : "“相似三角形”是..."
    }
  } ]
}

除此之外还有敏感词拦截器SafeGuardAdvisor,用户也可以自定义拦截器。

自定义拦截

​ 假如我们要实现一个重读的拦截器,重读策略的核心在于让LLM重新审视输入问题,这借鉴了人类解决问题的思维当时。通过这种方式,LLM能够更深入地理解问题,发现复杂的模式,从而在各种推理任务中表现得更加强大。

{query}
再次阅读问题:{query}

​ 可以基于BaseAdvisor 来实现自定义Advisor,BaseAdvisor 实现了重复的代码,提供模板方法让我们可以专注于自己业务代码编写。

	@Override
	default ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
		Assert.notNull(chatClientRequest, "chatClientRequest cannot be null");
		Assert.notNull(callAdvisorChain, "callAdvisorChain cannot be null");

		ChatClientRequest processedChatClientRequest = before(chatClientRequest, callAdvisorChain);
		ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(processedChatClientRequest);
		return after(chatClientResponse, callAdvisorChain);
	}

上边这段代码是BaseAdivsor中的adviseCall代码,所以我们继承之后只用重写beforeafter代码即可。其中order代表优先级,order值越大,位于栈顶。根据官方order值相同顺序不确定。

public class ReReadAdvisor implements BaseAdvisor {
    private static final String DEFAULT_USER_TEXT_ADVISE = """
            {re2_input_query}
            Read the question again: {re2_input_query}
            """;

    @Override
    public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {
        String contents = chatClientRequest.prompt().getContents();
        String re2InputQuery = PromptTemplate.builder().template(DEFAULT_USER_TEXT_ADVISE).build()
                .render(Map.of("re2_input_query", contents));

        ChatClientRequest clientRequest = chatClientRequest.mutate() //用mutate复制一个chatClientRequest
                .prompt(Prompt.builder().content(re2InputQuery).build())
                .build();

        return clientRequest;
    }

    @Override
    public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
        return null;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

可看到已经修改了用户提示词:

o.s.a.c.c.advisor.SimpleLoggerAdvisor    : request: ChatClientRequest[prompt=Prompt{messages=[UserMessage{content='诸葛亮帅吗
Read the question again: 诸葛亮帅吗
', metadata={messageType=USER}, messageType=USER}], modelOptions=null}, context={}]
advisors责任链模式(有待进一步了解):
//内部的 this.advisorChain.nextCall(chatClientRequest) 正是触发整个责任链的入口。
//这个调用会执行第一个 Advisor,然后由第一个 Advisor 决定是否调用第二个,以此类推,直到整个链条执行完毕并返回最终的 ChatClientResponse。

@Override
	public ChatClientResponse nextCall(ChatClientRequest chatClientRequest) {
		Assert.notNull(chatClientRequest, "the chatClientRequest cannot be null");

		if (this.callAdvisors.isEmpty()) {
			throw new IllegalStateException("No CallAdvisors available to execute");
		}

		var advisor = this.callAdvisors.pop();

		var observationContext = AdvisorObservationContext.builder()
			.advisorName(advisor.getName())
			.chatClientRequest(chatClientRequest)
			.order(advisor.getOrder())
			.build();

		return AdvisorObservationDocumentation.AI_ADVISOR
			.observation(null, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, this.observationRegistry)
			.observe(() -> advisor.adviseCall(chatClientRequest, this));
	}
工具调用(Function Calling):

工具调用(Tool Calling),又称函数调用(Function Calling),是大型语言模型(LLM)实现与外部系统交互的核心机制之一。它允许模型在生成回答时,根据上下文智能地请求调用一个或多个外部工具,以获取信息或执行特定任务。通过这种机制,AI 不再局限于“语言理解和生成”,而能够扩展为一个具备真实操作能力的智能体。

​ 从本质上看,模型本身并不会直接执行工具调用操作,而是表达调用意图:当模型认为某项任务需要外部信息或动作时,它会在响应中生成一个结构化的“调用请求”,包括要调用的工具名称及输入参数。随后,由客户端应用程序负责识别并执行对应的工具逻辑(例如调用 API、访问数据库、执行脚本等),再将结果反馈给模型,使其继续生成更精确或更具行动力的输出。

根据使用场景,工具调用主要可分为两大类:

  1. 信息检索类工具(Retrieval Tools)
    这类工具用于从外部数据源中获取信息,如数据库查询、Web 搜索、文件读取或第三方 API 调用等。它常被用于**检索增强生成(RAG)**场景,使模型能够结合最新或特定领域的数据回答问题。例如,模型可以调用工具来查询当前天气、访问企业知识库或获取实时新闻资讯。
  2. 动作执行类工具(Action Tools)
    这类工具用于在系统中执行具体操作,如创建记录、发送邮件、提交表单、触发任务流等。它让模型具备“执行意图”的能力,可被用于自动化办公、客服任务、智能流程编排等场景。例如,模型可通过工具为用户预定航班、生成代码文件或执行测试用例。

值得注意的是,虽然我们常说“模型调用了工具”,但实际的调用与执行逻辑由开发者在应用层实现,模型仅能“请求”而无法直接访问底层 API。这种设计不仅确保了系统的可控性与安全性,也使得模型与外部功能解耦,从而在不同应用中以安全、灵活的方式扩展智能能力。

使用示例:

​ 在以下示例中,我们将创建一个聊天机器人,通过调用我们自己的函数来回答问题。具体而言,我们将注册一个城市时间查询函数,该函数支持接收单个或多个城市名称作为输入参数,并返回对应城市的实时时间数据。当 AI 模型接收到 “请告诉我现在北京时间几点了” 等具象化查询时,会自动触发工具调用逻辑,将城市信息作为参数传递至该函数以获取精准时间结果;同时,该机器人具备基础推理能力,可响应 “3 小时后北京时间几点了” 等衍生性时间查询需求。

通过 ToolCallAutoConfiguration类实现自动配置:

@Configuration
@ConditionalOnClass(GetTimeByZoneIdService.class)
public class ToolCallAutoConfiguration {
    @Bean
    public GetTimeByZoneIdService getCurrentTimeByTimeZoneIdService() {
        return new GetTimeByZoneIdService();
    }

    @Bean
    public TimeTools timeTools(GetTimeByZoneIdService service) {
        return new TimeTools(service);
    }

    @Bean
    public ChatClient chatClient(ChatModel chatModel) {
        return ChatClient.builder(chatModel)
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }

}

Controller接口测试调用工具类:

@RestController
@RequestMapping("/time")
public class TimeController {
    private static final Logger log = LoggerFactory.getLogger(TimeController.class);
    private final ChatClient dashScopeChatClient;

    private final TimeTools timeTools;

    public TimeController(ChatClient chatClient, TimeTools timeTools) {

        this.dashScopeChatClient = chatClient;
        this.timeTools = timeTools;
    }

    /**
     * No Tool
     */
    @GetMapping("/chat")
    public String simpleChat(@RequestParam(value = "query", defaultValue = "请告诉我现在德国和北京时间几点了") String query) {

        return dashScopeChatClient.prompt(query).call().content();
    }

    /**
     * Methods as Tools
     */
    @GetMapping("/chat-tool-method")
    public String chatWithTimeFunction(@RequestParam(value = "query", defaultValue = "那你知道3小时候北京时间是几点吗") String query) {
        String res = dashScopeChatClient.prompt(query).tools(timeTools).call().content();
        log.info(res);
        return res;
    }

}

以下是聊天机器人使用TimeTools工具类的效果,用户提问:“请告诉我现在德国和北京时间几点了”,聊天机器人可准确回答当前的实时时间:

在这里插入图片描述

若不使用TimeTools工具类,无法获取到具体时间信息:

在这里插入图片描述

同时还支持简单的推理问题,提问的问题为:“3小时候北京时间是几点?”:

在这里插入图片描述

尽管查询实时时间的需求可通过 Java 标准类库直接实现,但本示例主要在于提供一套 标准化的外部服务集成范式。当业务场景扩展至 “查询当前天气”“获取地理位置信息” 等更复杂的外部依赖型需求时,可复用本示例的工具调用架构:通过封装外部服务接口、标准化参数传递与结果解析逻辑,即可快速实现外部能力与 AI 智能体的集成,高效扩展智能体的业务覆盖范围。

相关依赖导入:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springai</groupId>
    <artifactId>spring-ai-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-ai-helloworld</name>
    <description>spring-ai-helloworld</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
        <!-- Spring AI -->
        <spring-ai.version>1.1.0-M3</spring-ai.version>
        <!-- Spring AI Alibaba -->
        <spring-ai-alibaba.version>1.0.0.4</spring-ai-alibaba.version>
        <!-- Spring Boot -->
        <spring-boot.version>3.5.7</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-bom</artifactId>
            <version>${spring-ai-alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>


	<!--查询时间-->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-tool-calling-time</artifactId>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud.ai</groupId>
                <artifactId>spring-ai-alibaba-bom</artifactId>
                <version>${spring-ai-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>
</project>
搭建MCP服务:

参考:https://blog.youkuaiyun.com/static_coder/article/details/147732655

MCP服务端搭建

Spring AI支持MCP服务和客户端,只需要引入对应的依赖,用户就可以开发自己的服务和客户端。

Spring AI MCP (模型上下文协议) 服务器引导启动器提供了在Spring Boot应用程序中设置MCP服务器的自动配置。它使MCP服务器功能与Spring Boot的自动配置系统无缝集成。

MCP服务器启动程序提供:

  • 自动配置MCP服务器组件
  • 同时支持同步和异步操作模式
  • 多个传输层选项
  • 灵活的工具、资源和快速规范
  • 更改通知功能
Maven依赖引入

MCP Server有三个常用依赖:

  • spring-ai-starter-mcp-server:支持STDIO(标准流)传输的核心服务器
  • spring-ai-starter-mcp-server-webmvc:基于Spring MVC的SSE传输实现
  • spring-ai-starter-mcp-server-webflux:基于Spring WebFlux的SSE传输实现

这里我们选择基于Spring MVC的SSE传输实现实现方式。

<!-- 依赖管理 -->
<dependencyManagement>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- 实际要用到的依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>

MCP服务器配置
server:
  port: 8080

spring:
  application:
    name: mcp-server
  ai:
    mcp:
      server:
        name: recommend-mcp-server
        sse-message-endpoint: /api/v1/mcp

其他配置默认即可。

实现MCP服务

@Tool 是 Spring AI MCP 框架中用于快速暴露业务能力为 AI 工具的核心注解,该注解实现 Java 方法与 MCP 协议工具的自动映射,并且可以通过注解的属性 description,帮助人工智能模型根据用户输入的信息决定是否调用这些工具,并返回相应的结果。

MCP接口:

public interface RecommendService {

    String recommendGzhInfo();

    String bestContext();
}

MCP实现:

这里定义了两个MCP方法,一个模拟推荐技术类公众号,一个是选择公众号中最好的文章。

@Service
public class RecommendServiceImpl implements RecommendService {

    @Tool(description = "推荐技术类公众号")
    @Override
    public String recommendGzhInfo() {
        return "推荐【编程朝花夕拾】公众号,该公众号精选编程干货,回顾技术经典,分享实战经验、可以助你温故知新、在代码世界不断精进";
    }

    @Tool(description = "公众号中最好的文章")
    @Override
    public String bestContext() {
        return "技术类中【编程朝花夕拾】公众号的文章,都偏向技术干货,对于技术宅,都是好内容!";
    }
}
注册MCP方法:
@Configuration
public class ToolCallbackProviderConfig {

    @Bean
    public ToolCallbackProvider recommendTools(RecommendServiceImpl recommendService) {
        return MethodToolCallbackProvider.builder().toolObjects(recommendService).build();
    }
}
MCP服务启动:

在这里插入图片描述

启动之后,日志上显示注册了2个工具,说明注册成功。

MCP客户端搭建

MCP客户端常用的有两个:

  • spring-ai-starter-mcp-client:核心组件提供STDIO和基于HTTP的SSE支持
  • spring-ai-starter-mcp-client-webflux:基于SSE的WebFlux传输

这里我们选择基于基础的HTTP的SSE支持的依赖

Maven依赖引入
<!-- 依赖管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        
    </dependencies>
</dependencyManagement>
<!-- 实际用到的依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<!-- 使用的大模型依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
MCP客户端配置
server:
  port: 8081

spring:
  application:
    name: mcp-client
  ai:
    openai:
      api-key: # xxx API
      base-url: # xxx

    chat:
      client:
        enabled: true
    mcp:
      client:
        name: recommend-mcp-client
        sse:
          connections:
            server1:
              url: http://localhost:8080
        toolcallback:
           enabled: true
搭建应用调用MCP服务:
@RestController
public class ChatController {
    @Autowired
    private OpenAiChatModel openAiChatModel;

    @Autowired
    private ToolCallbackProvider toolCallbackProvider;

    @GetMapping("/ai/generate")
    public String generate(@RequestParam(value = "message", defaultValue = "推荐一个公众号") String message) {
        ChatClient chatClient = ChatClient.builder(openAiChatModel)
                .defaultTools(toolCallbackProvider.getToolCallbacks())
                .build();
        ChatClient.CallResponseSpec call = chatClient.prompt(message).call();
        String content = call.content();
        return content;
    }
}
MCP客户端启动

在这里插入图片描述

客户端测试

在这里插入图片描述

对话记忆(Chat Memory):

​ “大模型的对话记忆”(Chat Memory)是人工智能与自然语言处理领域的重要概念,特别针对具有深度学习能力的大型语言模型(Large Language Model,LLM)。它指模型在与用户进行多轮交互式对话过程中,能够追踪、理解并利用先前的对话上下文,从而在持续的交流中保持连贯性和上下文感知能力。通过这种机制,模型不仅能对即时输入做出合理响应,还能基于历史对话内容推断用户意图,实现更自然、更智能的交互体验。

​ 然而,从技术实现上看,LLM 本身是**无状态(stateless)**的,也就是说,模型在每一次推理(inference)过程中都不会主动保留任何历史交互信息。如果应用层不对上下文进行管理,那么模型在多轮对话中将无法记住之前的交流内容,导致对话割裂或语义丢失。

​ 为了解决这一问题,Spring AI 框架引入了 聊天记忆(Chat Memory)机制,使开发者能够在多轮对话中存储、检索和管理上下文信息。Spring AI 提供了 ChatMemory 抽象,用于定义不同的记忆策略;而具体的消息存储与读取由 ChatMemoryRepository 实现。
通过这种分层设计,开发者可以根据业务需求灵活配置记忆策略,例如:

  • 保留最近 N 条消息,以节省上下文长度;
  • 按时间窗口保留对话内容,适合临时上下文;
  • 按 Token 限制管理历史记录,平衡性能与语义完整性。

值得注意的是,在应用设计中,需要区分**聊天记忆(Chat Memory)聊天记录(Chat History)**两个概念:

  • 聊天记忆是指模型用于保持上下文感知、支撑当前对话逻辑所需的信息;
  • 聊天记录则是对整个会话过程的完整存档,包括用户与模型的所有消息往来。

Spring AI 的 ChatMemory 抽象专注于前者——即为模型提供可控的上下文信息管理能力。而如果应用需要长期保存完整的交互日志(如审计、追踪或分析场景),则应使用其他持久化方案,如基于 Spring Data 的数据库存储机制。

基于memory的对话记忆

spring-ai支持基于chat memory的对话记忆,也就是不需要调用显示的记录每一轮的对话历史。下边是一个基于内存存储的对话记忆实现:

public class ChatController {
    private static final Logger log = LoggerFactory.getLogger(ChatController.class);
    private final ChatClient chatClient;

    //在构造器中设置的话,advisors会在多个对话中生效。
    //也可以只在一次对话中设置生效
    public ChatController(ChatClient.Builder builder, ChatMemory chatMemory) {
        this.chatClient = builder
                .defaultAdvisors(
                        PromptChatMemoryAdvisor.builder(chatMemory).build()
                )
                .build();
    }
    @GetMapping("/chat")
    public String chat(String input) {
        log.info("人工提问:"+input);

            String content = this.chatClient.prompt()
                    .user("我叫柴可基")
                    .call()
                    .content();

        System.out.println(content);
        System.out.println("-----------------------------------------");
        content = this.chatClient.prompt()
                .user("我叫什么")
                .call()
                .content();

		return content;

    }
}
对话返回的结果:

在这里插入图片描述

引入ChatMemory依赖:
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-autoconfigure-model-chat-memory</artifactId>
    </dependency>
检索增强生成(RAG):

检索增强生成(RAG)是一种实用技术,可有效克服大型语言模型在长文本内容处理、事实准确性保障及上下文感知能力方面存在的局限性。

Spring AI 对 RAG 提供支持,其采用的模块化架构既允许开发者自行构建自定义的 RAG 流程,也可借助顾问 API(Advisor API)直接使用现成的 RAG 流程。

QuestionAnswerAdvisor

Spring AI 借助顾问 API(Advisor API),为常见的检索增强生成(RAG)流程提供了现成的支持能力。

使用QuestionAnswerAdvisor或VectorStoreChatMemoryAdvisor,需要在项目中添加 spring-ai-advisors-vector-store 依赖包。

<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>

向量数据库存储的是AI模型不知道的数据。当用户的问题发送至AI模型时,一个QuestionAnswerAdvisor会在向量数据库查询与该用户问题相关的文档。

来自向量数据库的响应被附加到用户文本中,为 AI 模型生成响应提供上下文。

假设已将数据加载到VectorStore中,只需向ChatClient提供一个QuestionAnswerAdvisor实例,即可执行RAG操作。

    @GetMapping("/chat")
    public String chat(String input) {

        return chatClient.prompt()
            .user(input)
            .advisors(new QuestionAnswerAdvisor(vectorStore))
            .call()
            .content();

    }

在此示例中,QuestionAnswerAdvisor将对矢量数据库中的所有文档执行相似性搜索。若要限制搜索的文档类型,可通过 SearchRequest 传入类 SQL 格式的过滤表达式 —— 该表达式在所有VectorStore中均具备可移植性。

此过滤表达式既可以在创建QuestionAnswerAdvisor时配置(配置后将对所有对话客户端(ChatClient)请求持续生效),也可以在运行时按单个请求分别提供。

以下是创建QuestionAnswerAdvisor其中阈值为0.8并返回Top 5的结果。

var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
        .searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(5).build())
        .build();
RetrievalAugmentationAdvisor

Spring AI 包括一个 RAG 模块库,可以使用它们来构建自己的 RAG 流。 RetrievalAugmentationAdvisor是一个Advisor为最常见的 RAG 流提供开箱即用的实现, 基于模块化架构。

要使用RetrievalAugmentationAdvisor,您需要添加spring-ai-rag对项目的依赖:

<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-rag</artifactId>
</dependency>
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
        .documentRetriever(VectorStoreDocumentRetriever.builder()
                .similarityThreshold(0.50)
                .vectorStore(vectorStore)
                .build())
        .build();

String answer = chatClient.prompt()
        .advisors(retrievalAugmentationAdvisor)
        .user(question)
        .call()
        .content();

默认情况下,RetrievalAugmentationAdvisor不允许检索到的上下文为空。当这种情况发生时, 它指示模型不回答用户查询。可以按如下方式允许空上下文。

Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
        .documentRetriever(VectorStoreDocumentRetriever.builder()
                .similarityThreshold(0.50)
                .vectorStore(vectorStore)
                .build())
        .queryAugmenter(ContextualQueryAugmenter.builder()
                .allowEmptyContext(true)
                .build())
        .build();

String answer = chatClient.prompt()
        .advisors(retrievalAugmentationAdvisor)
        .user(question)
        .call()
        .content();

VectorStoreDocumentRetriever接受FilterExpression以根据元数据过滤搜索结果。 可以在实例化VectorStoreDocumentRetriever或在每个请求的运行时, 使用FILTER_EXPRESSIONadvisor 上下文参数。

Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder()
        .documentRetriever(VectorStoreDocumentRetriever.builder()
                .similarityThreshold(0.50)
                .vectorStore(vectorStore)
                .build())
        .build();

String answer = chatClient.prompt()
        .advisors(retrievalAugmentationAdvisor)
        .advisors(a -> a.param(VectorStoreDocumentRetriever.FILTER_EXPRESSION, "type == 'Spring'"))
        .user(question)
        .call()
        .content();
格式化输出(Structured Output):

Spring AI 提供的 Converter 实现有 AbstractConversionServiceOutputConverter, AbstractMessageOutputConverter, BeanOutputConverter, MapOutputConverter and ListOutputConverter

  • BeanOutputConverter - 使用指定的 Java 类(例如 Bean)或 ParameterizedTypeReference 配置,此转换器指示 AI 模型生成符合 DRAFT_2020_12 的 JSON 响应,JSON 模式派生自指定的 Java 类,随后,它利用 ObjectMapper 将 JSON 输出反序列化为目标类的 Java 对象实例。
  • MapOutputConverter - 该实现指导 AI 模型生成符合 RFC8259 的 JSON 响应,此外,它还包含一个转换器实现,该实现利用提供的 MessageConverter 将 JSON 负载转换为 java.util.Map<String, Object> 实例。
  • ListOutputConverter - 该实现指导 AI 模型生成逗号分隔的格式化输出,最终转换器将模型文本输出转换为 java.util.List。

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值