Merge remote-tracking branch 'origin/master'
commit
5d883a1512
@ -0,0 +1,25 @@
|
||||
package org.dromara.ai;
|
||||
|
||||
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||
import org.dromara.common.properties.MesProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 系统模块
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@EnableDubbo
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(MesProperties.class)
|
||||
public class HwMomAiApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(HwMomAiApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ AI模块启动成功 ლ(´ڡ`ლ)゙ ");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,158 @@
|
||||
package org.dromara.ai.controller;
|
||||
|
||||
/**
|
||||
* @Author xins
|
||||
* @Date 2025/7/17 14:26
|
||||
* @Description:AI助手Controller
|
||||
*/
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageBo;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageTopicBo;
|
||||
import org.dromara.ai.domain.bo.AiModelBo;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageVo;
|
||||
import org.dromara.ai.domain.vo.AiModelVo;
|
||||
import org.dromara.ai.knowledge.vectorization.factory.EmbeddingServiceFactory;
|
||||
import org.dromara.ai.knowledge.vectorization.process.IEmbeddingProcessor;
|
||||
import org.dromara.ai.process.dto.AIMessage;
|
||||
import org.dromara.ai.process.dto.AIRequest;
|
||||
import org.dromara.ai.process.dto.AIResponse;
|
||||
import org.dromara.ai.process.provider.processor.AIProviderProcessorFactory;
|
||||
import org.dromara.ai.process.provider.processor.IUnifiedAIProviderProcessor;
|
||||
import org.dromara.ai.service.*;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.system.api.model.LoginUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/assistant")
|
||||
public class AiAssistantController extends BaseController {
|
||||
|
||||
private final AIProviderProcessorFactory aiProviderProcessorFactory;
|
||||
|
||||
private final EmbeddingServiceFactory embeddingServiceFactory;
|
||||
|
||||
private final IAIAssistantService aiAssistantService;
|
||||
|
||||
private final IAiModelService aiModelService;
|
||||
|
||||
private final IAiChatMessageService aiChatMessageService;
|
||||
|
||||
private final IAiChatMessageDetailService aiChatMessageDetailService;
|
||||
|
||||
/**
|
||||
* 下拉框查询AI模型列表
|
||||
*/
|
||||
@GetMapping("/getAiModelJoinList")
|
||||
public R<List<AiModelVo>> getAiModelJoinList(AiModelBo bo) {
|
||||
List<AiModelVo> list = aiModelService.queryJoinList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉框查询AI模型列表
|
||||
*/
|
||||
@GetMapping("/getAiChatMessageList")
|
||||
public R<List<AiChatMessageVo>> getAiChatMessageList(AiChatMessageBo bo) {
|
||||
List<AiChatMessageVo> list = aiChatMessageService.queryList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉框查询AI模型列表
|
||||
*/
|
||||
@GetMapping("/getAiChatMessages/{sessionId}")
|
||||
public R<List<AIMessage>> getAiChatMessages(@PathVariable("sessionId") String sessionId) {
|
||||
List<AIMessage> list = aiChatMessageDetailService.getAIChatMessages(sessionId);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新message topic
|
||||
*/
|
||||
@Log(title = "会话标题", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/updateAiChatMessageTopic")
|
||||
public R<Void> updateAiChatMessageTopic(@Validated(EditGroup.class) @RequestBody AiChatMessageTopicBo bo) {
|
||||
return toAjax(aiChatMessageService.updateMessageTopic(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天消息
|
||||
*
|
||||
* @param sessionId 会话ID
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:remove")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{sessionId}")
|
||||
public R<Void> remove(@NotEmpty(message = "会话ID不能为空")
|
||||
@PathVariable String sessionId) {
|
||||
return toAjax(aiChatMessageService.deleteWithValidBySessionId(sessionId, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式聊天接口
|
||||
*/
|
||||
@PostMapping(value = "/chatStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
public Flux<String> chatStream(
|
||||
@RequestParam("provider") String provider, @RequestBody AIRequest request) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
IUnifiedAIProviderProcessor processor = aiProviderProcessorFactory.getProcessor(provider);
|
||||
return processor.chatStream(request,loginUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 非流式聊天接口
|
||||
*/
|
||||
@PostMapping("/chat")
|
||||
public Mono<AIResponse> chat(
|
||||
@RequestParam("provider") String provider, @RequestBody AIRequest request) {
|
||||
|
||||
IUnifiedAIProviderProcessor processor = aiProviderProcessorFactory.getProcessor(provider);
|
||||
return processor.chat(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 向量化
|
||||
*/
|
||||
@PostMapping("/embedding")
|
||||
public String embedding(
|
||||
@RequestParam("provider") String provider) {
|
||||
|
||||
IEmbeddingProcessor embeddingProcessor = embeddingServiceFactory.getProcessor(provider);
|
||||
embeddingProcessor.getEmbedding("你好");
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package org.dromara.ai.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageVo;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageBo;
|
||||
import org.dromara.ai.service.IAiChatMessageService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 聊天消息
|
||||
* 前端访问路由地址为:/ai/aiChatMessage
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/aiChatMessage")
|
||||
public class AiChatMessageController extends BaseController {
|
||||
|
||||
private final IAiChatMessageService aiChatMessageService;
|
||||
|
||||
/**
|
||||
* 查询聊天消息列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<AiChatMessageVo> list(AiChatMessageBo bo, PageQuery pageQuery) {
|
||||
return aiChatMessageService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出聊天消息列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:export")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(AiChatMessageBo bo, HttpServletResponse response) {
|
||||
List<AiChatMessageVo> list = aiChatMessageService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "聊天消息", AiChatMessageVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取聊天消息详细信息
|
||||
*
|
||||
* @param chatMessageId 主键
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:query")
|
||||
@GetMapping("/{chatMessageId}")
|
||||
public R<AiChatMessageVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long chatMessageId) {
|
||||
return R.ok(aiChatMessageService.queryById(chatMessageId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:add")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody AiChatMessageBo bo) {
|
||||
return toAjax(aiChatMessageService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:edit")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AiChatMessageBo bo) {
|
||||
return toAjax(aiChatMessageService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除聊天消息
|
||||
*
|
||||
* @param chatMessageIds 主键串
|
||||
*/
|
||||
@SaCheckPermission("ai:aiChatMessage:remove")
|
||||
@Log(title = "聊天消息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{chatMessageIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] chatMessageIds) {
|
||||
return toAjax(aiChatMessageService.deleteWithValidByIds(List.of(chatMessageIds), true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下拉框查询聊天消息列表
|
||||
*/
|
||||
|
||||
@GetMapping("/getAiChatMessageList")
|
||||
public R<List<AiChatMessageVo>> getAiChatMessageList(AiChatMessageBo bo) {
|
||||
List<AiChatMessageVo> list = aiChatMessageService.queryList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
package org.dromara.ai.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ai.domain.vo.AiKnowledgeBaseTypeVo;
|
||||
import org.dromara.ai.domain.bo.AiKnowledgeBaseTypeBo;
|
||||
import org.dromara.ai.service.IAiKnowledgeBaseTypeService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* AI知识库类型
|
||||
* 前端访问路由地址为:/ai/aiKnowledgeBaseType
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/aiKnowledgeBaseType")
|
||||
public class AiKnowledgeBaseTypeController extends BaseController {
|
||||
|
||||
private final IAiKnowledgeBaseTypeService aiKnowledgeBaseTypeService;
|
||||
|
||||
/**
|
||||
* 查询AI知识库类型列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<AiKnowledgeBaseTypeVo> list(AiKnowledgeBaseTypeBo bo, PageQuery pageQuery) {
|
||||
return aiKnowledgeBaseTypeService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出AI知识库类型列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:export")
|
||||
@Log(title = "AI知识库类型", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(AiKnowledgeBaseTypeBo bo, HttpServletResponse response) {
|
||||
List<AiKnowledgeBaseTypeVo> list = aiKnowledgeBaseTypeService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "AI知识库类型", AiKnowledgeBaseTypeVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI知识库类型详细信息
|
||||
*
|
||||
* @param knowledgeBaseTypeId 主键
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:query")
|
||||
@GetMapping("/{knowledgeBaseTypeId}")
|
||||
public R<AiKnowledgeBaseTypeVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long knowledgeBaseTypeId) {
|
||||
return R.ok(aiKnowledgeBaseTypeService.queryById(knowledgeBaseTypeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI知识库类型
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:add")
|
||||
@Log(title = "AI知识库类型", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody AiKnowledgeBaseTypeBo bo) {
|
||||
return toAjax(aiKnowledgeBaseTypeService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI知识库类型
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:edit")
|
||||
@Log(title = "AI知识库类型", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AiKnowledgeBaseTypeBo bo) {
|
||||
return toAjax(aiKnowledgeBaseTypeService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除AI知识库类型
|
||||
*
|
||||
* @param knowledgeBaseTypeIds 主键串
|
||||
*/
|
||||
@SaCheckPermission("ai:aiKnowledgeBaseType:remove")
|
||||
@Log(title = "AI知识库类型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{knowledgeBaseTypeIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] knowledgeBaseTypeIds) {
|
||||
return toAjax(aiKnowledgeBaseTypeService.deleteWithValidByIds(List.of(knowledgeBaseTypeIds), true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下拉框查询AI知识库类型列表
|
||||
*/
|
||||
|
||||
@GetMapping("/getAiKnowledgeBaseTypeList")
|
||||
public R<List<AiKnowledgeBaseTypeVo>> getAiKnowledgeBaseTypeList(AiKnowledgeBaseTypeBo bo) {
|
||||
List<AiKnowledgeBaseTypeVo> list = aiKnowledgeBaseTypeService.queryList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
package org.dromara.ai.controller;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.dromara.ai.domain.bo.AiBaseModelBo;
|
||||
import org.dromara.ai.domain.bo.AiPlatformBo;
|
||||
import org.dromara.ai.domain.vo.AiBaseModelVo;
|
||||
import org.dromara.ai.domain.vo.AiPlatformVo;
|
||||
import org.dromara.ai.process.dto.AIMessage;
|
||||
import org.dromara.ai.process.dto.AIRequest;
|
||||
import org.dromara.ai.process.dto.AIResponse;
|
||||
import org.dromara.ai.process.provider.processor.AIProviderProcessorFactory;
|
||||
import org.dromara.ai.process.provider.processor.IUnifiedAIProviderProcessor;
|
||||
import org.dromara.ai.service.IAIAssistantService;
|
||||
import org.dromara.ai.service.IAiBaseModelService;
|
||||
import org.dromara.ai.service.IAiPlatformService;
|
||||
import org.dromara.common.encrypt.utils.EncryptUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ai.domain.vo.AiModelVo;
|
||||
import org.dromara.ai.domain.bo.AiModelBo;
|
||||
import org.dromara.ai.service.IAiModelService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* AI模型
|
||||
* 前端访问路由地址为:/ai/aiModel
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-07
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/aiModel")
|
||||
public class AiModelController extends BaseController {
|
||||
|
||||
private final IAiModelService aiModelService;
|
||||
|
||||
private final IAiPlatformService aiPlatformService;
|
||||
|
||||
private final IAiBaseModelService baseModelService;
|
||||
|
||||
private final IAIAssistantService assistantService;
|
||||
|
||||
@Autowired
|
||||
private AIProviderProcessorFactory aiProviderProcessorFactory;
|
||||
|
||||
/**
|
||||
* 查询AI模型列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<AiModelVo>> list(AiModelBo bo) {
|
||||
return R.ok(aiModelService.queryJoinList(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出AI模型列表
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:export")
|
||||
@Log(title = "AI模型", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(AiModelBo bo, HttpServletResponse response) {
|
||||
List<AiModelVo> list = aiModelService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "AI模型", AiModelVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI模型详细信息
|
||||
*
|
||||
* @param modelId 主键
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:query")
|
||||
@GetMapping("/{modelId}")
|
||||
public R<AiModelVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long modelId) {
|
||||
return R.ok(aiModelService.queryById(modelId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI模型
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:add")
|
||||
@Log(title = "AI模型", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody AiModelBo bo) {
|
||||
return toAjax(aiModelService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI模型
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:edit")
|
||||
@Log(title = "AI模型", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AiModelBo bo) {
|
||||
return toAjax(aiModelService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除AI模型
|
||||
*
|
||||
* @param modelIds 主键串
|
||||
*/
|
||||
@SaCheckPermission("ai:aiModel:remove")
|
||||
@Log(title = "AI模型", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{modelIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] modelIds) {
|
||||
return toAjax(aiModelService.deleteWithValidByIds(List.of(modelIds), true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下拉框查询AI模型列表
|
||||
*/
|
||||
|
||||
@GetMapping("/getAiModelList")
|
||||
public R<List<AiModelVo>> getAiModelList(AiModelBo bo) {
|
||||
List<AiModelVo> list = aiModelService.queryList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试配置是否正确
|
||||
*/
|
||||
@PostMapping("/testAIModel")
|
||||
public R<Void> testAIModel(@RequestParam("provider") String provider, @RequestBody AIRequest request) {
|
||||
IUnifiedAIProviderProcessor processor = aiProviderProcessorFactory.getProcessor(provider);
|
||||
|
||||
String modelType = request.getModelType();
|
||||
switch (modelType) {
|
||||
case "LLM":
|
||||
AIResponse aiResponse = processor.chatTest(request).block(Duration.ofSeconds(10));
|
||||
if (aiResponse != null && aiResponse.isSuccess()) {
|
||||
System.out.println(aiResponse.getContent());
|
||||
System.out.println(aiResponse.getRawResponse());
|
||||
return R.ok();
|
||||
} else {
|
||||
System.out.println(aiResponse.getContent());
|
||||
System.out.println(aiResponse.getErrorMessage());
|
||||
// return R.fail(aiResponse.getErrorMessage());
|
||||
throw new RuntimeException(aiResponse.getErrorMessage());
|
||||
}
|
||||
case "Embedding":
|
||||
List<Double> embedding = processor.getEmbeddingTest(request);
|
||||
if (embedding != null && !embedding.isEmpty()) {
|
||||
System.out.println(embedding);
|
||||
return R.ok();
|
||||
} else {
|
||||
// return R.fail(aiResponse.getErrorMessage());
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return R.fail("模型类型错误");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
package org.dromara.ai.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.dromara.ai.domain.AiBaseModel;
|
||||
import org.dromara.ai.domain.bo.AiBaseModelBo;
|
||||
import org.dromara.ai.service.IAiBaseModelService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.ai.domain.vo.AiPlatformVo;
|
||||
import org.dromara.ai.domain.bo.AiPlatformBo;
|
||||
import org.dromara.ai.service.IAiPlatformService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* AI平台
|
||||
* 前端访问路由地址为:/ai/base/aiPlatform
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/base/aiPlatform")
|
||||
public class AiPlatformController extends BaseController {
|
||||
|
||||
private final IAiPlatformService aiPlatformService;
|
||||
|
||||
private final IAiBaseModelService aiBaseModelService;
|
||||
|
||||
// /**
|
||||
// * 查询AI平台列表
|
||||
// */
|
||||
// @SaCheckPermission("ai/base:aiPlatform:list")
|
||||
// @GetMapping("/list")
|
||||
// public TableDataInfo<AiPlatformVo> list(AiPlatformBo bo, PageQuery pageQuery) {
|
||||
// return aiPlatformService.queryPageList(bo, pageQuery);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 查询AI平台列表
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:list")
|
||||
@GetMapping("/list")
|
||||
public R<List<AiPlatformVo>> list(AiPlatformBo bo) {
|
||||
return R.ok(aiPlatformService.queryList(bo));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getAiBaseModelList")
|
||||
public R<List<AiBaseModel>> getAiBaseModelList(AiBaseModelBo bo) {
|
||||
List<AiBaseModel> list = aiBaseModelService.queryJoinList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 导出AI平台列表
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:export")
|
||||
@Log(title = "AI平台", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(AiPlatformBo bo, HttpServletResponse response) {
|
||||
List<AiPlatformVo> list = aiPlatformService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "AI平台", AiPlatformVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AI平台详细信息
|
||||
*
|
||||
* @param platformId 主键
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:query")
|
||||
@GetMapping("/{platformId}")
|
||||
public R<AiPlatformVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long platformId) {
|
||||
return R.ok(aiPlatformService.queryById(platformId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI平台
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:add")
|
||||
@Log(title = "AI平台", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody AiPlatformBo bo) {
|
||||
return toAjax(aiPlatformService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI平台
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:edit")
|
||||
@Log(title = "AI平台", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody AiPlatformBo bo) {
|
||||
return toAjax(aiPlatformService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除AI平台
|
||||
*
|
||||
* @param platformIds 主键串
|
||||
*/
|
||||
@SaCheckPermission("ai/base:aiPlatform:remove")
|
||||
@Log(title = "AI平台", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{platformIds}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] platformIds) {
|
||||
return toAjax(aiPlatformService.deleteWithValidByIds(List.of(platformIds), true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下拉框查询AI平台列表
|
||||
*/
|
||||
|
||||
@GetMapping("/getAiPlatformList")
|
||||
public R<List<AiPlatformVo>> getAiPlatformList(AiPlatformBo bo) {
|
||||
List<AiPlatformVo> list = aiPlatformService.queryList(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package org.dromara.ai.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.ai.domain.AiChatMessage;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 聊天消息业务对象 ai_chat_message
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = AiChatMessage.class, reverseConvertGenerate = false)
|
||||
public class AiChatMessageTopicBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
@NotNull(message = "会话ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String sessionId;
|
||||
|
||||
/**
|
||||
* 聊天标题
|
||||
*/
|
||||
@NotBlank(message = "聊天标题不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String messageTopic;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package org.dromara.ai.domain.bo;
|
||||
|
||||
import org.dromara.ai.domain.AiKnowledgeBaseType;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* AI知识库类型业务对象 ai_knowledge_base_type
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = AiKnowledgeBaseType.class, reverseConvertGenerate = false)
|
||||
public class AiKnowledgeBaseTypeBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long knowledgeBaseTypeId;
|
||||
|
||||
/**
|
||||
* 知识库类型名称
|
||||
*/
|
||||
@NotBlank(message = "知识库类型名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String knowledgeBaseTypeName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package org.dromara.ai.domain.vo;
|
||||
|
||||
import org.dromara.ai.domain.AiKnowledgeBaseType;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AI知识库类型视图对象 ai_knowledge_base_type
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = AiKnowledgeBaseType.class)
|
||||
public class AiKnowledgeBaseTypeVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@ExcelProperty(value = "主键")
|
||||
private Long knowledgeBaseTypeId;
|
||||
|
||||
/**
|
||||
* 知识库类型名称
|
||||
*/
|
||||
@ExcelProperty(value = "知识库类型名称")
|
||||
private String knowledgeBaseTypeName;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import org.dromara.ai.domain.AiChatMessageDetail;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageDetailVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天消息详情Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
public interface AiChatMessageDetailMapper extends BaseMapperPlus<AiChatMessageDetail, AiChatMessageDetailVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import org.dromara.ai.domain.AiChatMessage;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 聊天消息Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
public interface AiChatMessageMapper extends BaseMapperPlus<AiChatMessage, AiChatMessageVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import org.dromara.ai.domain.AiKnowledgeBaseType;
|
||||
import org.dromara.ai.domain.vo.AiKnowledgeBaseTypeVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* AI知识库类型Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
public interface AiKnowledgeBaseTypeMapper extends BaseMapperPlus<AiKnowledgeBaseType, AiKnowledgeBaseTypeVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.ai.domain.AiBaseModel;
|
||||
import org.dromara.ai.domain.AiModel;
|
||||
import org.dromara.ai.domain.bo.AiBaseModelBo;
|
||||
import org.dromara.ai.domain.vo.AiModelVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI模型Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-07
|
||||
*/
|
||||
public interface AiModelMapper extends BaseMapperPlus<AiModel, AiModelVo> {
|
||||
|
||||
@InterceptorIgnore(tenantLine = "true") // leftJoin 的表不拼接租户
|
||||
List<AiModelVo> selectJoinList(@Param(Constants.WRAPPER) MPJLambdaWrapper<AiModel> wrapper);
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.dromara.ai.domain.AiModelType;
|
||||
import org.dromara.ai.domain.vo.AiModelTypeVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 模型类型Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@InterceptorIgnore(dataPermission = "true", tenantLine = "true")
|
||||
public interface AiModelTypeMapper extends BaseMapperPlus<AiModelType, AiModelTypeVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.dromara.ai.domain.AiPlatform;
|
||||
import org.dromara.ai.domain.vo.AiPlatformVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* AI平台Mapper接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@InterceptorIgnore(dataPermission = "true", tenantLine = "true")
|
||||
public interface AiPlatformMapper extends BaseMapperPlus<AiPlatform, AiPlatformVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package org.dromara.ai.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author xins
|
||||
* @Date 2025/7/8 9:22
|
||||
* @Description:
|
||||
*/
|
||||
@InterceptorIgnore(dataPermission = "true", tenantLine = "true")
|
||||
@Mapper
|
||||
public interface DatabaseMetaMapper {
|
||||
|
||||
/**
|
||||
* 获取所有用户表名
|
||||
*/
|
||||
@Select("SELECT name FROM hwmom.sys.tables where name = 'sys_user'ORDER BY name")
|
||||
List<String> getAllTableNames();
|
||||
|
||||
/**
|
||||
* 获取指定表的结构信息
|
||||
*/
|
||||
List<Map<String, Object>> getTableStructure(@Param("tableName") String tableName);
|
||||
|
||||
/**
|
||||
* 获取所有表的结构信息
|
||||
*/
|
||||
List<Map<String, Object>> getAllTablesStructure();
|
||||
|
||||
/**
|
||||
* 获取表的主键信息
|
||||
*/
|
||||
@Select("SELECT COL_NAME(ic.object_id, ic.column_id) AS columnName " +
|
||||
"FROM sys.indexes i " +
|
||||
"INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id " +
|
||||
"WHERE i.is_primary_key = 1 AND OBJECT_NAME(ic.object_id) = #{tableName}")
|
||||
List<String> getPrimaryKeys(@Param("tableName") String tableName);
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package org.dromara.ai.process.dto;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description AI聊天回复响应
|
||||
* @author xins
|
||||
* @date 2025/7/29 16:20
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public class AIResponse {
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* 生成的回复内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 完整的响应数据
|
||||
*/
|
||||
private Object rawResponse;
|
||||
|
||||
/**
|
||||
* 使用token情况
|
||||
*/
|
||||
private Usage usage;
|
||||
|
||||
public AIResponse(boolean success, String errorMessage, String content, Usage usage) {
|
||||
this.success = success;
|
||||
this.errorMessage = errorMessage;
|
||||
this.content = content;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
// 成功响应的便捷构造函数
|
||||
public AIResponse(String content, Usage usage) {
|
||||
this(true, null, content, usage);
|
||||
}
|
||||
|
||||
// 错误响应的便捷构造函数
|
||||
public AIResponse(String errorMessage) {
|
||||
this(false, errorMessage, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Token使用情况类
|
||||
*/
|
||||
@Data
|
||||
public static class Usage {
|
||||
private int promptTokens;
|
||||
private int completionTokens;
|
||||
private int totalTokens;
|
||||
|
||||
public Usage(int promptTokens, int completionTokens, int totalTokens) {
|
||||
this.promptTokens = promptTokens;
|
||||
this.completionTokens = completionTokens;
|
||||
this.totalTokens = totalTokens;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package org.dromara.ai.process.enums;
|
||||
|
||||
public enum AIChatMessageTypeEnum {
|
||||
AI_CHAT("1","ai-chat"), //AI问答
|
||||
KNOWLEDGE_CHAT("2","knowledge-chat");//知识库问答
|
||||
|
||||
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
AIChatMessageTypeEnum(String code,String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从字符串转换为枚举
|
||||
*/
|
||||
public static AIChatMessageTypeEnum fromString(String text) {
|
||||
for (AIChatMessageTypeEnum provider : AIChatMessageTypeEnum.values()) {
|
||||
if (provider.name().equalsIgnoreCase(text) ||
|
||||
provider.getName().equalsIgnoreCase(text)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("未知的大模型提供商: " + text);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package org.dromara.ai.process.enums;
|
||||
|
||||
public enum AIModelTypeEnum {
|
||||
LLM("LLM"),//大语言对话模型
|
||||
EMBEDDING("Embedding");//向量模型
|
||||
|
||||
private final String name;
|
||||
|
||||
AIModelTypeEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从字符串转换为枚举
|
||||
*/
|
||||
public static AIModelTypeEnum fromString(String text) {
|
||||
for (AIModelTypeEnum provider : AIModelTypeEnum.values()) {
|
||||
if (provider.name().equalsIgnoreCase(text) ||
|
||||
provider.getName().equalsIgnoreCase(text)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("未知的大模型提供商: " + text);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.dromara.ai.process.enums;
|
||||
|
||||
public enum AIProviderEnum {
|
||||
DEEPSEEK("DeepSeek"),
|
||||
TONGYI_QIANWEN("TongYi-QianWen"),//阿里通义千问
|
||||
TENCENT_LKE("Tencent-LKE"),//腾讯云智能体开发平台
|
||||
WENXIN_YIYAN("WenXin-YiYan");//百度文心一言
|
||||
|
||||
private final String name;
|
||||
|
||||
AIProviderEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从字符串转换为枚举
|
||||
*/
|
||||
public static AIProviderEnum fromString(String text) {
|
||||
for (AIProviderEnum provider : AIProviderEnum.values()) {
|
||||
if (provider.name().equalsIgnoreCase(text) ||
|
||||
provider.getName().equalsIgnoreCase(text)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("未知的大模型提供商: " + text);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.process.dto.AIRequest;
|
||||
|
||||
public interface IAIAssistantService {
|
||||
|
||||
public boolean testAIModel(String provider, AIRequest aiRequest);
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiBaseModel;
|
||||
import org.dromara.ai.domain.vo.AiBaseModelVo;
|
||||
import org.dromara.ai.domain.bo.AiBaseModelBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础模型Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
public interface IAiBaseModelService {
|
||||
|
||||
/**
|
||||
* 查询基础模型
|
||||
*
|
||||
* @param baseModelId 主键
|
||||
* @return 基础模型
|
||||
*/
|
||||
AiBaseModelVo queryById(Long baseModelId);
|
||||
|
||||
/**
|
||||
* 分页查询基础模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 基础模型分页列表
|
||||
*/
|
||||
TableDataInfo<AiBaseModelVo> queryPageList(AiBaseModelBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的基础模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 基础模型列表
|
||||
*/
|
||||
List<AiBaseModelVo> queryList(AiBaseModelBo bo);
|
||||
|
||||
/**
|
||||
* 新增基础模型
|
||||
*
|
||||
* @param bo 基础模型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiBaseModelBo bo);
|
||||
|
||||
/**
|
||||
* 修改基础模型
|
||||
*
|
||||
* @param bo 基础模型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiBaseModelBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除基础模型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
|
||||
/**
|
||||
* 查询符合条件的基础模型列表
|
||||
*
|
||||
* @param queryBaseModel 查询条件
|
||||
* @return 基础模型列表
|
||||
*/
|
||||
public List<AiBaseModel> queryJoinList(AiBaseModelBo queryBaseModel);
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiChatMessageDetail;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageDetailVo;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageDetailBo;
|
||||
import org.dromara.ai.process.dto.AIMessage;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天消息详情Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
public interface IAiChatMessageDetailService {
|
||||
|
||||
/**
|
||||
* 查询聊天消息详情
|
||||
*
|
||||
* @param messageDetailId 主键
|
||||
* @return 聊天消息详情
|
||||
*/
|
||||
AiChatMessageDetailVo queryById(Long messageDetailId);
|
||||
|
||||
/**
|
||||
* 分页查询聊天消息详情列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 聊天消息详情分页列表
|
||||
*/
|
||||
TableDataInfo<AiChatMessageDetailVo> queryPageList(AiChatMessageDetailBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的聊天消息详情列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 聊天消息详情列表
|
||||
*/
|
||||
List<AiChatMessageDetailVo> queryList(AiChatMessageDetailBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天消息详情
|
||||
*
|
||||
* @param bo 聊天消息详情
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiChatMessageDetailBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天消息详情
|
||||
*
|
||||
* @param bo 聊天消息详情
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiChatMessageDetailBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息详情信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 根据sessionId查询聊天消息详情列表
|
||||
* @param sessionId
|
||||
* @return LIST<AIMessage></AIMessage>
|
||||
*/
|
||||
public List<AIMessage> getAIChatMessages(String sessionId);
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiChatMessage;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageTopicBo;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageVo;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 聊天消息Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
public interface IAiChatMessageService {
|
||||
|
||||
/**
|
||||
* 查询聊天消息
|
||||
*
|
||||
* @param chatMessageId 主键
|
||||
* @return 聊天消息
|
||||
*/
|
||||
AiChatMessageVo queryById(Long chatMessageId);
|
||||
|
||||
/**
|
||||
* 分页查询聊天消息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 聊天消息分页列表
|
||||
*/
|
||||
TableDataInfo<AiChatMessageVo> queryPageList(AiChatMessageBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的聊天消息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 聊天消息列表
|
||||
*/
|
||||
List<AiChatMessageVo> queryList(AiChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiChatMessageBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
|
||||
/**
|
||||
* 修改聊天消息标题
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
public Boolean updateMessageTopic(AiChatMessageTopicBo bo);
|
||||
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息信息
|
||||
*
|
||||
* @param sessionId 待删除的会话ID
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteWithValidBySessionId(String sessionId, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiKnowledgeBaseType;
|
||||
import org.dromara.ai.domain.vo.AiKnowledgeBaseTypeVo;
|
||||
import org.dromara.ai.domain.bo.AiKnowledgeBaseTypeBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI知识库类型Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
public interface IAiKnowledgeBaseTypeService {
|
||||
|
||||
/**
|
||||
* 查询AI知识库类型
|
||||
*
|
||||
* @param knowledgeBaseTypeId 主键
|
||||
* @return AI知识库类型
|
||||
*/
|
||||
AiKnowledgeBaseTypeVo queryById(Long knowledgeBaseTypeId);
|
||||
|
||||
/**
|
||||
* 分页查询AI知识库类型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI知识库类型分页列表
|
||||
*/
|
||||
TableDataInfo<AiKnowledgeBaseTypeVo> queryPageList(AiKnowledgeBaseTypeBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI知识库类型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI知识库类型列表
|
||||
*/
|
||||
List<AiKnowledgeBaseTypeVo> queryList(AiKnowledgeBaseTypeBo bo);
|
||||
|
||||
/**
|
||||
* 新增AI知识库类型
|
||||
*
|
||||
* @param bo AI知识库类型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiKnowledgeBaseTypeBo bo);
|
||||
|
||||
/**
|
||||
* 修改AI知识库类型
|
||||
*
|
||||
* @param bo AI知识库类型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiKnowledgeBaseTypeBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI知识库类型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiModel;
|
||||
import org.dromara.ai.domain.vo.AiModelVo;
|
||||
import org.dromara.ai.domain.bo.AiModelBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI模型Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-07
|
||||
*/
|
||||
public interface IAiModelService {
|
||||
|
||||
/**
|
||||
* 查询AI模型
|
||||
*
|
||||
* @param modelId 主键
|
||||
* @return AI模型
|
||||
*/
|
||||
AiModelVo queryById(Long modelId);
|
||||
|
||||
/**
|
||||
* 分页查询AI模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI模型分页列表
|
||||
*/
|
||||
TableDataInfo<AiModelVo> queryPageList(AiModelBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI模型列表
|
||||
*/
|
||||
List<AiModelVo> queryList(AiModelBo bo);
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI模型列表,Join basemodel,modeltype,platform
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI模型列表
|
||||
*/
|
||||
public List<AiModelVo> queryJoinList(AiModelBo bo);
|
||||
|
||||
/**
|
||||
* 新增AI模型
|
||||
*
|
||||
* @param bo AI模型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiModelBo bo);
|
||||
|
||||
/**
|
||||
* 修改AI模型
|
||||
*
|
||||
* @param bo AI模型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiModelBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI模型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import org.dromara.ai.domain.AiPlatform;
|
||||
import org.dromara.ai.domain.vo.AiPlatformVo;
|
||||
import org.dromara.ai.domain.bo.AiPlatformBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI平台Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
public interface IAiPlatformService {
|
||||
|
||||
/**
|
||||
* 查询AI平台
|
||||
*
|
||||
* @param platformId 主键
|
||||
* @return AI平台
|
||||
*/
|
||||
AiPlatformVo queryById(Long platformId);
|
||||
|
||||
/**
|
||||
* 分页查询AI平台列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI平台分页列表
|
||||
*/
|
||||
TableDataInfo<AiPlatformVo> queryPageList(AiPlatformBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI平台列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI平台列表
|
||||
*/
|
||||
List<AiPlatformVo> queryList(AiPlatformBo bo);
|
||||
|
||||
/**
|
||||
* 新增AI平台
|
||||
*
|
||||
* @param bo AI平台
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiPlatformBo bo);
|
||||
|
||||
/**
|
||||
* 修改AI平台
|
||||
*
|
||||
* @param bo AI平台
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiPlatformBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI平台信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import org.dromara.ai.knowledge.vectorization.process.IEmbeddingProcessor;
|
||||
import org.dromara.ai.mapper.DatabaseMetaMapper;
|
||||
import org.dromara.ai.process.dto.AIMessage;
|
||||
import org.dromara.ai.process.dto.AIRequest;
|
||||
import org.dromara.ai.process.dto.AIResponse;
|
||||
import org.dromara.ai.process.provider.processor.AIProviderProcessorFactory;
|
||||
import org.dromara.ai.process.provider.processor.IUnifiedAIProviderProcessor;
|
||||
import org.dromara.ai.service.IAIAssistantService;
|
||||
import org.dromara.common.encrypt.utils.EncryptUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author xins
|
||||
* @Date 2025/7/17 14:31
|
||||
* @Description:
|
||||
*/
|
||||
@Service
|
||||
public class AIAssistantServiceImpl implements IAIAssistantService {
|
||||
|
||||
@Autowired
|
||||
private DatabaseMetaMapper databaseMetaMapper;
|
||||
|
||||
@Autowired
|
||||
private Map<String, IUnifiedAIProviderProcessor> aiProviderProcessorMap;
|
||||
|
||||
@Autowired
|
||||
private Map<String, IEmbeddingProcessor> embeddingProcessorMap;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AIProviderProcessorFactory aiProviderProcessorFactory;
|
||||
|
||||
|
||||
|
||||
|
||||
public String chatStream(String provider, AIRequest aiRequest){
|
||||
IUnifiedAIProviderProcessor processor = aiProviderProcessorFactory.getProcessor(provider);
|
||||
// processor.chatStream(aiRequest);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String aiFillForm(){
|
||||
String aiClient = "deepSeek";
|
||||
IUnifiedAIProviderProcessor service = aiProviderProcessorMap.get(aiClient);
|
||||
if (service == null) {
|
||||
throw new IllegalArgumentException("Unsupported payment type");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public String uploadContent(){
|
||||
String embeddingProcessor = "tencentlke";
|
||||
IEmbeddingProcessor service = embeddingProcessorMap.get(embeddingProcessor);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean testAIModel(String provider,AIRequest aiRequest){
|
||||
IUnifiedAIProviderProcessor processor = aiProviderProcessorMap.get(provider);
|
||||
if (processor == null) {
|
||||
throw new IllegalArgumentException("Unsupported processor type");
|
||||
}
|
||||
aiRequest.setModel("deepseek-chat");
|
||||
String decryptApiKey = EncryptUtils.decryptByBase64(aiRequest.getApiKey());
|
||||
aiRequest.setApiKey(decryptApiKey);
|
||||
AIMessage aiMessage = new AIMessage();
|
||||
aiMessage.setRole("user");
|
||||
aiMessage.setContent("这是一个测试请求,请回复'测试成功'");
|
||||
aiRequest.setMessages(Collections.singletonList(
|
||||
aiMessage
|
||||
));
|
||||
AIResponse aiResponse = processor.chat(aiRequest).block(Duration.ofSeconds(10));
|
||||
if (aiResponse != null && aiResponse.isSuccess()) {
|
||||
System.out.println(aiResponse.getContent());
|
||||
System.out.println(aiResponse.getUsage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiBaseModelBo;
|
||||
import org.dromara.ai.domain.vo.AiBaseModelVo;
|
||||
import org.dromara.ai.domain.AiBaseModel;
|
||||
import org.dromara.ai.mapper.AiBaseModelMapper;
|
||||
import org.dromara.ai.service.IAiBaseModelService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 基础模型Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiBaseModelServiceImpl implements IAiBaseModelService {
|
||||
|
||||
private final AiBaseModelMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询基础模型
|
||||
*
|
||||
* @param baseModelId 主键
|
||||
* @return 基础模型
|
||||
*/
|
||||
@Override
|
||||
public AiBaseModelVo queryById(Long baseModelId){
|
||||
return baseMapper.selectVoById(baseModelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询基础模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 基础模型分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiBaseModelVo> queryPageList(AiBaseModelBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiBaseModel> lqw = buildQueryWrapper(bo);
|
||||
Page<AiBaseModelVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的基础模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 基础模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiBaseModelVo> queryList(AiBaseModelBo bo) {
|
||||
MPJLambdaWrapper<AiBaseModel> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiBaseModel> buildQueryWrapper(AiBaseModelBo bo) {
|
||||
MPJLambdaWrapper<AiBaseModel> lqw = JoinWrappers.lambda(AiBaseModel.class)
|
||||
.selectAll(AiBaseModel.class)
|
||||
.eq(bo.getBaseModelId() != null, AiBaseModel::getBaseModelId, bo.getBaseModelId())
|
||||
.eq(bo.getPlatformId() != null, AiBaseModel::getPlatformId, bo.getPlatformId())
|
||||
.eq(bo.getModelTypeId() != null, AiBaseModel::getModelTypeId, bo.getModelTypeId())
|
||||
.like(StringUtils.isNotBlank(bo.getBaseModelName()), AiBaseModel::getBaseModelName, bo.getBaseModelName())
|
||||
.eq(StringUtils.isNotBlank(bo.getBaseModelDescription()), AiBaseModel::getBaseModelDescription, bo.getBaseModelDescription())
|
||||
.eq(bo.getContextLength() != null, AiBaseModel::getContextLength, bo.getContextLength())
|
||||
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), AiBaseModel::getActiveFlag, bo.getActiveFlag());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增基础模型
|
||||
*
|
||||
* @param bo 基础模型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiBaseModelBo bo) {
|
||||
AiBaseModel add = MapstructUtils.convert(bo, AiBaseModel.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setBaseModelId(add.getBaseModelId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改基础模型
|
||||
*
|
||||
* @param bo 基础模型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiBaseModelBo bo) {
|
||||
AiBaseModel update = MapstructUtils.convert(bo, AiBaseModel.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiBaseModel entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除基础模型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询符合条件的基础模型列表
|
||||
*
|
||||
* @param queryBaseModel 查询条件
|
||||
* @return 基础模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiBaseModel> queryJoinList(AiBaseModelBo queryBaseModel) {
|
||||
List<AiBaseModel> aiBaseModelList = baseMapper.selectAiBaseModelJoinList(queryBaseModel);
|
||||
|
||||
return aiBaseModelList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import org.dromara.ai.process.dto.AIMessage;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageDetailBo;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageDetailVo;
|
||||
import org.dromara.ai.domain.AiChatMessageDetail;
|
||||
import org.dromara.ai.mapper.AiChatMessageDetailMapper;
|
||||
import org.dromara.ai.service.IAiChatMessageDetailService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 聊天消息详情Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiChatMessageDetailServiceImpl implements IAiChatMessageDetailService {
|
||||
|
||||
private final AiChatMessageDetailMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询聊天消息详情
|
||||
*
|
||||
* @param messageDetailId 主键
|
||||
* @return 聊天消息详情
|
||||
*/
|
||||
@Override
|
||||
public AiChatMessageDetailVo queryById(Long messageDetailId) {
|
||||
return baseMapper.selectVoById(messageDetailId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询聊天消息详情列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 聊天消息详情分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiChatMessageDetailVo> queryPageList(AiChatMessageDetailBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiChatMessageDetail> lqw = buildQueryWrapper(bo);
|
||||
Page<AiChatMessageDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的聊天消息详情列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 聊天消息详情列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiChatMessageDetailVo> queryList(AiChatMessageDetailBo bo) {
|
||||
MPJLambdaWrapper<AiChatMessageDetail> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiChatMessageDetail> buildQueryWrapper(AiChatMessageDetailBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiChatMessageDetail> lqw = JoinWrappers.lambda(AiChatMessageDetail.class)
|
||||
.selectAll(AiChatMessageDetail.class)
|
||||
.eq(bo.getMessageDetailId() != null, AiChatMessageDetail::getMessageDetailId, bo.getMessageDetailId())
|
||||
.eq(bo.getChatMessageId() != null, AiChatMessageDetail::getChatMessageId, bo.getChatMessageId())
|
||||
.eq(bo.getSessionId() != null, AiChatMessageDetail::getSessionId, bo.getSessionId())
|
||||
.eq(StringUtils.isNotBlank(bo.getQuestionContent()), AiChatMessageDetail::getQuestionContent, bo.getQuestionContent())
|
||||
.eq(StringUtils.isNotBlank(bo.getAnswerContent()), AiChatMessageDetail::getAnswerContent, bo.getAnswerContent())
|
||||
.eq(bo.getPromptToken() != null, AiChatMessageDetail::getPromptToken, bo.getPromptToken())
|
||||
.eq(bo.getCompletionToken() != null, AiChatMessageDetail::getCompletionToken, bo.getCompletionToken())
|
||||
.eq(bo.getTotalToken() != null, AiChatMessageDetail::getTotalToken, bo.getTotalToken())
|
||||
.eq(bo.getModelId() != null, AiChatMessageDetail::getModelId, bo.getModelId())
|
||||
.eq(bo.getKnowledgeBaseId() != null, AiChatMessageDetail::getKnowledgeBaseId, bo.getKnowledgeBaseId())
|
||||
.eq(StringUtils.isNotBlank(bo.getTakeFlag()), AiChatMessageDetail::getTakeFlag, bo.getTakeFlag())
|
||||
.eq(StringUtils.isNotBlank(bo.getCompleteFlag()), AiChatMessageDetail::getCompleteFlag, bo.getCompleteFlag())
|
||||
.orderByDesc(AiChatMessageDetail::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天消息详情
|
||||
*
|
||||
* @param bo 聊天消息详情
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiChatMessageDetailBo bo) {
|
||||
AiChatMessageDetail add = MapstructUtils.convert(bo, AiChatMessageDetail.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setMessageDetailId(add.getMessageDetailId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天消息详情
|
||||
*
|
||||
* @param bo 聊天消息详情
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiChatMessageDetailBo bo) {
|
||||
AiChatMessageDetail update = MapstructUtils.convert(bo, AiChatMessageDetail.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiChatMessageDetail entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息详情信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据sessionId查询聊天消息详情列表
|
||||
* @param sessionId
|
||||
* @return LIST<AIMessage></AIMessage>
|
||||
*/
|
||||
@Override
|
||||
public List<AIMessage> getAIChatMessages(String sessionId) {
|
||||
AiChatMessageDetailBo bo = new AiChatMessageDetailBo();
|
||||
bo.setSessionId(sessionId);
|
||||
MPJLambdaWrapper<AiChatMessageDetail> lqw = buildQueryWrapper(bo);
|
||||
List<AiChatMessageDetail> aiChatMessageDetails = baseMapper.selectList(lqw);
|
||||
List<AIMessage> aiMessages = new ArrayList<>();
|
||||
//获取数据是根据时间倒序排序的,下面需要按照时间升序添加
|
||||
for (int i = aiChatMessageDetails.size() - 1; i >= 0; i--) {
|
||||
AiChatMessageDetail aiChatMessageDetail = aiChatMessageDetails.get(i);
|
||||
AIMessage aiUserMessage = new AIMessage();
|
||||
aiUserMessage.setRole("user");
|
||||
aiUserMessage.setContent(aiChatMessageDetail.getQuestionContent());
|
||||
aiUserMessage.setTimestamp(aiChatMessageDetail.getCreateTime().getTime());
|
||||
aiMessages.add(aiUserMessage);
|
||||
|
||||
AIMessage aiAssistantMessage = new AIMessage();
|
||||
aiAssistantMessage.setRole("assistant");
|
||||
aiAssistantMessage.setContent(aiChatMessageDetail.getAnswerContent());
|
||||
aiAssistantMessage.setTimestamp(aiChatMessageDetail.getCreateTime().getTime());
|
||||
aiMessages.add(aiAssistantMessage);
|
||||
}
|
||||
|
||||
return aiMessages;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,187 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import org.dromara.ai.domain.AiChatMessageDetail;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageTopicBo;
|
||||
import org.dromara.ai.mapper.AiChatMessageDetailMapper;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiChatMessageBo;
|
||||
import org.dromara.ai.domain.vo.AiChatMessageVo;
|
||||
import org.dromara.ai.domain.AiChatMessage;
|
||||
import org.dromara.ai.mapper.AiChatMessageMapper;
|
||||
import org.dromara.ai.service.IAiChatMessageService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 聊天消息Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-14
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiChatMessageServiceImpl implements IAiChatMessageService {
|
||||
|
||||
private final AiChatMessageMapper baseMapper;
|
||||
|
||||
private final AiChatMessageDetailMapper aiChatMessageDetailMapper;
|
||||
|
||||
/**
|
||||
* 查询聊天消息
|
||||
*
|
||||
* @param chatMessageId 主键
|
||||
* @return 聊天消息
|
||||
*/
|
||||
@Override
|
||||
public AiChatMessageVo queryById(Long chatMessageId) {
|
||||
return baseMapper.selectVoById(chatMessageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询聊天消息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 聊天消息分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiChatMessageVo> queryPageList(AiChatMessageBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiChatMessage> lqw = buildQueryWrapper(bo);
|
||||
Page<AiChatMessageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的聊天消息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 聊天消息列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiChatMessageVo> queryList(AiChatMessageBo bo) {
|
||||
MPJLambdaWrapper<AiChatMessage> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiChatMessage> buildQueryWrapper(AiChatMessageBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiChatMessage> lqw = JoinWrappers.lambda(AiChatMessage.class)
|
||||
.selectAll(AiChatMessage.class)
|
||||
.eq(bo.getChatMessageId() != null, AiChatMessage::getChatMessageId, bo.getChatMessageId())
|
||||
.eq(StringUtils.isNotBlank(bo.getMessageTopic()), AiChatMessage::getMessageTopic, bo.getMessageTopic())
|
||||
.eq(bo.getDeductCost() != null, AiChatMessage::getDeductCost, bo.getDeductCost())
|
||||
.eq(bo.getTotalToken() != null, AiChatMessage::getTotalToken, bo.getTotalToken())
|
||||
.eq(bo.getModelId() != null, AiChatMessage::getModelId, bo.getModelId())
|
||||
.eq(bo.getKnowledgeBaseId() != null, AiChatMessage::getKnowledgeBaseId, bo.getKnowledgeBaseId())
|
||||
.eq(StringUtils.isNotBlank(bo.getMessageType()), AiChatMessage::getMessageType, bo.getMessageType())
|
||||
.orderByDesc(AiChatMessage::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增聊天消息
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiChatMessageBo bo) {
|
||||
AiChatMessage add = MapstructUtils.convert(bo, AiChatMessage.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setChatMessageId(add.getChatMessageId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改聊天消息
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiChatMessageBo bo) {
|
||||
AiChatMessage update = MapstructUtils.convert(bo, AiChatMessage.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiChatMessage entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改聊天消息标题
|
||||
*
|
||||
* @param bo 聊天消息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateMessageTopic(AiChatMessageTopicBo bo) {
|
||||
UpdateWrapper<AiChatMessage> updateWrapper = new UpdateWrapper();
|
||||
updateWrapper.eq("session_id", bo.getSessionId())
|
||||
.set("message_topic", bo.getMessageTopic());
|
||||
|
||||
baseMapper.update(updateWrapper);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验并批量删除聊天消息信息
|
||||
*
|
||||
* @param sessionId 待删除的会话ID
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean deleteWithValidBySessionId(String sessionId, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
|
||||
// 先删除AI会话明细
|
||||
aiChatMessageDetailMapper.delete(Wrappers.<AiChatMessageDetail>lambdaQuery()
|
||||
.eq(AiChatMessageDetail::getSessionId, sessionId));
|
||||
|
||||
return baseMapper.delete(Wrappers.<AiChatMessage>lambdaQuery()
|
||||
.eq(AiChatMessage::getSessionId, sessionId)) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiKnowledgeBaseTypeBo;
|
||||
import org.dromara.ai.domain.vo.AiKnowledgeBaseTypeVo;
|
||||
import org.dromara.ai.domain.AiKnowledgeBaseType;
|
||||
import org.dromara.ai.mapper.AiKnowledgeBaseTypeMapper;
|
||||
import org.dromara.ai.service.IAiKnowledgeBaseTypeService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* AI知识库类型Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiKnowledgeBaseTypeServiceImpl implements IAiKnowledgeBaseTypeService {
|
||||
|
||||
private final AiKnowledgeBaseTypeMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询AI知识库类型
|
||||
*
|
||||
* @param knowledgeBaseTypeId 主键
|
||||
* @return AI知识库类型
|
||||
*/
|
||||
@Override
|
||||
public AiKnowledgeBaseTypeVo queryById(Long knowledgeBaseTypeId) {
|
||||
return baseMapper.selectVoById(knowledgeBaseTypeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询AI知识库类型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI知识库类型分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiKnowledgeBaseTypeVo> queryPageList(AiKnowledgeBaseTypeBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiKnowledgeBaseType> lqw = buildQueryWrapper(bo);
|
||||
Page<AiKnowledgeBaseTypeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI知识库类型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI知识库类型列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiKnowledgeBaseTypeVo> queryList(AiKnowledgeBaseTypeBo bo) {
|
||||
MPJLambdaWrapper<AiKnowledgeBaseType> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiKnowledgeBaseType> buildQueryWrapper(AiKnowledgeBaseTypeBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiKnowledgeBaseType> lqw = JoinWrappers.lambda(AiKnowledgeBaseType.class)
|
||||
.selectAll(AiKnowledgeBaseType.class)
|
||||
.eq(bo.getKnowledgeBaseTypeId() != null, AiKnowledgeBaseType::getKnowledgeBaseTypeId, bo.getKnowledgeBaseTypeId())
|
||||
.like(StringUtils.isNotBlank(bo.getKnowledgeBaseTypeName()), AiKnowledgeBaseType::getKnowledgeBaseTypeName, bo.getKnowledgeBaseTypeName())
|
||||
.like(StringUtils.isNotBlank(bo.getRemark()), AiKnowledgeBaseType::getRemark, bo.getRemark())
|
||||
.orderByDesc(AiKnowledgeBaseType::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI知识库类型
|
||||
*
|
||||
* @param bo AI知识库类型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiKnowledgeBaseTypeBo bo) {
|
||||
AiKnowledgeBaseType add = MapstructUtils.convert(bo, AiKnowledgeBaseType.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setKnowledgeBaseTypeId(add.getKnowledgeBaseTypeId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI知识库类型
|
||||
*
|
||||
* @param bo AI知识库类型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiKnowledgeBaseTypeBo bo) {
|
||||
AiKnowledgeBaseType update = MapstructUtils.convert(bo, AiKnowledgeBaseType.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiKnowledgeBaseType entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI知识库类型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,241 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.dromara.ai.domain.AiBaseModel;
|
||||
import org.dromara.ai.domain.AiModelType;
|
||||
import org.dromara.ai.domain.AiPlatform;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.encrypt.annotation.EncryptField;
|
||||
import org.dromara.common.encrypt.core.EncryptContext;
|
||||
import org.dromara.common.encrypt.core.EncryptorManager;
|
||||
import org.dromara.common.encrypt.enumd.AlgorithmType;
|
||||
import org.dromara.common.encrypt.enumd.EncodeType;
|
||||
import org.dromara.common.encrypt.properties.EncryptorProperties;
|
||||
import org.dromara.common.encrypt.utils.EncryptUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiModelBo;
|
||||
import org.dromara.ai.domain.vo.AiModelVo;
|
||||
import org.dromara.ai.domain.AiModel;
|
||||
import org.dromara.ai.mapper.AiModelMapper;
|
||||
import org.dromara.ai.service.IAiModelService;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* AI模型Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-07
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiModelServiceImpl implements IAiModelService {
|
||||
|
||||
private final AiModelMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询AI模型
|
||||
*
|
||||
* @param modelId 主键
|
||||
* @return AI模型
|
||||
*/
|
||||
@Override
|
||||
public AiModelVo queryById(Long modelId) {
|
||||
return baseMapper.selectVoById(modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询AI模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI模型分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiModelVo> queryPageList(AiModelBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiModel> lqw = buildQueryWrapper(bo);
|
||||
Page<AiModelVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI模型列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiModelVo> queryList(AiModelBo bo) {
|
||||
MPJLambdaWrapper<AiModel> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI模型列表,Join basemodel,modeltype,platform
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI模型列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiModelVo> queryJoinList(AiModelBo bo) {
|
||||
MPJLambdaWrapper<AiModel> lqw = buildJoinQueryWrapper(bo);
|
||||
return baseMapper.selectJoinList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiModel> buildQueryWrapper(AiModelBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiModel> lqw = JoinWrappers.lambda(AiModel.class)
|
||||
.selectAll(AiModel.class)
|
||||
.eq(bo.getModelId() != null, AiModel::getModelId, bo.getModelId())
|
||||
.like(StringUtils.isNotBlank(bo.getModelName()), AiModel::getModelName, bo.getModelName())
|
||||
.eq(bo.getPlatformId() != null, AiModel::getPlatformId, bo.getPlatformId())
|
||||
.eq(bo.getModelTypeId() != null, AiModel::getModelTypeId, bo.getModelTypeId())
|
||||
.eq(bo.getBaseModelId() != null, AiModel::getBaseModelId, bo.getBaseModelId())
|
||||
.eq(StringUtils.isNotBlank(bo.getChargeType()), AiModel::getChargeType, bo.getChargeType())
|
||||
.eq(bo.getModelPrice() != null, AiModel::getModelPrice, bo.getModelPrice())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiEndpoint()), AiModel::getApiEndpoint, bo.getApiEndpoint())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiKey()), AiModel::getApiKey, bo.getApiKey())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiSecret()), AiModel::getApiSecret, bo.getApiSecret())
|
||||
.eq(StringUtils.isNotBlank(bo.getVectorLibrary()), AiModel::getVectorLibrary, bo.getVectorLibrary())
|
||||
.eq(StringUtils.isNotBlank(bo.getDescription()), AiModel::getDescription, bo.getDescription())
|
||||
.eq(bo.getModelTemperature() != null, AiModel::getModelTemperature, bo.getModelTemperature())
|
||||
.eq(bo.getVocabularyAttribute() != null, AiModel::getVocabularyAttribute, bo.getVocabularyAttribute())
|
||||
.eq(bo.getTopicAttribute() != null, AiModel::getTopicAttribute, bo.getTopicAttribute())
|
||||
.eq(bo.getDuplicateAttribute() != null, AiModel::getDuplicateAttribute, bo.getDuplicateAttribute())
|
||||
.eq(bo.getMaxReply() != null, AiModel::getMaxReply, bo.getMaxReply())
|
||||
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), AiModel::getActiveFlag, bo.getActiveFlag())
|
||||
.orderByDesc(AiModel::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiModel> buildJoinQueryWrapper(AiModelBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiModel> lqw = JoinWrappers.lambda(AiModel.class)
|
||||
.selectAll(AiModel.class)
|
||||
.select(AiPlatform::getPlatformCode)
|
||||
.select(AiPlatform::getPlatformName)
|
||||
.select(AiPlatform::getPlatformIcon)
|
||||
.leftJoin(AiPlatform.class, AiPlatform::getPlatformId, AiModel::getPlatformId)
|
||||
.select(AiModelType::getModelTypeCode)
|
||||
.select(AiModelType::getModelTypeName)
|
||||
.leftJoin(AiModelType.class, AiModelType::getModelTypeId, AiModel::getModelTypeId)
|
||||
.select(AiBaseModel::getBaseModelName)
|
||||
.leftJoin(AiBaseModel.class, AiBaseModel::getBaseModelId, AiModel::getBaseModelId)
|
||||
.eq(bo.getModelId() != null, AiModel::getModelId, bo.getModelId())
|
||||
.like(StringUtils.isNotBlank(bo.getModelName()), AiModel::getModelName, bo.getModelName())
|
||||
.eq(bo.getPlatformId() != null, AiModel::getPlatformId, bo.getPlatformId())
|
||||
.eq(bo.getModelTypeId() != null, AiModel::getModelTypeId, bo.getModelTypeId())
|
||||
.eq(bo.getBaseModelId() != null, AiModel::getBaseModelId, bo.getBaseModelId())
|
||||
.eq(StringUtils.isNotBlank(bo.getChargeType()), AiModel::getChargeType, bo.getChargeType())
|
||||
.eq(bo.getModelPrice() != null, AiModel::getModelPrice, bo.getModelPrice())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiEndpoint()), AiModel::getApiEndpoint, bo.getApiEndpoint())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiKey()), AiModel::getApiKey, bo.getApiKey())
|
||||
.eq(StringUtils.isNotBlank(bo.getApiSecret()), AiModel::getApiSecret, bo.getApiSecret())
|
||||
.eq(StringUtils.isNotBlank(bo.getVectorLibrary()), AiModel::getVectorLibrary, bo.getVectorLibrary())
|
||||
.eq(StringUtils.isNotBlank(bo.getDescription()), AiModel::getDescription, bo.getDescription())
|
||||
.eq(bo.getModelTemperature() != null, AiModel::getModelTemperature, bo.getModelTemperature())
|
||||
.eq(bo.getVocabularyAttribute() != null, AiModel::getVocabularyAttribute, bo.getVocabularyAttribute())
|
||||
.eq(bo.getTopicAttribute() != null, AiModel::getTopicAttribute, bo.getTopicAttribute())
|
||||
.eq(bo.getDuplicateAttribute() != null, AiModel::getDuplicateAttribute, bo.getDuplicateAttribute())
|
||||
.eq(bo.getMaxReply() != null, AiModel::getMaxReply, bo.getMaxReply())
|
||||
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), AiModel::getActiveFlag, bo.getActiveFlag())
|
||||
.orderByDesc(AiModel::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI模型
|
||||
*
|
||||
* @param bo AI模型
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiModelBo bo) {
|
||||
AiModel add = MapstructUtils.convert(bo, AiModel.class);
|
||||
add.setActiveFlag("1");
|
||||
|
||||
String apiKey = add.getApiKey();
|
||||
String apiSecret = add.getApiSecret();
|
||||
if (StringUtils.isNotEmpty(apiKey)) {
|
||||
String encryptApiKey = EncryptUtils.encryptByBase64(add.getApiKey());
|
||||
// String decryptApiKey = EncryptUtils.decryptByBase64(encryptApiKey);
|
||||
add.setApiKey(encryptApiKey);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(apiSecret)) {
|
||||
String encryptApiSecret = EncryptUtils.encryptByBase64(add.getApiSecret());
|
||||
// String decryptApiSecret = EncryptUtils.decryptByBase64(encryptApiSecret);
|
||||
add.setApiSecret(encryptApiSecret);
|
||||
}
|
||||
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setModelId(add.getModelId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI模型
|
||||
*
|
||||
* @param bo AI模型
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiModelBo bo) {
|
||||
AiModel update = MapstructUtils.convert(bo, AiModel.class);
|
||||
validEntityBeforeSave(update);
|
||||
String apiKey = update.getApiKey();
|
||||
String apiSecret = update.getApiSecret();
|
||||
//todo:前端显示什么,如何修改
|
||||
if (StringUtils.isNotEmpty(apiKey)) {
|
||||
String encryptApiKey = EncryptUtils.encryptByBase64(update.getApiKey());
|
||||
// String decryptApiKey = EncryptUtils.decryptByBase64(encryptApiKey);
|
||||
update.setApiKey(encryptApiKey);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(apiSecret)) {
|
||||
String encryptApiSecret = EncryptUtils.encryptByBase64(update.getApiSecret());
|
||||
// String decryptApiSecret = EncryptUtils.decryptByBase64(encryptApiSecret);
|
||||
update.setApiSecret(encryptApiSecret);
|
||||
}
|
||||
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiModel entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI模型信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiPlatformBo;
|
||||
import org.dromara.ai.domain.vo.AiPlatformVo;
|
||||
import org.dromara.ai.domain.AiPlatform;
|
||||
import org.dromara.ai.mapper.AiPlatformMapper;
|
||||
import org.dromara.ai.service.IAiPlatformService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* AI平台Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-08-06
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiPlatformServiceImpl implements IAiPlatformService {
|
||||
|
||||
private final AiPlatformMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询AI平台
|
||||
*
|
||||
* @param platformId 主键
|
||||
* @return AI平台
|
||||
*/
|
||||
@Override
|
||||
public AiPlatformVo queryById(Long platformId){
|
||||
return baseMapper.selectVoById(platformId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询AI平台列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI平台分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiPlatformVo> queryPageList(AiPlatformBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiPlatform> lqw = buildQueryWrapper(bo);
|
||||
Page<AiPlatformVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI平台列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI平台列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiPlatformVo> queryList(AiPlatformBo bo) {
|
||||
MPJLambdaWrapper<AiPlatform> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiPlatform> buildQueryWrapper(AiPlatformBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiPlatform> lqw = JoinWrappers.lambda(AiPlatform.class)
|
||||
.selectAll(AiPlatform.class)
|
||||
.eq(bo.getPlatformId() != null, AiPlatform::getPlatformId, bo.getPlatformId())
|
||||
.like(StringUtils.isNotBlank(bo.getPlatformName()), AiPlatform::getPlatformName, bo.getPlatformName())
|
||||
.like(StringUtils.isNotBlank(bo.getPlatformDescription()), AiPlatform::getPlatformDescription, bo.getPlatformDescription())
|
||||
.eq(StringUtils.isNotBlank(bo.getBaseApiUrl()), AiPlatform::getBaseApiUrl, bo.getBaseApiUrl())
|
||||
.eq(StringUtils.isNotBlank(bo.getPlatformIcon()), AiPlatform::getPlatformIcon, bo.getPlatformIcon())
|
||||
.eq(StringUtils.isNotBlank(bo.getAuthMethod()), AiPlatform::getAuthMethod, bo.getAuthMethod())
|
||||
.orderByDesc(AiPlatform::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI平台
|
||||
*
|
||||
* @param bo AI平台
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiPlatformBo bo) {
|
||||
AiPlatform add = MapstructUtils.convert(bo, AiPlatform.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setPlatformId(add.getPlatformId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI平台
|
||||
*
|
||||
* @param bo AI平台
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiPlatformBo bo) {
|
||||
AiPlatform update = MapstructUtils.convert(bo, AiPlatform.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiPlatform entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI平台信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
# Tomcat
|
||||
server:
|
||||
port: 6019
|
||||
|
||||
# Spring
|
||||
spring:
|
||||
application:
|
||||
# 应用名称
|
||||
name: hwmom-ai
|
||||
profiles:
|
||||
# 环境配置
|
||||
active: @profiles.active@
|
||||
|
||||
--- # nacos 配置
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
# nacos 服务地址
|
||||
server-addr: @nacos.server@
|
||||
username: @nacos.username@
|
||||
password: @nacos.password@
|
||||
discovery:
|
||||
# 注册组
|
||||
group: @nacos.discovery.group@
|
||||
namespace: ${spring.profiles.active}
|
||||
config:
|
||||
# 配置组
|
||||
group: @nacos.config.group@
|
||||
namespace: ${spring.profiles.active}
|
||||
config:
|
||||
import:
|
||||
- optional:nacos:application-common.yml
|
||||
- optional:nacos:datasource.yml
|
||||
- optional:nacos:${spring.application.name}.yml
|
||||
@ -0,0 +1,7 @@
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
Spring Application Name: ${spring.application.name}
|
||||
__
|
||||
/ /_ _ ______ ___ ____ ____ ___ ____ ___ ___ _____
|
||||
/ __ \ | /| / / __ `__ \/ __ \/ __ `__ \______/ __ `__ \/ _ \/ ___/
|
||||
/ / / / |/ |/ / / / / / / /_/ / / / / / /_____/ / / / / / __(__ )
|
||||
/_/ /_/|__/|__/_/ /_/ /_/\____/_/ /_/ /_/ /_/ /_/ /_/\___/____/
|
||||
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="60 seconds" debug="false">
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="logs/${project.artifactId}" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="console.log.pattern"
|
||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<include resource="logback-common.xml" />
|
||||
|
||||
<include resource="logback-logstash.xml" />
|
||||
|
||||
<!-- 开启 skywalking 日志收集 -->
|
||||
<include resource="logback-skylog.xml" />
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
</configuration>
|
||||
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiBaseModelMapper">
|
||||
|
||||
<resultMap type="AiBaseModel" id="AiBaseModelResult">
|
||||
<result property="baseModelId" column="base_model_id" />
|
||||
<result property="baseModelName" column="base_model_name" />
|
||||
<result property="modelTypeId" column="model_type_id" />
|
||||
<result property="modelTypeCode" column="model_type_code" />
|
||||
<result property="contextLength" column="context_length" />
|
||||
<result property="activeFlag" column="active_flag" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="baseModelDescription" column="base_model_description" />
|
||||
<result property="modelTypeName" column="model_type_name" />
|
||||
|
||||
</resultMap>
|
||||
|
||||
|
||||
<resultMap id="AiBaseModelApiEndpointCapabilityResult" type="AiBaseModel"
|
||||
extends="AiBaseModelResult">
|
||||
<collection property="aiApiEndpointList" notNullColumn="sub_point_base_model_id" javaType="java.util.List"
|
||||
resultMap="AiApiEndpointResult"/>
|
||||
<collection property="aiModelCapabilityList" notNullColumn="sub_capability_base_model_id" javaType="java.util.List"
|
||||
resultMap="AiModelCapabilityResult"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
<resultMap type="AiApiEndpoint" id="AiApiEndpointResult">
|
||||
<result property="apiEndpointId" column="sub_api_endpoint_id"/>
|
||||
<result property="baseModelId" column="sub_point_base_model_id"/>
|
||||
<result property="apiEndpointName" column="sub_api_endpoint_name"/>
|
||||
<result property="apiVersion" column="sub_api_version"/>
|
||||
<result property="httpMethod" column="sub_http_method"/>
|
||||
<result property="apiEndpointPath" column="sub_api_endpoint_path"/>
|
||||
<result property="defaultFlag" column="sub_default_flag"/>
|
||||
<result property="rateLimit" column="sub_rate_limit"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap type="AiModelCapability" id="AiModelCapabilityResult">
|
||||
<result property="modelCapabilityId" column="sub_model_capability_id"/>
|
||||
<result property="baseModelId" column="sub_capability_base_model_id"/>
|
||||
<result property="modelCapabilityName" column="sub_model_capability_name"/>
|
||||
<result property="modelCapabilityDescription" column="sub_model_capability_description"/>
|
||||
</resultMap>
|
||||
|
||||
|
||||
|
||||
<select id="selectAiBaseModelJoinList" parameterType="AiBaseModel"
|
||||
resultMap="AiBaseModelApiEndpointCapabilityResult">
|
||||
select a.base_model_id,
|
||||
a.base_model_name,
|
||||
a.model_type_id,
|
||||
a.context_length,
|
||||
a.active_flag,
|
||||
a.base_model_description,
|
||||
amt.model_type_code,
|
||||
amt.model_type_name,
|
||||
b.base_model_id as sub_point_base_model_id,
|
||||
b.api_endpoint_id as sub_api_endpoint_id,
|
||||
b.api_endpoint_name as sub_api_endpoint_name,
|
||||
b.api_version as sub_api_version,
|
||||
b.http_method as sub_http_method,
|
||||
b.api_endpoint_path as sub_api_endpoint_path,
|
||||
b.default_flag as sub_default_flag,
|
||||
b.rate_limit as sub_rate_limit,
|
||||
c.model_capability_id as sub_model_capability_id,
|
||||
c.base_model_id as sub_capability_base_model_id,
|
||||
c.model_capability_name as sub_model_capability_name,
|
||||
c.model_capability_description as sub_model_capability_description
|
||||
from ai_base_model a
|
||||
left join ai_api_endpoint b on b.base_model_id = a.base_model_id
|
||||
left join ai_model_capability c on c.base_model_id = a.base_model_id
|
||||
left join ai_model_type amt on a.model_type_id = amt.model_type_id
|
||||
<where>
|
||||
<if test="platformId != null and platformId != ''">and a.platform_id = #{platformId}</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiChatMessageDetailMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiChatMessageMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiKnowledgeBaseTypeMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiModelMapper">
|
||||
|
||||
<!-- <resultMap type="AiModel" id="AiModelResult">-->
|
||||
<!-- <result property="modelId" column="model_id" />-->
|
||||
<!-- <result property="tenantId" column="tenant_id" />-->
|
||||
<!-- <result property="modelName" column="model_name" />-->
|
||||
<!-- <result property="platformId" column="platform_id" />-->
|
||||
<!-- <result property="modelTypeId" column="model_type_id" />-->
|
||||
<!-- <result property="baseModelId" column="base_model_id" />-->
|
||||
<!-- <result property="chargeType" column="charge_type" />-->
|
||||
<!-- <result property="modelPrice" column="model_price"/>-->
|
||||
<!-- <result property="apiEndpoint" column="api_endpoint" />-->
|
||||
<!-- <result property="apiKey" column="api_key" />-->
|
||||
<!-- <result property="apiSecret" column="api_secret" />-->
|
||||
<!-- <result property="vectorLibrary" column="vector_library" />-->
|
||||
<!-- <result property="description" column="description" />-->
|
||||
<!-- <result property="modelTemperature" column="model_temperature" />-->
|
||||
<!-- <result property="vocabularyAttribute" column="vocabulary_attribute" />-->
|
||||
<!-- <result property="topicAttribute" column="topic_attribute" />-->
|
||||
<!-- <result property="duplicateAttribute" column="duplicate_attribute" />-->
|
||||
<!-- <result property="modelReply" column="model_reply" />-->
|
||||
<!-- <result property="activeFlag" column="active_flag" />-->
|
||||
<!-- <result property="createDept" column="create_dept" />-->
|
||||
<!-- <result property="createBy" column="create_by" />-->
|
||||
<!-- <result property="createTime" column="create_time" />-->
|
||||
<!-- <result property="updateBy" column="update_by" />-->
|
||||
<!-- <result property="updateTime" column="update_time" />-->
|
||||
<!-- <result property="delFlag" column="del_flag" />-->
|
||||
<!-- -->
|
||||
<!-- <result property="platformName" column="platform_name" />-->
|
||||
<!-- <result property="platformIcon" column="platform_icon" />-->
|
||||
<!-- <result property="modelTypeName" column="model_type_name" />-->
|
||||
<!-- <result property="baseModelName" column="base_model_name" />-->
|
||||
<!-- </resultMap>-->
|
||||
|
||||
|
||||
<!-- <select id="queryJoinList" resultType="org.dromara.ai.domain.vo.AiModel">-->
|
||||
<!-- select a.*, b.base_model_name, c.platform_name as platform_name, d.model_type_name-->
|
||||
<!-- from ai_model a-->
|
||||
<!-- left join ai_base_model b on a.base_model_id = b.id-->
|
||||
<!-- left join ai_platform c on a.platform_id = c.id-->
|
||||
<!-- left join ai_model_type d on a.type_id = d.id-->
|
||||
<!-- </select>-->
|
||||
</mapper>
|
||||
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.AiPlatformMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.ai.mapper.DatabaseMetaMapper">
|
||||
|
||||
<!-- 获取指定表的结构信息 -->
|
||||
<select id="getTableStructure" resultType="map">
|
||||
SELECT
|
||||
c.name AS columnName,
|
||||
t.name AS dataType,
|
||||
c.max_length AS maxLength,
|
||||
c.precision,
|
||||
c.scale,
|
||||
c.is_nullable AS nullable,
|
||||
ISNULL(OBJECT_DEFINITION(c.default_object_id), '') AS defaultValue,
|
||||
ep.value AS description
|
||||
FROM sys.columns c
|
||||
JOIN sys.types t ON c.user_type_id = t.user_type_id
|
||||
LEFT JOIN sys.extended_properties ep ON
|
||||
ep.major_id = c.object_id AND
|
||||
ep.minor_id = c.column_id AND
|
||||
ep.name = 'MS_Description'
|
||||
WHERE OBJECT_NAME(c.object_id) = #{tableName}
|
||||
ORDER BY c.column_id
|
||||
</select>
|
||||
|
||||
<!-- 获取所有表的结构信息 -->
|
||||
<select id="getAllTablesStructure" resultType="map">
|
||||
SELECT
|
||||
OBJECT_NAME(c.object_id) AS tableName,
|
||||
c.name AS columnName,
|
||||
t.name AS dataType,
|
||||
c.max_length AS maxLength,
|
||||
c.precision,
|
||||
c.scale,
|
||||
c.is_nullable AS nullable,
|
||||
ISNULL(OBJECT_DEFINITION(c.default_object_id), '') AS defaultValue,
|
||||
ISNULL(ep.value, '') AS description
|
||||
FROM sys.columns c
|
||||
JOIN sys.types t ON c.user_type_id = t.user_type_id
|
||||
LEFT JOIN sys.extended_properties ep ON
|
||||
ep.major_id = c.object_id AND
|
||||
ep.minor_id = c.column_id AND
|
||||
ep.name = 'MS_Description'
|
||||
WHERE OBJECT_NAME(c.object_id) IN (SELECT name FROM hwmom.sys.tables where name='sys_user')
|
||||
ORDER BY tableName, c.column_id
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue