Skip to content

Spring AI 面试题库(2026-05-21 21:32) ​

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

【面试题】1. Spring AI 的 ChatClient 与传统 ChatModel 有什么本质区别?为什么推荐用 ChatClient? ​

【标准答案】ChatModel 是底层模型接口,直接对接各家 AI 服务商的 API。而 ChatClient 是 Spring AI 1.0 引入的统一高级抽象,提供了 fluent API 风格的调用方式,内置了 Prompt 模板、Advisor 链、ChatMemory 集成等能力。

核心区别:

  • ChatModel 是"裸模型",你得自己拼 Prompt、管理历史、处理响应
  • ChatClient 是"带上下文的智能客户端",一行代码搞定模板渲染 + 记忆注入 + 响应处理

为什么推荐 ChatClient:

  • 代码更简洁:.prompt().user("问").call().content() vs 手动拼 Prompt
  • 内置 Advisor 机制:自动注入对话记忆、RAG 增强、工具调用
  • 易于切换模型:改配置就行,不用改代码
  • Spring AI 1.0 官方推荐,后续新特性都围绕 ChatClient 展开

实战中,ChatModel 适合简单场景或需要精细控制的底层调用;ChatClient 适合业务开发,快速落地 AI 能力。


【面试题】2. Advisor 机制是什么?Spring AI 1.0 中的 Advisor 与拦截器、Filter 有啥区别? ​

【标准答案】Advisor 是 Spring AI 的请求增强机制,可以在 Prompt 发送给模型前后插入自定义逻辑。

本质理解:

  • Advisor = Prompt 增强器 + 响应处理器
  • 类似 Spring MVC 的拦截器,但专注于 AI 场景

与拦截器/Filter 的区别:

  • 作用域:Advisor 只作用于 ChatClient 的 AI 调用链;拦截器是 Web 层面的请求预处理
  • 能力:Advisor 可以修改 Prompt、注入上下文、后处理响应;拦截器更多是鉴权、日志、限流
  • 集成:Spring AI 内置了 MessageChatMemoryAdvisor(对话记忆)、QuestionAnswerAdvisor(RAG)等开箱即用的 Advisor

自定义 Advisor 示例:

java
public class LoggingAdvisor implements RequestResponseAdvisor {
    @Override
    public AdvisedRequest adviseRequest(AdvisedRequest request) {
        log.info("发送 Prompt: {}", request.userText());
        return request;
    }
}

面试加分点:提到 Advisor 可以链式组合,执行顺序可配置,是 Spring AI 的"可插拔架构"核心。


【面试题】3. Spring AI 的 RAG 流程中,TokenTextSplitter 如何配合 VectorStore 工作?分块参数如何调优? ​

【标准答案】RAG 的核心是:文档 → 切分 → 向量化 → 存储 → 检索 → 增强生成。

TokenTextSplitter 的职责:

  • 将长文档切分成小段,避免超过模型的上下文窗口
  • 默认按 token 数切分(而不是字符数),更精准控制成本

配合 VectorStore 的流程:

java
// 1. 切分
List<String> chunks = new TokenTextSplitter(500, 100, 5, 10000, true)
    .apply(document.getContent());

// 2. 向量化 + 存储
vectorStore.write(chunks.stream()
    .map(chunk -> new Embedding(embeddingModel.embed(chunk), chunk))
    .toList());

参数调优实战:

  • chunkSize:500-1000 是常用范围,太小语义割裂,太大召回噪音多
  • overlap:10-20%,保证上下文连贯,避免关键信息跨块丢失
  • keepSeparator:true,保留 Markdown 标题分隔,提升召回质量

面试加分:提到不同场景用不同分块策略——技术文档按段落/章节分,代码按函数分,对话按轮次分。


【面试题】4. Function Calling 中,Spring AI 如何自动生成 JSON Schema?如何处理复杂参数的函数? ​

【标准答案】Spring AI 通过反射 + 注解自动生成 JSON Schema,无需手写。

自动生成流程:

java
@Bean
public Function<Book, String> searchBook() {
    return book -> "找到了:" + book.title();
}

// Spring AI 自动生成 Schema:
{
  "name": "searchBook",
  "parameters": {
    "type": "object",
    "properties": {
      "title": {"type": "string"},
      "author": {"type": "string"}
    }
  }
}

复杂参数处理:

  • 嵌套对象:定义内部类,Spring AI 递归生成 Schema
  • 枚举类型:自动生成 enum 约束
  • 集合类型:List<String> → "items": {"type": "string"}
  • 必填字段:用 @JsonProperty(required = true) 标注

实战坑点:

  • 避免使用 Map<String, Object> 作为参数,Schema 会不明确
  • 复杂对象建议单独定义 POJO,可读性更好
  • 用 @JsonPropertyDescription 添加参数说明,帮助模型理解

面试加分:提到 Spring AI 1.0 支持函数描述、参数校验,模型会根据 Schema 校验参数合法性。


