mirror of
https://github.com/ccmjga/zhilu-admin
synced 2026-03-13 21:27:19 +08:00
174 lines
6.8 KiB
Java
174 lines
6.8 KiB
Java
package com.zl.mjga.controller;
|
|
|
|
import com.zl.mjga.dto.PageRequestDto;
|
|
import com.zl.mjga.dto.PageResponseDto;
|
|
import com.zl.mjga.dto.ai.ChatDto;
|
|
import com.zl.mjga.dto.ai.LlmQueryDto;
|
|
import com.zl.mjga.dto.ai.LlmVm;
|
|
import com.zl.mjga.exception.BusinessException;
|
|
import com.zl.mjga.repository.*;
|
|
import com.zl.mjga.service.AiChatService;
|
|
import com.zl.mjga.service.LlmService;
|
|
import com.zl.mjga.service.RagService;
|
|
import dev.langchain4j.service.TokenStream;
|
|
import jakarta.validation.Valid;
|
|
import java.security.Principal;
|
|
import java.time.Duration;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.jooq.generated.mjga.enums.LlmCodeEnum;
|
|
import org.jooq.generated.mjga.tables.pojos.*;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import reactor.core.publisher.Flux;
|
|
import reactor.core.publisher.Sinks;
|
|
|
|
@RestController
|
|
@RequestMapping("/ai")
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
public class AiController {
|
|
|
|
private final AiChatService aiChatService;
|
|
private final LlmService llmService;
|
|
private final RagService ragService;
|
|
private final UserRepository userRepository;
|
|
private final DepartmentRepository departmentRepository;
|
|
private final PositionRepository positionRepository;
|
|
private final RoleRepository repository;
|
|
private final PermissionRepository permissionRepository;
|
|
private final RoleRepository roleRepository;
|
|
|
|
@PostMapping(value = "/action/execute", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<String> actionExecute(Principal principal, @RequestBody String userMessage) {
|
|
Sinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();
|
|
TokenStream chat = aiChatService.actionPrecedenceExecuteWith(principal.getName(), userMessage);
|
|
chat.onPartialResponse(
|
|
(text) -> {
|
|
log.debug("ai action partialResponse: {}", text);
|
|
sink.tryEmitNext(
|
|
StringUtils.isNotEmpty(text) ? text.replace(" ", "␣").replace("\t", "⇥") : "");
|
|
})
|
|
.onToolExecuted(
|
|
toolExecution -> log.debug("当前请求 {} 成功执行函数调用: {}", userMessage, toolExecution))
|
|
.onCompleteResponse(
|
|
r -> {
|
|
log.debug("ai action completeResponse: {}", r);
|
|
sink.tryEmitComplete();
|
|
sink.emitComplete(Sinks.EmitFailureHandler.FAIL_FAST);
|
|
})
|
|
.onError(
|
|
(e) -> {
|
|
sink.tryEmitError(e);
|
|
sink.tryEmitComplete();
|
|
sink.emitComplete(Sinks.EmitFailureHandler.FAIL_FAST);
|
|
})
|
|
.start();
|
|
return sink.asFlux().timeout(Duration.ofSeconds(120));
|
|
}
|
|
|
|
@PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
|
public Flux<String> chat(Principal principal, @RequestBody ChatDto chatDto) {
|
|
Sinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();
|
|
TokenStream chat = aiChatService.chat(principal.getName(), chatDto);
|
|
chat.onPartialResponse(
|
|
text ->
|
|
sink.tryEmitNext(
|
|
StringUtils.isNotEmpty(text) ? text.replace(" ", "␣").replace("\t", "⇥") : ""))
|
|
.onCompleteResponse(
|
|
r -> {
|
|
sink.tryEmitComplete();
|
|
sink.emitComplete(Sinks.EmitFailureHandler.FAIL_FAST);
|
|
})
|
|
.onError(sink::tryEmitError)
|
|
.start();
|
|
return sink.asFlux().timeout(Duration.ofSeconds(120));
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_LLM_CONFIG_PERMISSION)")
|
|
@PutMapping(value = "/llm")
|
|
public void updateLlm(@RequestBody @Valid LlmVm llmVm) {
|
|
llmService.update(llmVm);
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).READ_LLM_CONFIG_PERMISSION)")
|
|
@GetMapping("/llm/page-query")
|
|
@ResponseStatus(HttpStatus.OK)
|
|
public PageResponseDto<List<LlmVm>> pageQueryLlm(
|
|
@ModelAttribute PageRequestDto pageRequestDto, @ModelAttribute LlmQueryDto llmQueryDto) {
|
|
return llmService.pageQueryLlm(pageRequestDto, llmQueryDto);
|
|
}
|
|
|
|
@PostMapping("/action/search")
|
|
public Map<String, String> searchAction(@RequestBody String message) {
|
|
AiLlmConfig aiLlmConfig = llmService.loadConfig(LlmCodeEnum.ZHI_PU);
|
|
if (!aiLlmConfig.getEnable()) {
|
|
throw new BusinessException("命令模型未启用,请开启后再试。");
|
|
}
|
|
return ragService.searchAction(message);
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_USER_ROLE_PERMISSION)")
|
|
@DeleteMapping("/action/user")
|
|
void deleteUser(@RequestParam String username, Principal principal) {
|
|
if (StringUtils.equals(username, principal.getName())) {
|
|
throw new BusinessException("不能删除当前登录用户");
|
|
}
|
|
User fetched = userRepository.fetchOneByUsername(username);
|
|
if (fetched == null) {
|
|
throw new BusinessException("该用户不存在");
|
|
}
|
|
userRepository.deleteByUsername(username);
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_DEPARTMENT_PERMISSION)")
|
|
@DeleteMapping("/action/department")
|
|
void deleteDepartment(@RequestParam String name) {
|
|
Department department = departmentRepository.fetchOneByName(name);
|
|
if (department == null) {
|
|
throw new BusinessException("该部门不存在");
|
|
}
|
|
departmentRepository.deleteByName(name);
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_POSITION_PERMISSION)")
|
|
@DeleteMapping("/action/position")
|
|
void deletePosition(@RequestParam String name) {
|
|
Position position = positionRepository.fetchOneByName(name);
|
|
if (position == null) {
|
|
throw new BusinessException("该岗位不存在");
|
|
}
|
|
positionRepository.deleteById(position.getId());
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_USER_ROLE_PERMISSION)")
|
|
@DeleteMapping("/action/role")
|
|
void deleteRole(@RequestParam String name) {
|
|
Role role = roleRepository.fetchOneByName(name);
|
|
if (role == null) {
|
|
throw new BusinessException("该角色不存在");
|
|
}
|
|
roleRepository.deleteById(role.getId());
|
|
}
|
|
|
|
@PreAuthorize("hasAuthority(T(com.zl.mjga.model.urp.EPermission).WRITE_USER_ROLE_PERMISSION)")
|
|
@DeleteMapping("/action/permission")
|
|
void deletePermission(@RequestParam String name) {
|
|
Permission permission = permissionRepository.fetchOneByName(name);
|
|
if (permission == null) {
|
|
throw new BusinessException("该权限不存在");
|
|
}
|
|
permissionRepository.deleteById(permission.getId());
|
|
}
|
|
|
|
@PostMapping("/chat/refresh")
|
|
void createNewConversation(Principal principal) {
|
|
aiChatService.evictChatMemory(principal.getName());
|
|
}
|
|
}
|