Skip to content

Spring AI 面试题库 - 2026-05-24 21:03 ​

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

【面试题】1. Spring AI 的 ToolCallback 接口是什么?和 @Bean 注册 Function 有什么区别?什么时候用哪个? ​

【标准答案】ToolCallback 是 Spring AI 1.0 中函数注册的底层抽象接口,而 @Bean 注册 Function 是更高层的便捷方式。区别主要有三点:第一,@Bean 方式靠 Spring 容器自动发现,函数名默认取 Bean 名,描述靠 @Description 注解或函数名推导,简单但灵活度低;ToolCallback 可以精确控制函数名、描述、输入 Schema,适合需要精细定义的场景。第二,@Bean 注册的函数是全局的,所有 ChatClient 调用都能看到;ToolCallback 可以按调用级别传入,实现"这次对话只暴露这3个工具"的动态控制。第三,ToolCallback 支持 toolContext 上下文传递,可以在函数执行时拿到调用方传入的额外信息,@Bean 方式做不到。实际项目中,简单的查询类工具用 @Bean 就够,需要动态工具列表、上下文传递、精细 Schema 控制的场景必须用 ToolCallback。

【面试题】2. Spring AI 的评估(Evaluation)机制怎么用?如何量化评估 RAG 的检索质量和生成质量? ​

【标准答案】Spring AI 提供了 spring-ai-evaluation 模块,核心是基于 LLM 自身做评估的思路。关键组件有两个:RelevanceEvaluator 评估检索相关性——给定问题和检索到的文档,让 LLM 判断文档是否真的和问题相关;FaithfulnessEvaluator 评估生成忠实度——给定上下文和生成答案,判断答案是否只基于上下文、有没有幻觉。用法很简单,注入 EvaluatingChatModel 后调用 evaluate() 方法,返回的是评分结果。实际落地建议:一是建一套标准测试集(问题+标准答案+相关文档),每次改 RAG 参数或换模型都跑一遍对比;二是别只看检索 top-K 的相似度分数,一定要加 RelevanceEvaluator 做"二次校验",因为向量相似度高不等于语义相关;三是 FaithfulnessEvaluator 是防线,特别是金融、医疗等对幻觉零容忍的场景必须上。评估不是一次性的,是持续性的,每次知识库更新都应该重新评估。

【面试题】3. Spring AI 的 DocumentReader 和 DocumentTransformer 管线如何设计?PDF、Word、Markdown 等多格式文档如何统一处理? ​

【标准答案】Spring AI 把文档处理拆成 Reader → Transformer → Writer 三段管线。Reader 负责把不同格式读成统一的 Document 对象(含 content + metadata),比如 PdfDocumentReader 读 PDF、TextDocumentReader 读纯文本、MarkdownDocumentReader 读 Markdown。Transformer 负责清洗和切分,TokenTextSplitter 就是最常用的 Transformer。多格式统一处理的核心设计是:第一,不同 Reader 产出统一的 Document 列表,后续管线完全不用关心源格式;第二,metadata 中保留来源信息(文件名、页码、章节),检索时可以溯源;第三,实际项目建议用工厂模式根据文件后缀自动选 Reader,组合成统一管线。踩坑点:PDF 的表格和图片用 PdfDocumentReader 可能丢失,复杂 PDF 建议先 OCR 再灌入;Word 文档的样式层级要映射到 metadata 的 section 字段,方便后续按章节检索;Markdown 的代码块和标题层级是最友好的,优先考虑 Markdown 作为中间格式。

【面试题】4. Spring AI 的 Advisor 链中,RequestAdvisor 和 ResponseAdvisor 的执行顺序是怎样的?多个 Advisor 之间如何协调? ​

