如何用 Spring AI + Ollama 構(gòu)建生成式 AI 應(yīng)用
一、故事背景:Java 老炮兒與 AI 新秀的較量
上周,產(chǎn)品經(jīng)理拍著桌子說:"三天內(nèi)必須上線智能客服!要能回答訂單查詢、退換貨政策,還要會講冷笑話!" 我盯著需求文檔陷入沉思:傳統(tǒng)規(guī)則引擎就像老黃牛,拉不動這么重的活;調(diào)用 OpenAI 又怕數(shù)據(jù)泄露——這不是讓 Java 程序員在鋼絲上跳霹靂舞嗎?
這時候,實習(xí)生小王推了推眼鏡:"試試 Spring AI + Ollama 唄!本地部署大模型,既能裝逼又安全!" 這場景讓我想起《黑客帝國》里 Neo 看到數(shù)據(jù)流的瞬間——當我們還在用 if-else 寫邏輯時,年輕人已經(jīng)掏出了矩陣級解決方案。
二、技術(shù)選型:為什么是這對 CP?
1. Spring AI:Java 界的 AI 翻譯官
- 零門檻上車:@Autowired 注入 LLM 客戶端,比寫 MyBatis 還簡單
- 企業(yè)級 buff:支持模型版本控制、請求限流、審計日志,CTO 看了都說穩(wěn)
- 生態(tài)融合:和 Spring Boot 天生一對,老項目改造就像換火花塞
2. Ollama:本地部署的 AI 變形金剛
- 數(shù)據(jù)安全屋:所有計算本地完成,數(shù)據(jù)不出服務(wù)器半步
- 模型百寶箱:LLaMA2、Mistral、CodeLlama 應(yīng)有盡有
- 性能黑科技:基于 Metal Performance Shaders 加速,MacBook Pro 秒變煉丹爐
小王神補刀:"這就像你家樓下開了個私人影院,想看啥片自己選,還不怕被鄰居偷聽。"
三、實戰(zhàn)開發(fā):從 Hello World 到智能客服
第一步:環(huán)境搭建(10 分鐘搞定)
# 安裝 Ollama(Mac 專屬福利)
brew install ollama
# 啟動服務(wù)(像啟動 Tomcat 一樣簡單)
ollama serve
# 拉取中文模型(注意別手抖寫成 pull request)
ollama pull mistral:7b-v0.1
小插曲:小王把 pull
敲成 push
,結(jié)果把本地模型推到公共倉庫,嚇得他連夜改密碼——這波操作像極了把私人日記發(fā)朋友圈。
第二步:Spring AI 集成
<!-- 添加依賴,比追女朋友還直接 -->
<dependency>
<groupId>com.ai.ollama</groupId>
<artifactId>ollama-spring-boot-starter</artifactId>
<version>0.2.1</version>
</dependency>
配置文件設(shè)置模型參數(shù):
ollama:
endpoint: http://localhost:11434
model: mistral:7b-v0.1
temperature: 0.8 # 0.1 是鋼鐵直男,1.0 是話癆文藝青年
max_tokens: 256 # 回答長度控制,比領(lǐng)導(dǎo)講話還精煉
第三步:核心業(yè)務(wù)邏輯
@Service
public class ChatService {
private final OllamaClient ollamaClient;
public ChatService(OllamaClient ollamaClient) {
this.ollamaClient = ollamaClient;
}
public String generateResponse(String query) {
// 給 AI 穿上客服制服
String prompt = """
你是專業(yè)電商客服豆包,回答要簡潔。用戶問:%s
""".formatted(query);
// 調(diào)用模型生成回答,像調(diào)用 Dubbo 接口一樣絲滑
return ollamaClient.generate(OllamaRequest.builder()
.model("mistral:7b-v0.1")
.prompt(prompt)
.build())
.stream()
.map(OllamaResponse::getContent)
.collect(Collectors.joining());
}
}
隱藏彩蛋:當用戶問"你是誰"時,AI 會回答:"我是您的專屬豆包,由 Spring AI 和 Ollama 聯(lián)合驅(qū)動,比您的前任更可靠。"
四、性能優(yōu)化:讓 AI 跑得比老板的 KPI 還快
1. 緩存加速(給 AI 配小本本)
private final Map<String, String> cache = new ConcurrentHashMap<>();
public String generateResponse(String query) {
if (cache.containsKey(query)) return cache.get(query);
String response = ollamaClient.generate(...);
cache.put(query, response);
return response;
}
注意:涉及隱私的問題不能緩存,比如用戶的銀行卡密碼——AI 也得守規(guī)矩。
2. 異步處理(多線程拯救世界)
@Async("chatExecutor")
public CompletableFuture<String> generateResponseAsync(String query) {
return CompletableFuture.supplyAsync(() ->
ollamaClient.generate(...).stream().collect(Collectors.joining())
);
}
線程池配置建議:核心線程數(shù)=CPU 核心數(shù),最大線程數(shù)=核心數(shù)×2,隊列大小=核心數(shù)×10——比火鍋配菜搭配還講究。
3. 流式響應(yīng)(實時看 AI 打字)
@GetMapping("/stream")
public Flux<String> streamResponse(@RequestParam String query) {
return ollamaClient.generateStream(OllamaRequest.builder()
.prompt(query)
.build())
.map(OllamaResponse::getContent);
}
效果:用戶能看到"豆包正在思考中…",就像看主播直播寫代碼,體驗感拉滿。
五、進階玩法:解鎖 AI 的隱藏技能
1. 多模態(tài)交互(AI 識圖功能)
public String handleImageQuery(MultipartFile image) throws IOException {
String imageText = ocrService.recognize(image.getBytes());
return chatService.generateResponse(imageText);
}
應(yīng)用場景:用戶發(fā)產(chǎn)品圖問"這是什么型號",AI 直接返回購買鏈接——比導(dǎo)購員還機靈。
2. 上下文管理(記住聊天歷史)
private final Map<String, List<Message>> historyMap = new ConcurrentHashMap<>();
public String generateResponse(String userId, String message) {
List<Message> history = historyMap.computeIfAbsent(userId, k -> new ArrayList<>());
history.add(new Message("user", message));
String prompt = buildPromptWithHistory(history);
String response = ollamaClient.generate(prompt);
history.add(new Message("assistant", response));
return response;
}
效果:用戶說"昨天推薦的手機",AI 能接著之前的話題聊——比人類還記性好。
3. 自定義插件(給 AI 安裝 APP)
@Bean
public OllamaPlugin calculatorPlugin() {
return new OllamaPlugin("calculator")
.addFunction("calculate", this::calculate)
.addSchema(CalculatorSchema.class);
}
private Double calculate(CalculatorRequest req) {
return req.getA() + req.getB();
}
用戶問"100 加 50 等于多少",AI 直接調(diào)用插件計算,比程序員用 Excel 還快。
六、避坑指南:AI 開發(fā)的十大禁忌
- 模型越大越好:用 70B 模型回答"今天天氣如何",就像用牛刀殺雞
- 忽略 prompt 工程:直接把用戶問題丟給 AI,結(jié)果生成火星文
- 數(shù)據(jù)裸奔:把身份證號傳給云端模型,等于把金庫鑰匙交給陌生人
- 性能預(yù)估錯誤:用 8GB 內(nèi)存跑 70B 模型,結(jié)果服務(wù)器直接 OOM
- 沒有監(jiān)控報警:AI 返回"我要統(tǒng)治人類"才發(fā)現(xiàn)模型中毒
- 缺乏回退機制:模型故障時讓用戶干等,比春運搶票還絕望
- 倫理失守:生成虛假醫(yī)療建議,可能吃官司
- 版本混亂:不同環(huán)境用不同模型版本,導(dǎo)致回答人格分裂
- 技術(shù)黑話:返回"根據(jù)余弦相似度計算…",用戶直接黑人問號臉
- 沒有測試用例:直接上線生產(chǎn),結(jié)果用戶問"怎么退貨",AI 開始寫詩
血淚教訓(xùn):小王把 temperature 設(shè)為 1.5,AI 直接開始創(chuàng)作七言絕句,用戶投訴“
客服是文藝青年”——這波操作像極了讓數(shù)學(xué)老師教語文。
七、行業(yè)洞察:生成式 AI 的未來在哪里?
1. 企業(yè)級應(yīng)用爆發(fā)
- 代碼生成:自動補全、單元測試生成,程序員可能失業(yè)?
- 數(shù)據(jù)分析:自動生成 SQL 查詢,BI 工程師瑟瑟發(fā)抖
- 文檔處理:合同條款自動解析,法務(wù)部要換人?
2. 硬件軍備競賽
- 蘋果 M3 Max 芯片跑 30B 模型無壓力
- 國產(chǎn)昇騰芯片性能逼近英偉達 A100
- 量子計算研究取得突破,傳統(tǒng) GPU 瑟瑟發(fā)抖
3. 監(jiān)管政策收緊
- GDPR 要求 AI 生成內(nèi)容必須標注
- 中國《生成式人工智能服務(wù)管理暫行辦法》正式實施
- 歐盟 AI Act 將模型分為四個風(fēng)險等級