[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

2
.gitignore vendored
View File

@@ -14,4 +14,4 @@ assembly/runtime/*
*.umi/
/assembly/deploy
/runtime
.flattened-pom.xml
**/.flattened-pom.xml

View File

@@ -8,3 +8,14 @@ davinci 0.3.0 change log
7) optimize css style
8) optimize filter
9) delete view module
supersonic 0.6.0 change log
1) add llm parser and llm api server
2) support fuzzy mapping
3) support query filter and domain filter in query and search
4) support standalone mode
5) add dsl query in semantic
6) code architecture adjustment in semantic and chat
7) add unit testing and integration testing
8) support dimension and metric alias

View File

@@ -4,6 +4,7 @@ English | [中文](README_CN.md)
**SuperSonic is an out-of-the-box yet highly extensible framework for building a data chatbot**. SuperSonic provides a chat interface that empowers users to query data using natural language and visualize the results with suitable charts. To enable such experience, the only thing necessary is to define logical semantic models (metrics, dimensions, relationships, etc) on top of physical data models, and no data modification or copying is required. Meanwhile SuperSonic is designed to be plugable, allowing new functionalities to be added through plugins and core components to be integrated into other systems.
<img src="./docs/images/supersonic_demo.gif" align="center"/>
## Motivation
@@ -28,8 +29,10 @@ With these ideas in mind, we developed SuperSonic as a reference implementation
SuperSonic is composed of two layers: supersonic-chat and supersonic-semantic. The chat layer is responsible for converting **natural language query** into semantic query (also known as DSL query), whereas the semantic layer is responsible for converting DSL query into **SQL query**. The high-level architecture and main process flow is shown in below diagram:
<img src="./docs/images/supersonic_components.png" height="80%" width="80%" align="center"/>
### Chat Layer
The chat layer contains four core components:

