Spring AI 面试题库
生成时间:2026-05-21 22:34
本轮 Spring AI 面试题库(带答案)
【面试题】1. EmbeddingModel在Spring AI中的作用是什么?如何选择合适的Embedding模型?
【标准答案】EmbeddingModel负责把文本转换成向量,是RAG流程的第一步。Spring AI提供了统一接口,底层可以对接OpenAI的text-embedding-ada-002、智谱的embedding-3、本地Ollama的nomic-embed-text等。
选型考虑四个维度:
- 效果:MTEB榜单看排名,OpenAI的ada-002和text-embedding-3-small效果好,智谱、通义的中文场景表现优秀
- 成本:OpenAI按token计费,大规模文本向量很贵;本地Ollama免费但需要GPU资源
- 速度:实时性要求高选小模型,比如all-MiniLM-L6-v2,128维向量够用且快
- 维度:高维向量(1536维)检索精度高但占用存储大、计算慢;低维向量(384维)牺牲精度换速度
实际项目经验:中文场景用智谱embedding-3,成本可控效果好;英文场景用text-embedding-3-small;本地私有化部署用Ollama + nomic-embed-text。向量维度建议512-1024平衡效果和性能。
【面试题】2. QuestionAnswerAdvisor在RAG中如何工作?和手动实现RAG有什么区别?
【标准答案】QuestionAnswerAdvisor是Spring AI封装的RAG拦截器,工作流程:
- 用户问题进来,Advisor拦截
- 调用VectorStore的similaritySearch检索相似文档
- 把检索结果拼接到Prompt的上下文区域
- 发给大模型生成答案
和手动实现RAG的区别:
- 手动实现:需要自己写检索逻辑、拼接Prompt、管理上下文窗口,代码量大
- QuestionAnswerAdvisor:一行代码配置,自动完成检索+拼接,还支持自定义检索策略
代码示例:
ChatClient.builder(chatModel)
.defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
.build();进阶用法:可以自定义检索参数(topK、相似度阈值)、对检索结果做重排序、添加引用来源标注。优势是解耦——检索策略变更有独立的Advisor,不影响业务代码。
【面试题】3. Spring AI的流式响应(Streaming)怎么实现?有哪些坑?
【标准答案】流式响应用ChatClient的.stream()方法,返回Flux<String>响应式流:
Flux<String> stream = chatClient.prompt()
.user("讲一个故事")
.stream()
.content();核心坑:
- 超时配置:流式响应可能持续几十秒,WebClient默认超时不够,要配置长连接超时
- 错误处理:流中途失败要优雅降级,不能抛异常后端无感知,用
.doOnError()处理 - 背压控制:前端消费速度可能跟不上大模型输出,要用
.buffer()或.sample()限速 - 连接保持:长连接可能被Nginx/网关断开,要配置心跳或调整超时设置
- Token统计:流式响应的token消耗是分块返回的,要累加统计,不能只看最后一次
实际项目经验:流式接口要用SSE(Server-Sent Events)协议,前端EventSource接收。Spring WebFlux天然支持,Controller返回Flux<ServerSentEvent<String>>即可。注意生产环境要加限流,大模型流式输出很耗资源。
【面试题】4. PromptTemplate模板引擎怎么用?和直接拼接字符串有什么优势?
【标准答案】PromptTemplate是Spring AI的模板引擎,支持占位符替换和复用:
PromptTemplate template = new PromptTemplate("""
你是一个{role},请用{style}风格回答问题。
用户问题:{question}
""");
Prompt prompt = template.create(Map.of(
"role", "技术专家",
"style", "简洁专业",
"question", userQuestion
));相比字符串拼接的优势:
- 可维护性:模板和代码分离,运营/产品可以直接改模板,不动代码
- 安全注入:自动处理占位符,避免注入问题
- 多语言支持:可以配置多套模板,按语言切换
- 外部化:模板可以存在数据库或配置中心,动态加载
- 变量校验:创建时检查占位符是否都有值,提前发现问题
进阶用法:支持条件判断、循环等简单逻辑({#if}语法),但不建议模板太复杂,保持纯文本替换为主。实际项目里把System Prompt模板放在配置文件,用@Value注入,运维可以随时调整。
【面试题】5. VectorStore的similaritySearch方法有哪些关键参数?如何调优检索效果?
【标准答案】核心参数:
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.query(query)
.withTopK(5) // 返回前5个最相似文档
.withSimilarityThreshold(0.7) // 相似度阈值,低于此值不返回
);参数调优策略:
- TopK:太小召回不足,太大噪音多。建议5-10,根据RAG场景调整
- SimilarityThreshold:0.7是常用值,太低会引入无关内容,太高可能召回为空
- 查询向量:问题本身要先做Embedding,确保和文档向量模型一致
- 预过滤:可以用metadata过滤,比如只检索某个分类的文档,缩小范围提精度
效果优化技巧:
- 混合检索:向量检索 + 关键词检索(BM25),结果融合,提高召回率
- 重排序:先用向量检索召回Top 50,再用cross-encoder重排,取Top 5
- 查询扩展:用户问题用大模型改写、扩展同义词,再检索
- 分块策略:检索到的文档块,追加前后文上下文,避免信息截断
实际项目:TopK=10、Threshold=0.75、加上metadata过滤(按文档类型),效果稳定。关键是要有评估集,定期回归测试检索效果。
【面试题】6. Spring AI如何实现多模态能力(图片/音频)?实际项目怎么用?
【标准答案】Spring AI 1.0已支持多模态,核心是Media类型:
UserMessage message = new UserMessage(
"这张图片里有什么?",
new Media(MimeTypeUtils.IMAGE_PNG, imageUrl)
);
chatClient.prompt()
.messages(message)
.call()
.content();支持的多模态能力:
- 图片理解:OpenAI GPT-4V、智谱GLM-4V、通义Qwen-VL,传图片URL或Base64
- 图片生成:OpenAI DALL-E,用
ImageModel接口生成图片 - 音频处理:部分模型支持音频输入(如Whisper做语音识别)
实际应用场景:
- 图文问答:用户上传截图,AI解读内容
- 文档解析:PDF转图片,AI提取表格/图表信息
- 代码截图:报错截图直接问AI解决方案
- 产品图片:电商场景生成商品描述
注意事项:
- 图片要压缩,大图Base64会爆token
- 不是所有模型都支持多模态,要检查
ChatModel实现 - 成本控制:图片按token计费,高频场景很贵,考虑缓存或降级到纯文本
【面试题】7. Spring AI对接Ollama本地模型有哪些关键配置?生产环境要注意什么?
【标准答案】Ollama配置项:
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: llama3
options:
temperature: 0.7
num-predict: 2048关键配置:
- base-url:Ollama服务地址,默认11434端口
- model:模型名称,llama3/qwen2/phi3等,要先用ollama pull下载
- options.temperature:温度参数,低温度更确定,高温度更随机
- options.num-predict:最大生成token数,避免无限生成
生产环境注意事项:
- GPU资源:本地模型需要GPU,要评估显存是否够用,7B模型至少8GB显存
- 并发控制:Ollama默认单并发,高并发要启动多个实例或用队列
- 模型版本:统一模型版本,不同机器模型一致,避免结果差异
- 健康检查:Ollama进程可能崩溃,要加健康检查和自动重启
- 超时设置:本地模型推理慢,超时要放宽到60-120秒
- 降级策略:本地模型能力有限,复杂任务考虑降级到云端API
适用场景: 数据隐私要求高、网络隔离、成本敏感、请求量不大。不适合高并发、低延迟场景。
【面试题】8. Function Calling中如何处理复杂参数类型(嵌套对象、数组、枚举)?
【标准答案】复杂参数类型要定义结构良好的POJO:
@Bean
public Function<OrderRequest, OrderResult> createOrder() {
return request -> {
// 处理逻辑
};
}
public record OrderRequest(
String orderId,
List<OrderItem> items,
PaymentMethod paymentMethod // 枚举
) {}
public record OrderItem(
String productId,
int quantity,
BigDecimal price
) {}
public enum PaymentMethod {
CREDIT_CARD, ALIPAY, WECHAT
}处理技巧:
- 嵌套对象:用record或简单POJO,字段要有清晰的语义
- 数组/List:Spring AI自动映射,但List泛型要明确
- 枚举:在Prompt里明确枚举值,避免大模型输出非法值
- BigDecimal:金额用BigDecimal,避免精度问题
- Optional字段:用
@JsonProperty(required=false)标记可选
常见坑:
- 泛型擦除:
List<OrderItem>在运行时丢失类型,需要@JsonProperty辅助 - null处理:大模型可能省略可选字段,POJO字段要允许null或给默认值
- 枚举匹配:大模型输出的枚举值要和Java枚举完全一致(大小写)
最佳实践:在System Prompt里给函数调用的few-shot示例,明确参数格式,提高成功率。
【面试题】9. 向量数据库的索引类型(IVF、HNSW)有什么区别?如何选择?
【标准答案】两种主流向量索引:
IVF(倒排索引):
- 原理:向量空间分簇,查询时只搜索最近的几个簇
- 特点:速度快,内存占用低,但精度有损失
- 适用:大规模数据(千万级以上),对精度要求中等
- 配置:nlist(簇数)是关键参数,nlist越大精度越高但速度越慢
HNSW(层次化小世界图):
- 原理:构建多层图结构,搜索时从顶层到底层逐层逼近
- 特点:精度高,查询速度快,但内存占用大
- 适用:中小规模数据(百万级),对精度要求高
- 配置:M(邻居数)、efConstruction(构建参数)是关键参数
选型建议:
- 数据量<100万:HNSW,精度优先
- 数据量>1000万:IVF,速度优先
- 中间规模:都试试,看实际效果
Spring AI配置示例(Milvus):
MilvusVectorStore.builder()
.indexType(IndexType.IVF_FLAT) // 或 HNSW
.metricType(MetricType.COSINE)
.build();实际项目经验:百万级数据用HNSW,M=16、efConstruction=200,查询ef=64,效果和速度平衡。超过千万用IVF,nlist=sqrt(N)是经验公式。
【面试题】10. 【场景题】面试官问:你们公司的Spring AI项目架构是怎么设计的?请画图说明。
【标准答案】这个问题要准备一个完整的架构图和设计思路:
典型架构分层:
┌─────────────────────────────────────────────────┐
│ 前端应用层 │
│ Web / App / 小程序 / 第三方接入 │
└─────────────────────┬───────────────────────────┘
│ API Gateway
┌─────────────────────▼───────────────────────────┐
│ 网关层 │
│ 认证鉴权 / 限流熔断 / 路由分发 / 日志追踪 │
└─────────────────────┬───────────────────────────┘
│
┌─────────────────────▼───────────────────────────┐
│ Spring AI 服务层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ChatClient│ │RAG Service│ │Tool Service│ │
│ │(对话服务) │ │(检索增强) │ │(工具调用) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┴─────────────┘ │
│ │ │
│ Advisor Chain │
│ MemoryAdvisor / RAGAdvisor / LogAdvisor │
└─────────────────────┬───────────────────────────┘
│
┌─────────────────────▼───────────────────────────┐
│ 模型层 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ OpenAI │ │智谱/通义 │ │ Ollama │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────┘
│
┌─────────────────────▼───────────────────────────┐
│ 存储层 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │VectorDB │ │ Redis │ │ MySQL │ │
│ │(向量) │ │(缓存) │ │(业务) │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────┘设计要点:
- 网关层:统一认证、限流、路由,大模型API贵,要控制调用量
- 服务层:按能力拆分,ChatClient是对话核心,RAG和Tool是增强能力
- Advisor链:统一拦截,Memory注入历史、RAG检索文档、Tool执行函数
- 模型层:多模型路由,OpenAI主力、智谱降级、Ollama私有化,按成本和场景选择
- 存储层:向量库存知识库、Redis存会话缓存、MySQL存业务数据
可观测性:
- Micrometer + Prometheus监控调用量、延迟、Token消耗
- ELK日志追踪,每次调用带traceId
- Grafana大盘 + 告警,异常5分钟内响应
面试这样说:"我们项目分层清晰,网关做限流保护,服务层解耦对话和检索,Advisor链统一增强,存储层分离向量和业务数据。关键是可观测性要完善,大模型API成本高、延迟不稳定,监控告警必不可少。"
题目统计
- 本次生成:10 道面试题
- 覆盖模块:Embedding模型选型、QuestionAnswerAdvisor、流式响应、PromptTemplate、向量检索调优、多模态能力、Ollama本地部署、复杂Function参数、向量索引优化、架构设计
- 适用版本:Spring AI 1.0 正式版
- 题目类型:技术基础(3)、架构设计(2)、场景实操(3)、性能优化(2)