
springboot项目调用本地和在线deepseek详解
springboot项目调用本地和在线deepseek教程来啦
·
springboot项目调用本地和在线deepseek详解
deepseek 日益火爆,是不是很多小伙伴跟我一样很好奇,都想在自己本地部署一个 deepseek 来玩一玩呢?当然使用 ollama 部署本地 deepseek 很方便,但是有没有小伙伴想跟我一样,自己使用java写一个脚本来实现下呢?这样不仅可以直接部署到你的项目中,而且遇到你不会想问题,直接切到 deepseek 菜单,直接提问就可以调用,是不是很酷炫呢?那么废话不多说,咱们开始吧!
下图是我自己设计的 JS智能问答系统:
1. Controller 层
package com.management.web.controller.myai;
import com.management.ai.service.IOllamaModelService;
import com.management.ai.service.IOllamaService;
import com.management.ai.service.IOllamaSessionService;
import com.management.common.annotation.Log;
import com.management.common.core.controller.BaseController;
import com.management.common.core.domain.AjaxResult;
import com.management.common.core.domain.ai.OllamaModel;
import com.management.common.core.domain.ai.OllamaQianWen;
import com.management.common.core.domain.ai.OllamaSession;
import com.management.common.enums.BusinessStatus;
import com.management.common.enums.BusinessType;
import com.management.common.enums.OperationResultEnum;
import com.management.common.utils.ShiroUtils;
import com.management.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.validation.Valid;
import java.util.List;
@Controller
@RequestMapping("/ollama/ai")
public class OllamaController extends BaseController {
//调用本地 deepseek 地址
private String LOCALHOST_BASE_URL = "http://localhost:11434/api/generate";
private String LOCALHOST_USE_MODEL = "deepseek-r1:14b";
//调用在线 deepseek 地址
private String ONLINE_BASE_URL = "https://api.deepseek.com/chat/completions";
private String ONLINE_USE_MODEL = "deepseek-chat";
private String ONLINE_APIKEY = "你deepseek的APIKEY";
@Autowired
private IOllamaService ollamaService;
@Autowired
private IOllamaSessionService ollamaSessionService;
@Autowired
private IOllamaModelService ollamaModelService;
private String prefix = "ai";
//前端页面
@GetMapping()
public String toIndex(ModelMap modelMap) {
return prefix + "/index";
}
/**
* 查询会话列表
*/
@PostMapping("/list")
@ResponseBody
public List<OllamaSession> list(OllamaSession ollamaSession) {
return ollamaSessionService.selectOllamaSessionList(ollamaSession);
}
/**
* 查询会话列表
*/
@PostMapping("/getHistoryList")
@ResponseBody
public List<OllamaQianWen> getHistoryList(OllamaQianWen ollamaQianWen) {
return ollamaService.selectListBySessionId(ollamaQianWen);
}
/**
* 跳转新增会话
*/
@GetMapping("/add")
public String add(ModelMap modelMap) {
List<OllamaModel> modelList = ollamaModelService.queryModelList();
modelMap.put("modelList", modelList);
return prefix + "/add";
}
/**
* 新增会话
*/
@Log(title = "新增会话", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(@ModelAttribute @Valid OllamaSession ollamaSession, BindingResult result) {
// 如果有错误,则返回错误信息
if (result.hasErrors()) {
return AjaxResult.error(result.getFieldError().getDefaultMessage());
}
String[] modelArr = ollamaSession.getMainAiModel().split("——");
ollamaSession.setMainAiModel(modelArr[0]);
ollamaSession.setUseModel(modelArr[1]);
String msg = ollamaModelService.verificationModel(ollamaSession);
if (!BusinessStatus.SUCCESS.toString().equals(msg)) {
return AjaxResult.error(msg);
}
return toAjax(ollamaSessionService.addSave(ollamaSession));
}
/**
* 跳转修改会话
*/
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap modelMap) {
OllamaSession ollamaSession = ollamaSessionService.selectOllamaSessionById(id);
ollamaSession.setMainAiModel(ollamaSession.getMainAiModel() + "——" + ollamaSession.getUseModel());
modelMap.put("ollamaSession", ollamaSession);
List<OllamaModel> modelList = ollamaModelService.queryModelList();
modelMap.put("modelList", modelList);
return prefix + "/edit";
}
/**
* 修改会话
*/
@Log(title = "修改会话", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(@ModelAttribute @Valid OllamaSession ollamaSession, BindingResult result) {
// 如果有错误,则返回错误信息
if (result.hasErrors()) {
return AjaxResult.error(result.getFieldError().getDefaultMessage());
}
String[] modelArr = ollamaSession.getMainAiModel().split("——");
ollamaSession.setMainAiModel(modelArr[0]);
ollamaSession.setUseModel(modelArr[1]);
String msg = ollamaModelService.verificationModel(ollamaSession);
if (!BusinessStatus.SUCCESS.toString().equals(msg)) {
return AjaxResult.error(msg);
}
return toAjax(ollamaSessionService.updateOllamaSession(ollamaSession));
}
/**
* 删除会话
*/
@Log(title = "删除会话", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids) {
return toAjax(ollamaSessionService.deleteSessionByIds(ids));
}
/*
普通调用 deepseek
即非流式输出 deepseek 答案,即问完问题后,deepseek 在后端加载完数据后,一次性输出给前端,缺点:不美观、交互性不好
*/
@PostMapping("/chat/v1")
@ResponseBody
public OllamaQianWen chatV1(OllamaQianWen ollamaQianWen) {
OllamaQianWen responseBody = null;
if (StringUtils.isEmpty(ollamaQianWen.getPrompt()) || ObjectUtils.isEmpty(ollamaQianWen.getSessionId())) {
return responseBody;
}
OllamaModel ollamaModel = getOllamaModel(ollamaQianWen);
ollamaQianWen.setIsOnline(ollamaModel.getIsOnline());
ollamaQianWen.setRequestUrl(ollamaModel.getRequestUrl());
ollamaQianWen.setUseModel(ollamaModel.getUseModel());
responseBody = ollamaService.invokeDeepSeekV1(ollamaQianWen, ONLINE_APIKEY);
return responseBody;
}
/*
流式调用 deepseek
即流式输出 deepseek 答案,deepseek 反馈多少,前端页面展示多少,优点:交互性好,缺点:不好控制前端展示格式
*/
@PostMapping(value = "/chat/v2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@ResponseBody
public SseEmitter chatV2(@RequestBody OllamaQianWen ollamaQianWen) {
// 使用 SseEmitter 流式输出
SseEmitter responseBody = null;
if (StringUtils.isEmpty(ollamaQianWen.getPrompt()) || ObjectUtils.isEmpty(ollamaQianWen.getSessionId())) {
return responseBody;
}
//-------------------由于我要收集 deepseek 问题和答案,所以需要存储到数据库中---------------------
String ip = ShiroUtils.getIp();
Long loginUserId = ShiroUtils.getLoginUserId();
OllamaModel ollamaModel = getOllamaModel(ollamaQianWen);
ollamaQianWen.setIsOnline(ollamaModel.getIsOnline());
ollamaQianWen.setRequestUrl(ollamaModel.getRequestUrl());
ollamaQianWen.setUseModel(ollamaModel.getUseModel());
ollamaQianWen.setUserId(loginUserId);
ollamaQianWen.setRequestIp(ip);
//----------------------------------------
responseBody = ollamaService.invokeDeepSeekV2(ollamaQianWen, ONLINE_APIKEY);
return responseBody;
}
private OllamaModel getOllamaModel(OllamaQianWen ollamaQianWen) {
//根据 sessionId 查询出使用的模型
OllamaSession ollamaSession = ollamaSessionService.selectOllamaSessionById(ollamaQianWen.getSessionId());
OllamaModel ollamaModel = ollamaModelService.selectByModel(ollamaSession.getMainAiModel(), ollamaSession.getUseModel());
if (ObjectUtils.isEmpty(ollamaModel)) {
throw new RuntimeException(OperationResultEnum.OLLAMA_MODEL_NOT_EXIST.getInfo());
}
return ollamaModel;
}
}
2. Service 层
package com.management.ai.service;
import com.management.common.core.domain.ai.OllamaQianWen;
import com.management.common.core.service.IBaseService;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
import java.util.List;
public interface IOllamaService extends IBaseService<OllamaQianWen> {
/**
* 普通响应
*/
OllamaQianWen invokeDeepSeekV1(OllamaQianWen ollamaQianWen, String apiKey);
/**
* 根据会话ID查询出所有历史会话数据
* @param ollamaQianWen
* @return
*/
List<OllamaQianWen> selectListBySessionId(OllamaQianWen ollamaQianWen);
/**
* 流式响应
*/
SseEmitter invokeDeepSeekV2(OllamaQianWen ollamaQianWen, String apiKey);
}
3. ServiceImpl 层
package com.management.ai.service.impl;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.management.ai.domain.model.*;
import com.management.ai.mapper.OllamaMapper;
import com.management.ai.service.IOllamaService;
import com.management.common.annotation.Anonymous;
import com.management.common.constant.Global;
import com.management.common.core.domain.ai.OllamaQianWen;
import com.management.common.core.service.impl.BaseServiceImpl;
import com.management.common.enums.BusinessStatus;
import com.management.common.utils.ShiroUtils;
import com.management.common.utils.StringUtils;
import okhttp3.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Mono;
import tk.mybatis.mapper.entity.Example;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
@Service
@Transactional(readOnly = true)
public class OllamaServiceImpl extends BaseServiceImpl<OllamaMapper, OllamaQianWen> implements IOllamaService {
private final OkHttpClient client = new OkHttpClient();
private final Gson gson = new Gson();
@Autowired
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
private OllamaMapper ollamaMapper;
/**
* 根据会话ID查询出所有历史会话数据
*
* @param ollamaQianWen
* @return
*/
@Override
public List<OllamaQianWen> selectListBySessionId(OllamaQianWen ollamaQianWen) {
if (ObjectUtils.isEmpty(ollamaQianWen.getSessionId())) {
return new ArrayList<>();
}
Long loginUserId = ShiroUtils.getLoginUserId();
Example example = new Example(OllamaQianWen.class);
example.orderBy("requestTime");
example.createCriteria()
.andEqualTo("userId", loginUserId)
.andEqualTo("sessionId", ollamaQianWen.getSessionId())
.andEqualTo("isValid", Global.TRUE);
return ollamaMapper.selectByExample(example);
}
/**
* 普通响应(非流式请求)
*/
@Override
@Transactional(readOnly = false)
@Anonymous
public OllamaQianWen invokeDeepSeekV1(OllamaQianWen ollamaQianWen, String apiKey) {
Request request = createRequestBody(ollamaQianWen, apiKey);
//设置请求时间
ollamaQianWen.setRequestTime(new Date());
StringBuilder tempRes = new StringBuilder();
ExceptionModel exceptionModel = new ExceptionModel();
try (Response response = client.newCall(request).execute()) {
//如果响应成功,并且返回体有内容,就输出内容,否则表示响应失败
if (response.isSuccessful() && response.body() != null) {
//解析响应流
ResponseBody responseBody = response.body();
String line;
while ((line = responseBody.source().readUtf8Line()) != null) {
logger.info("响应数据:【" + line + "】");
//调用本地 deepseek
if (!ollamaQianWen.getIsOnline()) {
LocalhostDeepSeekResponseModel jsonParse = gson.fromJson(line, LocalhostDeepSeekResponseModel.class);
logger.info("LocalhostDeepSeekResponseModel响应数据:【" + jsonParse.toString() + "】");
String responseResult = jsonParse.getResponse();
if (StringUtils.isNotBlank(responseResult) && !"stop".equals(jsonParse.getResponse())) {
tempRes.append(responseResult);
}
} else { //调用在线deepseek API
if (line.contains("data: ") && !line.contains("[DONE]")) {
DeepSeekResponseModel jsonParse = gson.fromJson(line.replace("data: ", ""), DeepSeekResponseModel.class);
logger.info("DeepSeekResponseModel响应数据:【" + jsonParse.toString() + "】");
List<DeepSeekResponseModel.Choices> choicesList = jsonParse.getChoices();
for (DeepSeekResponseModel.Choices temp : choicesList) {
String content = temp.getDelta().getContent();
if (StringUtils.isNotBlank(content) && !"stop".equals(temp.getFinishReason())) {
tempRes.append(temp.getDelta().getContent());
}
}
}
}
tempRes = new StringBuilder(tempRes.toString().replace("<think></think>", ""));
logger.info("响应结果:" + tempRes);
ollamaQianWen.setResponseTime(new Date());
}
}
} catch (IOException e) {
exceptionModel.setIsSuccess(Global.FALSE);
exceptionModel.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
}
ollamaQianWen.setResponseResult(tempRes.toString());
//异步新增
asynAddOllamaQianWen(ollamaQianWen, request.toString(), exceptionModel);
return ollamaQianWen;
}
/**
* 流式响应
*/
@Override
@Transactional(readOnly = false)
public SseEmitter invokeDeepSeekV2(OllamaQianWen ollamaQianWen, String apiKey) {
SseEmitter emitter = new SseEmitter(0L); // 0L 代表无超时
String request = createRequestBody2(ollamaQianWen, apiKey);
//设置请求时间
ollamaQianWen.setRequestTime(new Date());
StringBuilder tempRes = new StringBuilder();
ExceptionModel exceptionModel = new ExceptionModel();
WebClient webClient = WebClient.builder().build();
Subject subject = SecurityUtils.getSubject();
try {
subject.execute(() -> {
webClient.post()
.uri(ollamaQianWen.getRequestUrl())
.bodyValue(request)
.headers(httpHeaders -> {
httpHeaders.setContentType(org.springframework.http.MediaType.APPLICATION_JSON_UTF8);
// 使用 Bearer Token 认证
httpHeaders.setBearerAuth(apiKey);
})
.retrieve() //获取响应体
.onStatus(httpStatus -> httpStatus.is4xxClientError() || httpStatus.is5xxServerError(), clientResponse -> {
logger.info("Error Response: " + clientResponse.statusCode());
return Mono.error(new RuntimeException("请求失败"));
})
.bodyToFlux(String.class) //获取响应体的内容
.flatMap(line -> processStreamData(line, ollamaQianWen.getIsOnline())) //解析数据
.doOnTerminate(() -> {
logger.info("流处理结束,最终响应数据:" + tempRes.toString());
ollamaQianWen.setResponseResult(tempRes.toString());
ollamaQianWen.setResponseTime(new Date());
//异步新增
asynAddOllamaQianWen(ollamaQianWen, request, exceptionModel);
}) //结束时触发
.doOnNext(data -> {
try {
if (StringUtils.isNotBlank(data)) {
emitter.send(new MySseEventBuilderImpl().data(data)); // 发送数据到前端
logger.info("流式输出:" + data);
tempRes.append(data);
}
} catch (IOException e) {
emitter.completeWithError(e);
exceptionModel.setIsSuccess(Global.FALSE);
exceptionModel.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
}
})
.doOnComplete(emitter::complete)
.doOnError(e -> {
logger.error(e.getMessage());
exceptionModel.setIsSuccess(Global.FALSE);
exceptionModel.setErrorMessage(e.getMessage());
})
.subscribe(); // 启动异步请求
});
} catch (Exception e) {
emitter.completeWithError(e);
exceptionModel.setIsSuccess(Global.FALSE);
exceptionModel.setErrorMessage(e.getMessage());
logger.error(e.getMessage());
}
return emitter;
}
/**
* 异步新增 ollamaQianWen
* @param ollamaQianWen
* @param request
* @param exceptionModel
*/
@Transactional(readOnly = false)
public void asynAddOllamaQianWen(OllamaQianWen ollamaQianWen, String request, ExceptionModel exceptionModel) {
threadPoolExecutor.execute(() -> {
ollamaQianWen.setRequestParams(request);
ollamaQianWen.setUseModel(ollamaQianWen.getUseModel());
ollamaQianWen.setRequestUrl(ollamaQianWen.getRequestUrl());
//不为空表示请求成功
if (exceptionModel.getIsSuccess()) {
ollamaQianWen.setResponseStatus(BusinessStatus.SUCCESS.toString());
ollamaQianWen.setResponseResult(ollamaQianWen.getResponseResult());
} else {
ollamaQianWen.setResponseStatus(BusinessStatus.FAIL.toString());
ollamaQianWen.setResponseResult(exceptionModel.getErrorMessage());
}
logger.info("异步新增ollamaQianWen : " + ollamaQianWen.toString());
add(ollamaQianWen, ollamaQianWen.getUserId());
});
}
private String createRequestBody2(OllamaQianWen ollamaQianWen, String apiKey) {
String jsonBody = null;
if (ollamaQianWen.getIsOnline()) {
// 构建请求体
DeepSeekRequestModel.Message message = DeepSeekRequestModel.Message.builder().role("user").content(ollamaQianWen.getPrompt()).build();
DeepSeekRequestModel requestBody = DeepSeekRequestModel.builder().model(ollamaQianWen.getUseModel()).messages(Collections.singletonList(message)).stream(Global.TRUE).build();
//构建请求体json:{"messages":[{"content":"你好,DeepSeek!","role":"user"}],"model":"deepseek-chat"}
jsonBody = JSON.toJSONString(requestBody);
} else {
LocalhostDeepSeekRequestModel requestBody = LocalhostDeepSeekRequestModel.builder().model(ollamaQianWen.getUseModel()).prompt(ollamaQianWen.getPrompt()).temperature(0.7F).maxTokens(500).build();
//构建请求体json:{"prompt": "你好","model":"deepseek-chat","temperature":"0.7","max_tokens":"500"}
jsonBody = JSON.toJSONString(requestBody);
}
logger.info("构建请求体【" + jsonBody + "】");
return jsonBody;
}
/**
* 解析数据
*/
private Mono<String> processStreamData(String line, Boolean isOnline) {
logger.info("line响应数据:【" + line + "】");
String responseResult = null;
try {
if (isOnline) {
if (!line.contains("[DONE]")) {
DeepSeekResponseModel jsonParse = gson.fromJson(line.replaceAll("data:\\s*", ""), DeepSeekResponseModel.class);
logger.info("DeepSeekResponseModel响应数据:【" + jsonParse.toString() + "】");
List<DeepSeekResponseModel.Choices> choicesList = jsonParse.getChoices();
for (DeepSeekResponseModel.Choices temp : choicesList) {
String content = temp.getDelta().getContent();
if (StringUtils.isNotBlank(content) && !"stop".equals(temp.getFinishReason())) {
responseResult = temp.getDelta().getContent();
}
}
}
}else {
LocalhostDeepSeekResponseModel jsonParse = gson.fromJson(line, LocalhostDeepSeekResponseModel.class);
logger.info("LocalhostDeepSeekResponseModel响应数据:【" + jsonParse.toString() + "】");
responseResult = jsonParse.getResponse();
}
if (StringUtils.isNotBlank(responseResult)) {
return Mono.just(responseResult);
}
} catch (Exception e) {
return Mono.just("Error parsing JSON");
}
return Mono.empty();
}
/**
* 封装请求参数
*
* @return
*/
private Request createRequestBody(OllamaQianWen ollamaQianWen, String apiKey) {
Request request = null;
if (ollamaQianWen.getIsOnline()) {
// 构建请求体
DeepSeekRequestModel.Message message = DeepSeekRequestModel.Message.builder().role("user").content(ollamaQianWen.getPrompt()).build();
DeepSeekRequestModel requestBody = DeepSeekRequestModel.builder().model(ollamaQianWen.getUseModel()).messages(Collections.singletonList(message)).stream(Global.TRUE).build();
//构建请求体json:{"messages":[{"content":"你好,DeepSeek!","role":"user"}],"model":"deepseek-chat"}
String jsonBody = JSON.toJSONString(requestBody);
// 创建HTTP请求
request = new Request.Builder().url(ollamaQianWen.getRequestUrl()).post(RequestBody.create(jsonBody, MediaType.get("application/json"))).addHeader("Authorization", "Bearer " + apiKey).build();
} else {
LocalhostDeepSeekRequestModel requestBody = LocalhostDeepSeekRequestModel.builder().model(ollamaQianWen.getUseModel()).prompt(ollamaQianWen.getPrompt()).temperature(0.7F).maxTokens(500).build();
//构建请求体json:{"prompt": "你好","model":"deepseek-chat","temperature":"0.7","max_tokens":"500"}
String jsonBody = JSON.toJSONString(requestBody);
// 创建HTTP请求
request = new Request.Builder().url(ollamaQianWen.getRequestUrl()).post(RequestBody.create(jsonBody, MediaType.get("application/json"))).build();
}
logger.info("构建请求体【" + request + "】");
return request;
}
}
4. 实体类
OllamaQianWen
package com.management.common.core.domain.ai;
import com.management.common.annotation.Excel;
import com.management.common.core.domain.BaseEntity;
import com.management.common.enums.BusinessStatus;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.util.Date;
/**
- Ollama千问
- 3. @author management
- @date 2025-03-02
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Table(name = "ollama_qian_wen")
public class OllamaQianWen extends BaseEntity {
/** ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select RIGHT(uuid_short(), 19)")
private Long id;
/** 会话ID */
@Excel(name = "会话ID")
private Long sessionId;
/** 用户ID */
@Excel(name = "用户ID")
private Long userId;
@Excel(name = "请求IP")
private String requestIp;
@Excel(name = "请求时间")
private Date requestTime;
@Excel(name = "请求接口")
private String requestUrl;
@Excel(name = "使用模型")
private String useModel;
@Excel(name = "请求问题")
private String prompt;
@Excel(name = "请求参数")
private String requestParams;
@Excel(name = "响应结果")
private String responseResult;
@Excel(name = "响应时间")
private Date responseTime;
@Transient
private Boolean isOnline;
@Transient
private String apiKey;
/**
* 响应成功状态(0-响应失败;1-响应成功;2-响应中断;3-响应等待)
*/
@Excel(name = "响应成功状态")
private String responseStatus;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getRequestIp() {
return requestIp;
}
public void setRequestIp(String requestIp) {
this.requestIp = requestIp;
}
public Date getRequestTime() {
return requestTime;
}
public void setRequestTime(Date requestTime) {
this.requestTime = requestTime;
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl;
}
public String getUseModel() {
return useModel;
}
public void setUseModel(String useModel) {
this.useModel = useModel;
}
public String getRequestParams() {
return requestParams;
}
public void setRequestParams(String requestParams) {
this.requestParams = requestParams;
}
public String getResponseResult() {
return responseResult;
}
public void setResponseResult(String responseResult) {
this.responseResult = responseResult;
}
public Date getResponseTime() {
return responseTime;
}
public void setResponseTime(Date responseTime) {
this.responseTime = responseTime;
}
public String getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}
public Long getSessionId() {
return sessionId;
}
public void setSessionId(Long sessionId) {
this.sessionId = sessionId;
}
public String getPrompt() {
return prompt;
}
public void setPrompt(String prompt) {
this.prompt = prompt;
}
public Boolean getIsOnline() {
return isOnline;
}
public void setIsOnline(Boolean isOnline) {
this.isOnline = isOnline;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
@Override
public String toString() {
return "OllamaQianWen{" +
"id=" + id +
", sessionId=" + sessionId +
", userId=" + userId +
", requestIp='" + requestIp + '\'' +
", requestTime=" + requestTime +
", requestUrl='" + requestUrl + '\'' +
", useModel='" + useModel + '\'' +
", prompt='" + prompt + '\'' +
", requestParams='" + requestParams + '\'' +
", responseResult='" + responseResult + '\'' +
", responseTime=" + responseTime +
", isOnline=" + isOnline +
", apiKey='" + apiKey + '\'' +
", responseStatus='" + responseStatus + '\'' +
'}';
}
}
OllamaModel
package com.management.common.core.domain.ai;
import com.management.common.annotation.Excel;
import com.management.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
@Table(name = "ollama_model")
public class OllamaModel extends BaseEntity {
/** ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select RIGHT(uuid_short(), 19)")
private Long id;
@NotBlank(message = "AI大模型不能为空")
@Excel(name = "AI大模型")
private String mainAiModel;
@NotBlank(message = "使用模型不能为空")
@Excel(name = "使用模型")
private String useModel;
@Excel(name = "在线/本地")
private Boolean isOnline = false;
@Excel(name = "请求接口")
private String requestUrl;
@Excel(name = "是否开发完成(0:未完成;1-已完成)")
private Boolean isFinish;
@Excel(name = "是否启用(0:不启用;1-启用)")
private Boolean isOpen;
@Excel(name = "启用时间")
private Date startTime;
@Excel(name = "结束时间")
private Date endTime;
}
OllamaSession
package com.management.common.core.domain.ai;
import com.management.common.annotation.Excel;
import com.management.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
@Data
@EqualsAndHashCode(callSuper = true)
@Table(name = "ollama_session")
public class OllamaSession extends BaseEntity {
/** ID */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select RIGHT(uuid_short(), 19)")
private Long id;
/**
* 用户ID
*/
@Excel(name = "用户ID")
private Long userId;
@NotBlank(message = "会话标题不能为空")
@Excel(name = "会话标题")
private String sessionTitle;
@NotBlank(message = "AI大模型不能为空")
@Excel(name = "AI大模型")
private String mainAiModel;
@Excel(name = "使用模型")
private String useModel;
@Excel(name = "在线/本地")
private Boolean isOnline;
@Excel(name = "用途")
private String purpose;
}
DeepSeekRequestModel
package com.management.ai.domain.model;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
* @author 吴嘉诚
* @date 2025/2/24 10:08
* @desc
*/
@Data
@Builder
public class DeepSeekRequestModel {
/**
* 所用DeepSeek模型
*/
private String model;
private Boolean stream;
private List<Message> messages;
/**
* 消息体
*/
@Data
@Builder
public static class Message {
private String role;
private String content;
}
}
DeepSeekResponseModel
package com.management.ai.domain.model;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class DeepSeekResponseModel {
private String id;
private String object;
private String created;
@SerializedName("system_fingerprint")
private String systemFingerprint;
private List<Choices> choices;
private Usage usage;
@Data
@Builder
public static class Choices {
private Integer index;
private Delta delta;
private String logprobs;
@SerializedName("finish_reason")
private String finishReason;
}
@Data
@Builder
public static class Delta {
private String content;
}
@Data
@Builder
public static class Usage {
@SerializedName("prompt_tokens")
private Integer promptTokens;
@SerializedName("completion_tokens")
private Integer completionTokens;
@SerializedName("total_tokens")
private Integer totalTokens;
@SerializedName("prompt_tokens_details")
private PromptTokensDetails promptTokensDetails;
@SerializedName("prompt_cache_hit_tokens")
private Integer promptCacheHitTokens;
@SerializedName("prompt_cache_miss_tokens")
private Integer promptCacheMissTokens;
}
@Data
@Builder
public static class PromptTokensDetails {
@SerializedName("cached_tokens")
private Integer cachedTokens;
}
}
ExceptionModel
package com.management.ai.domain.model;
import com.management.common.constant.Global;
/**
* @author 吴嘉诚
* @date 2025/3/10 22:10
* @desc
*/
public class ExceptionModel {
private boolean isSuccess = Global.TRUE;
private String errorMessage;
public boolean getIsSuccess() {
return isSuccess;
}
public void setIsSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
- LocalhostDeepSeekRequestModel
package com.management.ai.domain.model;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LocalhostDeepSeekRequestModel {
private String model;
private String prompt;
private Float temperature;
private Integer maxTokens;
}
LocalhostDeepSeekResponseModel
package com.management.ai.domain.model;
import com.google.gson.annotations.SerializedName;
import lombok.Builder;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
@Builder
public class LocalhostDeepSeekResponseModel {
private String model;
private Date createdAt;
private String response;
private Boolean done;
@SerializedName("done_reason")
private String doneReason;
private List<String> context;
@SerializedName("total_duration")
private String totalDuration;
@SerializedName("load_duration")
private String loadDuration;
@SerializedName("prompt_eval_count")
private Integer promptEvalCount;
@SerializedName("prompt_eval_duration")
private String promptEvalDuration;
@SerializedName("eval_count")
private Integer evalCount;
@SerializedName("eval_duration")
private String evalDuration;
}
Message
package com.management.ai.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Message {
@JsonProperty("role")
private String role;
@JsonProperty("content")
private String content;
public Message(String role, String content) {
this.role = role;
this.content = content;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
以上就是所有的后端代码啦,大家可以去试试咯!!!在自己项目中部署一个流式输出的、又能灵活调用本地和在线 deepseek 、问题和答案还能保留到本地的数据库,太酷了!!!
我以后也会继续分享一些实用的代码,有需要的可以自取哦,麻烦关注三连,谢谢!!!
更多推荐
所有评论(0)