12
assembly/bin/build-chat.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
sbinDir=$(cd "$(dirname "$0")"; pwd)
baseDir=$(readlink -f $sbinDir/../)
runtimeDir=$baseDir/runtime
buildDir=$baseDir/build
cd $baseDir
#1. move package to build
cp $baseDir/../launchers/chat/target/*.tar.gz ${buildDir}/supersonic-chat.tar.gz

View File

@@ -7,14 +7,13 @@ buildDir=$baseDir/build
cd $baseDir
#1. build semantic chat service
#1. build semantic service
rm -fr ${buildDir}/*.tar.gz
rm -fr dist
mvn -f $baseDir/../ clean package -DskipTests
#2. move package to build
cp $baseDir/../launchers/chat/target/*.tar.gz ${buildDir}/supersonic-chat.tar.gz
cp $baseDir/../launchers/semantic/target/*.tar.gz ${buildDir}/supersonic-semantic.tar.gz
#3. build webapp

35
assembly/bin/start-chat.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
sbinDir=$(cd "$(dirname "$0")"; pwd)
baseDir=$(readlink -f $sbinDir/../)
runtimeDir=$baseDir/../runtime
buildDir=$baseDir/build
cd $baseDir
#2. package lib
tar -zxvf ${buildDir}/supersonic-chat.tar.gz -C ${runtimeDir}
mv ${runtimeDir}/launchers-chat-* ${runtimeDir}/supersonic-chat
tar -zxvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
mkdir -p ${runtimeDir}/supersonic-chat/webapp
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-chat/webapp
rm -fr ${buildDir}/supersonic-webapp
json=$(cat ${runtimeDir}/supersonic-chat/webapp/supersonic.config.json)
json=$(echo $json | jq '.env="chat"')
echo $json > ${runtimeDir}/supersonic-chat/webapp/supersonic.config.json
#3. start service
#3.1 start chat service
echo ${runtimeDir}
sh ${runtimeDir}/supersonic-chat/bin/service.sh restart
#3.2 start llm service
sh ${runtimeDir}/supersonic-chat/llm/bin/service.sh restart

View File

@@ -14,23 +14,23 @@ rm -fr ${runtimeDir}/*
#2. package lib
tar -zxvf ${buildDir}/supersonic-semantic.tar.gz -C ${runtimeDir}
tar -zxvf ${buildDir}/supersonic-chat.tar.gz -C ${runtimeDir}
mv ${runtimeDir}/launchers-chat-* ${runtimeDir}/supersonic-chat
mv ${runtimeDir}/launchers-semantic-* ${runtimeDir}/supersonic-semantic
tar -zxvf ${buildDir}/supersonic-webapp.tar.gz -C ${buildDir}
mkdir -p ${runtimeDir}/supersonic-semantic/webapp
mkdir -p ${runtimeDir}/supersonic-chat/webapp
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-semantic/webapp
cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-chat/webapp
rm -fr ${buildDir}/supersonic-webapp
json=$(cat ${runtimeDir}/supersonic-semantic/webapp/supersonic.config.json)
json=$(echo $json | jq '.env="semantic"')
echo $json > ${runtimeDir}/supersonic-semantic/webapp/supersonic.config.json
#3. start service
sh ${runtimeDir}/supersonic-semantic/bin/service.sh restart
sleep 5
sh ${runtimeDir}/supersonic-chat/bin/service.sh restart

View File

@@ -26,5 +26,7 @@ cp -fr ${buildDir}/supersonic-webapp/* ${runtimeDir}/supersonic-standalone/weba
rm -fr ${buildDir}/supersonic-webapp
#3. start service
#start standalone service
sh ${runtimeDir}/supersonic-standalone/bin/service.sh restart
#start llm service
sh ${runtimeDir}/supersonic-standalone/llm/bin/service.sh restart

View File

@@ -28,6 +28,12 @@
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/../../chat/core/src/main/python</directory>
<outputDirectory>llm</outputDirectory>
<fileMode>0777</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
</fileSets>
<dependencySets>

View File

@@ -2,6 +2,7 @@ package com.tencent.supersonic.auth.authentication.domain.interceptor;
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
import com.tencent.supersonic.auth.authentication.application.UserServiceImpl;
import com.tencent.supersonic.auth.authentication.domain.utils.UserTokenUtils;
@@ -27,11 +28,12 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
userTokenUtils = ContextUtils.getBean(UserTokenUtils.class);
s2ThreadContext = ContextUtils.getBean(S2ThreadContext.class);
if (!authenticationConfig.isEnabled()) {
setFakerUser(request);
return true;
}
if (isInternalRequest(request)) {
String token = userTokenUtils.generateAdminToken();
reflectSetparam(request, authenticationConfig.getTokenHttpHeaderKey(), token);
setFakerUser(request);
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
@@ -47,15 +49,25 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
UserWithPassword user = userTokenUtils.getUserWithPassword(request);
if (StringUtils.isNotBlank(user.getName())) {
ThreadContext threadContext = ThreadContext.builder()
.token(request.getHeader(authenticationConfig.getTokenHttpHeaderKey()))
.userName(user.getName())
.build();
s2ThreadContext.set(threadContext);
setContext(user.getName(), request);
return true;
}
throw new AccessException("authentication failed, please login");
}
private void setFakerUser(HttpServletRequest request) {
String token = userTokenUtils.generateAdminToken();
reflectSetparam(request, authenticationConfig.getTokenHttpHeaderKey(), token);
setContext(User.getFakeUser().getName(), request);
}
private void setContext(String userName, HttpServletRequest request) {
ThreadContext threadContext = ThreadContext.builder()
.token(request.getHeader(authenticationConfig.getTokenHttpHeaderKey()))
.userName(userName)
.build();
s2ThreadContext.set(threadContext);
}
}

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,
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,29 +131,108 @@ 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) {
if (CollectionUtils.isEmpty(knowledgeInfos)) {
@@ -240,26 +246,17 @@ 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);
}

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,27 +76,36 @@ 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) {
private EntityInfo getEntityInfo(ChatConfigRichResp chaConfigRichDesc) {
EntityInfo entityInfo = new EntityInfo();
if (entityDesc != null && Objects.nonNull(entityDesc.getDomainId())) {
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()) {
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());
@@ -105,7 +113,10 @@ public class DomainEntityService {
dimensions.add(mainEntityDimension);
}
entityInfo.setDimensions(dimensions);
for (MetricSchemaResp metricDesc : entityDesc.getEntityInternalDetailDesc().getMetricList()) {
}
if(!CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())){
for (SchemaItem metricDesc : chatDefaultConfig.getMetrics()) {
DataInfo dataInfo = new DataInfo();
dataInfo.setName(metricDesc.getName());
dataInfo.setBizName(metricDesc.getBizName());
@@ -115,6 +126,7 @@ public class DomainEntityService {
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());
}
@@ -146,7 +147,8 @@ public class SearchServiceImpl implements SearchService {
boolean existMetricAndDimension,
MatchText matchText,
Map<String, String> natureToNameMap,
Map.Entry<String, String> natureToNameEntry) {
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,37 +161,14 @@ 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,
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()))
@@ -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;
}
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);
}
}
}
return matchedQueries;
}
}

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,13 +42,18 @@ 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;
}
try {
Integer domainId = getDomainId(queryContext, chatCtx);
LLMResp llmResp = requestLLM(queryContext, domainId);
if (Objects.isNull(llmResp)) {
@@ -54,23 +61,32 @@ public class LLMSemanticParser implements SemanticParser {
}
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);
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);
}
}
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);
if (StringUtils.isEmpty(llmConfig.getUrl())) {
log.warn("llmConfig url is null, skip llm parser");
return null;
}
DomainInfos domainInfos = ContextUtils.getBean(WordNatureService.class).getCache().getUnchecked("");
Map<Integer, String> domainIdToName = domainInfos.getDomains().stream()
@@ -86,7 +102,7 @@ public class LLMSemanticParser implements SemanticParser {
List<SchemaElementMatch> matchedElements = queryContext.getMapInfo().getMatchedElements(domainId);
List<String> fieldNameList = matchedElements.stream()
Set<String> fieldNameList = matchedElements.stream()
.filter(schemaElementMatch ->
SchemaElementType.METRIC.equals(schemaElementMatch.getElementType()) ||
SchemaElementType.DIMENSION.equals(schemaElementMatch.getElementType()) ||
@@ -98,14 +114,14 @@ public class LLMSemanticParser implements SemanticParser {
return itemIdToName.get(schemaElementMatch.getElementID());
})
.filter(name -> StringUtils.isNotEmpty(name) && !name.contains("%"))
.collect(Collectors.toList());
.collect(Collectors.toSet());
LLMSchema llmSchema = new LLMSchema();
llmSchema.setDomainName(domainName);
llmSchema.setFieldNameList(fieldNameList);
llmSchema.setFieldNameList(new ArrayList<>(fieldNameList));
llmReq.setSchema(llmSchema);
log.info("domainId:{},llmReq:{}", domainId, llmReq);
log.info("requestLLM request, domainId:{},llmReq:{}", domainId, llmReq);
String questUrl = llmConfig.getUrl() + llmConfig.getQueryToSqlPath();
RestTemplate restTemplate = ContextUtils.getBean(RestTemplate.class);
@@ -114,16 +130,12 @@ public class LLMSemanticParser implements SemanticParser {
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);
log.info("requestLLM response, questUrl:{} \n entity:{} \n body:{}", questUrl, entity,
responseEntity.getBody());
return responseEntity.getBody();
} catch (Exception e) {
log.error("requestLLM error", e);
}
return null;
}
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) {
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) -> {
DimSchemaResp dimItem = entity.getDimItem();
if (Objects.nonNull(entity) && Objects.nonNull(dimItem)) {
SchemaItem dimension = new SchemaItem();
BeanUtils.copyProperties(dimSchemaDesc, dimension);
BeanUtils.copyProperties(dimItem, dimension);
dimensions.add(dimension);
primaryDimensions.add(dimSchemaDesc.getBizName());
});
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());
}

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,
public static void setEntityId(Long dimensionId, String value, ChatConfigRichResp 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)) {
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())) {
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(),
chatFilter.getValue().toString(), SchemaElementType.VALUE));
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,57 +36,74 @@ 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,
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;
// 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());
} 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();
}
fillThemeDefaultMetricLogic(semanticParseInfo, chaConfigRichDesc, queryContext);
}
if (isAddEntityDetailDimensionMetric) {
if (chaConfigRichDesc == null) {
chaConfigRichDesc = getChatConfigRichInfo(semanticParseInfo.getDomainId());
if (isFillAggDefaultMetricLogic) {
fillDefaultMetricAggLogic(semanticParseInfo, chaConfigRichDesc, queryContext);
}
if (isFillDetailDimensionMetric) {
addEntityDetailDimensionMetric(semanticParseInfo, chaConfigRichDesc, queryContext, chatContext);
}
fillDateDomain(semanticParseInfo, chatContext, chaConfigRichDesc, queryContext);
}
fillDateDomain(semanticParseInfo, chatContext, chaConfigRichDesc, chatDefaultConfig, isDetailMode);
// }
defaultQueryMode(semanticParseInfo, queryContext, chatContext);
addEntityTopDimension(semanticParseInfo, chaConfigRichDesc);
}
@@ -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 -> {
DimSchemaResp dimItem = entity.getDimItem();
SchemaItem dimension = new SchemaItem();
//BeanUtils.copyProperties(dimSchemaDesc, dimension);
dimension.setName(dimSchemaDesc.getName());
dimension.setBizName(dimSchemaDesc.getBizName());
dimension.setId(dimSchemaDesc.getId());
BeanUtils.copyProperties(dimItem, dimension);
dimensions.add(dimension);
primaryDimensions.add(dimSchemaDesc.getBizName());
});
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,37 +139,49 @@ 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,
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");
if (CollectionUtils.isEmpty(semanticParseInfo.getDimensions())) {
Set<SchemaItem> dimensions = new LinkedHashSet();
chaConfigRichDesc.getEntity().getEntityInternalDetailDesc().getDimensionList().stream()
.forEach(m -> dimensions.add(getDimension(m)));
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);
}
}
}
}
@@ -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();
if (isDetailMode) {
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());
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() {
}
@@ -129,38 +131,59 @@ public class DictMetaUtils {
private void fillDimValueDOList(List<DimValueDO> dimValueDOList, Long domainId,
Map<Long, DimSchemaResp> dimIdAndDescPair) {
ChatConfigRichInfo chaConfigRichDesc = defaultSemanticUtils.getChatConfigRichInfo(domainId);
if (Objects.nonNull(chaConfigRichDesc)) {
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();
List<KnowledgeInfo> knowledgeDetailInfo = chaConfigRichDesc.getChatDetailRichConfig().getKnowledgeInfos();
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.getIsDictInfo()
&& isVisibleDim(knowledgeInfo, chaConfigRichDesc.getVisibility()))
.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 (CollectionUtils.isEmpty(defaultMetricDescList)) {
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()));
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)
@@ -170,7 +193,6 @@ public class DictMetaUtils {
}
}
}
}
private boolean isVisibleDim(KnowledgeInfo knowledgeInfo, ItemVisibilityInfo itemVisibilityDesc) {
if (Objects.isNull(itemVisibilityDesc) || CollectionUtils.isEmpty(itemVisibilityDesc.getBlackDimIdList())) {

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;
@@ -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) {
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,12 +38,12 @@ public class ChatConfigController {
@Autowired
private ConfigService configService;
@Autowired
private DefaultSemanticInternalUtils defaultSemanticUtils;
private SemanticLayer semanticLayer = ComponentFactory.getSemanticLayer();
@PostMapping
public Long addChatConfig(@RequestBody ChatConfigBase extendBaseCmd,
public Long addChatConfig(@RequestBody ChatConfigBaseReq extendBaseCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
@@ -50,7 +51,7 @@ public class ChatConfigController {
}
@PutMapping
public Long editDomainExtend(@RequestBody ChatConfigEditReq extendEditCmd,
public Long editDomainExtend(@RequestBody ChatConfigEditReqReq extendEditCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
@@ -59,7 +60,7 @@ public class ChatConfigController {
@PostMapping("/search")
public List<ChatConfigInfo> search(@RequestBody ChatConfigFilter filter,
public List<ChatConfigResp> search(@RequestBody ChatConfigFilter filter,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
@@ -68,12 +69,12 @@ public class ChatConfigController {
@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());
}
}

View File

@@ -0,0 +1,28 @@
package com.tencent.supersonic.common.enums;
public enum ConfigMode {
DETAIL("DETAIL"),
AGG("AGG"),
UNKNOWN("UNKNOWN");
private String mode;
ConfigMode(String mode) {
this.mode = mode;
}
public String getMode() {
return mode;
}
public static ConfigMode of(String agg) {
for (ConfigMode configMode : ConfigMode.values()) {
if (configMode.getMode().equalsIgnoreCase(agg)) {
return configMode;
}
}
return ConfigMode.UNKNOWN;
}
}

View File

@@ -15,7 +15,7 @@ public class DateConf {
private static final long serialVersionUID = 3074129990945004340L;
private DateMode dateMode;
private DateMode dateMode = DateMode.RECENT_UNITS;
/**
* like 2021-10-22, dateMode=1

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.common.util.calcite;
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
public class S2MysqlSqlDialect extends MysqlSqlDialect {
public S2MysqlSqlDialect(Context context) {
super(context);
}
@Override
public void quoteStringLiteral(StringBuilder buf, String charsetName, String val) {
buf.append(this.literalQuoteString);
buf.append(val.replace(this.literalEndQuoteString, this.literalEscapedQuote));
buf.append(this.literalEndQuoteString);
}
}

View File

@@ -1,16 +1,24 @@
package com.tencent.supersonic.common.util.calcite;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlDialect;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOrderBy;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.util.SqlString;
import org.apache.commons.collections.CollectionUtils;
/**
* sql parse utils
@@ -28,11 +36,14 @@ public class SqlParseUtils {
SqlParser parser = SqlParser.create(sql);
SqlNode sqlNode = parser.parseQuery();
SqlParserInfo sqlParserInfo = new SqlParserInfo();
handlerSQL(sqlNode, sqlParserInfo);
List<String> collect = sqlParserInfo.getAllFields().stream().distinct().collect(Collectors.toList());
sqlParserInfo.setAllFields(sqlParserInfo.getAllFields().stream().distinct().collect(Collectors.toList()));
sqlParserInfo.setSelectFields(
sqlParserInfo.getSelectFields().stream().distinct().collect(Collectors.toList()));
sqlParserInfo.setAllFields(collect);
return sqlParserInfo;
} catch (SqlParseException e) {
throw new RuntimeException("getSqlParseInfo", e);
@@ -69,7 +80,8 @@ public class SqlParseUtils {
SqlNode query = sqlOrderBy.query;
handlerSQL(query, sqlParserInfo);
SqlNodeList orderList = sqlOrderBy.orderList;
handlerField(orderList, sqlParserInfo);
Set<String> orderFields = handlerField(orderList);
sqlParserInfo.getAllFields().addAll(orderFields);
}
/**
@@ -82,22 +94,26 @@ public class SqlParseUtils {
SqlSelect sqlSelect = (SqlSelect) select;
SqlNodeList selectList = sqlSelect.getSelectList();
List<String> allFields = sqlParserInfo.getAllFields();
selectList.getList().forEach(list -> {
handlerField(list, sqlParserInfo);
Set<String> selectFields = handlerField(list);
sqlParserInfo.getSelectFields().addAll(selectFields);
allFields.addAll(selectFields);
});
String tableName = handlerFrom(sqlSelect.getFrom());
sqlParserInfo.setTableName(tableName);
if (sqlSelect.hasWhere()) {
handlerField(sqlSelect.getWhere(), sqlParserInfo);
allFields.addAll(handlerField(sqlSelect.getWhere()));
}
if (sqlSelect.hasOrderBy()) {
handlerField(sqlSelect.getOrderList(), sqlParserInfo);
allFields.addAll(handlerField(sqlSelect.getOrderList()));
}
SqlNodeList group = sqlSelect.getGroup();
if (group != null) {
group.forEach(groupField -> {
handlerField(groupField, sqlParserInfo);
allFields.addAll(handlerField(groupField));
});
}
}
@@ -127,34 +143,120 @@ public class SqlParseUtils {
* handler field
*
* @param field
* @param sqlParserInfo
*/
private static void handlerField(SqlNode field, SqlParserInfo sqlParserInfo) {
private static Set<String> handlerField(SqlNode field) {
Set<String> fields = new HashSet<>();
SqlKind kind = field.getKind();
switch (kind) {
case AS:
List<SqlNode> operandList1 = ((SqlBasicCall) field).getOperandList();
SqlNode left_as = operandList1.get(0);
handlerField(left_as, sqlParserInfo);
SqlNode leftAs = operandList1.get(0);
fields.addAll(handlerField(leftAs));
break;
case IDENTIFIER:
SqlIdentifier sqlIdentifier = (SqlIdentifier) field;
sqlParserInfo.getAllFields().add(sqlIdentifier.getSimple());
fields.add(sqlIdentifier.getSimple());
break;
default:
if (field instanceof SqlBasicCall) {
List<SqlNode> operandList2 = ((SqlBasicCall) field).getOperandList();
for (int i = 0; i < operandList2.size(); i++) {
handlerField(operandList2.get(i), sqlParserInfo);
fields.addAll(handlerField(operandList2.get(i)));
}
}
if (field instanceof SqlNodeList) {
((SqlNodeList) field).getList().forEach(node -> {
handlerField(node, sqlParserInfo);
fields.addAll(handlerField(node));
});
}
break;
}
return fields;
}
public static String addAliasToSql(String sql) throws SqlParseException {
SqlParser parser = SqlParser.create(sql);
SqlNode sqlNode = parser.parseStmt();
if (!(sqlNode instanceof SqlSelect)) {
return sql;
}
SqlNodeList selectList = ((SqlSelect) sqlNode).getSelectList();
for (SqlNode node : selectList) {
if (node instanceof SqlBasicCall) {
SqlBasicCall sqlBasicCall = (SqlBasicCall) node;
List<SqlNode> operandList = sqlBasicCall.getOperandList();
if (CollectionUtils.isNotEmpty(operandList) && operandList.size() == 1) {
SqlIdentifier sqlIdentifier = (SqlIdentifier) operandList.get(0);
String simple = sqlIdentifier.getSimple();
SqlBasicCall aliasedNode = new SqlBasicCall(
SqlStdOperatorTable.AS,
new SqlNode[]{sqlBasicCall, new SqlIdentifier(simple.toLowerCase(), SqlParserPos.ZERO)},
SqlParserPos.ZERO);
selectList.set(selectList.indexOf(node), aliasedNode);
}
}
}
SqlDialect dialect = new S2MysqlSqlDialect(S2MysqlSqlDialect.DEFAULT_CONTEXT);
SqlString newSql = sqlNode.toSqlString(dialect);
return newSql.getSql().replaceAll("`", "");
}
public static String addFieldsToSql(String sql, List<String> addFields) throws SqlParseException {
if (CollectionUtils.isEmpty(addFields)) {
return sql;
}
SqlParser parser = SqlParser.create(sql);
SqlNode sqlNode = parser.parseStmt();
SqlNodeList selectList = getSelectList(sqlNode);
// agg to field not allow to add field
if (Objects.isNull(selectList)) {
return sql;
}
for (SqlNode node : selectList) {
if (node instanceof SqlBasicCall) {
return sql;
}
}
Set<String> existFields = new HashSet<>();
for (SqlNode node : selectList.getList()) {
if (node instanceof SqlIdentifier) {
String fieldName = ((SqlIdentifier) node).getSimple();
existFields.add(fieldName.toLowerCase());
}
}
for (String addField : addFields) {
if (existFields.contains(addField.toLowerCase())) {
continue;
}
SqlIdentifier newField = new SqlIdentifier(addField, SqlParserPos.ZERO);
selectList.add(newField);
existFields.add(addField.toLowerCase());
}
SqlDialect dialect = new S2MysqlSqlDialect(S2MysqlSqlDialect.DEFAULT_CONTEXT);
SqlString newSql = sqlNode.toSqlString(dialect);
return newSql.getSql().replaceAll("`", "");
}
private static SqlNodeList getSelectList(SqlNode sqlNode) {
SqlKind kind = sqlNode.getKind();
switch (kind) {
case SELECT:
SqlSelect sqlSelect = (SqlSelect) sqlNode;
return sqlSelect.getSelectList();
case ORDER_BY:
SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode;
SqlSelect query = (SqlSelect) sqlOrderBy.query;
return query.getSelectList();
}
return null;
}
}

