Skip to content

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

【面试题】1. Spring AI 中 ChatClient 和 ChatModel 有什么区别?什么场景用哪个? ​

【标准答案】 区别:ChatModel 是底层模型接口,负责和 AI 模型直接交互,你传 Prompt 它返回 ChatResponse,偏底层。ChatClient 是 1.0 新增的高层门面,内部封装了 ChatModel,提供了流式 API、Advisor 链、自动重试、错误处理等能力。

选型:

  • 用 ChatModel:只需要简单调用模型、对响应格式没特殊要求、想完全控制请求细节
  • 用 ChatClient:需要流式输出、要加 Advisor(比如 RAG、Memory)、要统一错误处理、要构建复杂对话流程

实战建议:新项目直接用 ChatClient,它是对 ChatModel 的增强封装,功能更全、代码更简洁。除非有特殊定制需求,否则不用直接操作 ChatModel。

【面试题】2. Spring AI 的 Advisor 机制是什么?能解决什么问题? ​

【标准答案】 定义:Advisor 是 Spring AI 的拦截器模式,每个 Advisor 可以在请求发往模型前、响应返回后插入自定义逻辑。类似 Spring MVC 的 Interceptor 或 AOP。

核心能力:

  • 请求预处理:改 Prompt、加系统提示、注入上下文
  • 响应后处理:格式转换、结果过滤、日志记录
  • 链式调用:多个 Advisor 顺序执行,责任链模式

典型应用:

  • QuestionAnswerAdvisor:自动从向量库检索相关文档,注入到 Prompt,实现 RAG
  • MessageChatMemoryAdvisor:自动管理历史消息,实现对话记忆
  • 日志监控 Advisor:记录每个请求的耗时、token 消耗

代码示例:

java
ChatClient.builder(chatModel)
    .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
    .build();

【面试题】3. RAG 中的 TokenTextSplitter 怎么设置分块大小?有什么坑? ​

【标准答案】 设置原则:

  • 默认值:默认 800 token,重叠 100 token
  • 调整依据:根据向量模型的最大输入长度(比如 OpenAI text-embedding-3-small 最大 8191 token)和业务文档特点来定
  • 经验值:问答场景 500-1000 token,长文档总结 1000-2000 token

常见坑:

  1. 切在句子中间:导致语义割裂,检索召回率下降 → 解决:用递归分割器,先按段落再按句子
  2. 分块太大:超出向量模型限制,或者召回太多噪音 → 解决:控制在模型上限的 80% 以内
  3. 分块太小:上下文不足,回答质量差 → 解决:适当增加 overlap,保留上下文
  4. 忽略中英文差异:中文 token 计数和英文不同 → 解决:实际测试 token 数,别只看字符数

代码示例:

java
TokenTextSplitter splitter = new TokenTextSplitter(
    500,  // targetChunkSize
    100,  // overlap
    5,    // minChunkSize
    10000 // maxNumChunks
);

【面试题】4. Spring AI 的 Function Calling 是怎么实现的?整个调用流程是什么? ​

【标准答案】 核心原理:Spring AI 自动把带 @Bean 的方法转成 JSON Schema,传给模型。模型判断需要调用函数时返回 tool_call 指令,框架自动执行函数,把结果回传模型继续推理。

完整流程:

  1. 注册函数:定义 @Bean 方法,Spring AI 扫描并生成 JSON Schema
  2. 发起请求:ChatClient 把函数描述加入请求的 tools 字段
  3. 模型决策:模型分析用户问题,决定是否需要调用函数
  4. 返回 tool_call:模型返回函数名 + 参数(JSON 格式)
  5. 框架执行:Spring AI 自动解析参数,调用对应方法,拿到返回值
  6. 回传结果:把执行结果追加到消息历史,再次调用模型
  7. 最终回答:模型基于函数返回结果生成最终答案

关键点:

  • 函数参数用 POJO 定义,Spring AI 自动映射
  • 返回值会序列化成 JSON 字符串传给模型
  • 可以配置 toolChoice 强制调用或让模型自主选择

【面试题】5. Spring AI 支持哪些向量数据库?选型时怎么选? ​

【标准答案】 官方支持:PGVector、Redis、Pinecone、Chroma、Milvus、Weaviate、Qdrant、MongoDB Atlas、Oracle 等 10+ 种。

选型维度:

  1. 开发环境:PGVector(直接用现有 PostgreSQL)、Chroma(嵌入式,零配置)
  2. 生产环境:
    • 中小规模:PGVector(运维简单,已有 PG 基础设施)、Redis(高性能,但需要 Redis Stack)
    • 大规模:Milvus(分布式,性能强)、Pinecone(全托管,零运维)
  3. 云厂商绑定:AWS 选 OpenSearch,阿里云选 Milvus/Hologres
  4. 成本考虑:PGVector/Chroma 开源免费,Pinecone 按量付费

实战建议:

  • 开发阶段用 Chroma 或 PGVector,快速验证
  • 生产环境优先 Milvus(开源生态好)或 Pinecone(托管省心)
  • 代码层面用 VectorStore 接口,方便切换实现

【面试题】6. Spring AI 的 Structured Output 怎么用?有什么限制? ​

【标准答案】 用法:通过 BeanOutputConverter 把模型输出映射成 POJO,自动校验字段类型和格式。

代码示例:

