添加智能对话功能代码

main
gitee 1 week ago
parent 797c3257ac
commit 969a7cf534

@ -109,6 +109,10 @@
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

@ -3,6 +3,7 @@ package com.supervision.config;
import com.supervision.constant.ResultStatusEnum;
import com.supervision.dto.R;
import com.supervision.exception.BusinessException;
import com.supervision.exception.UnauthorizedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ -44,6 +45,15 @@ public class ExceptionHandlerConfig {
return R.fail(511, exception.getMessage());
}
@ExceptionHandler(UnauthorizedException.class)
public R<?> unauthorizedExceptionResponse(UnauthorizedException exception) {
log.error("=========运行异常=========>>>");
log.error(exception.getMessage(), exception);
log.error("<<<=========运行异常=========");
return R.fail(400, exception.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public R<?> manualValidationExceptionResponse(RuntimeException exception) {
log.error("=========运行异常=========>>>");

@ -36,7 +36,7 @@ public class SecurityConfig {
http
.csrf(AbstractHttpConfigurer::disable) // 禁用CSRF
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/auth/**","/agent/streamChat").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session

@ -0,0 +1,15 @@
package com.supervision.constant;
public class PromptTemplate {
public static final String GENERAL_INDUSTRY_TEMPLATE = """
{query}
""";
public static final String HEART_GUIDE_TEMPLATE = """
怀
{query}
""";
}

@ -0,0 +1,46 @@
package com.supervision.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.domain.UserDetail;
import com.supervision.dto.AgentChatReqDTO;
import com.supervision.dto.AgentInfoDTO;
import com.supervision.dto.ChatResponseDTO;
import com.supervision.dto.R;
import com.supervision.service.AgentService;
import com.supervision.util.UserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
@Slf4j
@RestController
@RequestMapping("/agent")
@RequiredArgsConstructor
public class AgentController {
private final AgentService agentService;
/**
*
* @param agentChatReqDTO agentChatReqDTO
* @return
*/
@PostMapping(value = "/streamChat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ChatResponseDTO> streamChat(@RequestBody AgentChatReqDTO agentChatReqDTO) {
UserDetail userDetail = UserUtil.currentUser();
agentChatReqDTO.setUserId(userDetail.getUserId());
return agentService.streamChat(agentChatReqDTO);
}
@GetMapping("/pageList")
public R<IPage<AgentInfoDTO>> pageList(@RequestParam (name = "page", required = false,defaultValue = "1") Integer page,
@RequestParam (name = "pageSize", required = false,defaultValue = "10") Integer pageSize) {
IPage<AgentInfoDTO> paged = agentService.pageList(page, pageSize);
return R.ok(paged);
}
}

@ -0,0 +1,26 @@
package com.supervision.controller;
import cn.hutool.core.lang.Assert;
import com.supervision.dto.R;
import com.supervision.service.AuthService;
import com.supervision.vo.LoginReqVo;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
@PostMapping("/login")
public R<String> login(@RequestBody LoginReqVo loginReqVo) {
Assert.notEmpty(loginReqVo.getUsername(), "用户名不能为空");
String token = authService.login(loginReqVo.getUsername(), loginReqVo.getPassword());
return R.ok(token);
}
}

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -59,12 +57,14 @@ public class AgentDialogueLog implements Serializable {
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -44,12 +42,14 @@ public class AgentInfo implements Serializable {
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -60,12 +58,14 @@ public class DigitalHuman implements Serializable {
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -54,12 +52,14 @@ public class DigitalHumanDialogueLog implements Serializable {
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -1,11 +1,8 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -24,17 +21,19 @@ public class SysByteArray implements Serializable {
/**
*
*/
private Object bytes;
private byte[] bytes;
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -21,11 +19,6 @@ public class SysUser implements Serializable {
@TableId
private String id;
/**
* id
*/
private String appId;
/**
*
*/
@ -42,24 +35,16 @@ public class SysUser implements Serializable {
private String status;
/**
*
*/
private String createUserId;
/**
*
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
/**
*
*/
private String updateUserId;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -0,0 +1,32 @@
package com.supervision.domain;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
public class UserDetail extends User {
private String userId;
public UserDetail(String userId ,String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
this.userId = userId;
}
public UserDetail(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public UserDetail(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
}

@ -1,11 +1,9 @@
package com.supervision.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDateTime;
import lombok.Data;
/**
@ -34,12 +32,14 @@ public class VoiceInfo implements Serializable {
/**
*
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
*
*/
private Date updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;

@ -0,0 +1,27 @@
package com.supervision.dto;
import lombok.Data;
@Data
public class AgentChatReqDTO {
/**
* id
*/
private String agentId;
/**
*
*/
private String query;
/**
* id
*/
private String conversationId;
/**
* id
*/
private String userId;
}

@ -0,0 +1,87 @@
package com.supervision.dto;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.supervision.domain.AgentDialogueLog;
import lombok.Data;
import java.time.Duration;
import java.time.LocalDateTime;
@Data
public class AgentDialogueLogDTO {
/**
* id
*/
private String id;
/**
* id
*/
private String userId;
/**
* id
*/
private String conversationId;
/**
*
*/
private String userInput;
/**
*
*/
private String systemOut;
/**
*
*/
private Long timeCost;
/**
* 0 1
*/
private Integer answerType = 0;
/**
* id
*/
private String agentId;
/**
*
*/
private LocalDateTime createTime;
public AgentDialogueLogDTO() {
}
public AgentDialogueLogDTO(AgentChatReqDTO agentChatReqDTO) {
this.userId = agentChatReqDTO.getUserId();
if (StrUtil.isEmpty(agentChatReqDTO.getConversationId())){
this.conversationId = UUID.fastUUID().toString();// 生成一个新的对话ID
} else {
this.conversationId = agentChatReqDTO.getConversationId();
}
this.agentId = agentChatReqDTO.getAgentId();
this.userInput = agentChatReqDTO.getQuery();
this.createTime = LocalDateTime.now();
}
public AgentDialogueLog toDialogueLog(){
AgentDialogueLog dialogueLog = new AgentDialogueLog();
dialogueLog.setId(this.id);
dialogueLog.setUserId(this.userId);
dialogueLog.setAgentId(this.agentId);
dialogueLog.setAnswerType(this.answerType);
dialogueLog.setConversationId(this.conversationId);
dialogueLog.setUserInput(this.userInput);
dialogueLog.setSystemOut(this.systemOut);
if (null != this.createTime){
dialogueLog.setTimeCost(Duration.between(this.createTime, LocalDateTime.now()).toMillis());
}
return dialogueLog;
}
}

@ -0,0 +1,44 @@
package com.supervision.dto;
import com.supervision.domain.AgentInfo;
import lombok.Data;
@Data
public class AgentInfoDTO {
/**
* id
*/
private String id;
/**
* code
*/
private String agentCode;
/**
*
*/
private String agentName;
/**
*
*/
private String agentDesc;
/**
* 0 1
*/
private String adapterStatus;
public AgentInfoDTO() {
}
public AgentInfoDTO(AgentInfo agentInfo) {
this.id = agentInfo.getId();
this.agentCode = agentInfo.getAgentCode();
this.agentName = agentInfo.getAgentName();
this.agentDesc = agentInfo.getAgentDesc();
this.adapterStatus = agentInfo.getAdapterStatus();
}
}

@ -0,0 +1,22 @@
package com.supervision.dto;
import lombok.Data;
@Data
public class ChatResponseDTO {
/**
* message, message_end
*/
private String event;
/**
* id
*/
private String conversationId;
/**
*
*/
private String answer;
}

@ -0,0 +1,15 @@
package com.supervision.exception;
public class UnauthorizedException extends RuntimeException {
public UnauthorizedException() {
super("用户未登录");
}
public UnauthorizedException(String message) {
super(message);
}
public UnauthorizedException(String message, Throwable cause) {
super(message, cause);
}
}

@ -1,5 +1,7 @@
package com.supervision.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.domain.AgentDialogueLog;
import com.baomidou.mybatisplus.extension.service.IService;
@ -10,4 +12,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface AgentDialogueLogService extends IService<AgentDialogueLog> {
/**
*
* @param page
* @param conversationId ID
* @return
*/
IPage<AgentDialogueLog> pageList(Page<AgentDialogueLog> page, String conversationId);
}

@ -0,0 +1,25 @@
package com.supervision.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.supervision.dto.AgentChatReqDTO;
import com.supervision.dto.AgentInfoDTO;
import com.supervision.dto.ChatResponseDTO;
import reactor.core.publisher.Flux;
public interface AgentService {
/**
*
* @param agentChatReqDTO agentChatReqDTO
* @return
*/
Flux<ChatResponseDTO> streamChat(AgentChatReqDTO agentChatReqDTO);
/**
*
* @param page
* @param pageSize
* @return
*/
IPage<AgentInfoDTO> pageList(Integer page, Integer pageSize);
}

@ -0,0 +1,23 @@
package com.supervision.service;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.embedding.Embedding;
import reactor.core.publisher.Flux;
import java.util.List;
/**
* @description: AI
*/
public interface AiCallService {
String call(String prompt);
Flux<ChatResponse> stream(Prompt prompt);
Embedding embedding(String text);
List<Embedding> embedding(List<String> texts);
}

@ -0,0 +1,7 @@
package com.supervision.service;
public interface AuthService {
String login(String username, String password);
}

@ -0,0 +1,54 @@
package com.supervision.service;
import org.springframework.ai.chat.model.ChatResponse;
public class ThinkTagState {
private boolean inThink = false;
private final StringBuilder buffer = new StringBuilder();
private ChatResponse chatResponse;
public ThinkTagState() {
System.out.println("ThinkTagState initialized");
}
public ThinkTagState process(String chunk) {
StringBuilder output = new StringBuilder();
String remaining = chunk;
while (!remaining.isEmpty()) {
if (!inThink) {
int startIdx = remaining.indexOf("<think>");
if (startIdx == -1) {
output.append(remaining);
break;
}
output.append(remaining.substring(0, startIdx));
inThink = true;
remaining = remaining.substring(startIdx + "<think>".length());
} else {
int endIdx = remaining.indexOf("</think>");
if (endIdx == -1) {
break; // 等待后续分块
}
inThink = false;
remaining = remaining.substring(endIdx + "</think>".length());
}
}
buffer.append(output);
return this;
}
public String getFilteredText() {
return buffer.toString();
}
public ChatResponse getChatResponse() {
return chatResponse;
}
public void setChatResponse(ChatResponse chatResponse) {
this.chatResponse = chatResponse;
}
}

@ -1,5 +1,7 @@
package com.supervision.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.domain.AgentDialogueLog;
import com.supervision.service.AgentDialogueLogService;
@ -15,6 +17,13 @@ import org.springframework.stereotype.Service;
public class AgentDialogueLogServiceImpl extends ServiceImpl<AgentDialogueLogMapper, AgentDialogueLog>
implements AgentDialogueLogService{
@Override
public IPage<AgentDialogueLog> pageList(Page<AgentDialogueLog> page, String conversationId) {
return this.lambdaQuery()
.eq(AgentDialogueLog::getConversationId, conversationId)
.orderByDesc(AgentDialogueLog::getCreateTime)
.page(page);
}
}

@ -2,6 +2,7 @@ package com.supervision.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.domain.AgentInfo;
import com.supervision.dto.AgentDialogueLogDTO;
import com.supervision.service.AgentInfoService;
import com.supervision.mapper.AgentInfoMapper;
import org.springframework.stereotype.Service;

@ -0,0 +1,118 @@
package com.supervision.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.supervision.constant.PromptTemplate;
import com.supervision.domain.AgentDialogueLog;
import com.supervision.domain.AgentInfo;
import com.supervision.dto.AgentChatReqDTO;
import com.supervision.dto.AgentDialogueLogDTO;
import com.supervision.dto.AgentInfoDTO;
import com.supervision.dto.ChatResponseDTO;
import com.supervision.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.metadata.ChatResponseMetadata;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class AgentServiceImpl implements AgentService {
private final AiCallService aiCallService;
private final AgentInfoService agentInfoService;
private final AgentDialogueLogService agentDialogueLogService;
@Override
public Flux<ChatResponseDTO> streamChat(AgentChatReqDTO agentChatReqDTO) {
// 查询历史对话(记忆功能)
List<Message> messages = buildHistoryMessages(agentChatReqDTO.getConversationId(), 10);
// 构建当前对话
Message message = buildQueryMessage(agentChatReqDTO.getQuery(), agentChatReqDTO.getAgentId());
Assert.notNull(message, "Agent not found for ID: " + agentChatReqDTO.getAgentId());
messages.add(message);
AgentDialogueLogDTO dialogueLogDTO = new AgentDialogueLogDTO(agentChatReqDTO);
StringBuilder aiResponseBuilder = new StringBuilder();
Flux<ChatResponseDTO> map = aiCallService.stream(new Prompt(messages))
.scan(new ThinkTagState(), (state, response) -> {
String chunk = response.getResult().getOutput().getText();
state.setChatResponse(response);
return state.process(chunk);
})
.filter(state -> StrUtil.isNotEmpty(state.getFilteredText()))
.map(response -> {
ChatResponseDTO responseDTO = new ChatResponseDTO();
responseDTO.setAnswer(response.getChatResponse().getResult().getOutput().getText());
responseDTO.setConversationId(StrUtil.isNotEmpty(agentChatReqDTO.getConversationId()) ? agentChatReqDTO.getConversationId() : UUID.fastUUID().toString());
ChatResponseMetadata metadata = response.getChatResponse().getMetadata();
Boolean done = metadata.get("done");
responseDTO.setEvent(done ? "message_end" : "message");
dialogueLogDTO.setConversationId(responseDTO.getConversationId());
aiResponseBuilder.append(responseDTO.getAnswer());
return responseDTO;
}).doOnComplete(() -> {
dialogueLogDTO.setSystemOut(aiResponseBuilder.toString());
agentDialogueLogService.save(dialogueLogDTO.toDialogueLog());
}).doOnError(e -> {
log.error("Error during AI chat stream: {}", e.getMessage());
dialogueLogDTO.setSystemOut(aiResponseBuilder.toString());
dialogueLogDTO.setAnswerType(1);
agentDialogueLogService.save(dialogueLogDTO.toDialogueLog());
});
return map;
}
@Override
public IPage<AgentInfoDTO> pageList(Integer page, Integer pageSize) {
IPage<AgentInfo> paged = agentInfoService.page(Page.of(page, pageSize));
return paged.convert(AgentInfoDTO::new);
}
private Message buildQueryMessage(String query,String agentId) {
if (StrUtil.equals(agentId, "1")) {
String template = PromptTemplate.GENERAL_INDUSTRY_TEMPLATE;
return new UserMessage(StrUtil.format(template, Map.of("query",query)));
}else if (StrUtil.equals(agentId, "2")) {
String template = PromptTemplate.HEART_GUIDE_TEMPLATE;
return new UserMessage(StrUtil.format(template, Map.of("query",query)));
}
return null;
}
private List<Message> buildHistoryMessages(String conversationId,int historySize) {
List<Message> messages = new ArrayList<>();
if (StrUtil.isEmpty(conversationId)){
return messages;
}
IPage<AgentDialogueLog> dialogueLogs = agentDialogueLogService.pageList(Page.of(1, historySize), conversationId);
dialogueLogs.getRecords().sort((o1, o2) -> - o2.getCreateTime().compareTo(o1.getCreateTime()));
if (CollUtil.isNotEmpty(dialogueLogs.getRecords())) {
for (AgentDialogueLog dialogueLog : dialogueLogs.getRecords()) {
if (dialogueLog.getAnswerType() == 1){
continue;
}
if (StrUtil.isNotEmpty(dialogueLog.getUserInput()) && historySize > 0) {
messages.add(new UserMessage(dialogueLog.getUserInput()));
String result = dialogueLog.getSystemOut().replaceAll("(?is)<think\\b[^>]*>(.*?)</think>", "").trim();
messages.add(new AssistantMessage(result));
historySize--;
}
}
}
return messages;
}
}

@ -0,0 +1,38 @@
package com.supervision.service.impl;
import com.supervision.service.AuthService;
import com.supervision.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
private final AuthenticationManager authenticationManager;
private final JwtUtils jwtUtils;
/**
* JWT Token
*/
@Override
public String login(String username, String password) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
return jwtUtils.generateToken(userDetails);
} catch (BadCredentialsException e) {
throw new RuntimeException("用户名或密码错误");
} catch (DisabledException e) {
throw new RuntimeException("用户已被禁用");
}
}
}

@ -0,0 +1,48 @@
package com.supervision.service.impl;
import com.supervision.service.AiCallService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.embedding.Embedding;
import org.springframework.ai.embedding.EmbeddingRequest;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.OllamaEmbeddingModel;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class OllamaCallServiceImpl implements AiCallService {
private final OllamaChatModel ollamaChatModel;
private final OllamaEmbeddingModel embeddingModel;
@Override
public String call(String prompt) {
return ollamaChatModel.call(prompt);
}
@Override
public Flux<ChatResponse> stream(Prompt prompt) {
return ollamaChatModel.stream(prompt);
}
public Embedding embedding(String text) {
EmbeddingResponse embeddingResponse = embeddingModel.call(new EmbeddingRequest(List.of(text),null));
return embeddingResponse.getResult();
}
@Override
public List<Embedding> embedding(List<String> texts) {
EmbeddingResponse embeddingResponse = embeddingModel.call(new EmbeddingRequest(texts,null));
return embeddingResponse.getResults();
}
}

@ -1,11 +1,11 @@
package com.supervision.service.impl;
import com.supervision.domain.SysUser;
import com.supervision.domain.UserDetail;
import com.supervision.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ -33,6 +33,6 @@ public class UserDetailsServiceImpl implements UserDetailsService {
if (sysUser == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
return new User(sysUser.getUserName(), sysUser.getPassword(), authorities);
return new UserDetail(sysUser.getId(),sysUser.getUserName(), sysUser.getPassword(), authorities);
}
}

@ -0,0 +1,23 @@
package com.supervision.util;
import com.supervision.domain.UserDetail;
import com.supervision.exception.UnauthorizedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
public class UserUtil {
public static UserDetail currentUser() {
SecurityContext context = SecurityContextHolder.getContext();
if (null == context) {
throw new UnauthorizedException("未登录或登录已过期,请重新登录");
}
Authentication authentication = context.getAuthentication();
Object principal = authentication.getPrincipal();
if ("anonymousUser".equals(principal)) {
throw new UnauthorizedException("未登录或登录已过期,请重新登录");
}
return (UserDetail) authentication.getPrincipal();
}
}

@ -0,0 +1,11 @@
package com.supervision.vo;
import lombok.Data;
@Data
public class LoginReqVo {
private String username;
private String password;
}

@ -15,10 +15,30 @@ spring:
multipart:
max-file-size: 10MB
max-request-size: 100MB
ai:
openai:
baseUrl: https://api.deepseek.com
apiKey: sk-0b2c506c47e74594b5361c0f6844fd25
chat:
options:
model: deepseek-chat
ollama:
baseUrl: http://192.168.10.70:11434
chat:
model: qwen3:30b-a3b
#model: qwen3:32b
options:
max_tokens: 51200
top_p: 0.9
top_k: 40
temperature: 0.7
timeout: 180000
embedding:
model: dengcao/Qwen3-Embedding-0.6B:F16
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
jwt:
secret: "DlHaPUePiN6MyvpMpsMq/t6swzMHqtrRFd2YnofKz4k=" # JWT密钥 使用官方推荐方式生成 Base64.getEncoder().encodeToString(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
expiration: 3600000 # 1小时3600000 1天86400000
expiration: 86400000 # 1小时3600000 1天86400000

@ -6,7 +6,7 @@
<resultMap id="BaseResultMap" type="com.supervision.domain.SysByteArray">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="bytes" column="bytes" jdbcType="OTHER"/>
<result property="bytes" column="bytes" jdbcType="BINARY"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>

@ -6,19 +6,16 @@
<resultMap id="BaseResultMap" type="com.supervision.domain.SysUser">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="appId" column="app_id" jdbcType="VARCHAR"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="VARCHAR"/>
<result property="createUserId" column="create_user_id" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="updateUserId" column="update_user_id" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id,app_id,user_name,
password,status,create_user_id,
create_time,update_time,update_user_id
id,user_name,
password,status,
create_time,update_time
</sql>
</mapper>

@ -0,0 +1,29 @@
package com.supervision;
import com.supervision.domain.SysByteArray;
import com.supervision.service.SysByteArrayService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
public class PlatformApplicationTest {
@Autowired
private SysByteArrayService sysByteArrayService;
@Test
void saveByteArray() {
SysByteArray sysByteArray = new SysByteArray();
sysByteArray.setBytes(new byte[]{1,2,3});
boolean save = sysByteArrayService.save(sysByteArray);
System.out.println("保存结果: " + save);
}
@Test
void queryByteArray() {
SysByteArray sysByteArray = sysByteArrayService.getById("1945676008645058562");
log.info("查询结果: {}", sysByteArray);
}
}
Loading…
Cancel
Save