View File

@@ -12,6 +12,7 @@ public class SqlParserInfo implements Serializable {
private String tableName;
private List<String> allFields = new ArrayList<>();
private List<String> selectFields = new ArrayList<>();
private List<String> allFields = new ArrayList<>();
}

View File

@@ -0,0 +1,106 @@
package com.tencent.supersonic.common.util.calcite;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.calcite.sql.parser.SqlParseException;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
/**
* SqlParseUtils Test
*
* @date 2023/7/12 12:00
*/
class SqlParseUtilsTest {
@Test
void addAliasToSql() throws SqlParseException {
String addAliasToSql = SqlParseUtils.addAliasToSql(
"select sum(pv) from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1");
Assert.assertTrue(addAliasToSql.toLowerCase().contains("as `pv`"));
}
@Test
void addFieldToSql() throws SqlParseException {
String addFieldToSql = SqlParseUtils.addFieldsToSql(
"select pv from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1",
Collections.singletonList("uv"));
Assert.assertTrue(addFieldToSql.toLowerCase().contains("uv"));
addFieldToSql = SqlParseUtils.addFieldsToSql(
"select uv from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1 order by play_count desc limit 10",
Collections.singletonList("pv"));
Assert.assertTrue(addFieldToSql.toLowerCase().contains("pv"));
addFieldToSql = SqlParseUtils.addFieldsToSql(
"select uv from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1 where user_id = '张三' order by play_count desc limit 10",
Collections.singletonList("pv"));
Assert.assertTrue(addFieldToSql.toLowerCase().contains("pv"));
}
@Test
void getSqlParseInfo() {
SqlParserInfo sqlParserInfo = SqlParseUtils.getSqlParseInfo(
"select pv from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1 ");
Assert.assertTrue(sqlParserInfo.getTableName().equalsIgnoreCase("t_1"));
List<String> collect = sqlParserInfo.getAllFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(collect.contains("pv"));
Assert.assertTrue(!collect.contains("uv"));
List<String> selectFields = sqlParserInfo.getSelectFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(selectFields.contains("pv"));
Assert.assertTrue(!selectFields.contains("uv"));
sqlParserInfo = SqlParseUtils.getSqlParseInfo(
"select uv from t_1 order by play_count desc limit 10");
Assert.assertTrue(sqlParserInfo.getTableName().equalsIgnoreCase("t_1"));
collect = sqlParserInfo.getAllFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(collect.contains("uv"));
Assert.assertTrue(collect.contains("play_count"));
Assert.assertTrue(!collect.contains("pv"));
selectFields = sqlParserInfo.getSelectFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(selectFields.contains("uv"));
Assert.assertTrue(!selectFields.contains("pv"));
Assert.assertTrue(!selectFields.contains("play_count"));
sqlParserInfo = SqlParseUtils.getSqlParseInfo(
"select uv from ( select * from t_1 where sys_imp_date >= '2023-07-07' and sys_imp_date <= '2023-07-07' ) as t_sub_1 where user_id = '1' order by play_count desc limit 10");
Assert.assertTrue(sqlParserInfo.getTableName().equalsIgnoreCase("t_1"));
collect = sqlParserInfo.getAllFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(collect.contains("uv"));
Assert.assertTrue(collect.contains("play_count"));
Assert.assertTrue(collect.contains("user_id"));
Assert.assertTrue(!collect.contains("pv"));
selectFields = sqlParserInfo.getSelectFields().stream().map(field -> field.toLowerCase())
.collect(Collectors.toList());
Assert.assertTrue(selectFields.contains("uv"));
Assert.assertTrue(!selectFields.contains("pv"));
Assert.assertTrue(!selectFields.contains("user_id"));
Assert.assertTrue(!selectFields.contains("play_count"));
}
}

