本轮 Spring AI 面试题库(带答案)
【面试题】1. Spring AI中ChatClient和直接使用ChatModel有什么区别?实际项目中如何选择?
【标准答案】ChatModel是底层模型接口,直接调用API,适合简单场景。ChatClient是Spring AI 1.0推出的统一入口,内置了Prompt模板、Advisor链、Memory管理、Structured Output等高级能力,API更流畅。
实际项目中:简单问答用ChatModel足够,但涉及RAG、Function Calling、对话历史、结构化输出时,ChatClient一行代码搞定,不需要手动拼接。推荐默认用ChatClient,只有极致性能需求才降级到ChatModel。
【面试题】2. Spring AI的Advisor机制是什么?能解决哪些问题?
【标准答案】Advisor是拦截器模式,可以在请求前后插入自定义逻辑。Spring AI内置了QuestionAnswerAdvisor(RAG检索)、MessageChatMemoryAdvisor(对话记忆)、SafeGuardAdvisor(安全过滤)等。
解决的问题:统一的横切关注点处理,比如检索增强、历史注入、内容过滤、日志追踪,不用每个业务方法重复写。自定义Advisor只需实现RequestResponseAdvisor接口,重写adviseRequest和adviseResponse方法,然后加入ChatClient的advisor链即可。
【面试题】3. VectorStore选型时,PGVector、Redis、Pinecone、Chroma、Milvus各有什么优劣势?
【标准答案】PGVector:依托PostgreSQL,部署简单,适合中小规模、已有PG基础设施的场景,但大规模向量检索性能一般。
Redis:内存级速度,适合实时性要求高的推荐系统,但容量受限、持久化需配置。
Pinecone:全托管,零运维,扩展性好,但成本较高、数据不在本地。
Chroma:轻量级嵌入式向量库,适合开发测试、小规模应用,生产环境需自己管理持久化。
Milvus:开源分布式向量库,支持亿级向量,适合大规模生产场景,但部署运维成本高。
选型建议:开发用Chroma/PGVector快速验证,生产根据规模选择Redis(小中型)、Milvus(大规模)、Pinecone(不想运维)。
【面试题】4. Spring AI的Function Calling底层是如何工作的?@Bean注册函数后发生了什么?
【标准答案】流程分四步:
Spring AI扫描所有@Bean标记的Function,通过Jackson自动生成JSON Schema(参数名、类型、描述)。
用户提问时,LLM判断是否需要调用工具,返回tool_call指令(函数名+参数)。
Spring AI自动执行函数,拿到返回值作为上下文。
将函数结果回传给LLM,生成最终回答。
@Bean函数需要满足:返回值类型明确,参数用record或POJO定义,可选添加@Description注解提供工具描述。Spring AI的ChatClient会在内部自动处理整个调度流程,开发者只需关注业务逻辑。
【面试题】5. 实际项目中如何实现Spring AI的多模型动态切换?配置怎么管理?
【标准答案】两种方式:
方式一:配置文件切换,通过spring.ai.openai.api-key、spring.ai.ollama.base-url等配置,结合Spring Profile实现不同环境用不同模型。
方式二:运行时切换,注入ChatModel接口,通过@Qualifier指定具体实现,或者自定义路由策略,根据请求类型(简单问答用Ollama本地模型、复杂推理用GPT-4、代码生成用Claude)动态选择。
推荐做法:核心业务逻辑依赖ChatModel抽象接口,具体实现通过配置+条件注入切换,避免硬编码绑定单一模型,方便降级和成本优化。
【面试题】6. BeanOutputConverter实现结构化输出时有哪些常见坑?如何规避?
【标准答案】常见坑:
POJO必须有无参构造器,否则反序列化失败。
字段必须是public或有getter/setter,Jackson才能识别。
嵌套对象的Schema可能生成不完整,建议手动指定@JsonClassDescription。
LLM可能返回不符合Schema的JSON,需要异常捕获+重试。
枚举类型需要明确描述可选值,否则LLM可能瞎编。
规避方法:使用record定义输出对象,字段加@Description注解,复杂场景用entity()方法显式指定Schema,生产环境加校验层确保数据合法。
【面试题】7. Spring AI的Chat Memory如何实现对话历史持久化?生产环境推荐什么方案?
【标准答案】内置的InMemoryChatMemory只适合单机测试,重启丢失。生产环境需要自己实现ChatMemory接口的持久化方案:
方案一:Redis存储,按sessionId为key,消息列表为value,设置过期时间自动清理。
方案二:数据库存储,设计conversation_message表,关联用户ID和会话ID,支持查询历史对话。
方案三:结合Spring AI的MessageChatMemoryAdvisor,在adviseRequest时从持久化存储加载历史,adviseResponse时保存新消息。
推荐方案:短期会话用Redis(性能好),长期归档用数据库(可审计),同时设置消息数量上限避免上下文过长。
【面试题】8. Spring AI 1.0相比之前版本有哪些重大变化?为什么要升级?
【标准答案】核心变化:
ChatClient统一入口:替代原来的PromptTemplate+ChatModel组合,API更简洁流畅。
Advisor架构标准化:所有横切能力(RAG、Memory、安全)统一通过Advisor链扩展。
VectorStore接口统一:不同向量库实现同一接口,切换成本低。
spring.ai.*配置前缀:所有配置项统一前缀,解决之前版本配置混乱问题。
Structured Output增强:BeanOutputConverter支持更复杂类型,entity()方法直接映射。
升级理由:更规范的架构、更少的样板代码、更好的扩展性,Spring AI 1.0是稳定生产版本,后续版本会在此基础上迭代。
【面试题】9. 在微服务架构下,Spring AI的API Key如何安全管理?有哪些最佳实践?
【标准答案】绝对不能硬编码在代码里。推荐方案:
环境变量注入:spring.ai.openai.api-key=${OPENAI_API_KEY},容器启动时传入。
配置中心管理:结合Spring Cloud Config或Nacos,集中管理不同环境的密钥。
密钥管理服务:生产环境用Vault或云厂商的KMS,密钥加密存储,运行时动态获取。
网关层代理:所有AI请求走统一网关,网关负责注入API Key,后端服务无需感知。
密钥轮换:定期更新密钥,支持平滑切换,避免单点泄露风险。
最佳实践:最小权限原则,不同服务用不同密钥,日志脱敏,监控异常调用,配额限流防止密钥被盗刷。
【面试题】10. Spring AI的Streaming响应如何实现?有哪些性能优化技巧?
【标准答案】Streaming用ChatClient的stream()方法返回Flux<String>,支持响应式流式输出。
实现步骤:调用chatClient.prompt().user(question).stream().content(),拿到Flux后用WebFlux的ServerSentEvent推给前端。
性能优化:
连接复用:保持HTTP长连接,避免每次请求重建连接。
背压控制:根据客户端消费速度调节推送速率,避免内存溢出。
超时设置:合理配置spring.ai.openai.timeout,防止慢请求堆积。
熔断降级:异常时返回预设回复,不影响整体体验。
监控指标:用Micrometer记录请求延迟、Token消耗、错误率,及时发现问题。
实际项目中,Streaming比一次性返回响应感知更快,但需要处理好异常和超时逻辑。