个人随笔
目录
Spring AI 2.0 简单学习总结篇
2026-11-04 23:15:55

本系列共 10 篇笔记,记录了从零开始上手 Spring AI 2.0 的完整路径:环境搭建 → 提示词 → 结构化输出 → 会话记忆 → 工具调用 → Advisor → 嵌入模型 → 向量数据库 → RAG → MCP。本文是收官总结,串联所有知识点并沉淀踩坑经验。


一、整体知识地图

Spring AI 的核心思路是:用 Spring 的方式(自动装配、Bean、链式 API)把”调大模型”这件事工程化。学习路线可以分成三层:

  1. 基础层:环境搭建、ChatClient、提示词(Prompt)、流式输出
  2. 进阶层:结构化输出、会话记忆、工具调用、Advisor 机制
  3. 应用层:嵌入模型、向量数据库、RAG、MCP

一条主线贯穿始终:所有能力最终都通过 ChatClient 的链式 API 组装起来——

  1. chatClient.prompt()
  2. .system(...) // 系统提示词
  3. .user(u -> u.text("{topic}").param("topic", topic)) // 用户提示词 + 模板参数
  4. .tools(new MyTools()) // 工具调用
  5. .advisors(memoryAdvisor, ragAdvisor) // 记忆 / RAG 等 Advisor
  6. .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 —— 朴素 RAG
    • RetrievalAugmentationAdvisor —— 模块化 RAG
    • ToolCallingAdvisor —— 工具调用循环(框架自动挂载)
    • 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 相似度阈值要调:设太高(查询太严格)可能什么都检索不到
  • 本质: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

三、贯穿全程的三个设计思想

  1. 一切皆链式 API:ChatClient 的 prompt().system().user().tools().advisors().call() 把所有能力串成一条流式管道,学习成本极低。
  2. 一切皆 Advisor:记忆(MessageChatMemoryAdvisor)、RAG(QuestionAnswerAdvisor)、日志(SimpleLoggerAdvisor)、工具循环(ToolCallingAdvisor)都是 Advisor。理解了 Advisor 链的栈式执行顺序,就理解了 Spring AI 的扩展模型。
  3. 一切皆可替换:模型(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 篇。

 2

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2