一、背景与问题
在基于 RAG(Retrieval-Augmented Generation)的知识库问答系统中,当前主流技术栈通常包括:
- 应用层:Spring Boot + Spring AI
- 向量存储:Milvus
- Embedding / LLM:
- DeepSeek(高质量推理)
- 豆包(Doubao)
- Mimo(低成本模型)
典型流程如下:
- 文档切块(Chunking)
- 向量化(Embedding)
- 向量检索(TopK)
- 拼接上下文(Context)
- LLM 生成回答 核心问题
在实际落地过程中,会遇到以下问题:
- 成本问题
- 上下文较长(文档块 + 用户问题)
- 每次都调用 LLM(尤其是 DeepSeek)
- Token 消耗高(输入成本远高于输出)
- 性能问题
- LLM 响应延迟高
- 高频重复问题无法复用
- 效果问题
- 每次都是“从头推理”
- 无法利用历史高质量回答
二、优化目标
本方案主要围绕以下目标展开:
| 目标 | 描述 |
|---|---|
| 降低成本 | 减少 LLM 调用次数 + 使用低成本模型 |
| 提升响应速度 | 命中缓存直接返回 |
| 提升回答稳定性 | 复用高质量历史回答 |
| 保证数据一致性 | 文档更新后不污染结果 |
三、总体架构设计
整体优化思路为:模型分层 + 对话缓存复用 + 智能存储策略
架构分层
用户请求
↓
【1】历史对话向量库(缓存层)
↓(命中)
直接返回 / 半命中 → 低成本模型优化
↓(未命中)
【2】知识库向量检索(Milvus)
↓
【3】模型分层调用
- 低成本模型(Doubao / Mimo)
- 高质量模型(DeepSeek)
↓
【4】回答评估与存储
四、核心优化策略
4.1 对话缓存机制(核心)
设计思想
RAG 本质是“知识检索”,用户问题具有明显的重复性:
- FAQ 类问题
- 操作类问题
- 业务规则类问题
没有必要每次都调用 LLM
存储结构设计
向量库存储内容:
| 字段 | 内容 |
|---|---|
| embedding | 向量 |
| content | 问题文本 |
| metadata | chunkIds/ai_answer/question_text |
| id | id |
| 关键点: |
- 只对“问题”做 embedding(降低成本)
- 回答和上下文作为 metadata 存储
4.2 查询阶段优化(对话复用)
Step 1:查询历史对话库
对用户问题进行向量检索:
情况一:相似度 ≥ 0.9(强命中)
直接返回历史回答 不调用 LLM 响应速度最快 成本为 0
情况二:0.5 ≤ 相似度 < 0.9(弱命中)
处理策略:
- 取历史库 Top1
- 获取:
- 历史回答
- 历史文档块
- 同时执行:
- 知识库 Top5 检索
合并上下文: 历史文档块 + 知识库文档块 → LLM
模型选择策略
此阶段使用低成本模型: 原因:
| 模型 | 输入成本 |
|---|---|
| DeepSeek | ~2元 / 百万 token |
| Doubao | ~0.4元 / 百万 token |
| miMO | ~0.7元 / 百万 token |
成本降低约 80%
情况三:相似度 < 0.5(未命中)
标准 RAG 流程
4.3 模型分层策略
分层原则
不是所有请求都需要高质量模型。
模型分层设计
| 层级 | 模型 | 使用场景 |
|---|---|---|
| L1(缓存层) | 无 | 直接返回 |
| L2(低成本层) | Doubao / Mimo | 弱命中、简单问题 |
| L3(高质量层) | DeepSeek | 复杂问题 |
4.4 智能存储策略(关键)
为什么不能全部存?
如果所有回答都存储,会带来:
- 噪音数据
- 错误传播
- 存储膨胀
存储策略
仅对 DeepSeek 生成的回答进行存储判断
原因:
- DeepSeek 质量更高
- 更适合作为“知识沉淀”
存储判断流程
- LLM(DeepSeek)生成回答后
- 再调用一次 LLM(或规则引擎)进行判断:
判断内容:
- 是否通用问题?
- 是否具备复用价值?
- 是否包含敏感/权限信息?
存储规则设计 按实际业务场景设计存储规则,通常是通用类问题进行存储
五、数据一致性设计
问题
文档更新后:
- 历史缓存可能失效
- 回答可能错误
解决方案
-
文档版本控制
- 每个 chunk 绑定 doc_version
-
变更清理机制
当文档更新时:
- 删除相关历史缓存(按 doc_id)
六、收益分析
1. 成本优化
| 优化点 | 效果 |
|---|---|
| 缓存命中 | 0 成本 |
| 低成本模型替代 | 降低 80% |
| embedding 优化 | 减少向量计算 |
2. 性能提升
- 缓存命中:毫秒级
- 避免重复推理
- 降低 LLM 压力
3. 效果提升
- 复用高质量回答
- 降低 hallucination
- 提升稳定性