Skip to content

本轮 Spring AI 面试题库(带答案)

【面试题】1. Spring AI 1.0中ChatClient统一入口相比直接使用ChatModel有哪些优势? ​

【标准答案】ChatClient是Spring AI 1.0推荐的高层API,优势主要体现在三点:第一是Fluent API链式调用,代码更简洁优雅,比如chatClient.prompt().user("你好").call().content()一行搞定;第二是内置Advisor机制,可以在请求前后插入切面逻辑,比如自动添加系统提示、对话记忆、RAG检索等;第三是与Spring生态深度集成,支持自动配置、依赖注入,配置项统一在spring.ai.*前缀下。而ChatModel是底层抽象,需要手动处理更多细节。简单说,ChatClient是"开箱即用"的门面,ChatModel是"底层引擎",面试时建议强调实际项目中优先使用ChatClient。

【面试题】2. Advisor机制在Spring AI中是如何工作的?执行顺序是怎样的? ​

【标准答案】Advisor是Spring AI的AOP切面机制,核心是CallAroundAdvisor和StreamAroundAdvisor两个接口。执行顺序遵循"洋葱模型":请求阶段按注册顺序正向执行,响应阶段逆向执行。比如注册了Advisor A和B,请求链是A前→B前→调用模型→B后→A后。典型应用场景:MessageChatMemoryAdvisor在请求前注入历史对话、QuestionAnswerAdvisor在请求前做RAG检索。通过@Order注解或getOrder()方法控制顺序,数值小的先执行。面试重点:Advisor不侵入业务代码,实现了横切关注点的解耦,是Spring AI架构设计的亮点。

【面试题】3. Spring AI的Function Calling中,@Bean注册的函数是如何被模型发现和调用的? ​

【标准答案】流程分四步:第一步,开发者用@Bean定义一个返回类型为Function<I,O>的bean,Spring AI自动扫描注册到FunctionCallbackRegistry;第二步,在ChatClient调用时通过.functions("funcName")指定可用函数;第三步,Spring AI根据函数签名自动生成JSON Schema,随请求发送给模型,模型据此知道有哪些工具可用;第四步,模型返回tool_call时,Spring AI自动反序列化参数、执行函数、将结果回传给模型继续对话。关键点:JSON Schema自动生成省去了手动定义的繁琐,整个调度对开发者透明。面试加分项:提一句可以用FunctionCallback.builder()自定义函数描述和参数schema。

【面试题】4. RAG场景中TokenTextSplitter的作用是什么?有哪些关键参数需要调优? ​

【标准答案】TokenTextSplitter负责将长文档切分成适合向量化的文本块。核心作用是让每个chunk不超过embedding模型的token限制,同时保持语义完整性。关键参数有三个:defaultChunkSize控制每个块的最大token数,一般500-1000;defaultOverlapSize是块之间的重叠token数,保证跨块语义不丢失,通常50-200;keepSeparator是否保留分隔符。调优思路:chunk太大→检索粒度粗、召回不精准;chunk太小→上下文丢失、需要更多overlap补救。面试建议结合实际项目说,比如技术文档用800/100,FAQ类短文档用300/50。还要提一句:TokenTextSplitter基于tiktoken计算token数,比简单按字符切分更准确。

【面试题】5. Spring AI支持哪些VectorStore?它们的选型依据是什么? ​

【标准答案】Spring AI 1.0统一了VectorStore接口,主流实现包括:PGVector(PostgreSQL扩展,适合已有PG基础设施)、Redis(高性能、支持混合查询)、Pinecone(全托管、免运维)、Chroma(轻量级、适合快速原型)、Milvus(开源、支持大规模向量)。选型考虑四点:第一,数据规模,百万级以上推荐Milvus或Pinecone;第二,运维成本,不想管基础设施选Pinecone;第三,查询复杂度,Redis支持向量+关键词混合查询;第四,团队技术栈,���有PostgreSQL就别另起炉灶。面试加分:提一句Spring AI的VectorStore接口让切换成本极低,配置文件改一行就能换实现。

