共计 1950 个字符,预计需要花费 5 分钟才能阅读完成。
为什么需要 RAG?
最近在做一个智能客服项目时,发现直接用 GPT 这类大模型会遇到两个头疼的问题:

- 知识更新延迟 :当公司产品价格调整后,模型还在用旧数据回答客户
- 专业领域盲区 :遇到技术文档细节查询时,模型开始一本正经地胡说
这就像让一个记忆力超强但从不看新闻的教授来回答时事问题——基础能力很强,但缺少最新信息输入。RAG(Retrieval-Augmented Generation/ 检索增强生成)刚好能解决这个问题,它让 AI 在回答前先「查资料」再组织语言。
框架选型实战
Java 生态里常见的选择有:
- LangChain4j:功能全面但依赖复杂,需要自己组装向量数据库、LLM 适配等模块
- AgentScope:开箱即用的 Java SDK,特别适合已有 Spring 技术栈的团队
对比测试发现,同样实现商品问答场景:
| 指标 | AgentScope 方案 | LangChain 方案 |
|---|---|---|
| 启动时间 | 2.1s | 4.7s |
| 平均响应延迟 | 328ms | 512ms |
| 依赖 JAR 包数量 | 7 个 | 15 个 |
四步搭建核心流程
1. 知识库准备
用 Spring Data Elasticsearch 建立产品文档索引,关键是要处理好 embedding(向量嵌入):
@Document(indexName = "product_knowledge")
public class ProductDoc {
@Id
private String id;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Dense_Vector, dims = 768) // 使用 BERT 向量维度
private float[] embedding;}
2. 检索增强实现
AgentScope 的 Java SDK 让检索和生成无缝衔接:
// 初始化检索器(带余弦相似度计算)Retriever retriever = new ElasticsearchRetriever("product_knowledge")
.setSimilarity(Similarity.COSINE);
// 构建 RAG 链
RAGChain chain = new RAGChain.Builder()
.withRetriever(retriever)
.withLLM(new OpenAIGPT()) // 可替换为国产模型
.withPromptTemplate("基于以下内容回答问题:\n{context}\n\n 问题:{query}")
.build();
3. 性能优化技巧
缓存策略 :用 Caffeine 做检索结果缓存,减少 ES 压力
LoadingCache<String, List<Document>> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(1, TimeUnit.HOURS)
.build(query -> retriever.search(query));
异步处理 :配置专用线程池避免阻塞
# application.properties
task.executor.pool.size=20
task.executor.queue.capacity=500
4. 安全防护
通过 Hook 机制添加敏感词过滤:
chain.addPreProcessor(query -> {if(SensitiveWordFilter.contains(query)) {throw new IllegalQueryException("包含敏感词");
}
return query;
});
生产环境指标
压测结果(单节点 4 核 8G):
| 并发数 | 平均响应时间 | P99 | 错误率 |
|---|---|---|---|
| 50 | 217ms | 423ms | 0% |
| 100 | 382ms | 728ms | 0.2% |
| 200 | 891ms | 1.4s | 1.5% |
进阶实践建议
- 冷启动优化 :服务启动时预加载高频查询 embedding
- 结果解释 :在返回答案时附带引用文档片段
- 动态更新 :监听数据库 binlog 触发知识库增量更新
动手实验
尝试修改 prompt 模板体验不同效果:
// 原始模板
String template1 = "请根据内容回答:{context}\n 问题:{query}";
// 增加角色设定
String template2 = "你是一个严谨的客服专家,只能根据以下材料回答:\n{context}\n\n 用户问:{query}";
调整后会发现第二个模板生成的答案会更克制,减少幻觉(hallucination)现象。
这次实践最大的体会是:RAG 不是银弹,但确实是现阶段平衡效果与成本的最佳选择。特别是用 AgentScope 这种轻量框架,两天就能搭出可用原型,这对业务快速迭代太重要了。下次我会分享如何用 Kubernetes 实现知识库的滚动更新,欢迎继续关注。
正文完
发表至: 技术分享
近三天内
