[improvement][project] supersonic 0.6.0 version update (#16)

Co-authored-by: lexluo <lexluo@tencent.com>
This commit is contained in:
lexluo09
2023-07-16 21:32:33 +08:00
committed by GitHub
parent a0869dc7bd
commit 041daad1e4
261 changed files with 12031 additions and 3266 deletions

View File

@@ -1,8 +1,10 @@
package com.tencent.supersonic.chat.api.component;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.core.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.core.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.core.response.*;
import com.tencent.supersonic.semantic.api.query.request.QuerySqlReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
@@ -26,8 +28,24 @@ public interface SemanticLayer {
QueryResultWithSchemaResp queryBySql(QuerySqlReq querySqlReq, User user);
DomainSchemaResp getDomainSchemaInfo(Long domain);
DomainSchemaResp getDomainSchemaInfo(Long domain, Boolean cacheEnable);
List<DomainSchemaResp> getDomainSchemaInfo(List<Long> ids);
List<DomainResp> getDomainListForViewer();
List<DomainResp> getDomainListForAdmin();
PageInfo<DimensionResp> queryDimensionPage(PageDimensionReq pageDimensionCmd);
PageInfo<MetricResp> queryMetricPage(PageMetricReq pageMetricCmd);
// PageInfo<MetricResp> queryMetricPage(PageMetricReq pageMetricCmd);
//
// PageInfo<DimensionResp> queryDimensionPage(PageDimensionReq pageDimensionCmd);
//
// List<DomainResp> getDomainListForAdmin();
//
// List<DomainResp> getDomainListForViewer();
}

View File

@@ -3,32 +3,25 @@ package com.tencent.supersonic.chat.application;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBase;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilter;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetric;
import com.tencent.supersonic.chat.domain.pojo.config.EntityRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ItemVisibilityInfo;
import com.tencent.supersonic.chat.domain.pojo.config.KnowledgeInfo;
import com.tencent.supersonic.chat.domain.repository.ChatConfigRepository;
import com.tencent.supersonic.chat.domain.service.ConfigService;
import com.tencent.supersonic.chat.domain.utils.ChatConfigUtils;
import com.tencent.supersonic.chat.domain.pojo.config.*;
import com.tencent.supersonic.chat.domain.utils.ComponentFactory;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import com.tencent.supersonic.common.util.json.JsonUtil;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.chat.domain.repository.ChatConfigRepository;
import com.tencent.supersonic.chat.domain.service.ConfigService;
import com.tencent.supersonic.chat.domain.utils.ChatConfigUtils;
import com.tencent.supersonic.common.util.json.JsonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
@@ -40,33 +33,31 @@ import org.springframework.util.CollectionUtils;
@Service
public class ConfigServiceImpl implements ConfigService {
private final ChatConfigRepository chaConfigRepository;
private final ChatConfigRepository chatConfigRepository;
private final ChatConfigUtils chatConfigUtils;
private final DefaultSemanticInternalUtils defaultSemanticUtils;
private SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
public ConfigServiceImpl(ChatConfigRepository chaConfigRepository,
ChatConfigUtils chatConfigUtils,
@Lazy DefaultSemanticInternalUtils defaultSemanticUtils) {
this.chaConfigRepository = chaConfigRepository;
public ConfigServiceImpl(ChatConfigRepository chatConfigRepository,
ChatConfigUtils chatConfigUtils) {
this.chatConfigRepository = chatConfigRepository;
this.chatConfigUtils = chatConfigUtils;
this.defaultSemanticUtils = defaultSemanticUtils;
}
@Override
public Long addConfig(ChatConfigBase configBaseCmd, User user) {
public Long addConfig(ChatConfigBaseReq configBaseCmd, User user) {
log.info("[create domain extend] object:{}", JsonUtil.toString(configBaseCmd, true));
duplicateCheck(configBaseCmd.getDomainId());
permissionCheckLogic(configBaseCmd.getDomainId(), user.getName());
ChatConfig chaConfig = chatConfigUtils.newChatConfig(configBaseCmd, user);
chaConfigRepository.createConfig(chaConfig);
return chaConfig.getDomainId();
Long id = chatConfigRepository.createConfig(chaConfig);
return id;
}
private void duplicateCheck(Long domainId) {
ChatConfigFilter filter = new ChatConfigFilter();
filter.setDomainId(domainId);
List<ChatConfigInfo> chaConfigDescList = chaConfigRepository.getChatConfig(filter);
List<ChatConfigResp> chaConfigDescList = chatConfigRepository.getChatConfig(filter);
if (!CollectionUtils.isEmpty(chaConfigDescList)) {
throw new RuntimeException("chat config existed, no need to add repeatedly");
}
@@ -74,16 +65,16 @@ public class ConfigServiceImpl implements ConfigService {
@Override
public Long editConfig(ChatConfigEditReq configEditCmd, User user) {
public Long editConfig(ChatConfigEditReqReq configEditCmd, User user) {
log.info("[edit domain extend] object:{}", JsonUtil.toString(configEditCmd, true));
if (Objects.isNull(configEditCmd) || Objects.isNull(configEditCmd.getId()) && Objects.isNull(
configEditCmd.getDomainId())) {
throw new RuntimeException("editConfig, id and domainId are not allowed to be empty at the same time");
}
permissionCheckLogic(configEditCmd.getDomainId(), user.getName());
ChatConfig chaConfig = chatConfigUtils.editChaConfig(configEditCmd, user);
chaConfigRepository.updateConfig(chaConfig);
return configEditCmd.getDomainId();
ChatConfig chaConfig = chatConfigUtils.editChatConfig(configEditCmd, user);
chatConfigRepository.updateConfig(chaConfig);
return configEditCmd.getId();
}
@@ -96,98 +87,34 @@ public class ConfigServiceImpl implements ConfigService {
}
@Override
public List<ChatConfigInfo> search(ChatConfigFilter filter, User user) {
public List<ChatConfigResp> search(ChatConfigFilter filter, User user) {
log.info("[search domain extend] object:{}", JsonUtil.toString(filter, true));
List<ChatConfigInfo> chaConfigDescList = chaConfigRepository.getChatConfig(filter);
List<ChatConfigResp> chaConfigDescList = chatConfigRepository.getChatConfig(filter);
return chaConfigDescList;
}
public ChatConfigInfo fetchConfigByDomainId(Long domainId) {
return chaConfigRepository.getConfigByDomainId(domainId);
}
public EntityRichInfo fetchEntityDescByDomainId(Long domainId) {
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
ChatConfigInfo chaConfigDesc = chaConfigRepository.getConfigByDomainId(domainId);
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(domainId);
return fetchEntityDescByConfig(chaConfigDesc, domainSchemaDesc);
}
public EntityRichInfo fetchEntityDescByConfig(ChatConfigInfo chatConfigDesc, DomainSchemaResp domain) {
Long domainId = chatConfigDesc.getDomainId();
EntityRichInfo entityDesc = new EntityRichInfo();
if (Objects.isNull(chatConfigDesc) || Objects.isNull(chatConfigDesc.getEntity())) {
log.info("domainId:{}, entityDesc info is null", domainId);
return entityDesc;
}
entityDesc.setDomainId(domain.getId());
entityDesc.setDomainBizName(domain.getBizName());
entityDesc.setDomainName(domain.getName());
entityDesc.setNames(chatConfigDesc.getEntity().getNames());
entityDesc.setEntityIds(chatConfigUtils.generateDimDesc(chatConfigDesc.getEntity().getEntityIds(), domain));
entityDesc.setEntityInternalDetailDesc(
chatConfigUtils.generateEntityDetailData(chatConfigDesc.getEntity().getDetailData(), domain));
return entityDesc;
@Override
public ChatConfigResp fetchConfigByDomainId(Long domainId) {
return chatConfigRepository.getConfigByDomainId(domainId);
}
public List<DefaultMetric> fetchDefaultMetricDescByDomainId(Long domainId) {
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
ChatConfigInfo chatConfigDesc = chaConfigRepository.getConfigByDomainId(domainId);
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(domainId);
return fetchDefaultMetricDescByConfig(chatConfigDesc, domainSchemaDesc);
}
public List<DefaultMetric> fetchDefaultMetricDescByConfig(ChatConfigInfo chatConfigDesc, DomainSchemaResp domain) {
Long domainId = chatConfigDesc.getDomainId();
List<DefaultMetric> defaultMetricDescList = new ArrayList<>();
if (Objects.isNull(chatConfigDesc) || CollectionUtils.isEmpty(chatConfigDesc.getDefaultMetrics())) {
log.info("domainId:{}, defaultMetricDescList info is null", domainId);
return defaultMetricDescList;
}
List<Long> metricIds = chatConfigDesc.getDefaultMetrics().stream()
.map(defaultMetricInfo -> defaultMetricInfo.getMetricId()).collect(Collectors.toList());
Map<Long, MetricSchemaResp> metricIdAndDescPair = chatConfigUtils.generateMetricIdAndDescPair(metricIds,
domain);
chatConfigDesc.getDefaultMetrics().stream().forEach(defaultMetricInfo -> {
DefaultMetric defaultMetricDesc = new DefaultMetric();
BeanUtils.copyProperties(defaultMetricInfo, defaultMetricDesc);
if (metricIdAndDescPair.containsKey(defaultMetricInfo.getMetricId())) {
MetricSchemaResp metricDesc = metricIdAndDescPair.get(defaultMetricInfo.getMetricId());
defaultMetricDesc.setBizName(metricDesc.getBizName());
defaultMetricDesc.setName(metricDesc.getName());
}
defaultMetricDescList.add(defaultMetricDesc);
});
return defaultMetricDescList;
}
public ItemVisibilityInfo fetchVisibilityDescByDomainId(Long domainId) {
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
ChatConfigInfo chatConfigDesc = chaConfigRepository.getConfigByDomainId(domainId);
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(domainId);
return fetchVisibilityDescByConfig(chatConfigDesc, domainSchemaDesc);
}
private ItemVisibilityInfo fetchVisibilityDescByConfig(ChatConfigInfo chatConfigDesc,
DomainSchemaResp domainSchemaDesc) {
private ItemVisibilityInfo fetchVisibilityDescByConfig(ItemVisibility visibility,
DomainSchemaResp domainSchemaDesc) {
ItemVisibilityInfo itemVisibilityDesc = new ItemVisibilityInfo();
Long domainId = chatConfigDesc.getDomainId();
List<Long> dimIdAllList = chatConfigUtils.generateAllDimIdList(domainSchemaDesc);
List<Long> metricIdAllList = chatConfigUtils.generateAllMetricIdList(domainSchemaDesc);
List<Long> blackDimIdList = new ArrayList<>();
List<Long> blackMetricIdList = new ArrayList<>();
if (Objects.nonNull(chatConfigDesc.getVisibility())) {
if (!CollectionUtils.isEmpty(chatConfigDesc.getVisibility().getBlackDimIdList())) {
blackDimIdList.addAll(chatConfigDesc.getVisibility().getBlackDimIdList());
if (Objects.nonNull(visibility)) {
if (!CollectionUtils.isEmpty(visibility.getBlackDimIdList())) {
blackDimIdList.addAll(visibility.getBlackDimIdList());
}
if (!CollectionUtils.isEmpty(chatConfigDesc.getVisibility().getBlackMetricIdList())) {
blackMetricIdList.addAll(chatConfigDesc.getVisibility().getBlackMetricIdList());
if (!CollectionUtils.isEmpty(visibility.getBlackMetricIdList())) {
blackMetricIdList.addAll(visibility.getBlackMetricIdList());
}
}
List<Long> whiteMetricIdList = metricIdAllList.stream().filter(id -> !blackMetricIdList.contains(id))
@@ -204,31 +131,110 @@ public class ConfigServiceImpl implements ConfigService {
}
@Override
public ChatConfigRichInfo getConfigRichInfo(Long domainId) {
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
ChatConfigRichInfo chaConfigRichDesc = new ChatConfigRichInfo();
ChatConfigInfo chatConfigDesc = chaConfigRepository.getConfigByDomainId(domainId);
if (Objects.isNull(chatConfigDesc)) {
public ChatConfigRichResp getConfigRichInfo(Long domainId) {
ChatConfigRichResp chatConfigRichResp = new ChatConfigRichResp();
ChatConfigResp chatConfigResp = chatConfigRepository.getConfigByDomainId(domainId);
if (Objects.isNull(chatConfigResp)) {
log.info("there is no chatConfigDesc for domainId:{}", domainId);
return chaConfigRichDesc;
return chatConfigRichResp;
}
BeanUtils.copyProperties(chatConfigDesc, chaConfigRichDesc);
BeanUtils.copyProperties(chatConfigResp, chatConfigRichResp);
DomainSchemaResp domainSchemaInfo = semanticLayer.getDomainSchemaInfo(domainId);
chaConfigRichDesc.setBizName(domainSchemaInfo.getBizName());
chaConfigRichDesc.setName(domainSchemaInfo.getName());
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
DomainSchemaResp domainSchemaInfo = semanticLayer.getDomainSchemaInfo(domainId, false);
chatConfigRichResp.setBizName(domainSchemaInfo.getBizName());
chatConfigRichResp.setDomainName(domainSchemaInfo.getName());
chaConfigRichDesc.setKnowledgeInfos(
fillKnowledgeBizName(chaConfigRichDesc.getKnowledgeInfos(), domainSchemaInfo));
chaConfigRichDesc.setDefaultMetrics(fetchDefaultMetricDescByConfig(chatConfigDesc, domainSchemaInfo));
chaConfigRichDesc.setVisibility(fetchVisibilityDescByConfig(chatConfigDesc, domainSchemaInfo));
chaConfigRichDesc.setEntity(fetchEntityDescByConfig(chatConfigDesc, domainSchemaInfo));
chatConfigRichResp.setChatAggRichConfig(fillChatAggRichConfig(domainSchemaInfo, chatConfigResp));
chatConfigRichResp.setChatDetailRichConfig(fillChatDetailRichConfig(domainSchemaInfo, chatConfigRichResp, chatConfigResp));
return chaConfigRichDesc;
return chatConfigRichResp;
}
private ChatDetailRichConfig fillChatDetailRichConfig(DomainSchemaResp domainSchemaInfo, ChatConfigRichResp chatConfigRichResp, ChatConfigResp chatConfigResp) {
if (Objects.isNull(chatConfigResp) || Objects.isNull(chatConfigResp.getChatDetailConfig())) {
return null;
}
ChatDetailRichConfig detailRichConfig = new ChatDetailRichConfig();
ChatDetailConfig chatDetailConfig = chatConfigResp.getChatDetailConfig();
detailRichConfig.setVisibility(fetchVisibilityDescByConfig(chatDetailConfig.getVisibility(), domainSchemaInfo));
detailRichConfig.setKnowledgeInfos(fillKnowledgeBizName(chatDetailConfig.getKnowledgeInfos(), domainSchemaInfo));
detailRichConfig.setGlobalKnowledgeConfig(chatDetailConfig.getGlobalKnowledgeConfig());
detailRichConfig.setChatDefaultConfig(fetchDefaultConfig(chatDetailConfig.getChatDefaultConfig(), domainSchemaInfo));
detailRichConfig.setEntity(generateRichEntity(chatDetailConfig.getEntity(), domainSchemaInfo));
return detailRichConfig;
}
private EntityRichInfo generateRichEntity(Entity entity, DomainSchemaResp domainSchemaInfo) {
EntityRichInfo entityRichInfo = new EntityRichInfo();
if (Objects.isNull(entity) || Objects.isNull(entity.getEntityId())) {
return entityRichInfo;
}
BeanUtils.copyProperties(entity, entityRichInfo);
Map<Long, DimSchemaResp> dimIdAndRespPair = domainSchemaInfo.getDimensions().stream()
.collect(Collectors.toMap(DimSchemaResp::getId, Function.identity()));
entityRichInfo.setDimItem(dimIdAndRespPair.get(entity.getEntityId()));
return entityRichInfo;
}
private ChatAggRichConfig fillChatAggRichConfig(DomainSchemaResp domainSchemaInfo, ChatConfigResp chatConfigResp) {
if (Objects.isNull(chatConfigResp) || Objects.isNull(chatConfigResp.getChatAggConfig())) {
return null;
}
ChatAggConfig chatAggConfig = chatConfigResp.getChatAggConfig();
ChatAggRichConfig chatAggRichConfig = new ChatAggRichConfig();
chatAggRichConfig.setVisibility(fetchVisibilityDescByConfig(chatAggConfig.getVisibility(), domainSchemaInfo));
chatAggRichConfig.setKnowledgeInfos(fillKnowledgeBizName(chatAggConfig.getKnowledgeInfos(), domainSchemaInfo));
chatAggRichConfig.setGlobalKnowledgeConfig(chatAggConfig.getGlobalKnowledgeConfig());
chatAggRichConfig.setChatDefaultConfig(fetchDefaultConfig(chatAggConfig.getChatDefaultConfig(), domainSchemaInfo));
return chatAggRichConfig;
}
private ChatDefaultRichConfig fetchDefaultConfig(ChatDefaultConfig chatDefaultConfig, DomainSchemaResp domainSchemaInfo) {
ChatDefaultRichConfig defaultRichConfig = new ChatDefaultRichConfig();
if (Objects.isNull(chatDefaultConfig)) {
return defaultRichConfig;
}
BeanUtils.copyProperties(chatDefaultConfig, defaultRichConfig);
Map<Long, DimSchemaResp> dimIdAndRespPair = domainSchemaInfo.getDimensions().stream()
.collect(Collectors.toMap(DimSchemaResp::getId, Function.identity()));
Map<Long, MetricSchemaResp> metricIdAndRespPair = domainSchemaInfo.getMetrics().stream()
.collect(Collectors.toMap(MetricSchemaResp::getId, Function.identity()));
List<SchemaItem> dimensions = new ArrayList<>();
List<SchemaItem> metrics = new ArrayList<>();
if (!CollectionUtils.isEmpty(chatDefaultConfig.getDimensionIds())) {
chatDefaultConfig.getDimensionIds().stream().forEach(dimId -> {
DimSchemaResp dimSchemaResp = dimIdAndRespPair.get(dimId);
SchemaItem dimSchema = new SchemaItem();
BeanUtils.copyProperties(dimSchemaResp, dimSchema);
dimensions.add(dimSchema);
});
}
if (!CollectionUtils.isEmpty(chatDefaultConfig.getMetricIds())) {
chatDefaultConfig.getMetricIds().stream().forEach(metricId -> {
MetricSchemaResp metricSchemaResp = metricIdAndRespPair.get(metricId);
SchemaItem metricSchema = new SchemaItem();
BeanUtils.copyProperties(metricSchemaResp, metricSchema);
metrics.add(metricSchema);
});
}
defaultRichConfig.setDimensions(dimensions);
defaultRichConfig.setMetrics(metrics);
return defaultRichConfig;
}
private List<KnowledgeInfo> fillKnowledgeBizName(List<KnowledgeInfo> knowledgeInfos,
DomainSchemaResp domainSchemaInfo) {
DomainSchemaResp domainSchemaInfo) {
if (CollectionUtils.isEmpty(knowledgeInfos)) {
return new ArrayList<>();
}
@@ -240,30 +246,21 @@ public class ConfigServiceImpl implements ConfigService {
if (Objects.nonNull(dimSchemaResp)) {
knowledgeInfo.setBizName(dimSchemaResp.getBizName());
}
if (CollectionUtils.isEmpty(knowledgeInfo.getBlackList())) {
knowledgeInfo.setBlackList(new ArrayList<>());
}
if (CollectionUtils.isEmpty(knowledgeInfo.getRuleList())) {
knowledgeInfo.setRuleList(new ArrayList<>());
}
if (CollectionUtils.isEmpty(knowledgeInfo.getWhiteList())) {
knowledgeInfo.setWhiteList(new ArrayList<>());
}
}
});
return knowledgeInfos;
}
@Override
public List<ChatConfigRichInfo> getAllChatRichConfig() {
List<ChatConfigRichInfo> chatConfigRichInfoList = new ArrayList<>();
List<DomainResp> domainRespList = defaultSemanticUtils.getDomainListForAdmin();
public List<ChatConfigRichResp> getAllChatRichConfig() {
List<ChatConfigRichResp> chatConfigRichInfoList = new ArrayList<>();
List<DomainResp> domainRespList = semanticLayer.getDomainListForAdmin();
domainRespList.stream().forEach(domainResp -> {
ChatConfigRichInfo chatConfigRichInfo = getConfigRichInfo(domainResp.getId());
ChatConfigRichResp chatConfigRichInfo = getConfigRichInfo(domainResp.getId());
if (Objects.nonNull(chatConfigRichInfo)) {
chatConfigRichInfoList.add(chatConfigRichInfo);
}
});
return chatConfigRichInfoList;
}
}
}

View File

@@ -8,15 +8,14 @@ import com.tencent.supersonic.chat.api.pojo.DomainInfo;
import com.tencent.supersonic.chat.api.pojo.EntityInfo;
import com.tencent.supersonic.chat.api.pojo.Filter;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatDefaultRichConfig;
import com.tencent.supersonic.chat.domain.pojo.config.EntityRichInfo;
import com.tencent.supersonic.chat.domain.utils.ComponentFactory;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import com.tencent.supersonic.chat.domain.utils.SchemaInfoConverter;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
import java.util.ArrayList;
@@ -37,7 +36,7 @@ public class DomainEntityService {
private SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
@Autowired
private DefaultSemanticInternalUtils defaultSemanticUtils;
private ConfigServiceImpl configService;
public EntityInfo getEntityInfo(SemanticParseInfo parseInfo, User user) {
if (parseInfo != null && parseInfo.getDomainId() > 0) {
@@ -77,42 +76,55 @@ public class DomainEntityService {
}
public EntityInfo getEntityInfo(Long domain) {
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(domain);
return getEntityInfo(chaConfigRichDesc.getEntity());
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(domain);
if (Objects.isNull(chaConfigRichDesc) || Objects.isNull(chaConfigRichDesc.getChatDetailRichConfig())) {
return new EntityInfo();
}
return getEntityInfo(chaConfigRichDesc);
}
private EntityInfo getEntityInfo(EntityRichInfo entityDesc) {
EntityInfo entityInfo = new EntityInfo();
private EntityInfo getEntityInfo(ChatConfigRichResp chaConfigRichDesc) {
if (entityDesc != null && Objects.nonNull(entityDesc.getDomainId())) {
EntityInfo entityInfo = new EntityInfo();
EntityRichInfo entityDesc = chaConfigRichDesc.getChatDetailRichConfig().getEntity();
if (entityDesc != null && Objects.nonNull(chaConfigRichDesc.getDomainId())) {
DomainInfo domainInfo = new DomainInfo();
domainInfo.setItemId(Integer.valueOf(entityDesc.getDomainId().intValue()));
domainInfo.setName(entityDesc.getDomainName());
domainInfo.setItemId(Integer.valueOf(chaConfigRichDesc.getDomainId().intValue()));
domainInfo.setName(chaConfigRichDesc.getDomainName());
domainInfo.setWords(entityDesc.getNames());
domainInfo.setBizName(entityDesc.getDomainBizName());
if (entityDesc.getEntityIds().size() > 0) {
domainInfo.setPrimaryEntityBizName(entityDesc.getEntityIds().get(0).getBizName());
domainInfo.setBizName(chaConfigRichDesc.getBizName());
if (Objects.nonNull(entityDesc.getDimItem())) {
domainInfo.setPrimaryEntityBizName(entityDesc.getDimItem().getBizName());
}
entityInfo.setDomainInfo(domainInfo);
List<DataInfo> dimensions = new ArrayList<>();
List<DataInfo> metrics = new ArrayList<>();
if (entityDesc.getEntityInternalDetailDesc() != null) {
for (DimSchemaResp dimensionDesc : entityDesc.getEntityInternalDetailDesc().getDimensionList()) {
DataInfo mainEntityDimension = new DataInfo();
mainEntityDimension.setItemId(dimensionDesc.getId().intValue());
mainEntityDimension.setName(dimensionDesc.getName());
mainEntityDimension.setBizName(dimensionDesc.getBizName());
dimensions.add(mainEntityDimension);
if (Objects.nonNull(chaConfigRichDesc) && Objects.nonNull(chaConfigRichDesc.getChatDetailRichConfig())
&& Objects.nonNull(chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig())) {
ChatDefaultRichConfig chatDefaultConfig = chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig();
if(!CollectionUtils.isEmpty(chatDefaultConfig.getDimensions())){
for (SchemaItem dimensionDesc : chatDefaultConfig.getDimensions()) {
DataInfo mainEntityDimension = new DataInfo();
mainEntityDimension.setItemId(dimensionDesc.getId().intValue());
mainEntityDimension.setName(dimensionDesc.getName());
mainEntityDimension.setBizName(dimensionDesc.getBizName());
dimensions.add(mainEntityDimension);
}
entityInfo.setDimensions(dimensions);
}
entityInfo.setDimensions(dimensions);
for (MetricSchemaResp metricDesc : entityDesc.getEntityInternalDetailDesc().getMetricList()) {
DataInfo dataInfo = new DataInfo();
dataInfo.setName(metricDesc.getName());
dataInfo.setBizName(metricDesc.getBizName());
dataInfo.setItemId(metricDesc.getId().intValue());
metrics.add(dataInfo);
if(!CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())){
for (SchemaItem metricDesc : chatDefaultConfig.getMetrics()) {
DataInfo dataInfo = new DataInfo();
dataInfo.setName(metricDesc.getName());
dataInfo.setBizName(metricDesc.getBizName());
dataInfo.setItemId(metricDesc.getId().intValue());
metrics.add(dataInfo);
}
entityInfo.setMetrics(metrics);
}
entityInfo.setMetrics(metrics);
}
}
return entityInfo;

View File

@@ -14,6 +14,7 @@ import com.tencent.supersonic.chat.domain.service.QueryService;
import com.tencent.supersonic.chat.domain.service.ChatService;
import com.tencent.supersonic.chat.domain.utils.ComponentFactory;
import com.tencent.supersonic.chat.domain.utils.SchemaInfoConverter;
import com.tencent.supersonic.common.util.json.JsonUtil;
import com.tencent.supersonic.semantic.api.core.response.QueryResultWithSchemaResp;
import java.util.List;
import java.util.stream.Collectors;
@@ -50,7 +51,6 @@ public class QueryServiceImpl implements QueryService {
log.info("semanticParser processing:[{}]", semanticParser.getClass().getName());
semanticParser.parse(queryCtx, chatCtx);
}
if (queryCtx.getCandidateQueries().size() > 0) {
log.info("pick before [{}]", queryCtx.getCandidateQueries().stream().collect(
Collectors.toList()));

View File

@@ -29,7 +29,7 @@ public class RecommendServiceImpl implements RecommendService {
}
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(
Long.valueOf(domainId));
Long.valueOf(domainId), true);
List<RecommendResponse.Item> dimensions = domainSchemaDesc.getDimensions().stream().map(dimSchemaDesc -> {
RecommendResponse.Item item = new RecommendResponse.Item();

View File

@@ -2,6 +2,8 @@ package com.tencent.supersonic.chat.application;
import com.google.common.collect.Lists;
import com.hankcs.hanlp.seg.common.Term;
import com.tencent.supersonic.chat.api.pojo.Filter;
import com.tencent.supersonic.chat.api.pojo.QueryFilter;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.request.QueryContextReq;
import com.tencent.supersonic.chat.application.knowledge.NatureHelper;
@@ -64,8 +66,7 @@ public class SearchServiceImpl implements SearchService {
List<ItemDO> metricsDb = domainInfosDb.getMetrics();
final Map<Integer, String> domainToName = domainInfosDb.getDomainToName();
// 2.detect by segment
List<Term> originals = HanlpHelper.getSegment().seg(queryText.toLowerCase()).stream()
.collect(Collectors.toList());
List<Term> originals = HanlpHelper.getTerms(queryText);
Map<MatchText, List<MapResult>> regTextMap = searchMatchStrategy.match(queryText, originals,
queryCtx.getDomainId());
regTextMap.entrySet().stream().forEach(m -> HanlpHelper.transLetterOriginal(m.getValue()));
@@ -101,7 +102,7 @@ public class SearchServiceImpl implements SearchService {
for (Map.Entry<String, String> natureToNameEntry : natureToNameMap.entrySet()) {
searchDimensionValue(metricsDb, domainToName, domainStat.getMetricDomainCount(), searchResults,
existMetricAndDimension, matchText, natureToNameMap, natureToNameEntry);
existMetricAndDimension, matchText, natureToNameMap, natureToNameEntry, queryCtx.getQueryFilter());
}
return searchResults.stream().limit(RESULT_SIZE).collect(Collectors.toList());
}
@@ -140,13 +141,14 @@ public class SearchServiceImpl implements SearchService {
}
private void searchDimensionValue(List<ItemDO> metricsDb,
Map<Integer, String> domainToName,
long metricDomainCount,
Set<SearchResult> searchResults,
boolean existMetricAndDimension,
MatchText matchText,
Map<String, String> natureToNameMap,
Map.Entry<String, String> natureToNameEntry) {
Map<Integer, String> domainToName,
long metricDomainCount,
Set<SearchResult> searchResults,
boolean existMetricAndDimension,
MatchText matchText,
Map<String, String> natureToNameMap,
Map.Entry<String, String> natureToNameEntry,
QueryFilter queryFilter) {
String nature = natureToNameEntry.getKey();
String wordName = natureToNameEntry.getValue();
@@ -158,6 +160,9 @@ public class SearchServiceImpl implements SearchService {
}
// If there are no metric/dimension, complete the metric information
if (metricDomainCount <= 0 && !existMetricAndDimension) {
if (filterByQueryFilter(matchText.getRegText(), queryFilter)) {
return;
}
searchResults.add(
new SearchResult(matchText.getRegText() + wordName, wordName, domainToName.get(domain), domain,
schemaElementType));
@@ -167,7 +172,6 @@ public class SearchServiceImpl implements SearchService {
}
List<String> metrics = filerMetricsByDomain(metricsDb, domain).stream().limit(metricSize).collect(
Collectors.toList());
;
for (String metric : metrics) {
String subRecommend = matchText.getRegText() + wordName + NatureType.SPACE + metric;
searchResults.add(
@@ -181,6 +185,19 @@ public class SearchServiceImpl implements SearchService {
}
}
private boolean filterByQueryFilter(String regText, QueryFilter queryFilter) {
if (queryFilter == null || CollectionUtils.isEmpty(queryFilter.getFilters())) {
return false;
}
List<Filter> filters = queryFilter.getFilters();
for (Filter filter : filters) {
if (regText.equalsIgnoreCase(String.valueOf(filter.getValue()))) {
return false;
}
}
return true;
}
protected List<String> filerMetricsByDomain(List<ItemDO> metricsDb, Integer domain) {
if (CollectionUtils.isEmpty(metricsDb)) {
return Lists.newArrayList();

View File

@@ -31,8 +31,7 @@ public class DatabaseSchemaMapper implements SchemaMapper {
log.debug("before db mapper,mapInfo:{}", queryContext.getMapInfo());
List<Term> terms = HanlpHelper.getSegment().seg(queryContext.getQueryText().toLowerCase()).stream()
.collect(Collectors.toList());
List<Term> terms = HanlpHelper.getTerms(queryContext.getQueryText());
WordNatureService wordNatureService = ContextUtils.getBean(WordNatureService.class);

View File

@@ -30,8 +30,7 @@ public class HanlpSchemaMapper implements SchemaMapper {
@Override
public void map(QueryContextReq queryContext) {
List<Term> terms = HanlpHelper.getSegment().seg(queryContext.getQueryText().toLowerCase()).stream()
.collect(Collectors.toList());
List<Term> terms = HanlpHelper.getTerms(queryContext.getQueryText());
terms.forEach(
item -> log.info("word:{},nature:{},frequency:{}", item.word, item.nature.toString(),
@@ -56,6 +55,8 @@ public class HanlpSchemaMapper implements SchemaMapper {
convertTermsToSchemaMapInfo(matches, queryContext.getMapInfo(), terms);
}
private void convertTermsToSchemaMapInfo(List<MapResult> mapResults, SchemaMapInfo schemaMap, List<Term> terms) {
if (CollectionUtils.isEmpty(mapResults)) {
return;

View File

@@ -4,9 +4,12 @@ import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.api.component.SchemaMapper;
import com.tencent.supersonic.chat.api.pojo.*;
import com.tencent.supersonic.chat.api.request.QueryContextReq;
import com.tencent.supersonic.common.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@@ -25,6 +28,7 @@ public class QueryFilterMapper implements SchemaMapper {
QueryFilter queryFilter = queryContext.getQueryFilter();
SchemaMapInfo schemaMapInfo = queryContext.getMapInfo();
List<SchemaElementMatch> schemaElementMatches = schemaMapInfo.getMatchedElements(domainId);
clearOtherSchemaElementMatch(domainId, schemaMapInfo);
convertFilterToSchemaMapInfo(queryFilter.getFilters(), schemaElementMatches);
}
@@ -33,6 +37,7 @@ public class QueryFilterMapper implements SchemaMapper {
if (CollectionUtils.isEmpty(schemaElementMatches)) {
schemaElementMatches = Lists.newArrayList();
}
List<String> words = schemaElementMatches.stream().map(SchemaElementMatch::getWord).collect(Collectors.toList());
for (Filter filter : filters) {
SchemaElementMatch schemaElementMatch = SchemaElementMatch.builder()
.elementType(SchemaElementType.VALUE)
@@ -40,11 +45,22 @@ public class QueryFilterMapper implements SchemaMapper {
.frequency(FREQUENCY)
.word(String.valueOf(filter.getValue()))
.similarity(SIMILARITY)
.detectWord(filter.getName())
.detectWord(Constants.EMPTY)
.build();
if (words.contains(schemaElementMatch.getWord())) {
continue;
}
schemaElementMatches.add(schemaElementMatch);
}
log.info("schemaElementMatches after queryFilerMapper:{}", schemaElementMatches);
}
private void clearOtherSchemaElementMatch(Integer domainId, SchemaMapInfo schemaMapInfo) {
for (Map.Entry<Integer, List<SchemaElementMatch>> entry : schemaMapInfo.getDomainElementMatches().entrySet()) {
if (!entry.getKey().equals(domainId)) {
entry.getValue().clear();
}
}
}
}

View File

@@ -2,24 +2,28 @@ package com.tencent.supersonic.chat.application.parser;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.api.component.SemanticParser;
import com.tencent.supersonic.chat.api.component.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.*;
import com.tencent.supersonic.chat.api.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.request.QueryContextReq;
import com.tencent.supersonic.chat.application.query.*;
import com.tencent.supersonic.chat.application.query.EntitySemanticQuery;
import com.tencent.supersonic.chat.application.query.MetricSemanticQuery;
import com.tencent.supersonic.chat.application.query.RuleSemanticQuery;
import com.tencent.supersonic.chat.application.query.RuleSemanticQueryManager;
import com.tencent.supersonic.chat.domain.pojo.chat.DomainInfos;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.utils.*;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import com.tencent.supersonic.chat.domain.service.ConfigService;
import com.tencent.supersonic.chat.domain.utils.ComponentFactory;
import com.tencent.supersonic.chat.domain.utils.ContextHelper;
import com.tencent.supersonic.chat.domain.utils.DefaultMetricUtils;
import com.tencent.supersonic.chat.domain.utils.SchemaInfoConverter;
import com.tencent.supersonic.common.util.context.ContextUtils;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
@@ -37,10 +41,15 @@ public class DomainSemanticParser implements SemanticParser {
// iterate all schemaElementMatches to resolve semantic query
for (Integer domainId : mapInfo.getMatchedDomains()) {
List<SchemaElementMatch> elementMatches = mapInfo.getMatchedElements(domainId);
Map<RuleSemanticQuery, List<SchemaElementMatch>> queryMatches = resolveQuery(elementMatches, queryContext);
for (Map.Entry<RuleSemanticQuery, List<SchemaElementMatch>> match : queryMatches.entrySet()) {
List<RuleSemanticQuery> queries = resolveQuery(elementMatches, queryContext);
for (RuleSemanticQuery query : queries) {
if (useBlackItem(query, domainId)) {
log.info("useBlackItem, skip query:{}", query);
continue;
}
addCandidateQuery(queryContext, chatContext, domainId.longValue(),
domainToName.get(domainId), match.getKey(), match.getValue());
domainToName.get(domainId), query);
}
}
@@ -50,27 +59,95 @@ public class DomainSemanticParser implements SemanticParser {
Integer chatDomainId = Integer.valueOf(chatContext.getParseInfo().getDomainId().intValue());
if (mapInfo.getMatchedDomains().contains(chatDomainId)) {
List<SchemaElementMatch> elementMatches = mapInfo.getMatchedElements(chatDomainId);
detectionContext(chatContext);
Map<RuleSemanticQuery, List<SchemaElementMatch>> queryMatches = tryParseByContext(elementMatches,
chatContext, queryContext);
for (Map.Entry<RuleSemanticQuery, List<SchemaElementMatch>> match : queryMatches.entrySet()) {
List<RuleSemanticQuery> queries = tryParseByContext(elementMatches, chatContext, queryContext);
for (RuleSemanticQuery query : queries) {
addCandidateQuery(queryContext, chatContext, chatDomainId.longValue(),
domainToName.get(chatDomainId), match.getKey(), match.getValue());
domainToName.get(chatDomainId), query);
}
}
}
}
}
private boolean useBlackItem(RuleSemanticQuery query, Integer domainId) {
if (Objects.isNull(domainId)) {
return false;
}
ConfigService configService = ContextUtils.getBean(ConfigService.class);
ChatConfigResp chatConfigResp = configService.fetchConfigByDomainId(domainId.longValue());
if (Objects.nonNull(chatConfigResp) && Objects.nonNull(query) && Objects.nonNull(query.getParseInfo())) {
List<SchemaElementMatch> elementMatches = query.getParseInfo().getElementMatches();
if (!CollectionUtils.isEmpty(elementMatches)) {
return useBlackItemInternal(elementMatches, chatConfigResp, query);
}
}
return false;
}
private boolean useBlackItemInternal(List<SchemaElementMatch> elementMatches, ChatConfigResp chatConfigResp, RuleSemanticQuery query) {
if (Objects.isNull(chatConfigResp)) {
return false;
}
List<Long> blackDimIdList = new ArrayList<>();
List<Long> blackMetricIdList = new ArrayList<>();
if (query instanceof EntitySemanticQuery
&& Objects.nonNull(chatConfigResp.getChatDetailConfig())
&& Objects.nonNull(chatConfigResp.getChatDetailConfig().getVisibility())) {
log.info("useBlackItem, handle EntitySemanticQuery blackList logic");
blackDimIdList = chatConfigResp.getChatDetailConfig().getVisibility().getBlackDimIdList();
blackMetricIdList = chatConfigResp.getChatDetailConfig().getVisibility().getBlackMetricIdList();
}
if (query instanceof MetricSemanticQuery
&& Objects.nonNull(chatConfigResp.getChatAggConfig())
&& Objects.nonNull(chatConfigResp.getChatAggConfig().getVisibility())) {
log.info("useBlackItem, handle MetricSemanticQuery blackList logic");
blackDimIdList = chatConfigResp.getChatAggConfig().getVisibility().getBlackDimIdList();
blackMetricIdList = chatConfigResp.getChatAggConfig().getVisibility().getBlackMetricIdList();
}
return useBlackItemWithElementMatches(elementMatches, blackDimIdList, blackMetricIdList);
}
private boolean useBlackItemWithElementMatches(List<SchemaElementMatch> elementMatches, List<Long> blackDimIdList, List<Long> blackMetricIdList) {
Set<Long> dimIds = elementMatches.stream()
.filter(element -> SchemaElementType.VALUE.equals(element.getElementType()) || SchemaElementType.DIMENSION.equals(element.getElementType()))
.map(element -> Long.valueOf(element.getElementID())).collect(Collectors.toSet());
Set<Long> metricIds = elementMatches.stream()
.filter(element -> SchemaElementType.METRIC.equals(element.getElementType()))
.map(element -> Long.valueOf(element.getElementID())).collect(Collectors.toSet());
return useBlackItemWithIds(dimIds, metricIds, blackDimIdList, blackMetricIdList);
}
private boolean useBlackItemWithIds(Set<Long> dimIds, Set<Long> metricIds, List<Long> blackDimIdList, List<Long> blackMetricIdList) {
if (!CollectionUtils.isEmpty(blackDimIdList) && !CollectionUtils.isEmpty(dimIds)) {
if (blackDimIdList.stream().anyMatch(dimIds::contains)) {
log.info("useBlackItem, blackDimIdList:{}", blackDimIdList.stream().filter(dimIds::contains).collect(Collectors.toList()));
return true;
}
}
if (!CollectionUtils.isEmpty(blackMetricIdList) && !CollectionUtils.isEmpty(metricIds)) {
if (blackMetricIdList.stream().anyMatch(metricIds::contains)) {
log.info("useBlackItem, blackMetricIdList:{}", blackMetricIdList.stream().filter(metricIds::contains).collect(Collectors.toList()));
return true;
}
}
return false;
}
private void addCandidateQuery(QueryContextReq queryContext, ChatContext chatContext,
Long domainId, String domainName,
RuleSemanticQuery semanticQuery, List<SchemaElementMatch> elementMatches) {
Long domainId, String domainName, RuleSemanticQuery semanticQuery) {
if (semanticQuery != null) {
fillParseInfo(semanticQuery, domainId, domainName, elementMatches);
// inherit from context
DefaultMetricUtils defaultMetricUtils = ContextUtils.getBean(DefaultMetricUtils.class);
defaultMetricUtils.fillParseInfo(semanticQuery, domainId, domainName);
inheritContext(semanticQuery, chatContext);
// default metric, date, dimension
injectDefaultMetric(semanticQuery, queryContext, chatContext);
defaultMetricUtils.fillDefaultMetric(semanticQuery.getParseInfo(), queryContext, chatContext);
queryContext.getCandidateQueries().add(semanticQuery);
}
}
@@ -84,38 +161,15 @@ public class DomainSemanticParser implements SemanticParser {
}
}
protected void injectDefaultMetric(RuleSemanticQuery semanticQuery, QueryContextReq queryContext,
ChatContext chatContext) {
DefaultMetricUtils defaultMetricUtils = ContextUtils.getBean(DefaultMetricUtils.class);
defaultMetricUtils.injectDefaultMetric(semanticQuery.getParseInfo(), queryContext, chatContext);
}
/**
* get the chatContext for the tryParseByContext
*
* @param chatContext
*/
protected void detectionContext(ChatContext chatContext) {
if (chatContext.getParseInfo() != null) {
SemanticParseInfo semanticParseInfo = chatContext.getParseInfo();
if (semanticParseInfo.getQueryMode().equals(EntityDetail.QUERY_MODE)) {
// EntityDetail model will unset some items
semanticParseInfo.setDateInfo(null);
semanticParseInfo.setMetrics(new HashSet<>());
semanticParseInfo.setDimensions(new HashSet<>());
}
}
}
/**
* try to add ChatContext to SchemaElementMatch and look if match QueryMode
* try to add ChatContext to SchemaMatch and look if match QueryMode
*
* @param elementMatches
* @param chatCtx
* @return
*/
private Map<RuleSemanticQuery, List<SchemaElementMatch>> tryParseByContext(List<SchemaElementMatch> elementMatches,
ChatContext chatCtx, QueryContextReq queryCtx) {
private List<RuleSemanticQuery> tryParseByContext(List<SchemaElementMatch> elementMatches,
ChatContext chatCtx, QueryContextReq queryCtx) {
if (chatCtx.getParseInfo() != null && chatCtx.getParseInfo().getEntity() > 0) {
Long entityCount = elementMatches.stream().filter(i -> SchemaElementType.ENTITY.equals(i.getElementType()))
.count();
@@ -125,15 +179,14 @@ public class DomainSemanticParser implements SemanticParser {
// try entity parse
SchemaElementMatch entityElementMatch = SchemaElementMatch.builder()
.elementType(SchemaElementType.ENTITY).build();
List<SchemaElementMatch> newSchemaElementMatch = new ArrayList<>();
List<SchemaElementMatch> newSchemaMatches = new ArrayList<>();
if (!CollectionUtils.isEmpty(elementMatches)) {
newSchemaElementMatch.addAll(elementMatches);
newSchemaMatches.addAll(elementMatches);
}
newSchemaElementMatch.add(entityElementMatch);
Map<RuleSemanticQuery, List<SchemaElementMatch>> queryMatches = doParseByContext(newSchemaElementMatch,
chatCtx, queryCtx);
if (queryMatches.size() > 0) {
return queryMatches;
newSchemaMatches.add(entityElementMatch);
List<RuleSemanticQuery> queries = doParseByContext(newSchemaMatches, chatCtx, queryCtx);
if (queries.size() > 0) {
return queries;
}
}
}
@@ -141,8 +194,8 @@ public class DomainSemanticParser implements SemanticParser {
}
private Map<RuleSemanticQuery, List<SchemaElementMatch>> doParseByContext(List<SchemaElementMatch> elementMatches,
ChatContext chatCtx, QueryContextReq queryCtx) {
private List<RuleSemanticQuery> doParseByContext(List<SchemaElementMatch> elementMatches,
ChatContext chatCtx, QueryContextReq queryContext) {
SemanticParseInfo contextSemanticParse = chatCtx.getParseInfo();
if (contextSemanticParse != null) {
List<SchemaElementMatch> newElementMatches = new ArrayList<>();
@@ -162,123 +215,36 @@ public class DomainSemanticParser implements SemanticParser {
trySchemaElementTypes.add(new ArrayList<>(Arrays.asList(SchemaElementType.VALUE)));
trySchemaElementTypes.add(new ArrayList<>(Arrays.asList(SchemaElementType.DIMENSION)));
for (List<SchemaElementType> schemaElementTypes : trySchemaElementTypes) {
for (List<SchemaElementType> schemaTypes : trySchemaElementTypes) {
newElementMatches.clear();
if (!CollectionUtils.isEmpty(elementMatches)) {
newElementMatches.addAll(elementMatches);
}
ContextHelper.mergeContextSchemaElementMatch(newElementMatches, elementMatches, schemaElementTypes,
ContextHelper.mergeContextSchemaElementMatch(newElementMatches, elementMatches, schemaTypes,
contextSemanticParse);
Map<RuleSemanticQuery, List<SchemaElementMatch>> queryMatches = resolveQuery(newElementMatches,
queryCtx);
if (queryMatches.size() > 0) {
return queryMatches;
List<RuleSemanticQuery> queries = resolveQuery(newElementMatches, queryContext);
if (queries.size() > 0) {
return queries;
}
}
}
return new HashMap<>();
return new ArrayList<>();
}
private Map<RuleSemanticQuery, List<SchemaElementMatch>> resolveQuery(List<SchemaElementMatch> elementMatches,
QueryContextReq queryCtx) {
Map<RuleSemanticQuery, List<SchemaElementMatch>> matchMap = new HashMap<>();
private List<RuleSemanticQuery> resolveQuery(List<SchemaElementMatch> candidateElementMatches,
QueryContextReq queryContext) {
List<RuleSemanticQuery> matchedQueries = new ArrayList<>();
for (RuleSemanticQuery semanticQuery : RuleSemanticQueryManager.getSemanticQueries()) {
List<SchemaElementMatch> matches = semanticQuery.match(elementMatches, queryCtx);
List<SchemaElementMatch> matches = semanticQuery.match(candidateElementMatches, queryContext);
if (matches.size() > 0) {
log.info("resolve match [{}:{}] ", semanticQuery.getQueryMode(), matches.size());
matchMap.put(RuleSemanticQueryManager.create(semanticQuery.getQueryMode()), matches);
RuleSemanticQuery query = RuleSemanticQueryManager.create(semanticQuery.getQueryMode());
query.getParseInfo().getElementMatches().addAll(matches);
matchedQueries.add(query);
}
}
return matchMap;
return matchedQueries;
}
public void fillParseInfo(SemanticQuery query, Long domainId, String domainName,
List<SchemaElementMatch> elementMatches) {
SemanticParseInfo parseInfo = query.getParseInfo();
parseInfo.setDomainId(domainId);
parseInfo.setDomainName(domainName);
parseInfo.setQueryMode(query.getQueryMode());
parseInfo.getElementMatches().addAll(elementMatches);
DefaultSemanticInternalUtils defaultSemanticUtils = ContextUtils.getBean(DefaultSemanticInternalUtils.class);
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(parseInfo.getDomainId());
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(parseInfo.getDomainId());
Map<Long, DimSchemaResp> dimensionDescMap = domainSchemaDesc.getDimensions().stream()
.collect(Collectors.toMap(DimSchemaResp::getId, Function.identity()));
Map<Long, MetricSchemaResp> metricDescMap = domainSchemaDesc.getMetrics().stream()
.collect(Collectors.toMap(MetricSchemaResp::getId, Function.identity()));
Map<Long, List<SchemaElementMatch>> dim2Values = new HashMap<>();
for (SchemaElementMatch schemaElementMatch : elementMatches) {
Long elementID = Long.valueOf(schemaElementMatch.getElementID());
switch (schemaElementMatch.getElementType()) {
case ID:
case VALUE:
if (dimensionDescMap.containsKey(elementID)) {
if (dim2Values.containsKey(elementID)) {
dim2Values.get(elementID).add(schemaElementMatch);
} else {
dim2Values.put(elementID, new ArrayList<>(Arrays.asList(schemaElementMatch)));
}
}
break;
case DIMENSION:
DimSchemaResp dimensionDesc = dimensionDescMap.get(elementID);
if (dimensionDesc != null) {
SchemaItem dimensionParseInfo = new SchemaItem();
dimensionParseInfo.setBizName(dimensionDesc.getBizName());
dimensionParseInfo.setName(dimensionDesc.getName());
dimensionParseInfo.setId(dimensionDesc.getId());
parseInfo.getDimensions().add(dimensionParseInfo);
}
break;
case METRIC:
MetricSchemaResp metricDesc = metricDescMap.get(elementID);
if (metricDesc != null) {
SchemaItem metricItem = new SchemaItem();
metricItem.setBizName(metricDesc.getBizName());
metricItem.setName(metricDesc.getName());
metricItem.setId(metricDesc.getId());
metricItem.setCreatedAt(null);
metricItem.setUpdatedAt(null);
parseInfo.getMetrics().add(metricItem);
}
break;
default:
}
}
if (!dim2Values.isEmpty()) {
for (Map.Entry<Long, List<SchemaElementMatch>> entry : dim2Values.entrySet()) {
DimSchemaResp dimensionDesc = dimensionDescMap.get(entry.getKey());
if (entry.getValue().size() == 1) {
SchemaElementMatch schemaElementMatch = entry.getValue().get(0);
Filter dimensionFilter = new Filter();
dimensionFilter.setValue(schemaElementMatch.getWord());
dimensionFilter.setBizName(dimensionDesc.getBizName());
dimensionFilter.setName(dimensionDesc.getName());
dimensionFilter.setOperator(FilterOperatorEnum.EQUALS);
dimensionFilter.setElementID(Long.valueOf(schemaElementMatch.getElementID()));
parseInfo.getDimensionFilters().add(dimensionFilter);
ContextHelper.setEntityId(entry.getKey(), schemaElementMatch.getWord(), chaConfigRichDesc,
parseInfo);
} else {
Filter dimensionFilter = new Filter();
List<String> vals = new ArrayList<>();
entry.getValue().stream().forEach(i -> vals.add(i.getWord()));
dimensionFilter.setValue(vals);
dimensionFilter.setBizName(dimensionDesc.getBizName());
dimensionFilter.setName(dimensionDesc.getName());
dimensionFilter.setOperator(FilterOperatorEnum.IN);
dimensionFilter.setElementID(entry.getKey());
parseInfo.getDimensionFilters().add(dimensionFilter);
}
}
}
}
}
}

View File

@@ -20,6 +20,7 @@ import com.tencent.supersonic.chat.domain.utils.SemanticSatisfactionChecker;
import com.tencent.supersonic.common.nlp.ItemDO;
import com.tencent.supersonic.common.util.context.ContextUtils;
import com.tencent.supersonic.common.util.json.JsonUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,6 +29,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.http.HttpEntity;
@@ -40,90 +42,100 @@ import org.springframework.web.client.RestTemplate;
@Slf4j
public class LLMSemanticParser implements SemanticParser {
private DslToSemanticInfo dslToSemanticInfo = new DslToSemanticInfo();
@Override
public void parse(QueryContextReq queryContext, ChatContext chatCtx) {
String queryText = queryContext.getQueryText();
if (SemanticSatisfactionChecker.check(queryContext)) {
log.info("There is no need parse by llm , queryText:{}", queryContext.getQueryText());
log.info("There is no need parse by llm , queryText:{}", queryText);
return;
}
Integer domainId = getDomainId(queryContext, chatCtx);
LLMResp llmResp = requestLLM(queryContext, domainId);
if (Objects.isNull(llmResp)) {
try {
Integer domainId = getDomainId(queryContext, chatCtx);
LLMResp llmResp = requestLLM(queryContext, domainId);
if (Objects.isNull(llmResp)) {
return;
}
LLMSemanticQuery semanticQuery = new LLMSemanticQuery();
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
String sql = convertToSql(llmResp, parseInfo, domainId);
parseInfo.setInfo(sql);
parseInfo.setDomainId(Long.valueOf(domainId));
parseInfo.setBonus(queryText.length() * 1.0);
parseInfo.setQueryMode(LLMSemanticQuery.QUERY_MODE);
queryContext.getCandidateQueries().add(semanticQuery);
return;
} catch (Exception e) {
log.error("llm parse error , skip the parser. error:", e);
}
LLMSemanticQuery semanticQuery = new LLMSemanticQuery();
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
String sql = convertToSql(llmResp, parseInfo);
parseInfo.setDomainId(Long.valueOf(domainId));
parseInfo.setBonus(queryContext.getQueryText().length() * 1.0);
parseInfo.setQueryMode(LLMSemanticQuery.QUERY_MODE);
parseInfo.setInfo(sql);
queryContext.getCandidateQueries().add(semanticQuery);
return;
}
protected String convertToSql(LLMResp llmResp, SemanticParseInfo parseInfo) {
return DslToSemanticInfo.convert(parseInfo, llmResp);
protected String convertToSql(LLMResp llmResp, SemanticParseInfo parseInfo, Integer domainId)
throws SqlParseException {
return dslToSemanticInfo.convert(parseInfo, llmResp, domainId);
}
protected LLMResp requestLLM(QueryContextReq queryContext, Integer domainId) {
try {
final LLMConfig llmConfig = ContextUtils.getBean(LLMConfig.class);
final LLMConfig llmConfig = ContextUtils.getBean(LLMConfig.class);
DomainInfos domainInfos = ContextUtils.getBean(WordNatureService.class).getCache().getUnchecked("");
Map<Integer, String> domainIdToName = domainInfos.getDomains().stream()
.collect(Collectors.toMap(ItemDO::getDomain, a -> a.getName(), (k1, k2) -> k1));
Map<Integer, String> itemIdToName = domainInfos.getDimensions().stream()
.filter(entry -> domainId.equals(entry.getDomain()))
.collect(Collectors.toMap(ItemDO::getItemId, ItemDO::getName, (value1, value2) -> value2));
String domainName = domainIdToName.get(domainId);
LLMReq llmReq = new LLMReq();
llmReq.setQueryText(queryContext.getQueryText());
List<SchemaElementMatch> matchedElements = queryContext.getMapInfo().getMatchedElements(domainId);
List<String> fieldNameList = matchedElements.stream()
.filter(schemaElementMatch ->
SchemaElementType.METRIC.equals(schemaElementMatch.getElementType()) ||
SchemaElementType.DIMENSION.equals(schemaElementMatch.getElementType()) ||
SchemaElementType.VALUE.equals(schemaElementMatch.getElementType()))
.map(schemaElementMatch -> {
if (!SchemaElementType.VALUE.equals(schemaElementMatch.getElementType())) {
return schemaElementMatch.getWord();
}
return itemIdToName.get(schemaElementMatch.getElementID());
})
.filter(name -> StringUtils.isNotEmpty(name) && !name.contains("%"))
.collect(Collectors.toList());
LLMSchema llmSchema = new LLMSchema();
llmSchema.setDomainName(domainName);
llmSchema.setFieldNameList(fieldNameList);
llmReq.setSchema(llmSchema);
log.info("domainId:{},llmReq:{}", domainId, llmReq);
String questUrl = llmConfig.getUrl() + llmConfig.getQueryToSqlPath();
RestTemplate restTemplate = ContextUtils.getBean(RestTemplate.class);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(llmReq), headers);
log.info("requestLLM request:{},entity:{}", questUrl, entity);
ResponseEntity<LLMResp> responseEntity = restTemplate.exchange(questUrl, HttpMethod.POST, entity,
LLMResp.class);
log.info("requestLLM result:{}", responseEntity);
return responseEntity.getBody();
} catch (Exception e) {
log.error("requestLLM error", e);
if (StringUtils.isEmpty(llmConfig.getUrl())) {
log.warn("llmConfig url is null, skip llm parser");
return null;
}
return null;
DomainInfos domainInfos = ContextUtils.getBean(WordNatureService.class).getCache().getUnchecked("");
Map<Integer, String> domainIdToName = domainInfos.getDomains().stream()
.collect(Collectors.toMap(ItemDO::getDomain, a -> a.getName(), (k1, k2) -> k1));
Map<Integer, String> itemIdToName = domainInfos.getDimensions().stream()
.filter(entry -> domainId.equals(entry.getDomain()))
.collect(Collectors.toMap(ItemDO::getItemId, ItemDO::getName, (value1, value2) -> value2));
String domainName = domainIdToName.get(domainId);
LLMReq llmReq = new LLMReq();
llmReq.setQueryText(queryContext.getQueryText());
List<SchemaElementMatch> matchedElements = queryContext.getMapInfo().getMatchedElements(domainId);
Set<String> fieldNameList = matchedElements.stream()
.filter(schemaElementMatch ->
SchemaElementType.METRIC.equals(schemaElementMatch.getElementType()) ||
SchemaElementType.DIMENSION.equals(schemaElementMatch.getElementType()) ||
SchemaElementType.VALUE.equals(schemaElementMatch.getElementType()))
.map(schemaElementMatch -> {
if (!SchemaElementType.VALUE.equals(schemaElementMatch.getElementType())) {
return schemaElementMatch.getWord();
}
return itemIdToName.get(schemaElementMatch.getElementID());
})
.filter(name -> StringUtils.isNotEmpty(name) && !name.contains("%"))
.collect(Collectors.toSet());
LLMSchema llmSchema = new LLMSchema();
llmSchema.setDomainName(domainName);
llmSchema.setFieldNameList(new ArrayList<>(fieldNameList));
llmReq.setSchema(llmSchema);
log.info("requestLLM request, domainId:{},llmReq:{}", domainId, llmReq);
String questUrl = llmConfig.getUrl() + llmConfig.getQueryToSqlPath();
RestTemplate restTemplate = ContextUtils.getBean(RestTemplate.class);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(llmReq), headers);
ResponseEntity<LLMResp> responseEntity = restTemplate.exchange(questUrl, HttpMethod.POST, entity,
LLMResp.class);
log.info("requestLLM response, questUrl:{} \n entity:{} \n body:{}", questUrl, entity,
responseEntity.getBody());
return responseEntity.getBody();
}
protected Integer getDomainId(QueryContextReq queryContext, ChatContext chatCtx) {

View File

@@ -66,19 +66,18 @@ public class TimeSemanticParser implements SemanticParser {
DateConf info = new DateConf();
String zhPeriod = m.group("zhPeriod");
int days;
info.setPeriod(Constants.DAY);
switch (zhPeriod) {
case "":
days = 7;
//info.setPeriod(Constants.WEEK);
info.setPeriod(Constants.WEEK);
break;
case "":
days = 30;
//info.setPeriod(Constants.MONTH);
info.setPeriod(Constants.MONTH);
break;
case "":
days = 365;
//info.setPeriod(Constants.YEAR);
info.setPeriod(Constants.YEAR);
break;
default:
days = 1;
@@ -92,7 +91,7 @@ public class TimeSemanticParser implements SemanticParser {
}
info.setText(text);
info.setStartDate(LocalDate.now().minusDays(days).toString());
info.setUnit(days);
info.setUnit(num);
//queryContext.getParseInfo().setDateInfo(info);
for (SemanticQuery query : queryContext.getCandidateQueries()) {
if (query instanceof MetricSemanticQuery) {

View File

@@ -1,31 +1,33 @@
package com.tencent.supersonic.chat.application.query;
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.VALUE;
import static com.tencent.supersonic.chat.application.query.QueryMatchOption.RequireNumberType.AT_LEAST;
import static com.tencent.supersonic.chat.domain.pojo.chat.SchemaElementOption.REQUIRED;
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.*;
import static com.tencent.supersonic.chat.application.query.QueryMatchOption.RequireNumberType.*;
import static com.tencent.supersonic.chat.domain.pojo.chat.SchemaElementOption.*;
import static com.tencent.supersonic.common.constant.Constants.DAY;
import com.tencent.supersonic.chat.api.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatDefaultRichConfig;
import com.tencent.supersonic.chat.domain.pojo.config.EntityRichInfo;
import com.tencent.supersonic.chat.domain.service.ConfigService;
import com.tencent.supersonic.chat.domain.utils.ContextHelper;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import com.tencent.supersonic.common.constant.Constants;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.Order;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.common.util.context.ContextUtils;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Slf4j
@Component
@@ -34,11 +36,14 @@ public class EntityListFilter extends EntitySemanticQuery {
public static String QUERY_MODE = "ENTITY_LIST_FILTER";
private static Long entityListLimit = 200L;
public EntityListFilter() {
super();
queryMatcher.addOption(VALUE, REQUIRED, AT_LEAST, 1);
queryMatcher.addOption(VALUE, REQUIRED, AT_LEAST, 1)
.addOption(ENTITY, REQUIRED, AT_LEAST, 1);
}
@Override
public String getQueryMode() {
return QUERY_MODE;
@@ -67,33 +72,32 @@ public class EntityListFilter extends EntitySemanticQuery {
private void addEntityDetailAndOrderByMetric(SemanticParseInfo semanticParseInfo) {
if (semanticParseInfo.getDomainId() > 0L) {
DefaultSemanticInternalUtils defaultSemanticUtils = ContextUtils.getBean(
DefaultSemanticInternalUtils.class);
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(
ConfigService configService = ContextUtils.getBean(ConfigService.class);
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(
semanticParseInfo.getDomainId());
if (chaConfigRichDesc != null) {
//SemanticParseInfo semanticParseInfo = queryContext.getParseInfo();
if (chaConfigRichDesc != null && chaConfigRichDesc.getChatDetailRichConfig() != null
&& chaConfigRichDesc.getChatDetailRichConfig().getEntity() != null) {
// SemanticParseInfo semanticParseInfo = queryContext.getParseInfo();
// EntityRichInfo entity = chaConfigRichDesc.getChatDetailRichConfig().getEntity();
Set<SchemaItem> dimensions = new LinkedHashSet();
Set<String> primaryDimensions = this.addPrimaryDimension(chaConfigRichDesc.getEntity(), dimensions);
// Set<String> primaryDimensions = this.addPrimaryDimension(entity, dimensions);
Set<SchemaItem> metrics = new LinkedHashSet();
if (chaConfigRichDesc.getEntity() != null
&& chaConfigRichDesc.getEntity().getEntityInternalDetailDesc() != null) {
chaConfigRichDesc.getEntity().getEntityInternalDetailDesc().getMetricList().stream()
.forEach((m) -> metrics.add(this.getMetric(m)));
chaConfigRichDesc.getEntity().getEntityInternalDetailDesc().getDimensionList().stream()
.filter((m) -> !primaryDimensions.contains(m.getBizName()))
.forEach((m) -> dimensions.add(this.getDimension(m)));
Set<Order> orders = new LinkedHashSet();
ChatDefaultRichConfig chatDefaultConfig = chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig();
if (chatDefaultConfig != null) {
chatDefaultConfig.getMetrics().stream()
.forEach(metric -> {
metrics.add(metric);
orders.add(new Order(metric.getBizName(), Constants.DESC_UPPER));
});
chatDefaultConfig.getDimensions().stream()
// .filter((m) -> !primaryDimensions.contains(m.getBizName()))
.forEach(dimension -> dimensions.add(dimension));
}
semanticParseInfo.setDimensions(dimensions);
semanticParseInfo.setMetrics(metrics);
Set<Order> orders = new LinkedHashSet();
if (chaConfigRichDesc.getEntity() != null
&& chaConfigRichDesc.getEntity().getEntityInternalDetailDesc() != null) {
chaConfigRichDesc.getEntity().getEntityInternalDetailDesc().getMetricList().stream()
.forEach((metric) -> orders.add(new Order(metric.getBizName(), Constants.DESC_UPPER)));
}
semanticParseInfo.setOrders(orders);
}
}
@@ -102,35 +106,18 @@ public class EntityListFilter extends EntitySemanticQuery {
private Set<String> addPrimaryDimension(EntityRichInfo entity, Set<SchemaItem> dimensions) {
Set<String> primaryDimensions = new HashSet();
if (!Objects.isNull(entity) && !CollectionUtils.isEmpty(entity.getEntityIds())) {
entity.getEntityIds().stream().forEach((dimSchemaDesc) -> {
SchemaItem dimension = new SchemaItem();
BeanUtils.copyProperties(dimSchemaDesc, dimension);
dimensions.add(dimension);
primaryDimensions.add(dimSchemaDesc.getBizName());
});
DimSchemaResp dimItem = entity.getDimItem();
if (Objects.nonNull(entity) && Objects.nonNull(dimItem)) {
SchemaItem dimension = new SchemaItem();
BeanUtils.copyProperties(dimItem, dimension);
dimensions.add(dimension);
primaryDimensions.add(dimItem.getBizName());
return primaryDimensions;
} else {
return primaryDimensions;
}
}
private SchemaItem getMetric(MetricSchemaResp metricSchemaDesc) {
SchemaItem queryMeta = new SchemaItem();
queryMeta.setId(metricSchemaDesc.getId());
queryMeta.setBizName(metricSchemaDesc.getBizName());
queryMeta.setName(metricSchemaDesc.getName());
return queryMeta;
}
private SchemaItem getDimension(DimSchemaResp dimSchemaDesc) {
SchemaItem queryMeta = new SchemaItem();
queryMeta.setId(dimSchemaDesc.getId());
queryMeta.setBizName(dimSchemaDesc.getBizName());
queryMeta.setName(dimSchemaDesc.getName());
return queryMeta;
}
private void dealNativeQuery(SemanticParseInfo semanticParseInfo, boolean isNativeQuery) {
if (Objects.nonNull(semanticParseInfo)) {
semanticParseInfo.setNativeQuery(isNativeQuery);

View File

@@ -1,6 +1,6 @@
package com.tencent.supersonic.chat.application.query;
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.METRIC;
import static com.tencent.supersonic.chat.api.pojo.SchemaElementType.*;
import static com.tencent.supersonic.chat.application.query.QueryMatchOption.RequireNumberType.AT_LEAST;
import static com.tencent.supersonic.chat.domain.pojo.chat.SchemaElementOption.REQUIRED;

View File

@@ -16,6 +16,7 @@ import com.tencent.supersonic.chat.domain.utils.ContextHelper;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -95,7 +96,7 @@ public class MetricCompare extends MetricSemanticQuery {
if (toAdd.isPresent()) {
if (FilterOperatorEnum.EQUALS.equals(toAdd.get().getOperator()) || FilterOperatorEnum.IN.equals(
toAdd.get().getOperator())) {
List<Object> vals = new ArrayList<>();
Set<Object> vals = new HashSet<>();
if (toAdd.get().getOperator().equals(FilterOperatorEnum.IN)) {
vals.addAll((List<Object>) (toAdd.get().getValue()));
} else {
@@ -106,7 +107,7 @@ public class MetricCompare extends MetricSemanticQuery {
} else {
vals.add(filter.getValue());
}
toAdd.get().setValue(vals);
toAdd.get().setValue(new ArrayList<>(vals));
toAdd.get().setOperator(FilterOperatorEnum.IN);
continue;
}

View File

@@ -2,7 +2,6 @@ package com.tencent.supersonic.chat.application.query;
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.domain.pojo.chat.SchemaElementOption;
import com.tencent.supersonic.common.enums.AggregateTypeEnum;
@@ -12,10 +11,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import lombok.Data;
import lombok.ToString;

View File

@@ -1,3 +1,4 @@
package com.tencent.supersonic.chat.application.query;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
@@ -24,7 +25,6 @@ import java.util.*;
public abstract class RuleSemanticQuery implements SemanticQuery, Serializable {
protected SemanticParseInfo parseInfo = new SemanticParseInfo();
protected List<SchemaElementMatch> schemaElementMatches = new ArrayList<>();
protected QueryMatcher queryMatcher = new QueryMatcher();
protected SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
@@ -32,7 +32,8 @@ public abstract class RuleSemanticQuery implements SemanticQuery, Serializable {
RuleSemanticQueryManager.register(this);
}
public List<SchemaElementMatch> match(List<SchemaElementMatch> candidateElementMatches, QueryContextReq queryCtx) {
public List<SchemaElementMatch> match(List<SchemaElementMatch> candidateElementMatches,
QueryContextReq queryCtx) {
return queryMatcher.match(candidateElementMatches);
}
@@ -57,6 +58,7 @@ public abstract class RuleSemanticQuery implements SemanticQuery, Serializable {
QueryResultWithSchemaResp queryResult = semanticLayer.queryByStruct(
SchemaInfoConverter.convertTo(parseInfo), user);
if (queryResult != null) {
queryResponse.setQueryAuthorization(queryResult.getQueryAuthorization());
}
@@ -84,4 +86,4 @@ public abstract class RuleSemanticQuery implements SemanticQuery, Serializable {
public void setParseInfo(SemanticParseInfo parseInfo) {
this.parseInfo = parseInfo;
}
}
}

View File

@@ -16,8 +16,4 @@ public class LLMConfig {
@Value("${query2sql.path:query2sql}")
private String queryToSqlPath;
@Value("${query2sql.endpoint:}")
private String endpoint;
}

View File

@@ -15,29 +15,11 @@ public class ChatConfigDO {
private Long id;
private Long domainId;
/**
* default metrics information about the domain
*/
private String defaultMetrics;
/**
* invisible dimensions/metrics
*/
private String visibility;
private String chatDetailConfig;
/**
* the entity info about the domain
*/
private String entity;
private String chatAggConfig;
/**
* information about dictionary about the domain
*/
private String knowledgeInfo;
/**
* available status
*/
private Integer status;
/**

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import lombok.Data;
import java.util.List;
@Data
public class ChatAggConfig {
/**
* invisible dimensions/metrics
*/
private ItemVisibility visibility;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
private KnowledgeAdvancedConfig globalKnowledgeConfig;
private ChatDefaultConfig chatDefaultConfig;
}

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import lombok.Data;
import java.util.List;
@Data
public class ChatAggRichConfig {
/**
* invisible dimensions/metrics
*/
private ItemVisibilityInfo visibility;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
private KnowledgeAdvancedConfig globalKnowledgeConfig;
private ChatDefaultRichConfig chatDefaultConfig;
}

View File

@@ -16,25 +16,16 @@ public class ChatConfig {
private Long id;
private Long domainId;
/**
* default metrics information about the domain
*/
private List<DefaultMetricInfo> defaultMetrics;
/**
* invisible dimensions/metrics
* the chatDetailConfig about the domain
*/
private ItemVisibility visibility;
private ChatDetailConfig chatDetailConfig;
/**
* the entity info about the domain
* the chatAggConfig about the domain
*/
private Entity entity;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
private ChatAggConfig chatAggConfig;
/**
* available status

View File

@@ -0,0 +1,34 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.List;
import lombok.Data;
import lombok.ToString;
/**
* extended information command about domain
*/
@Data
@ToString
public class ChatConfigBaseReq {
private Long domainId;
/**
* the chatDetailConfig about the domain
*/
private ChatDetailConfig chatDetailConfig;
/**
* the chatAggConfig about the domain
*/
private ChatAggConfig chatAggConfig;
/**
* available status
*/
private StatusEnum status;
}

View File

@@ -4,7 +4,7 @@ import lombok.Data;
@Data
public class ChatConfigEditReq extends ChatConfigBase {
public class ChatConfigEditReqReq extends ChatConfigBaseReq {
private Long id;
}

View File

@@ -1,44 +0,0 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
public class ChatConfigInfo {
private Long id;
private Long domainId;
/**
* default metrics information about the domain
*/
private List<DefaultMetricInfo> defaultMetrics;
/**
* invisible dimensions/metrics
*/
private ItemVisibility visibility;
/**
* the entity info about the domain
*/
private Entity entity;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
/**
* available status
*/
private StatusEnum statusEnum;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.Date;
import lombok.Data;
@Data
public class ChatConfigResp {
private Long id;
private Long domainId;
private ChatDetailConfig chatDetailConfig;
private ChatAggConfig chatAggConfig;
/**
* available status
*/
private StatusEnum statusEnum;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -1,47 +0,0 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
public class ChatConfigRichInfo {
private Long id;
private Long domainId;
private String name;
private String bizName;
/**
* default metrics information about the domain
*/
private List<DefaultMetric> defaultMetrics;
/**
* invisible dimensions/metrics
*/
private ItemVisibilityInfo visibility;
/**
* the entity info about the domain
*/
private EntityRichInfo entity;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
/**
* available status
*/
private StatusEnum statusEnum;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,31 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
public class ChatConfigRichResp {
private Long id;
private Long domainId;
private String domainName;
private String bizName;
private ChatAggRichConfig chatAggRichConfig;
private ChatDetailRichConfig chatDetailRichConfig;
/**
* available status
*/
private StatusEnum statusEnum;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.constant.Constants;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class ChatDefaultConfig {
private List<Long> dimensionIds = new ArrayList<>();
private List<Long> metricIds = new ArrayList<>();
/**
* default time span unit
*/
private Integer unit = 1;
/**
* default time type: day
* DAY, WEEK, MONTH, YEAR
*/
private String period = Constants.DAY;
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.constant.Constants;
import com.tencent.supersonic.common.pojo.SchemaItem;
import lombok.Data;
import java.util.List;
@Data
public class ChatDefaultRichConfig {
private List<SchemaItem> dimensions;
private List<SchemaItem> metrics;
/**
* default time span unit
*/
private Integer unit = 1;
/**
* default time type: day
* DAY, WEEK, MONTH, YEAR
*/
private String period = Constants.DAY;
}

View File

@@ -1,41 +1,29 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import com.tencent.supersonic.common.enums.StatusEnum;
import java.util.List;
import lombok.Data;
import lombok.ToString;
/**
* extended information command about domain
*/
import java.util.List;
@Data
@ToString
public class ChatConfigBase {
private Long domainId;
/**
* default metrics information about the domain
*/
private List<DefaultMetricInfo> defaultMetrics;
public class ChatDetailConfig {
/**
* invisible dimensions/metrics
*/
private ItemVisibility visibility;
/**
* the entity info about the domain
*/
private Entity entity;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
private KnowledgeAdvancedConfig globalKnowledgeConfig;
private ChatDefaultConfig chatDefaultConfig;
/**
* available status
* the entity info about the domain
*/
private StatusEnum status;
private Entity entity;
}

View File

@@ -0,0 +1,30 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import lombok.Data;
import java.util.List;
@Data
public class ChatDetailRichConfig {
/**
* invisible dimensions/metrics
*/
private ItemVisibilityInfo visibility;
/**
* the entity info about the domain
*/
private EntityRichInfo entity;
/**
* information about dictionary about the domain
*/
private List<KnowledgeInfo> knowledgeInfos;
private KnowledgeAdvancedConfig globalKnowledgeConfig;
private ChatDefaultRichConfig chatDefaultConfig;
}

View File

@@ -3,11 +3,13 @@ package com.tencent.supersonic.chat.domain.pojo.config;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@ToString
@NoArgsConstructor
public class Dim4Dict {
private Long dimId;

View File

@@ -18,16 +18,12 @@ public class Entity {
/**
* uniquely identifies an entity
*/
private List<Long> entityIds;
private Long entityId;
/**
* entity name list
*/
private List<String> names;
/**
* query entity default information
*/
private EntityDetailData detailData;
}

View File

@@ -7,14 +7,14 @@ import lombok.Data;
@Data
public class EntityRichInfo {
private Long domainId;
private String domainName;
private String domainBizName;
// private Long domainId;
// private String domainName;
// private String domainBizName;
/**
* entity alias
*/
private List<String> names;
private List<DimSchemaResp> entityIds;
private EntityInternalDetail entityInternalDetailDesc;
private DimSchemaResp dimItem;
}

View File

@@ -1,5 +1,6 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.ToString;
@@ -12,10 +13,10 @@ public class ItemVisibility {
/**
* invisible dimensions
*/
private List<Long> blackDimIdList;
private List<Long> blackDimIdList = new ArrayList<>();
/**
* invisible metrics
*/
private List<Long> blackMetricIdList;
private List<Long> blackMetricIdList = new ArrayList<>();
}

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.chat.domain.pojo.config;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* advanced knowledge config
*/
@Data
public class KnowledgeAdvancedConfig {
private List<String> blackList = new ArrayList<>();
private List<String> whiteList = new ArrayList<>();
private List<String> ruleList = new ArrayList<>();
}

View File

@@ -27,9 +27,12 @@ public class KnowledgeInfo {
@NotNull
private TypeEnums type = TypeEnums.DIMENSION;
private List<String> blackList;
private List<String> whiteList;
private List<String> ruleList;
private Boolean isDictInfo;
private Boolean searchEnable = false;
/**
* advanced knowledge config for single item
*/
private KnowledgeAdvancedConfig knowledgeAdvancedConfig;
}

View File

@@ -3,7 +3,7 @@ package com.tencent.supersonic.chat.domain.repository;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilter;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import java.util.List;
@@ -13,7 +13,7 @@ public interface ChatConfigRepository {
Long updateConfig(ChatConfig chaConfig);
List<ChatConfigInfo> getChatConfig(ChatConfigFilter filter);
List<ChatConfigResp> getChatConfig(ChatConfigFilter filter);
ChatConfigInfo getConfigByDomainId(Long domainId);
ChatConfigResp getConfigByDomainId(Long domainId);
}

View File

@@ -2,22 +2,25 @@ package com.tencent.supersonic.chat.domain.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBase;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBaseReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilter;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import java.util.List;
public interface ConfigService {
Long addConfig(ChatConfigBase extendBaseCmd, User user);
Long addConfig(ChatConfigBaseReq extendBaseCmd, User user);
Long editConfig(ChatConfigEditReq extendEditCmd, User user);
Long editConfig(ChatConfigEditReqReq extendEditCmd, User user);
List<ChatConfigInfo> search(ChatConfigFilter filter, User user);
List<ChatConfigResp> search(ChatConfigFilter filter, User user);
ChatConfigRichInfo getConfigRichInfo(Long domainId);
ChatConfigRichResp getConfigRichInfo(Long domainId);
List<ChatConfigRichInfo> getAllChatRichConfig();
ChatConfigResp fetchConfigByDomainId(Long domainId);
List<ChatConfigRichResp> getAllChatRichConfig();
}

View File

@@ -3,20 +3,11 @@ package com.tencent.supersonic.chat.domain.utils;
import static com.tencent.supersonic.common.constant.Constants.ADMIN_LOWER;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.domain.pojo.config.*;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.chat.domain.dataobject.ChatConfigDO;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBase;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetricInfo;
import com.tencent.supersonic.chat.domain.pojo.config.Entity;
import com.tencent.supersonic.chat.domain.pojo.config.EntityDetailData;
import com.tencent.supersonic.chat.domain.pojo.config.EntityInternalDetail;
import com.tencent.supersonic.chat.domain.pojo.config.ItemVisibility;
import com.tencent.supersonic.chat.domain.pojo.config.KnowledgeInfo;
import com.tencent.supersonic.common.enums.StatusEnum;
import com.tencent.supersonic.common.util.RecordInfo;
import com.tencent.supersonic.common.util.json.JsonUtil;
@@ -39,31 +30,28 @@ import org.springframework.util.CollectionUtils;
@Slf4j
public class ChatConfigUtils {
public ChatConfig newChatConfig(ChatConfigBase extendBaseCmd, User user) {
ChatConfig chaConfig = new ChatConfig();
BeanUtils.copyProperties(extendBaseCmd, chaConfig);
public ChatConfig newChatConfig(ChatConfigBaseReq extendBaseCmd, User user) {
ChatConfig chatConfig = new ChatConfig();
BeanUtils.copyProperties(extendBaseCmd, chatConfig);
RecordInfo recordInfo = new RecordInfo();
String creator = (Objects.isNull(user) || Strings.isEmpty(user.getName())) ? ADMIN_LOWER : user.getName();
recordInfo.createdBy(creator);
chaConfig.setRecordInfo(recordInfo);
chaConfig.setStatus(StatusEnum.ONLINE);
return chaConfig;
chatConfig.setRecordInfo(recordInfo);
chatConfig.setStatus(StatusEnum.ONLINE);
return chatConfig;
}
public ChatConfig editChaConfig(ChatConfigEditReq extendEditCmd, User facadeUser) {
ChatConfig chaConfig = new ChatConfig();
BeanUtils.copyProperties(extendEditCmd, chaConfig);
public ChatConfig editChatConfig(ChatConfigEditReqReq extendEditCmd, User facadeUser) {
ChatConfig chatConfig = new ChatConfig();
BeanUtils.copyProperties(extendEditCmd, chatConfig);
RecordInfo recordInfo = new RecordInfo();
String user = (Objects.isNull(facadeUser) || Strings.isEmpty(facadeUser.getName()))
? ADMIN_LOWER : facadeUser.getName();
recordInfo.updatedBy(user);
chaConfig.setRecordInfo(recordInfo);
return chaConfig;
chatConfig.setRecordInfo(recordInfo);
return chatConfig;
}
@@ -126,45 +114,76 @@ public class ChatConfigUtils {
return new ArrayList<>(metricIdAndDescPair.keySet());
}
public ChatConfigDO chatConfig2DO(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = new ChatConfigDO();
BeanUtils.copyProperties(chaConfig, chaConfigDO);
public ChatConfigDO chatConfig2DO(ChatConfig chatConfig) {
ChatConfigDO chatConfigDO = new ChatConfigDO();
BeanUtils.copyProperties(chatConfig, chatConfigDO);
chaConfigDO.setDefaultMetrics(JsonUtil.toString(chaConfig.getDefaultMetrics()));
chaConfigDO.setVisibility(JsonUtil.toString(chaConfig.getVisibility()));
chaConfigDO.setEntity(JsonUtil.toString(chaConfig.getEntity()));
chaConfigDO.setKnowledgeInfo(JsonUtil.toString(chaConfig.getKnowledgeInfos()));
chatConfigDO.setChatAggConfig(JsonUtil.toString(chatConfig.getChatAggConfig()));
chatConfigDO.setChatDetailConfig(JsonUtil.toString(chatConfig.getChatDetailConfig()));
if (Objects.isNull(chaConfig.getStatus())) {
chaConfigDO.setStatus(null);
if (Objects.isNull(chatConfig.getStatus())) {
chatConfigDO.setStatus(null);
} else {
chaConfigDO.setStatus(chaConfig.getStatus().getCode());
chatConfigDO.setStatus(chatConfig.getStatus().getCode());
}
chaConfigDO.setCreatedBy(chaConfig.getRecordInfo().getCreatedBy());
chaConfigDO.setCreatedAt(chaConfig.getRecordInfo().getCreatedAt());
chaConfigDO.setUpdatedBy(chaConfig.getRecordInfo().getUpdatedBy());
chaConfigDO.setUpdatedAt(chaConfig.getRecordInfo().getUpdatedAt());
chatConfigDO.setCreatedBy(chatConfig.getRecordInfo().getCreatedBy());
chatConfigDO.setCreatedAt(chatConfig.getRecordInfo().getCreatedAt());
chatConfigDO.setUpdatedBy(chatConfig.getRecordInfo().getUpdatedBy());
chatConfigDO.setUpdatedAt(chatConfig.getRecordInfo().getUpdatedAt());
return chaConfigDO;
return chatConfigDO;
}
public ChatConfigInfo chatConfigDO2Descriptor(ChatConfigDO chaConfigDO) {
ChatConfigInfo chaConfigDescriptor = new ChatConfigInfo();
BeanUtils.copyProperties(chaConfigDO, chaConfigDescriptor);
public ChatConfigResp chatConfigDO2Descriptor(Long domainId, ChatConfigDO chatConfigDO) {
ChatConfigResp chatConfigDescriptor = new ChatConfigResp();
chaConfigDescriptor.setDefaultMetrics(
JsonUtil.toList(chaConfigDO.getDefaultMetrics(), DefaultMetricInfo.class));
chaConfigDescriptor.setVisibility(JsonUtil.toObject(chaConfigDO.getVisibility(), ItemVisibility.class));
chaConfigDescriptor.setEntity(JsonUtil.toObject(chaConfigDO.getEntity(), Entity.class));
chaConfigDescriptor.setKnowledgeInfos(JsonUtil.toList(chaConfigDO.getKnowledgeInfo(), KnowledgeInfo.class));
chaConfigDescriptor.setStatusEnum(StatusEnum.of(chaConfigDO.getStatus()));
if (Objects.isNull(chatConfigDO)) {
// deal empty chatConfigDO
return generateEmptyChatConfigResp(domainId);
}
chaConfigDescriptor.setCreatedBy(chaConfigDO.getCreatedBy());
chaConfigDescriptor.setCreatedAt(chaConfigDO.getCreatedAt());
chaConfigDescriptor.setUpdatedBy(chaConfigDO.getUpdatedBy());
chaConfigDescriptor.setUpdatedAt(chaConfigDO.getUpdatedAt());
BeanUtils.copyProperties(chatConfigDO, chatConfigDescriptor);
return chaConfigDescriptor;
chatConfigDescriptor.setChatDetailConfig(JsonUtil.toObject(chatConfigDO.getChatDetailConfig(), ChatDetailConfig.class));
chatConfigDescriptor.setChatAggConfig(JsonUtil.toObject(chatConfigDO.getChatAggConfig(), ChatAggConfig.class));
chatConfigDescriptor.setStatusEnum(StatusEnum.of(chatConfigDO.getStatus()));
chatConfigDescriptor.setCreatedBy(chatConfigDO.getCreatedBy());
chatConfigDescriptor.setCreatedAt(chatConfigDO.getCreatedAt());
chatConfigDescriptor.setUpdatedBy(chatConfigDO.getUpdatedBy());
chatConfigDescriptor.setUpdatedAt(chatConfigDO.getUpdatedAt());
if (Strings.isEmpty(chatConfigDO.getChatAggConfig())) {
chatConfigDescriptor.setChatAggConfig(generateEmptyChatAggConfigResp());
}
if (Strings.isEmpty(chatConfigDO.getChatDetailConfig())) {
chatConfigDescriptor.setChatDetailConfig(generateEmptyChatDetailConfigResp());
}
return chatConfigDescriptor;
}
private ChatConfigResp generateEmptyChatConfigResp(Long domainId) {
ChatConfigResp chatConfigResp = new ChatConfigResp();
chatConfigResp.setDomainId(domainId);
chatConfigResp.setChatDetailConfig(generateEmptyChatDetailConfigResp());
chatConfigResp.setChatAggConfig(generateEmptyChatAggConfigResp());
return chatConfigResp;
}
private ChatDetailConfig generateEmptyChatDetailConfigResp() {
ChatDetailConfig chatDetailConfig = new ChatDetailConfig();
ItemVisibility visibility = new ItemVisibility();
chatDetailConfig.setVisibility(visibility);
return chatDetailConfig;
}
private ChatAggConfig generateEmptyChatAggConfigResp() {
ChatAggConfig chatAggConfig = new ChatAggConfig();
ItemVisibility visibility = new ItemVisibility();
chatAggConfig.setVisibility(visibility);
return chatAggConfig;
}
}

View File

@@ -1,24 +1,24 @@
package com.tencent.supersonic.chat.domain.utils;
import com.tencent.supersonic.chat.api.component.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.Filter;
import com.tencent.supersonic.chat.api.pojo.QueryMatchInfo;
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.component.SemanticQuery;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.common.pojo.SchemaItem;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
public class ContextHelper {
@@ -137,17 +137,18 @@ public class ContextHelper {
return difference;
}
public static void setEntityId(Long dimensionId, String value, ChatConfigRichInfo chaConfigRichDesc,
SemanticParseInfo semanticParseInfo) {
if (chaConfigRichDesc != null && chaConfigRichDesc.getEntity() != null) {
Optional<DimSchemaResp> dimensionDesc = chaConfigRichDesc.getEntity().getEntityIds().stream()
.filter(i -> i.getId().equals(dimensionId)).findFirst();
if (dimensionDesc.isPresent() && StringUtils.isNumeric(value)) {
public static void setEntityId(Long dimensionId, String value, ChatConfigRichResp chaConfigRichDesc,
SemanticParseInfo semanticParseInfo) {
if (chaConfigRichDesc != null && chaConfigRichDesc.getChatDetailRichConfig() != null
&& chaConfigRichDesc.getChatDetailRichConfig().getEntity() != null) {
DimSchemaResp dimSchemaResp = chaConfigRichDesc.getChatDetailRichConfig().getEntity().getDimItem();
if (Objects.nonNull(dimSchemaResp) && StringUtils.isNumeric(value)) {
semanticParseInfo.setEntity(Long.valueOf(value));
}
}
}
public static boolean hasEntityId(ChatContext chatCtx) {
if (chatCtx != null && chatCtx.getParseInfo() != null) {
return chatCtx.getParseInfo().getEntity() > 0;
@@ -198,9 +199,17 @@ public class ContextHelper {
for (Filter chatFilter : contextSemanticParse.getDimensionFilters()) {
if (!isInSchemaElementMatchList(elementMatches, SchemaElementType.VALUE,
chatFilter.getValue().toString())) {
toSchemaElementMatch.add(
getSchemaElementMatchByContext(chatFilter.getElementID().intValue(),
chatFilter.getValue().toString(), SchemaElementType.VALUE));
List<String> values = new ArrayList<>();
if (chatFilter.getOperator().equals(FilterOperatorEnum.IN)) {
values.addAll((List<String>) chatFilter.getValue());
} else {
values.add(chatFilter.getValue().toString());
}
for (String value : values) {
toSchemaElementMatch.add(
getSchemaElementMatchByContext(chatFilter.getElementID().intValue(),
value, SchemaElementType.VALUE));
}
}
}
}
@@ -224,8 +233,7 @@ public class ContextHelper {
return false;
}
Long num = elementMatches.stream()
.filter(element -> element != null && element.getWord() != null && element.getWord()
.equalsIgnoreCase(word) && element.getElementType().equals(schemaElementType)).count();
.filter(element -> element != null && element.getElementType().equals(schemaElementType)).count();
return num > 0;
}
@@ -247,6 +255,7 @@ public class ContextHelper {
.elementID(id)
.elementType(schemaElementType)
.word(word)
.detectWord(word)
.similarity(0.5)
.build();
}

View File

@@ -2,34 +2,33 @@ package com.tencent.supersonic.chat.domain.utils;
import static java.time.LocalDate.now;
import com.tencent.supersonic.chat.api.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.api.component.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.*;
import com.tencent.supersonic.chat.api.request.QueryContextReq;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.application.parser.DomainResolver;
import com.tencent.supersonic.chat.application.query.EntityDetail;
import com.tencent.supersonic.chat.application.query.EntityListFilter;
import com.tencent.supersonic.chat.application.query.EntityListTopN;
import com.tencent.supersonic.chat.application.query.EntityMetricFilter;
import com.tencent.supersonic.chat.application.query.MetricDomain;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetric;
import com.tencent.supersonic.chat.application.query.*;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatDefaultRichConfig;
import com.tencent.supersonic.chat.domain.pojo.config.EntityRichInfo;
import com.tencent.supersonic.common.constant.Constants;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.common.util.context.ContextUtils;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.api.query.enums.FilterOperatorEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -37,64 +36,81 @@ import org.springframework.util.CollectionUtils;
@Component
public class DefaultMetricUtils {
@Autowired
private ConfigServiceImpl configService;
/**
* supplementary default metric date dimension
*/
public void injectDefaultMetric(SemanticParseInfo semanticParseInfo, QueryContextReq queryContext,
ChatContext chatContext) {
public void fillDefaultMetric(SemanticParseInfo semanticParseInfo, QueryContextReq queryContext,
ChatContext chatContext) {
String queryMode = semanticParseInfo.getQueryMode();
ChatConfigRichInfo chaConfigRichDesc = null;
if (StringUtils.isNotEmpty(queryMode)) {
Map<String, RuleSemanticQuery> semanticQuery = RuleSemanticQueryManager.getSemanticQueries().stream().collect(Collectors.toMap(RuleSemanticQuery::getQueryMode, Function.identity()));
RuleSemanticQuery ruleSemanticQuery = semanticQuery.get(queryMode);
if (semanticParseInfo == null) {
return;
}
if (!EntityListFilter.QUERY_MODE.equals(queryMode)) {
boolean isFillThemeDefaultMetricLogic = false;
boolean isAddEntityDetailDimensionMetric = false;
Integer domainId = queryContext.getDomainId().intValue();
List<SchemaElementMatch> matchedElements = queryContext.getMapInfo().getMatchedElements(domainId);
// if (!EntityListFilter.QUERY_MODE.equals(queryMode)) {
boolean isFillAggDefaultMetricLogic = false;
boolean isFillDetailDimensionMetric = false;
Integer domainId = queryContext.getDomainId().intValue();
ChatDefaultRichConfig chatDefaultConfig = null;
Boolean isDetailMode = false;
List<SchemaElementMatch> matchedElements = queryContext.getMapInfo().getMatchedElements(domainId);
ChatConfigRichResp chaConfigRichDesc = getChatConfigRichInfo(semanticParseInfo.getDomainId());
if (Objects.isNull(chaConfigRichDesc)) {
return;
}
if (ruleSemanticQuery instanceof MetricSemanticQuery) {
if (!CollectionUtils.isEmpty(matchedElements)) {
long metricCount = matchedElements.stream()
.filter(schemaElementMatch -> schemaElementMatch.getElementType()
.equals(SchemaElementType.METRIC)).count();
if (metricCount <= 0) {
if (chatContext.getParseInfo() == null
|| chatContext.getParseInfo().getMetrics() == null
|| chatContext.getParseInfo().getMetrics().size() <= 0) {
log.info("fillThemeDefaultMetricLogic");
isFillThemeDefaultMetricLogic = true;
log.info("isFillAggDefaultMetricLogic is true");
isFillAggDefaultMetricLogic = true;
}
}
} else {
log.info("fillThemeDefaultMetricLogic for empty matchedElements ");
isFillThemeDefaultMetricLogic = true;
}
if (EntityDetail.QUERY_MODE.equals(queryMode) || EntityMetricFilter.QUERY_MODE.equals(queryMode)) {
isAddEntityDetailDimensionMetric = true;
dealNativeQuery(semanticParseInfo, queryContext, true);
if (Objects.nonNull(chaConfigRichDesc.getChatAggRichConfig())) {
chatDefaultConfig = chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig();
}
if (isFillThemeDefaultMetricLogic) {
if (chaConfigRichDesc == null) {
chaConfigRichDesc = getChatConfigRichInfo(semanticParseInfo.getDomainId());
}
fillThemeDefaultMetricLogic(semanticParseInfo, chaConfigRichDesc, queryContext);
} else if (ruleSemanticQuery instanceof EntitySemanticQuery) {
log.info("fillThemeDefaultMetricLogic for empty matchedElements ");
isFillDetailDimensionMetric = true;
dealNativeQuery(semanticParseInfo, queryContext, true);
isDetailMode = true;
if (Objects.nonNull(chaConfigRichDesc.getChatDetailRichConfig())) {
chatDefaultConfig = chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig();
}
if (isAddEntityDetailDimensionMetric) {
if (chaConfigRichDesc == null) {
chaConfigRichDesc = getChatConfigRichInfo(semanticParseInfo.getDomainId());
}
addEntityDetailDimensionMetric(semanticParseInfo, chaConfigRichDesc, queryContext, chatContext);
}
fillDateDomain(semanticParseInfo, chatContext, chaConfigRichDesc, queryContext);
}
if (isFillAggDefaultMetricLogic) {
fillDefaultMetricAggLogic(semanticParseInfo, chaConfigRichDesc, queryContext);
}
if (isFillDetailDimensionMetric) {
addEntityDetailDimensionMetric(semanticParseInfo, chaConfigRichDesc, queryContext, chatContext);
}
fillDateDomain(semanticParseInfo, chatContext, chaConfigRichDesc, chatDefaultConfig, isDetailMode);
// }
defaultQueryMode(semanticParseInfo, queryContext, chatContext);
addEntityTopDimension(semanticParseInfo, chaConfigRichDesc);
}
}
public void dealNativeQuery(SemanticParseInfo semanticParseInfo, QueryContextReq queryContext,
boolean isNativeQuery) {
boolean isNativeQuery) {
if (Objects.nonNull(queryContext) && Objects.nonNull(semanticParseInfo)) {
semanticParseInfo.setNativeQuery(isNativeQuery);
}
@@ -102,22 +118,18 @@ public class DefaultMetricUtils {
public Set<String> addPrimaryDimension(EntityRichInfo entity, List<SchemaItem> dimensions) {
Set<String> primaryDimensions = new HashSet<>();
if (Objects.isNull(entity) || CollectionUtils.isEmpty(entity.getEntityIds())) {
if (Objects.isNull(entity) || Objects.isNull(entity.getDimItem())) {
return primaryDimensions;
}
entity.getEntityIds().stream().forEach(dimSchemaDesc -> {
SchemaItem dimension = new SchemaItem();
//BeanUtils.copyProperties(dimSchemaDesc, dimension);
dimension.setName(dimSchemaDesc.getName());
dimension.setBizName(dimSchemaDesc.getBizName());
dimension.setId(dimSchemaDesc.getId());
dimensions.add(dimension);
primaryDimensions.add(dimSchemaDesc.getBizName());
});
DimSchemaResp dimItem = entity.getDimItem();
SchemaItem dimension = new SchemaItem();
BeanUtils.copyProperties(dimItem, dimension);
dimensions.add(dimension);
primaryDimensions.add(dimItem.getBizName());
return primaryDimensions;
}
public void addEntityTopDimension(SemanticParseInfo semanticParseInfo, ChatConfigRichInfo chaConfigRichDesc) {
public void addEntityTopDimension(SemanticParseInfo semanticParseInfo, ChatConfigRichResp chaConfigRichDesc) {
if (!semanticParseInfo.getQueryMode().equals(EntityListTopN.QUERY_MODE) || !semanticParseInfo.getDimensions()
.isEmpty()) {
return;
@@ -127,44 +139,56 @@ public class DefaultMetricUtils {
if (chaConfigRichDesc == null) {
chaConfigRichDesc = getChatConfigRichInfo(domainId);
}
if (chaConfigRichDesc != null && chaConfigRichDesc.getEntity() != null) {
if (chaConfigRichDesc != null && chaConfigRichDesc.getChatDetailRichConfig() != null
&& chaConfigRichDesc.getChatDetailRichConfig().getEntity() != null) {
List<SchemaItem> dimensions = new ArrayList<>();
addPrimaryDimension(chaConfigRichDesc.getEntity(), dimensions);
addPrimaryDimension(chaConfigRichDesc.getChatDetailRichConfig().getEntity(), dimensions);
semanticParseInfo.setDimensions(new HashSet<>(dimensions));
semanticParseInfo.setLimit(1L);
}
}
}
public void addEntityDetailDimensionMetric(SemanticParseInfo semanticParseInfo,
ChatConfigRichInfo chaConfigRichDesc, QueryContextReq queryContext,
ChatContext chatCtx) {
public void addEntityDetailDimensionMetric(SemanticParseInfo semanticParseInfo, ChatConfigRichResp chaConfigRichDesc, QueryContextReq queryContext,
ChatContext chatCtx) {
if (semanticParseInfo.getDomainId() > 0) {
Long domainId = semanticParseInfo.getDomainId();
if (chaConfigRichDesc != null) {
if (chaConfigRichDesc.getEntity() == null
|| chaConfigRichDesc.getEntity().getEntityInternalDetailDesc() == null) {
if (chaConfigRichDesc != null && chaConfigRichDesc.getChatDetailRichConfig() != null) {
if (chaConfigRichDesc.getChatDetailRichConfig().getEntity() == null
|| chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig() == null) {
return;
}
List<SchemaElementMatch> schemaElementMatches = queryContext.getMapInfo()
.getMatchedElements(domainId.intValue());
if (CollectionUtils.isEmpty(schemaElementMatches) || schemaElementMatches.stream()
.filter(s -> SchemaElementType.DIMENSION.equals(s.getElementType())).count() <= 0) {
if (CollectionUtils.isEmpty(schemaElementMatches)
|| schemaElementMatches.stream().filter(s -> SchemaElementType.DIMENSION.equals(s.getElementType())).count() <= 0) {
log.info("addEntityDetailDimensionMetric catch");
Set<SchemaItem> dimensions = new LinkedHashSet();
chaConfigRichDesc.getEntity().getEntityInternalDetailDesc().getDimensionList().stream()
.forEach(m -> dimensions.add(getDimension(m)));
semanticParseInfo.setDimensions(dimensions);
if (CollectionUtils.isEmpty(semanticParseInfo.getDimensions())) {
Set<SchemaItem> dimensions = new LinkedHashSet();
List<SchemaItem> dimensionsConfig = chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig().getDimensions();
if (!CollectionUtils.isEmpty(dimensionsConfig)) {
dimensionsConfig.stream().forEach(m -> dimensions.add(m));
}
semanticParseInfo.setDimensions(dimensions);
}
if (CollectionUtils.isEmpty(semanticParseInfo.getMetrics())) {
Set<SchemaItem> metrics = new LinkedHashSet();
List<SchemaItem> metricsConfig = chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig().getMetrics();
if (!CollectionUtils.isEmpty(metricsConfig)) {
metricsConfig.stream().forEach(m -> metrics.add(m));
}
semanticParseInfo.setMetrics(metrics);
}
}
}
}
}
public void defaultQueryMode(SemanticParseInfo semanticParseInfo, QueryContextReq queryContext,
ChatContext chatCtx) {
ChatContext chatCtx) {
SchemaMapInfo schemaMap = queryContext.getMapInfo();
if (StringUtils.isEmpty(semanticParseInfo.getQueryMode())) {
if (chatCtx.getParseInfo() != null && chatCtx.getParseInfo().getDomainId() > 0) {
@@ -216,9 +240,94 @@ public class DefaultMetricUtils {
}
}
public void fillParseInfo(SemanticQuery query, Long domainId, String domainName) {
SemanticParseInfo parseInfo = query.getParseInfo();
parseInfo.setDomainId(domainId);
parseInfo.setDomainName(domainName);
parseInfo.setQueryMode(query.getQueryMode());
public void fillDateDomain(SemanticParseInfo parseInfo, ChatContext chatCtx, ChatConfigRichInfo chaConfigRichDesc,
QueryContextReq queryContext) {
SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
DomainSchemaResp domainSchemaDesc = semanticLayer.getDomainSchemaInfo(parseInfo.getDomainId(), true);
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(parseInfo.getDomainId());
Map<Long, DimSchemaResp> dimensionDescMap = domainSchemaDesc.getDimensions().stream()
.collect(Collectors.toMap(DimSchemaResp::getId, Function.identity()));
Map<Long, MetricSchemaResp> metricDescMap = domainSchemaDesc.getMetrics().stream()
.collect(Collectors.toMap(MetricSchemaResp::getId, Function.identity()));
Map<Long, List<SchemaElementMatch>> dim2Values = new HashMap<>();
List<SchemaElementMatch> elementMatches = query.getParseInfo().getElementMatches();
for (SchemaElementMatch schemaMatch : elementMatches) {
Long elementID = Long.valueOf(schemaMatch.getElementID());
switch (schemaMatch.getElementType()) {
case ID:
case VALUE:
if (dimensionDescMap.containsKey(elementID)) {
if (dim2Values.containsKey(elementID)) {
dim2Values.get(elementID).add(schemaMatch);
} else {
dim2Values.put(elementID, new ArrayList<>(Arrays.asList(schemaMatch)));
}
}
break;
case DIMENSION:
DimSchemaResp dimensionDesc = dimensionDescMap.get(elementID);
if (dimensionDesc != null) {
SchemaItem dimensionParseInfo = new SchemaItem();
dimensionParseInfo.setBizName(dimensionDesc.getBizName());
dimensionParseInfo.setName(dimensionDesc.getName());
dimensionParseInfo.setId(dimensionDesc.getId());
parseInfo.getDimensions().add(dimensionParseInfo);
}
break;
case METRIC:
MetricSchemaResp metricDesc = metricDescMap.get(elementID);
if (metricDesc != null) {
SchemaItem metricItem = new SchemaItem();
metricItem.setBizName(metricDesc.getBizName());
metricItem.setName(metricDesc.getName());
metricItem.setId(metricDesc.getId());
metricItem.setCreatedAt(null);
metricItem.setUpdatedAt(null);
parseInfo.getMetrics().add(metricItem);
}
break;
default:
}
}
if (!dim2Values.isEmpty()) {
for (Map.Entry<Long, List<SchemaElementMatch>> entry : dim2Values.entrySet()) {
DimSchemaResp dimensionDesc = dimensionDescMap.get(entry.getKey());
if (entry.getValue().size() == 1) {
SchemaElementMatch schemaMatch = entry.getValue().get(0);
Filter dimensionFilter = new Filter();
dimensionFilter.setValue(schemaMatch.getWord());
dimensionFilter.setBizName(dimensionDesc.getBizName());
dimensionFilter.setName(dimensionDesc.getName());
dimensionFilter.setOperator(FilterOperatorEnum.EQUALS);
dimensionFilter.setElementID(Long.valueOf(schemaMatch.getElementID()));
parseInfo.getDimensionFilters().add(dimensionFilter);
ContextHelper.setEntityId(entry.getKey(), schemaMatch.getWord(), chaConfigRichDesc,
parseInfo);
} else {
Filter dimensionFilter = new Filter();
List<String> vals = new ArrayList<>();
entry.getValue().stream().forEach(i -> vals.add(i.getWord()));
dimensionFilter.setValue(vals);
dimensionFilter.setBizName(dimensionDesc.getBizName());
dimensionFilter.setName(dimensionDesc.getName());
dimensionFilter.setOperator(FilterOperatorEnum.IN);
dimensionFilter.setElementID(entry.getKey());
parseInfo.getDimensionFilters().add(dimensionFilter);
}
}
}
}
public void fillDateDomain(SemanticParseInfo parseInfo, ChatContext chatCtx, ChatConfigRichResp chaConfigRichDesc,
ChatDefaultRichConfig chatDefaultConfig, Boolean isDetailMode) {
//SemanticParseInfo parseInfo = queryContext.getParseInfo();
if (parseInfo == null || parseInfo.getDateInfo() == null) {
@@ -232,16 +341,18 @@ public class DefaultMetricUtils {
isUpdateTime = true;
}
if (isUpdateTime && parseInfo != null && parseInfo.getDomainId() > 0) {
fillThemeDefaultTime(parseInfo.getDomainId(), chaConfigRichDesc, parseInfo);
fillThemeDefaultTime(chaConfigRichDesc, parseInfo, chatDefaultConfig, isDetailMode);
}
}
}
public void fillThemeDefaultMetricLogic(SemanticParseInfo semanticParseInfo, ChatConfigRichInfo chaConfigRichDesc,
QueryContextReq queryContext) {
public void fillDefaultMetricAggLogic(SemanticParseInfo semanticParseInfo, ChatConfigRichResp chaConfigRichDesc, QueryContextReq queryContext) {
//SemanticParseInfo semanticParseInfo = queryContext.getParseInfo();
if (Objects.isNull(chaConfigRichDesc) || CollectionUtils.isEmpty(chaConfigRichDesc.getDefaultMetrics())) {
if (Objects.isNull(chaConfigRichDesc) || Objects.isNull(chaConfigRichDesc.getChatAggRichConfig())
|| Objects.isNull(chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig())
|| CollectionUtils.isEmpty(chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig().getMetrics())) {
log.info("there is no defaultMetricIds info");
return;
}
@@ -258,9 +369,9 @@ public class DefaultMetricUtils {
.filter(e -> e.getElementType().equals(SchemaElementType.DIMENSION)).count();
if (metricNum <= 0 && dimensionNum <= 0) {
Set<SchemaItem> metrics = new LinkedHashSet();
chaConfigRichDesc.getDefaultMetrics().stream().forEach(metric -> {
chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig().getMetrics().stream().forEach(metric -> {
SchemaItem metricTmp = new SchemaItem();
metricTmp.setId(metric.getMetricId());
metricTmp.setId(metric.getId());
metricTmp.setBizName(metric.getBizName());
metrics.add(metricTmp);
});
@@ -269,18 +380,17 @@ public class DefaultMetricUtils {
if (Objects.isNull(semanticParseInfo.getDateInfo()) || Objects.isNull(
semanticParseInfo.getDateInfo().getDateMode())) {
DefaultMetric defaultMetricInfo = chaConfigRichDesc.getDefaultMetrics().get(0);
ChatDefaultRichConfig chatDefaultConfig = chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig();
DateConf dateInfo = new DateConf();
dateInfo.setDateMode(DateConf.DateMode.RECENT_UNITS);
dateInfo.setUnit(defaultMetricInfo.getUnit());
dateInfo.setPeriod(defaultMetricInfo.getPeriod());
dateInfo.setUnit(chatDefaultConfig.getUnit());
dateInfo.setPeriod(chatDefaultConfig.getPeriod());
semanticParseInfo.setDateInfo(dateInfo);
}
}
public void fillThemeDefaultTime(Long domain, ChatConfigRichInfo chaConfigRichDesc,
SemanticParseInfo semanticParseInfo) {
public void fillThemeDefaultTime(ChatConfigRichResp chaConfigRichDesc, SemanticParseInfo semanticParseInfo, ChatDefaultRichConfig chatDefaultConfig, Boolean isDetailMode) {
if (!Objects.isNull(semanticParseInfo.getDateInfo()) && !Objects.isNull(
semanticParseInfo.getDateInfo().getDateMode())) {
return;
@@ -288,22 +398,26 @@ public class DefaultMetricUtils {
if (chaConfigRichDesc == null) {
chaConfigRichDesc = getChatConfigRichInfo(semanticParseInfo.getDomainId());
}
if (!Objects.isNull(chaConfigRichDesc) && !CollectionUtils.isEmpty(chaConfigRichDesc.getDefaultMetrics())) {
DefaultMetric defaultMetricInfo = chaConfigRichDesc.getDefaultMetrics().get(0);
if (!Objects.isNull(chaConfigRichDesc) && Objects.nonNull(chatDefaultConfig) && !CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())) {
DateConf dateInfo = new DateConf();
dateInfo.setDateMode(DateConf.DateMode.RECENT_UNITS);
dateInfo.setUnit(defaultMetricInfo.getUnit());
dateInfo.setStartDate(now().minusDays(defaultMetricInfo.getUnit()).toString());
dateInfo.setEndDate(now().minusDays(1).toString());
dateInfo.setPeriod(defaultMetricInfo.getPeriod());
if (isDetailMode) {
dateInfo.setDateMode(DateConf.DateMode.RECENT_UNITS);
dateInfo.setUnit(1);
dateInfo.setPeriod(Constants.DAY);
} else {
dateInfo.setDateMode(DateConf.DateMode.RECENT_UNITS);
dateInfo.setUnit(chatDefaultConfig.getUnit());
dateInfo.setPeriod(chatDefaultConfig.getPeriod());
}
semanticParseInfo.setDateInfo(dateInfo);
log.info("fillThemeDefaultTime");
}
}
public ChatConfigRichInfo getChatConfigRichInfo(Long domain) {
DefaultSemanticInternalUtils defaultSemanticUtils = ContextUtils.getBean(DefaultSemanticInternalUtils.class);
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(domain);
public ChatConfigRichResp getChatConfigRichInfo(Long domain) {
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(domain);
return chaConfigRichDesc;
}

View File

@@ -1,153 +0,0 @@
package com.tencent.supersonic.chat.domain.utils;
import static com.tencent.supersonic.common.constant.Constants.LIST_LOWER;
import static com.tencent.supersonic.common.constant.Constants.PAGESIZE_LOWER;
import static com.tencent.supersonic.common.constant.Constants.TOTAL_LOWER;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.core.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.core.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.core.response.DimensionResp;
import com.tencent.supersonic.semantic.api.core.response.DomainResp;
import com.tencent.supersonic.semantic.api.core.response.MetricResp;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.common.result.ResultData;
import com.tencent.supersonic.common.result.ReturnCode;
import com.tencent.supersonic.common.util.context.S2ThreadContext;
import com.tencent.supersonic.common.util.context.ThreadContext;
import com.tencent.supersonic.common.util.json.JsonUtil;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
@Component
@Slf4j
public class DefaultSemanticInternalUtils {
@Value("${semantic.url.prefix:http://localhost:8081}")
private String semanticUrl;
@Value("${fetchDomainList.path:/api/semantic/schema/dimension/page}")
private String fetchDimensionPagePath;
@Value("${fetchDomainList.path:/api/semantic/schema/metric/page}")
private String fetchMetricPagePath;
@Value("${fetchDomainList.path:/api/semantic/schema/domain/list}")
private String fetchDomainListPath;
@Autowired
private RestTemplate restTemplate;
@Autowired
private ConfigServiceImpl chaConfigService;
@Autowired
private S2ThreadContext s2ThreadContext;
@Autowired
private AuthenticationConfig authenticationConfig;
public ChatConfigRichInfo getChatConfigRichInfo(Long domain) {
return chaConfigService.getConfigRichInfo(domain);
}
public PageInfo<MetricResp> queryMetricPage(PageMetricReq pageMetricCmd, User user) {
String body = JsonUtil.toString(pageMetricCmd);
Object dimensionListObject = fetchHttpResult(semanticUrl + fetchMetricPagePath, body, HttpMethod.POST);
LinkedHashMap map = (LinkedHashMap) dimensionListObject;
PageInfo<Object> metricDescObjectPageInfo = generatePageInfo(map);
PageInfo<MetricResp> metricDescPageInfo = new PageInfo<>();
BeanUtils.copyProperties(metricDescObjectPageInfo, metricDescPageInfo);
metricDescPageInfo.setList(metricDescPageInfo.getList());
return metricDescPageInfo;
}
public PageInfo<DimensionResp> queryDimensionPage(PageDimensionReq pageDimensionCmd, User user) {
String body = JsonUtil.toString(pageDimensionCmd);
Object dimensionListObject = fetchHttpResult(semanticUrl + fetchDimensionPagePath, body, HttpMethod.POST);
LinkedHashMap map = (LinkedHashMap) dimensionListObject;
PageInfo<Object> dimensionDescObjectPageInfo = generatePageInfo(map);
PageInfo<DimensionResp> dimensionDescPageInfo = new PageInfo<>();
BeanUtils.copyProperties(dimensionDescObjectPageInfo, dimensionDescPageInfo);
dimensionDescPageInfo.setList(dimensionDescPageInfo.getList());
return dimensionDescPageInfo;
}
private PageInfo<Object> generatePageInfo(LinkedHashMap map) {
PageInfo<Object> pageInfo = new PageInfo<>();
pageInfo.setList((List<Object>) map.get(LIST_LOWER));
Integer total = (Integer) map.get(TOTAL_LOWER);
pageInfo.setTotal(total);
Integer pageSize = (Integer) map.get(PAGESIZE_LOWER);
pageInfo.setPageSize(pageSize);
pageInfo.setPages((int) Math.ceil((double) total / pageSize));
return pageInfo;
}
public Object fetchHttpResult(String url, String bodyJson, HttpMethod httpMethod) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
fillToken(headers);
URI requestUrl = UriComponentsBuilder.fromHttpUrl(url).build().encode().toUri();
ParameterizedTypeReference<ResultData<Object>> responseTypeRef =
new ParameterizedTypeReference<ResultData<Object>>() {
};
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(bodyJson), headers);
try {
ResponseEntity<ResultData<Object>> responseEntity = restTemplate.exchange(requestUrl,
httpMethod, entity, responseTypeRef);
ResultData<Object> responseBody = responseEntity.getBody();
log.debug("ApiResponse<fetchDomainSchema> responseBody:{}", responseBody);
if (ReturnCode.SUCCESS.getCode() == responseBody.getCode()) {
Object data = responseBody.getData();
return data;
}
} catch (Exception e) {
throw new RuntimeException("fetchDomainSchema interface error", e);
}
throw new RuntimeException("fetchDomainSchema interface error");
}
public void fillToken(HttpHeaders headers) {
ThreadContext threadContext = s2ThreadContext.get();
if (Objects.nonNull(threadContext) && Strings.isNotEmpty(threadContext.getToken())) {
if (Objects.nonNull(authenticationConfig) && Strings.isNotEmpty(
authenticationConfig.getTokenHttpHeaderKey())) {
headers.set(authenticationConfig.getTokenHttpHeaderKey(), threadContext.getToken());
}
} else {
log.debug("threadContext is null:{}", Objects.isNull(threadContext));
}
}
public List<DomainResp> getDomainListForAdmin() {
Object domainDescListObject = fetchHttpResult(semanticUrl + fetchDomainListPath, null, HttpMethod.GET);
List<DomainResp> domainDescList = JsonUtil.toList(JsonUtil.toString(domainDescListObject), DomainResp.class);
return domainDescList;
}
}

View File

@@ -4,14 +4,12 @@ import static com.tencent.supersonic.common.constant.Constants.DAY;
import static com.tencent.supersonic.common.constant.Constants.UNDERLINE;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.domain.pojo.config.*;
import com.tencent.supersonic.common.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.chat.domain.dataobject.DimValueDO;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetric;
import com.tencent.supersonic.chat.domain.pojo.config.Dim4Dict;
import com.tencent.supersonic.chat.domain.pojo.config.ItemVisibilityInfo;
import com.tencent.supersonic.chat.domain.pojo.config.KnowledgeInfo;
import com.tencent.supersonic.knowledge.domain.pojo.DictUpdateMode;
import com.tencent.supersonic.knowledge.domain.pojo.DimValue2DictCommand;
@@ -25,6 +23,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -32,13 +32,15 @@ import org.springframework.util.CollectionUtils;
@Component
public class DictMetaUtils {
private final DefaultSemanticInternalUtils defaultSemanticUtils;
@Autowired
private ConfigServiceImpl configService;
@Value("${model.internal.metric.suffix:internal_cnt}")
private String internalMetricNameSuffix;
private SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
public DictMetaUtils(DefaultSemanticInternalUtils defaultSemanticUtils) {
this.defaultSemanticUtils = defaultSemanticUtils;
public DictMetaUtils() {
}
@@ -128,46 +130,66 @@ public class DictMetaUtils {
}
private void fillDimValueDOList(List<DimValueDO> dimValueDOList, Long domainId,
Map<Long, DimSchemaResp> dimIdAndDescPair) {
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(domainId);
if (Objects.nonNull(chaConfigRichDesc)) {
Map<Long, DimSchemaResp> dimIdAndDescPair) {
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(domainId);
if (Objects.nonNull(chaConfigRichDesc) && Objects.nonNull(chaConfigRichDesc.getChatAggRichConfig())) {
List<DefaultMetric> defaultMetricDescList = chaConfigRichDesc.getDefaultMetrics();
ChatDefaultRichConfig chatDefaultConfig = chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig();
List<KnowledgeInfo> knowledgeAggInfo = chaConfigRichDesc.getChatAggRichConfig().getKnowledgeInfos();
List<KnowledgeInfo> knowledgeInfos = chaConfigRichDesc.getKnowledgeInfos();
if (!CollectionUtils.isEmpty(knowledgeInfos)) {
List<Dim4Dict> dimensions = new ArrayList<>();
knowledgeInfos.stream()
.filter(knowledgeInfo -> knowledgeInfo.getIsDictInfo()
&& isVisibleDim(knowledgeInfo, chaConfigRichDesc.getVisibility()))
.forEach(knowledgeInfo -> {
if (dimIdAndDescPair.containsKey(knowledgeInfo.getItemId())) {
DimSchemaResp dimensionDesc = dimIdAndDescPair.get(knowledgeInfo.getItemId());
List<KnowledgeInfo> knowledgeDetailInfo = chaConfigRichDesc.getChatDetailRichConfig().getKnowledgeInfos();
//default cnt
if (CollectionUtils.isEmpty(defaultMetricDescList)) {
String datasourceBizName = dimensionDesc.getDatasourceBizName();
if (Strings.isNotEmpty(datasourceBizName)) {
String internalMetricName =
datasourceBizName + UNDERLINE + internalMetricNameSuffix;
defaultMetricDescList.add(new DefaultMetric(internalMetricName, 2, DAY));
}
fillKnowledgeDimValue(knowledgeDetailInfo, chatDefaultConfig, dimValueDOList, dimIdAndDescPair, domainId);
fillKnowledgeDimValue(knowledgeAggInfo, chatDefaultConfig, dimValueDOList, dimIdAndDescPair, domainId);
}
}
private void fillKnowledgeDimValue(List<KnowledgeInfo> knowledgeInfos, ChatDefaultRichConfig chatDefaultConfig,
List<DimValueDO> dimValueDOList, Map<Long, DimSchemaResp> dimIdAndDescPair, Long domainId) {
if (!CollectionUtils.isEmpty(knowledgeInfos)) {
List<Dim4Dict> dimensions = new ArrayList<>();
List<DefaultMetric> defaultMetricDescList = new ArrayList<>();
knowledgeInfos.stream()
.filter(knowledgeInfo -> knowledgeInfo.getSearchEnable() && !CollectionUtils.isEmpty(dimIdAndDescPair)
&& dimIdAndDescPair.containsKey(knowledgeInfo.getItemId()))
.forEach(knowledgeInfo -> {
if (dimIdAndDescPair.containsKey(knowledgeInfo.getItemId())) {
DimSchemaResp dimensionDesc = dimIdAndDescPair.get(knowledgeInfo.getItemId());
//default cnt
if (Objects.isNull(chatDefaultConfig) || CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())) {
String datasourceBizName = dimensionDesc.getDatasourceBizName();
if (Strings.isNotEmpty(datasourceBizName)) {
String internalMetricName =
datasourceBizName + UNDERLINE + internalMetricNameSuffix;
defaultMetricDescList.add(new DefaultMetric(internalMetricName, 2, DAY));
}
} else {
SchemaItem schemaItem = chatDefaultConfig.getMetrics().get(0);
defaultMetricDescList.add(new DefaultMetric(schemaItem.getBizName(), chatDefaultConfig.getUnit(), chatDefaultConfig.getPeriod()));
String bizName = dimensionDesc.getBizName();
dimensions.add(new Dim4Dict(knowledgeInfo.getItemId(), bizName,
knowledgeInfo.getBlackList(), knowledgeInfo.getWhiteList(),
knowledgeInfo.getRuleList()));
}
});
if (!CollectionUtils.isEmpty(dimensions)) {
DimValueDO dimValueDO = new DimValueDO()
.setDomainId(domainId)
.setDefaultMetricIds(defaultMetricDescList)
.setDimensions(dimensions);
dimValueDOList.add(dimValueDO);
}
String bizName = dimensionDesc.getBizName();
Dim4Dict dim4Dict = new Dim4Dict();
dim4Dict.setDimId(knowledgeInfo.getItemId());
dim4Dict.setBizName(bizName);
if(Objects.nonNull(knowledgeInfo.getKnowledgeAdvancedConfig())){
KnowledgeAdvancedConfig knowledgeAdvancedConfig = knowledgeInfo.getKnowledgeAdvancedConfig();
BeanUtils.copyProperties(knowledgeAdvancedConfig, dim4Dict);
}
dimensions.add(dim4Dict);
}
});
if (!CollectionUtils.isEmpty(dimensions)) {
DimValueDO dimValueDO = new DimValueDO()
.setDomainId(domainId)
.setDefaultMetricIds(defaultMetricDescList)
.setDimensions(dimensions);
dimValueDOList.add(dimValueDO);
}
}
}
@@ -178,4 +200,4 @@ public class DictMetaUtils {
}
return !itemVisibilityDesc.getBlackDimIdList().contains(knowledgeInfo.getItemId());
}
}
}

View File

@@ -17,35 +17,36 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
public class DslToSemanticInfo {
public static final String SUB_TABLE = " ( select * from t_{0} where {1} >= ''{2}'' and {1} <= ''{3}'' ) as t_sub_{0}";
private static final Logger LOG = LoggerFactory.getLogger(DslToSemanticInfo.class);
protected static final String SUB_TABLE = " ( select * from t_{0} where {1} >= ''{2}'' and {1} <= ''{3}'' ) as t_sub_{0}";
public static String convert(SemanticParseInfo parseInfo, LLMResp llmResp) {
public String convert(SemanticParseInfo parseInfo, LLMResp llmResp, Integer domainId) throws SqlParseException {
String sqlOutput = llmResp.getSqlOutput();
String domainName = llmResp.getDomainName();
DomainInfos domainInfos = ContextUtils.getBean(WordNatureService.class).getCache().getUnchecked("");
// 1. extra deal with,such as add alias.
sqlOutput = extraConvert(sqlOutput, domainId);
SqlParserInfo sqlParseInfo = SqlParseUtils.getSqlParseInfo(sqlOutput);
String tableName = sqlParseInfo.getTableName();
List<String> allFields = sqlParseInfo.getAllFields();
if (StringUtils.isEmpty(domainName)) {
domainName = tableName;
}
List<String> allFields = sqlParseInfo.getAllFields();
Map<String, Integer> domainNameToId = domainInfos.getDomains().stream()
.collect(Collectors.toMap(ItemDO::getName, a -> a.getDomain(), (k1, k2) -> k1));
Integer domainId = domainNameToId.get(domainName);
LOG.info("sqlParseInfo:{} ,domainName:{},domainId:{}", sqlParseInfo, domainName, domainId);
// 2. replace the llm dsl, such as replace fieldName and tableName.
log.info("sqlParseInfo:{} ,domainName:{},domainId:{}", sqlParseInfo, domainName, domainId);
DomainInfos domainInfos = ContextUtils.getBean(WordNatureService.class).getCache().getUnchecked("");
List<ItemDO> fieldList = domainInfos.getMetrics();
fieldList.addAll(domainInfos.getDimensions());
Map<String, String> fieldToBizName = getMapInfo(domainId, fieldList);
@@ -56,6 +57,7 @@ public class DslToSemanticInfo {
sqlOutput = sqlOutput.replaceAll(fieldName, fieldBizName);
}
}
//3. deal with dayNo.
DateConf dateInfo = new DateConf();
if (Objects.nonNull(parseInfo) && Objects.nonNull(parseInfo.getDateInfo())) {
dateInfo = parseInfo.getDateInfo();
@@ -72,15 +74,18 @@ public class DslToSemanticInfo {
TimeDimensionEnum timeDimension = TimeDimensionEnum.valueOf(period);
String dayField = timeDimension.getName();
// add dayno
String subTable = MessageFormat.format(SUB_TABLE, domainId, dayField, startDate, endDate);
String querySql = sqlOutput.replaceAll(tableName, subTable);
LOG.info("querySql:{},sqlOutput:{},dateInfo:{}", querySql, sqlOutput, dateInfo);
log.info("querySql:{},sqlOutput:{},dateInfo:{}", querySql, sqlOutput, dateInfo);
return querySql;
}
private static Map<String, String> getMapInfo(Integer domainId, List<ItemDO> metrics) {
protected String extraConvert(String sqlOutput, Integer domainId) throws SqlParseException {
return SqlParseUtils.addAliasToSql(sqlOutput);
}
protected Map<String, String> getMapInfo(Integer domainId, List<ItemDO> metrics) {
return metrics.stream().filter(entry -> entry.getDomain().equals(domainId))
.collect(Collectors.toMap(ItemDO::getName, a -> a.getBizName(), (k1, k2) -> k1));
}

View File

@@ -1,16 +1,16 @@
package com.tencent.supersonic.chat.infrastructure.repository;
import com.tencent.supersonic.chat.domain.dataobject.ChatConfigDO;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilter;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilterInternal;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.*;
import com.tencent.supersonic.chat.domain.repository.ChatConfigRepository;
import com.tencent.supersonic.chat.domain.utils.ChatConfigUtils;
import com.tencent.supersonic.chat.infrastructure.mapper.ChatConfigMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@@ -24,7 +24,7 @@ public class ChatConfigRepositoryImpl implements ChatConfigRepository {
private final ChatConfigMapper chatConfigMapper;
public ChatConfigRepositoryImpl(ChatConfigUtils chatConfigUtils,
ChatConfigMapper chatConfigMapper) {
ChatConfigMapper chatConfigMapper) {
this.chatConfigUtils = chatConfigUtils;
this.chatConfigMapper = chatConfigMapper;
}
@@ -32,8 +32,8 @@ public class ChatConfigRepositoryImpl implements ChatConfigRepository {
@Override
public Long createConfig(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = chatConfigUtils.chatConfig2DO(chaConfig);
return chatConfigMapper.addConfig(chaConfigDO);
chatConfigMapper.addConfig(chaConfigDO);
return chaConfigDO.getId();
}
@Override
@@ -45,26 +45,23 @@ public class ChatConfigRepositoryImpl implements ChatConfigRepository {
}
@Override
public List<ChatConfigInfo> getChatConfig(ChatConfigFilter filter) {
List<ChatConfigInfo> chaConfigDescriptorList = new ArrayList<>();
public List<ChatConfigResp> getChatConfig(ChatConfigFilter filter) {
List<ChatConfigResp> chaConfigDescriptorList = new ArrayList<>();
ChatConfigFilterInternal filterInternal = new ChatConfigFilterInternal();
BeanUtils.copyProperties(filter, filterInternal);
filterInternal.setStatus(filter.getStatus().getCode());
List<ChatConfigDO> chaConfigDOList = chatConfigMapper.search(filterInternal);
if (!CollectionUtils.isEmpty(chaConfigDOList)) {
chaConfigDOList.stream().forEach(chaConfigDO ->
chaConfigDescriptorList.add(chatConfigUtils.chatConfigDO2Descriptor(chaConfigDO)));
chaConfigDescriptorList.add(chatConfigUtils.chatConfigDO2Descriptor(chaConfigDO.getDomainId(), chaConfigDO)));
}
return chaConfigDescriptorList;
}
@Override
public ChatConfigInfo getConfigByDomainId(Long domainId) {
public ChatConfigResp getConfigByDomainId(Long domainId) {
ChatConfigDO chaConfigPO = chatConfigMapper.fetchConfigByDomainId(domainId);
if (Objects.isNull(chaConfigPO)) {
return new ChatConfigInfo();
}
return chatConfigUtils.chatConfigDO2Descriptor(chaConfigPO);
return chatConfigUtils.chatConfigDO2Descriptor(domainId, chaConfigPO);
}
}

View File

@@ -1,7 +1,6 @@
package com.tencent.supersonic.chat.infrastructure.semantic;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -24,12 +23,21 @@ public class DefaultSemanticConfig {
@Value("${fetchDomainSchemaPath.path:/api/semantic/schema}")
private String fetchDomainSchemaPath;
@Autowired
private DefaultSemanticInternalUtils defaultSemanticInternalUtils;
@Value("${fetchDomainList.path:/api/semantic/schema/dimension/page}")
private String fetchDimensionPagePath;
@Value("${fetchDomainList.path:/api/semantic/schema/metric/page}")
private String fetchMetricPagePath;
@Value("${fetchDomainList.path:/api/semantic/schema/domain/list}")
private String fetchDomainListPath;
@Value("${fetchDomainList.path:/api/semantic/schema/domain/view/list}")
private String fetchDomainViewListPath;
@Autowired
private RestTemplate restTemplate;
@Autowired
private ConfigServiceImpl chaConfigService;
private ConfigServiceImpl configService;
}

View File

@@ -1,20 +1,27 @@
package com.tencent.supersonic.chat.infrastructure.semantic;
import com.github.pagehelper.PageInfo;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatAggConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatDetailConfig;
import com.tencent.supersonic.chat.domain.pojo.config.ItemVisibility;
import com.tencent.supersonic.common.util.context.ContextUtils;
import com.tencent.supersonic.common.util.context.S2ThreadContext;
import com.tencent.supersonic.common.util.context.ThreadContext;
import com.tencent.supersonic.common.util.json.JsonUtil;
import com.tencent.supersonic.semantic.api.core.request.DomainSchemaFilterReq;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.core.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.core.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.core.response.*;
import com.tencent.supersonic.semantic.api.query.request.QuerySqlReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.core.domain.DimensionService;
import com.tencent.supersonic.semantic.core.domain.DomainService;
import com.tencent.supersonic.semantic.core.domain.MetricService;
import com.tencent.supersonic.semantic.query.domain.SchemaService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -30,8 +37,21 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
private static final Cache<String, List<DomainSchemaResp>> domainSchemaCache =
CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build();
private SchemaService schemaService;
private S2ThreadContext s2ThreadContext;
private DomainService domainService;
private DimensionService dimensionService;
private MetricService metricService;
// public LocalSemanticLayerImpl(DomainService domainService){
// this.domainService=domainService;
// }
@Override
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user) {
deletionDuplicated(queryStructReq);
@@ -60,6 +80,7 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
return null;
}
public List<DomainSchemaResp> fetchDomainSchemaAll(List<Long> ids) {
DomainSchemaFilterReq filter = new DomainSchemaFilterReq();
@@ -71,23 +92,23 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
@SneakyThrows
public List<DomainSchemaResp> fetchDomainSchema(List<Long> ids) {
// return domainSchemaCache.get(String.valueOf(ids), () -> {
// List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
// fillEntityNameAndFilterBlackElement(data);
// return data;
// });
public List<DomainSchemaResp> fetchDomainSchema(List<Long> ids, Boolean cacheEnable) {
if (cacheEnable) {
return domainSchemaCache.get(String.valueOf(ids), () -> {
List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
fillEntityNameAndFilterBlackElement(data);
return data;
});
}
List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
fillEntityNameAndFilterBlackElement(data);
return data;
}
@Override
public DomainSchemaResp getDomainSchemaInfo(Long domain) {
public DomainSchemaResp getDomainSchemaInfo(Long domain, Boolean cacheEnable) {
List<Long> ids = new ArrayList<>();
ids.add(domain);
List<DomainSchemaResp> domainSchemaResps = fetchDomainSchema(ids);
List<DomainSchemaResp> domainSchemaResps = fetchDomainSchema(ids, cacheEnable);
if (!CollectionUtils.isEmpty(domainSchemaResps)) {
Optional<DomainSchemaResp> domainSchemaResp = domainSchemaResps.stream()
.filter(d -> d.getId().equals(domain)).findFirst();
@@ -101,21 +122,21 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
@Override
public List<DomainSchemaResp> getDomainSchemaInfo(List<Long> ids) {
return fetchDomainSchema(ids);
return fetchDomainSchema(ids, true);
}
public DomainSchemaResp fillEntityNameAndFilterBlackElement(DomainSchemaResp domainSchemaResp) {
if (Objects.isNull(domainSchemaResp) || Objects.isNull(domainSchemaResp.getId())) {
return domainSchemaResp;
}
ChatConfigInfo chaConfigInfo = getConfigBaseInfo(domainSchemaResp.getId());
ChatConfigResp chatConfigResp = getConfigBaseInfo(domainSchemaResp.getId());
// fill entity names
fillEntityNamesInfo(domainSchemaResp, chaConfigInfo);
fillEntityNamesInfo(domainSchemaResp, chatConfigResp);
// filter black element
filterBlackDim(domainSchemaResp, chaConfigInfo);
filterBlackMetric(domainSchemaResp, chaConfigInfo);
filterBlackDim(domainSchemaResp, chatConfigResp);
filterBlackMetric(domainSchemaResp, chatConfigResp);
return domainSchemaResp;
}
@@ -126,9 +147,9 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
}
}
private void filterBlackMetric(DomainSchemaResp domainSchemaResp, ChatConfigInfo chaConfigInfo) {
ItemVisibility visibility = chaConfigInfo.getVisibility();
if (Objects.nonNull(chaConfigInfo) && Objects.nonNull(visibility)
private void filterBlackMetric(DomainSchemaResp domainSchemaResp, ChatConfigResp chatConfigResp) {
ItemVisibility visibility = generateFinalVisibility(chatConfigResp);
if (Objects.nonNull(chatConfigResp) && Objects.nonNull(visibility)
&& !CollectionUtils.isEmpty(visibility.getBlackMetricIdList())
&& !CollectionUtils.isEmpty(domainSchemaResp.getMetrics())) {
List<MetricSchemaResp> metric4Chat = domainSchemaResp.getMetrics().stream()
@@ -138,9 +159,32 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
}
}
private void filterBlackDim(DomainSchemaResp domainSchemaResp, ChatConfigInfo chatConfigInfo) {
ItemVisibility visibility = chatConfigInfo.getVisibility();
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(visibility)
private ItemVisibility generateFinalVisibility(ChatConfigResp chatConfigInfo) {
ItemVisibility visibility = new ItemVisibility();
ChatAggConfig chatAggConfig = chatConfigInfo.getChatAggConfig();
ChatDetailConfig chatDetailConfig = chatConfigInfo.getChatDetailConfig();
// both black is exist
if (Objects.nonNull(chatAggConfig) && Objects.nonNull(chatAggConfig.getVisibility())
&& Objects.nonNull(chatDetailConfig) && Objects.nonNull(chatDetailConfig.getVisibility())) {
List<Long> blackDimIdList = new ArrayList<>();
blackDimIdList.addAll(chatAggConfig.getVisibility().getBlackDimIdList());
blackDimIdList.retainAll(chatDetailConfig.getVisibility().getBlackDimIdList());
List<Long> blackMetricIdList = new ArrayList<>();
blackMetricIdList.addAll(chatAggConfig.getVisibility().getBlackMetricIdList());
blackMetricIdList.retainAll(chatDetailConfig.getVisibility().getBlackMetricIdList());
visibility.setBlackDimIdList(blackDimIdList);
visibility.setBlackMetricIdList(blackMetricIdList);
}
return visibility;
}
private void filterBlackDim(DomainSchemaResp domainSchemaResp, ChatConfigResp chatConfigResp) {
ItemVisibility visibility = generateFinalVisibility(chatConfigResp);
if (Objects.nonNull(chatConfigResp) && Objects.nonNull(visibility)
&& !CollectionUtils.isEmpty(visibility.getBlackDimIdList())
&& !CollectionUtils.isEmpty(domainSchemaResp.getDimensions())) {
List<DimSchemaResp> dim4Chat = domainSchemaResp.getDimensions().stream()
@@ -150,10 +194,11 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
}
}
private void fillEntityNamesInfo(DomainSchemaResp domainSchemaResp, ChatConfigInfo chatConfigInfo) {
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(chatConfigInfo.getEntity())
&& !CollectionUtils.isEmpty(chatConfigInfo.getEntity().getNames())) {
domainSchemaResp.setEntityNames(chatConfigInfo.getEntity().getNames());
private void fillEntityNamesInfo(DomainSchemaResp domainSchemaResp, ChatConfigResp chatConfigResp) {
if (Objects.nonNull(chatConfigResp) && Objects.nonNull(chatConfigResp.getChatDetailConfig())
&& Objects.nonNull(chatConfigResp.getChatDetailConfig().getEntity())
&& !CollectionUtils.isEmpty(chatConfigResp.getChatDetailConfig().getEntity().getNames())) {
domainSchemaResp.setEntityNames(chatConfigResp.getChatDetailConfig().getEntity().getNames());
}
}
@@ -173,9 +218,37 @@ public class LocalSemanticLayerImpl implements SemanticLayer {
}
}
public ChatConfigInfo getConfigBaseInfo(Long domain) {
public ChatConfigResp getConfigBaseInfo(Long domain) {
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
return defaultSemanticConfig.getChaConfigService().fetchConfigByDomainId(domain);
return defaultSemanticConfig.getConfigService().fetchConfigByDomainId(domain);
}
@Override
public List<DomainResp> getDomainListForViewer() {
s2ThreadContext = ContextUtils.getBean(S2ThreadContext.class);
ThreadContext threadContext = s2ThreadContext.get();
domainService = ContextUtils.getBean(DomainService.class);
return domainService.getDomainListForViewer(threadContext.getUserName());
}
@Override
public List<DomainResp> getDomainListForAdmin() {
domainService = ContextUtils.getBean(DomainService.class);
s2ThreadContext = ContextUtils.getBean(S2ThreadContext.class);
ThreadContext threadContext = s2ThreadContext.get();
return domainService.getDomainListForAdmin(threadContext.getUserName());
}
@Override
public PageInfo<DimensionResp> queryDimensionPage(PageDimensionReq pageDimensionCmd) {
dimensionService = ContextUtils.getBean(DimensionService.class);
return dimensionService.queryDimension(pageDimensionCmd);
}
@Override
public PageInfo<MetricResp> queryMetricPage(PageMetricReq pageMetricCmd) {
metricService = ContextUtils.getBean(MetricService.class);
return metricService.queryMetric(pageMetricCmd);
}
}

View File

@@ -1,39 +1,40 @@
package com.tencent.supersonic.chat.infrastructure.semantic;
import static com.tencent.supersonic.common.constant.Constants.TRUE_LOWER;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.Gson;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.domain.pojo.config.*;
import com.tencent.supersonic.common.util.context.ContextUtils;
import com.tencent.supersonic.common.util.context.S2ThreadContext;
import com.tencent.supersonic.common.util.context.ThreadContext;
import com.tencent.supersonic.common.util.json.JsonUtil;
import com.tencent.supersonic.semantic.api.core.request.DomainSchemaFilterReq;
import com.tencent.supersonic.semantic.api.core.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.core.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.core.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.core.response.*;
import com.tencent.supersonic.semantic.api.query.request.QuerySqlReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ItemVisibility;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import com.tencent.supersonic.common.exception.CommonException;
import com.tencent.supersonic.common.result.ResultData;
import com.tencent.supersonic.common.result.ReturnCode;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
@@ -41,11 +42,27 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import static com.tencent.supersonic.common.constant.Constants.*;
import static com.tencent.supersonic.common.constant.Constants.PAGESIZE_LOWER;
@Slf4j
public class RemoteSemanticLayerImpl implements SemanticLayer {
private RestTemplate restTemplate;
@Autowired
private ConfigServiceImpl configService;
@Autowired
private S2ThreadContext s2ThreadContext;
@Autowired
private AuthenticationConfig authenticationConfig;
private static final Cache<String, List<DomainSchemaResp>> domainSchemaCache =
CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build();
private ParameterizedTypeReference<ResultData<QueryResultWithSchemaResp>> structTypeRef =
@@ -70,11 +87,9 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
public QueryResultWithSchemaResp searchByRestTemplate(String url, String jsonReq) {
DefaultSemanticInternalUtils defaultSemanticInternalUtils = ContextUtils.getBean(
DefaultSemanticInternalUtils.class);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
defaultSemanticInternalUtils.fillToken(headers);
fillToken(headers);
URI requestUrl = UriComponentsBuilder.fromHttpUrl(url).build().encode().toUri();
HttpEntity<String> entity = new HttpEntity<>(jsonReq, headers);
log.info("url:{},searchByRestTemplate:{}", url, entity.getBody());
@@ -102,12 +117,10 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
public List<DomainSchemaResp> fetchDomainSchemaAll(List<Long> ids) {
DefaultSemanticInternalUtils defaultSemanticInternalUtils = ContextUtils.getBean(
DefaultSemanticInternalUtils.class);
HttpHeaders headers = new HttpHeaders();
headers.set(UserConstants.INTERNAL, TRUE_LOWER);
headers.setContentType(MediaType.APPLICATION_JSON);
defaultSemanticInternalUtils.fillToken(headers);
fillToken(headers);
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
URI requestUrl = UriComponentsBuilder.fromHttpUrl(
@@ -139,19 +152,24 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
@SneakyThrows
public List<DomainSchemaResp> fetchDomainSchema(List<Long> ids) {
return domainSchemaCache.get(String.valueOf(ids), () -> {
List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
fillEntityNameAndFilterBlackElement(data);
return data;
});
public List<DomainSchemaResp> fetchDomainSchema(List<Long> ids, Boolean cacheEnable) {
if (cacheEnable) {
return domainSchemaCache.get(String.valueOf(ids), () -> {
List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
fillEntityNameAndFilterBlackElement(data);
return data;
});
}
List<DomainSchemaResp> data = fetchDomainSchemaAll(ids);
fillEntityNameAndFilterBlackElement(data);
return data;
}
@Override
public DomainSchemaResp getDomainSchemaInfo(Long domain) {
public DomainSchemaResp getDomainSchemaInfo(Long domain, Boolean cacheEnable) {
List<Long> ids = new ArrayList<>();
ids.add(domain);
List<DomainSchemaResp> domainSchemaResps = fetchDomainSchema(ids);
List<DomainSchemaResp> domainSchemaResps = fetchDomainSchema(ids, cacheEnable);
if (!CollectionUtils.isEmpty(domainSchemaResps)) {
Optional<DomainSchemaResp> domainSchemaResp = domainSchemaResps.stream()
.filter(d -> d.getId().equals(domain)).findFirst();
@@ -165,21 +183,21 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
@Override
public List<DomainSchemaResp> getDomainSchemaInfo(List<Long> ids) {
return fetchDomainSchema(ids);
return fetchDomainSchema(ids, true);
}
public DomainSchemaResp fillEntityNameAndFilterBlackElement(DomainSchemaResp domainSchemaResp) {
if (Objects.isNull(domainSchemaResp) || Objects.isNull(domainSchemaResp.getId())) {
return domainSchemaResp;
}
ChatConfigInfo chaConfigInfo = getConfigBaseInfo(domainSchemaResp.getId());
ChatConfigResp chaConfigInfo = getConfigBaseInfo(domainSchemaResp.getId());
// fill entity names
fillEntityNamesInfo(domainSchemaResp, chaConfigInfo);
// filter black element
filterBlackDim(domainSchemaResp, chaConfigInfo);
filterBlackMetric(domainSchemaResp, chaConfigInfo);
return domainSchemaResp;
}
@@ -190,8 +208,9 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
}
private void filterBlackMetric(DomainSchemaResp domainSchemaResp, ChatConfigInfo chaConfigInfo) {
ItemVisibility visibility = chaConfigInfo.getVisibility();
private void filterBlackMetric(DomainSchemaResp domainSchemaResp, ChatConfigResp chaConfigInfo) {
ItemVisibility visibility = generateFinalVisibility(chaConfigInfo);
if (Objects.nonNull(chaConfigInfo) && Objects.nonNull(visibility)
&& !CollectionUtils.isEmpty(visibility.getBlackMetricIdList())
&& !CollectionUtils.isEmpty(domainSchemaResp.getMetrics())) {
@@ -202,8 +221,31 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
}
private void filterBlackDim(DomainSchemaResp domainSchemaResp, ChatConfigInfo chatConfigInfo) {
ItemVisibility visibility = chatConfigInfo.getVisibility();
private ItemVisibility generateFinalVisibility(ChatConfigResp chatConfigInfo) {
ItemVisibility visibility = new ItemVisibility();
ChatAggConfig chatAggConfig = chatConfigInfo.getChatAggConfig();
ChatDetailConfig chatDetailConfig = chatConfigInfo.getChatDetailConfig();
// both black is exist
if (Objects.nonNull(chatAggConfig) && Objects.nonNull(chatAggConfig.getVisibility())
&& Objects.nonNull(chatDetailConfig) && Objects.nonNull(chatDetailConfig.getVisibility())) {
List<Long> blackDimIdList = new ArrayList<>();
blackDimIdList.addAll(chatAggConfig.getVisibility().getBlackDimIdList());
blackDimIdList.retainAll(chatDetailConfig.getVisibility().getBlackDimIdList());
List<Long> blackMetricIdList = new ArrayList<>();
blackMetricIdList.addAll(chatAggConfig.getVisibility().getBlackMetricIdList());
blackMetricIdList.retainAll(chatDetailConfig.getVisibility().getBlackMetricIdList());
visibility.setBlackDimIdList(blackDimIdList);
visibility.setBlackMetricIdList(blackMetricIdList);
}
return visibility;
}
private void filterBlackDim(DomainSchemaResp domainSchemaResp, ChatConfigResp chatConfigInfo) {
ItemVisibility visibility = generateFinalVisibility(chatConfigInfo);
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(visibility)
&& !CollectionUtils.isEmpty(visibility.getBlackDimIdList())
&& !CollectionUtils.isEmpty(domainSchemaResp.getDimensions())) {
@@ -214,10 +256,11 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
}
private void fillEntityNamesInfo(DomainSchemaResp domainSchemaResp, ChatConfigInfo chatConfigInfo) {
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(chatConfigInfo.getEntity())
&& !CollectionUtils.isEmpty(chatConfigInfo.getEntity().getNames())) {
domainSchemaResp.setEntityNames(chatConfigInfo.getEntity().getNames());
private void fillEntityNamesInfo(DomainSchemaResp domainSchemaResp, ChatConfigResp chatConfigInfo) {
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(chatConfigInfo.getChatDetailConfig())
&& Objects.nonNull(chatConfigInfo.getChatDetailConfig().getEntity())
&& !CollectionUtils.isEmpty(chatConfigInfo.getChatDetailConfig().getEntity().getNames())) {
domainSchemaResp.setEntityNames(chatConfigInfo.getChatDetailConfig().getEntity().getNames());
}
}
@@ -237,9 +280,102 @@ public class RemoteSemanticLayerImpl implements SemanticLayer {
}
}
public ChatConfigInfo getConfigBaseInfo(Long domain) {
public ChatConfigResp getConfigBaseInfo(Long domain) {
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
return defaultSemanticConfig.getChaConfigService().fetchConfigByDomainId(domain);
return defaultSemanticConfig.getConfigService().fetchConfigByDomainId(domain);
}
@Override
public List<DomainResp> getDomainListForViewer() {
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
Object domainDescListObject = fetchHttpResult(defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getFetchDomainViewListPath(), null, HttpMethod.GET);
List<DomainResp> domainDescList = JsonUtil.toList(JsonUtil.toString(domainDescListObject), DomainResp.class);
return domainDescList;
}
@Override
public List<DomainResp> getDomainListForAdmin() {
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
Object domainDescListObject = fetchHttpResult(defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getFetchDomainListPath(), null, HttpMethod.GET);
List<DomainResp> domainDescList = JsonUtil.toList(JsonUtil.toString(domainDescListObject), DomainResp.class);
return domainDescList;
}
public Object fetchHttpResult(String url, String bodyJson, HttpMethod httpMethod) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
fillToken(headers);
URI requestUrl = UriComponentsBuilder.fromHttpUrl(url).build().encode().toUri();
ParameterizedTypeReference<ResultData<Object>> responseTypeRef =
new ParameterizedTypeReference<ResultData<Object>>() {
};
HttpEntity<String> entity = new HttpEntity<>(JsonUtil.toString(bodyJson), headers);
try {
restTemplate = ContextUtils.getBean(RestTemplate.class);
ResponseEntity<ResultData<Object>> responseEntity = restTemplate.exchange(requestUrl,
httpMethod, entity, responseTypeRef);
ResultData<Object> responseBody = responseEntity.getBody();
log.debug("ApiResponse<fetchDomainSchema> responseBody:{}", responseBody);
if (ReturnCode.SUCCESS.getCode() == responseBody.getCode()) {
Object data = responseBody.getData();
return data;
}
} catch (Exception e) {
throw new RuntimeException("fetchDomainSchema interface error", e);
}
throw new RuntimeException("fetchDomainSchema interface error");
}
public void fillToken(HttpHeaders headers) {
s2ThreadContext = ContextUtils.getBean(S2ThreadContext.class);
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
ThreadContext threadContext = s2ThreadContext.get();
if (Objects.nonNull(threadContext) && Strings.isNotEmpty(threadContext.getToken())) {
if (Objects.nonNull(authenticationConfig) && Strings.isNotEmpty(
authenticationConfig.getTokenHttpHeaderKey())) {
headers.set(authenticationConfig.getTokenHttpHeaderKey(), threadContext.getToken());
}
} else {
log.debug("threadContext is null:{}", Objects.isNull(threadContext));
}
}
@Override
public PageInfo<MetricResp> queryMetricPage(PageMetricReq pageMetricCmd) {
String body = JsonUtil.toString(pageMetricCmd);
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
log.info("url:{}", defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getFetchMetricPagePath());
Object dimensionListObject = fetchHttpResult(defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getFetchMetricPagePath(), body, HttpMethod.POST);
LinkedHashMap map = (LinkedHashMap) dimensionListObject;
PageInfo<Object> metricDescObjectPageInfo = generatePageInfo(map);
PageInfo<MetricResp> metricDescPageInfo = new PageInfo<>();
BeanUtils.copyProperties(metricDescObjectPageInfo, metricDescPageInfo);
metricDescPageInfo.setList(metricDescPageInfo.getList());
return metricDescPageInfo;
}
@Override
public PageInfo<DimensionResp> queryDimensionPage(PageDimensionReq pageDimensionCmd) {
String body = JsonUtil.toString(pageDimensionCmd);
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
Object dimensionListObject = fetchHttpResult(defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getFetchDimensionPagePath(), body, HttpMethod.POST);
LinkedHashMap map = (LinkedHashMap) dimensionListObject;
PageInfo<Object> dimensionDescObjectPageInfo = generatePageInfo(map);
PageInfo<DimensionResp> dimensionDescPageInfo = new PageInfo<>();
BeanUtils.copyProperties(dimensionDescObjectPageInfo, dimensionDescPageInfo);
dimensionDescPageInfo.setList(dimensionDescPageInfo.getList());
return dimensionDescPageInfo;
}
private PageInfo<Object> generatePageInfo(LinkedHashMap map) {
PageInfo<Object> pageInfo = new PageInfo<>();
pageInfo.setList((List<Object>) map.get(LIST_LOWER));
Integer total = (Integer) map.get(TOTAL_LOWER);
pageInfo.setTotal(total);
Integer pageSize = (Integer) map.get(PAGESIZE_LOWER);
pageInfo.setPageSize(pageSize);
pageInfo.setPages((int) Math.ceil((double) total / pageSize));
return pageInfo;
}
}

View File

@@ -3,18 +3,19 @@ package com.tencent.supersonic.chat.rest;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.component.SemanticLayer;
import com.tencent.supersonic.chat.domain.utils.ComponentFactory;
import com.tencent.supersonic.semantic.api.core.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.core.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.core.response.DimensionResp;
import com.tencent.supersonic.semantic.api.core.response.DomainResp;
import com.tencent.supersonic.semantic.api.core.response.MetricResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBase;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigBaseReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigFilter;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.chat.domain.service.ConfigService;
import com.tencent.supersonic.chat.domain.utils.DefaultSemanticInternalUtils;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
@@ -37,43 +38,43 @@ public class ChatConfigController {
@Autowired
private ConfigService configService;
@Autowired
private DefaultSemanticInternalUtils defaultSemanticUtils;
private SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
@PostMapping
public Long addChatConfig(@RequestBody ChatConfigBase extendBaseCmd,
HttpServletRequest request,
HttpServletResponse response) {
public Long addChatConfig(@RequestBody ChatConfigBaseReq extendBaseCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.addConfig(extendBaseCmd, user);
}
@PutMapping
public Long editDomainExtend(@RequestBody ChatConfigEditReq extendEditCmd,
HttpServletRequest request,
HttpServletResponse response) {
public Long editDomainExtend(@RequestBody ChatConfigEditReqReq extendEditCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.editConfig(extendEditCmd, user);
}
@PostMapping("/search")
public List<ChatConfigInfo> search(@RequestBody ChatConfigFilter filter,
HttpServletRequest request,
HttpServletResponse response) {
public List<ChatConfigResp> search(@RequestBody ChatConfigFilter filter,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.search(filter, user);
}
@GetMapping("/richDesc/{domainId}")
public ChatConfigRichInfo getDomainExtendRichInfo(@PathVariable("domainId") Long domainId) {
public ChatConfigRichResp getDomainExtendRichInfo(@PathVariable("domainId") Long domainId) {
return configService.getConfigRichInfo(domainId);
}
@GetMapping("/richDesc/all")
public List<ChatConfigRichInfo> getAllChatRichConfig() {
public List<ChatConfigRichResp> getAllChatRichConfig() {
return configService.getAllChatRichConfig();
}
@@ -85,23 +86,29 @@ public class ChatConfigController {
*/
@GetMapping("/domainList")
public List<DomainResp> getDomainList() {
return defaultSemanticUtils.getDomainListForAdmin();
return semanticLayer.getDomainListForAdmin();
//return defaultSemanticUtils.getDomainListForAdmin();
}
@GetMapping("/domainList/view")
public List<DomainResp> getDomainListForViewer() {
return semanticLayer.getDomainListForViewer();
//return defaultSemanticUtils.getDomainListForViewer();
}
@PostMapping("/dimension/page")
public PageInfo<DimensionResp> queryDimension(@RequestBody PageDimensionReq pageDimensionCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return defaultSemanticUtils.queryDimensionPage(pageDimensionCmd, user);
return semanticLayer.queryDimensionPage(pageDimensionCmd);
}
@PostMapping("/metric/page")
public PageInfo<MetricResp> queryMetric(@RequestBody PageMetricReq pageMetrricCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return defaultSemanticUtils.queryMetricPage(pageMetrricCmd, user);
return semanticLayer.queryMetricPage(pageMetrricCmd);
}

View File

@@ -0,0 +1,10 @@
# python path
export python_path="/usr/local/bin/python3.9"
# pip path
export pip_path="/usr/local/bin/pip3.9"
# host
export llm_host="127.0.0.1"
# port
export llm_port=9092
# start name
export start_name=api_service

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
binDir=$(cd "$(dirname "$0")"; pwd)
baseDir=$(readlink -f $binDir/../)
echo $binDir
source ${binDir}/env.sh
${pip_path} install -r $baseDir/requirements.txt
if ${python_path} -c "import langchain,fastapi,chromadb,tiktoken,uvicorn" >/dev/null 2>&1
then
echo "install ok, will pass"
else
if [ $? -eq 0 ]; then
echo "install ok"
else
echo "install fail ,pls check your install error log. cmd is : "
echo ${pip_path} install -r $baseDir/requirements.txt
exit 1
fi
fi

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
llm_host=$1
llm_port=$2
binDir=$(cd "$(dirname "$0")"; pwd)
baseDir=$(readlink -f $binDir/../)
source ${baseDir}/bin/env.sh
if [ "${llm_host}" = "" ] || [ "${llm_port}" = "" ]
then
echo "llm_host llm_port is not set"
exit 1
fi
if [ "${python_path}" = "" ] || [ "${pip_path}" = "" ]
then
echo "please set env value python_path , pip_path to python, pip path by export cmd "
exit 1
fi
chmod +x $binDir/install.sh
$binDir/install.sh
if [ $? -ne 0 ]; then
exit 1
fi
cd $baseDir/llm
nohup ${python_path} -m uvicorn ${start_name}:app --port ${llm_port} --host ${llm_host} > $baseDir/llm.log 2>&1 &

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
binDir=$(cd "$(dirname "$0")"; pwd)
baseDir=$(readlink -f $binDir/../)
source ${baseDir}/bin/env.sh
command=$1
function start()
{
pid=$(ps aux |grep ${start_name} | grep -v grep )
if [[ "$pid" == "" ]]; then
$baseDir/bin/run.sh && echo "Process started."
return 0
else
echo "Process (PID = $pid) is running."
return 1
fi
}
function stop()
{
pid=$(ps aux | grep ${start_name} | grep -v grep | awk '{print $2}')
if [[ "$pid" == "" ]]; then
echo "Process is not running !"
return 1
else
kill -9 $pid
echo "Process (PID = $pid) is killed !"
return 0
fi
}
case "$command" in
start)
echo -e "Starting ${start_name}"
start
;;
stop)
echo -e "Stopping ${start_name}"
stop
;;
restart)
echo -e "Resetting ${start_name}E"
stop
start
;;
*)
echo "Use command {start|stop|status|restart} to run."
exit 1
esac
exit 0

View File

@@ -0,0 +1,33 @@
# -*- coding:utf-8 -*-
import os
import logging
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from typing import Any, Mapping
from fastapi import FastAPI, HTTPException
from sql.run import query2sql
app = FastAPI()
@app.post("/query2sql/")
async def din_query2sql(query_body: Mapping[str, Any]):
if 'queryText' not in query_body:
raise HTTPException(status_code=400,
detail="query_text is not in query_body")
else:
query_text = query_body['queryText']
if 'schema' not in query_body:
raise HTTPException(status_code=400, detail="schema is not in query_body")
else:
schema = query_body['schema']
resp = query2sql(query_text=query_text, schema=schema)
return resp

View File

@@ -0,0 +1,147 @@
examplars = [
{
"table_name": "内容库产品",
"fields_list": """["部门", "模块", "用户名", "访问次数", "访问人数", "访问时长"]""",
"question": "比较jerryjzhang和lexluo在内容库的访问次数",
"analysis": """让我们一步一步地思考。在问题“比较jerryjzhang和lexluo在内容库的访问次数“中我们被问
“比较jerryjzhang和lexluo”所以我们需要column=[用户名]
”内容库的访问次数“所以我们需要column=[访问次数]
基于table和columns可能的cell values 是 = ['jerryjzhang', 'lexluo']。""",
"schema_links": """["用户名", "访问次数", "'jerryjzhang'", "'lexluo'"]""",
"sql": """select 用户名, 访问次数 from 内容库产品 where 用户名 in ('jerryjzhang', 'lexluo')"""
},
{
"table_name": "内容库产品",
"fields_list": """["部门", "模块", "用户名", "访问次数", "访问人数", "访问时长"]""",
"question": "内容库近12个月访问人数 按部门",
"analysis": """让我们一步一步地思考。在问题“内容库近12个月访问人数 按部门“中,我们被问:
“内容库近12个月访问人数”所以我们需要column=[访问人数]
”按部门“所以我们需要column=[部门]
基于table和columns可能的cell values 是 = []。""",
"schema_links": """["访问人数", "部门"]""",
"sql": """select 部门, sum(访问人数) from 内容库产品 where 部门 group by 部门"""
},
{
"table_name": "内容库产品",
"fields_list": """["部门", "模块", "用户名", "访问次数", "访问人数", "访问时长"]""",
"question": "内容库内容合作部、生态业务部的访问时长",
"analysis": """让我们一步一步地思考。在问题“内容库内容合作部、生态业务部的访问时长“中,我们被问:
“访问时长”所以我们需要column=[访问时长]
”内容库内容合作部、生态业务部“所以我们需要column=[部门]
基于table和columns可能的cell values 是 = ['内容合作部', '生态业务部']。""",
"schema_links": """["访问时长", "部门", "'内容合作部'", "'生态业务部'"]""",
"sql": """select 部门, 访问时长 from 内容库产品 where 部门 in ('内容合作部', '生态业务部')"""
},
{
"table_name": "优选",
"fields_list": """['优选版权归属系', '付费模式', '结算播放份额', '付费用户结算播放份额']""",
"question": "近3天阔景系TME结算播放份额",
"analysis": """让我们一步一步地思考。在问题“近3天阔景系TME结算播放份额“中我们被问
“TME结算播放份额”所以我们需要column=[结算播放份额]
”阔景系“所以我们需要column=[优选版权归属系]
基于table和columns可能的cell values 是 = ['阔景系']。""",
"schema_links": """["结算播放份额", "优选版权归属系", "'阔景系'"]""",
"sql": """select 优选版权归属系, 结算播放份额 from 优选 where 优选版权归属系 in ('阔景系')"""
},
{
"table_name": "歌曲库",
"fields_list": """['是否音乐人歌曲', 'Q音歌曲ID', 'Q音歌曲MID', '歌曲名', '歌曲版本', '歌曲类型', '翻唱类型', 'TME歌曲ID', '是否优选窄口径歌曲', '是否优选宽口径歌曲', '结算播放量', '运营播放量', '付费用户结算播放量', '历史累计结算播放量', '运营搜播量', '结算搜播量', '运营完播量', '运营推播量', '近7日复播率', '日均搜播量']""",
"question": "对比近3天翻唱版和纯音乐的歌曲播放量",
"analysis": """让我们一步一步地思考。在问题“对比近3天翻唱版和纯音乐的歌曲播放量“中我们被问
“歌曲播放量”所以我们需要column=[结算播放量]
”翻唱版和纯音乐的歌曲“所以我们需要column=[歌曲类型]
基于table和columns可能的cell values 是 = ['翻唱版', '纯音乐']。""",
"schema_links": """["结算播放量", "歌曲类型", "'翻唱版'", "'纯音乐'"]""",
"sql": """select 歌曲类型, 结算播放量 from 歌曲库 where 歌曲类型 in ('翻唱版', '纯音乐')"""
},
{
"table_name": "艺人库",
"fields_list": """['上下架状态', '歌手名', '歌手等级', '歌手类型', '歌手来源', 'TME音乐人等级', '活跃区域', '年龄', '歌手才能', '歌手风格', '粉丝数', '抖音粉丝数', '网易粉丝数', '微博粉丝数', '网易歌曲数', '在架歌曲数', '网易分享数', '独占歌曲数', '网易在架歌曲评论数', '有播放量歌曲数']""",
"question": "对比一下陈卓璇、孟美岐、赖美云的粉丝数",
"analysis": """让我们一步一步地思考。在问题“对比一下陈卓璇、孟美岐、赖美云的粉丝数“中,我们被问:
“粉丝数”所以我们需要column=[粉丝数]
”陈卓璇、孟美岐、赖美云“所以我们需要column=[歌手名]
基于table和columns可能的cell values 是 = ['陈卓璇', '孟美岐', '赖美云']。""",
"schema_links": """["粉丝数", "歌手名", "'陈卓璇'", "'孟美岐'", "'赖美云'"]""",
"sql": """select 歌手名, 粉丝数 from 艺人库 where 歌手名 in ('陈卓璇', '孟美岐', '赖美云')"""
},
{
"table_name": "歌曲库",
"fields_list": """['歌曲名', '歌曲版本', '歌曲类型', 'TME歌曲ID', '是否优选窄口径歌曲', '是否优选宽口径歌曲', '是否音乐人歌曲', '网易歌曲ID', 'Q音歌曲ID', 'Q音歌曲MID', '结算播放量', '运营播放量', '分享量', '收藏量', '运营搜播量', '结算搜播量', '拉新用户数', '拉活用户数', '分享率', '结算播放份额']""",
"question": "播放量大于1万的歌曲有多少",
"analysis": """让我们一步一步地思考。在问题“播放量大于1万的歌曲有多少“中我们被问
“歌曲有多少”所以我们需要column=[歌曲名]
”播放量大于1万的“所以我们需要column=[结算播放量]
基于table和columns可能的cell values 是 = [10000]。""",
"schema_links": """["歌曲名", "结算播放量", 10000]""",
"sql": """select 歌曲名 from 歌曲库 where 结算播放量 > 10000"""
},
{
"table_name": "内容库产品",
"fields_list": """['用户名', '部门', '模块', '访问时长', '访问次数', '访问人数']""",
"question": "内容库访问时长小于1小时且来自内容合作部的用户是哪些",
"analysis": """让我们一步一步地思考。在问题“内容库访问时长小于1小时且来自内容合作部的用户是哪些“中我们被问
“用户是哪些”所以我们需要column=[用户名]
”内容合作部的“所以我们需要column=[部门]
”访问时长小于1小时“所以我们需要column=[访问时长]
基于table和columns可能的cell values 是 = ['内容合作部', 1]。""",
"schema_links": """["用户名", "部门", "访问时长", "'内容合作部'", 1]""",
"sql": """select 用户名 from 内容库产品 where 部门 = '内容合作部' and 访问时长 < 1"""
},
{
"table_name": "内容库产品",
"fields_list": """['用户名', '部门', '模块', '访问次数', '访问人数', '访问时长']""",
"question": "内容库pv最高的用户有哪些",
"analysis": """让我们一步一步地思考。在问题“内容库pv最高的用户有哪些“中我们被问
“用户有哪些”所以我们需要column=[用户名]
”pv最高的“所以我们需要column=[访问次数]
基于table和columns可能的cell values 是 = []。""",
"schema_links": """["用户名", "访问次数"]""",
"sql": """select 用户名 from 内容库产品 order by 访问次数 desc limit 10"""
},
{
"table_name": "艺人库",
"fields_list": """['播放量层级', '播放量单调性', '播放量方差', '播放量突增类型', '播放量集中度', '歌手名', '歌手等级', '歌手类型', '歌手来源', 'TME音乐人等级', '结算播放量', '运营播放量', '历史累计结算播放量', '有播放量歌曲数', '历史累计运营播放量', '付费用户结算播放量', '结算播放量占比', '运营播放份额', '免费用户结算播放占比', '完播量']""",
"question": "近90天袁娅维播放量平均值是多少",
"analysis": """让我们一步一步地思考。在问题“近90天袁娅维播放量平均值是多少“中我们被问
“播放量平均值是多少”所以我们需要column=[结算播放量]
”袁娅维“所以我们需要column=[歌手名]
基于table和columns可能的cell values 是 = ['袁娅维']。""",
"schema_links": """["结算播放量", "歌手名", "'袁娅维'"]""",
"sql": """select avg(结算播放量) from 艺人库 where 歌手名 = '袁娅维'"""
},
{
"table_name": "艺人库",
"fields_list": """['播放量层级', '播放量单调性', '播放量方差', '播放量突增类型', '播放量集中度', '歌手名', '歌手等级', '歌手类型', '歌手来源', 'TME音乐人等级', '结算播放量', '历史累计结算播放量', '付费用户结算播放量', '结算播放量占比', '免费用户结算播放占比', '付费用户结算播放占比', '付费用户结算播放占比', '运营播放量', '有播放量歌曲数', '历史累计运营播放量']""",
"question": "周深近7天结算播放量总和是多少",
"analysis": """让我们一步一步地思考。在问题“周深近7天结算播放量总和是多少“中我们被问
“结算播放量总和是多少”所以我们需要column=[结算播放量]
”周深“所以我们需要column=[歌手名]
基于table和columns可能的cell values 是 = ['周深']。""",
"schema_links": """["结算播放量", "歌手名", "'周深'"]""",
"sql": """select sum(结算播放量) from 艺人库 where 歌手名 = '周深'"""
},
{
"table_name": "内容库产品",
"fields_list": """['部门', '模块', '用户名', '访问次数', '访问人数', '访问时长']""",
"question": "内容库访问次数大于1k的部门是哪些",
"analysis": """让我们一步一步地思考。在问题“内容库访问次数大于1k的部门是哪些“中我们被问
“部门是哪些”所以我们需要column=[部门]
”访问次数大于1k的“所以我们需要column=[访问次数]
基于table和columns可能的cell values 是 = [1000]。""",
"schema_links": """["部门", "访问次数", 1000]""",
"sql": """select 部门 from 内容库产品 where 访问次数 > 1000"""
},
{
"table_name": "歌曲库",
"fields_list": """['歌曲名', '歌手名' , '歌曲版本', '歌曲类型', 'TME歌曲ID', '是否优选窄口径歌曲', '是否优选宽口径歌曲', '是否音乐人歌曲', '网易歌曲ID', 'Q音歌曲ID', 'Q音歌曲MID', '结算播放量', '运营播放量', '分享量', '收藏量', '运营搜播量', '结算搜播量', '拉新用户数', '拉活用户数', '分享率', '结算播放份额']""",
"question": "陈奕迅唱的所有的播放量大于20k的孤勇者有哪些",
"analysis": """让我们一步一步地思考。在问题“陈奕迅唱的所有的播放量大于20k的孤勇者有哪些“中我们被问
“孤勇者有哪些”所以我们需要column=[歌曲名]
”播放量大于20k的“所以我们需要column=[结算播放量]
”陈奕迅唱的“所以我们需要column=[歌手名]
基于table和columns可能的cell values 是 = [20000, '陈奕迅']。""",
"schema_links": """["歌曲名", "结算播放量", "歌手名", 20000, "'陈奕迅'"]""",
"sql": """select 歌曲名 from 歌曲库 where 结算播放量 > 20000 and 歌手名 = '陈奕迅'"""
}
]

View File

@@ -0,0 +1,15 @@
# -*- coding:utf-8 -*-
import re
def schema_link_parse(schema_link_output):
try:
schema_link_output = schema_link_output.strip()
pattern = r'Schema_links:(.*)'
schema_link_output = re.findall(pattern, schema_link_output, re.DOTALL)[
0].strip()
except Exception as e:
print(e)
schema_link_output = None
return schema_link_output

View File

@@ -0,0 +1,88 @@
# -*- coding:utf-8 -*-
from typing import Any, List, Mapping, Optional, Union
import requests
import logging
import json
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from langchain.prompts import PromptTemplate
from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.llms import OpenAI
from few_shot_example.sql_exampler import examplars
from output_parser import schema_link_parse
def schema_linking_prompt_maker(user_query: str, domain_name: str,
fields_list: List[str],
few_shots_example: str):
instruction = "# 根据数据库的表结构,找出为每个问题生成SQL查询语句的schema_links\n"
schema_linking_prompt = "Table {table_name}, columns = {fields_list}\n问题:{user_query}\n分析: 让我们一步一步地思考。".format(
table_name=domain_name,
fields_list=fields_list,
user_query=user_query)
return instruction + few_shots_example + schema_linking_prompt
def schema_linking_exampler(user_query: str,
domain_name: str,
fields_list: List[str]
) -> str:
example_prompt_template = PromptTemplate(
input_variables=["table_name", "fields_list", "question", "analysis",
"schema_links"],
template="Table {table_name}, columns = {fields_list}\n问题:{question}\n分析:{analysis} 所以Schema_links是:\nSchema_links:{schema_links}")
instruction = "# 根据数据库的表结构,找出为每个问题生成SQL查询语句的schema_links"
schema_linking_prompt = "Table {table_name}, columns = {fields_list}\n问题:{question}\n分析: 让我们一步一步地思考。"
schema_linking_example_prompt_template = FewShotPromptTemplate(
examples=examplars,
example_prompt=example_prompt_template,
example_separator="\n\n",
prefix=instruction,
input_variables=["table_name", "fields_list", "question"],
suffix=schema_linking_prompt
)
schema_linking_example_prompt = schema_linking_example_prompt_template.format(
table_name=domain_name,
fields_list=fields_list,
question=user_query)
return schema_linking_example_prompt
def sql_exampler(user_query: str,
domain_name: str,
schema_link_str: str
) -> str:
instruction = "# 根据schema_links为每个问题生成SQL查询语句"
sql_example_prompt_template = PromptTemplate(
input_variables=["question", "table_name", "schema_links", "sql"],
template="问题:{question}\nTable {table_name}\nSchema_links:{schema_links}\nSQL:{sql}")
sql_prompt = "问题:{question}\nTable {table_name}\nSchema_links:{schema_links}\nSQL:"
sql_example_prompt_template = FewShotPromptTemplate(
examples=examplars,
example_prompt=sql_example_prompt_template,
example_separator="\n\n",
prefix=instruction,
input_variables=["question", "table_name", "schema_links"],
suffix=sql_prompt
)
sql_example_prompt = sql_example_prompt_template.format(question=user_query,
table_name=domain_name,
schema_links=schema_link_str)
return sql_example_prompt

View File

@@ -0,0 +1,48 @@
# -*- coding:utf-8 -*-
from typing import List, Union
import logging
import json
import os
import sys
from langchain.llms import OpenAI
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from sql.prompt_maker import schema_linking_exampler, schema_link_parse, \
sql_exampler
MODEL_NAME = "gpt-3.5-turbo-16k"
OPENAI_API_KEY = "YOUR_API_KEY"
TEMPERATURE = 0.0
llm = OpenAI(openai_api_key=OPENAI_API_KEY, model_name=MODEL_NAME,
temperature=TEMPERATURE)
def query2sql(query_text: str, schema: dict):
print("schema: ", schema)
domain_name = schema['domainName']
fields_list = schema['fieldNameList']
schema_linking_prompt = schema_linking_exampler(query_text, domain_name,
fields_list)
schema_link_output = llm(schema_linking_prompt)
schema_link_str = schema_link_parse(schema_link_output)
sql_prompt = sql_exampler(query_text, domain_name, schema_link_str)
sql_output = llm(sql_prompt)
resp = dict()
resp['query'] = query_text
resp['domain'] = domain_name
resp['fields'] = fields_list
resp['schemaLinkingOutput'] = schema_link_output
resp['schemaLinkStr'] = schema_link_str
resp['sqlOutput'] = sql_output
return resp

View File

@@ -0,0 +1,8 @@
langchain==0.0.207
openai==0.27.4
fastapi==0.95.1
chromadb==0.3.21
tiktoken==0.3.3
uvicorn[standard]==0.21.1

View File

@@ -9,10 +9,8 @@
type="com.tencent.supersonic.chat.domain.dataobject.ChatConfigDO">
<id column="id" property="id"/>
<result column="domain_id" property="domainId"/>
<result column="default_metrics" property="defaultMetrics"/>
<result column="visibility" property="visibility"/>
<result column="entity_info" property="entity"/>
<result column="dictionary_info" property="knowledgeInfo"/>
<result column="chat_detail_config" property="chatDetailConfig"/>
<result column="chat_agg_config" property="chatAggConfig"/>
<result column="status" property="status"/>
<result column="created_by" property="createdBy"/>
<result column="updated_by" property="updatedBy"/>
@@ -25,11 +23,11 @@
useGeneratedKeys="true" keyProperty="id">
insert into s2_chat_config
(
domain_id, `default_metrics`, visibility, entity_info, dictionary_info, status, created_by, updated_by, created_at, updated_at
domain_id, `chat_detail_config`, chat_agg_config, status, created_by, updated_by, created_at, updated_at
)
values
(
#{domainId}, #{defaultMetrics}, #{visibility}, #{entity}, #{knowledgeInfo}, #{status}, #{createdBy}, #{updatedBy}, #{createdAt}, #{updatedAt}
#{domainId}, #{chatDetailConfig}, #{chatAggConfig}, #{status}, #{createdBy}, #{updatedBy}, #{createdAt}, #{updatedAt}
)
</insert>
@@ -38,18 +36,11 @@
update s2_chat_config
<set>
`updated_at` = #{updatedAt} ,
<if test="defaultMetrics != null and defaultMetrics != ''">
`default_metrics` = #{defaultMetrics} ,
<if test="chatDetailConfig != null and chatDetailConfig != ''">
`chat_detail_config` = #{chatDetailConfig} ,
</if>
<if test="visibility != null and visibility != ''">
visibility = #{visibility} ,
</if>
<if test="entity != null and entity != ''">
entity_info = #{entity} ,
</if>
<if test="knowledgeInfo != null and knowledgeInfo != ''">
`dictionary_info` = #{knowledgeInfo} ,
<if test="chatAggConfig != null and chatAggConfig != ''">
chat_agg_config = #{chatAggConfig} ,
</if>
<if test="status != null and status != ''">
status = #{status} ,
@@ -90,7 +81,8 @@
select *
from s2_chat_config
where domain_id = #{domainId}
order by status
and status != 3
order by updated_at desc
limit 1
</select>

View File

@@ -1,28 +0,0 @@
package com.tencent.supersonic.chat.domain.utils;
import com.tencent.supersonic.semantic.api.core.enums.TimeDimensionEnum;
import java.text.MessageFormat;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
/**
* @author lex luo
* @date 2023/6/29 16:05
*/
class DslToSemanticInfoTest {
@Test
void search() {
Integer domainId = 1;
String dayField = TimeDimensionEnum.DAY.getName();
String startDate = "2023-04-01";
String endDate = "2023-06-01";
String format = MessageFormat.format(DslToSemanticInfo.SUB_TABLE, domainId, dayField, startDate, endDate);
Assert.assertEquals(format,
" ( select * from t_1 where sys_imp_date >= '2023-04-01' and sys_imp_date <= '2023-06-01' ) as t_sub_1");
}
}

View File

@@ -13,8 +13,8 @@ import com.tencent.supersonic.semantic.api.core.response.DomainSchemaResp;
import com.tencent.supersonic.semantic.api.core.response.MetricResp;
import com.tencent.supersonic.semantic.api.core.response.MetricSchemaResp;
import com.tencent.supersonic.chat.application.ConfigServiceImpl;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichInfo;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigResp;
import com.tencent.supersonic.chat.domain.pojo.config.ChatConfigRichResp;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetric;
import com.tencent.supersonic.chat.domain.pojo.config.DefaultMetricInfo;
import com.tencent.supersonic.chat.domain.pojo.config.EntityInternalDetail;
@@ -47,17 +47,17 @@ public class MockBeansConfiguration {
public static void buildHttpSemanticServiceImpl(SemanticLayer httpSemanticLayer, List<DimSchemaResp> dimensionDescs,
List<MetricSchemaResp> metricDescs) {
ChatConfigRichInfo chaConfigRichDesc = new ChatConfigRichInfo();
ChatConfigRichResp chaConfigRichDesc = new ChatConfigRichResp();
DefaultMetric defaultMetricDesc = new DefaultMetric();
defaultMetricDesc.setUnit(3);
defaultMetricDesc.setPeriod(Constants.DAY);
chaConfigRichDesc.setDefaultMetrics(new ArrayList<>(Arrays.asList(defaultMetricDesc)));
// chaConfigRichDesc.setDefaultMetrics(new ArrayList<>(Arrays.asList(defaultMetricDesc)));
EntityRichInfo entityDesc = new EntityRichInfo();
List<DimSchemaResp> dimensionDescs1 = new ArrayList<>();
DimSchemaResp dimensionDesc = new DimSchemaResp();
dimensionDesc.setId(162L);
dimensionDescs1.add(dimensionDesc);
entityDesc.setEntityIds(dimensionDescs1);
// entityDesc.setEntityIds(dimensionDescs1);
DimSchemaResp dimensionDesc2 = new DimSchemaResp();
dimensionDesc2.setId(163L);
@@ -71,14 +71,14 @@ public class MockBeansConfiguration {
metricDesc.setBizName("js_play_cnt");
metricDesc.setName("结算播放量");
entityInternalDetailDesc.setMetricList(new ArrayList<>(Arrays.asList(metricDesc)));
entityDesc.setEntityInternalDetailDesc(entityInternalDetailDesc);
// entityDesc.setEntityInternalDetailDesc(entityInternalDetailDesc);
chaConfigRichDesc.setEntity(entityDesc);
// chaConfigRichDesc.setEntity(entityDesc);
// when(httpSemanticLayer.getChatConfigRichInfo(anyLong())).thenReturn(chaConfigRichDesc);
DomainSchemaResp domainSchemaDesc = new DomainSchemaResp();
domainSchemaDesc.setDimensions(dimensionDescs);
domainSchemaDesc.setMetrics(metricDescs);
when(httpSemanticLayer.getDomainSchemaInfo(anyLong())).thenReturn(domainSchemaDesc);
// when(httpSemanticLayer.getDomainSchemaInfo(anyLong())).thenReturn(domainSchemaDesc);
DomainInfos domainInfos = new DomainInfos();
when(SchemaInfoConverter.convert(httpSemanticLayer.getDomainSchemaInfo(anyList()))).thenReturn(domainInfos);
@@ -92,8 +92,8 @@ public class MockBeansConfiguration {
List<DefaultMetricInfo> defaultMetricInfos = new ArrayList<>();
defaultMetricInfos.add(defaultMetricInfo);
ChatConfigInfo chaConfigDesc = new ChatConfigInfo();
chaConfigDesc.setDefaultMetrics(defaultMetricInfos);
ChatConfigResp chaConfigDesc = new ChatConfigResp();
// chaConfigDesc.setDefaultMetrics(defaultMetricInfos);
when(configService.fetchConfigByDomainId(anyLong())).thenReturn(chaConfigDesc);
}

View File

@@ -14,8 +14,12 @@ import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.seg.common.Vertex;
import com.hankcs.hanlp.seg.common.WordNet;
import com.hankcs.hanlp.utility.TextUtility;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.*;
public abstract class WordBasedSegment extends Segment {

View File

@@ -6,12 +6,15 @@ import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.dictionary.CoreDictionary;
import com.hankcs.hanlp.dictionary.DynamicCustomDictionary;
import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.tencent.supersonic.common.nlp.MapResult;
import com.tencent.supersonic.common.nlp.NatureType;
import com.tencent.supersonic.common.nlp.WordNature;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
@@ -173,5 +176,10 @@ public class HanlpHelper {
}
}
public static List<Term> getTerms(String text) {
return getSegment().seg(text.toLowerCase()).stream()
.filter(term -> term.getNature().startsWith(NatureType.NATURE_SPILT))
.collect(Collectors.toList());
}
}