【面试题】6. BeanOutputConverter在结构化输出中的原理是什么?有哪些常见坑? ​

【标准答案】BeanOutputConverter利用JSON Schema将LLM输出映射为Java POJO。原理:通过反射分析POJO字段,生成对应的JSON Schema,作为prompt的一部分约束模型输出;模型返回JSON后,用ObjectMapper反序列化为对象。常见坑有三个:第一,字段名不匹配,默认用Java字段名,需要@JsonProperty注解映射;第二,枚举类型处理不当,模型可能返回不在枚举中的值,需要@JsonCreator兜底;第三,复杂嵌套对象schema生成不准确,建议用BeanOutputConverter.builder()手动定制schema。面试建议:强调schema是"指导"而非"强制",模型可能不遵守,重要字段要做后置校验。

【面试题】7. ChatMemory的InMemoryChatMemory实现有什么局限?生产环境如何持久化? ​

【标准答案】InMemoryChatMemory是Spring AI内置的内存实现,优点是简单、零配置;缺点是应用重启丢失、单机无法跨实例共享。生产环境持久化方案有三类:第一,数据库存储,自定义实现ChatMemory接口,将对话历史存入MySQL/PostgreSQL的JSON字���;第二,Redis存储,用Redis List或Stream存储,天然支持TTL过期;第三,VectorStore混合方案,把重要对话向量化后存入向量库,支持语义检索历史。面试关键点:ChatMemory是接口,Spring AI没有内置持久化实现,需要自己写或用社区方案。MessageChatMemoryAdvisor负责在请求前从ChatMemory加载历史、请求后保存新消息,两者配合完成对话记忆闭环。

【面试题】8. 如何在Spring AI中实现多模型切换?配置前缀spring.ai.*如何工作? ​

【标准答案】Spring AI 1.0统一了配置前缀spring.ai.*,不同模型通过spring.ai.<provider>区分。比如spring.ai.openai.api-key、spring.ai.ollama.base-url、spring.ai.zhipuai.api-key。切换方式有三层:第一层,配置文件切换,改spring.ai.chat.model指定默认模型;第二层,代码动态切换,通过ChatClient.builder().defaultModel("modelName")覆盖;第三层,运行时切换,chatClient.prompt().model("gpt-4").call()指定单次请求模型。面试要点:强调Spring AI的统一抽象让切换成本极低,改配置就能换供应商,不被单一模型绑定。加分项:提一句可以用ChatModel接口多实现,结合@Qualifier注入不同模型的bean。

【面试题】9. QuestionAnswerAdvisor在RAG流程中做了什么?与手动实现RAG有什么区别? ​

【标准答案】QuestionAnswerAdvisor是Spring AI内置的RAG Advisor,封装了"检索-增强-生成"的完整流程。工作原理:请求前调用VectorStore.similaritySearch(query)检索相关文档,将检索结果注入prompt作为上下文,然后调用模型生成答案。与手动实现RAG的区别:手动实现需要自己写检索、拼接prompt、调用模型三步,代码分散;QuestionAnswerAdvisor一行配置搞定,chatClient.prompt().advisors(new QuestionAnswerAdvisor(vectorStore)).call()。面试重点:它只是简化,不是替代,复杂RAG场景(如多轮检索、混合检索、重排序)还是需要自定义Advisor。加分项:提一句可以通过构造函数传入自定义的SearchRequest定制检索参数。

【面试题】10. Spring AI的Streaming响应如何处理?与同步调用有什么区别? ​

【标准答案】Streaming响应通过chatClient.prompt().stream().content()获取,返回Flux<String>(响应式流),可以逐token接收模型输出。与同步调用call().content()的区别:同步调用等待完整响应返回,适合短文本、无需实时反馈的场景;Streaming适合长文本生成、聊天界面实时打字效果、降低首字延迟。技术细节:底层使用WebFlux的响应式编程模型,支持背压(backpressure)控制流速。面试加分:��一句Streaming需要配合前端SSE或WebSocket,后端直接返回Flux,框架自动转换为流式响应。坑点:Streaming模式下Advisor的aroundStream方法生效,用错aroundCall会不执行。