> 技术文档 > 学习SpringAI这一篇就够了

学习SpringAI这一篇就够了


文章目录

  • 一、简介
    • 1.1 Spring AI 简介
      • 定义与目标
      • 与 Spring 生态系统的关系
    • 1.2 应用场景
      • 自然语言处理
      • 图像生成
      • 智能客服
    • 1.3 优势与特点
      • 简化 AI 集成
      • 模型支持
      • 与 Spring 框架的无缝结合
  • 二、快速入门
    • 一、环境要求与支持版本
    • 二、项目创建方式
    • 三、依赖管理与仓库配置
      • (一)稳定版本(1.0.0-M6 及以后)
      • (二)快照版本(Snapshot)
    • 四、引入 Spring AI BOM
    • 五、添加具体功能依赖
    • 六、快速开始示例
  • 三、SpringAI核心概念
    • Models
    • Prompts
    • Embeddings
    • Structured Output
    • Bringing Your Data
    • Tool Calling
    • Retrieval Augmented Generation
      • 技术实现流程
        • 1. **批处理式数据预处理(ETL管道)**
        • 2. **用户查询实时处理**
      • 技术优势
  • 四、SpringAI核心组件
    • ChatClient
      • 一、ChatClient 概述
      • 二、创建 ChatClient
      • 三、流式 API 核心用法
      • 四、提示模板与动态参数
      • 五、默认配置与动态覆盖
      • 六、Advisors配置
    • Advisor
      • 一、Advisors 核心概念与作用
      • 二、核心组件与接口
      • 三、执行流程与顺序控制
      • 四、自定义顾问实现
      • 五、内置顾问与常用场景
      • 六、配置与最佳实践
    • Prompt
      • 一、Prompts 核心概念与作用
      • 二、Prompt 核心结构与接口
      • 三、Prompt 构建示例
      • 四、多模态与高级特性
      • 五、与其他组件的集成
    • ChatMemory
      • 一、ChatMemory 核心概念与作用
      • 二、快速开始与默认配置
      • 三、记忆类型与实现
      • 四、存储实现与配置
      • 五、与 ChatClient 集成(通过 Advisors)
      • 六、与 ChatModel 直接集成
      • 七、配置属性与最佳实践
    • Tool Calling
      • 一、Tool Calling 核心概念与作用
      • 二、快速开始:工具定义与使用
      • 三、工具定义方式
        • (一)基于方法的工具(Method as Tools)
        • (二)基于函数的工具(Functions as Tools)
      • 四、工具核心组件与接口
      • 五、工具执行流程
      • 六、工具结果处理
      • 七、工具上下文与异常处理
      • 八、支持的模型与最佳实践
      • 九、工具与其他组件集成
    • RAG
      • 一、RAG 核心概念与作用
      • 二、核心 Advisor 实现
        • (一)QuestionAnswerAdvisor
        • (二)RetrievalAugmentationAdvisor
      • 三、RAG 模块化架构
        • (一)Pre-Retrieval(检索前处理)
        • (二)Retrieval(检索)
        • (三)Post-Retrieval(检索后处理)
        • (四)Generation(生成)
      • 四、关键配置与最佳实践
      • 五、依赖与集成
      • 六、典型应用场景

一、简介

1.1 Spring AI 简介

定义与目标

  • SpringAI是一个基于Spring框架的开源项目,旨在简化人工智能(AI)技术在 Java 应用程序中的集成过程。
  • 可以快速将大语言模型、自然语言处理、图像生成等 AI 功能融入到 Spring Boot 或其他 Spring 项目中。
  • 核心目标在于降低 AI 技术的使用门槛,并提升 AI 应用开发效率

与 Spring 生态系统的关系

  • 在架构层面,Spring AI 遵循 Spring 框架的依赖注入(DI)、控制反转(IoC)以及面向切面编程(AOP)等核心设计理念。
  • 开发者可以像使用 Spring 其他组件一样,通过注解或 XML 配置的方式管理 AI 相关的 Bean,如模型客户端、提示工程处理器等,实现 AI 功能的灵活装配与扩展。

1.2 应用场景

自然语言处理

  • 文本生成:利用 Spring AI 可轻松实现自动生成文章、故事、报告等内容。例如在新闻媒体行业,可基于模板和现有数据自动生成体育赛事、财经数据等方面的简短新闻报道。
  • 情感分析:通过 Spring AI 可以对用户评论、社交媒体内容等文本进行情感分析,判断其情感倾向(积极、消极或中性)。电商平台可利用该功能分析用户对商品的评价,帮助商家了解消费者的满意度和需求,及时调整产品策略和服务质量。

图像生成

  • 创意设计辅助:广告公司或设计团队可以使用 Spring AI 开发的应用,根据文字描述生成创意图像,为设计工作提供灵感和参考。
  • 产品展示图生成:电商平台可以利用 Spring AI 自动生成产品的展示图片。

智能客服

  • 自动问答:基于 Spring AI 开发的智能客服系统可以自动回答用户的常见问题,减轻客服人员的工作负担。

1.3 优势与特点

简化 AI 集成

  • Spring AI 为不同类型的 AI 模型(如语言模型、图像模型等)提供了统一的编程接口,开发者可以使用相同的方式调用不同的模型。
  • 无论是调用 OpenAI 的 GPT 模型还是本地部署的 LLaMA 模型,都可以通过 Spring AI 提供的 ChatClient 接口进行操作。

多模型支持

  • Spring AI 支持多种主流的 AI 模型和服务提供商,具有良好的模型兼容性和扩展性。

与 Spring 框架的无缝结合

  • Spring AI 遵循 Spring 框架的编程模型,使用注解、依赖注入等特性,开发者可以使用熟悉的方式开发 AI 应用。
  • Spring AI 提供了 Spring Boot Starter 依赖,能够与 Spring Boot 无缝集成。通过自动配置和 Starter 机制,开发者可以快速搭建基于 Spring Boot 的 AI 应用。

二、快速入门

一、环境要求与支持版本

  • Spring Boot 版本:当前支持 Spring Boot 3.4.x,未来将支持 3.5.x。
  • JDK 版本:需使用与 Spring Boot 兼容的 JDK 版本(建议 JDK 17+)。

