本系列共 10 篇笔记,记录了从零开始上手 Spring AI 2.0 的完整路径:环境搭建 → 提示词 → 结构化输出 → 会话记忆 → 工具调用 → Advisor → 嵌入模型 → 向量数据库 → RAG → MCP。本文是收官总结,串联所有知识点并沉淀踩坑经验。
一、整体知识地图
Spring AI 的核心思路是:用 Spring 的方式(自动装配、Bean、链式 API)把”调大模型”这件事工程化。学习路线可以分成三层:
基础层:环境搭建、ChatClient、提示词(Prompt)、流式输出进阶层:结构化输出、会话记忆、工具调用、Advisor 机制应用层:嵌入模型、向量数据库、RAG、MCP
一条主线贯穿始终:所有能力最终都通过 ChatClient 的链式 API 组装起来——
chatClient.prompt().system(...) // 系统提示词.user(u -> u.text("{topic}").param("topic", topic)) // 用户提示词 + 模板参数.tools(new MyTools()) // 工具调用.advisors(memoryAdvisor, ragAdvisor) // 记忆 / RAG 等 Advisor.call().content(); // 同步调用(.stream() 则为流式)
二、各篇要点回顾
1. 环境搭建(地基)
- 版本要求:Spring AI 2.0.x 搭配 Spring Boot 4.0.x/4.1.x,JDK 17+,IDEA 2025.3+
- 依赖:
spring-ai-bom统一管版本,按模型引入 starter(如spring-ai-starter-model-openai) - 模型选择:用 OpenAI 协议兼容层接入阿里百炼(
base-url指向 dashscope compatible-mode),api-key 放系统环境变量 - 核心对象:
ChatClient建议在@Configuration中统一创建,便于后续切换 Ollama、DeepSeek 等不同模型 - 踩坑经验:配置项在不同版本间可能不一致,最可靠的方法是用 IDEA(Ctrl+N)搜
OpenAiChatAutoConfiguration找到对应的 Properties 配置类,直接看源码里的 key
2. 提示词(Prompt)
- 系统提示词:可在
ChatClient创建时defaultSystem()全局设置,也可在单次请求.system()覆盖 - 提示词模板:两种方式——
PromptTemplate显式创建,或user(u -> u.text("{topic}").param(...))流式写法 - 四种消息角色:System(定行为)、User(提问题)、Assistant(模型回应,可含工具调用请求)、Tool/Function(回传工具执行结果)
- 编写要素:清晰的指令(Instructions)+ 外部背景(Context)+ 用户输入 + 输出格式指示(Output Indicator);注意模型不一定严格遵守输出格式
3. 结构化输出
- 解决的问题:LLM 输出的是文本,业务代码需要的是类型化对象
- 用法:链式 API 末尾用
.entity(Topic.class)或.entity(new ParameterizedTypeReference<List<Book>>() {}) - 原理:Spring AI 根据你的 Java 类型自动生成 JSON Schema,注入提示词要求模型遵循,再把响应反序列化回对象
- 实用技巧:POJO 字段用
@JsonPropertyDescription("作者名称")标注用途——描述会写入 Schema,模型理解更准,否则可能出错
4. 会话记忆(ChatMemory)
- 背景:LLM 无状态,多轮对话需自己维护上下文
- 核心组合:
MessageWindowChatMemory+ChatMemoryRepository,通过MessageChatMemoryAdvisor挂到 ChatClient 上 - 使用要点:请求时必须通过
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, ...))指定会话 ID;窗口满后淘汰最早消息,system 消息始终保留 - 两种策略对比:
MessageWindowChatMemory:滑动窗口,按顺序保留最近 N 条(默认 20),最常用VectorStoreChatMemory:语义检索召回相关历史,不固定窗口,解决超长对话 token 爆炸
- 存储后端:内存(开发测试)、Redis(生产/多实例)、JDBC(需持久化+事务)、Cassandra(超大规模)
5. 工具调用(Tool Calling)
- 意义:只能生成文本的是聊天机器人;能发现信息、采取行动、循环执行直到达成目标的才是智能体。两大用途:信息检索(查天气、查数据库)和采取行动(发邮件、订票、触发工作流)
- 用法:方法上加
@Tool(description = "..."),请求时.tools(new MyTools()) - 执行流程:模型判断需要工具 → 返回调用请求 → Spring AI 本地执行 → 结果回传模型 → 继续生成(日志可见多轮请求)
- 踩坑经验:日志里看不到工具定义是正常的——
SimpleLoggerAdvisor只打印 messages,而工具 schema 放在请求体的tools字段(ChatOptions)里,不属于 Message
6. Advisor 机制
- 定位:AOP 思想在 AI 请求上的落地——拦截请求做处理(日志、记忆注入、RAG 检索),响应回来再做处理
- 执行流程:请求沿 advisor 链依次处理 → 最终发给模型 → 响应沿链回传;链是栈式结构,order 越小越先处理请求、越后处理响应
- 自定义:实现
CallAdvisor(同步)和/或StreamAdvisor(流式),最佳实践是两者都实现 - 内置 Advisor 速查:
MessageChatMemoryAdvisor—— 会话记忆QuestionAnswerAdvisor—— 朴素 RAGRetrievalAugmentationAdvisor—— 模块化 RAGToolCallingAdvisor—— 工具调用循环(框架自动挂载)SimpleLoggerAdvisor/SafeGuardAdvisor/ReReadingAdvisor等
7. 嵌入模型(Embedding)
- 概念:把文本转成定长浮点数组(向量),维度即数组长度;向量间余弦相似度越大语义越相近
- 配置:与 chat 同级,
spring.ai.openai.embedding.model / dimensions(百炼 qwen embedding,2048 维) - 验证实验:「我爱java」vs「我爱php」相似度 0.69 >「我爱java」vs「我爱小猫咪」0.64,符合语义直觉
- 价值:解决传统关键词检索无法理解语义的问题(”治疗感冒的药”能匹配”缓解伤风症状的药物”),是 RAG 检索环节的核心支撑
8. 向量数据库(VectorStore)
- 特点:不做精确匹配,做相似性搜索——给一个查询向量,返回”最像”的向量
- 支持范围:Spring AI 支持近 20 种向量库(PgVector、Redis、Milvus、Elasticsearch、Chroma、Neo4j……),统一接口,换库只换依赖和配置
- 入门首选:
SimpleVectorStore——内存实现、无需启动客户端,doAdd()存入、similaritySearch(SearchRequest.builder().query(...).topK(2))查询 - 实验结论:查询”开发语言”,能正确召回”我爱java””我爱JavaScript”而过滤掉”我爱小猫咪”
9. RAG(检索增强生成)
- 流程五步:用户输入 → 转向量 → 向量库查相似内容 → 拼上下文发给大模型 → 返回结果
- 实践要点:
- 文档要分片(chunk):自己写了
TxtDocumentLoader,按 chunkSize=800、overlap=150 切分,并给每个 Document 附上 file_name、chunk_index 等元数据 - 用
QuestionAnswerAdvisor.builder(vectorStore)一行接入 RAG similarityThreshold相似度阈值要调:设太高(查询太严格)可能什么都检索不到
- 文档要分片(chunk):自己写了
- 本质:RAG 在 Spring AI 里就是一个 Advisor,和记忆、日志是同一套机制——这正是 Advisor 设计的优雅之处
10. MCP(模型上下文协议)
- 定位:标准化协议,让 AI 模型以结构化方式访问数据库、API、文件系统等外部资源,是”AI 连接现实世界的桥梁”
- 服务端:
spring-ai-starter-mcp-server-webmvc,@McpTool/@McpResource注解暴露工具与资源,支持 STREAMABLE/SSE/STATELESS 传输,复用/mcp端点 - 客户端:
spring-ai-starter-mcp-client,配置里声明连接(如self-server: url: http://localhost:8081),注入ToolCallbackProvider后.tools(mcpTools)即可使用 - 验证:问”1 加 1 等于多少”,模型通过 MCP 调到服务端的 add 工具,服务端日志打印
有调用:1;1
三、贯穿全程的三个设计思想
- 一切皆链式 API:ChatClient 的
prompt().system().user().tools().advisors().call()把所有能力串成一条流式管道,学习成本极低。 - 一切皆 Advisor:记忆(MessageChatMemoryAdvisor)、RAG(QuestionAnswerAdvisor)、日志(SimpleLoggerAdvisor)、工具循环(ToolCallingAdvisor)都是 Advisor。理解了 Advisor 链的栈式执行顺序,就理解了 Spring AI 的扩展模型。
- 一切皆可替换:模型(OpenAI 兼容协议换百炼/DeepSeek/Ollama)、记忆存储(内存/Redis/JDBC)、向量库(近 20 种实现同一接口),都是”换依赖 + 换配置”的事。
四、踩坑与经验清单
| # | 问题 | 结论 |
|---|---|---|
| 1 | 配置项 key 不确定 | 直接 Ctrl+N 搜 XxxAutoConfiguration,看 Properties 源码 |
| 2 | 日志看不到工具定义 | 工具 schema 在请求体 tools 字段,不属于 messages |
| 3 | 结构化输出字段理解错 | 用 @JsonPropertyDescription 给字段加描述 |
| 4 | 记忆”丢”了 | 窗口满了按序淘汰;且必须设置 CONVERSATION_ID |
| 5 | RAG 查不到内容 | 检查 similarityThreshold 是否设太高 |
| 6 | 每次请求系统提示词不同 | .system() 会覆盖 defaultSystem,按需选择 |
五、下一步可以学什么
- 多模态:图像、音频输入输出
- 可观测性:生产环境的 token 用量、延迟监控
- 评估(Evaluation):对 RAG 检索质量、模型输出的自动化评测
- 进阶 RAG:
RetrievalAugmentationAdvisor模块化架构、混合检索、重排序 - MCP 深入:SSE 实时通信、MCP 生态工具集成、把现有系统能力封装成 MCP Server
本篇为系列收官总结,对应笔记:环境搭建 / Prompt / 结构化输出 / 会话记忆 / 工具调用 / Advisor / Embedding / 向量数据库 / RAG / MCP,共 10 篇。