java
ChatResponse response = chatClient.prompt()
    .user("提取用户信息")
    .call()
    .chatResponse();

UserEntity user = new BeanOutputConverter<>(UserEntity.class)
    .fromEntity(response.getResult().getOutput().getContent());

关键限制:

  1. 模型支持:不是所有模型都支持,OpenAI GPT-4、Claude 3.5 支持最好,国内模型部分支持
  2. Schema 复杂度:嵌套层级太深可能解析失败,建议控制在 3 层以内
  3. 字段校验:框架只做类型校验,业务逻辑校验需要自己实现
  4. 错误处理:模型输出不符合 Schema 时会抛异常,需要 try-catch 并降级处理

最佳实践:

  • POJO 字段加 @JsonProperty 和 @JsonPropertyDescription,提升模型理解
  • 必填字段用包装类型,避免 null 问题
  • 提供示例值,引导模型输出正确格式

【面试题】7. Chat Memory 怎么实现持久化?线上环境用什么方案? ​

【标准答案】 接口设计:Spring AI 提供 ChatMemory 接口,核心方法是 add(message) 和 get(conversationId, lastN)。

持久化方案:

  1. Redis:适合高并发场景,天然支持 TTL 自动清理过期对话
    java
    public class RedisChatMemory implements ChatMemory {
        // 用 Redis List 存储,conversationId 作 key
    }
  2. 数据库:适合需要查询分析的场景,存 MySQL/MongoDB
  3. 混合方案:热数据存 Redis,冷数据定期归档到数据库

关键考虑:

  • 存储限制:对话历史太长占内存和 token,需要限制 lastN(比如最近 10 轮)
  • 并发控制:多实例部署时用分布式锁,避免消息顺序错乱
  • 隐私合规:敏感对话需要加密存储,或定期清理

线上建议:Redis + 定时清理任务,控制单次对话历史在 20-30 条以内。

【面试题】8. Spring AI 1.0 正式版有哪些重要更新?和 M 系列版本有什么区别? ​

【标准答案】 核心变化:

  1. ChatClient 统一入口:M 系列用 ChatModel 直接调用,1.0 推荐 ChatClient,统一流式和非流式 API
  2. Advisor 架构:1.0 引入 Advisor 机制,实现了 RAG、Memory 等能力的模块化插拔
  3. 配置前缀统一:从 spring.ai.openai.api-key 改为 spring.ai.openai.api-key,所有模型配置统一前缀
  4. VectorStore 接口标准化:1.0 定义了统一的向量库操作接口,切换实现只需改依赖和配置
  5. Observability 增强:集成 Micrometer,提供 token 消耗、耗时、错误率等指标

迁移要点:

  • M 系列的 ChatModel.call(prompt) → 1.0 用 ChatClient.prompt().user(text).call()
  • 手动实现的 RAG 逻辑 → 改用 QuestionAnswerAdvisor
  • 自定义配置前缀 → 统一改成 spring.ai.*

建议:新项目直接上 1.0,M 系列老项目评估迁移成本,核心功能不受影响。

【面试题】9. Spring AI 如何实现多模型切换?配置怎么管理? ​

【标准答案】 实现方式:

  1. 配置文件切换:修改 spring.ai.model 或具体模型配置,重启生效

    yaml
    spring:
      ai:
        openai:
          api-key: ${OPENAI_API_KEY}
          chat:
            options:
              model: gpt-4-turbo
  2. 运行时切换:注入不同的 ChatModel Bean,按业务选择

    java
    @Autowired @Qualifier("openAiChatModel") ChatModel openAiModel;
    @Autowired @Qualifier("zhipuChatModel") ChatModel zhipuModel;
    
    ChatModel model = useZhipu ? zhipuModel : openAiModel;
  3. 动态路由:根据请求参数、用户等级、成本控制自动选模型

    java
    public ChatModel selectModel(Request request) {
        if (request.isPremium()) return gpt4Model;
        if (request.isLowCost()) return localOllamaModel;
        return defaultModel;
    }

配置管理:

  • 多环境:用 Spring Profile 区分 dev/test/prod 配置
  • 密钥管理:API Key 从环境变量或 Vault 读取,别写死在配置文件
  • 成本控制:高成本模型(GPT-4)限流,低成本模型(Ollama 本地)兜底

【面试题】10. Spring AI 的 Streaming 流式响应怎么实现?前端怎么对接? ​

【标准答案】 后端实现:

java
Flux<String> stream = chatClient.prompt()
    .user("写一首诗")
    .stream()
    .content();  // 返回 Flux<String>

// WebFlux 直接返回
return ResponseEntity.ok()
    .contentType(MediaType.TEXT_EVENT_STREAM)
    .body(stream);

关键点:

  • stream() 方法返回 Flux<ChatResponse>,可以用 .content() 提取纯文本
  • 需要依赖 spring-boot-starter-webflux
  • 超时设置:流式请求可能很慢,配置合理的超时时间

前端对接:

javascript
const eventSource = new EventSource('/api/chat/stream');
eventSource.onmessage = (event) => {
    document.getElementById('output').textContent += event.data;
};
eventSource.onerror = () => eventSource.close();

注意事项:

  • 用 SSE(Server-Sent Events)协议,前端 EventSource 自动重连
  • 长连接问题:Nginx/网关需要配置超时时间,避免中断
  • 错误处理:流式返回中可能包含错误,需要解析并提示用户