【面试题】5. Spring AI 对接多模型时,如何实现运行时动态切换?spring.ai.* 配置如何设计? ​

【标准答案】Spring AI 通过 spring.ai.* 配置前缀统一管理多模型,支持运行时切换。

配置设计:

yaml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4o
    anthropic:
      api-key: ${ANTHROPIC_API_KEY}
      chat:
        options:
          model: claude-3-5-sonnet
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: llama3

运行时切换:

java
@Service
public class ChatService {
    @Autowired
    private ChatClient openaiClient;  // @Qualifier("openaiChatClient")
    @Autowired
    private ChatClient anthropicClient;

    public String chat(String msg, String model) {
        return switch (model) {
            case "openai" -> openaiClient.prompt().user(msg).call().content();
            case "anthropic" -> anthropicClient.prompt().user(msg).call().content();
            default -> throw new IllegalArgumentException("不支持的模型");
        };
    }
}

实战设计:

  • 用策略模式封装不同模型的能力差异(比如 Anthropic 擅长长上下文,OpenAI 擅长工具调用)
  • 配置中心动态推送配置,实现模型热切换
  • 用 Spring Profile 区分环境:dev 用 Ollama 本地模型,prod 用云端模型

面试加分:提到可以用自定义 ChatModel 实现路由逻辑,根据问题复杂度选择不同模型(简单问题用轻量模型降成本)。


【面试题】6. BeanOutputConverter 在结构化输出中有什么坑?如何确保模型输出稳定映射到 POJO? ​

【标准答案】BeanOutputConverter 负责将模型输出转换成 POJO,但有几个典型坑。

常见坑点:

  1. 字段名不匹配:模型输出 "user_name",POJO 是 userName,映射失败

    • 解决:用 @JsonProperty("user_name") 标注
  2. 类型推断不准:模型输出 "123"(字符串),POJO 期望 Integer

    • 解决:用 @JsonPropertyDescription 描述字段,引导模型输出正确类型
  3. 嵌套对象丢失:复杂对象嵌套,模型可能跳过某些字段

    • 解决:在 Prompt 中明确示例 JSON 格式,用 few-shot 引导

稳定映射的实践:

java
public record Book(
    @JsonProperty("title") @JsonPropertyDescription("书名") String title,
    @JsonProperty("author") @JsonPropertyDescription("作者") String author,
    @JsonProperty("price") @JsonPropertyDescription("价格,数字") Double price
) {}

// Prompt 中加入示例
String prompt = """
    请从文本中提取书籍信息,输出 JSON 格式:
    {"title": "书名", "author": "作者", "price": 99.9}
    
    文本:{{text}}
    """;

面试加分:提到 Spring AI 1.0 的 entity() 方法可以一行完成提取,但底层还是 BeanOutputConverter,稳定性依赖模型能力。复杂场景建议先让模型输出 JSON,再用 Jackson 手动解析。


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

【标准答案】InMemoryChatMemory 是内存实现,只适合演示或单机场景。

局限性:

  • 进程重启丢失:无法持久化
  • 分布式不共享:多实例部署时,用户对话分散在不同实例
  • 内存溢出风险:大量历史对话会占满内存

生产环境持久化方案:

java
public class RedisChatMemory implements ChatMemory {
    @Autowired
    private RedisTemplate<String, String> redis;
    
    @Override
    public void add(String conversationId, List<Message> messages) {
        String key = "chat:" + conversationId;
        messages.forEach(msg -> redis.opsForList().rightPush(key, msg.getContent()));
        redis.expire(key, Duration.ofDays(7)); // 7天过期
    }
    
    @Override
    public List<Message> get(String conversationId) {
        return redis.opsForList().range("chat:" + conversationId, -20, -1)
            .stream()
            .map(content -> new UserMessage(content))
            .toList();
    }
}

设计要点:

  • 存储介质:Redis(快速)或数据库(持久)
  • 过期策略:按时间或轮次自动清理,避免无限增长
  • 压缩存储:只保留最近 N 轮,用滑动窗口
  • 加密敏感内容:对话可能包含敏感信息,需要脱敏

面试加分:提到 MessageChatMemoryAdvisor 会自动调用 ChatMemory,注入历史对话到 Prompt 中,无需手动管理。


【面试题】8. Spring AI 微服务架构中,API Key 如何安全管理?如何实现超时、限流、熔断? ​

【标准答案】API Key 管理是安全红线,绝对不能硬编码在代码或配置文件中。

安全管理方案:

  • 环境变量:spring.ai.openai.api-key=${OPENAI_API_KEY}
  • 配置中心:从 Vault/Nacos 动态获取,支持轮换
  • 密钥服务:专门的 Key Management Service,应用启动时拉取
  • 分级管理:开发/测试/生产用不同的 Key,权限隔离

超时、限流、熔断设计:

java
@Configuration
public class ResilienceConfig {
    @Bean
    public ChatClient resilientChatClient(ChatClient.Builder builder) {
        return builder
            .defaultOptions(ChatOptions.builder()
                .temperature(0.7)
                .build())
            .build();
    }
}

