Spring系列之Spring AI入门

发布于:2025-08-10 ⋅ 阅读:(13) ⋅ 点赞:(0)

概述

GitHub官网,目前最新版是1.0.1。

功能:

  • 跨AI提供商的可移植API:用于聊天、文本到图像和嵌入模型。
  • 支持同步和流API选项。还支持下拉访问模型特定功能。
  • 跨Vector Store提供商的可移植API,包括同样可移植的新颖的类似SQL的元数据过滤器API。支持8个矢量数据库
  • 函数调用。Spring AI使AI模型可以轻松调用java.util.FunctionPOJO对象
  • AI模型和向量存储的Spring Boot自动配置和启动器
  • 数据工程的ETL框架。这为将数据加载到矢量数据库提供了基础,有助于实现检索增强生成模式。

如需使用SNAPSHOT版本,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>
		<id>central-portal-snapshots</id>
		<name>Central Portal Snapshots</name>
		<url>https://central.sonatype.com/repository/maven-snapshots/</url>
		<releases><enabled>false</enabled></releases>
		<snapshots><enabled>true</enabled></snapshots>
	</repository>
</repositories>

Spring Initializr:https://start.spring.io/

application.yml配置文件:

spring:
  ai:
    chat:
      memory:
        repository:
          jdbc:
            initialize-schema: nerver
    openai:
      api-key: 
      embedding:
        options:
          model: text-embedding-v4
      base-url: https://dashscope.aliyuncs.com/compatible-mode/
      chat:
        options:
          model: qwen-max
    vectorstore:
      pgvector:
        enabled: true
        indexType: HNSW
      redis:
        initialize-schema: true
        index-name: custom-index
        prefix: custom-prefix
    zhipuai:
      api-key: ${ZHIPUAI_API_KEY}
    mcp:
      server:
        name: webflux-mcp-server
        version: 1.0.0
        type: ASYNC 
        sse-message-endpoint: /mcp/messages
      client:
        request-timeout: 30s
        sse:
          connections:
            server1:
              url: https://mcp.amap.com
              sse-endpoint: /sse?key=?
            server2:
              url: https://mcp-pan/baidu.com
              sse-endpoint: /sse?access_token=?
            server3:
              url: https://mcp-youxuan.baidu.com
              sse-endpoint: /mcp/sse?key=?
        toolcallback:
          enabled: true
        stdio:
          servers-configuration: classpath:/mcp-servers-config.json
amap:
 key: ${AMAP_API_KEY}

代码片段

PromptTemplate template = new PromptTemplate("请用{style}风格解释:{topic}");
Prompt prompt = template.create(Map.of("style", "幽默", "topic", "量子力学"));

@Bean
VectorStore vectorStore(EmbeddingClient embeddingClient) {
	return new SimpleVectorStore(embeddingClient);
}

@Resource
private SyncMcpToolCallbackProvider toolCallbackProvider;
	var chatClient = chatClientBuilder
		.defaultTools(toolCallbackProvider)
		.build();

// 实现Tool       
@Service
public class WeatherService {
	@Tool(description = "Get weather information by city name")
	public String getWeather(String cityName) {
	}
}
// 注册Tool
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
        return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
    }

Chat Client,用于简化与AI模型的交互过程,支持同步和反应式编程模型,隐藏诸多底层细节:

  • 提示词管理:定制和组装模型的输入(Prompt)
  • 响应处理:格式化解析模型的输出(Structured Output)
  • 参数选项:调整模型交互参数(ChatOptions)
  • 高级功能:整合聊天记忆、函数调用、RAG等能力

Spring AI提供两种方式创建ChatClient:使用自动配置的Builder或编程方式。

@RestController
public class ChatController {
    private final ChatClient chatClient;

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

    @GetMapping("/chat")
    public String chat(String input) {
        return this.chatClient.prompt()
            .user(input)
            .call()
            .content();
    }
}

禁用自动配置:spring.ai.chat.client.enabled=false

// 通常通过自动装配获取ChatModel实例
ChatModel myChatModel =
// 使用Builder
ChatClient chatClient = ChatClient.builder(myChatModel).build();
// 直接create
ChatClient chatClient = ChatClient.create(myChatModel);