View File

@@ -5,7 +5,7 @@ baseDir=$(readlink -f $binDir/../)
confDir=$baseDir/conf
source ${baseDir}/bin/env.sh
commond=$1
command=$1
function start()
{
@@ -33,7 +33,7 @@ function stop()
fi
}
case "$commond" in
case "$command" in
start)
echo -e "Starting $APP_NAME"
start

View File

@@ -6,8 +6,8 @@ com.tencent.supersonic.chat.api.component.SchemaMapper=\
com.tencent.supersonic.chat.api.component.SemanticParser=\
com.tencent.supersonic.chat.application.parser.DomainSemanticParser, \
com.tencent.supersonic.chat.application.parser.TimeSemanticParser, \
com.tencent.supersonic.chat.application.parser.AggregateSemanticParser
# com.tencent.supersonic.chat.application.parser.LLMSemanticParser
com.tencent.supersonic.chat.application.parser.AggregateSemanticParser, \
com.tencent.supersonic.chat.application.parser.LLMSemanticParser
com.tencent.supersonic.chat.api.component.SemanticLayer=\

View File

@@ -5,3 +5,15 @@ dean _1_2 36
john _1_2 50
jack _1_2 38
admin _1_2 70
周杰伦 _2_7 100
陈奕迅 _2_7 100
林俊杰 _2_7 100
张碧晨 _2_7 100
程响 _2_7 100
Taylor#Swift _2_7 100
中国 _2_4 100
欧美 _2_4 100
流行 _2_6 100
爱情 _2_6 100
激情 _2_6 100
国风 _2_6 100

View File

