From 1020d2375b32a6ee1445f69f6662a8c6dedeba4a Mon Sep 17 00:00:00 2001 From: junjun Date: Tue, 9 Jul 2024 11:48:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Ecopilot=E6=89=80?= =?UTF-8?q?=E9=9C=80=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/dataease/copilot/api/CopilotAPI.java | 104 +++++ .../dao/auto/entity/CoreCopilotConfig.java | 71 ++++ .../dao/auto/entity/CoreCopilotMsg.java | 276 +++++++++++++ .../dao/auto/entity/CoreCopilotToken.java | 74 ++++ .../auto/mapper/CoreCopilotConfigMapper.java | 18 + .../dao/auto/mapper/CoreCopilotMsgMapper.java | 18 + .../auto/mapper/CoreCopilotTokenMapper.java | 18 + .../copilot/manage/CopilotManage.java | 377 ++++++++++++++++++ .../io/dataease/copilot/manage/MsgManage.java | 100 +++++ .../dataease/copilot/manage/TokenManage.java | 36 ++ .../copilot/service/CopilotService.java | 40 ++ .../main/resources/db/migration/V2.9__ddl.sql | 48 +++ .../io/dataease/api/copilot/CopilotApi.java | 30 ++ .../io/dataease/api/copilot/dto/AxisDTO.java | 12 + .../io/dataease/api/copilot/dto/ChartDTO.java | 13 + .../api/copilot/dto/DEReceiveDTO.java | 13 + .../dataease/api/copilot/dto/DESendDTO.java | 16 + .../dataease/api/copilot/dto/HistoryDTO.java | 12 + .../io/dataease/api/copilot/dto/MsgDTO.java | 53 +++ .../dataease/api/copilot/dto/ReceiveDTO.java | 18 + .../io/dataease/api/copilot/dto/SendDTO.java | 16 + .../io/dataease/api/copilot/dto/TokenDTO.java | 16 + 22 files changed, 1379 insertions(+) create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/api/CopilotAPI.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotConfig.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotMsg.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotToken.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/manage/CopilotManage.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/manage/MsgManage.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/manage/TokenManage.java create mode 100644 core/core-backend/src/main/java/io/dataease/copilot/service/CopilotService.java create mode 100644 core/core-backend/src/main/resources/db/migration/V2.9__ddl.sql create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/CopilotApi.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/AxisDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ChartDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DEReceiveDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DESendDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/HistoryDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/MsgDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ReceiveDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/SendDTO.java create mode 100644 sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/TokenDTO.java diff --git a/core/core-backend/src/main/java/io/dataease/copilot/api/CopilotAPI.java b/core/core-backend/src/main/java/io/dataease/copilot/api/CopilotAPI.java new file mode 100644 index 0000000000..f46c204c17 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/api/CopilotAPI.java @@ -0,0 +1,104 @@ +package io.dataease.copilot.api; + +import io.dataease.api.copilot.dto.ReceiveDTO; +import io.dataease.api.copilot.dto.SendDTO; +import io.dataease.copilot.dao.auto.entity.CoreCopilotConfig; +import io.dataease.copilot.dao.auto.mapper.CoreCopilotConfigMapper; +import io.dataease.exception.DEException; +import io.dataease.utils.HttpClientConfig; +import io.dataease.utils.HttpClientUtil; +import io.dataease.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.json.simple.JSONObject; +import org.springframework.stereotype.Component; + +import java.util.Base64; +import java.util.Map; + +/** + * @Author Junjun + */ +@Component +public class CopilotAPI { + + public static final String TOKEN = "/auth/token/license"; + + public static final String FREE_TOKEN = "/auth/token/free"; + + public static final String API = "/copilot/v1"; + + public static final String CHART = "/generate-chart"; + + public static final String RATE_LIMIT = "/rate-limit"; + + @Resource + private CoreCopilotConfigMapper coreCopilotConfigMapper; + + public String basicAuth(String userName, String password) { + String auth = userName + ":" + password; + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes()); + return "Basic " + encodedAuth; + } + + public String bearerAuth(String token) { + return "Bearer " + token; + } + + public CoreCopilotConfig getConfig() { + CoreCopilotConfig coreCopilotConfig = coreCopilotConfigMapper.selectById(1); + coreCopilotConfig.setPwd(new String(Base64.getDecoder().decode(coreCopilotConfig.getPwd()))); + return coreCopilotConfig; + } + + public String getToken(String license) throws Exception { + String url = getConfig().getCopilotUrl() + TOKEN; + JSONObject json = new JSONObject(); + json.put("licenseText", license); + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", basicAuth(getConfig().getUsername(), getConfig().getPwd())); + String tokenJson = HttpClientUtil.post(url, json.toString(), httpClientConfig); + return (String) JsonUtil.parse(tokenJson, Map.class).get("accessToken"); + } + + public String getFreeToken() throws Exception { + String url = getConfig().getCopilotUrl() + FREE_TOKEN; + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", basicAuth(getConfig().getUsername(), getConfig().getPwd())); + String tokenJson = HttpClientUtil.post(url, "", httpClientConfig); + return (String) JsonUtil.parse(tokenJson, Map.class).get("accessToken"); + } + + public ReceiveDTO generateChart(String token, SendDTO sendDTO) { + String url = getConfig().getCopilotUrl() + API + CHART; + String request = (String) JsonUtil.toJSONString(sendDTO); + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", bearerAuth(token)); + String result = HttpClientUtil.post(url, request, httpClientConfig); + return JsonUtil.parseObject(result, ReceiveDTO.class); + } + + public void checkRateLimit(String token) { + String url = getConfig().getCopilotUrl() + API + RATE_LIMIT; + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", bearerAuth(token)); + HttpResponse httpResponse = HttpClientUtil.postWithHeaders(url, null, httpClientConfig); + Header[] allHeaders = httpResponse.getAllHeaders(); + + String limit = ""; + String seconds = ""; + for (Header header : allHeaders) { + if (StringUtils.equalsIgnoreCase(header.getName(), "x-rate-limit-remaining")) { + limit = header.getValue(); + } + if (StringUtils.equalsIgnoreCase(header.getName(), "x-rate-limit-retry-after-seconds")) { + seconds = header.getValue(); + } + } + if (Long.parseLong(limit) <= 0) { + DEException.throwException(String.format("当前请求频率已达上限,请在%s秒后重试", seconds)); + } + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotConfig.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotConfig.java new file mode 100644 index 0000000000..7b7177b0c9 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotConfig.java @@ -0,0 +1,71 @@ +package io.dataease.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author fit2cloud + * @since 2024-07-08 + */ +@TableName("core_copilot_config") +public class CoreCopilotConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + private String copilotUrl; + + private String username; + + private String pwd; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCopilotUrl() { + return copilotUrl; + } + + public void setCopilotUrl(String copilotUrl) { + this.copilotUrl = copilotUrl; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPwd() { + return pwd; + } + + public void setPwd(String pwd) { + this.pwd = pwd; + } + + @Override + public String toString() { + return "CoreCopilotConfig{" + + "id = " + id + + ", copilotUrl = " + copilotUrl + + ", username = " + username + + ", pwd = " + pwd + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotMsg.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotMsg.java new file mode 100644 index 0000000000..5c6f746044 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotMsg.java @@ -0,0 +1,276 @@ +package io.dataease.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author fit2cloud + * @since 2024-07-04 + */ +@TableName("core_copilot_msg") +public class CoreCopilotMsg implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 数据集ID + */ + private Long datasetGroupId; + + /** + * user or api + */ + private String msgType; + + /** + * mysql oracle ... + */ + private String engineType; + + /** + * create sql + */ + private String schemaSql; + + /** + * 用户提问 + */ + private String question; + + /** + * 历史信息 + */ + private String history; + + /** + * copilot 返回 sql + */ + private String copilotSql; + + /** + * copilot 返回信息 + */ + private String apiMsg; + + /** + * sql 状态 + */ + private Integer sqlOk; + + /** + * chart 状态 + */ + private Integer chartOk; + + /** + * chart 内容 + */ + private String chart; + + /** + * 视图数据 + */ + private String chartData; + + /** + * 执行请求的SQL + */ + private String execSql; + + /** + * msg状态,0失败 1成功 + */ + private Integer msgStatus; + + /** + * de错误信息 + */ + private String errMsg; + + /** + * 创建时间 + */ + private Long createTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getDatasetGroupId() { + return datasetGroupId; + } + + public void setDatasetGroupId(Long datasetGroupId) { + this.datasetGroupId = datasetGroupId; + } + + public String getMsgType() { + return msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String getEngineType() { + return engineType; + } + + public void setEngineType(String engineType) { + this.engineType = engineType; + } + + public String getSchemaSql() { + return schemaSql; + } + + public void setSchemaSql(String schemaSql) { + this.schemaSql = schemaSql; + } + + public String getQuestion() { + return question; + } + + public void setQuestion(String question) { + this.question = question; + } + + public String getHistory() { + return history; + } + + public void setHistory(String history) { + this.history = history; + } + + public String getCopilotSql() { + return copilotSql; + } + + public void setCopilotSql(String copilotSql) { + this.copilotSql = copilotSql; + } + + public String getApiMsg() { + return apiMsg; + } + + public void setApiMsg(String apiMsg) { + this.apiMsg = apiMsg; + } + + public Integer getSqlOk() { + return sqlOk; + } + + public void setSqlOk(Integer sqlOk) { + this.sqlOk = sqlOk; + } + + public Integer getChartOk() { + return chartOk; + } + + public void setChartOk(Integer chartOk) { + this.chartOk = chartOk; + } + + public String getChart() { + return chart; + } + + public void setChart(String chart) { + this.chart = chart; + } + + public String getChartData() { + return chartData; + } + + public void setChartData(String chartData) { + this.chartData = chartData; + } + + public String getExecSql() { + return execSql; + } + + public void setExecSql(String execSql) { + this.execSql = execSql; + } + + public Integer getMsgStatus() { + return msgStatus; + } + + public void setMsgStatus(Integer msgStatus) { + this.msgStatus = msgStatus; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + @Override + public String toString() { + return "CoreCopilotMsg{" + + "id = " + id + + ", userId = " + userId + + ", datasetGroupId = " + datasetGroupId + + ", msgType = " + msgType + + ", engineType = " + engineType + + ", schemaSql = " + schemaSql + + ", question = " + question + + ", history = " + history + + ", copilotSql = " + copilotSql + + ", apiMsg = " + apiMsg + + ", sqlOk = " + sqlOk + + ", chartOk = " + chartOk + + ", chart = " + chart + + ", chartData = " + chartData + + ", execSql = " + execSql + + ", msgStatus = " + msgStatus + + ", errMsg = " + errMsg + + ", createTime = " + createTime + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotToken.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotToken.java new file mode 100644 index 0000000000..40b0617386 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/entity/CoreCopilotToken.java @@ -0,0 +1,74 @@ +package io.dataease.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author fit2cloud + * @since 2024-07-08 + */ +@TableName("core_copilot_token") +public class CoreCopilotToken implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * free or license + */ + private String type; + + private String token; + + private Long updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "CoreCopilotToken{" + + "id = " + id + + ", type = " + type + + ", token = " + token + + ", updateTime = " + updateTime + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java new file mode 100644 index 0000000000..85e1097a32 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java @@ -0,0 +1,18 @@ +package io.dataease.copilot.dao.auto.mapper; + +import io.dataease.copilot.dao.auto.entity.CoreCopilotConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fit2cloud + * @since 2024-07-08 + */ +@Mapper +public interface CoreCopilotConfigMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java new file mode 100644 index 0000000000..c513ec6baa --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java @@ -0,0 +1,18 @@ +package io.dataease.copilot.dao.auto.mapper; + +import io.dataease.copilot.dao.auto.entity.CoreCopilotMsg; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fit2cloud + * @since 2024-07-04 + */ +@Mapper +public interface CoreCopilotMsgMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java new file mode 100644 index 0000000000..9aff24664c --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java @@ -0,0 +1,18 @@ +package io.dataease.copilot.dao.auto.mapper; + +import io.dataease.copilot.dao.auto.entity.CoreCopilotToken; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author fit2cloud + * @since 2024-07-08 + */ +@Mapper +public interface CoreCopilotTokenMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/manage/CopilotManage.java b/core/core-backend/src/main/java/io/dataease/copilot/manage/CopilotManage.java new file mode 100644 index 0000000000..651ef3ea9e --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/manage/CopilotManage.java @@ -0,0 +1,377 @@ +package io.dataease.copilot.manage; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.dataease.api.copilot.dto.DESendDTO; +import io.dataease.api.copilot.dto.MsgDTO; +import io.dataease.api.copilot.dto.ReceiveDTO; +import io.dataease.api.copilot.dto.TokenDTO; +import io.dataease.api.dataset.union.DatasetGroupInfoDTO; +import io.dataease.api.dataset.union.UnionDTO; +import io.dataease.chart.utils.ChartDataBuild; +import io.dataease.copilot.api.CopilotAPI; +import io.dataease.dataset.dao.auto.entity.CoreDatasetGroup; +import io.dataease.dataset.dao.auto.mapper.CoreDatasetGroupMapper; +import io.dataease.dataset.manage.DatasetDataManage; +import io.dataease.dataset.manage.DatasetSQLManage; +import io.dataease.dataset.manage.DatasetTableFieldManage; +import io.dataease.dataset.manage.PermissionManage; +import io.dataease.engine.constant.DeTypeConstants; +import io.dataease.engine.utils.Utils; +import io.dataease.exception.DEException; +import io.dataease.extensions.datasource.constant.SqlPlaceholderConstants; +import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO; +import io.dataease.extensions.datasource.dto.DatasourceRequest; +import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO; +import io.dataease.extensions.datasource.dto.TableField; +import io.dataease.extensions.datasource.factory.ProviderFactory; +import io.dataease.extensions.datasource.provider.Provider; +import io.dataease.extensions.view.dto.ColumnPermissionItem; +import io.dataease.i18n.Translator; +import io.dataease.license.dao.po.LicensePO; +import io.dataease.license.manage.F2CLicManage; +import io.dataease.license.utils.LicenseUtil; +import io.dataease.utils.AuthUtils; +import io.dataease.utils.BeanUtils; +import io.dataease.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author Junjun + */ +@Component +public class CopilotManage { + @Resource + private DatasetSQLManage datasetSQLManage; + @Resource + private CoreDatasetGroupMapper coreDatasetGroupMapper; + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + @Resource + private DatasetDataManage datasetDataManage; + @Resource + private PermissionManage permissionManage; + @Resource + private MsgManage msgManage; + + private static Logger logger = LoggerFactory.getLogger(CopilotManage.class); + + @Resource + private TokenManage tokenManage; + + @Resource + private CopilotAPI copilotAPI; + + @Resource + private F2CLicManage f2CLicManage; + + public MsgDTO chat(MsgDTO msgDTO) throws Exception { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(msgDTO.getDatasetGroupId()); + if (coreDatasetGroup == null) { + return null; + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(msgDTO.getDatasetGroupId()); + List allFields = dsFields.stream().filter(ele -> ele.getExtField() == 0) + .map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getDataeaseName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null); + String sql = (String) sqlMap.get("sql");// 数据集原始SQL + Map dsMap = (Map) sqlMap.get("dsMap"); + boolean crossDs = Utils.isCrossDs(dsMap); + if (crossDs) { + DEException.throwException("跨源数据集不支持该功能"); + } + + // 调用copilot service 获取SQL和chart struct,将返回SQL中表名替换成数据集SQL + // deSendDTO 构建schema和engine + if (ObjectUtils.isEmpty(dsMap)) { + DEException.throwException("No datasource"); + } + + DatasourceSchemaDTO ds = dsMap.entrySet().iterator().next().getValue(); + String type = ds.getType();// 数据库类型,如mysql,oracle等,可能需要映射成copilot需要的类型 + + datasetDataManage.buildFieldName(sqlMap, allFields); + List strings = transCreateTableFields(allFields); + String createSql = "CREATE TABLE de_tmp_table (" + StringUtils.join(strings, ",") + ")"; + logger.info("Copilot Schema SQL: " + createSql); + +// PerMsgDTO perMsgDTO = new PerMsgDTO(); + msgDTO.setDatasetGroupId(dto.getId()); + msgDTO.setMsgType("user"); + msgDTO.setEngineType(type); + msgDTO.setSchemaSql(createSql); + msgDTO.setHistory(msgDTO.getHistory()); + msgDTO.setMsgStatus(1); + msgManage.save(msgDTO);// 到这里为止,提问所需参数构建完毕,往数据库插入一条提问记录 + + DESendDTO deSendDTO = new DESendDTO(); + deSendDTO.setDatasetGroupId(dto.getId()); + deSendDTO.setQuestion(msgDTO.getQuestion()); + deSendDTO.setHistory(msgDTO.getHistory()); + deSendDTO.setEngine(type); + deSendDTO.setSchema(createSql); + + // do copilot chat + ReceiveDTO receiveDTO = copilotChat(deSendDTO); + + // copilot 请求结束,继续de获取数据 + // 获取数据集相关行列权限、最终再套一层SQL + Map desensitizationList = new HashMap<>(); + allFields = permissionManage.filterColumnPermissions(allFields, desensitizationList, dto.getId(), null); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_column_permission")); + } + + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + + if (!crossDs) { + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsList.getFirst()); + } + +// List rowPermissionsTree = new ArrayList<>(); +// TokenUserBO user = AuthUtils.getUser(); +// if (user != null) { +// rowPermissionsTree = permissionManage.getRowPermissionsTree(dto.getId(), user.getUserId()); +// } + + // build query sql +// SQLMeta sqlMeta = new SQLMeta(); +// Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); +// Field2SQLObj.field2sqlObj(sqlMeta, allFields, allFields, crossDs, dsMap); +// WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, allFields, crossDs, dsMap); +// Order2SQLObj.getOrders(sqlMeta, dto.getSortFields(), allFields, crossDs, dsMap); +// String querySQL = SQLProvider.createQuerySQL(sqlMeta, false, false, needOrder); +// querySQL = provider.rebuildSQL(querySQL, sqlMeta, crossDs, dsMap); +// logger.info("preview sql: " + querySQL); + // todo test + String querySQL = sql; + + String copilotSQL = receiveDTO.getSql(); + // 通过数据源请求数据 + // 调用数据源的calcite获得data + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setDsList(dsMap); + String s = ""; + Map data; + try { + s = copilotSQL + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "de_tmp_table" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ")") + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "DE_TMP_TABLE" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ")"); + logger.info("copilot sql: " + s); + datasourceRequest.setQuery(s); + data = provider.fetchResultField(datasourceRequest); + } catch (Exception e) { + try { + s = copilotSQL + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "de_tmp_table" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ") tmp") + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "DE_TMP_TABLE" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ") tmp"); + logger.info("copilot sql: " + s); + datasourceRequest.setQuery(s); + data = provider.fetchResultField(datasourceRequest); + } catch (Exception e1) { + // 如果异常,则获取最后一条成功的history + MsgDTO lastSuccessMsg = msgManage.getLastSuccessMsg(AuthUtils.getUser().getUserId(), dto.getId()); + // 请求数据出错,记录错误信息和copilot返回的信息 + MsgDTO result = new MsgDTO(); + result.setDatasetGroupId(dto.getId()); + result.setMsgType("api"); + result.setHistory(lastSuccessMsg == null ? new ArrayList<>() : lastSuccessMsg.getHistory()); + result.setCopilotSql(receiveDTO.getSql()); + result.setApiMsg(receiveDTO.getApiMessage()); + result.setSqlOk(receiveDTO.getSqlOk() ? 1 : 0); + result.setChartOk(receiveDTO.getChartOk() ? 1 : 0); + result.setChart(receiveDTO.getChart()); + result.setExecSql(s); + result.setMsgStatus(0); + result.setErrMsg(e1.getMessage()); + msgManage.save(result); + return result; + } + } + + List fields = (List) data.get("fields"); + Map map = new LinkedHashMap<>(); + // 重新构造data + Map previewData = buildPreviewData(data, fields, desensitizationList); + + map.put("data", previewData); +// map.put("allFields", allFields);// map.data 中包含了fields和data +// if (ObjectUtils.isEmpty(dto.getId())) { +// map.put("allFields", allFields); +// } else { +// List fieldList = datasetTableFieldManage.selectByDatasetGroupId(dto.getId()); +// map.put("allFields", fieldList); +// } + map.put("sql", Base64.getEncoder().encodeToString(s.getBytes())); + + MsgDTO result = new MsgDTO(); + result.setDatasetGroupId(dto.getId()); + result.setMsgType("api"); + result.setHistory(receiveDTO.getHistory()); + result.setCopilotSql(receiveDTO.getSql()); + result.setApiMsg(receiveDTO.getApiMessage()); + result.setSqlOk(receiveDTO.getSqlOk() ? 1 : 0); + result.setChartOk(receiveDTO.getChartOk() ? 1 : 0); + result.setChart(receiveDTO.getChart()); + result.setChartData(map); + result.setExecSql(s); + result.setMsgStatus(1); + msgManage.save(result); + return result; + } + + public ReceiveDTO copilotChat(DESendDTO deSendDTO) throws Exception { + boolean valid = LicenseUtil.licenseValid(); + // call copilot service + TokenDTO tokenDTO = tokenManage.getToken(valid); + ReceiveDTO receiveDTO; + if (StringUtils.isEmpty(tokenDTO.getToken())) { + // get token + String token; + if (valid) { + LicensePO read = f2CLicManage.read(); + token = copilotAPI.getToken(read.getLicense()); + } else { + token = copilotAPI.getFreeToken(); + } + tokenManage.updateToken(token, valid); + receiveDTO = copilotAPI.generateChart(token, deSendDTO); + } else { + try { + receiveDTO = copilotAPI.generateChart(tokenDTO.getToken(), deSendDTO); + } catch (Exception e) { + // error, get token again + String token; + if (valid) { + LicensePO read = f2CLicManage.read(); + token = copilotAPI.getToken(read.getLicense()); + } else { + token = copilotAPI.getFreeToken(); + } + tokenManage.updateToken(token, valid); + receiveDTO = copilotAPI.generateChart(token, deSendDTO); + } + } + + if (!receiveDTO.getSqlOk() || !receiveDTO.getChartOk()) { + DEException.throwException((String) JsonUtil.toJSONString(receiveDTO)); + } + logger.info("Copilot Service SQL: " + receiveDTO.getSql()); + logger.info("Copilot Service Chart: " + JsonUtil.toJSONString(receiveDTO.getChart())); + return receiveDTO; + } + + public List getList(Long userId) { + MsgDTO lastMsg = msgManage.getLastMsg(userId); + if (lastMsg == null) { + return null; + } + List msg = msgManage.getMsg(lastMsg); + msgManage.deleteMsg(lastMsg); + return msg; + } + + public void clearAll(Long userId) { + msgManage.clearAllUserMsg(userId); + } + + public MsgDTO errorMsg(MsgDTO msgDTO, String errMsg) throws Exception { + // 如果异常,则获取最后一条成功的history + MsgDTO lastSuccessMsg = msgManage.getLastSuccessMsg(AuthUtils.getUser().getUserId(), msgDTO.getDatasetGroupId()); + MsgDTO dto = new MsgDTO(); + dto.setDatasetGroupId(msgDTO.getDatasetGroupId()); + dto.setHistory(lastSuccessMsg == null ? new ArrayList<>() : lastSuccessMsg.getHistory()); + dto.setMsgStatus(0); + dto.setMsgType("api"); + dto.setErrMsg(errMsg); + msgManage.save(dto); + return dto; + } + + public Map buildPreviewData(Map data, List fields, Map desensitizationList) { + Map map = new LinkedHashMap<>(); + List dataList = (List) data.get("data"); + List> dataObjectList = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(dataList)) { + for (int i = 0; i < dataList.size(); i++) { + String[] row = dataList.get(i); + LinkedHashMap obj = new LinkedHashMap<>(); + if (row.length > 0) { + for (int j = 0; j < fields.size(); j++) { + TableField tableField = fields.get(j); + if (desensitizationList.containsKey(tableField.getOriginName())) { + obj.put(tableField.getOriginName(), ChartDataBuild.desensitizationValue(desensitizationList.get(tableField.getOriginName()), String.valueOf(row[j]))); + } else { + if (tableField.getDeExtractType() == DeTypeConstants.DE_INT + || tableField.getDeExtractType() == DeTypeConstants.DE_FLOAT + || tableField.getDeExtractType() == DeTypeConstants.DE_BOOL) { + try { + obj.put(tableField.getOriginName(), new BigDecimal(row[j])); + } catch (Exception e) { + obj.put(tableField.getOriginName(), row[j]); + } + } else { + obj.put(tableField.getOriginName(), row[j]); + } + } + } + } + dataObjectList.add(obj); + } + } + + map.put("fields", fields); + map.put("data", dataObjectList); + return map; + } + + public List transCreateTableFields(List allFields) { + List list = new ArrayList<>(); + for (DatasetTableFieldDTO dto : allFields) { + list.add(" " + dto.getDataeaseName() + " " + transNum2Type(dto.getDeExtractType()) + + " COMMENT '" + dto.getName() + "'"); + } + return list; + } + + public String transNum2Type(Integer num) { + return switch (num) { + case 0, 1, 5 -> "VARCHAR(50)"; + case 2, 3, 4 -> "INT(10)"; + default -> "VARCHAR(50)"; + }; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/manage/MsgManage.java b/core/core-backend/src/main/java/io/dataease/copilot/manage/MsgManage.java new file mode 100644 index 0000000000..a3dbaa29ab --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/manage/MsgManage.java @@ -0,0 +1,100 @@ +package io.dataease.copilot.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.dataease.api.copilot.dto.ChartDTO; +import io.dataease.api.copilot.dto.HistoryDTO; +import io.dataease.api.copilot.dto.MsgDTO; +import io.dataease.copilot.dao.auto.entity.CoreCopilotMsg; +import io.dataease.copilot.dao.auto.mapper.CoreCopilotMsgMapper; +import io.dataease.utils.AuthUtils; +import io.dataease.utils.BeanUtils; +import io.dataease.utils.IDUtils; +import io.dataease.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @Author Junjun + */ +@Component +public class MsgManage { + @Resource + private CoreCopilotMsgMapper coreCopilotMsgMapper; + + private ObjectMapper objectMapper = new ObjectMapper(); + + public void save(MsgDTO msgDTO) throws Exception { + msgDTO.setId(IDUtils.snowID()); + msgDTO.setCreateTime(System.currentTimeMillis()); + msgDTO.setUserId(AuthUtils.getUser().getUserId()); + coreCopilotMsgMapper.insert(transDTO(msgDTO)); + } + + public List getMsg(MsgDTO msgDTO) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", msgDTO.getUserId()); + wrapper.eq("dataset_group_id", msgDTO.getDatasetGroupId()); + wrapper.orderByAsc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return perCopilotMsgs.stream().map(this::transRecord).toList(); + } + + public void deleteMsg(MsgDTO msgDTO) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", msgDTO.getUserId()); + wrapper.ne("dataset_group_id", msgDTO.getDatasetGroupId()); + coreCopilotMsgMapper.delete(wrapper); + } + + public void clearAllUserMsg(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + coreCopilotMsgMapper.delete(wrapper); + } + + public MsgDTO getLastMsg(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + wrapper.orderByDesc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return ObjectUtils.isEmpty(perCopilotMsgs) ? null : transRecord(perCopilotMsgs.getFirst()); + } + + public MsgDTO getLastSuccessMsg(Long userId, Long datasetGroupId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + wrapper.eq("dataset_group_id", datasetGroupId); + wrapper.eq("msg_status", 1); + wrapper.eq("msg_type", "api"); + wrapper.orderByDesc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return ObjectUtils.isEmpty(perCopilotMsgs) ? null : transRecord(perCopilotMsgs.getFirst()); + } + + private CoreCopilotMsg transDTO(MsgDTO dto) throws Exception { + CoreCopilotMsg record = new CoreCopilotMsg(); + BeanUtils.copyBean(record, dto); + record.setHistory(dto.getHistory() == null ? null : objectMapper.writeValueAsString(dto.getHistory())); + record.setChart(dto.getChart() == null ? null : objectMapper.writeValueAsString(dto.getChart())); + record.setChartData(dto.getChartData() == null ? null : objectMapper.writeValueAsString(dto.getChartData())); + return record; + } + + private MsgDTO transRecord(CoreCopilotMsg record) { + MsgDTO dto = new MsgDTO(); + BeanUtils.copyBean(dto, record); + TypeReference> tokenType = new TypeReference<>() { + }; + dto.setHistory(record.getHistory() == null ? new ArrayList<>() : JsonUtil.parseList(record.getHistory(), tokenType)); + dto.setChart(record.getChart() == null ? null : JsonUtil.parseObject(record.getChart(), ChartDTO.class)); + dto.setChartData(record.getChartData() == null ? null : JsonUtil.parse(record.getChartData(), Map.class)); + return dto; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/manage/TokenManage.java b/core/core-backend/src/main/java/io/dataease/copilot/manage/TokenManage.java new file mode 100644 index 0000000000..104de25ac1 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/manage/TokenManage.java @@ -0,0 +1,36 @@ +package io.dataease.copilot.manage; + +import io.dataease.api.copilot.dto.TokenDTO; +import io.dataease.copilot.dao.auto.entity.CoreCopilotToken; +import io.dataease.copilot.dao.auto.mapper.CoreCopilotTokenMapper; +import io.dataease.utils.BeanUtils; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * @Author Junjun + */ +@Component +public class TokenManage { + @Resource + private CoreCopilotTokenMapper coreCopilotTokenMapper; + + public TokenDTO getToken(boolean valid) { + CoreCopilotToken perCopilotToken = coreCopilotTokenMapper.selectById(valid ? 2 : 1); + return transRecord(perCopilotToken); + } + + public void updateToken(String token, boolean valid) { + CoreCopilotToken record = new CoreCopilotToken(); + record.setId(valid ? 2L : 1L); + record.setToken(token); + record.setUpdateTime(System.currentTimeMillis()); + coreCopilotTokenMapper.updateById(record); + } + + private TokenDTO transRecord(CoreCopilotToken perCopilotToken) { + TokenDTO dto = new TokenDTO(); + BeanUtils.copyBean(dto, perCopilotToken); + return dto; + } +} diff --git a/core/core-backend/src/main/java/io/dataease/copilot/service/CopilotService.java b/core/core-backend/src/main/java/io/dataease/copilot/service/CopilotService.java new file mode 100644 index 0000000000..e78a7bd230 --- /dev/null +++ b/core/core-backend/src/main/java/io/dataease/copilot/service/CopilotService.java @@ -0,0 +1,40 @@ +package io.dataease.copilot.service; + +import io.dataease.api.copilot.CopilotApi; +import io.dataease.api.copilot.dto.MsgDTO; +import io.dataease.copilot.manage.CopilotManage; +import io.dataease.utils.AuthUtils; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @Author Junjun + */ +@RestController +@RequestMapping("copilot") +public class CopilotService implements CopilotApi { + @Resource + private CopilotManage copilotManage; + + @Override + public MsgDTO chat(MsgDTO msgDTO) throws Exception { + try { + return copilotManage.chat(msgDTO); + } catch (Exception e) { + return copilotManage.errorMsg(msgDTO, e.getMessage()); + } + } + + @Override + public List getList() throws Exception { + return copilotManage.getList(AuthUtils.getUser().getUserId()); + } + + @Override + public void clearAll() throws Exception { + copilotManage.clearAll(AuthUtils.getUser().getUserId()); + } +} diff --git a/core/core-backend/src/main/resources/db/migration/V2.9__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.9__ddl.sql new file mode 100644 index 0000000000..6a8724cabf --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.9__ddl.sql @@ -0,0 +1,48 @@ +DROP TABLE IF EXISTS `core_copilot_msg`; +CREATE TABLE `core_copilot_msg` ( + `id` bigint NOT NULL COMMENT 'ID', + `user_id` bigint DEFAULT NULL COMMENT '用户ID', + `dataset_group_id` bigint DEFAULT NULL COMMENT '数据集ID', + `msg_type` varchar(255) DEFAULT NULL COMMENT 'user or api', + `engine_type` varchar(255) DEFAULT NULL COMMENT 'mysql oracle ...', + `schema_sql` longtext COMMENT 'create sql', + `question` longtext COMMENT '用户提问', + `history` longtext COMMENT '历史信息', + `copilot_sql` longtext COMMENT 'copilot 返回 sql', + `api_msg` longtext COMMENT 'copilot 返回信息', + `sql_ok` int DEFAULT NULL COMMENT 'sql 状态', + `chart_ok` int DEFAULT NULL COMMENT 'chart 状态', + `chart` longtext COMMENT 'chart 内容', + `chart_data` longtext COMMENT '视图数据', + `exec_sql` longtext COMMENT '执行请求的SQL', + `msg_status` int DEFAULT NULL COMMENT 'msg状态,0失败 1成功', + `err_msg` longtext COMMENT 'de错误信息', + `create_time` bigint DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) +); + + +DROP TABLE IF EXISTS `core_copilot_token`; +CREATE TABLE `core_copilot_token` ( + `id` bigint NOT NULL COMMENT 'ID', + `type` varchar(255) DEFAULT NULL COMMENT 'free or license', + `token` longtext, + `update_time` bigint DEFAULT NULL, + PRIMARY KEY (`id`) +); + +INSERT INTO `core_copilot_token` VALUES (1, 'free', null, null); +INSERT INTO `core_copilot_token` VALUES (2, 'license', null, null); + + +DROP TABLE IF EXISTS `core_copilot_config`; +CREATE TABLE `core_copilot_config` ( + `id` bigint NOT NULL COMMENT 'ID', + `copilot_url` varchar(255) DEFAULT NULL, + `username` varchar(255) DEFAULT NULL, + `pwd` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +); + +INSERT INTO `core_copilot_config` VALUES (1, 'https://copilot-demo.test.fit2cloud.dev:5000', 'xlab', 'Q2Fsb25nQDIwMTU='); + diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/CopilotApi.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/CopilotApi.java new file mode 100644 index 0000000000..73437083c7 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/CopilotApi.java @@ -0,0 +1,30 @@ +package io.dataease.api.copilot; + +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import io.dataease.api.copilot.dto.MsgDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; + +/** + * @Author Junjun + */ +@Tag(name = "Copilot") +@ApiSupport(order = 999) +public interface CopilotApi { + @Operation(summary = "发起一次对话") + @PostMapping("chat") + MsgDTO chat(@RequestBody MsgDTO msgDTO) throws Exception; + + @Operation(summary = "获取对话记录") + @PostMapping("getList") + List getList() throws Exception; + + @Operation(summary = "清空对话") + @PostMapping("clearAll") + void clearAll() throws Exception; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/AxisDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/AxisDTO.java new file mode 100644 index 0000000000..208914af9e --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/AxisDTO.java @@ -0,0 +1,12 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class AxisDTO { + private String x; + private String y; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ChartDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ChartDTO.java new file mode 100644 index 0000000000..acf5cb85f5 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ChartDTO.java @@ -0,0 +1,13 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class ChartDTO { + private String type; + private AxisDTO axis; + private String title; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DEReceiveDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DEReceiveDTO.java new file mode 100644 index 0000000000..e19d8e2f5e --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DEReceiveDTO.java @@ -0,0 +1,13 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * @Author Junjun + */ +@Data +public class DEReceiveDTO extends ReceiveDTO { + private Map chartData; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DESendDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DESendDTO.java new file mode 100644 index 0000000000..aceb17a028 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/DESendDTO.java @@ -0,0 +1,16 @@ +package io.dataease.api.copilot.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class DESendDTO extends SendDTO { + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetGroupId; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/HistoryDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/HistoryDTO.java new file mode 100644 index 0000000000..ca8d00a980 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/HistoryDTO.java @@ -0,0 +1,12 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class HistoryDTO { + private String type; + private String message; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/MsgDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/MsgDTO.java new file mode 100644 index 0000000000..58ae5496be --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/MsgDTO.java @@ -0,0 +1,53 @@ +package io.dataease.api.copilot.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * @Author Junjun + */ +@Data +public class MsgDTO { + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long userId; + + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetGroupId; + + private String msgType; + + private String engineType; + + private String schemaSql; + + private String question; + + private List history; + + private String copilotSql; + + private String apiMsg; + + private Integer sqlOk; + + private Integer chartOk; + + private ChartDTO chart; + + private Long createTime; + + private Map chartData; + + private String execSql; + + private Integer msgStatus; + + private String errMsg; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ReceiveDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ReceiveDTO.java new file mode 100644 index 0000000000..d234450b2b --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/ReceiveDTO.java @@ -0,0 +1,18 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @Author Junjun + */ +@Data +public class ReceiveDTO { + private String sql; + private List history; + private String apiMessage; + private Boolean sqlOk; + private Boolean chartOk; + private ChartDTO chart; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/SendDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/SendDTO.java new file mode 100644 index 0000000000..2bb7c360c3 --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/SendDTO.java @@ -0,0 +1,16 @@ +package io.dataease.api.copilot.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @Author Junjun + */ +@Data +public class SendDTO { + private String engine; + private String schema; + private String question; + private List history; +} diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/TokenDTO.java b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/TokenDTO.java new file mode 100644 index 0000000000..93b52c69fe --- /dev/null +++ b/sdk/api/api-base/src/main/java/io/dataease/api/copilot/dto/TokenDTO.java @@ -0,0 +1,16 @@ +package io.dataease.api.copilot.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class TokenDTO { + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + private String token; + private Long updateTime; +}