二、项目创建方式

  1. Spring Initializr
    • 访问 start.spring.io。
    • 在依赖选择中添加 AI 相关模块(如 AI Models、Vector Stores)。
  2. 手动创建:通过 Maven 或 Gradle 构建项目,添加对应依赖。

三、依赖管理与仓库配置

(一)稳定版本(1.0.0-M6 及以后)

  • Maven 配置:无需额外仓库,直接从 Maven Central 拉取。
  • Gradle 配置:使用 mavenCentral() 仓库。

(二)快照版本(Snapshot)

  1. Maven 仓库配置
<repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases><enabled>false</enabled></releases> </repository> <repository> <name>Central Portal Snapshots</name> <id>central-portal-snapshots</id> <url>https://central.sonatype.com/repository/maven-snapshots/</url> <snapshots><enabled>true</enabled></snapshots> </repository></repositories>
  1. Gradle 仓库配置
repositories { mavenCentral() maven { url \'https://repo.spring.io/milestone\' } maven { url \'https://repo.spring.io/snapshot\' } maven { name = \'Central Portal Snapshots\' url = \'https://central.sonatype.com/repository/maven-snapshots/\' }}
  1. Maven 镜像配置注意事项
    • settings.xml 中存在通配符镜像(*),需排除 Spring 快照仓库:
<mirror> <id>my-mirror</id> <mirrorOf>*,!spring-snapshots,!central-portal-snapshots</mirrorOf> <url>https://my-company-repository.com/maven</url></mirror>

四、引入 Spring AI BOM

  • 作用:统一管理 Spring AI 依赖版本,避免版本冲突。
  1. Maven 配置
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>
  1. Gradle 配置
dependencies { implementation platform(\"org.springframework.ai:spring-ai-bom:1.0.0-SNAPSHOT\") // 添加具体模块依赖(如 OpenAI 集成) implementation \'org.springframework.ai:spring-ai-openai\'}

五、添加具体功能依赖

根据需求选择以下模块依赖:

  1. 聊天模型(Chat Models)
    • spring-ai-openai:集成 OpenAI 聊天模型(如 GPT-3.5/4)。
    • spring-ai-anthropic:集成 Anthropic 模型(如 Claude)。
  2. 嵌入模型(Embeddings Models)
    • spring-ai-embeddings-openai:OpenAI 文本嵌入模型。
  3. 图像生成模型(Image Generation Models)
    • spring-ai-image-generator-openai:OpenAI 图像生成(如 DALL・E)。
  4. 转录模型(Transcription Models)
    • spring-ai-transcription-openai:OpenAI 语音转文本(如 Whisper)。
  5. 向量数据库(Vector Databases)
    • spring-ai-vector-store-pinecone:集成 Pinecone 向量存储。
    • spring-ai-vector-store-weaviate:集成 Weaviate 向量存储。

六、快速开始示例

  1. 引入 OpenAI 聊天模型依赖
<dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai</artifactId> </dependency>  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency></dependencies>
  1. 创建简单的聊天客户端
import org.springframework.ai.chat.ChatClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class AIController { private final ChatClient chatClient; @Autowired public AIController(ChatClient chatClient) { this.chatClient = chatClient; } @GetMapping(\"/ai/chat\") public String chat(@RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); }}
  1. 配置 OpenAI API 密钥
    • application.properties 中添加:
spring.ai.openai.api-key=your-openai-api-key

三、SpringAI核心概念

Models

根据输入输出类型对常见的模型进行分类:

学习SpringAI这一篇就够了

Prompts

提示词(Prompt)是引导AI模型生成特定输出的语言输入基础。

提示词并非简单的字符串——以ChatGPT的API为例,单个提示词可能包含多个具有不同角色的文本输入。

  • 系统角色(System Role):定义模型行为准则,设定交互上下文
  • 用户角色(User Role):通常指用户的实际输入内容

Spring AI采用基于文本的模板引擎来实现提示词的创建与管理,其底层使用开源库StringTemplate实现该功能。

例如一个基础提示词模板:

Tell me a {adjective} joke about {content}.

在Spring AI框架中,提示词模板的定位类似于Spring MVC架构中的视图层(View)。开发者通过提供模型对象(通常是java.util.Map)来填充模板中的占位符,最终\"渲染\"生成的字符串将作为AI模型的输入内容。

Embeddings

嵌入是将文本、图像或视频转化为数值化表示的技术,其核心在于捕捉输入数据之间的关联性。

通过将文本、图像及视频转换为浮点数数组(即向量),嵌入技术能够有效编码原始数据的语义信息。该数组的长度称为向量的维度(dimensionality)

通过计算两个文本对应向量之间的数值距离,应用程序可精确量化原始对象之间的相似度。例如:

  • 语义搜索:比对查询文本与文档库的嵌入向量
  • 内容推荐:识别相似特征的媒体资源
  • 异常检测:发现偏离常规模式的数据点

学习SpringAI这一篇就够了

Structured Output

AI模型的输出本质上是字符串形态,即使请求返回JSON格式,其本质仍是包含JSON文本的java.lang.String,而非可直接操作的JSON数据结构。

SpringAI提供结构化输出适配器解决该痛点

学习SpringAI这一篇就够了

Bringing Your Data

GPT-3.5/4.0等模型的训练数据截止到2021年9月(约650GB数据集),对于之后的事件或专有领域知识存在固有局限。以下是突破这一限制的解决方案:

  1. 微调(Fine-Tuning):通过调整模型内部权重参数,使其适应特定领域数据
  2. 提示词填充:在上下文窗口中直接注入相关数据
  3. 检索增强生成(RAG):基于语义相似度的向量搜索,动态构建含上下文的提示词
维度 微调 提示词填充 RAG 实施成本 $$$$ $ $$ 知识更新延迟 月/季度级 实时 近实时 适合场景 标准化术语 简单QA 复杂知识系统 是否需要ML专家 是 否 部分

Spring AI推荐优先采用RAG模式,通过VectorStoreTemplate简化实现

学习SpringAI这一篇就够了

Tool Calling

大语言模型(LLMs)在训练完成后即处于固化状态,这导致其知识存在时效性局限,且无法直接访问或修改外部数据。

工具调用(Tool Calling)机制正是为了解决这些缺陷而设计。该机制允许开发者将自定义服务注册为工具,从而将大语言模型与外部系统的API连接起来。这些外部系统能够为LLM提供实时数据,并代其执行数据处理操作。

Spring AI 极大简化了工具调用的代码实现

  • 自动处理工具调用的交互流程
  • 只需通过@Tool注解声明工具方法,并在提示词配置中启用,即可让模型调用该工具
  • 支持在单次提示词中定义和引用多个工具

工具调用流程详解

  1. 工具注册
    在聊天请求中需包含工具定义,每个工具定义包括:
    • 工具名称
    • 功能描述
    • 输入参数的结构化模式(Schema)
  2. 模型决策
    当模型决定调用工具时,会返回包含以下内容的响应:
    • 目标工具名称
    • 符合预定义模式的输入参数
  3. 应用端执行
    • 应用根据工具名称定位并执行对应服务
    • 处理工具调用的返回结果
  4. 结果反馈
    • 应用将工具执行结果返回给模型
    • 模型结合该结果生成最终响应

学习SpringAI这一篇就够了

Retrieval Augmented Generation

检索增强生成(Retrieval Augmented Generation,RAG)是一种通过将相关数据动态注入提示词,以提升AI模型响应准确性的技术方案。其核心在于建立外部知识库大语言模型的协同机制。

学习SpringAI这一篇就够了

技术实现流程

1. 批处理式数据预处理(ETL管道)
  • 数据提取(Extract):从非结构化文档(PDF/HTML/Markdown等)读取原始内容
  • 数据转换(Transform):关键步骤包括:
    • 语义分块:保持内容逻辑完整性
      • 避免在段落/表格中间拆分
      • 代码文件需确保方法完整性(不截断函数实现)
    • 尺寸优化:每个分块大小需控制在模型令牌限制的20%-30%(如GPT-4的32K上下文窗口对应6K-10K令牌/块)
  • 数据加载(Load):将处理后的数据存入向量数据库(如Pinecone/Weaviate)
2. 用户查询实时处理

语义检索

# 伪代码示例:向量相似度搜索 query_embedding = embed(\"Spring AI的事务管理机制\") similar_chunks = vector_db.search(query_embedding, top_k=3)

提示词构建:将用户问题与检索到的相似文档片段组合:

请基于以下上下文回答问题: [检索到的文档片段1...] [检索到的文档片段2...] 问题:如何配置Spring AI的事务管理?
  1. 模型推理:增强后的提示词发送至AI模型生成最终响应

技术优势

维度 传统模型 RAG方案 知识时效性 训练截止日期固定 可实时更新知识库 领域适应性 需微调模型 仅需更新文档内容 成本效益 每次训练消耗大量资源 仅需向量数据库存储费用

四、SpringAI核心组件

ChatClient

一、ChatClient 概述

  • 核心功能:提供与 AI 模型通信的流式 API,支持同步和流式编程模型。
  • 输入构建:通过流式 API 构建包含用户消息和系统消息的提示(Prompt),消息可包含运行时替换的占位符。
  • 输出处理:支持返回文本内容、结构化实体、带元数据的响应(如 token 使用量),以及流式响应。

二、创建 ChatClient

  1. 自动配置方式
    • Spring Boot 自动配置会创建 ChatClient.Builder bean,可直接注入并构建实例:
@RestControllerclass MyController { private final ChatClient chatClient; public MyController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder.build(); } @GetMapping(\"/ai\") String generation(String userInput) { return this.chatClient.prompt().user(userInput).call().content(); }}
  1. 手动创建方式
  • 禁用自动配置后(spring.ai.chat.client.enabled=false),可手动创建多个实例:
// 同一模型类型,不同配置ChatModel model = ...; // 自动配置的模型ChatClient client1 = ChatClient.create(model);ChatClient client2 = ChatClient.builder(model) .defaultSystemPrompt(\"You are a helper.\") .build();// 不同模型类型@Configurationclass ChatConfig { @Bean ChatClient openAiClient(OpenAiChatModel model) { return ChatClient.create(model); } @Bean ChatClient anthropicClient(AnthropicChatModel model) { return ChatClient.create(model); }}

三、流式 API 核心用法

  1. 构建提示的三种方式
    • prompt():空参,手动构建用户、系统消息。
    • prompt(Prompt prompt):传入已构建的 Prompt 实例。
    • prompt(String content):快速设置用户消息内容。
  2. 同步调用(call)返回值
    • content():返回字符串内容。
    • chatResponse():返回包含元数据(如 token 数)的 ChatResponse
    • entity(Class type):将响应映射为实体类(如 record ActorFilms(String actor, List movies))。
  3. 流式调用(stream)返回值
    • content():返回 Flux 流式文本。
    • chatResponse():返回 Flux 流式响应(含元数据)。

四、提示模板与动态参数

  • 模板语法:默认使用 {} 包裹变量,基于 StTemplateRenderer 引擎,可自定义分隔符:
String response = ChatClient.create(model).prompt() .user(u -> u.text(\"Tell me 5 movies by {director}\") .param(\"director\", \"Christopher Nolan\")) .call().content();
  • 自定义模板引擎:实现 TemplateRenderer 接口,或配置现有引擎(如修改分隔符为 )。

五、默认配置与动态覆盖

  1. 默认系统消息
    • 在配置类中设置全局默认系统消息,避免每次调用重复设置:
@Configurationclass Config { @Bean ChatClient chatClient(ChatClient.Builder builder) { return builder.defaultSystem(\"You speak like a pirate.\") .build(); }}
  1. 带参数的动态默认值
    • 系统消息中使用占位符,运行时通过 system(sp -> sp.param(\"key\", value)) 动态赋值:
// 配置类中设置带参数的默认系统消息builder.defaultSystem(\"You speak as {character}.\");// 运行时覆盖参数chatClient.prompt().system(sp -> sp.param(\"character\", \"Shakespeare\")) .user(\"Tell a story\").call().content();
  1. 其他默认配置
    • defaultOptions(ChatOptions):设置模型默认参数(如温度、模型类型)。
    • defaultFunctions(Function...):注册默认工具调用函数。
    • defaultAdvisors(Advisor...):添加默认顾问(如记忆、检索增强)。

六、Advisors配置

  1. 核心作用:拦截、修改提示或上下文,支持检索增强生成(RAG)、对话记忆等。
  2. 常用顾问
    • MessageChatMemoryAdvisor:维护对话历史,超过最大窗口(默认 20 条)时淘汰旧消息。
    • QuestionAnswerAdvisor:结合向量存储检索上下文,增强回答准确性。
    • SimpleLoggerAdvisor:日志记录请求和响应,用于调试(需设置日志级别为 DEBUG)。
  3. 配置示例:按顺序执行多个顾问,先添加对话历史,再检索相关文档:
chatClient.prompt() .advisors( MessageChatMemoryAdvisor.builder(chatMemory).build(), QuestionAnswerAdvisor.builder(vectorStore).build() ) .user(\"What is RAG?\") .call().content();

Advisor

一、Advisors 核心概念与作用

  • 定义:Advisors 是 Spring AI 中用于拦截、修改和增强 AI 交互的组件,可封装通用的生成式 AI 模式,实现数据转换和跨模型复用。
  • 核心价值
    • 封装对话历史管理、检索增强(RAG)等重复模式。
    • 支持请求和响应的预处理与后处理,提升 LLM 交互灵活性。
    • 集成可观测性,记录执行指标和追踪信息。
  • 使用场景
    • 对话记忆管理(维护历史消息)。
    • 检索增强生成(结合向量存储补充上下文)。
    • 内容安全过滤(防止有害输出)。
    • 日志记录与调试。

二、核心组件与接口

  1. 基础接口
    • Advisor:所有顾问的基接口,继承 Ordered,需实现 getName()getOrder()
    • CallAroundAdvisor:同步顾问接口,处理非流式请求,核心方法 aroundCall(AdvisedRequest, CallAroundAdvisorChain)
    • StreamAroundAdvisor:流式顾问接口,处理响应式请求,核心方法 aroundStream(AdvisedRequest, StreamAroundAdvisorChain)
  2. 请求与响应载体
    • AdvisedRequest:包含可修改的 Prompt 数据(用户文本、参数)和共享上下文 adviseContext
    • AdvisedResponse:包含 LLM 响应 ChatResponse 和上下文,用于顾问链间数据传递。
  3. 顾问链
    • CallAroundAdvisorChain:同步顾问链,通过 nextAroundCall() 按顺序调用下一个顾问。
    • StreamAroundAdvisorChain:流式顾问链,通过 nextAroundStream() 处理响应式流。

三、执行流程与顺序控制

  1. 执行流程
    • 框架将用户 Prompt 转换为 AdvisedRequest,并初始化空上下文。
    • 顾问链按顺序处理请求,可修改 Prompt 或阻塞请求(不调用下一个顾问)。
    • 最后一个顾问将请求发送给 LLM,响应沿顾问链反向处理,最终转换为 AdvisedResponse
  2. 顺序控制
    • 通过 getOrder() 确定执行顺序:值越小优先级越高(Ordered.HIGHEST_PRECEDENCE 为最小)。
    • 同步场景下,顾问链类似栈结构:先执行的顾问后处理响应,后执行的顾问先处理响应。
    • 示例:设置 getOrder() = 0 使顾问优先执行,getOrder() = Integer.MAX_VALUE 最后执行。

四、自定义顾问实现

  1. 同步 / 流式顾问示例
public class SimpleLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor { @Override public String getName() { return \"SimpleLoggerAdvisor\"; } @Override public int getOrder() { return 0; } // 优先执行 @Override public AdvisedResponse aroundCall(AdvisedRequest req, CallAroundAdvisorChain chain) { logger.debug(\"请求前: {}\", req); AdvisedResponse res = chain.nextAroundCall(req); logger.debug(\"响应后: {}\", res); return res; } @Override public Flux<AdvisedResponse> aroundStream(AdvisedRequest req, StreamAroundAdvisorChain chain) { logger.debug(\"流式请求前: {}\", req); Flux<AdvisedResponse> flux = chain.nextAroundStream(req); return flux.doOnNext(res -> logger.debug(\"流式响应后: {}\", res)); }}
  1. 核心方法说明
    • aroundCall/aroundStream:拦截请求,调用 chain.nextAroundCall/Stream() 继续链执行,可修改 AdvisedRequest 或直接返回响应。
    • updateContext:通过 advisedRequest.updateContext(map -> {...}) 修改共享上下文(生成新不可变 map)。

五、内置顾问与常用场景

  1. 对话记忆顾问(Chat Memory Advisors)
    • MessageChatMemoryAdvisor:从记忆存储中获取历史消息,以消息集合形式添加到 Prompt。
    • PromptChatMemoryAdvisor:将历史消息合并到系统消息中。
    • VectorStoreChatMemoryAdvisor:从向量存储检索相关记忆,添加到系统消息。
  2. 检索增强顾问(RAG)
    • QuestionAnswerAdvisor:结合向量存储,检索相关文档并追加到 Prompt,实现检索增强生成。
  3. 内容安全顾问
    • SafeGuardAdvisor:过滤有害内容,防止模型生成不当响应。
  4. 日志顾问
    • SimpleLoggerAdvisor:记录请求和响应数据,用于调试(需设置日志级别为 DEBUG)。

六、配置与最佳实践

  1. 注册方式
    • ChatClient.Builder 中通过 defaultAdvisors() 注册全局顾问:
ChatClient client = ChatClient.builder(model) .defaultAdvisors( new MessageChatMemoryAdvisor(chatMemory), new QuestionAnswerAdvisor(vectorStore) ) .build();
- 运行时通过 `advisors(Advisor...)` 动态覆盖:
client.prompt() .advisors(new SimpleLoggerAdvisor()) .user(\"问题\") .call().content();
  1. 最佳实践
    • 单一职责:每个顾问专注于一个功能(如仅记录日志或仅处理记忆)。
    • 上下文共享:通过 adviseContext 在顾问间传递状态(如对话 ID、检索结果)。
    • 兼容两种模式:同时实现 CallAroundAdvisorStreamAroundAdvisor 以支持同步 / 流式场景。
    • 顺序测试:通过 getOrder() 严格控制执行顺序,避免逻辑冲突。

Prompt

一、Prompts 核心概念与作用

  • 定义:Prompt 是引导 AI 模型生成特定输出的输入,其设计和措辞直接影响模型响应。类比 Spring MVC 中的 “View” 或带占位符的 SQL 语句,支持动态内容替换。
  • 核心组件
    • Prompt:封装多个 MessageChatOptions,作为与 AI 模型交互的基本输入单元。
    • Message:包含文本内容、元数据和角色(如用户、系统、助手),构成 Prompt 的基本元素。
    • PromptTemplate:模板引擎,支持动态生成 Prompt,替换占位符内容。
  • 演进历程:从简单字符串发展为结构化消息集合,OpenAI 引入按角色分类的消息(如 USER、SYSTEM),提升交互精度。

二、Prompt 核心结构与接口

  1. Prompt 类
public class Prompt implements ModelRequest<List<Message>> { private final List<Message> messages; private ChatOptions chatOptions;}
  • messages:消息列表,每个消息有明确角色(如用户、系统)。
  • chatOptions:模型请求参数(如温度、最大 token 数)。
  1. Message 接口与实现
public interface Message extends Content { MessageType getMessageType();}public enum MessageType { USER, ASSISTANT, SYSTEM, TOOL }
  • 主要实现类
    • UserMessage:用户输入消息(getMessageType() = USER)。
    • SystemMessage:系统指令消息(getMessageType() = SYSTEM)。
    • AssistantMessage:助手响应消息(getMessageType() = ASSISTANT,可包含工具调用)。
    • ToolResponseMessage:工具返回结果(getMessageType() = TOOL)。
  • 多模态支持MediaContent 接口支持附加媒体内容(如图像、音频)。
  1. 消息角色与作用
    • System:设定 AI 行为和响应风格(如 “你是一个乐于助人的助手”)。
    • User:用户问题或指令(如 “告诉我三个著名海盗”)。
    • Assistant:AI 历史响应,维持对话上下文。
    • Tool:工具调用结果或函数返回值(如计算结果、数据查询)。

三、Prompt 构建示例

  1. 基础构建:手动创建消息并组装为 Prompt
// 创建用户消息Message userMsg = new UserMessage(\"Tell me about famous pirates\");// 创建系统消息(带模板变量)SystemPromptTemplate sysTemplate = new SystemPromptTemplate( \"You are a helper named {name}, respond in {voice} style\");Message sysMsg = sysTemplate.createMessage(Map.of(\"name\", \"PirateBot\", \"voice\", \"pirate\"));// 组装 PromptPrompt prompt = new Prompt(List.of(sysMsg, userMsg));// 调用模型ChatResponse response = chatModel.call(prompt);
  1. 模板引擎构建:通过 PromptTemplate 动态生成
// 定义模板PromptTemplate template = new PromptTemplate( \"Generate a {adjective} joke about {topic}\");// 渲染为 PromptPrompt prompt = template.create(Map.of(\"adjective\", \"funny\", \"topic\", \"cats\"));// 调用模型String result = chatModel.call(prompt).getResult();
  1. 资源文件加载:从类路径加载模板文件
@Value(\"classpath:/prompts/system-template.st\")private Resource systemResource;SystemPromptTemplate template = new SystemPromptTemplate(systemResource);Message sysMsg = template.createMessage(Map.of(\"key\", \"value\"));

四、多模态与高级特性

  1. 多模态支持:通过 MediaContent 接口添加媒体内容(如图像 URL、音频文件):
// 创建带媒体的消息Media image = Media.builder() .name(\"logo\") .mimeType(MimeType.IMAGE_PNG) .data(ByteArrayResource) // 或 URL .build();Message mediaMsg = new UserMessage(\"Describe this image\", List.of(image));
  1. 工具调用集成:在 AssistantMessage 中包含工具调用指令:
ToolCall toolCall = ToolCall.builder() .id(\"calc-1\") .name(\"calculate\") .arguments(\"{\\\"formula\\\": \\\"2+2\\\"}\") .build();Message toolMsg = new AssistantMessage(null, List.of(toolCall));

五、与其他组件的集成

  1. 与 ChatClient 结合:通过 ChatClient 的流式 API 构建 Prompt:
String response = chatClient.prompt() .system(\"You are a translator\") .user(\"Translate \'hello\' to French\") .call().content();
  1. 与 Advisors 结合:通过顾问动态修改 Prompt(如添加对话历史):
ChatClient client = ChatClient.builder(model) .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)) .build();// 顾问会自动将历史消息添加到 Prompt 中String response = client.prompt().user(\"What did we talk about earlier?\").call().content();

ChatMemory

一、ChatMemory 核心概念与作用

  • 背景:LLM(大语言模型)无状态,无法保留历史交互信息,ChatMemory 用于存储和检索跨交互的上下文,维持对话连续性。
  • 核心区别
    • Chat Memory:模型用于维持对话上下文的相关信息(非完整历史)。
    • Chat History:用户与模型交互的完整消息记录(需用其他方式存储,如 Spring Data)。
  • 抽象设计
    • ChatMemory:管理对话上下文的核心接口,决定保留哪些消息。
    • ChatMemoryRepository:负责消息的底层存储(如内存、数据库)。

二、快速开始与默认配置

  • 自动配置:Spring AI 自动配置 ChatMemory bean,默认使用:
    • 存储InMemoryChatMemoryRepository(内存存储)。
    • 实现MessageWindowChatMemory(窗口大小 20 条消息)。
  • 直接使用
@AutowiredChatMemory chatMemory;
  • 手动创建示例
// 创建窗口大小为 10 的内存存储对话记忆ChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(10) .build();

三、记忆类型与实现

  • MessageWindowChatMemory(核心实现):
    • 特点:维护固定大小的消息窗口,超出时移除旧消息,但保留系统消息。
    • 配置
// 设置最大消息数为 10MessageWindowChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(10) .build();

四、存储实现与配置

  1. InMemoryChatMemoryRepository(默认):
    • 存储方式:使用 ConcurrentHashMap 在内存中存储消息。
    • 手动创建
ChatMemoryRepository repository = new InMemoryChatMemoryRepository();
  1. JdbcChatMemoryRepository(关系型数据库):
    • 依赖
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId></dependency>
  • 支持数据库:PostgreSQL、MySQL/MariaDB、SQL Server、HSQLDB。
  • 配置示例
@AutowiredJdbcChatMemoryRepository repository;ChatMemory memory = MessageWindowChatMemory.builder() .chatMemoryRepository(repository) .maxMessages(10) .build();
  • Schema 初始化:通过 spring.ai.chat.memory.repository.jdbc.initialize-schema 控制(默认仅嵌入式数据库初始化)。
  1. CassandraChatMemoryRepository(分布式存储):
    • 依赖
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-chat-memory-repository-cassandra</artifactId></dependency>
  • 特点:支持时间序列模式、TTL(生存时间),适合大规模持久化存储。
  1. Neo4jChatMemoryRepository(图数据库):
    • 依赖
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-chat-memory-repository-neo4j</artifactId></dependency>
  • 特点:将消息存储为图节点和关系,利用 Neo4j 的图查询能力。

五、与 ChatClient 集成(通过 Advisors)

核心 Advisors

  1. MessageChatMemoryAdvisor
    * 行为:从记忆中获取历史消息,以消息集合形式添加到 Prompt。
    * 配置
ChatMemory memory = MessageWindowChatMemory.builder().build();ChatClient client = ChatClient.builder(model) .defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build()) .build();
  1. PromptChatMemoryAdvisor
    • 行为:将历史消息作为纯文本追加到系统提示中。
    • 自定义模板
PromptTemplate template = PromptTemplate.builder() .template(\"Instructions: {instructions}\\nMemory: {memory}\") .build();PromptChatMemoryAdvisor advisor = PromptChatMemoryAdvisor.builder(memory) .promptTemplate(template) .build();
  1. VectorStoreChatMemoryAdvisor
    • 行为:从向量存储中检索历史消息,追加到系统提示。
    • 自定义模板:需包含 {instructions}{long_term_memory} 占位符。
  • 运行时指定对话 ID
String conversationId = \"007\";String response = chatClient.prompt() .user(\"Do I have license to code?\") .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId)) .call().content();

六、与 ChatModel 直接集成

  • 手动管理记忆流程
// 1. 创建记忆实例ChatMemory memory = MessageWindowChatMemory.builder().build();String conversationId = \"007\";// 2. 第一次交互UserMessage msg1 = new UserMessage(\"My name is James Bond\");memory.add(conversationId, msg1);ChatResponse res1 = chatModel.call(new Prompt(memory.get(conversationId)));memory.add(conversationId, res1.getResult().getOutput());// 3. 第二次交互UserMessage msg2 = new UserMessage(\"What is my name?\");memory.add(conversationId, msg2);ChatResponse res2 = chatModel.call(new Prompt(memory.get(conversationId)));// res2 应包含 \"James Bond\"

七、配置属性与最佳实践

  • Jdbc 配置属性
    • spring.ai.chat.memory.repository.jdbc.initialize-schema:控制 Schema 初始化(embedded/always/never)。
    • spring.ai.chat.memory.repository.jdbc.schema:自定义 Schema 脚本路径。
  • Cassandra 配置属性
    • spring.ai.chat.memory.cassandra.time-to-live:消息生存时间(TTL)。
  • 最佳实践
    • 内存存储:适合测试或小型应用,无需持久化。
    • JDBC/Neo4j:适合需要持久化和复杂查询的场景。
    • Cassandra:适合大规模、分布式部署,需高可用性和可扩展性。
    • 窗口大小:根据模型上下文窗口调整 maxMessages(如 GPT-3 通常 4K tokens,约 20-30 条短消息)。

Tool Calling

一、Tool Calling 核心概念与作用

  • 定义:允许 AI 模型调用外部工具(如 API、数据库查询),扩展模型能力,实现信息检索和操作执行。
  • 两大应用场景
    • 信息检索:获取实时数据(如天气、新闻),支持 RAG 场景。
    • 操作执行:自动化任务(如发送邮件、创建数据库记录)。
  • 安全机制:模型仅能请求工具调用,实际执行由应用负责,模型无法直接访问 API。

二、快速开始:工具定义与使用

  1. 信息检索工具(获取当前时间)
class DateTimeTools { @Tool(description = \"获取用户时区的当前日期和时间\") String getCurrentDateTime() { return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString(); }}// 使用 ChatClient 调用String response = ChatClient.create(chatModel) .prompt(\"明天是星期几?\") .tools(new DateTimeTools()) .call().content();// 输出:\"Tomorrow is 2025-06-27.\"
  1. 操作执行工具(设置闹钟)
class DateTimeTools { @Tool(description = \"设置指定时间的闹钟,时间格式为 ISO-8601\") void setAlarm(@ToolParam(description = \"ISO-8601 格式时间\") String time) { LocalDateTime alarmTime = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME); System.out.println(\"闹钟设置为: \" + alarmTime); }}// 使用 ChatClient 调用String response = ChatClient.create(chatModel) .prompt(\"10分钟后设置一个闹钟\") .tools(new DateTimeTools()) .call().content();// 控制台输出闹钟时间

三、工具定义方式

(一)基于方法的工具(Method as Tools)
  1. 声明式定义(@Tool 注解)
    • 注解参数
      • name:工具名称(默认方法名)。
      • description:工具描述(关键,影响模型调用决策)。
      • returnDirect:是否直接返回结果给客户端(默认 false,返回给模型)。
    • 参数注解
      • @ToolParam(description = \"参数说明\", required = false):设置参数描述和必填性。
class Tools { @Tool(description = \"计算两数之和\") int add(@ToolParam(\"第一个加数\") int a, @ToolParam(\"第二个加数\") int b) { return a + b; }}
  1. 编程式定义(MethodToolCallback)
Method method = ReflectionUtils.findMethod(Tools.class, \"add\", int.class, int.class);ToolCallback toolCallback = MethodToolCallback.builder() .toolDefinition(ToolDefinition.builder(method) .description(\"计算两数之和\") .build()) .toolMethod(method) .toolObject(new Tools()) .build();
(二)基于函数的工具(Functions as Tools)
  1. 编程式定义(FunctionToolCallback)
// 函数接口interface WeatherService extends Function<WeatherRequest, WeatherResponse> { @Override WeatherResponse apply(WeatherRequest request);}record WeatherRequest(String location, Unit unit) {}record WeatherResponse(double temp, Unit unit) {}// 创建工具ToolCallback toolCallback = FunctionToolCallback.builder( \"currentWeather\", new WeatherService() { @Override public WeatherResponse apply(WeatherRequest request) { return new WeatherResponse(25.5, request.unit()); } }) .description(\"获取指定地点的天气\") .inputType(WeatherRequest.class) .build();
  1. 动态定义(@Bean 注解)
@Configurationclass ToolConfig { public static final String WEATHER_TOOL = \"currentWeather\"; @Bean(WEATHER_TOOL) @Description(\"获取指定地点的天气\") Function<WeatherRequest, WeatherResponse> currentWeather() { return request -> new WeatherResponse(30.0, request.unit()); }}// 使用工具名称调用ChatClient.create(chatModel) .prompt(\"哥本哈根天气如何?\") .tools(WeatherTools.WEATHER_TOOL) .call().content();

四、工具核心组件与接口

  1. ToolCallback 接口:工具的核心接口,定义执行逻辑。
public interface ToolCallback { ToolDefinition getToolDefinition(); // 工具定义(名称、描述、输入 schema) ToolMetadata getToolMetadata(); // 工具元数据(如是否直接返回结果) String call(String toolInput); // 执行工具}
  1. ToolDefinition 接口:工具元数据,供模型理解调用方式。
public interface ToolDefinition { String name(); // 工具名称 String description(); // 工具描述 String inputSchema(); // 输入参数的 JSON Schema}
  1. ToolCallingManager:工具执行管理器,处理工具调用流程。
// 自定义工具执行管理器@BeanToolCallingManager toolCallingManager() { return ToolCallingManager.builder() .exceptionProcessor(exception -> \"工具调用失败: \" + exception.getMessage()) .build();}

五、工具执行流程

  1. 框架控制执行(默认)
    1. 模型返回工具调用请求(含工具名和参数)。
    2. ChatModel 调用 ToolCallingManager 执行工具。
    3. 工具结果返回给模型,模型生成最终响应。
  2. 用户控制执行:手动处理工具调用循环。
ChatOptions options = ToolCallingChatOptions.builder() .toolCallbacks(tools) .internalToolExecutionEnabled(false) // 禁用自动执行 .build();ChatResponse response = chatModel.call(new Prompt(\"6*8是多少?\", options));ToolCallingManager manager = ToolCallingManager.builder().build();while (response.hasToolCalls()) { ToolExecutionResult result = manager.executeToolCalls(prompt, response); prompt = new Prompt(result.conversationHistory(), options); response = chatModel.call(prompt);}

六、工具结果处理

  1. 直接返回结果(returnDirect = true)
@Tool(description = \"获取用户信息\", returnDirect = true)UserInfo getUser(@ToolParam(\"用户ID\") Long id) { return userRepository.findById(id);}// 结果直接返回给客户端,不经过模型
  1. 自定义结果转换
// 自定义转换器class CustomConverter implements ToolCallResultConverter { @Override public String convert(Object result, Type returnType) { if (result instanceof UserInfo) { return \"用户: \" + ((UserInfo) result).getName(); } return String.valueOf(result); }}// 使用自定义转换器@Tool(description = \"获取用户信息\", resultConverter = CustomConverter.class)UserInfo getUser(Long id) { ... }

七、工具上下文与异常处理

  1. 工具上下文(ToolContext):传递额外参数(如租户 ID)。
ChatClient.create(chatModel) .prompt(\"查询客户42的信息\") .tools(new CustomerTools()) .toolContext(Map.of(\"tenantId\", \"acme\")) // 传递租户ID .call().content(); // 工具中使用上下文@Tool(description = \"查询客户信息\")Customer getCustomer(Long id, ToolContext context) { String tenantId = context.get(\"tenantId\"); return customerRepo.findByTenantAndId(tenantId, id);}
  1. 异常处理:自定义工具执行异常处理器。
@BeanToolExecutionExceptionProcessor exceptionProcessor() { return e -> { if (e.getCause() instanceof SQLException) { return \"数据库错误: \" + e.getMessage(); } return \"工具调用失败: \" + e.getMessage(); };}

八、支持的模型与最佳实践

  1. 支持模型:OpenAI、Anthropic Claude 3、Azure OpenAI、Mistral AI、Ollama 等。
  2. 最佳实践
    • 描述清晰:工具描述需明确用途和参数要求,避免模型误用。
    • 参数必填性:合理设置 @ToolParam(required = false),防止模型虚构参数。
    • 安全考虑:工具不应暴露敏感操作,结果直接返回时需验证权限。
    • 性能优化:批量处理工具调用,减少模型交互次数。

九、工具与其他组件集成

  1. 与对话记忆(ChatMemory)集成
ChatMemory memory = MessageWindowChatMemory.builder().build();ChatClient client = ChatClient.builder(chatModel) .defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build()) .defaultTools(new DateTimeTools()) .build(); // 对话中自动包含历史工具调用记录String response = client.prompt(\"之前设置的闹钟时间是?\").call().content();
  1. 与检索增强(RAG)集成:工具可调用向量存储检索上下文。
@Tool(description = \"检索相关文档\")List<Document> searchDocs(@ToolParam(\"查询关键词\") String query) { return vectorStore.search(query, 5);}

RAG

一、RAG 核心概念与作用

  • 定义:RAG 是一种结合检索与生成的技术,解决大语言模型(LLM)在长文本处理、事实准确性和上下文感知方面的局限。
  • 核心逻辑:通过检索外部知识库(如向量数据库)获取相关文档,将其作为上下文附加到用户查询中,辅助 LLM 生成更准确、有依据的回答。
  • Spring AI 支持:提供模块化架构和开箱即用的 Advisor,允许自定义 RAG 流程或使用现成实现。

二、核心 Advisor 实现

(一)QuestionAnswerAdvisor
  • 功能:基于向量存储检索相关文档,并将结果附加到用户查询中,形成上下文。
  • 使用方式
// 基础用法ChatResponse response = ChatClient.builder(chatModel) .build().prompt() .advisors(new QuestionAnswerAdvisor(vectorStore)) .user(userText) .call() .chatResponse();// 配置检索参数(阈值、返回数量)var qaAdvisor = new QuestionAnswerAdvisor(vectorStore, SearchRequest.builder() .similarityThreshold(0.8d) // 相似度阈值 .topK(6) // 返回前6条结果 .build());// 动态过滤(运行时设置过滤条件)String content = chatClient.prompt() .user(\"请回答问题\") .advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, \"type == \'Spring\'\")) .call().content();
  • 过滤表达式:使用类似 SQL 的过滤语法,支持跨向量存储的便携式过滤(如 type == \'Spring\')。
(二)RetrievalAugmentationAdvisor
  • 模块化 RAG 实现:基于模块化架构,支持构建复杂 RAG 流程。
  • 基础用法(Naive RAG)
// 基础配置Advisor advisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(VectorStoreDocumentRetriever.builder() .similarityThreshold(0.50) .vectorStore(vectorStore) .build()) .build();// 允许空上下文(无相关文档时仍生成回答)Advisor advisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(...) .queryAugmenter(ContextualQueryAugmenter.builder() .allowEmptyContext(true) .build()) .build();
  • 高级用法(带查询转换)
Advisor advisor = RetrievalAugmentationAdvisor.builder() .queryTransformers(RewriteQueryTransformer.builder() .chatClientBuilder(chatClientBuilder.build().mutate()) .build()) .documentRetriever(...) .build();

三、RAG 模块化架构

Spring AI 将 RAG 拆分为四个阶段模块,每个模块可独立定制:

(一)Pre-Retrieval(检索前处理)
  • 查询转换(Query Transformation):优化用户查询,提升检索效果。
    • CompressionQueryTransformer:压缩对话历史和查询为独立查询(适用于长对话场景)。
Query query = Query.builder() .text(\"第二大城市是?\") .history(new UserMessage(\"丹麦首都\"), new AssistantMessage(\"哥本哈根\")) .build();QueryTransformer transformer = CompressionQueryTransformer.builder() .chatClientBuilder(chatClientBuilder) .build();Query transformed = transformer.transform(query);
- **RewriteQueryTransformer**:重写查询以提高检索相关性(适用于模糊或冗长查询)。- **TranslationQueryTransformer**:翻译查询至嵌入模型支持的语言。
  • 查询扩展(Query Expansion):生成多个语义变体查询,增加命中概率。
MultiQueryExpander expander = MultiQueryExpander.builder() .chatClientBuilder(chatClientBuilder) .numberOfQueries(3) // 生成3个变体 .includeOriginal(false) // 不包含原始查询 .build();List<Query> expanded = expander.expand(new Query(\"如何运行Spring Boot应用?\"));
(二)Retrieval(检索)
  • 文档检索(Document Search):从向量存储获取相关文档。
DocumentRetriever retriever = VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) .similarityThreshold(0.73) .topK(5) .filterExpression(new FilterExpressionBuilder() .eq(\"genre\", \"fairytale\") .build()) .build();List<Document> docs = retriever.retrieve(new Query(\"故事主角是谁?\"));
- **动态过滤**:支持通过 `Supplier` 或查询上下文动态设置过滤条件。
  • 文档合并(Document Join):合并多源检索结果,去重排序。
DocumentJoiner joiner = new ConcatenationDocumentJoiner();List<Document> merged = joiner.join(documentsForQuery);
(三)Post-Retrieval(检索后处理)
  • 文档排序(Document Ranking):按相关性重排文档顺序(不删除文档)。
  • 文档筛选(Document Selection):移除不相关或冗余文档(解决上下文长度限制)。
  • 文档压缩(Document Compression):压缩文档内容,减少噪声(不改变文档列表顺序)。
(四)Generation(生成)
  • 查询增强(Query Augmentation):将检索到的文档内容附加到查询中,形成完整上下文。****
QueryAugmenter augmenter = ContextualQueryAugmenter.builder() .allowEmptyContext(true) // 允许空上下文时生成回答 .build();
  • 提示模板定制:通过 promptTemplate()emptyContextPromptTemplate() 自定义生成阶段的提示格式。

四、关键配置与最佳实践

  1. 查询转换温度设置:配置 ChatClient.Builder 为低温(如 0.0),确保查询转换结果更确定(默认温度过高可能影响检索效果)。
  2. 空上下文处理:通过 allowEmptyContext(true) 允许无相关文档时仍生成回答,避免模型拒答。
  3. 过滤表达式优先级:查询级过滤表达式(Query.context)优先级高于检索器级过滤。
  4. 多阶段组合:结合查询转换、扩展、筛选等模块,构建复杂 RAG 流程(如翻译→扩展→检索→压缩→生成)。

五、依赖与集成

  • 必备依赖:添加 spring-ai-advisors-vector-store 依赖以使用 RAG Advisors。
  • 向量存储集成:支持主流向量存储(如 Pinecone、Weaviate、Elasticsearch 等),通过 VectorStore 接口对接。

六、典型应用场景

  • 企业知识库问答:基于内部文档库,快速响应员工问题。
  • 客服系统:结合产品文档,生成准确的客户支持回答。
  • 学术研究辅助:检索相关文献,辅助论文写作。
  • 代码问答:基于代码库文档,回答开发问题。