@@ -3,7 +3,15 @@ insert into s2_user (id, `name`, password, display_name, email) values (2, 'jack
insert into s2_user (id, `name`, password, display_name, email) values (3, 'tom','123456','tom','tom@xx.com');
insert into s2_user (id, `name`, password, display_name, email) values (4, 'lucy','123456','lucy','lucy@xx.com');
insert into s2_chat_config (`id` ,`domain_id` ,`default_metrics`,`visibility`,`entity_info` ,`dictionary_info`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` ) values (1,1,'[{"metricId":1,"unit":7,"period":"DAY"}]','{"blackDimIdList":[],"blackMetricIdList":[]}','{"entityIds":[2],"names":["用户","用户姓名"],"detailData":{"dimensionIds":[1,2],"metricIds":[2]}}','[{"itemId":1,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":2,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":3,"type":"DIMENSION","blackList":[],"isDictInfo":true}]','2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
-- insert into s2_chat_config (`id` ,`domain_id` ,`default_metrics`,`visibility`,`entity_info` ,`dictionary_info`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` ) values (1,1,'[{"metricId":1,"unit":7,"period":"DAY"}]','{"blackDimIdList":[],"blackMetricIdList":[]}','{"entityIds":[2],"names":["用户","用户姓名"],"detailData":{"dimensionIds":[1,2],"metricIds":[2]}}','[{"itemId":1,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":2,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":3,"type":"DIMENSION","blackList":[],"isDictInfo":true}]','2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat_config (`id` ,`domain_id` ,`chat_detail_config`,`chat_agg_config`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` )
values (1,1,'{"visibility":{"blackDimIdList":[1],"blackMetricIdList":[2]},"knowledgeInfos":[{"itemId":2,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[1,2],"metricIds":[1],"unit":1,"period":"DAY"},"entity":null}',
'{"visibility":{"blackDimIdList":[3],"blackMetricIdList":[3]},"knowledgeInfos":[{"itemId":2,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[1,2],"metricIds":[1],"unit":1,"period":"DAY"}}',
'2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat_config (`id` ,`domain_id` ,`chat_detail_config`,`chat_agg_config`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` )
values (2,2,'{"visibility":{"blackDimIdList":[],"blackMetricIdList":[]},"knowledgeInfos":[{"itemId":7,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[4,5,6,7],"metricIds":[4],"unit":7,"period":"DAY"},"entity":{"entityId":1,"names":["歌手","艺人"]}}',
'{"visibility":{"blackDimIdList":[],"blackMetricIdList":[]},"knowledgeInfos":[{"itemId":7,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[4,5,6,7],"metricIds":[4],"unit":7,"period":"DAY"}}',
'2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat (chat_id, `chat_name`, create_time, last_time, creator,last_question,is_delete,is_top) values (1, '超音数访问统计','2023-06-10 10:00:52.495','2023-06-10 10:00:52','admin','您好欢迎使用内容智能小Q','0','0');
insert into s2_chat (chat_id, `chat_name`, create_time, last_time, creator,last_question,is_delete,is_top) values (2, '用户访问统计','2023-06-10 10:01:04.528','2023-06-10 10:01:04','admin','您好欢迎使用内容智能小Q','0','0');

View File

@@ -37,15 +37,11 @@ CREATE TABLE `s2_chat_query`
PRIMARY KEY (`question_id`)
);
CREATE TABLE IF NOT EXISTS `s2_chat_config` (
`id` INT NOT NULL AUTO_INCREMENT,
`domain_id` INT DEFAULT NULL ,
`default_metrics` varchar(655) DEFAULT NULL,
`visibility` varchar(655) , -- invisible dimension metric information
`entity_info` varchar(655) ,
`dictionary_info` varchar(655) , -- dictionary-related dimension setting information
`chat_detail_config` varchar(655) ,
`chat_agg_config` varchar(655) ,
`created_at` TIMESTAMP NOT NULL ,
`updated_at` TIMESTAMP NOT NULL ,
`created_by` varchar(100) NOT NULL ,
@@ -53,6 +49,22 @@ CREATE TABLE IF NOT EXISTS `s2_chat_config` (
`status` INT NOT NULL DEFAULT '0' , -- domain extension information status : 0 is normal, 1 is off the shelf, 2 is deleted
PRIMARY KEY (`id`)
) ;
-- CREATE TABLE IF NOT EXISTS `s2_chat_config` (
-- `id` INT NOT NULL AUTO_INCREMENT,
-- `domain_id` INT DEFAULT NULL ,
-- `default_metrics` varchar(655) DEFAULT NULL,
-- `visibility` varchar(655) , -- invisible dimension metric information
-- `entity_info` varchar(655) ,
-- `dictionary_info` varchar(655) , -- dictionary-related dimension setting information
-- `created_at` TIMESTAMP NOT NULL ,
-- `updated_at` TIMESTAMP NOT NULL ,
-- `created_by` varchar(100) NOT NULL ,
-- `updated_by` varchar(100) NOT NULL ,
-- `status` INT NOT NULL DEFAULT '0' , -- domain extension information status : 0 is normal, 1 is off the shelf, 2 is deleted
-- PRIMARY KEY (`id`)
-- ) ;
COMMENT ON TABLE s2_chat_config IS 'chat config information table ';

View File

@@ -90,7 +90,7 @@
</manifest>
</archive>
<descriptors>
<descriptor>../../assembly/build/build.xml</descriptor>
<descriptor>../semantic/src/main/build/build.xml</descriptor>
</descriptors>
</configuration>
<executions>

View File

@@ -5,7 +5,7 @@ baseDir=$(readlink -f $binDir/../)
confDir=$baseDir/conf
source ${baseDir}/bin/env.sh
commond=$1
command=$1
function start()
{
@@ -33,7 +33,7 @@ function stop()
fi
}
case "$commond" in
case "$command" in
start)
echo -e "Starting $APP_NAME"
start

View File

@@ -0,0 +1,39 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>bin</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0777</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0777</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>

View File

@@ -1,17 +1,27 @@
insert into s2_database (id, domain_id , `name`, description, `type` ,config ,created_at ,created_by ,updated_at ,updated_by) VALUES(1, 1, 'H2数据实例', '', 'h2', '{"password":"semantic","url":"jdbc:h2:mem:semantic;DATABASE_TO_UPPER=false","userName":"root"}', '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin');
insert into s2_database (id, domain_id , `name`, description, `type` ,config ,created_at ,created_by ,updated_at ,updated_by) VALUES(2, 2, 'H2数据实例', '', 'h2', '{"password":"semantic","url":"jdbc:h2:mem:semantic;DATABASE_TO_UPPER=false","userName":"root"}', '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(1, 1, '停留时长统计', 's2_stay_time_statis', '停留时长统计', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"page","dateFormat":"yyyy-MM-dd","expr":"page","isCreateDimension":0,"type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[{"agg":"sum","bizName":"s2_stay_time_statis_stay_hours","expr":"stay_hours","isCreateMetric":1,"name":"停留时长"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date, page,user_name,stay_hours FROM s2_stay_time_statis"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(2, 1, 'PVUV统计', 's2_pv_uv_statis', 'PVUV统计', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"page","dateFormat":"yyyy-MM-dd","expr":"page","isCreateDimension":0,"type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[{"agg":"sum","bizName":"s2_pv_uv_statis_pv","expr":"pv","isCreateMetric":1,"name":"访问次数"},{"agg":"count_distinct","bizName":"s2_pv_uv_statis_uv","expr":"uv","isCreateMetric":1,"name":"访问人数"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date, user_name,page,1 as pv, user_name as uv FROM s2_pv_uv_statis"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(3, 1, '用户部门', 'user_department', '用户部门', 1, '{"dimensions":[{"bizName":"department","dateFormat":"yyyy-MM-dd","expr":"department","isCreateDimension":1,"name":"部门","type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[],"queryType":"sql_query","sqlQuery":"SELECT user_name,department FROM s2_user_department"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(4, 2, '艺人库', 'singer', '艺人库', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"act_area","dateFormat":"yyyy-MM-dd","expr":"act_area","isCreateDimension":1,"name":"活跃区域","type":"categorical"},{"bizName":"song_name","dateFormat":"yyyy-MM-dd","expr":"song_name","isCreateDimension":1,"name":"代表作","type":"categorical"},{"bizName":"genre","dateFormat":"yyyy-MM-dd","expr":"genre","isCreateDimension":1,"name":"风格","type":"categorical"}],"identifiers":[{"bizName":"singer_name","name":"歌手名","type":"primary"}],"measures":[{"agg":"sum","bizName":"music_down_cnt","expr":"down_cnt","isCreateMetric":1,"name":"下载量"},{"agg":"sum","bizName":"music_js_play_cnt","expr":"js_play_cnt","isCreateMetric":1,"name":"播放量"},{"agg":"sum","bizName":"music_favor_cnt","expr":"favor_cnt","isCreateMetric":1,"name":"收藏量"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date,singer_name,act_area,song_name,genre,js_play_cnt,down_cnt,favor_cnt FROM singer "}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(1, 1, 1, 2, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(2, 1, 1, 3, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(3, 1, 2, 3, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(1, 1, 3, '部门', 'department', '部门', 1, 0, 'categorical', NULL, 'department', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(2, 1, 1, '用户名', 'user_name', '用户名', 1, 0, 'primary', NULL, 'user_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(3, 1, 2, '页面', 'page', '页面', 1, 2, 'categorical', NULL, 'page', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(4, 2, 4, '活跃区域', 'act_area', '活跃区域', 1, 2, 'categorical', NULL, 'act_area', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(5, 2, 4, '代表作', 'song_name', '代表作', 1, 2, 'categorical', NULL, 'song_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(6, 2, 4, '风格', 'genre', '风格', 1, 2, 'categorical', NULL, 'genre', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(7, 2, 4, '歌手名', 'singer_name', '歌手名', 1, 2, 'categorical', NULL, 'singer_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_domain (id, `name`, biz_name, parent_id, status, created_at, created_by, updated_at, updated_by, `admin`, admin_org, is_open, viewer, view_org) VALUES(1, '超音数', 'supersonic', 0, 1, '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin', 'admin', '', 0, 'admin,tom,jack', 'admin' );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(1, 1, '停留时长', 'stay_hours', '停留时长', 1, 2, 'expr', '{"expr":"s2_stay_time_statis_stay_hours","measures":[{"agg":"sum","expr":"stay_hours","isCreateMetric":1,"datasourceId":1,"bizName":"s2_stay_time_statis_stay_hours","name":"s2_stay_time_statis_stay_hours"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(2, 1, '访问次数', 'pv', '访问次数', 1, 0, 'expr', ' {"expr":"s2_pv_uv_statis_pv","measures":[{"agg":"sum","bizName":"s2_pv_uv_statis_pv","datasourceId":2,"expr":"pv","isCreateMetric":1,"name":"s2_pv_uv_statis_pv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(3, 1, '访问', 'uv', '访问', 1, 0, 'expr', ' {"expr":"s2_pv_uv_statis_uv","measures":[{"agg":"count_distinct","bizName":"s2_pv_uv_statis_uv","datasourceId":2,"expr":"uv","isCreateMetric":1,"name":"s2_pv_uv_statis_uv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_domain (id, `name`, biz_name, parent_id, status, created_at, created_by, updated_at, updated_by, `admin`, admin_org, is_open, viewer, view_org) VALUES(2, '艺人库', 'singer', 0, 1, '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin', 'admin', '', 0, 'admin,tom,jack', 'admin' );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(1, 1, '停留时长', 'stay_hours', '停留时长', 1, 2, 'ATOMIC', '{"expr":"s2_stay_time_statis_stay_hours","measures":[{"agg":"sum","expr":"stay_hours","isCreateMetric":1,"datasourceId":1,"bizName":"s2_stay_time_statis_stay_hours","name":"s2_stay_time_statis_stay_hours"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(2, 1, '访问', 'pv', '访问', 1, 0, 'ATOMIC', ' {"expr":"s2_pv_uv_statis_pv","measures":[{"agg":"sum","bizName":"s2_pv_uv_statis_pv","datasourceId":2,"expr":"pv","isCreateMetric":1,"name":"s2_pv_uv_statis_pv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(3, 1, '访问人数', 'uv', '访问人数', 1, 0, 'ATOMIC', ' {"expr":"s2_pv_uv_statis_uv","measures":[{"agg":"count_distinct","bizName":"s2_pv_uv_statis_uv","datasourceId":2,"expr":"uv","isCreateMetric":1,"name":"s2_pv_uv_statis_uv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(4, 2, '播放量', 'js_play_cnt', '播放量', 1, 2, 'ATOMIC', '{"expr":"music_js_play_cnt","measures":[{"agg":"sum","expr":"js_play_cnt","isCreateMetric":1,"datasourceId":4,"bizName":"music_js_play_cnt","name":"music_js_play_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(5, 2, '下载量', 'down_cnt', '下载量', 1, 0, 'ATOMIC', ' {"expr":"music_down_cnt","measures":[{"agg":"sum","bizName":"music_down_cnt","datasourceId":4,"expr":"down_cnt","isCreateMetric":1,"name":"music_down_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(6, 2, '收藏量', 'favor_cnt', '收藏量', 1, 0, 'ATOMIC', ' {"expr":"music_favor_cnt","measures":[{"agg":"sum","bizName":"music_favor_cnt","datasourceId":4,"expr":"favor_cnt","isCreateMetric":1,"name":"music_favor_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_available_date_info(`item_id` ,`type` ,`date_format` ,`start_date` ,`end_date` ,`unavailable_date` ,`created_at` ,`created_by` ,`updated_at` ,`updated_by` )
values (1, 'dimension', 'yyyy-MM-dd', DATEADD('DAY', -28, CURRENT_DATE()), DATEADD('DAY', -1, CURRENT_DATE()), '[]', '2023-06-01', 'admin', '2023-06-01', 'admin');
@@ -39,6 +49,60 @@ insert into s2_user_department (user_name, department) values ('john','strategy'
insert into s2_user_department (user_name, department) values ('alice','sales');
insert into s2_user_department (user_name, department) values ('dean','marketing');
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO s2_pv_uv_statis (imp_date, user_name, page) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), 'lucy', 'p1');
INSERT INTO s2_pv_uv_statis (imp_date, user_name, page) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), 'jack', 'p1');

View File

@@ -211,6 +211,7 @@ CREATE TABLE IF NOT EXISTS `s2_available_date_info` (
`created_by` varchar(100) NOT NULL ,
`updated_at` TIMESTAMP NOT NULL ,
`updated_by` varchar(100) NOT NULL ,
`date_period` varchar(100) DEFAULT NULL ,
`status` INT DEFAULT '0', -- 1-in use 0 is normal, 1 is off the shelf, 2 is deleted
PRIMARY KEY (`id`)
);
@@ -239,4 +240,16 @@ CREATE TABLE IF NOT EXISTS `s2_stay_time_statis` (
);
COMMENT ON TABLE s2_stay_time_statis IS 's2_stay_time_statis_info';
CREATE TABLE IF NOT EXISTS `singer` (
`imp_date` varchar(200) NOT NULL,
`singer_name` varchar(200) NOT NULL,
`act_area` varchar(200) NOT NULL,
`song_name` varchar(200) NOT NULL,
`genre` varchar(200) NOT NULL,
`js_play_cnt` bigINT DEFAULT NULL,
`down_cnt` bigINT DEFAULT NULL,
`favor_cnt` bigINT DEFAULT NULL
);
COMMENT ON TABLE singer IS 'singer_info';

View File

@@ -1,2 +1,2 @@
export APP_NAME=chat-service
export MAIN_CLASS=com.tencent.supersonic.Launcher
export MAIN_CLASS=com.tencent.supersonic.StandaloneLauncher

View File

@@ -5,7 +5,7 @@ baseDir=$(readlink -f $binDir/../)
confDir=$baseDir/conf
source ${baseDir}/bin/env.sh
commond=$1
command=$1
function start()
{
@@ -33,7 +33,7 @@ function stop()
fi
}
case "$commond" in
case "$command" in
start)
echo -e "Starting $APP_NAME"
start

View File

@@ -6,8 +6,8 @@ com.tencent.supersonic.chat.api.component.SchemaMapper=\
com.tencent.supersonic.chat.api.component.SemanticParser=\
com.tencent.supersonic.chat.application.parser.DomainSemanticParser, \
com.tencent.supersonic.chat.application.parser.TimeSemanticParser, \
com.tencent.supersonic.chat.application.parser.AggregateSemanticParser
# com.tencent.supersonic.chat.application.parser.LLMSemanticParser
com.tencent.supersonic.chat.application.parser.AggregateSemanticParser, \
com.tencent.supersonic.chat.application.parser.LLMSemanticParser
com.tencent.supersonic.chat.api.component.SemanticLayer=\

View File

@@ -16,7 +16,7 @@ server:
port: 9080
authentication:
enable: false
enable: true
exclude:
path: /api/auth/user/register,/api/auth/user/login

View File

@@ -5,3 +5,15 @@ dean _1_2 36
john _1_2 50
jack _1_2 38
admin _1_2 70
周杰伦 _2_7 100
陈奕迅 _2_7 100
林俊杰 _2_7 100
张碧晨 _2_7 100
程响 _2_7 100
Taylor#Swift _2_7 100
中国 _2_4 100
欧美 _2_4 100
流行 _2_6 100
爱情 _2_6 100
激情 _2_6 100
国风 _2_6 100

View File

@@ -4,7 +4,15 @@ insert into s2_user (id, `name`, password, display_name, email) values (2, 'jack
insert into s2_user (id, `name`, password, display_name, email) values (3, 'tom','123456','tom','tom@xx.com');
insert into s2_user (id, `name`, password, display_name, email) values (4, 'lucy','123456','lucy','lucy@xx.com');
insert into s2_chat_config (`id` ,`domain_id` ,`default_metrics`,`visibility`,`entity_info` ,`dictionary_info`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` ) values (1,1,'[{"metricId":1,"unit":7,"period":"DAY"}]','{"blackDimIdList":[],"blackMetricIdList":[]}','{"entityIds":[2],"names":["用户","用户姓名"],"detailData":{"dimensionIds":[1,2],"metricIds":[2]}}','[{"itemId":1,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":2,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":3,"type":"DIMENSION","blackList":[],"isDictInfo":true}]','2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
--insert into s2_chat_config (`id` ,`domain_id` ,`default_metrics`,`visibility`,`entity_info` ,`dictionary_info`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` ) values (1,1,'[{"metricId":1,"unit":7,"period":"DAY"}]','{"blackDimIdList":[],"blackMetricIdList":[]}','{"entityIds":[2],"names":["用户","用户姓名"],"detailData":{"dimensionIds":[1,2],"metricIds":[2]}}','[{"itemId":1,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":2,"type":"DIMENSION","blackList":[],"isDictInfo":true},{"itemId":3,"type":"DIMENSION","blackList":[],"isDictInfo":true}]','2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat_config (`id` ,`domain_id` ,`chat_detail_config`,`chat_agg_config`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` )
values (1,1,'{"visibility":{"blackDimIdList":[1],"blackMetricIdList":[2]},"knowledgeInfos":[{"itemId":2,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[1,2],"metricIds":[1],"unit":1,"period":"DAY"},"entity":null}',
'{"visibility":{"blackDimIdList":[3],"blackMetricIdList":[3]},"knowledgeInfos":[{"itemId":2,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[1,2],"metricIds":[1],"unit":1,"period":"DAY"}}',
'2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat_config (`id` ,`domain_id` ,`chat_detail_config`,`chat_agg_config`,`created_at`,`updated_at`,`created_by`,`updated_by`,`status` )
values (2,2,'{"visibility":{"blackDimIdList":[],"blackMetricIdList":[]},"knowledgeInfos":[{"itemId":7,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[4,5,6,7],"metricIds":[4],"unit":7,"period":"DAY"},"entity":{"entityId":1,"names":["歌手","艺人"]}}',
'{"visibility":{"blackDimIdList":[],"blackMetricIdList":[]},"knowledgeInfos":[{"itemId":7,"type":"DIMENSION","searchEnable":true}],"chatDefaultConfig":{"dimensionIds":[4,5,6,7],"metricIds":[4],"unit":7,"period":"DAY"}}',
'2023-05-24 18:00:00','2023-05-25 11:00:00','admin','admin',1);
insert into s2_chat (chat_id, `chat_name`, create_time, last_time, creator,last_question,is_delete,is_top) values (1, '超音数访问统计','2023-06-10 10:00:52.495','2023-06-10 10:00:52','admin','您好欢迎使用内容智能小Q','0','0');
insert into s2_chat (chat_id, `chat_name`, create_time, last_time, creator,last_question,is_delete,is_top) values (2, '用户访问统计','2023-06-10 10:01:04.528','2023-06-10 10:01:04','admin','您好欢迎使用内容智能小Q','0','0');
@@ -22,19 +30,29 @@ insert into s2_chat_query (`question_id`,`create_time`,`query_text`,`user_name`,
-- semantic data
insert into s2_database (id, domain_id , `name`, description, `type` ,config ,created_at ,created_by ,updated_at ,updated_by) VALUES(1, 1, 'H2数据实例', '', 'h2', '{"password":"semantic","url":"jdbc:h2:mem:semantic;DATABASE_TO_UPPER=false","userName":"root"}', '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin');
insert into s2_database (id, domain_id , `name`, description, `type` ,config ,created_at ,created_by ,updated_at ,updated_by) VALUES(2, 2, 'H2数据实例', '', 'h2', '{"password":"semantic","url":"jdbc:h2:mem:semantic;DATABASE_TO_UPPER=false","userName":"root"}', '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(1, 1, '停留时长统计', 's2_stay_time_statis', '停留时长统计', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"page","dateFormat":"yyyy-MM-dd","expr":"page","isCreateDimension":0,"type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[{"agg":"sum","bizName":"s2_stay_time_statis_stay_hours","expr":"stay_hours","isCreateMetric":1,"name":"停留时长"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date, page,user_name,stay_hours FROM s2_stay_time_statis"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(2, 1, 'PVUV统计', 's2_pv_uv_statis', 'PVUV统计', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"page","dateFormat":"yyyy-MM-dd","expr":"page","isCreateDimension":0,"type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[{"agg":"sum","bizName":"s2_pv_uv_statis_pv","expr":"pv","isCreateMetric":1,"name":"访问次数"},{"agg":"count_distinct","bizName":"s2_pv_uv_statis_uv","expr":"uv","isCreateMetric":1,"name":"访问人数"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date, user_name,page,1 as pv, user_name as uv FROM s2_pv_uv_statis"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(3, 1, '用户部门', 'user_department', '用户部门', 1, '{"dimensions":[{"bizName":"department","dateFormat":"yyyy-MM-dd","expr":"department","isCreateDimension":1,"name":"部门","type":"categorical"}],"identifiers":[{"bizName":"user_name","name":"用户名","type":"primary"}],"measures":[],"queryType":"sql_query","sqlQuery":"SELECT user_name,department FROM s2_user_department"}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource (id , domain_id, `name`, biz_name, description, database_id ,datasource_detail, created_at, created_by, updated_at, updated_by ) VALUES(4, 2, '艺人库', 'singer', '艺人库', 1, '{"dimensions":[{"bizName":"imp_date","dateFormat":"yyyy-MM-dd","expr":"imp_date","isCreateDimension":0,"type":"time","typeParams":{"isPrimary":"true","timeGranularity":"day"}},{"bizName":"act_area","dateFormat":"yyyy-MM-dd","expr":"act_area","isCreateDimension":1,"name":"活跃区域","type":"categorical"},{"bizName":"song_name","dateFormat":"yyyy-MM-dd","expr":"song_name","isCreateDimension":1,"name":"代表作","type":"categorical"},{"bizName":"genre","dateFormat":"yyyy-MM-dd","expr":"genre","isCreateDimension":1,"name":"风格","type":"categorical"}],"identifiers":[{"bizName":"singer_name","name":"歌手名","type":"primary"}],"measures":[{"agg":"sum","bizName":"music_down_cnt","expr":"down_cnt","isCreateMetric":1,"name":"下载量"},{"agg":"sum","bizName":"music_js_play_cnt","expr":"js_play_cnt","isCreateMetric":1,"name":"播放量"},{"agg":"sum","bizName":"music_favor_cnt","expr":"favor_cnt","isCreateMetric":1,"name":"收藏量"}],"queryType":"sql_query","sqlQuery":"SELECT imp_date,singer_name,act_area,song_name,genre,js_play_cnt,down_cnt,favor_cnt FROM singer "}', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(1, 1, 1, 2, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(2, 1, 1, 3, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_datasource_rela (id , domain_id, `datasource_from`, datasource_to, join_key, created_at, created_by, updated_at, updated_by ) VALUES(3, 1, 2, 3, 'user_name', '2023-05-25 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(1, 1, 3, '部门', 'department', '部门', 1, 0, 'categorical', NULL, 'department', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(2, 1, 1, '用户名', 'user_name', '用户名', 1, 0, 'primary', NULL, 'user_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(3, 1, 2, '页面', 'page', '页面', 1, 2, 'categorical', NULL, 'page', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(4, 2, 4, '活跃区域', 'act_area', '活跃区域', 1, 2, 'categorical', NULL, 'act_area', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(5, 2, 4, '代表作', 'song_name', '代表作', 1, 2, 'categorical', NULL, 'song_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(6, 2, 4, '风格', 'genre', '风格', 1, 2, 'categorical', NULL, 'genre', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_dimension (id , domain_id, datasource_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, expr, created_at, created_by, updated_at, updated_by, semantic_type) VALUES(7, 2, 4, '歌手名', 'singer_name', '歌手名', 1, 2, 'categorical', NULL, 'singer_name', '2023-05-24 00:00:00', 'admin', '2023-05-25 00:00:00', 'admin', 'CATEGORY');
insert into s2_domain (id, `name`, biz_name, parent_id, status, created_at, created_by, updated_at, updated_by, `admin`, admin_org, is_open, viewer, view_org) VALUES(1, '超音数', 'supersonic', 0, 1, '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin', 'admin', '', 0, 'admin,tom,jack', 'admin' );
insert into s2_domain (id, `name`, biz_name, parent_id, status, created_at, created_by, updated_at, updated_by, `admin`, admin_org, is_open, viewer, view_org) VALUES(2, '艺人库', 'singer', 0, 1, '2023-05-24 00:00:00', 'admin', '2023-05-24 00:00:00', 'admin', 'admin', '', 0, 'admin,tom,jack', 'admin' );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(1, 1, '停留时长', 'stay_hours', '停留时长', 1, 2, 'expr', '{"expr":"s2_stay_time_statis_stay_hours","measures":[{"agg":"sum","expr":"stay_hours","isCreateMetric":1,"datasourceId":1,"bizName":"s2_stay_time_statis_stay_hours","name":"s2_stay_time_statis_stay_hours"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(2, 1, '访问次数', 'pv', '访问次数', 1, 0, 'expr', ' {"expr":"s2_pv_uv_statis_pv","measures":[{"agg":"sum","bizName":"s2_pv_uv_statis_pv","datasourceId":2,"expr":"pv","isCreateMetric":1,"name":"s2_pv_uv_statis_pv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(3, 1, '访问人数', 'uv', '访问人数', 1, 0, 'expr', ' {"expr":"s2_pv_uv_statis_uv","measures":[{"agg":"count_distinct","bizName":"s2_pv_uv_statis_uv","datasourceId":2,"expr":"uv","isCreateMetric":1,"name":"s2_pv_uv_statis_uv"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(4, 2, '播放量', 'js_play_cnt', '播放量', 1, 2, 'expr', '{"expr":"music_js_play_cnt","measures":[{"agg":"sum","expr":"js_play_cnt","isCreateMetric":1,"datasourceId":4,"bizName":"music_js_play_cnt","name":"music_js_play_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(5, 2, '下载量', 'down_cnt', '下载量', 1, 0, 'expr', ' {"expr":"music_down_cnt","measures":[{"agg":"sum","bizName":"music_down_cnt","datasourceId":4,"expr":"down_cnt","isCreateMetric":1,"name":"music_down_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_metric (id, domain_id, `name`, biz_name, description, status, sensitive_level, `type`, type_params, created_at, created_by, updated_at, updated_by, data_format_type, data_format) VALUES(6, 2, '收藏量', 'favor_cnt', '收藏量', 1, 0, 'expr', ' {"expr":"music_favor_cnt","measures":[{"agg":"sum","bizName":"music_favor_cnt","datasourceId":4,"expr":"favor_cnt","isCreateMetric":1,"name":"music_favor_cnt"}]}' , '2023-05-24 17:00:00', 'admin', '2023-05-25 00:00:00', 'admin', NULL, NULL );
insert into s2_available_date_info(`item_id` ,`type` ,`date_format` ,`start_date` ,`end_date` ,`unavailable_date` ,`created_at` ,`created_by` ,`updated_at` ,`updated_by` )
values (1, 'dimension', 'yyyy-MM-dd', DATEADD('DAY', -28, CURRENT_DATE()), DATEADD('DAY', -1, CURRENT_DATE()), '[]', '2023-06-01', 'admin', '2023-06-01', 'admin');
@@ -48,13 +66,64 @@ values (1, '{"domainId":"1","name":"admin-permission","groupId":1,"authRules":[{
insert into s2_auth_groups (group_id, config)
values (2, '{"domainId":"1","name":"tom_sales_permission","groupId":2,"authRules":[{"metrics":["stay_hours"],"dimensions":["page"]}],"dimensionFilters":["department in (''sales'')"],"dimensionFilterDescription":"开通 tom sales部门权限", "authorizedUsers":["tom"],"authorizedDepartmentIds":[]}');
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '周杰伦', '中国','青花瓷','流行',1000000,1000000,1000000);
-- insert into s2_user (id, `name`, password, display_name, email) values (1, 'admin','admin','admin','admin@xx.com');
-- insert into s2_user (id, `name`, password, display_name, email) values (2, 'jack','123456','jack','jack@xx.com');
-- insert into s2_user (id, `name`, password, display_name, email) values (3, 'tom','123456','tom','tom@xx.com');
-- insert into s2_user (id, `name`, password, display_name, email) values (4, 'lucy','123456','lucy','lucy@xx.com');
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '陈奕迅', '中国','爱情转移','激情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '林俊杰', '中国','美人鱼','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '张碧晨', '中国','光的方向','流行',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), '程响', '中国','人间烟火','国风',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -5, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -4, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -3, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -2, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -6, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
INSERT INTO singer (imp_date,singer_name,act_area, song_name,genre,js_play_cnt,down_cnt,favor_cnt) VALUES (DATEADD('DAY', -7, CURRENT_DATE()), 'Taylor Swift
', '欧美','Love Story','爱情',1000000,1000000,1000000);
---demo data for semantic and chat
insert into s2_user_department (user_name, department) values ('jack','HR');
insert into s2_user_department (user_name, department) values ('jack','HR');
insert into s2_user_department (user_name, department) values ('tom','sales');
insert into s2_user_department (user_name, department) values ('lucy','marketing');

View File

@@ -39,14 +39,11 @@ CREATE TABLE `s2_chat_query`
);
CREATE TABLE IF NOT EXISTS `s2_chat_config` (
`id` INT NOT NULL AUTO_INCREMENT,
`domain_id` INT DEFAULT NULL ,
`default_metrics` varchar(655) DEFAULT NULL,
`visibility` varchar(655) , -- invisible dimension metric information
`entity_info` varchar(655) ,
`dictionary_info` varchar(655) , -- dictionary-related dimension setting information
`chat_detail_config` varchar(655) ,
`chat_agg_config` varchar(655) ,
`created_at` TIMESTAMP NOT NULL ,
`updated_at` TIMESTAMP NOT NULL ,
`created_by` varchar(100) NOT NULL ,
@@ -306,6 +303,7 @@ CREATE TABLE IF NOT EXISTS `s2_available_date_info` (
`created_by` varchar(100) NOT NULL ,
`updated_at` TIMESTAMP NOT NULL ,
`updated_by` varchar(100) NOT NULL ,
`date_period` varchar(100) DEFAULT NULL ,
`status` INT DEFAULT '0', -- 1-in use 0 is normal, 1 is off the shelf, 2 is deleted
PRIMARY KEY (`id`)
);
@@ -334,6 +332,18 @@ CREATE TABLE IF NOT EXISTS `s2_stay_time_statis` (
);
COMMENT ON TABLE s2_stay_time_statis IS 's2_stay_time_statis_info';
CREATE TABLE IF NOT EXISTS `singer` (
`imp_date` varchar(200) NOT NULL,
`singer_name` varchar(200) NOT NULL,
`act_area` varchar(200) NOT NULL,
`song_name` varchar(200) NOT NULL,
`genre` varchar(200) NOT NULL,
`js_play_cnt` bigINT DEFAULT NULL,
`down_cnt` bigINT DEFAULT NULL,
`favor_cnt` bigINT DEFAULT NULL
);
COMMENT ON TABLE singer IS 'singer_info';

View File

@@ -1,31 +0,0 @@
package com.tencent.supersonic.db;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
@Configuration
@MapperScan(value = "com.tencent.supersonic", annotationClass = Mapper.class)
public class MybatisConfig {
private static final String MAPPER_LOCATION = "classpath*:mapper/**/*.xml";
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
return bean.getObject();
}
}

Some files were not shown because too many files have changed in this diff Show More