本轮 Spring AI 面试题库(带答案)
【面试题】1. Spring AI 中 ChatClient 和 ChatModel 有什么区别?什么场景用哪个?
【标准答案】 区别:ChatModel 是底层模型接口,负责和 AI 模型直接交互,你传 Prompt 它返回 ChatResponse,偏底层。ChatClient 是 1.0 新增的高层门面,内部封装了 ChatModel,提供了流式 API、Advisor 链、自动重试、错误处理等能力。
选型:
- 用 ChatModel:只需要简单调用模型、对响应格式没特殊要求、想完全控制请求细节
- 用 ChatClient:需要流式输出、要加 Advisor(比如 RAG、Memory)、要统一错误处理、要构建复杂对话流程
实战建议:新项目直接用 ChatClient,它是对 ChatModel 的增强封装,功能更全、代码更简洁。除非有特殊定制需求,否则不用直接操作 ChatModel。
【面试题】2. Spring AI 的 Advisor 机制是什么?能解决什么问题?
【标准答案】 定义:Advisor 是 Spring AI 的拦截器模式,每个 Advisor 可以在请求发往模型前、响应返回后插入自定义逻辑。类似 Spring MVC 的 Interceptor 或 AOP。
核心能力:
- 请求预处理:改 Prompt、加系统提示、注入上下文
- 响应后处理:格式转换、结果过滤、日志记录
- 链式调用:多个 Advisor 顺序执行,责任链模式
典型应用:
- QuestionAnswerAdvisor:自动从向量库检索相关文档,注入到 Prompt,实现 RAG
- MessageChatMemoryAdvisor:自动管理历史消息,实现对话记忆
- 日志监控 Advisor:记录每个请求的耗时、token 消耗
代码示例:
ChatClient.builder(chatModel)
.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
.build();【面试题】3. RAG 中的 TokenTextSplitter 怎么设置分块大小?有什么坑?
【标准答案】 设置原则:
- 默认值:默认 800 token,重叠 100 token
- 调整依据:根据向量模型的最大输入长度(比如 OpenAI text-embedding-3-small 最大 8191 token)和业务文档特点来定
- 经验值:问答场景 500-1000 token,长文档总结 1000-2000 token
常见坑:
- 切在句子中间:导致语义割裂,检索召回率下降 → 解决:用递归分割器,先按段落再按句子
- 分块太大:超出向量模型限制,或者召回太多噪音 → 解决:控制在模型上限的 80% 以内
- 分块太小:上下文不足,回答质量差 → 解决:适当增加 overlap,保留上下文
- 忽略中英文差异:中文 token 计数和英文不同 → 解决:实际测试 token 数,别只看字符数
代码示例:
TokenTextSplitter splitter = new TokenTextSplitter(
500, // targetChunkSize
100, // overlap
5, // minChunkSize
10000 // maxNumChunks
);【面试题】4. Spring AI 的 Function Calling 是怎么实现的?整个调用流程是什么?
【标准答案】 核心原理:Spring AI 自动把带 @Bean 的方法转成 JSON Schema,传给模型。模型判断需要调用函数时返回 tool_call 指令,框架自动执行函数,把结果回传模型继续推理。
完整流程:
- 注册函数:定义
@Bean方法,Spring AI 扫描并生成 JSON Schema - 发起请求:ChatClient 把函数描述加入请求的
tools字段 - 模型决策:模型分析用户问题,决定是否需要调用函数
- 返回 tool_call:模型返回函数名 + 参数(JSON 格式)
- 框架执行:Spring AI 自动解析参数,调用对应方法,拿到返回值
- 回传结果:把执行结果追加到消息历史,再次调用模型
- 最终回答:模型基于函数返回结果生成最终答案
关键点:
- 函数参数用 POJO 定义,Spring AI 自动映射
- 返回值会序列化成 JSON 字符串传给模型
- 可以配置
toolChoice强制调用或让模型自主选择
【面试题】5. Spring AI 支持哪些向量数据库?选型时怎么选?
【标准答案】 官方支持:PGVector、Redis、Pinecone、Chroma、Milvus、Weaviate、Qdrant、MongoDB Atlas、Oracle 等 10+ 种。
选型维度:
- 开发环境:PGVector(直接用现有 PostgreSQL)、Chroma(嵌入式,零配置)
- 生产环境:
- 中小规模:PGVector(运维简单,已有 PG 基础设施)、Redis(高性能,但需要 Redis Stack)
- 大规模:Milvus(分布式,性能强)、Pinecone(全托管,零运维)
- 云厂商绑定:AWS 选 OpenSearch,阿里云选 Milvus/Hologres
- 成本考虑:PGVector/Chroma 开源免费,Pinecone 按量付费
实战建议:
- 开发阶段用 Chroma 或 PGVector,快速验证
- 生产环境优先 Milvus(开源生态好)或 Pinecone(托管省心)
- 代码层面用
VectorStore接口,方便切换实现
【面试题】6. Spring AI 的 Structured Output 怎么用?有什么限制?
【标准答案】 用法:通过 BeanOutputConverter 把模型输出映射成 POJO,自动校验字段类型和格式。
代码示例:
ChatResponse response = chatClient.prompt()
.user("提取用户信息")
.call()
.chatResponse();
UserEntity user = new BeanOutputConverter<>(UserEntity.class)
.fromEntity(response.getResult().getOutput().getContent());关键限制:
- 模型支持:不是所有模型都支持,OpenAI GPT-4、Claude 3.5 支持最好,国内模型部分支持
- Schema 复杂度:嵌套层级太深可能解析失败,建议控制在 3 层以内
- 字段校验:框架只做类型校验,业务逻辑校验需要自己实现
- 错误处理:模型输出不符合 Schema 时会抛异常,需要 try-catch 并降级处理
最佳实践:
- POJO 字段加
@JsonProperty和@JsonPropertyDescription,提升模型理解 - 必填字段用包装类型,避免 null 问题
- 提供示例值,引导模型输出正确格式
【面试题】7. Chat Memory 怎么实现持久化?线上环境用什么方案?
【标准答案】 接口设计:Spring AI 提供 ChatMemory 接口,核心方法是 add(message) 和 get(conversationId, lastN)。
持久化方案:
- Redis:适合高并发场景,天然支持 TTL 自动清理过期对话java
public class RedisChatMemory implements ChatMemory { // 用 Redis List 存储,conversationId 作 key } - 数据库:适合需要查询分析的场景,存 MySQL/MongoDB
- 混合方案:热数据存 Redis,冷数据定期归档到数据库
关键考虑:
- 存储限制:对话历史太长占内存和 token,需要限制 lastN(比如最近 10 轮)
- 并发控制:多实例部署时用分布式锁,避免消息顺序错乱
- 隐私合规:敏感对话需要加密存储,或定期清理
线上建议:Redis + 定时清理任务,控制单次对话历史在 20-30 条以内。
【面试题】8. Spring AI 1.0 正式版有哪些重要更新?和 M 系列版本有什么区别?
【标准答案】 核心变化:
- ChatClient 统一入口:M 系列用 ChatModel 直接调用,1.0 推荐 ChatClient,统一流式和非流式 API
- Advisor 架构:1.0 引入 Advisor 机制,实现了 RAG、Memory 等能力的模块化插拔
- 配置前缀统一:从
spring.ai.openai.api-key改为spring.ai.openai.api-key,所有模型配置统一前缀 - VectorStore 接口标准化:1.0 定义了统一的向量库操作接口,切换实现只需改依赖和配置
- Observability 增强:集成 Micrometer,提供 token 消耗、耗时、错误率等指标
迁移要点:
- M 系列的
ChatModel.call(prompt)→ 1.0 用ChatClient.prompt().user(text).call() - 手动实现的 RAG 逻辑 → 改用
QuestionAnswerAdvisor - 自定义配置前缀 → 统一改成
spring.ai.*
建议:新项目直接上 1.0,M 系列老项目评估迁移成本,核心功能不受影响。
【面试题】9. Spring AI 如何实现多模型切换?配置怎么管理?
【标准答案】 实现方式:
配置文件切换:修改
spring.ai.model或具体模型配置,重启生效yamlspring: ai: openai: api-key: ${OPENAI_API_KEY} chat: options: model: gpt-4-turbo运行时切换:注入不同的
ChatModelBean,按业务选择java@Autowired @Qualifier("openAiChatModel") ChatModel openAiModel; @Autowired @Qualifier("zhipuChatModel") ChatModel zhipuModel; ChatModel model = useZhipu ? zhipuModel : openAiModel;动态路由:根据请求参数、用户等级、成本控制自动选模型
javapublic ChatModel selectModel(Request request) { if (request.isPremium()) return gpt4Model; if (request.isLowCost()) return localOllamaModel; return defaultModel; }
配置管理:
- 多环境:用 Spring Profile 区分 dev/test/prod 配置
- 密钥管理:API Key 从环境变量或 Vault 读取,别写死在配置文件
- 成本控制:高成本模型(GPT-4)限流,低成本模型(Ollama 本地)兜底
【面试题】10. Spring AI 的 Streaming 流式响应怎么实现?前端怎么对接?
【标准答案】 后端实现:
Flux<String> stream = chatClient.prompt()
.user("写一首诗")
.stream()
.content(); // 返回 Flux<String>
// WebFlux 直接返回
return ResponseEntity.ok()
.contentType(MediaType.TEXT_EVENT_STREAM)
.body(stream);关键点:
stream()方法返回Flux<ChatResponse>,可以用.content()提取纯文本- 需要依赖
spring-boot-starter-webflux - 超时设置:流式请求可能很慢,配置合理的超时时间
前端对接:
const eventSource = new EventSource('/api/chat/stream');
eventSource.onmessage = (event) => {
document.getElementById('output').textContent += event.data;
};
eventSource.onerror = () => eventSource.close();注意事项:
- 用 SSE(Server-Sent Events)协议,前端 EventSource 自动重连
- 长连接问题:Nginx/网关需要配置超时时间,避免中断
- 错误处理:流式返回中可能包含错误,需要解析并提示用户