Spring AI 集成实践:从零搭建企业级 AI 聊天 + RAG 知识库
分享一套 Spring AI 落地方案,通过硅基流动统一接入 Qwen 对话与 Embedding 模型,重点讲设计取舍、技术选型和踩坑注意点,少走弯路。
读完本文,你将掌握:
✅ 如何用 Spring AI + 硅基流动统一接入 Qwen 对话与 Embedding 模型
✅ RAG 中 System 和 User 的正确分工
✅ Milvus 集成的 3 个关键注意点(插入后 load、维度探测、自定义 VectorStore)
✅ 生产环境必备的熔断限流舱壁配置
✅ 多模型切换的策略模式实现
一、整体架构与流程
1.1 请求链路(用户问 → 答)
用户提问 → 聊天/RAG 服务 → 有 kid?→ 向量相似度检索 → 获取向量库实例 → 查询向量化 → 检索 topK 文档 → 拼 Prompt(System=规则+人设,User=问题+上下文) → 获取对话模型 → 硅基流动 /v1/chat/completions → 流式返回
1.2 数据准备链路(文档入库)
文件上传 → ETL 流程 → 文档读取(PDF/Word/TXT) → 文档分割(按知识库配置) → 存关系库(短事务) → 向量化 + 存 Milvus(无事务) → insert + load
1.3 技术栈总览
|
层级 |
技术 |
模型 |
接入方式 |
|---|---|---|---|
|
AI 框架 |
Spring AI |
1.1.3 |
ChatModel、Prompt、流式、多模态 |
|
对话 / 视觉 |
硅基流动 |
Qwen/Qwen3.5-397B-A17B |
OpenAI 兼容 API |
|
Embedding |
硅基流动 |
Qwen/Qwen3-Embedding-8B |
兼容 /v1/embeddings |
|
向量库 |
Milvus |
2.5.8 SDK |
自定义实现,kid 作集合名 |
|
稳定性 |
Resilience4j |
2.2.0 |
熔断、限流、舱壁 |
模型配置存平台模型表,按 modelName 动态读取;Embedding 按 kid 查知识库关联的向量模型。
二、硅基流动接入(核心坑点)
2.1 baseUrl 不能带 /v1
Spring AI 请求 URL = baseUrl + "/v1/chat/completions"。若 baseUrl 配成 https://api.siliconflow.cn/v1,会变成 .../v1/v1/chat/completions,404。
✅ 正确:https://api.siliconflow.cn(协议 + 主机,不带 /v1)❌ 错误:https://api.siliconflow.cn/v1
配置标准化时,会对硅基流动地址自动去掉末尾 /v1。
2.2 Embedding 接入
按 kid 查知识库关联的向量模型(功能默认 embedding 或平台 category=vector)。apiHost 含 siliconflow 或 modelName 以 BAAI/ 开头时,走硅基流动 Embedding 实现。
请求:POST {apiHost}/v1/embeddings(apiHost 末尾自动补 /)
请求体:
{ "model": "Qwen/Qwen3-Embedding-8B", "input": ["text"], "encoding_format": "float" }
响应:data[0].embedding 为 float 数组
⚠️ readTimeout=120s(Qwen3-Embedding-8B 计算慢)
2.3 思维链:category=reasoning 时传 enable_thinking=false
构建请求 Options 时,若模型 category 为 reasoning,需在请求体传 enable_thinking: false,否则会输出冗长推理过程。
关键:平台模型表的 category 需正确配置。思维链模型填 reasoning,非推理模型填 chat/vision,否则可能 400。
|
category |
说明 |
enable_thinking |
|---|---|---|
|
reasoning |
思考 / 推理模型 |
传 false |
|
chat |
通用聊天模型 |
不传 |
|
vision |
多模态视觉模型 |
不传 |
三、向量存储:Milvus 自定义实现
3.1 为什么自定义?
Spring AI 自带的 Milvus 实现存在 vector 字段缺失问题,需自定义实现。
3.2 核心实现要点
|
要点 |
说明 |
|---|---|
|
集合名 = kid |
每个知识库一个 collection,用 kid 作集合名,天然隔离 |
|
维度动态探测 |
用短文本调用 embed 取维度,失败默认 1024,避免写死 |
|
插入后必须 load |
insert 后 loadCollection,否则检索不到(Milvus 特性) |
|
索引同步建 |
插入成功后建 IVF_FLAT 索引,已存在则跳过 |
|
集合自动创建 |
首次使用前检查,不存在则创建集合和索引 |
四、RAG 设计:90% 的人把上下文放错地方了
4.1 方案要点
System:只放规则 + 人设,不含检索内容
User:放问题 + 上下文,用 --- BEGIN CONTEXT --- /--- END CONTEXT --- 包起来
4.2 流程
向量相似度检索,获取 topK 相关文档
topK 从知识库配置的 retrieveLimit 动态取,默认 3-5 条
无检索结果 → 空上下文提示 + 用户问题
有结果 → 构建 System(人设 + 规则)+ User(问题 + 上下文)→ 流式调用模型
4.3 注意点
|
注意点 |
说明 |
|---|---|
|
上下文别放 System |
否则模型易把知识库当身份,输出 “根据检索到的上下文” |
|
规则强调「不许编造」 |
固定规则:“未找到时回答‘不清楚’”,减少幻觉 |
|
topK 按知识库配置 |
避免全局写死,一般 3~10 条,太多会引入噪音 |
|
多模态时暂不走 RAG |
有图片时保留多模态能力,不走 kid 检索 |
五、知识库 ETL:分离事务
5.1 流程
Extract:文档读取(PDF/Word/TXT)
Transform:按块大小、重叠字符、分隔符分割
Load:存关系库(短事务)→ 向量化 + 存 Milvus(无事务)
5.2 核心:数据库与向量化分步
若全在一个事务:Embedding API 耗时长(秒级),事务占连接,易 Lock wait timeout。
✅ 方案:数据库短事务快速提交,向量化无 DB 事务。
5.3 分割参数按知识库配置
分隔符、块大小、重叠字符存知识库元数据,默认 \n、100、100,支持不同知识库不同策略。
六、多模型与智能体
6.1 策略模式
按 modelName 选策略,apiHost 指向硅基流动即可。从平台模型表按 modelName 取 apiKey、apiHost、category。
6.2 智能体
请求带 agentId 时,从智能体配置取 persona(model、prompt)、knowledge(attached),自动覆盖 model、System、kid。
6.3 注意点
|
注意点 |
说明 |
|---|---|
|
apiHost 按模型存 |
平台模型表,支持不同平台(硅基流动 / 阿里云等) |
|
category 决定 enable_thinking |
reasoning = 传 false,其他不传 |
|
agentId 优先 |
有 agentId 时,人设和 kid 以智能体为准 |
|
对话客户端可缓存 |
相同 key 复用,避免重复创建,注意过期策略 |
七、生产环境:熔断、限流、舱壁
Resilience4j 三层保护:
|
组件 |
作用 |
配置建议 |
|---|---|---|
|
熔断器 |
防止级联故障 |
failure-rate-threshold=50%,wait-duration=60s |
|
限流器 |
控制 QPS |
limit-for-period=100,limit-refresh-period=1s |
|
舱壁 |
隔离线程池 |
max-concurrent-calls=50 |
⚠️ 注意:Embedding 超时单独调大(120s),避免被熔断器误判;舱壁拒绝时打日志便于排查。
八、配置要点速查
# 对话/视觉:平台模型表
# api_host: https://api.siliconflow.cn (不要带 /v1)
# model_name: Qwen/Qwen3.5-397B-A17B
# category: vision 或 chat(思维链填 reasoning)
# Embedding:知识库关联的向量模型
# api_host: https://api.siliconflow.cn
# model_name: Qwen/Qwen3-Embedding-8B
milvus:
host: localhost
port: 19530
resilience4j:
circuitbreaker:
instances:
ai-chat:
failure-rate-threshold: 50
ratelimiter:
instances:
ai-chat:
limit-for-period: 100
bulkhead:
instances:
ai-chat:
max-concurrent-calls: 50
九、核心决策与注意点总表
|
模块 |
方案要点 |
关键技术 |
注意点 |
|---|---|---|---|
|
硅基流动 |
统一接入对话 + Embedding |
OpenAI 兼容 API |
baseUrl 不带 /v1 |
|
思维链 |
category=reasoning 传 enable_thinking=false |
extraBody |
非推理别填 reasoning |
|
Milvus |
自定义实现,kid = 集合名 |
insert→load、维度探测 |
插入后 load |
|
RAG |
System = 规则 + 人设,User = 问题 + 上下文 |
向量检索、Prompt 拼接 |
上下文别放 System |
|
Embedding |
按 kid 查,硅基流动 Qwen3-Embedding-8B |
/v1/embeddings |
超时 120s |
|
ETL |
库与向量分离事务 |
短事务 + 无事务 |
分割参数按 kid |
|
向量库 |
按 kid 缓存获取 |
每知识库一 collection |
缓存复用 |
|
稳定性 |
熔断 + 限流 + 舱壁 |
Resilience4j |
舱壁拒绝打日志 |
十、踩坑总结
回顾整个集成过程,最值得记住的几个坑:
baseUrl 不能带 /v1 —— Spring AI 会自动补,配错就是 404
category=reasoning 必须传 enable_thinking=false —— 否则输出冗长推理过程
Milvus 插入后必须 load —— 不 load 搜不到,这是 Milvus 特性
RAG 上下文别放 System —— 放 User 更干净,避免输出 “根据上下文”
Embedding 超时调大 —— Qwen3-Embedding-8B 计算慢,120s 是合理的
下一步可以做什么?
如果数据量超过百万级,考虑 Milvus 集群部署
如果需要更精准的检索,可以引入 Rerank 模型
如果需要多租户隔离,可以在 Milvus 中用 partition key 实现
如果觉得有用,欢迎点赞、收藏、评论交流
持续更新中
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)