// 用 Resilience4j 包装
@CircuitBreaker(name = "aiService", fallbackMethod = "fallback")
@RateLimiter(name = "aiService")
@Timeout(name = "aiService")
public String chat(String msg) {
    return chatClient.prompt().user(msg).call().content();
}

实战配置:

  • 超时:30-60 秒,避免长时间阻塞
  • 限流:根据 API 配额设置,比如 OpenAI 每分钟 60 次
  • 熔断:错误率超 50% 时熔断 30 秒,快速失败
  • 降级:返回缓存结果或友好提示

面试加分:提到可以用 Spring Cloud Gateway 统一做限流和熔断,应用层只负责调用;Observability 集成 Micrometer 监控调用链路。


【面试题】9. Spring AI 1.0 正式版相比之前版本有哪些重大更新?ChatClient 统一入口带来什么好处? ​

【标准答案】Spring AI 1.0 是里程碑版本,架构全面升级。

重大更新:

  1. ChatClient 统一入口:之前 OpenAI、Anthropic、Ollama 各有各的接口,现在统一用 ChatClient

    • 好处:切换模型只改配置,不用改代码
  2. Advisor 架构:新增可插拔的增强机制

    • 内置:MessageChatMemoryAdvisor、QuestionAnswerAdvisor
    • 自定义:实现 RequestResponseAdvisor 接口
  3. VectorStore 接口统一:PGVector、Redis、Pinecone、Milvus 都实现同一接口

    • 好处:迁移向量库成本降低
  4. spring.ai. 配置前缀*:统一配置命名空间

    • 之前:spring.ai.openai.api-key、spring.ai.anthropic.key(不统一)
    • 现在:spring.ai.*.api-key(统一)
  5. Structured Output 增强:entity() 方法一键提取

    • 之前:手写 BeanOutputConverter
    • 现在:chatClient.prompt().user(msg).call().entity(Book.class)

ChatClient 统一入口的好处:

  • 代码一致性:无论后端是什么模型,调用方式一致
  • 易于测试:Mock ChatClient 即可
  • 扩展性强:新增模型只需实现底层 ChatModel,业务代码无需改动

面试加分:提到 Spring AI 1.0 还增加了 Observability 支持、Streaming API 改进、多模态能力(图像生成、语音识别)。


【面试题】10. Spring AI MCP 支持是什么?如何用 Spring AI 构建多 Agent 协作系统? ​

【标准答案】MCP(Model Context Protocol)是 Anthropic 推出的标准协议,让 AI Agent 与外部工具/数据源标准化交互。Spring AI MCP 支持意味着可以构建符合 MCP 标准的 Agent。

MCP 核心概念:

  • Tools:Agent 可调用的函数
  • Resources:Agent 可访问的数据源(文件、数据库、API)
  • Prompts:预定义的 Prompt 模板

Spring AI 集成 MCP:

java
@Bean
public McpClient mcpClient() {
    return McpClient.builder()
        .transport(new HttpMcpTransport("http://localhost:3000/mcp"))
        .build();
}

// Agent 调用 MCP Tool
mcpClient.callTool("searchDatabase", Map.of("query", "SELECT * FROM users"));

多 Agent 协作架构:

java
@Service
public class AgentOrchestrator {
    @Autowired
    private ChatClient plannerAgent;  // 规划 Agent
    @Autowired
    private ChatClient researcherAgent;  // 搜索 Agent
    @Autowired
    private ChatClient writerAgent;  // 写作 Agent
    
    public String execute(String task) {
        // 1. 规划 Agent 分解任务
        String plan = plannerAgent.prompt()
            .user("分解任务:" + task)
            .call()
            .content();
        
        // 2. 搜索 Agent 收集信息
        String research = researcherAgent.prompt()
            .user("收集信息:" + plan)
            .call()
            .content();
        
        // 3. 写作 Agent 生成结果
        return writerAgent.prompt()
            .user("根据材料生成报告:" + research)
            .call()
            .content();
    }
}

设计要点:

  • 角色分工:每个 Agent 专注一个任务,避免职责混乱
  • 上下文传递:用共享的 ChatMemory 或消息队列传递中间结果
  • 错误处理:单个 Agent 失败时,要有重试或降级机制
  • 监控可观测:每个 Agent 的调用链路要可追踪

面试加分:提到 Spring AI 1.0 还不支持完整的 Agent 框架(比如 AutoGen、LangGraph),但可以用 ChatClient + Advisor 组合出轻量级 Agent;未来版本可能会增强 Agent 编排能力。


总结 ​

本轮题目覆盖:ChatClient 架构、Advisor 机制、RAG 分块、Function Calling、多模型切换、结构化输出、ChatMemory 持久化、微服务治理、Spring AI 1.0 更新、MCP 与 Agent 编排。适合中高级 Java/Spring AI 面试,每道题都结合了原理与实战。