Skip to content

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 步骤:

  1. 实现 Advisor 接口,定义处理逻辑
  2. 注册为 @Bean 或通过构造器传入 ChatClient
  3. 指定 order 控制执行顺序(Ordered 接口或 @Order 注解)

典型应用场景:

  • 日志记录:记录请求响应、耗时统计
  • 内容审核:拦截敏感内容
  • 缓存:相同query直接返回缓存结果
  • 重试:模型调用失败自动重试
  • 自定义 RAG:注入检索结果到 Prompt

Spring AI 1.0 内置了 QuestionAnswerAdvisor(RAG)、MessageChatMemoryAdvisor(记忆)等,开箱即用。


【面试题】8. 多模型对接时,如何动态切换 OpenAI、智谱、Ollama 等不同模型? ​

【标准答案】 Spring AI 统一了 ChatModel 接口,切换方式:

方式一,配置文件切换(静态)

yaml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4

改配置重启应用,适合固定模型场景。

方式二,多 Bean 注入(运行时切换)

java
@Bean
ChatModel openaiChatModel() { ... }
@Bean
ChatModel zhipuChatModel() { ... }

// 注入时指定
@Autowired @Qualifier("zhipuChatModel") ChatModel chatModel;

方式三,动态路由(高级)

  • 定义 ChatModelRouter,根据用户ID、租户、任务类型选择模型
  • 配合 Spring 的 @Conditional 或 Profile 实现环境隔离

方式四,ChatClient 动态指定

java
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 响应怎么用?前端怎么接收流式输出? ​

【标准答案】 后端实现:

java
chatClient.prompt()
    .user("介绍一下Spring AI")
    .stream()
    .content()
    // 返回 Flux<String>

WebFlux 集成:

java
@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):

javascript
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题