Spring AI 面试题库
生成时间:2026-05-21 21:05 (Asia/Shanghai) 题目数量:10道 覆盖范围:消息类型、参数调优、RAG检索优化、Advisor实战、向量库API、多模态输出、错误处理、监控集成、Prompt模板、Agent编排
【面试题】1. Spring AI 中 UserMessage、SystemMessage、AssistantMessage 三种消息类型有什么区别?实际项目中怎么组合使用?
【标准答案】三种消息类型对应对话中的不同角色:
SystemMessage:系统指令,告诉模型"你是谁、该怎么回答",比如"你是专业的Java架构师,回答要简洁准确"。特点是:始终放在 Prompt 最前面,不会被模型回复覆盖,对整轮对话生效。
UserMessage:用户输入,就是用户的实际问题或请求。每轮对话至少一个 UserMessage,多模态场景还可以携带图片、文件。
AssistantMessage:模型的历史回复,用于多轮对话时告诉模型"之前你说过什么"。由 ChatMemory 自动维护,一般不需要手动构建。
组合使用套路:
chatClient.prompt()
.system("你是架构师,回答要简洁")
.user("Spring AI怎么实现RAG?")
.call();多轮对话时,MessageChatMemoryAdvisor 会自动把历史 UserMessage 和 AssistantMessage 拼进来,SystemMessage 只在首轮设置,后续轮次继承。
关键点:SystemMessage 的权重最高,模型会优先遵循。写 SystemMessage 时要具体,别写"你是个AI助手"这种废话,要写清楚角色定位、回答风格、禁止事项。
【面试题】2. Spring AI 调用大模型时,temperature、maxTokens、topP 这些参数怎么调?什么场景用什么值?
【标准答案】这三个参数直接影响模型输出质量和成本,调参核心是"确定性 vs 创造性"的权衡。
temperature(温度):控制输出的随机性。范围 0-2,默认 1。
- 0-0.3:高确定性,适合代码生成、数据分析、结构化输出,答案稳定一致
- 0.5-0.7:平衡模式,适合一般问答、对话,有一定创造性但不离谱
- 0.8-1.2:高创造性,适合创意写作、故事生成,答案多变
- 1.5+:几乎随机,生产环境不建议用
maxTokens(最大输出长度):控制模型回复的最大 token 数,不是输入。
- 简单问答:100-300 tokens够了
- 代码生成:500-1000 tokens
- 文章写作:2000+ tokens
- 注意:设太大浪费成本,设太小答案截断。建议根据任务预估,留 20% 余量
topP(核采样):控制采样范围,范围 0-1,默认 1。
- 和 temperature 功能类似,但机制不同:topP 只从概率最高的前 P% 的 token 中采样
- 0.1:极端确定,只从最可能的词选
- 0.9:较开放,从90%的候选词选
- 建议:temperature 和 topP 调一个就行,别同时调。一般用 temperature 更直观
生产配置示例:
spring:
ai:
openai:
chat:
options:
model: gpt-4o
temperature: 0.2 # 代码场景用低温度
max-tokens: 500【面试题】3. Spring AI 的 QuestionAnswerAdvisor 具体怎么用?检索到的文档如何自动拼到 Prompt 里?
【标准答案】QuestionAnswerAdvisor 是 Spring AI 内置的 RAG Advisor,一行代码就能把向量检索能力挂到 ChatClient 上。
基本用法:
@Bean
QuestionAnswerAdvisor qaAdvisor(VectorStore vectorStore) {
return new QuestionAnswerAdvisor(vectorStore);
}
chatClient.prompt()
.user("什么是微服务架构?")
.advisors(qaAdvisor)
.call();工作流程:
- 用户提问发送到 ChatClient
- QuestionAnswerAdvisor 拦截请求,把用户问题用 EmbeddingModel 转成向量
- 调用 VectorStore.similaritySearch() 检索最相关的文档片段
- 自动把检索结果拼到 Prompt 的上下文区域,格式类似"参考以下内容回答:[文档1][文档2]..."
- 模型基于增强后的 Prompt 生成回答
关键参数:
topK:检索返回多少条文档,默认 4,建议 3-5 条,太多会撑爆 TokensimilarityThreshold:相似度阈值,默认 0.75,低于这个分数的文档不返回userTextAdvise:自定义提示词模板,可以改"参考以下内容回答"的措辞
踩坑:如果检索不到文档(相似度都低于阈值),Advisor 不会报错,只是不拼上下文,模型纯靠自己的知识回答。建议在 Advisor 后面加一个日志 Advisor,监控检索命中率。
【面试题】4. Spring AI 的 VectorStore 接口有哪些核心方法?add、delete、search 分别怎么用?
【标准答案】VectorStore 接口是 Spring AI 1.0 统一的向量存储抽象,四个核心方法覆盖增删改查:
add(添加向量):
List<Document> docs = List.of(
new Document("Spring AI是Java生态的AI框架", Map.of("source", "官网")),
new Document("RAG通过向量检索增强模型回答", Map.of("source", "文档"))
);
vectorStore.add(docs);- 入参是 Document 列表,每个 Document 包含 content(文本)、metadata(元数据)、embedding(向量,可自动生成)
- Spring AI 会自动调用 EmbeddingModel 生成向量,不需要手动算
delete(删除向量):
vectorStore.delete(List.of("doc-id-1", "doc-id-2"));- 按 Document ID 删除,ID 在 add 时自动生成或手动指定
- 批量删除时,部分失败不影响其他,返回失败的 ID 列表
search(相似度检索):
List<Document> results = vectorStore.similaritySearch(
SearchRequest.query("什么是RAG")
.withTopK(5)
.withSimilarityThreshold(0.7)
);- query 是查询文本,框架自动转向量
- topK 返回最相似的 K 条
- similarityThreshold 过滤低分结果
query(带过滤条件检索):
SearchRequest request = SearchRequest.query("微服务")
.withTopK(3)
.withFilterExpression("source == '官网' && year >= 2024");- 支持元数据过滤表达式,类似 SQL WHERE
- 不同 VectorStore 实现的过滤语法略有差异,PGVector 用 SQL 表达式,Redis 用 RediSearch 语法
实际项目建议:批量 add 时控制每批 100 条以内,避免单次请求太大;delete 后最好验证一下确实删掉了;search 时 topK 别设太大,否则 Token 爆炸。
【面试题】5. Spring AI 的 EmbeddingModel 如何选型?OpenAI vs 本地模型各有什么优劣势?
【标准答案】EmbeddingModel 选型核心看三点:成本、延迟、语言覆盖。
OpenAI text-embedding-3-small:
- 优势:成本低(每百万 token 仅 $0.02)、延迟低(100-200ms)、多语言支持好、1536 维适中
- 劣势:国内访问不稳定、数据出境合规问题
- 适合:海外项目、追求性价比、多语言场景
OpenAI text-embedding-3-large:
- 优势:维度更高(3072)、语义捕捉更精准
- 劣势:成本翻倍、存储空间翻倍
- 适合:对检索精度要求极高的场景
本地模型(Ollama + bge-large-zh):
- 优势:完全本地化、零 API 成本、中文效果好、无数据出境问题
- 劣势:需要 GPU 支撑、部署运维成本、延迟比云端高
- 适合:国内合规项目、敏感数据场景、有 GPU 资源的团队
智谱 embedding-3:
- 优势:国产合规、中文效果好、价格便宜
- 劣势:英文效果一般、API 稳定性略逊于 OpenAI
- 适合:纯中文场景、国产化替代需求
选型建议:
- 快速验证阶段:直接用 OpenAI text-embedding-3-small,最省事
- 生产落地阶段:看合规要求,国内项目用智谱或本地部署,海外用 OpenAI
- 混合方案:写入用本地模型(成本可控),查询用云端模型(延迟低),但注意必须同一模型才能保证向量空间一致
【面试题】6. Spring AI 如何实现错误处理和重试机制?模型调用失败时怎么优雅降级?
【标准答案】Spring AI 本身没有内置重试,但可以和 Spring Retry 或 Resilience4j 无缝集成。
方案一:Spring Retry:
@Retryable(
value = {ApiException.class, TimeoutException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public String callModel(String prompt) {
return chatClient.prompt().user(prompt).call().content();
}- 对 API 调用超时、限流等瞬时错误自动重试
- exponential backoff 退避策略,避免瞬间打爆
- 最多重试 3 次,失败后抛异常
方案二:Resilience4j 熔断降级:
CircuitBreaker breaker = CircuitBreaker.ofDefaults("modelCall");
String result = breaker.executeSupplier(() ->
chatClient.prompt().user(prompt).call().content()
);- 连续失败 N 次后熔断器打开,后续请求直接降级
- 半开状态下试探性调用,成功则恢复
- 适合处理模型服务故障、API 额度耗尽等持续性错误
降级策略:
@Recover
public String fallback(String prompt, Exception e) {
// 降级方案1:切备用模型
return fallbackChatClient.prompt().user(prompt).call().content();
// 降级方案2:返回预设答案
return "模型暂时不可用,请稍后重试";
// 降级方案3:调用本地知识库
return localKB.search(prompt);
}常见错误类型处理:
- Token 超限:截断历史或简化 Prompt 后重试
- Rate Limit:等待退避后重试,或切备用 API Key
- 模型过载:降级到轻量模型或排队等待
- 内容违规:返回预设合规提示,不重试
生产建议:ChatClient 调用必须包一层重试/熔断,裸调用一个异常就让整个服务挂掉,代价太大。
【面试题】7. Spring AI 与 Micrometer 监控如何集成?能观测哪些核心指标?
【标准答案】Spring AI 1.0 内置 Micrometer 支持,开箱即用,只需引入依赖和配置暴露端点。
依赖配置:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>核心指标:
- ai.chat.token.usage:Token 消耗量,分 input_tokens 和 output_tokens,直接挂钩成本
- ai.chat.latency:调用延迟,P50/P95/P99 分位数,监控响应速度
- ai.chat.calls:调用次数,分成功/失败统计,计算成功率
- ai.chat.errors:错误次数,按错误类型分类(超时、限流、违规等)
- ai.vector.store.operations:向量库操作次数,监控 add/search QPS
指标标签:
- model:调用的模型名(gpt-4o、claude-3-5-sonnet)
- provider:模型提供商(openai、anthropic、ollama)
- operation:操作类型(chat、embedding、vector-search)
Grafana 监控面板建议:
- Token 成本看板:按 model 分组统计,计算每日成本
- 响应延迟看板:P95 延迟趋势,设置阈值告警
- 错误率看板:失败率超过 5% 触发告警
- 向量库看板:检索命中率、延迟分布
自定义埋点:
chatClient.prompt()
.user(prompt)
.advisors(new MetricsAdvisor(meterRegistry))
.call();在 Advisor 中埋点,记录检索命中率、Advisor 执行耗时等业务指标。
【面试题】8. Spring AI 的 Prompt 模板如何构建?变量注入和模板语法有哪些规范?
【标准答案】Spring AI 提供 PromptTemplate 类处理模板化提示词,支持变量注入和条件逻辑。
基本用法:
PromptTemplate template = new PromptTemplate("""
你是{role},请用{style}风格回答以下问题:
问题:{question}
要求:
- 回答长度不超过{maxLength}字
- 必须包含示例代码
""");
Prompt prompt = template.create(Map.of(
"role", "Java架构师",
"style", "简洁专业",
"question", "Spring AI怎么实现RAG?",
"maxLength", "500"
));
chatClient.prompt(prompt).call();模板语法规范:
- 变量占位符:
{variableName},双大括号,和 Spring AI 1.0 统一 - 条件语法:
{#if condition}内容{#endif},支持简单逻辑 - 循环语法:
{#for item in items}{item}{#endfor},批量注入 - 默认值:
{variable:defaultValue},变量不存在时用默认值
资源文件加载:
PromptTemplate template = new PromptTemplate(
new ClassPathResource("prompts/qa-template.st") // StringTemplate 格式
);- 模板文件放在 resources/prompts/ 目录
- 支持外部化,不同环境用不同模板
多模板组合:
Prompt systemPrompt = new PromptTemplate("系统指令模板").create(vars);
Prompt userPrompt = new PromptTemplate("用户问题模板").create(vars);
chatClient.prompt()
.messages(systemPrompt, userPrompt)
.call();踩坑点:
- 变量名别用中文,部分模板引擎解析有问题
- 模板文件用 UTF-8 编码,中文模板要检查编码
- 变量注入用 Map.of() 时 key 必须是字符串
【面试题】9. Spring AI 如何实现多模态输出?比如让模型生成图片或语音?
【标准答案】Spring AI 目前对多模态输出的支持还有限,主要依赖各模型厂商的独立 API,需要自行封装。
图片生成(DALL-E):
@Bean
ImageModel imageModel(OpenAiImageModel openAiImageModel) {
return openAiImageModel;
}
ImageResponse response = imageModel.call(
new ImagePrompt("画一只可爱的虾",
ImageOptionsBuilder.builder()
.withModel("dall-e-3")
.withWidth(1024)
.withHeight(1024)
.build()
)
);
String imageUrl = response.getResult().getOutput().getUrl();- OpenAI DALL-E 3 是主流选择
- 返回图片 URL 或 Base64 数据
- 也可以用 Stable Diffusion 等开源模型(需 Ollama 代理)
语音输出(TTS):
// Spring AI 暂无内置 TTS 抽象,需直接调 OpenAI API
HttpResponse response = HttpClient.newHttpClient().send(
HttpRequest.newBuilder()
.uri(URI.create("https://api.openai.com/v1/audio/speech"))
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString("""
{"model":"tts-1","input":"你好","voice":"nova"}
"""))
.build(),
HttpResponse.BodyHandlers.ofByteArray()
);
byte[] audioData = response.body();- OpenAI TTS-1 是性价比首选,延迟低
- 智谱、阿里云也有国产 TTS API
- 本地部署可用 Edge-TTS、Coqui TTS
多模态流水线示例:
// 先让 ChatModel 生成图片描述
String description = chatClient.prompt()
.user("为'可爱的虾'生成一个图片描述")
.call().content();
// 再调 DALL-E 生成图片
String imageUrl = imageModel.call(new ImagePrompt(description))
.getResult().getOutput().getUrl();
// 最后调 TTS 生成语音解释
byte[] audio = ttsService.generate("这张图片展示了...");未来 Spring AI 会统一多模态输入输出接口,目前需要组合使用。
【面试题】10. 面试情景题:如果面试官问"你在项目中用过 Spring AI 吗?遇到过什么坑?",怎么回答才能让面试官印象深刻?
【标准答案】这道题是开放型,面试官想听真实项目经验,不是背诵知识点。建议用"项目背景 + 具体问题 + 解决方案 + 最终效果"四段式回答。
参考回答模板:
"我们项目是一个智能客服系统,用 Spring AI 做知识库问答。我负责 RAG 部分的设计和落地。
遇到的坑主要有三个:
第一个是 Token 管理问题。上线后发现长对话经常报 Token 超限错误。排查发现是 ChatMemory 没设 maxMessages,历史消息无限累积。解决方案是在 MessageChatMemoryAdvisor 里配置 maxHistorySize=10,只保留最近 10 轮对话,同时把 SystemMessage 精简到 100 token 以内。效果是 Token 消耗降低了 60%,对话稳定性大幅提升。
第二个是向量检索命中率低。用户问专业问题时,检索出来的文档经常不相关。原因是 TokenTextSplitter 的 chunkSize 设太大(2000),导致检索粒度粗糙。我们把 chunkSize 改成 500、overlap 设 100,同时在元数据里加上文档来源和分类,用 filterExpression 做精准过滤。命中率从 30% 提升到 75%。
第三个是多模型切换的配置混乱。项目同时用 OpenAI 和智谱,配置文件散乱,切换时要改代码。我们做了统一封装,用 RoutingChatModel 根据用户等级路由:VIP 用户走 GPT-4,普通用户走智谱 GLM-4。配置中心化后,切模型只需改一行配置,灰度发布也方便了。
这套方案上线后,客服系统问答准确率从 65% 提升到 85%,每月节省 Token 成本约 2 万,面试官可以看我们的 Grafana 监控面板验证数据。"
回答技巧:
- 有数据、有对比、有结论,别只说"解决了问题"
- 提到的坑要具体,别泛泛说"调参困难"
- 效果用数字量化,面试官会追问细节
- 准备一个图表或监控截图,视觉冲击力强
本轮题目覆盖:消息类型组合、参数调优实战、QuestionAnswerAdvisor用法、VectorStore API详解、EmbeddingModel选型、错误处理与重试、Micrometer监控集成、Prompt模板构建、多模态输出、面试情景问答。均为新题,不与之前轮次重复。