ChatClient的流畅API通过prompt方法提供三种不同的方式来创建Prompt:

  1. prompt():无参方法,允许从头开始构建提示,后续可添加用户消息、系统消息等。chatClient.prompt().user("你好").call().content();
  2. prompt(Prompt prompt):接受Prompt对象参数,允许传入使用非流畅API创建的Prompt实例。
Prompt myPrompt = new Prompt(List.of(new UserMessage("你好")));
chatClient.prompt(myPrompt).call().content();
  1. prompt(String content):便捷方法,直接接受用户文本内容作为参数。
    chatClient.prompt("你好").call().content();

ChatResponse包含完整的响应数据和元数据,如Token使用情况。
entity()方法还提供一个重载版本,允许传入自定义参数来指导实体转换过程:

record Product(String name, String description, Double price) {}

Product product = chatClient.prompt()
	.user("创建一个价格在100元以内的产品")
	.call()
	.entity(Product.class, EntityPreference.create()
		.withFormat(EntityFormat.JSON)
		.build());

ChatClient提供两个核心方法来获取响应:

  • call:用于同步响应,返回ResponseWithChatClient对象;
  • stream():用于流式响应,返回StreamWithChatClient`对象。
Flux<String> responseStream = chatClient.prompt()
	.user("给我讲一个长故事")
	.stream()
	.content();

默认值:

ChatClient chatClient = ChatClient.builder(chatModel)
	.defaultSystem("你是一位专业的Java开发助手,擅长使用Spring框架")
	.defaultUser("默认用户消息")
	.defaultOptions(options -> options.withTemperature(0.7f))
	.defaultResponseFormat(new StructuredResponseFormat<>(MyResponseType.class))
	.build();

ToolCallback

之前叫FunctionCallback,升级:

  1. 术语更准确:从"函数"改为"工具",更符合行业通用术语
  2. 架构更清晰:分离工具定义与实现,提高复用性
  3. 功能更强大:支持更灵活的工具注册和调用方式
  4. 注解驱动:新增@Tool注解,开发更便捷
FunctionToolCallback.builder("getWeather", service)
    .description("获取天气")

结构化输出

如JSON格式优势:

  1. 便于程序解析和处理
  2. 确保数据格式一致性
  3. 方便与前端或其他服务集成

StructuredOutputConverter
在这里插入图片描述

  • 在LLM调用前:转换器会向提示词追加格式指令,为模型生成目标输出结构提供明确指导。
  • 在LLM调用后:转换器将模型的原始文本输出转换为结构化类型,将其映射为对应的结构化JSON特定的数据结。

StructuredOutputConverter实现类型:接口允许您从基于文本的AI模型输出中获取结构化数据,默认BeanOutConverter实现类
在这里插入图片描述

public News generateAsString(String message) {
	News news = this.chatClient.prompt()
		.user(promptUserSpec -> promptUserSpec.text(message))
		.call()
		.entity(News.class);
}

@Data
public class News {
	private String entity;
	private String time;
	private String summary;
}    

RAG

添加依赖:
implementation 'org.springframework.ai:spring-ai-starter-vector-store-redis:1.0.1'

private final VectorStore vectorStore;
public String similaritySearch(String query) {
   SearchRequest request = SearchRequest.builder().query(query).topK(1).build();
   List<Document> results = this.vectorStore.similaritySearch(request);
   return JSONObject.valueToString(results);
}

或其他向量数据库。

模型

CogView-4:智谱开源文生图模型,支持任意长度的中英双语输入,能够生成在给定范围内的任意分辨率图像。

implementation ‘org.springframework.ai:spring-ai-starter-model-zhipuai:1.0.1’

private final ZhiPuAiImageModel zhiPuAiImageModel;

public String getImage(String imageName) {
	ImageResponse response = zhiPuAiImageModel.call(new ImagePrompt(imageName, ZhiPuAiImageOptions.builder().build()));
	return response.getResult().getOutput().getUrl();
}

Chat Memory

ChatMemory接口,支持实现不同类型的内存策略,默认MessageWindowChatMemory类

ChatMemoryRepository:专责消息的存储与检索,底层消息存储实现默认实现 InMemoryChatMemoryRepository 类

引入依赖:implementation 'org.springframework.ai:spring-ai-starter-model-chat-memory-repository-jdbc:1.0.1',JdbcChatMemoryRepository

配置:
spring.ai.chat.memory.repository.jdbc.initialize-schema=nerver

public ChatClientService(ChatClient.Builder builder,JdbcChatMemoryRepository chatMemoryRepository)
ChatMemory chatMemory = MessageWindowChatMemory.builder()
	.chatMemoryRepository(chatMemoryRepository)
	.maxMessages(10)
	.build();
ChatClient chatClient = builider.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();

chatClient.prompt()
	.user("你好")
	.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
	.call().content();

Advisors

用于拦截、修改和增强AI驱动的交互,封装常见的生成式AI模式,转换发送到和接收自LLMs的数据,在各种模型和用例之间提供可移植性。

优势:

  1. 封装常见模式:将RAG、内容安全检查等模式封装为可重用组件
  2. 数据转换:在请求发送前和响应接收后修改和增强数据
  3. 跨模型可移植性:编写一次Advisor,可用于多种AI模型和用例
  4. 可观测性:Advisors参与可观测性堆栈,支持指标和跟踪功能

工作原理类似于AOP:

  • 在AI交互的请求和响应阶段拦截处理流程
  • 可以访问和修改请求内容和上下文
  • 可以访问和修改响应内容和上下文
  • 多个Advisors可以组成处理链,按特定顺序执行

API

  • Advisor:基础接口,定义名称和顺序等基本特性
  • CallAdvisor:用于非流式场景的接口
  • StreamAdvisor:用于流式场景的接口
  • BaseAdvisor:同时继承CallAdvisor和StreamAdvisor的接口
  • BaseChatMemoryAdvisor:继承BaseAdvisor的接口
  • MessageChatMemoryAdvisor:将记忆作为消息集合添加到prompt
  • PromptChatMemoryAdvisor:将记忆整合到prompt的系统文本中
  • SafeGuardAdvisor:用于防止模型生成有害或不适当的内容
  • ChatModelCallAdvisor:
  • ChatModelStreamAdvisor:
  • SimpleLoggerAdvisor:日志记录

继承关系图
在这里插入图片描述
其他相关API:

  • ChatClientRequest:请求
  • ChatClientResponse:响应
  • CallAdvisorChain:
  • StreamAdvisorChain:

Advisors的执行顺序由getOrder()方法决定:

  • 较低的order值优先执行
  • Advisor链按照栈的方式工作:第一个加入链的Advisor最先处理请求;也是最后处理响应的Advisor
  • 高优先级的Advisor先执行请求处理,后执行响应处理
  • 如果多个Advisor具有相同的order值,它们的执行顺序不保证

Advisors支持两种处理模式:

  • 非流式处理:处理完整的请求和响应,实现CallAdvisor接口,重写adviseCall()方法;
  • 流式处理:处理连续的请求和响应流,实现StreamAdvisor接口,重写adviseStream()方法,使用响应式编程概念(如Flux)。

示例:

// 创建带有Advisors的ChatClient
var chatClient= ChatClient.builder(chatModel)
	.defaultAdvisors(
		MessageChatMemoryAdvisor.builder(chatMemory).build(),  // 聊天记忆顾问
		QuestionAnswerAdvisor.builder(vectorStore).build()     // RAG顾问
	)
	.build();

// 设置运行时参数
String response= chatClient.prompt()
	.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, "678"))
	.user(userText)
	.call()
	.content();

Prompt Engineering

几个参数:

  • Temperature:控制模型响应的随机性或创造力

    • 较低的值:0.0-0.3,更具确定性、更集中的响应。适用于事实类问题、分类或对一致性要求严格的任务;
    • 中等值:0.4-0.7,在确定性和创造力之间取得平衡。适用于一般用例;
    • 较高值:0.8-1.0,更具创造力、多样化且可能带来惊喜的响应。适用于创意写作、头脑风暴或生成多样化选项。
  • MaxTokens:限制模型在其响应中可生成Token数量

    • 较低值:适用于单个词、短语或分类标签。
    • 中等值:适用于段落或简短解释。
    • 较高值:适用于长篇内容、故事或复杂解释。
  • 采样控制:两个参数,允许对生成过程中的Token选择进行细粒度控制。

    • Top-K:将Token选择限制在K个最有可能的下一个Token中。较高值(如40-50)会引入更多多样性
    • Top-P:核采样,从累积概率超过P的最小Token集合中动态选择。常见的值如 0.8-0.95。

Role Prompting

public void rolePrompting(ChatClient chatClient) {
	String result = chatClient
		.prompt()
		.system(s -> s.text("你是一位经验丰富的Java开发专家,专注于Spring框架。请以简洁、专业的方式回答问题,并提供代码示例。"))
		.user(u -> u.text("如何在Spring Boot应用中实现基本的认证功能?"))
		.call()
		.content();
}

Self-Consistency通过生成多个独立的推理路径,然后选择最一致的答案来提高复杂推理任务的准确性。

public void selfConsistencyPrompting(ChatClient chatClient) {
    // 生成多个推理路径
    List<String> responses = newArrayList<>();
    for (int i = 0; i < 3; i++) {
        String response = chatClient
                .prompt()
                .user(u -> u.text("""
                        问题: 小明有5个苹果,他给了小红2个,又从小华那里得到3个,然后他又吃了1个。小明现在有多少个苹果?
                        让我们一步步思考得出答案。
                        """))
                .options(ChatOptions.builder().temperature(0.7).build()) // 使用较高温度以获得多样化的推理路径
                .call()
                .content();   
        responses.add(response);
    }   
}

解读:上面的让我们一步步思考得出答案正体现Chain-of-Thought Prompting。

MCP

MCP能力:

  • 标准化交互协议:统一AI模型与外部工具的通信方式
  • 多传输支持:STDIO/HTTP/SSE全兼容,适应本地或云端部署
  • 会话管理:v0.8.0全新升级的会话架构

MCP Java SDK采用清晰的三层设计,可轻松集成到现有系统:
在这里插入图片描述

  1. 客户端/服务端层
    • McpClient:搞定协议协商、工具调用
    • McpServer:暴露工具接口,管理资源URI
    • 支持同步/异步调用,兼容HTTP长连接和进程间通信
  2. 会话层:通过McpSession管理对话状态,多轮交互不再丢上下文
  3. 传输层:JSON-RPC消息一键序列化,三种传输任选:
    • STDIO:本地进程间通信
    • HTTP SSE:Servlet/WebFlux双版本支持
    • Reactive流:WebFlux实现高并发

server模块引入依赖:

implementation 'org.springframework.ai:spring-ai-starter-mcp-server-webflux:1.0.1'
implementation 'org.springframework.ai:spring-ai-starter-mcp-server:1.0.1'
implementation 'org.springframework.ai:spring-ai-starter-mcp-server-webmvc:1.0.1'

client引入依赖:

implementation 'org.springframework.ai:spring-ai-starter-mcp-client:1.0.1'
implementation 'org.springframework.ai:spring-ai-starter-mcp-client-webflux:1.0.1'

MCP Server

诸如:

  • 高德MCP Server:提供全场景覆盖的地图服务,包括地理编码、逆地理编码、IP定位、天气查询、骑行路径规划、步行路径规划、驾车路径规划、公交路径规划、距离测量、关键词搜索、周边搜索、详情搜索等。
  • 百度网盘MCP:核心API现已全面兼容MCP协议。涵盖用户信息、获取文件信息、文件上传、文件管理、文件搜索等。 开发者仅需简单配置,即可快速接入百度网盘服务,实现文件上传、文件管理等能力,大幅降低开发者调用网盘服务门槛,显著提升开发者的开发效率。
  • 百度优选MCP:提供MCP工具列表包含8个核心API,涵盖参数对比、品牌排行、商品检索、交易等。为用户提供全维度对比决策助手,实时品牌天梯榜单,轻松获取全网相关SPU与优质低价商品链接等能力。
  • Playwright MCP:微软推出的现代化跨浏览器自动化测试工具,支持Chromium、Firefox和WebKit,提供高速、可靠的端到端测试能力,适用于Web应用开发和持续集成。结合LLM能够无障碍与网页进行交互,从而实现智能浏览器页面操作。
  • Office-Word-MCP:用于创建、读取、编辑和格式化Microsoft Word文档。主要操作能力如下:创建表格、添加不同级别的标题、插入段落可选样式;格式化加粗、斜体、下划线、颜色和字体属性、搜索和替换;边框和样式格式化表格、格式表头行、应用单元格阴影和自定义边框。
  • antvis/mcp-server-chart:用于生成可视化图表的,目前支持 15+ 种图表:
    • 条形图、饼图、 柱形图、 折线图
    • 鱼骨图、思维导图、流程图、
    • 直方图、线型图、树形图、网络图
    • 雷达图、二维散点图、词语图、区域图表
  • MySQL MCP:提供SQL语句查询数据库的能力:
    • execute_query :支持select查询、show展示、describe描述;
    • get_table_info:获取数据表的详细结构信息;
    • list_tables:列出数据库中的所有数据表。
  • Excel-MCP:基于MCP的文件处理服务器,提供读取、写入和分析Excel文件的功能:
    • 读取Excel文件:获取工作表列表,读取特定工作表的数据,读取所有工作表的数据;
    • 写入Excel文件:创建新的Excel文件,向特定工作表写入数据,支持多工作表;
    • 分析Excel结构:分析工作表结构,将结构导出到新文件
  • Nacos MCP Router:一个基于MCP官方标准SDK实现的的MCP Server,提供一组工具,提供推荐、分发、安装及代理其他MCP Server的功能,帮助用户更方便地使用MCP Server服务。
    在这里插入图片描述
    安装较新版Nacos,打开管理后台,MCP管理,创建MCP Server。
  • @Joooook/12306-mcp:提供简单的API接口,允许用户搜索12306的车票。
  • HowToCooke MCP,让AI助手能够为你推荐菜谱、规划膳食,解决"今天吃什么"的世纪难题!
    1. 查询全部菜谱:获取所有可用菜谱数据,做菜百科全书
    2. 根据分类查询菜谱:按照分类筛选菜谱,想吃水产?早餐?荤菜?主食?一键搞定!
    3. 智能推荐膳食:根据你的忌口、过敏原和用餐人数,为你规划整整一周的美味佳肴
    4. 不知道吃什么:选择困难症福音!根据人数直接推荐今日菜单,再也不用纠结了
  • mcp-server-weread:支持将微信读书的书籍、笔记和划线数据提供给支持MCP的LLM:
    • 从微信读书获取书架信息;
    • 搜索书架中的图书;
    • 获取图书的笔记和划线;
    • 支持按章节组织笔记和划线。
  • Fetch MCP:从互联网上抓取URL并将其内容作为Markdown文件,接口参数:
    • url : 要抓取的URL
    • max_length:返回的最大字符数,默认5000
    • start_index:字符索引开始提取内容,默认0
    • raw:获取未经MarkDown转换的原始内容,默认false
{
    "mcpServers": {
        "playwright": {
            "command": "npx.cmd",
            "args": [
                "@playwright/mcp@latest"
            ]
        },
        "nacos-mcp-router": {
            "command": "docker",
            "args": [
                "run",
                "-i",
                "--rm",
                "--network",
                "host",
                "-e",
                "NACOS_ADDR=localhost:8848",
                "-e",
                "NACOS_USERNAME=nacos",
                "-e",
                "NACOS_PASSWORD=nacos",
                "-e",
                "TRANSPORT_TYPE=stdio",
                "nacos/nacos-mcp-router:latest"
            ]
        },
        "amap-maps": {
            "command": "npx",
            "args": [
                "-y",
                "@amap/amap-maps-mcp-server"
            ],
            "env": {
                "AMAP_MAPS_API_KEY": ""
            }
        },
        "mysql": {
            "command": "npx",
            "args": [
                "mysql-mcp-server"
            ],
            "env": {
                "MYSQL_HOST": "127.0.0.1",
                "MYSQL_PORT": "3306",
                "MYSQL_USER": "root",
                "MYSQL_PASSWORD": "root",
                "MYSQL_DB": "demo"
            }
        },
        "excel": {
            "command": "npx",
            "args": [
                "--yes",
                "@zhiweixu/excel-mcp-server"
            ],
            "env": {
                "fileAbsolutePath": "D:\data\excel"
            }
        },
        "12306-mcp": {
            "command": "npx",
            "args": [
                "-y",
                "12306-mcp"
            ]
        },
        "word-document-server": {
            "command": "uvx",
            "args": [
                "--from",
                "office-word-mcp-server",
                "word_mcp_server"
            ]
        },
        "fetch": {
            "command": "uvx",
            "args": [
                "mcp-server-fetch"
            ]
        },
        "mcp-server-chart": {
            "command": "npx.cmd",
            "args": [
                "-y",
                "@antv/mcp-server-chart"
            ]
        }
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到