SpringBoot集成Ollama本地模型
目錄
- 項目準備
- 創建Ollama服務客戶端
- 創建控制器
- 配置應用屬性
- 創建前端界面
- 添加靜態資源支持
- 完整項目結構
- 啟動應用
- 高級功能擴展
- 部署注意事項
- 性能優化
1. 項目準備
- 創建一個SpringBoot項目,可以使用Spring Initializr或IDE創建
- 添加必要的依賴到
pom.xml
:<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- WebClient --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency> </dependencies>
2. 創建Ollama服務客戶端
package com.example.ollama.service;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.util.List;
import java.util.Map;@Slf4j
@Service
public class OllamaService {private final WebClient webClient;public OllamaService(@Value("${ollama.api.url:http://localhost:11434}") String ollamaApiUrl) {this.webClient = WebClient.builder().baseUrl(ollamaApiUrl).build();}/*** 生成文本*/public Mono<String> generateText(String model, String prompt, Double temperature) {Map<String, Object> requestBody = Map.of("model", model,"prompt", prompt,"temperature", temperature != null ? temperature : 0.7);return webClient.post().uri("/api/generate").bodyValue(requestBody).retrieve().bodyToMono(Map.class).map(response -> (String) response.get("response"));}/*** 聊天對話*/public Mono<String> chat(String model, List<Map<String, String>> messages) {Map<String, Object> requestBody = Map.of("model", model,"messages", messages);return webClient.post().uri("/api/chat").bodyValue(requestBody).retrieve().bodyToMono(Map.class).map(response -> {Map<String, Object> message = (Map<String, Object>) response.get("message");return (String) message.get("content");});}/*** 流式生成文本*/public Flux<String> streamGenerateText(String model, String prompt, Double temperature) {Map<String, Object> requestBody = Map.of("model", model,"prompt", prompt,"temperature", temperature != null ? temperature : 0.7,"stream", true);return webClient.post().uri("/api/generate").bodyValue(requestBody).retrieve().bodyToFlux(Map.class).map(response -> (String) response.get("response"));}
}
3. 創建控制器
package com.example.ollama.controller;import com.example.ollama.service.OllamaService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/api/ollama")
@RequiredArgsConstructor
public class OllamaController {private final OllamaService ollamaService;@PostMapping("/generate")public Mono<String> generateText(@RequestParam(defaultValue = "llama2") String model,@RequestParam String prompt,@RequestParam(required = false) Double temperature) {return ollamaService.generateText(model, prompt, temperature);}@PostMapping("/chat")public Mono<String> chat(@RequestParam(defaultValue = "llama2") String model,@RequestBody List<Map<String, String>> messages) {return ollamaService.chat(model, messages);}@PostMapping("/stream")public Flux<String> streamGenerateText(@RequestParam(defaultValue = "llama2") String model,@RequestParam String prompt,@RequestParam(required = false) Double temperature) {return ollamaService.streamGenerateText(model, prompt, temperature);}
}
4. 配置應用屬性
在application.properties
或application.yml
中添加配置:
# Ollama API配置
ollama.api.url=http://localhost:11434# 服務器配置
server.port=8080
5. 創建前端界面
創建一個簡單的HTML頁面用于與Ollama交互:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Ollama聊天界面</title><style>body {font-family: Arial, sans-serif;max-width: 800px;margin: 0 auto;padding: 20px;}.chat-container {border: 1px solid #ccc;border-radius: 5px;padding: 20px;margin-bottom: 20px;height: 400px;overflow-y: auto;}.message {margin-bottom: 10px;padding: 10px;border-radius: 5px;}.user-message {background-color: #e6f7ff;margin-left: 20%;}.ai-message {background-color: #f0f0f0;margin-right: 20%;}.input-container {display: flex;}#message-input {flex-grow: 1;padding: 10px;border: 1px solid #ccc;border-radius: 5px;margin-right: 10px;}button {padding: 10px 20px;background-color: #4CAF50;color: white;border: none;border-radius: 5px;cursor: pointer;}button:hover {background-color: #45a049;}</style>
</head>
<body><h1>Ollama聊天界面</h1><div class="chat-container" id="chat-container"></div><div class="input-container"><input type="text" id="message-input" placeholder="輸入消息..."><button onclick="sendMessage()">發送</button></div><script>const chatContainer = document.getElementById('chat-container');const messageInput = document.getElementById('message-input');// 按Enter鍵發送消息messageInput.addEventListener('keypress', function(e) {if (e.key === 'Enter') {sendMessage();}});function sendMessage() {const message = messageInput.value.trim();if (!message) return;// 添加用戶消息到聊天界面addMessage(message, 'user');messageInput.value = '';// 發送消息到后端fetch('/api/ollama/chat', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify([{'role': 'user','content': message}])}).then(response => response.text()).then(response => {// 添加AI回復到聊天界面addMessage(response, 'ai');}).catch(error => {console.error('Error:', error);addMessage('發生錯誤,請稍后重試。', 'ai');});}function addMessage(message, sender) {const messageDiv = document.createElement('div');messageDiv.classList.add('message');messageDiv.classList.add(sender === 'user' ? 'user-message' : 'ai-message');messageDiv.textContent = message;chatContainer.appendChild(messageDiv);chatContainer.scrollTop = chatContainer.scrollHeight;}</script>
</body>
</html>
6. 添加靜態資源支持
在SpringBoot應用中添加靜態資源支持:
package com.example.ollama.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");}
}
7. 完整項目結構
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── ollama/
│ │ ├── OllamaApplication.java
│ │ ├── controller/
│ │ │ └── OllamaController.java
│ │ ├── service/
│ │ │ └── OllamaService.java
│ │ └── config/
│ │ └── WebConfig.java
│ └── resources/
│ ├── static/
│ │ └── index.html
│ └── application.properties
8. 啟動應用
- 確保Ollama服務已啟動并運行在默認端口(11434)
- 運行SpringBoot應用
- 訪問
http://localhost:8080
查看聊天界面
9. 高級功能擴展
9.1 添加模型選擇功能
@GetMapping("/models")
public Mono<List<String>> listModels() {return webClient.get().uri("/api/tags").retrieve().bodyToMono(Map.class).map(response -> {List<Map<String, Object>> models = (List<Map<String, Object>>) response.get("models");return models.stream().map(model -> (String) model.get("name")).collect(Collectors.toList());});
}
9.2 添加流式響應支持
@GetMapping(value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> streamChat(@RequestParam(defaultValue = "llama2") String model,@RequestParam String message) {return ollamaService.streamGenerateText(model, message, 0.7).map(response -> ServerSentEvent.<String>builder().data(response).build());
}
9.3 添加會話管理
@Service
public class ChatSessionService {private final Map<String, List<Map<String, String>>> sessions = new ConcurrentHashMap<>();public List<Map<String, String>> getOrCreateSession(String sessionId) {return sessions.computeIfAbsent(sessionId, k -> new ArrayList<>());}public void addMessage(String sessionId, String role, String content) {List<Map<String, String>> messages = getOrCreateSession(sessionId);messages.add(Map.of("role", role, "content", content));}public void clearSession(String sessionId) {sessions.remove(sessionId);}
}
10. 部署注意事項
- 確保服務器上已安裝并運行Ollama服務
- 配置適當的防火墻規則,允許SpringBoot應用訪問Ollama服務
- 在生產環境中使用HTTPS保護API通信
- 考慮添加身份驗證和授權機制
- 監控Ollama服務的資源使用情況,避免過載
11. 性能優化
- 使用連接池管理WebClient連接
- 實現請求緩存,避免重復請求
- 使用異步處理提高并發能力
- 考慮使用響應式編程模式處理流式響應