Spring AI 面试题库
生成时间: 2026-05-21 23:38
本轮 Spring AI 面试题库(带答案)
【面试题】1. Spring AI 中 ChatClient 和直接使用 ChatModel 有什么区别?什么时候用哪个?
【标准答案】 ChatModel 是底层抽象,直接调用模型API,适合简单的一次性对话场景。ChatClient 是高层封装,提供了 Fluent API、内置 Advisor 机制、自动处理对话记忆等功能。
实际项目中:
- 简单问答、单轮调用 → 用 ChatModel,代码更简洁
- 需要对话记忆、RAG、工具调用、多步编排 → 用 ChatClient,开箱即用
ChatClient 的核心价值是把通用能力(记忆、RAG、日志、重试)通过 Advisor 链式组合,避免每个场景都写重复代码。Spring AI 1.0 正式版推荐统一使用 ChatClient 作为入口。
【面试题】2. RAG 场景下,TokenTextSplitter 的 chunkSize 和 overlap 参数怎么调优?
【标准答案】 这是典型的召回率和上下文连续性权衡问题。
chunkSize 经验值:
- 技术文档、API手册 → 500-1000 tokens,粒度细便于精确匹配
- 长文章、报告 → 1000-2000 tokens,保留段落完整性
- 代码片段 → 按函数/类边界切,而非固定token数
overlap 经验值:
- 一般场景 → chunkSize 的 10-20%
- 语义关联强的内容 → 可提高到 25-30%
- 过大会导致重复召回,浪费token预算
实际做法:先用默认值(1000/200)跑基线,然后用几个典型query做召回测试,看命中率。同时监控向量库的查询延迟,chunk太多会影响性能。
【面试题】3. Spring AI 的 Function Calling 是怎么实现的?@Bean 注册的函数怎么被模型调用的?
【标准答案】 核心流程分三步:
第一步,函数注册。@Bean 定义一个普通方法,Spring AI 自动扫描并生成 JSON Schema(包含参数名、类型、描述),这个 Schema 会作为 tools 字段传给模型。
第二步,模型决策。模型返回 tool_call,包含函数名和参数JSON。Spring AI 拦截这个响应,通过函数名找到对应的 Bean,用反射或直接调用执行。
第三步,结果回填。执行结果作为 tool message 追加到对话历史,再次调用模型,让它基于工具结果生成最终回答。
关键点:
- 函数签名要清晰,参数名和描述要准确,模型依赖这些决定何时调用
- 复杂参数用 record 或 POJO,Spring AI 会递归生成嵌套 Schema
- 默认自动执行,可配置手动确认(涉及写操作时建议开启)
【面试题】4. VectorStore 接口统一后,PGVector 和 Redis 作为向量库各自适用什么场景?
【标准答案】 PGVector:
- 已有 PostgreSQL 基础设施,不想引入新组件 → 首选
- 数据量中等(百万级向量以内)、查询QPS不高
- 需要事务、复杂SQL关联查询(向量+结构化混合查询)
- 运维成本低,一库多用
Redis(RedisSearch + Vector):
- 已有 Redis 集群,追求极低延迟 → 首选
- 高QPS、低延迟要求场景(实时推荐、在线检索)
- 数据量不大、可接受内存成本
- 支持淘汰策略,适合热度数据
实际选型:先看现有技术栈,再评估数据规模和延迟要求。两个都有成熟的 Spring AI Starter,切换成本低。
【面试题】5. ChatMemory 的持久化方案怎么设计?生产环境直接用 InMemoryChatMemory 会出什么问题?
【标准答案】 InMemoryChatMemory 问题:
- 应用重启,对话历史丢失
- 多实例部署,用户请求路由到不同实例,记忆不共享
- 内存无上限,长对话会OOM
生产方案:
方案一,Redis 持久化
- 实现 ChatMemory 接口,用 Redis List/String 存消息
- 设置 TTL(如7天),自动清理过期对话
- 适合高并发、多实例共享场景
方案二,数据库持久化
- PostgreSQL/MySQL 存消息表,按 conversationId 查询
- 适合需要审计、历史查询的场景
- 配合缓存层减少数据库压力
方案三,混合策略
- 最近N轮对话放 Redis(热数据)
- 完整历史落数据库(冷数据)
- 按需加载历史,控制上下文窗口大小
Spring AI 1.0 的 MessageChatMemoryAdvisor 已经支持配置 ChatMemory 实现,注入持久化版本即可。
【面试题】6. Structured Output 用 BeanOutputConverter 时遇到过什么坑?entity() 和 beanOutputConverter() 有什么区别?
【标准答案】 常见坑:
坑一,模型输出不严格符合Schema
- 模型可能输出额外字段、嵌套对象缺失、枚举值不匹配
- 解决:设置 strictMode,失败后重试或降级到文本解析
坑二,复杂嵌套POJO
- List嵌套List、Map嵌套复杂对象,Schema生成可能不完整
- 解决:简化数据结构,或手动定义Schema
坑三,字段描述不准
- 模型依赖字段名和描述理解语义,描述含糊会导致输出偏移
- 解决:用 @JsonProperty + @JsonPropertyDescription 精准描述
entity() vs beanOutputConverter():
- entity() 是 ChatClient 的快捷方法,一行代码完成调用+转换,适合简单POJO
- beanOutputConverter() 更灵活,可以获取 Schema 字符串、自定义解析逻辑、处理流式输出
实际建议:简单场景用 entity(),复杂场景(需要自定义格式、错误处理)用 BeanOutputConverter。
【面试题】7. Spring AI 1.0 正式版的 Advisor 机制是怎么设计的?如何自定义一个 Advisor?
【标准答案】 Advisor 核心设计:
Advisor 接口有两个关键方法:
- adviseRequest():请求发出前拦截,可修改 Prompt、添加参数
- adviseResponse():响应返回后拦截,可修改输出、添加后处理
调用链路: ChatClient → Advisor链 → ChatModel → Advisor链(反向)→ 返回结果
自定义 Advisor 步骤:
- 实现 Advisor 接口,定义处理逻辑
- 注册为 @Bean 或通过构造器传入 ChatClient
- 指定 order 控制执行顺序(Ordered 接口或 @Order 注解)
典型应用场景:
- 日志记录:记录请求响应、耗时统计
- 内容审核:拦截敏感内容
- 缓存:相同query直接返回缓存结果
- 重试:模型调用失败自动重试
- 自定义 RAG:注入检索结果到 Prompt
Spring AI 1.0 内置了 QuestionAnswerAdvisor(RAG)、MessageChatMemoryAdvisor(记忆)等,开箱即用。
【面试题】8. 多模型对接时,如何动态切换 OpenAI、智谱、Ollama 等不同模型?
【标准答案】 Spring AI 统一了 ChatModel 接口,切换方式:
方式一,配置文件切换(静态)
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4改配置重启应用,适合固定模型场景。
方式二,多 Bean 注入(运行时切换)
@Bean
ChatModel openaiChatModel() { ... }
@Bean
ChatModel zhipuChatModel() { ... }
// 注入时指定
@Autowired @Qualifier("zhipuChatModel") ChatModel chatModel;方式三,动态路由(高级)
- 定义 ChatModelRouter,根据用户ID、租户、任务类型选择模型
- 配合 Spring 的 @Conditional 或 Profile 实现环境隔离
方式四,ChatClient 动态指定
chatClient.prompt()
.model("gpt-4") // 覆盖默认配置
.call();实际项目:核心是抽象一层模型选择逻辑,业务代码不感知具体模型。Spring AI 的 spring.ai.* 配置前缀让多模型配置很清晰。
【面试题】9. 生产环境部署 Spring AI 应用,API Key 管理和熔断限流怎么做?
【标准答案】 API Key 管理:
- 禁止硬编码,用 Spring 的 @Value + 配置中心(Nacos/Apollo/Consul)
- 敏感配置用 Vault 或云厂商的 Secrets Manager
- 多环境隔离(dev/staging/prod 不同Key)
- 定期轮换,设置过期告警
熔断限流方案:
限流:
- 模型API调用 → Resilience4j RateLimiter 或 Bucket4j
- 按 API Key 或用户维度限流,避免单个用户打满配额
- 注意模型厂商的 RPM/TPM 限制
熔断:
- Resilience4j CircuitBreaker,配置失败阈值和恢复时间
- 降级策略:返回缓存结果、切换备用模型、友好提示稍后重试
- 监控熔断状态,及时告警
其他生产要点:
- 超时设置:模型API响应慢,必须设超时(建议30-60s)
- 重试策略:幂等请求可重试,非幂等要谨慎
- 观测:Micrometer + Prometheus + Grafana,监控调用耗时、错误率、token消耗
Spring AI 原生支持 Micrometer,集成 Spring Boot Actuator 后自动暴露指标。
【面试题】10. Spring AI 的 Streaming 响应怎么用?前端怎么接收流式输出?
【标准答案】 后端实现:
chatClient.prompt()
.user("介绍一下Spring AI")
.stream()
.content()
// 返回 Flux<String>WebFlux 集成:
@GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chat(@RequestParam String question) {
return chatClient.prompt()
.user(question)
.stream()
.content();
}前端接收:
- SSE(Server-Sent Events):原生 EventSource 或 EventSourcePolyfill
- WebSocket:双向通信场景
- fetch + ReadableStream:现代浏览器推荐
示例(fetch):
const response = await fetch('/chat?question=hello');
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
// 渲染到页面
}注意事项:
- 流式响应不支持重试(已输出部分无法撤回)
- Token 统计要等流结束才能获取
- 错误处理要考虑流中途异常的情况
- 前端要做打字效果优化,避免闪烁
Spring AI 1.0 的 stream() 方法返回 Flux,天然支持 WebFlux,响应式全栈一致性很好。
题目统计:
- 技术基础:2题(ChatClient vs ChatModel、Function Calling)
- 架构设计:2题(ChatMemory持久化、多模型切换)
- 场景实操:2题(RAG切分、Structured Output)
- 性能优化:2题(TokenTextSplitter调优、熔断限流)
- 版本更新:1题(Advisor机制)
- 部署监控:1题(API Key管理与生产部署)
总计:10题