【标准答案】Advisor 在 Spring AI 1.0 中分为两个方向:Request 阶段(拦截请求发给模型之前)和 Response 阶段(拦截模型返回的响应)。执行顺序是——Request 阶段按添加顺序正序执行(先加的先执行),Response 阶段反序执行(后加的先执行),形成洋葱模型。比如 .advisors(memoryAdvisor, loggingAdvisor, ragAdvisor),请求时是 memory → logging → rag 依次增强 Prompt,响应时是 rag → logging → memory 依次处理返回。协调的关键点:一是顺序很重要,MemoryAdvisor 要放最前面(先加载历史上下文),RAG Advisor 放后面(在完整上下文基础上检索);二是 Advisor 之间通过 AdvisedRequest 和 AdvisedResponse 传递数据,可以用 context 字段共享中间结果;三是 Response 阶段的 Advisor 可以短路,比如安全脱敏 Advisor 发现敏感信息可以直接修改响应不再传递。自定义 Advisor 时实现 CallAroundAdvisor 或 StreamAroundAdvisor,在 aroundCall/aroundStream 方法里做拦截逻辑。

【面试题】5. Spring AI 对接 Anthropic Claude 时有哪些特殊配置和注意事项?和 OpenAI 的 ChatModel 实现有哪些关键差异? ​

【标准答案】对接 Claude 要引入 spring-ai-anthropic 依赖,配置前缀是 spring.ai.anthropic。和 OpenAI 的关键差异有四点:第一,Claude 支持 System Message 但实现方式不同——OpenAI 的 system message 是独立的 role,Claude 在 Spring AI 中也是通过 SystemMessage 处理,但底层 API 格式有差异,Spring AI 做了适配;第二,Claude 的 maxTokens 参数是必填的,OpenAI 是可选的,不设会报错;第三,Claude 支持的 tool_choice 策略和 OpenAI 不完全一致,Claude 更倾向于让模型自主决定是否调工具;第四,Claude 的上下文窗口更大(200K),但 temperature 范围是 0-1,OpenAI 可以到 2。注意事项:Claude 的 API 响应速度比 OpenAI 稍慢,流式输出需要配置 stream 选项;Claude 对 System Prompt 的长度没有硬限制但太长会影响质量;费用方面 Claude 3.5 Sonnet 性价比不错,建议作为 OpenAI 的备选做路由切换。

【面试题】6. Spring AI 的 VectorStore 中 metadata filtering 的语法是什么?如何实现多条件组合过滤? ​

【标准答案】VectorStore 的 similaritySearch 方法支持通过 FilterExpressionBuilder 构建元数据过滤条件。基本语法:FilterExpressionBuilder b = new FilterExpressionBuilder(); b.eq("category", "tech") 表示 category 等于 "tech";b.gt("year", 2024) 表示 year 大于 2024。多条件组合用 and/or:b.eq("category", "tech").and(b.gte("year", 2024)) 表示同时满足两个条件。支持的运算符有 eq(等于)、ne(不等于)、gt/gte(大于/大于等于)、lt/lte(小于/小于等于)、in(包含于)、nin(不包含于)、regex(正则匹配)。实际用法:vectorStore.similaritySearch(SearchRequest.query("微服务").withTopK(5).withFilterExpression(filter))。踩坑点:第一,metadata 的值类型要一致,"2024"字符串和 2024 数字是不同的;第二,不是所有 VectorStore 实现都支持所有运算符,PGVector 支持最全,Redis 有部分限制,Chroma 的 in 操作有数量上限;第三,过滤条件太复杂会显著拖慢检索速度,建议在 metadata 中做冗余字段预计算,减少运行时复杂过滤。

【面试题】7. Spring AI 的 Structured Output 中,MapOutputConverter 和 ListOutputConverter 分别适合什么场景?和 BeanOutputConverter 怎么选? ​

【标准答案】Spring AI 提供三种结构化输出 Converter:BeanOutputConverter 最强,能直接映射到 Java POJO,有完整的 JSON Schema 约束;MapOutputConverter 把输出解析成 Map<String, Object>,适合结构不确定或动态字段的场景;ListOutputConverter 把输出解析成 List<String>,适合提取枚举值、标签列表等简单场景。选择依据:如果输出结构固定、有明确的 Java 类型对应,必须用 BeanOutputConverter,类型安全且有编译期检查;如果输出字段是动态的(比如用户自定义表单的提取结果),用 MapOutputConverter 更灵活;如果只是提取一组关键词、分类标签,ListOutputConverter 最轻量。关键坑点:MapOutputConverter 和 ListOutputConverter 没有 Schema 约束,模型输出格式不稳定时容易解析失败,建议在 Prompt 中用 few-shot 示例明确输出格式。BeanOutputConverter 的 Schema 会自动注入 Prompt,稳定性最高,能用就优先用。

