本轮 Spring AI 面试题库(带答案)
【面试题】1. Spring AI 中 ChatClient 和直接用 ChatModel 有什么区别?为什么推荐用 ChatClient?
【标准答案】ChatModel 是底层模型调用接口,只负责发送 Prompt 拿到响应,属于"裸调用"。ChatClient 是 Spring AI 1.0 推出的统一入口,基于 Fluent API 设计,内置了 Advisor 链式处理能力。核心区别三点:第一,ChatClient 封装了 Prompt 模板、输出格式转换、记忆管理等横切关注点,不用手写样板代码;第二,Advisor 机制让你可以在请求前后插入拦截逻辑,比如加对话记忆、做 RAG 检索、限流熔断,而 ChatModel 没有这个扩展点;第三,ChatClient 的链式调用 .prompt().user("xxx").advisors(...).call() 代码更简洁可读。面试一句话总结:ChatModel 是引擎,ChatClient 是方向盘加仪表盘,生产环境必须用 ChatClient。
【面试题】2. Spring AI 的 Advisor 机制是怎么工作的?能举个实际应用场景吗?
【标准答案】Advisor 是 Spring AI 的请求拦截链,类似 Servlet Filter 或 Spring Interceptor 的思路。每个 Advisor 实现了 CallAroundAdvisor(同步)或 StreamAroundAdvisor(流式),在请求发往模型前后各有一个拦截点。执行流程:ChatClient 收到请求 → 按顺序执行 Advisor 链的 before → 调用 ChatModel → 按逆序执行 Advisor 链的 after → 返回结果。实际场景举例:MessageChatMemoryAdvisor 在 before 阶段从 ChatMemory 取历史消息拼入 Prompt,在 after 阶段把新一轮对话存回 ChatMemory;QuestionAnswerAdvisor 在 before 阶段从 VectorStore 检索相关文档注入上下文。Advisor 之间通过 order 控制顺序,数字小的先执行。面试关键点:Advisor 让横切逻辑可插拔,不用改业务代码就能加功能。
【面试题】3. Spring AI 做 RAG 时,TokenTextSplitter 的 chunk size 怎么定?太大太小各有什么问题?
【标准答案】chunk size 需要平衡语义完整性和检索精度,没有万能值,但有个决策框架。太大(比如超过 2000 token):检索召回的 chunk 包含太多无关信息,噪声稀释了关键内容,模型回答容易跑偏,同时消耗更多 token 预算。太小(比如低于 100 token):语义被截断,一个完整概念被拆到多个 chunk 里,单独检索任何一个 chunk 都不完整,导致回答碎片化。实际建议:一般文档用 500-1000 token、overlap 50-100 token;代码文件用较小 chunk(200-400)因为代码语义密度高;法律合同等长段落文档用较大 chunk(800-1200)。overlap 的作用是避免关键信息刚好在切分边界被截断。另外 chunk size 要和 Embedding 模型的最大输入长度匹配,比如 text-embedding-3-small 最大 8191 token,chunk 不要超过这个上限。
【面试题】4. Spring AI 的 Function Calling 流程是怎样的?@Bean 注册的函数是怎么被模型发现的?
【标准答案】流程分四步:第一步,开发者用 @Bean 注册一个 java.util.function 接口实现(如 Function<I, O>),Spring AI 自动扫描并生成 JSON Schema 描述函数的参数和返回值;第二步,ChatClient 发请求时把可用函数列表的 Schema 传给模型;第三步,模型判断需要调函数时返回 tool_call 指令(包含函数名和参数 JSON),而不是最终回答;第四步,Spring AI 框架自动执行对应函数,把结果拼回 Prompt 再次调用模型,模型基于函数返回值生成最终回答。关键细节:函数注册不需要手动写 Schema,Spring AI 通过泛型参数 I 的类型自动推导;函数名就是 Bean 名称;如果模型一次请求要调多个函数,Spring AI 会并行执行再合并结果。面试加分点:提到 tool_call 是模型输出不是代码调用,模型只是在说"我需要这个函数的结果",真正执行是框架侧完成的。
【面试题】5. Spring AI 的 Structured Output 有哪几种实现方式?BeanOutputConverter 有什么坑?
【标准答案】三种方式:第一,BeanOutputConverter<T> 配合 ChatClient 的 .call() 手动解析,最灵活但需要自己处理异常;第二,ChatClient 的 .entity() 方法直接映射 POJO,一行代码搞定,底层还是 BeanOutputConverter;第三,Spring AI 1.0 新增的 output() 流式 API,支持 outputFormat(BeanOutputConverter) 链式调用。BeanOutputConverter 的坑主要有三个:一是模型不保证100%按 Schema 输出,可能输出非法 JSON 或缺少字段,必须做 fallback 处理;二是复杂嵌套对象(List套Map套对象)的 Schema 生成可能不准确,建议用扁平结构;三是枚举类型需要加 @JsonProperty 或 @Schema(description=...) 辅助模型理解可选值。面试建议答法:先说三种方式,再重点说 entity() 最常用,最后提一个坑和解决方案——加 retry + 降级到文本解析。
【面试题】6. Spring AI 的 ChatMemory 接口和 InMemoryChatMemory 在生产环境能用吗?持久化方案怎么选?
【标准答案】InMemoryChatMemory 只适合开发测试,生产环境绝对不能用——应用重启记忆全丢,多实例部署时各实例记忆不共享。ChatMemory 接口只定义了 add、get、clear 三个方法,持久化需要自己实现或用社区方案。选型思路:如果已经有 Redis,实现一个 RedisChatMemory 最简单,用 List 结构存 Message,设置 TTL 自动过期;如果用关系型数据库,用 PG 存 JSON 也行,适合需要审计追踪的场景;如果对话量特别大,考虑分片策略——只保留最近 N 轮对话,早期对话做摘要压缩。另外一个关键点:ChatMemory 要和 MessageChatMemoryAdvisor 配合使用,Advisor 负责在请求前后自动读写记忆,你只需要提供 ChatMemory 实现类。面试加分:提到对话记忆的 token 窗口有限,必须做淘汰策略,否则长对话会撑爆上下文。
【面试题】7. Spring AI 多模型对接时,如何通过配置切换不同 AI 供应商?有没有踩坑经验?
【标准答案】Spring AI 通过 spring.ai.* 配置前缀实现模型切换,每个供应商有独立的 starter。比如 spring-ai-openai-spring-boot-starter 对应 spring.ai.openai.*,spring-ai-ollama-spring-boot-starter 对应 spring.ai.ollama.*。切换只需要两步:改 Maven/Gradle 依赖的 starter,改 application.yml 的配置前缀和参数。ChatModel 的 Bean 名称按供应商自动注册,比如 openAiChatModel、ollamaChatModel,用 @Qualifier 注入指定实例。踩坑经验:第一,不同供应商的 Prompt 格式有差异,OpenAI 用 system/user/assistant 角色,有些国产模型角色名不同,需要测试兼容性;第二,国内模型 API 响应格式可能不完全遵循 OpenAI 标准,Spring AI 的适配层可能有 bug;第三,多模型同时引入时配置项可能冲突,建议用 Profile 隔离。面试加分:提到可以用 Spring AI 的 ChatClient 统一抽象层屏蔽底层差异,业务代码不感知具体模型。
【面试题】8. Spring AI 在微服务架构下部署,API Key 管理和限流熔断怎么做?
【标准答案】API Key 管理三原则:一是不硬编码,通过 Spring 的 Properties 外部化配置,配合 Config Server 或 Vault 注入;二是多 Key 轮换,当单个 Key 有 QPS 限制时,配置多个 Key 用策略轮换(随机或轮询),避免单 Key 被限流;三是 Key 权限最小化,只开通需要的模型和接口权限。限流熔断方面:Spring AI 本身没有内置限流,需要结合 Resilience4j 或 Sentinel。Resilience4j 的 RateLimiter 限制每秒对 AI 服务的调用次数,CircuitBreaker 在错误率超阈值时自动熔断走降级逻辑。降级策略可以是返回缓存答案、切换到更便宜的模型、或返回"服务繁忙请稍后"。另外一个实战点:不同模型 API 的限流规则不同,OpenAI 是 RPM+TPM 双重限制,Anthropic 按Tier分级,需要针对每个供应商单独配置限流参数。面试一句话:API Key 用外部配置+轮换,限流用 Resilience4j,降级要有兜底方案。
【面试题】9. Spring AI 的 VectorStore 接口统一了哪些向量库?选型时怎么考虑?
【标准答案】Spring AI 的 VectorStore 接口定义了 add、delete、similaritySearch 三个核心方法,已经适配了 PGVector、Redis、Pinecone、Chroma、Milvus、Weaviate 等。选型维度有四个:第一,数据规模——百万级以下 PGVector 就够,千万级以上考虑 Milvus 或 Pinecone;第二,部署方式——要私有化部署选 PGVector/Milvus/Chroma,接受 SaaS 选 Pinecone;第三,已有基础设施——已经用 PostgreSQL 了直接加 PGVector 扩展零运维成本,已有 Redis 可以复用但注意 Redis 的向量搜索性能不如专用库;第四,功能需求——需要元数据过滤、混合检索(向量+关键词)选 Milvus 或 Weaviate。面试关键点:强调 VectorStore 接口让你可以先用 PGVector 开发,后期无缝切换到 Milvus,业务代码零修改——这就是抽象层的价值。
【面试题】10. Spring AI 1.0 正式版相比之前的 Milestone 版本,有哪些核心变化?升级要注意什么?
【标准答案】核心变化五个方面:第一,ChatClient 成为统一入口,之前直接用 ChatModel 的方式虽然还能用但不再推荐,ChatClient 封装了所有高级能力;第二,Advisor 架构正式定型,之前是实验性的 Adviser(注意拼写从 Adviser 改成了 Advisor),接口和生命周期方法有调整;第三,VectorStore 接口统一,各向量库的实现类包路径有变化;第四,配置前缀统一为 spring.ai.*,之前的 spring.ai.openai.* 等前缀有细微调整;第五,依赖坐标从 milestone 仓库迁移到 Maven Central,不再需要配置额外的仓库地址。升级注意事项:一是 Advisor 接口签名变了,自定义 Advisor 要改代码;二是部分废弃 API 被移除,编译会报错,需要逐个替换;三是 Streaming API 有调整,流式响应的处理方式要适配;四是建议先在测试环境验证所有功能点再上线,尤其是 Function Calling 和 Structured Output 这两个变化较大的模块。