feat(oa): 添加 AI 对话管理功能
- 新增 AI配置、对话历史、对话消息等相关的实体类、Mapper、Service 和 Controller - 实现 AI 对话管理的基础功能,包括创建对话、发送消息、结束对话等- 集成 DeepSeek AI 服务,实现与 AI 模型的交互 - 添加 token消耗和费用计算相关逻辑
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package com.ruoyi.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* AI配置对象 sys_oa_ai_config
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oa_ai_config")
|
||||
public class SysOaAiConfig extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 配置ID
|
||||
*/
|
||||
@TableId(value = "config_id")
|
||||
private Long configId;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 基础URL
|
||||
*/
|
||||
private String baseUrl;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 最大重试次数
|
||||
*/
|
||||
private Integer maxRetries;
|
||||
|
||||
/**
|
||||
* 温度参数
|
||||
*/
|
||||
private BigDecimal temperature;
|
||||
|
||||
/**
|
||||
* 最大token数
|
||||
*/
|
||||
private Integer maxTokens;
|
||||
|
||||
/**
|
||||
* 状态(0:禁用 1:启用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.ruoyi.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* AI对话历史对象 sys_oa_ai_conversation
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oa_ai_conversation")
|
||||
public class SysOaAiConversation extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
@TableId(value = "conversation_id")
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 对话标题
|
||||
*/
|
||||
private String conversationTitle;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* AI模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 对话状态(0:已结束 1:进行中)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 总消耗token数
|
||||
*/
|
||||
private Integer totalTokens;
|
||||
|
||||
/**
|
||||
* 总费用
|
||||
*/
|
||||
private BigDecimal totalCost;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ruoyi.oa.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* AI对话详情对象 sys_oa_ai_message
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("sys_oa_ai_message")
|
||||
public class SysOaAiMessage extends BaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
@TableId(value = "message_id")
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant)
|
||||
*/
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 消耗token数
|
||||
*/
|
||||
private Integer tokens;
|
||||
|
||||
/**
|
||||
* 费用
|
||||
*/
|
||||
private BigDecimal cost;
|
||||
|
||||
/**
|
||||
* 消息顺序
|
||||
*/
|
||||
private Integer messageOrder;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.ruoyi.oa.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI配置业务对象 sys_oa_ai_config
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOaAiConfigBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 配置ID
|
||||
*/
|
||||
@NotNull(message = "配置ID不能为空", groups = { EditGroup.class })
|
||||
private Long configId;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
@NotBlank(message = "配置名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
@NotBlank(message = "API密钥不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 基础URL
|
||||
*/
|
||||
@NotBlank(message = "基础URL不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String baseUrl;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 最大重试次数
|
||||
*/
|
||||
private Integer maxRetries;
|
||||
|
||||
/**
|
||||
* 温度参数
|
||||
*/
|
||||
private BigDecimal temperature;
|
||||
|
||||
/**
|
||||
* 最大token数
|
||||
*/
|
||||
private Integer maxTokens;
|
||||
|
||||
/**
|
||||
* 状态(0:禁用 1:启用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.ruoyi.oa.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI对话历史业务对象 sys_oa_ai_conversation
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOaAiConversationBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
@NotNull(message = "对话ID不能为空", groups = { EditGroup.class })
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 对话标题
|
||||
*/
|
||||
@NotBlank(message = "对话标题不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String conversationTitle;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* AI模型名称
|
||||
*/
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 对话状态(0:已结束 1:进行中)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 总消耗token数
|
||||
*/
|
||||
private Integer totalTokens;
|
||||
|
||||
/**
|
||||
* 总费用
|
||||
*/
|
||||
private BigDecimal totalCost;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ruoyi.oa.domain.bo;
|
||||
|
||||
import com.ruoyi.common.core.validate.AddGroup;
|
||||
import com.ruoyi.common.core.validate.EditGroup;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI对话详情业务对象 sys_oa_ai_message
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOaAiMessageBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
@NotNull(message = "消息ID不能为空", groups = { EditGroup.class })
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
@NotNull(message = "对话ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant)
|
||||
*/
|
||||
@NotBlank(message = "角色不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@NotBlank(message = "消息内容不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 消耗token数
|
||||
*/
|
||||
private Integer tokens;
|
||||
|
||||
/**
|
||||
* 费用
|
||||
*/
|
||||
private BigDecimal cost;
|
||||
|
||||
/**
|
||||
* 消息顺序
|
||||
*/
|
||||
private Integer messageOrder;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI配置视图对象 sys_oa_ai_config
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class SysOaAiConfigVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 配置ID
|
||||
*/
|
||||
@ExcelProperty(value = "配置ID")
|
||||
private Long configId;
|
||||
|
||||
/**
|
||||
* 配置名称
|
||||
*/
|
||||
@ExcelProperty(value = "配置名称")
|
||||
private String configName;
|
||||
|
||||
/**
|
||||
* API密钥
|
||||
*/
|
||||
@ExcelProperty(value = "API密钥")
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 基础URL
|
||||
*/
|
||||
@ExcelProperty(value = "基础URL")
|
||||
private String baseUrl;
|
||||
|
||||
/**
|
||||
* 模型名称
|
||||
*/
|
||||
@ExcelProperty(value = "模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 最大重试次数
|
||||
*/
|
||||
@ExcelProperty(value = "最大重试次数")
|
||||
private Integer maxRetries;
|
||||
|
||||
/**
|
||||
* 温度参数
|
||||
*/
|
||||
@ExcelProperty(value = "温度参数")
|
||||
private BigDecimal temperature;
|
||||
|
||||
/**
|
||||
* 最大token数
|
||||
*/
|
||||
@ExcelProperty(value = "最大token数")
|
||||
private Integer maxTokens;
|
||||
|
||||
/**
|
||||
* 状态(0:禁用 1:启用)
|
||||
*/
|
||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "ai_config_status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ExcelProperty(value = "创建者")
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@ExcelProperty(value = "更新者")
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI对话历史视图对象 sys_oa_ai_conversation
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class SysOaAiConversationVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
@ExcelProperty(value = "对话ID")
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 对话标题
|
||||
*/
|
||||
@ExcelProperty(value = "对话标题")
|
||||
private String conversationTitle;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* AI模型名称
|
||||
*/
|
||||
@ExcelProperty(value = "AI模型名称")
|
||||
private String modelName;
|
||||
|
||||
/**
|
||||
* 对话状态(0:已结束 1:进行中)
|
||||
*/
|
||||
@ExcelProperty(value = "对话状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "ai_conversation_status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 总消耗token数
|
||||
*/
|
||||
@ExcelProperty(value = "总消耗token数")
|
||||
private Integer totalTokens;
|
||||
|
||||
/**
|
||||
* 总费用
|
||||
*/
|
||||
@ExcelProperty(value = "总费用")
|
||||
private BigDecimal totalCost;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ExcelProperty(value = "创建者")
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
@ExcelProperty(value = "更新者")
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@ExcelProperty(value = "备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.ruoyi.oa.domain.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* AI对话详情视图对象 sys_oa_ai_message
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-12-19
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class SysOaAiMessageVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
@ExcelProperty(value = "消息ID")
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* 对话ID
|
||||
*/
|
||||
@ExcelProperty(value = "对话ID")
|
||||
private Long conversationId;
|
||||
|
||||
/**
|
||||
* 角色(user/assistant)
|
||||
*/
|
||||
@ExcelProperty(value = "角色", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "ai_message_role")
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@ExcelProperty(value = "消息内容")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* 消耗token数
|
||||
*/
|
||||
@ExcelProperty(value = "消耗token数")
|
||||
private Integer tokens;
|
||||
|
||||
/**
|
||||
* 费用
|
||||
*/
|
||||
@ExcelProperty(value = "费用")
|
||||
private BigDecimal cost;
|
||||
|
||||
/**
|
||||
* 消息顺序
|
||||
*/
|
||||
@ExcelProperty(value = "消息顺序")
|
||||
private Integer messageOrder;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
@ExcelProperty(value = "创建者")
|
||||
private String createBy;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user