【面试题】8. Spring AI 的 ChatMemory 如何实现滑动窗口策略?多轮对话历史无限增长会导致什么问题? ​

【标准答案】多轮对话历史无限增长有两个致命问题:一是 Token 超限导致 API 报错,大多数模型上下文窗口是 4K-128K Token,历史消息很容易撑爆;二是历史太长模型注意力分散,回复质量下降。Spring AI 的 MessageChatMemoryAdvisor 支持滑动窗口策略——通过设置 maxMessages 参数控制保留最近 N 轮对话。比如 .advisors(MessageChatMemoryAdvisor.builder(chatMemory).maxMessages(10).build()) 表示只保留最近10条消息。更精细的策略可以自定义 ChatMemory 实现:一是基于 Token 计数的窗口(按 Token 数而非消息数截断,更精确但需要 Tokenizer 配合);二是摘要压缩策略(超过阈值后让 LLM 对旧对话做摘要,用摘要替代原文,保留关键信息又节省 Token);三是混合策略(最近 N 轮原文 + 早期摘要)。生产环境建议:简单场景用 maxMessages 就够,复杂长对话用摘要压缩,ChatMemory 持久化到 Redis/数据库时同时存储对话元数据(Token 数、时间戳),方便做精细化淘汰。

【面试题】9. Spring AI 的 FunctionCallbackContext 是什么?如何实现运行时动态注册和注销工具函数? ​

【标准答案】FunctionCallbackContext 是 Spring AI 管理 Function Calling 工具的注册中心。默认情况下,@Bean 注册的函数在应用启动时就固定了,但实际项目经常需要动态管理——比如不同租户看到不同工具、运行时根据权限增减工具。实现动态注册有两种方式:第一,手动构建 FunctionCallback 并通过 ChatClient.tools() 方法按调用级别传入,每次调用指定不同的工具集,这是最灵活的方式;第二,自定义 FunctionCallbackContext 实现类,覆写获取函数列表的逻辑,比如从数据库或配置中心读取当前可用的工具列表。动态注销的典型场景:多租户 SaaS 中,A 租户只能用"查订单"工具,B 租户还能用"退款"工具,在 FunctionCallbackContext 层根据租户 ID 过滤即可。注意事项:动态注册的函数没有 Spring 容器管理依赖注入,工具类内部需要的 Bean 要手动传入;频繁动态注册/注销要考虑缓存,避免每次调用都重新查库;工具函数的 Schema 变化后要确保和大模型已知的工具列表同步。

【面试题】10. Spring AI 在 Kubernetes 环境下部署,如何实现模型服务的弹性伸缩和高可用?有哪些关键配置? ​

【标准答案】K8s 部署 Spring AI 应用关注三个维度:弹性伸缩、高可用、配置管理。弹性伸缩方面:基于 QPS 做 HPA(Horizontal Pod Autoscaler),Spring AI 的 Micrometer 指标暴露给 Prometheus,配合 Pod 自定义指标做弹性伸缩比 CPU 更精准;VectorStore 如果用 PGVector,数据库层单独部署 StatefulSet,AI 应用层用 Deployment 无状态扩缩容。高可用方面:多副本部署,Pod 反亲和打散到不同节点;模型调用做故障转移,配置多个 ChatModel Bean + 自定义路由策略,OpenAI 挂了自动切智谱;VectorStore 做读写分离,PGVector 主从复制或 Milvus 集群模式。关键配置:spring.ai.openai.connect-timeout 和 read-timeout 要设合理值(建议 connect 5s、read 60s),避免 K8s 中网络抖动导致级联超时;资源限制要给够,AI 应用做 Embedding 计算时 CPU 峰值很高;ConfigMap 管理 spring.ai.* 配置,Secret 管理 API Key,不要进镜像;健康检查端点 /actuator/health 要包含 VectorStore 连通性检查,避免流量打到连不上向量库的 Pod。