Merge fixes and improvements (#1910)

Co-authored-by: tristanliu <tristanliu@tencent.com>
This commit is contained in:
Jun Zhang
2024-11-16 13:57:54 +08:00
committed by GitHub
parent 5e22b412c6
commit ba1938f04b
40 changed files with 1382 additions and 2784 deletions

View File

@@ -30,11 +30,10 @@ public abstract class BaseSemanticCorrector implements SemanticCorrector {
public void correct(ChatQueryContext chatQueryContext, SemanticParseInfo semanticParseInfo) {
try {
String s2SQL = semanticParseInfo.getSqlInfo().getParsedS2SQL();
String s2SQL = semanticParseInfo.getSqlInfo().getCorrectedS2SQL();
if (Objects.isNull(s2SQL)) {
return;
}
semanticParseInfo.getSqlInfo().setCorrectedS2SQL(s2SQL);
doCorrect(chatQueryContext, semanticParseInfo);
log.debug("sqlCorrection:{} sql:{}", this.getClass().getSimpleName(),
semanticParseInfo.getSqlInfo());

View File

@@ -6,8 +6,6 @@ import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.chat.ChatQueryContext;
import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
/** QueryTypeParser resolves query type as either AGGREGATE or DETAIL */
@Slf4j
public class QueryTypeParser implements SemanticParser {
@@ -17,14 +15,12 @@ public class QueryTypeParser implements SemanticParser {
chatQueryContext.getCandidateQueries().forEach(query -> {
SemanticParseInfo parseInfo = query.getParseInfo();
String s2SQL = parseInfo.getSqlInfo().getParsedS2SQL();
if (Objects.isNull(s2SQL)) {
return;
}
QueryType queryType = QueryType.DETAIL;
if (SqlSelectFunctionHelper.hasAggregateFunction(s2SQL)) {
queryType = QueryType.AGGREGATE;
}
parseInfo.setQueryType(queryType);
});
}

View File

@@ -49,6 +49,7 @@ public class LLMResponseService {
parseInfo.setScore(queryCtx.getRequest().getQueryText().length() * (1 + weight));
parseInfo.setQueryMode(semanticQuery.getQueryMode());
parseInfo.getSqlInfo().setParsedS2SQL(s2SQL);
parseInfo.getSqlInfo().setCorrectedS2SQL(s2SQL);
queryCtx.getCandidateQueries().add(semanticQuery);
}

View File

@@ -40,9 +40,7 @@ public class RuleSqlParser implements SemanticParser {
auxiliaryParsers.forEach(p -> p.parse(chatQueryContext));
if (chatQueryContext.needSQL()) {
candidateQueries.forEach(query -> query.buildS2Sql(
chatQueryContext.getDataSetSchema(query.getParseInfo().getDataSetId())));
}
}
}

View File

@@ -1,6 +1,7 @@
package com.tencent.supersonic.headless.chat.query.llm.s2sql;
import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
import com.tencent.supersonic.headless.api.pojo.SqlInfo;
import com.tencent.supersonic.headless.chat.query.QueryManager;
import com.tencent.supersonic.headless.chat.query.llm.LLMSemanticQuery;
import lombok.extern.slf4j.Slf4j;
@@ -22,5 +23,8 @@ public class LLMSqlQuery extends LLMSemanticQuery {
}
@Override
public void buildS2Sql(DataSetSchema dataSetSchema) {}
public void buildS2Sql(DataSetSchema dataSetSchema) {
SqlInfo sqlInfo = parseInfo.getSqlInfo();
sqlInfo.setCorrectedS2SQL(sqlInfo.getParsedS2SQL());
}
}

View File

@@ -60,6 +60,7 @@ public abstract class RuleSemanticQuery extends BaseSemanticQuery {
convertBizNameToName(dataSetSchema, queryStructReq);
QuerySqlReq querySQLReq = queryStructReq.convert();
parseInfo.getSqlInfo().setParsedS2SQL(querySQLReq.getSql());
parseInfo.getSqlInfo().setCorrectedS2SQL(querySQLReq.getSql());
}
protected QueryStructReq convertQueryStruct() {

View File

@@ -147,6 +147,12 @@ public class QueryReqBuilder {
return aggregateType.name();
}
private static boolean isDateFieldAlreadyPresent(SemanticParseInfo parseInfo,
String dateField) {
return parseInfo.getDimensions().stream()
.anyMatch(dimension -> dimension.getBizName().equalsIgnoreCase(dateField));
}
public static Set<Order> getOrder(Set<Order> existingOrders, AggregateTypeEnum aggregator,
SchemaElement metric) {
if (existingOrders != null && !existingOrders.isEmpty()) {

View File

@@ -56,13 +56,13 @@ public class S2CompanyDemo extends S2BaseDemo {
ModelResp model_company = addModel_1(domain, demoDatabase);
ModelResp model_brand = addModel_2(domain, demoDatabase);
ModelResp model_company_revenue = addModel_3(domain, demoDatabase);
ModelResp company_brand_revenue_proportion = addModel_3(domain, demoDatabase);
ModelResp model_brand_revenue = addModel_4(domain, demoDatabase);
addModelRela_1(domain, model_company_revenue, model_company);
addModelRela_2(domain, model_brand, model_company);
addModelRela_3(domain, model_brand_revenue, model_brand);
addModelRela_4(domain, model_company_revenue, model_brand);
addModelRela(domain, company_brand_revenue_proportion, model_company, "company_id");
addModelRela(domain, company_brand_revenue_proportion, model_brand, "brand_id");
addModelRela(domain, model_brand, model_company, "company_id");
addModelRela(domain, model_brand_revenue, model_brand, "brand_id");
DataSetResp dataset = addDataSet(domain);
addAgent(dataset.getId());
@@ -85,7 +85,7 @@ public class S2CompanyDemo extends S2BaseDemo {
public DomainResp addDomain() {
DomainReq domainReq = new DomainReq();
domainReq.setName("企业数据");
domainReq.setName("企业数据");
domainReq.setBizName("corporate");
domainReq.setParentId(0L);
domainReq.setViewers(Arrays.asList("admin", "tom", "jack"));
@@ -188,7 +188,7 @@ public class S2CompanyDemo extends S2BaseDemo {
public ModelResp addModel_3(DomainResp domain, DatabaseResp database) throws Exception {
ModelReq modelReq = new ModelReq();
modelReq.setName("公司品牌收入占比");
modelReq.setBizName("company_revenue");
modelReq.setBizName("company_brand_revenue_proportion");
modelReq.setDatabaseId(database.getId());
modelReq.setDomainId(domain.getId());
modelReq.setViewers(Arrays.asList("admin", "tom", "jack"));
@@ -210,8 +210,7 @@ public class S2CompanyDemo extends S2BaseDemo {
modelDetail.setIdentifiers(identifiers);
List<Measure> measures = new ArrayList<>();
Measure measure = new Measure("营收占比", "revenue_proportion", AggOperatorEnum.MAX.name(), 1);
measures.add(measure);
measures.add(new Measure("营收占比", "revenue_proportion", AggOperatorEnum.MAX.name(), 1));
measures.add(new Measure("利润占比", "profit_proportion", AggOperatorEnum.MAX.name(), 1));
measures.add(new Measure("支出占比", "expenditure_proportion", AggOperatorEnum.MAX.name(), 1));
modelDetail.setMeasures(measures);
@@ -268,7 +267,7 @@ public class S2CompanyDemo extends S2BaseDemo {
dataSetReq.setName("企业数据集");
dataSetReq.setBizName("CorporateData");
dataSetReq.setDomainId(domain.getId());
dataSetReq.setDescription("互联网企业核心经营数据");
dataSetReq.setDescription("巨头公司核心经营数据");
dataSetReq.setAdmins(Lists.newArrayList("admin"));
List<DataSetModelConfig> dataSetModelConfigs = getDataSetModelConfigs(domain.getId());
@@ -289,10 +288,10 @@ public class S2CompanyDemo extends S2BaseDemo {
return dataSetService.save(dataSetReq, defaultUser);
}
public void addModelRela_1(DomainResp domain, ModelResp fromModel, ModelResp toModel) {
public void addModelRela(DomainResp domain, ModelResp fromModel, ModelResp toModel,
String joinField) {
List<JoinCondition> joinConditions = Lists.newArrayList();
joinConditions
.add(new JoinCondition("company_id", "company_id", FilterOperatorEnum.EQUALS));
joinConditions.add(new JoinCondition(joinField, joinField, FilterOperatorEnum.EQUALS));
ModelRela modelRelaReq = new ModelRela();
modelRelaReq.setDomainId(domain.getId());
modelRelaReq.setFromModelId(fromModel.getId());

View File

@@ -51,9 +51,7 @@ public class S2SingerDemo extends S2BaseDemo {
public void doRun() {
try {
DomainResp singerDomain = addDomain();
TagObjectResp singerTagObject = addTagObjectSinger(singerDomain);
ModelResp singerModel = addModel(singerDomain, demoDatabase, singerTagObject);
addTags(singerModel);
ModelResp singerModel = addModel(singerDomain, demoDatabase);
long dataSetId = addDataSet(singerDomain, singerModel);
addAgent(dataSetId);
} catch (Exception e) {
@@ -83,7 +81,7 @@ public class S2SingerDemo extends S2BaseDemo {
public DomainResp addDomain() {
DomainReq domainReq = new DomainReq();
domainReq.setName("歌手数据");
domainReq.setName("歌手数据");
domainReq.setBizName("singer");
domainReq.setParentId(0L);
domainReq.setStatus(StatusEnum.ONLINE.getCode());
@@ -95,15 +93,13 @@ public class S2SingerDemo extends S2BaseDemo {
return domainService.createDomain(domainReq, defaultUser);
}
public ModelResp addModel(DomainResp singerDomain, DatabaseResp s2Database,
TagObjectResp singerTagObject) throws Exception {
public ModelResp addModel(DomainResp singerDomain, DatabaseResp s2Database) throws Exception {
ModelReq modelReq = new ModelReq();
modelReq.setName("歌手库");
modelReq.setBizName("singer");
modelReq.setDescription("歌手库");
modelReq.setDatabaseId(s2Database.getId());
modelReq.setDomainId(singerDomain.getId());
modelReq.setTagObjectId(singerTagObject.getId());
modelReq.setViewers(Arrays.asList("admin", "tom", "jack"));
modelReq.setViewOrgs(Collections.singletonList("1"));
modelReq.setAdmins(Collections.singletonList("admin"));
@@ -128,7 +124,14 @@ public class S2SingerDemo extends S2BaseDemo {
modelDetail.setSqlQuery("select singer_name, act_area, song_name, genre, "
+ "js_play_cnt, down_cnt, favor_cnt from singer");
modelReq.setModelDetail(modelDetail);
return modelService.createModel(modelReq, defaultUser);
ModelResp modelResp = modelService.createModel(modelReq, defaultUser);
// create dict conf for dimensions
enableDimensionValue(getDimension("act_area", modelResp));
enableDimensionValue(getDimension("genre", modelResp));
enableDimensionValue(getDimension("singer_name", modelResp));
return modelResp;
}
private void addTags(ModelResp model) {

View File

@@ -182,7 +182,7 @@ public class S2VisitsDemo extends S2BaseDemo {
public DomainResp addDomain() {
DomainReq domainReq = new DomainReq();
domainReq.setName("产品数据");
domainReq.setName("产品数据");
domainReq.setBizName("supersonic");
domainReq.setParentId(0L);
domainReq.setStatus(StatusEnum.ONLINE.getCode());

View File

@@ -1044,11 +1044,11 @@ insert INTO artist(artist_name,citizenship,gender,g_name) VALUES ('Michel','英
-------S2CompanyDemo
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','微软','西雅图','1975','盖茨','纳德拉',102300000000,40000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','特斯拉','加州','2003','艾伯哈德','马斯克',376800000000,103699);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','谷歌','加州','1998','拉里佩奇','劈柴',321600000000,56310);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','亚马逊','加州','1994','贝索斯','贝索斯',28800000000,179000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','英伟达','杭州','1993','黄仁勋','黄仁勋',67500000000,20000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','微软','西雅图','1975','盖茨','纳德拉',102300000000,210000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','特斯拉','加州','2003','艾伯哈德','马斯克',376800000000,140473);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','谷歌','加州','1998','拉里佩奇','劈柴',321600000000,182503);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','亚马逊','加州','1994','贝索斯','贝索斯',28800000000,950000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','英伟达','杭州','1993','黄仁勋','黄仁勋',67500000000,29000);
insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_131','Office','1990','item_enterprise_13_131','盖茨',50000000);
insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_132','Windows','1991','item_enterprise_13_131','盖茨',50000000);
@@ -1063,24 +1063,22 @@ insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_131',10,10,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_132',10,10,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_133',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_134',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_135',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_136',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_137',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_138',80,80,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_139',10,10,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_140',10,10,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_131',500000000, 300000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_132',600000000, 300000000,20,20);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_133',700000000, 300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_134',500000000, 300000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_135',600000000, 300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_136',700000000, 300000000,40,40);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_137',800000000, 300000000,50,50);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_138',400000000, 300000000,20,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_139',300000000, 300000000,60,70);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_140',900000000, 300000000,80,100);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_133',30,30,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_134',20,20,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_135',40,50,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_136',20,30,40);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_137',10,30,50);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_138',40,30,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_139',20,10,80);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_140',20,10,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_131',500000000, 13100000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_132',600000000, 13200000000,20,20);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_133',700000000, 13300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_134',500000000, 13400000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_135',600000000, 13500000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_136',700000000, 13600000000,40,40);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_137',800000000, 13700000000,50,50);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_138',400000000, 13800000000,20,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_139',300000000, 13900000000,60,70);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_140',900000000, 14000000000,80,100);

View File

@@ -21,7 +21,7 @@ s2:
date: true
demo:
names: S2VisitsDemo,S2SingerDemo,S2CompanyDemo,S2SmallTalkDemo,
names: S2VisitsDemo,S2SingerDemo,S2CompanyDemo,S2SmallTalkDemo
enableLLM: true
authentication:

View File

@@ -27,6 +27,11 @@ import static com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum.SUM;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MetricTest extends BaseTest {
@Test
public void testMetric() throws Exception {
QueryResult actualResult = submitNewChat("超音数 访问次数", DataUtils.metricAgentId);
}
@Test
public void testMetricFilter() throws Exception {
QueryResult actualResult = submitNewChat("alice的访问次数", DataUtils.metricAgentId);

View File

@@ -1,10 +1,12 @@
import { Spin, Switch, Tooltip } from 'antd';
import { Space, Spin, Switch, Tooltip, message } from 'antd';
import { CheckCircleFilled, InfoCircleOutlined } from '@ant-design/icons';
import { PREFIX_CLS, MsgContentTypeEnum } from '../../common/constants';
import { MsgDataType } from '../../common/type';
import ChatMsg from '../ChatMsg';
import WebPage from '../ChatMsg/WebPage';
import Loading from './Loading';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { solarizedlight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import React, { ReactNode, useState } from 'react';
type Props = {
@@ -43,10 +45,10 @@ const ExecuteItem: React.FC<Props> = ({
const prefixCls = `${PREFIX_CLS}-item`;
const [showMsgContentTable, setShowMsgContentTable] = useState<boolean>(false);
const [msgContentType, setMsgContentType] = useState<MsgContentTypeEnum>();
const [showErrMsg, setShowErrMsg] = useState<boolean>(false);
const titlePrefix = queryMode === 'PLAIN_TEXT' || queryMode === 'WEB_SERVICE' ? '问答' : '数据';
const getNodeTip = (title: ReactNode, tip?: string) => {
const getNodeTip = (title: ReactNode, tip?: string | ReactNode) => {
return (
<>
<div className={`${prefixCls}-title-bar`}>
@@ -65,21 +67,38 @@ const ExecuteItem: React.FC<Props> = ({
return getNodeTip(`${titlePrefix}查询中`);
}
const handleCopy = (_: string, result: any) => {
result ? message.success('复制SQL成功', 1) : message.error('复制SQL失败', 1);
};
if (executeTip) {
return getNodeTip(
<>
<span>{titlePrefix}</span>
{executeErrorMsg && (
<Tooltip title={executeErrorMsg}>
<Space>
<InfoCircleOutlined style={{ marginLeft: 5, color: 'red' }} />
</Tooltip>
<a
onClick={() => {
setShowErrMsg(!showErrMsg);
}}
>
{!showErrMsg ? '查看' : '收起'}
</a>
</Space>
)}
{!!data?.queryTimeCost && isDeveloper && (
<span className={`${prefixCls}-title-tip`}>(: {data.queryTimeCost}ms)</span>
)}
</>,
executeTip
<>
{showErrMsg && (
<SyntaxHighlighter className={`${prefixCls}-code`} language="sql" style={solarizedlight}>
{executeErrorMsg}
</SyntaxHighlighter>
)}
</>
);
}

View File

@@ -443,7 +443,6 @@ const ChatItem: React.FC<Props> = ({
: ''}
</div>
<div className={contentClass}>
{/* {!isSimpleMode && ( */}
<>
{currentAgent?.enableFeedback === 1 && !questionId && showExpandParseTip && (
<div style={{ marginBottom: 10 }}>
@@ -489,7 +488,6 @@ const ChatItem: React.FC<Props> = ({
/>
)}
</>
{/* )} */}
{executeMode && (
<Spin spinning={entitySwitchLoading}>

View File

@@ -207,6 +207,15 @@
color: var(--text-color);
}
&-code {
margin-top: 10px !important;
padding: 6px 14px 8px !important;
border: 1px solid var(--border-color-base) !important;
border-radius: 4px !important;
background: #f5f8fb !important;
max-width: calc(100vw - 410px);
}
&-execute-title-bar {
display: flex;
align-items: center;

View File

@@ -13,11 +13,12 @@ import moment from 'moment';
type Props = {
data: MsgDataType;
size?: SizeType;
question: string;
loading?: boolean;
onApplyAuth?: (model: string) => void;
};
const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => {
const Table: React.FC<Props> = ({ data, size, loading, question, onApplyAuth }) => {
const { entityInfo, queryColumns, queryResults } = data;
const prefixCls = `${CLS_PREFIX}-table`;
@@ -27,6 +28,13 @@ const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => {
dataIndex: nameEn,
key: nameEn,
title: name || nameEn,
defaultSortOrder: 'descend',
sorter:
showType === 'NUMBER'
? (a, b) => {
return a[nameEn] - b[nameEn];
}
: undefined,
render: (value: string | number) => {
if (!authorized) {
return (
@@ -76,9 +84,11 @@ const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => {
const dataSource = dateColumn
? queryResults.sort((a, b) => moment(a[dateColumn.nameEn]).diff(moment(b[dateColumn.nameEn])))
: queryResults;
return (
<div className={prefixCls}>
<div className={`${prefixCls}-top-bar`}>
<div className={`${prefixCls}-indicator-name`}>{question}</div>
</div>
<AntTable
pagination={
queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] }

View File

@@ -26,6 +26,22 @@
color: var(--text-color-third);
}
&-top-bar {
display: flex;
align-items: baseline;
flex-wrap: wrap;
column-gap: 8px;
row-gap: 12px;
font-style: italic;
margin-bottom: 15px;
}
&-indicator-name {
font-size: 14px;
color: var(--text-color);
font-weight: 500;
margin-top: 2px;
}
&-filter-item {
display: flex;
align-items: center;

View File

@@ -180,6 +180,7 @@ const ChatMsg: React.FC<Props> = ({
case MsgContentTypeEnum.TABLE:
return (
<Table
question={question}
data={{ ...data, queryColumns: columns, queryResults: dataSource }}
loading={loading}
/>
@@ -221,6 +222,7 @@ const ChatMsg: React.FC<Props> = ({
default:
return (
<Table
question={question}
data={{ ...data, queryColumns: columns, queryResults: dataSource }}
loading={loading}
/>

View File

@@ -18,6 +18,7 @@ export default defineConfig({
API_BASE_URL: '/api/semantic/', // 直接在define中挂载裸露的全局变量还需要配置eslintts相关配置才能导致在使用中不会飘红冗余较高这里挂在进程环境下
CHAT_API_BASE_URL: '/api/chat/',
AUTH_API_BASE_URL: '/api/auth/',
SHOW_TAG: false,
...ENV_CONFIG,
},
},

View File

@@ -115,12 +115,12 @@ const ROUTES = [
},
],
},
{
path: '/tag',
name: 'tag',
component: './SemanticModel/Insights',
envEnableList: [ENV_KEY.SEMANTIC],
hideInMenu: process.env.SHOW_TAG ? false : true,
routes: [
{
path: '/tag',

View File

@@ -69,7 +69,7 @@
"@umijs/route-utils": "2.2.2",
"ace-builds": "^1.4.12",
"ahooks": "^3.7.7",
"antd": "5.11.2",
"antd": "^5.17.4",
"classnames": "^2.2.6",
"compression-webpack-plugin": "^11.0.0",
"copy-to-clipboard": "^3.3.1",

View File

@@ -38,6 +38,7 @@ const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
exportTagButton: {
key: 'exportTagButton',
label: '导出为标签',
hidden: !!!process.env.SHOW_TAG,
icon: <ExportOutlined />,
disabled: disabledList?.includes('exportTagButton'),
},
@@ -142,9 +143,11 @@ const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
icon: <DeleteOutlined />,
disabled: disabledList?.includes('batchDelete'),
},
].filter((item) => {
]
.filter((item) => {
return !hiddenList.includes(item.key);
});
})
.filter((item) => !!!item.hidden);
const popoverConfig = {
title: '选择下载区间',

View File

@@ -217,7 +217,11 @@ const MemorySection = ({ agentId }: Props) => {
};
const loadMemoryList = async (
{ filtersValue, current }: { filtersValue?: any; current?: number } = {},
{
filtersValue,
current,
pageSize,
}: { filtersValue?: any; current?: number; pageSize?: number } = {},
sort?: any,
) => {
if (!agentId) {
@@ -249,10 +253,11 @@ const MemorySection = ({ agentId }: Props) => {
agentId,
chatMemoryFilter: filtersValue || filters,
current: current || 1,
pageSize,
...sortParams,
});
setLoading(false);
const { list, total, pageSize, pageNum } = res.data;
const { list, total, pageNum } = res.data;
setDataSource(list);
setPagination({
pageSize,

View File

@@ -35,15 +35,20 @@ export function getMetricList(modelId: number) {
});
}
export function getMemeoryList(data: { agentId: number; chatMemoryFilter: any; current: number }) {
const { agentId, chatMemoryFilter, current } = data;
export function getMemeoryList(data: {
agentId: number;
chatMemoryFilter: any;
current: number;
pageSize: number;
}) {
const { agentId, chatMemoryFilter, current, pageSize } = data;
return request<Result<{ list: MetricType[] }>>('/api/chat/memory/pageMemories', {
method: 'POST',
data: {
...data,
chatMemoryFilter: { agentId, ...chatMemoryFilter },
current,
pageSize: 10,
pageSize: pageSize || 10,
sort: 'desc',
// orderCondition: 'updatedAt',
},

View File

@@ -190,14 +190,14 @@ const ModelBasicForm: React.FC<Props> = ({
<FormItem name="description" label="模型描述">
<TextArea placeholder="请输入模型描述" />
</FormItem>
<FormItem name={['ext', 'usId']} label="调度任务ID">
{/* <FormItem name={['ext', 'usId']} label="调度任务ID">
<Select
mode="tags"
placeholder="输入ID后回车确认多ID输入、复制粘贴支持英文逗号自动分隔"
tokenSeparators={[',']}
maxTagCount={9}
/>
</FormItem>
</FormItem> */}
</Spin>
);
};

View File

@@ -229,7 +229,9 @@ const ModelFieldForm: React.FC<Props> = ({
);
}
if (type === EnumDataSourceType.MEASURES) {
const agg = fields.find((field) => field.expr === record.expr)?.agg;
const agg = record.expr
? fields.find((field) => field.expr === record.expr)?.agg
: undefined;
return (
<Select
placeholder="度量算子"
@@ -249,6 +251,8 @@ const ModelFieldForm: React.FC<Props> = ({
</Select>
);
}
if (process.env.SHOW_TAG) {
if (type === EnumDataSourceType.CATEGORICAL) {
const isTag = fields.find((field) => field.bizName === record.bizName)?.isTag;
return (
@@ -270,6 +274,30 @@ const ModelFieldForm: React.FC<Props> = ({
</Space>
);
}
}
if (process.env.SHOW_TAG) {
if (type === EnumDataSourceType.CATEGORICAL) {
const isTag = fields.find((field) => field.bizName === record.bizName)?.isTag;
return (
<Space>
<Space>
<span>:</span>
<Switch
defaultChecked
size="small"
checked={!!isTag}
onChange={(value) => {
handleFieldChange(record, 'isTag', value);
}}
/>
<Tooltip title="如果勾选,代表维度的取值都是一种“标签”,可用作对实体的圈选">
<ExclamationCircleOutlined />
</Tooltip>
</Space>
</Space>
);
}
}
if ([EnumDataSourceType.TIME, EnumDataSourceType.PARTITION_TIME].includes(type)) {
const dateFormat = fields.find((field) => field.bizName === record.bizName)?.dateFormat;
const timeGranularity = fields.find(

View File

@@ -33,14 +33,14 @@ export const modelDataClass = {
};
export const DIM_OPTIONS = [
{
label: '主键',
value: EnumDataSourceType.PRIMARY_KEY,
},
{
label: '外键',
value: EnumDataSourceType.FOREIGN_KEY,
},
// {
// label: '主键',
// value: EnumDataSourceType.PRIMARY_KEY,
// },
// {
// label: '外键',
// value: EnumDataSourceType.FOREIGN_KEY,
// },
{
label: '枚举',
value: EnumDataSourceType.CATEGORICAL,

View File

@@ -78,6 +78,9 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
const backward = () => setCurrentStep(currentStep - 1);
const queryModelDetail = async (modelId) => {
if (!modelId) {
return;
}
const { code, data } = await getModelDetail({ modelId });
if (code === 200) {
if (Array.isArray(data?.modelDetail?.fields)) {

View File

@@ -728,6 +728,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
<FormItem
name="isTag"
valuePropName="checked"
hidden={!!!process.env.SHOW_TAG}
getValueFromEvent={(value) => {
return value === true ? 1 : 0;
}}
@@ -749,8 +750,9 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
<Switch />
</Col>
</Row>
</FormItem>
<Divider />
</FormItem>
<FormItem>
<Row gutter={20}>
<Col flex="1 1 200px">

View File

@@ -48,6 +48,9 @@ const ModelRelationFormDrawer: React.FC<ModelRelationFormDrawerProps> = ({
}, [relationData]);
const queryModelDetail = async (modelId: number, isSource: boolean) => {
if (!modelId) {
return;
}
const { code, data } = await getModelDetail({ modelId });
if (code === 200) {
if (Array.isArray(data?.modelDetail?.identifiers)) {

View File

@@ -172,6 +172,7 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
dataIndex: 'isTag',
title: '是否标签',
// width: 90,
hideInTable: !!!process.env.SHOW_TAG,
render: (isTag) => {
switch (isTag) {
case 0:
@@ -324,7 +325,8 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
headerTitle={
<div style={{ marginLeft: 15 }}>
<TableHeaderFilter
components={[
components={
[
{
label: '维度搜索',
component: (
@@ -363,6 +365,7 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
},
{
label: '是否为标签',
hidden: !!!process.env.SHOW_TAG,
component: (
<Select
style={{ width: 145 }}
@@ -383,7 +386,8 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
/>
),
},
]}
].filter((item) => !!!item.hidden) as any
}
/>
</div>
}

View File

@@ -177,7 +177,7 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
{
dataIndex: 'isTag',
title: '是否标签',
// width: 90,
hideInTable: !!!process.env.SHOW_TAG,
render: (isTag) => {
switch (isTag) {
case 0:
@@ -353,13 +353,14 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
headerTitle={
<div style={{ marginLeft: 15 }}>
<TableHeaderFilter
components={[
components={
[
{
label: '指标搜索',
component: (
<Input.Search
style={{ width: 280 }}
placeholder="请输入ID/指标名称/英文名称/标签"
placeholder="请输入ID/指标名称/英文名称"
onSearch={(value) => {
setFilterParams((preState) => {
return {
@@ -392,6 +393,7 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
},
{
label: '是否为标签',
hidden: !!!process.env.SHOW_TAG,
component: (
<Select
style={{ width: 145 }}
@@ -412,7 +414,8 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
/>
),
},
]}
].filter((item) => !!!item.hidden) as any
}
/>
</div>
}

View File

@@ -305,6 +305,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
<InfoTagList />
</FormItem> */}
<Form.Item
hidden={!!!process.env.SHOW_TAG}
label={
<FormItemTitle
title={`设为标签`}

View File

@@ -73,7 +73,7 @@ const DomainManagerTab: React.FC<Props> = ({
{
label: '标签对象管理',
key: 'tagObjectManage',
hidden: !!domainData?.parentId,
hidden: !!!process.env.SHOW_TAG ? true : !!domainData?.parentId,
children: <TagObjectTable />,
},
{

View File

@@ -53,7 +53,7 @@ const DimensionMetricVisibleTableTransfer: React.FC<Props> = ({
{
dataIndex: 'isTag',
title: '是否标签',
// hidden: true,
hidden: true,
render: (isTag) => {
if (isTag) {
return <span style={{ color: '#0958d9' }}></span>;

View File

@@ -213,7 +213,7 @@ const DimensionValueSettingForm: React.FC<Props> = ({
>
{dimensionVisible && (
<Space size={20} style={{ marginBottom: 20 }}>
<Tooltip title={`立即将${KnowledgeConfigTypeWordingMap[type]}值导入字典`}>
<Tooltip title={`维度值可见后将定期启动导入任务,如果想立即启动可手动触发`}>
<Button
type="link"
size="small"

View File

@@ -713,6 +713,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
</FormItem>
<Form.Item
hidden={!!!process.env.SHOW_TAG}
label={
<FormItemTitle
title={`设为标签`}

View File

@@ -452,6 +452,9 @@ export function getUnAvailableItem(data: any): Promise<any> {
}
export function getModelDetail(data: any): Promise<any> {
if (!data.modelId) {
return;
}
return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`);
}

3568
webapp/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff