🍺 案例:Spring AI + RAG 打造“啤酒推荐师”
——AI调酒师在线营业,比人类更懂IPA配烤肉
1. 场景设定:啤酒界的“百科全书”
想象一个场景:用户问“什么啤酒配烟熏肉最合适?”,传统大模型可能只会回答“试试深色啤酒”——这就像让一个只喝过白开水的人推荐红酒。但结合RAG的Spring AI,瞬间变身“啤酒老饕”,能精准推荐“Smoked Porter Ale,酒精度8%,苦度36 IBU,带有咖啡和摩卡风味,完美搭配烟熏肉的油脂感”。
2. 数据准备:22,000种啤酒的“知识库”
数据来源:一个包含啤酒名称、酒精度(ABV)、苦度(IBU)、描述的JSON数据集,比如:
{
"id": "00gkb9",
"name": "Smoked Porter Ale",
"description": "The Porter Pounder...dry hopping",
"abv": 8,
"ibu": 36
}
加载到Redis:通过RagDataLoader类,在应用启动时将数据转换为向量并存入Redis:
// 创建JSON阅读器,指定关键字段
JsonReader loader = new JsonReader(file, "name", "abv", "ibu", "description");
// 自动注入VectorStore,将文档插入Redis
vectorStore.add(loader.get());
至此,Redis中已存储了22,000种啤酒的“风味密码”。
3. 代码实现:四步搞定RAG流程
① RAG服务层:RagService类处理用户查询,核心代码如下:
public Generation retrieve(String message) {
// 1. 检索最相关的啤酒文档
List<Document> docs = store.similaritySearch(SearchRequest.query(message).withTopK(5));
// 2. 构建提示词模板,结合上下文和用户问题
Prompt prompt = new Prompt(List.of(
new SystemMessage("你是一个啤酒专家,根据以下信息回答:" + docs),
new UserMessage(message)
));
// 3. 调用大模型生成回答
return client.call(prompt).getResult();
}
② 对外接口:通过RagController暴露HTTP端点:
@PostMapping("/chat")
public Message recommendBeer(@RequestBody String question) {
return Message.of(ragService.retrieve(question).getContent());
}
4. 效果演示:AI的“精准投喂”
用户提问:
curl http://localhost:8080/chat -d "What beer pairs well with smoked meats?"
AI响应:
推荐IPA或烟熏波特艾尔!
- Smoked Porter Ale(ABV 8%,IBU 36):烟熏麦芽与咖啡风味,完美平衡烟熏肉的油腻感。
- Son of Berserker Stout(ABV 6.9%):厚重口感搭配烟熏肉,仿佛在北欧篝火旁狂欢。
5. 技术亮点:Spring AI的“骚操作”
- 向量检索:利用Redis的语义搜索能力,秒级定位相关啤酒。
- 动态提示词:将检索结果嵌入提示词,让大模型“有的放矢”,避免胡说八道。
- 低成本高精度:相比直接喂给大模型长文本,RAG处理1000万字仅需$0.11,成本降低千倍。
6. 彩蛋:AI的“职业病”
如果你问“怎么选西瓜?”,这位“啤酒推荐师”可能会回答:“根据我的啤酒数据库,西瓜汁配小麦啤酒更解渴哦!”——毕竟,它连挑瓜都要先查资料!