下面是一个基于 Ollama 搭建本地大语言模型(LLM)服务,并通过 Java + Spring Boot + Vue + Spring Cloud 实现完整前后端交互的完整示例项目结构和代码说明。
该项目将展示如何:
- 使用
Ollama
部署本地 LLM 模型(如Llama3
,Qwen
,Phi3
等)。 - 通过 Spring Boot 构建 RESTful API 接口调用 Ollama。
- 使用 Vue 前端发送请求并显示模型返回结果。
- 可扩展为微服务架构(Spring Cloud)。
🧱 一、技术栈
技术 | 描述 |
---|---|
Ollama | 本地运行大模型,提供 OpenAI 兼容接口 |
Java 17+ | 后端开发语言 |
Spring Boot | 快速构建后端服务 |
Spring Web | 提供 RESTful API |
Vue 3 + Vite | 前端框架 |
Axios | 前端 HTTP 请求库 |
Spring Cloud (可选) | 微服务架构支持(Nacos / Gateway) |
📦 二、项目结构
ollama-ai-demo/
├── backend/ # Spring Boot 后端
│ ├── src/
│ │ └── main/
│ │ ├── java/com/example/demo/
│ │ │ ├── controller/AiController.java
│ │ │ ├── service/AiService.java
│ │ │ └── DemoApplication.java
│ │ └── resources/application.yml
│ └── pom.xml
│
├── frontend/ # Vue 前端
│ ├── src/
│ │ ├── components/
│ │ ├── views/
│ │ │ └── ChatView.vue
│ │ └── App.vue
│ └── vite.config.js
│
└── README.md
🛠️ 三、实现步骤详解
1. 安装 Ollama 并运行模型
# macOS 安装 Ollama
brew install ollama
# 运行一个模型(如 llama3)
ollama run llama3
默认情况下,Ollama 会在本地启动 HTTP 服务在 http://localhost:11434
,支持以下 API:
/api/chat
:聊天对话接口(JSON 格式)/api/generate
:生成文本接口
2. 创建 Spring Boot 后端服务
✅ 依赖配置 (pom.xml
)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
✅ 配置文件 (application.yml
)
server:
port: 8080
ollama:
url: http://localhost:11434/api/chat
✅ 请求封装类 (AiRequest.java
)
package com.example.demo.dto;
import java.util.List;
public class AiRequest {
private String model;
private List<Message> messages;
// Getters and Setters
}
✅ 响应封装类 (AiResponse.java
)
package com.example.demo.dto;
public class AiResponse {
private Message message;
public Message getMessage() {
return message;
}
public static class Message {
private String content;
public String getContent() {
return content;
}
}
}
✅ Service 层 (AiService.java
)
package com.example.demo.service;
import com.example.demo.dto.AiRequest;
import com.example.demo.dto.AiResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.*;
@Service
public class AiService {
@Value("${ollama.url}")
private String ollamaUrl;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
public AiService(RestTemplate restTemplate, ObjectMapper objectMapper) {
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
}
public String getResponse(String prompt) throws Exception {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "llama3");
requestBody.put("messages", Collections.singletonList(Map.of("role", "user", "content", prompt)));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(requestBody), headers);
ResponseEntity<String> response = restTemplate.postForEntity(ollamaUrl, entity, String.class);
// 解析 JSON 字符串
Map<String, Object> result = objectMapper.readValue(response.getBody(), Map.class);
Map<String, Object> message = (Map<String, Object>) result.get("message");
return (String) message.get("content");
}
}
✅ Controller 层 (AiController.java
)
package com.example.demo.controller;
import com.example.demo.service.AiService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class AiController {
private final AiService aiService;
public AiController(AiService aiService) {
this.aiService = aiService;
}
@PostMapping("/chat")
public String chat(@RequestBody Map<String, String> payload) throws Exception {
return aiService.getResponse(payload.get("prompt"));
}
}
3. 创建 Vue 前端页面 (ChatView.vue
)
<template>
<div>
<h2>本地大模型聊天助手</h2>
<input v-model="prompt" placeholder="输入问题..." />
<button @click="sendPrompt">发送</button>
<div v-if="response">
<strong>回答:</strong>{{ response }}
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const prompt = ref('')
const response = ref('')
const sendPrompt = async () => {
const res = await axios.post('http://localhost:8080/api/chat', {
prompt: prompt.value
})
response.value = res.data
}
</script>
📊 四、总结表格对比功能与模块
模块 | 技术 | 功能描述 |
---|---|---|
Ollama | 本地模型服务 | 提供 /api/chat 接口,运行本地大模型 |
Spring Boot | Java 后端 | 封装对 Ollama 的调用,暴露 REST API |
AiService | 服务层 | 处理请求、调用 Ollama、解析响应 |
AiController | 控制器 | 提供 /api/chat 接口给前端调用 |
Vue 3 + Vite | 前端框架 | 用户界面,调用后端 API 显示结果 |
Axios | HTTP 客户端 | 发送请求到后端 Spring Boot 接口 |
Spring Cloud(可选) | 微服务架构 | 支持注册中心、网关、配置中心等企业级功能 |
✅ 五、部署建议
-
开发环境:
- 启动 Ollama:
ollama run llama3
- 启动 Spring Boot:
./mvnw spring-boot:run
- 启动 Vue:
npm run dev
- 启动 Ollama:
-
生产环境:
- Docker 化部署 Ollama 和 Spring Boot 应用
- 使用 Nginx 或 Spring Cloud Gateway 统一代理
- 可使用 Spring Cloud Alibaba(Nacos + Sentinel)管理服务
📌 六、后续可扩展方向
扩展方向 | 实现方式 |
---|---|
对话历史记录 | 引入 Redis 缓存用户会话 |
多模型选择 | 在前端添加下拉框选择不同模型 |
权限控制 | 添加 JWT 登录认证机制 |
微服务化 | 使用 Spring Cloud Alibaba 拆分为多个服务 |
日志监控 | 引入 ELK(Elasticsearch + Logstash + Kibana) |
如果你希望我为你打包成完整 GitHub 项目模板、添加登录认证、或支持多模型切换,请继续提问!