(improvement)(chat) Split chat into three modules: server, api, and core. (#594)

This commit is contained in:
lexluo09
2024-01-04 16:56:49 +08:00
committed by GitHub
parent 0858c13365
commit 023e84c420
337 changed files with 2407 additions and 2715 deletions

56
chat/server/pom.xml Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>chat</artifactId>
<groupId>com.tencent.supersonic</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>chat-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>auth-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>chat-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>headless-core</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>chat-core</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,46 @@
package com.tencent.supersonic.chat.server.config;
import com.tencent.supersonic.chat.api.pojo.request.ChatAggConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.RecordInfo;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString
public class ChatConfig {
/**
* database auto-increment primary key
*/
private Long id;
private Long modelId;
/**
* the chatDetailConfig about the model
*/
private ChatDetailConfigReq chatDetailConfig;
/**
* the chatAggConfig about the model
*/
private ChatAggConfigReq chatAggConfig;
private List<RecommendedQuestionReq> recommendedQuestions;
/**
* available status
*/
private StatusEnum status;
/**
* about createdBy, createdAt, updatedBy, updatedAt
*/
private RecordInfo recordInfo;
}

View File

@@ -0,0 +1,11 @@
package com.tencent.supersonic.chat.server.config;
import lombok.Data;
@Data
public class ChatConfigFilterInternal {
private Long id;
private Long modelId;
private Integer status;
}

View File

@@ -0,0 +1,85 @@
package com.tencent.supersonic.chat.server.listener;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import com.tencent.supersonic.chat.server.service.KnowledgeService;
import com.tencent.supersonic.chat.server.service.impl.SchemaService;
import com.tencent.supersonic.chat.server.service.impl.WordService;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@Order(2)
public class ApplicationStartedListener implements CommandLineRunner {
@Autowired
private KnowledgeService knowledgeService;
@Autowired
private WordService wordService;
@Autowired
private SchemaService schemaService;
@Override
public void run(String... args) {
updateKnowledgeDimValue();
}
public Boolean updateKnowledgeDimValue() {
Boolean isOk = false;
try {
log.debug("ApplicationStartedInit start");
List<DictWord> dictWords = wordService.getAllDictWords();
wordService.setPreDictWords(dictWords);
knowledgeService.reloadAllData(dictWords);
log.debug("ApplicationStartedInit end");
isOk = true;
} catch (Exception e) {
log.error("ApplicationStartedInit error", e);
}
return isOk;
}
public Boolean updateKnowledgeDimValueAsync() {
CompletableFuture.supplyAsync(() -> {
updateKnowledgeDimValue();
return null;
});
return true;
}
/***
* reload knowledge task
*/
@Scheduled(cron = "${reload.knowledge.corn:0 0/1 * * * ?}")
public void reloadKnowledge() {
log.debug("reloadKnowledge start");
try {
List<DictWord> dictWords = wordService.getAllDictWords();
List<DictWord> preDictWords = wordService.getPreDictWords();
if (CollectionUtils.isEqualCollection(dictWords, preDictWords)) {
log.debug("dictWords has not changed, reloadKnowledge end");
return;
}
log.info("dictWords has changed");
wordService.setPreDictWords(dictWords);
knowledgeService.updateOnlineKnowledge(wordService.getAllDictWords());
schemaService.getCache().refresh(SchemaService.ALL_CACHE);
} catch (Exception e) {
log.error("reloadKnowledge error", e);
}
log.debug("reloadKnowledge end");
}
}

View File

@@ -0,0 +1,51 @@
package com.tencent.supersonic.chat.server.listener;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import com.tencent.supersonic.chat.core.utils.HanlpHelper;
import com.tencent.supersonic.chat.server.service.impl.SchemaService;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.enums.DictWordType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Component
@Slf4j
public class SchemaDictUpdateListener implements ApplicationListener<DataEvent> {
@Autowired
private SchemaService schemaService;
@Async
@Override
public void onApplicationEvent(DataEvent dataEvent) {
if (CollectionUtils.isEmpty(dataEvent.getDataItems())) {
return;
}
schemaService.getCache().invalidateAll();
dataEvent.getDataItems().forEach(dataItem -> {
DictWord dictWord = new DictWord();
dictWord.setWord(dataItem.getName());
String sign = DictWordType.NATURE_SPILT;
String nature = sign + dataItem.getModelId() + sign + dataItem.getId()
+ sign + dataItem.getType().getName();
String natureWithFrequency = nature + " " + Constants.DEFAULT_FREQUENCY;
dictWord.setNature(nature);
dictWord.setNatureWithFrequency(natureWithFrequency);
if (EventType.ADD.equals(dataEvent.getEventType())) {
HanlpHelper.addToCustomDictionary(dictWord);
} else if (EventType.DELETE.equals(dataEvent.getEventType())) {
HanlpHelper.removeFromCustomDictionary(dictWord);
} else if (EventType.UPDATE.equals(dataEvent.getEventType())) {
HanlpHelper.removeFromCustomDictionary(dictWord);
dictWord.setWord(dataItem.getNewName());
HanlpHelper.addToCustomDictionary(dictWord);
}
});
}
}

View File

@@ -0,0 +1,206 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
public class AgentDO {
/**
*/
private Integer id;
/**
*/
private String name;
/**
*/
private String description;
/**
* 0 offline, 1 online
*/
private Integer status;
/**
*/
private String examples;
/**
*/
private String config;
/**
*/
private String createdBy;
/**
*/
private Date createdAt;
/**
*/
private String updatedBy;
/**
*/
private Date updatedAt;
/**
*/
private Integer enableSearch;
/**
* @return id
*/
public Integer getId() {
return id;
}
/**
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* @param name
*/
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
/**
* @return description
*/
public String getDescription() {
return description;
}
/**
* @param description
*/
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
/**
* 0 offline, 1 online
* @return status 0 offline, 1 online
*/
public Integer getStatus() {
return status;
}
/**
* 0 offline, 1 online
* @param status 0 offline, 1 online
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* @return examples
*/
public String getExamples() {
return examples;
}
/**
* @param examples
*/
public void setExamples(String examples) {
this.examples = examples == null ? null : examples.trim();
}
/**
* @return config
*/
public String getConfig() {
return config;
}
/**
* @param config
*/
public void setConfig(String config) {
this.config = config == null ? null : config.trim();
}
/**
* @return created_by
*/
public String getCreatedBy() {
return createdBy;
}
/**
* @param createdBy
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy == null ? null : createdBy.trim();
}
/**
* @return created_at
*/
public Date getCreatedAt() {
return createdAt;
}
/**
* @param createdAt
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/**
* @return updated_by
*/
public String getUpdatedBy() {
return updatedBy;
}
/**
* @param updatedBy
*/
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
}
/**
* @return updated_at
*/
public Date getUpdatedAt() {
return updatedAt;
}
/**
* @param updatedAt
*/
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
/**
* @return enable_search
*/
public Integer getEnableSearch() {
return enableSearch;
}
/**
* @param enableSearch
*/
public void setEnableSearch(Integer enableSearch) {
this.enableSearch = enableSearch;
}
}

View File

@@ -0,0 +1,38 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class ChatConfigDO {
/**
* database auto-increment primary key
*/
private Long id;
private Long modelId;
private String chatDetailConfig;
private String chatAggConfig;
private String recommendedQuestions;
private Integer status;
private String llmExamples;
/**
* record info
*/
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,15 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.io.Serializable;
import java.time.Instant;
import lombok.Data;
@Data
public class ChatContextDO implements Serializable {
private Integer chatId;
private Instant modifiedAt;
private String user;
private String queryText;
private String semanticParse;
}

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.Data;
@Data
public class ChatDO {
private long chatId;
private Integer agentId;
private String chatName;
private String createTime;
private String lastTime;
private String creator;
private String lastQuestion;
private int isDelete;
private int isTop;
}

View File

@@ -0,0 +1,142 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
public class ChatParseDO {
/**
* questionId
*/
private Long questionId;
/**
* chatId
*/
private Long chatId;
/**
* parseId
*/
private Integer parseId;
/**
* createTime
*/
private Date createTime;
/**
* queryText
*/
private String queryText;
/**
* userName
*/
private String userName;
/**
* parseInfo
*/
private String parseInfo;
/**
* isCandidate
*/
private Integer isCandidate;
/**
* return question_id
*/
public Long getQuestionId() {
return questionId;
}
/**
* questionId
*/
public void setQuestionId(Long questionId) {
this.questionId = questionId;
}
/**
* return create_time
*/
public Date getCreateTime() {
return createTime;
}
/**
* createTime
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* return user_name
*/
public String getUserName() {
return userName;
}
/**
* userName
*/
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
/**
* return chat_id
*/
public Long getChatId() {
return chatId;
}
/**
* chatId
*/
public void setChatId(Long chatId) {
this.chatId = chatId;
}
/**
* return query_text
*/
public String getQueryText() {
return queryText;
}
/**
* queryText
*/
public void setQueryText(String queryText) {
this.queryText = queryText == null ? null : queryText.trim();
}
public Integer getIsCandidate() {
return isCandidate;
}
public Integer getParseId() {
return parseId;
}
public String getParseInfo() {
return parseInfo;
}
public void setParseId(Integer parseId) {
this.parseId = parseId;
}
public void setIsCandidate(Integer isCandidate) {
this.isCandidate = isCandidate;
}
public void setParseInfo(String parseInfo) {
this.parseInfo = parseInfo;
}
}

View File

@@ -0,0 +1,50 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.Data;
import java.util.Date;
@Data
public class ChatQueryDO {
/**
*/
private Long questionId;
/**
*/
private Integer agentId;
/**
*/
private Date createTime;
/**
*/
private String userName;
/**
*/
private Integer queryState;
/**
*/
private Long chatId;
/**
*/
private Integer score;
/**
*/
private String feedback;
/**
*/
private String queryText;
/**
*/
private String queryResult;
private String similarQueries;
}

View File

@@ -0,0 +1,790 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ChatQueryDOExample {
/**
* s2_chat_query
*/
protected String orderByClause;
/**
* s2_chat_query
*/
protected boolean distinct;
/**
* s2_chat_query
*/
protected List<Criteria> oredCriteria;
/**
* s2_chat_query
*/
protected Integer limitStart;
/**
* s2_chat_query
*/
protected Integer limitEnd;
/**
* @mbg.generated
*/
public ChatQueryDOExample() {
oredCriteria = new ArrayList<Criteria>();
}
/**
* @mbg.generated
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* @mbg.generated
*/
public String getOrderByClause() {
return orderByClause;
}
/**
* @mbg.generated
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* @mbg.generated
*/
public boolean isDistinct() {
return distinct;
}
/**
* @mbg.generated
*/
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
/**
* @mbg.generated
*/
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
/**
* @mbg.generated
*/
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
/**
* @mbg.generated
*/
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
/**
* @mbg.generated
*/
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
/**
* @mbg.generated
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
/**
* @mbg.generated
*/
public void setLimitStart(Integer limitStart) {
this.limitStart = limitStart;
}
/**
* @mbg.generated
*/
public Integer getLimitStart() {
return limitStart;
}
/**
* @mbg.generated
*/
public void setLimitEnd(Integer limitEnd) {
this.limitEnd = limitEnd;
}
/**
* @mbg.generated
*/
public Integer getLimitEnd() {
return limitEnd;
}
/**
* s2_chat_query null
*/
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andQuestionIdIsNull() {
addCriterion("question_id is null");
return (Criteria) this;
}
public Criteria andQuestionIdIsNotNull() {
addCriterion("question_id is not null");
return (Criteria) this;
}
public Criteria andQuestionIdEqualTo(Long value) {
addCriterion("question_id =", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdNotEqualTo(Long value) {
addCriterion("question_id <>", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdGreaterThan(Long value) {
addCriterion("question_id >", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdGreaterThanOrEqualTo(Long value) {
addCriterion("question_id >=", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdLessThan(Long value) {
addCriterion("question_id <", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdLessThanOrEqualTo(Long value) {
addCriterion("question_id <=", value, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdIn(List<Long> values) {
addCriterion("question_id in", values, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdNotIn(List<Long> values) {
addCriterion("question_id not in", values, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdBetween(Long value1, Long value2) {
addCriterion("question_id between", value1, value2, "questionId");
return (Criteria) this;
}
public Criteria andQuestionIdNotBetween(Long value1, Long value2) {
addCriterion("question_id not between", value1, value2, "questionId");
return (Criteria) this;
}
public Criteria andAgentIdIsNull() {
addCriterion("agent_id is null");
return (Criteria) this;
}
public Criteria andAgentIdIsNotNull() {
addCriterion("agent_id is not null");
return (Criteria) this;
}
public Criteria andAgentIdEqualTo(Integer value) {
addCriterion("agent_id =", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdNotEqualTo(Integer value) {
addCriterion("agent_id <>", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdGreaterThan(Integer value) {
addCriterion("agent_id >", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdGreaterThanOrEqualTo(Integer value) {
addCriterion("agent_id >=", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdLessThan(Integer value) {
addCriterion("agent_id <", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdLessThanOrEqualTo(Integer value) {
addCriterion("agent_id <=", value, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdIn(List<Integer> values) {
addCriterion("agent_id in", values, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdNotIn(List<Integer> values) {
addCriterion("agent_id not in", values, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdBetween(Integer value1, Integer value2) {
addCriterion("agent_id between", value1, value2, "agentId");
return (Criteria) this;
}
public Criteria andAgentIdNotBetween(Integer value1, Integer value2) {
addCriterion("agent_id not between", value1, value2, "agentId");
return (Criteria) this;
}
public Criteria andCreateTimeIsNull() {
addCriterion("create_time is null");
return (Criteria) this;
}
public Criteria andCreateTimeIsNotNull() {
addCriterion("create_time is not null");
return (Criteria) this;
}
public Criteria andCreateTimeEqualTo(Date value) {
addCriterion("create_time =", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotEqualTo(Date value) {
addCriterion("create_time <>", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThan(Date value) {
addCriterion("create_time >", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThanOrEqualTo(Date value) {
addCriterion("create_time >=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThan(Date value) {
addCriterion("create_time <", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThanOrEqualTo(Date value) {
addCriterion("create_time <=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeIn(List<Date> values) {
addCriterion("create_time in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotIn(List<Date> values) {
addCriterion("create_time not in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeBetween(Date value1, Date value2) {
addCriterion("create_time between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotBetween(Date value1, Date value2) {
addCriterion("create_time not between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andUserNameIsNull() {
addCriterion("user_name is null");
return (Criteria) this;
}
public Criteria andUserNameIsNotNull() {
addCriterion("user_name is not null");
return (Criteria) this;
}
public Criteria andUserNameEqualTo(String value) {
addCriterion("user_name =", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameNotEqualTo(String value) {
addCriterion("user_name <>", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameGreaterThan(String value) {
addCriterion("user_name >", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameGreaterThanOrEqualTo(String value) {
addCriterion("user_name >=", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameLessThan(String value) {
addCriterion("user_name <", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameLessThanOrEqualTo(String value) {
addCriterion("user_name <=", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameLike(String value) {
addCriterion("user_name like", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameNotLike(String value) {
addCriterion("user_name not like", value, "userName");
return (Criteria) this;
}
public Criteria andUserNameIn(List<String> values) {
addCriterion("user_name in", values, "userName");
return (Criteria) this;
}
public Criteria andUserNameNotIn(List<String> values) {
addCriterion("user_name not in", values, "userName");
return (Criteria) this;
}
public Criteria andUserNameBetween(String value1, String value2) {
addCriterion("user_name between", value1, value2, "userName");
return (Criteria) this;
}
public Criteria andUserNameNotBetween(String value1, String value2) {
addCriterion("user_name not between", value1, value2, "userName");
return (Criteria) this;
}
public Criteria andQueryStateIsNull() {
addCriterion("query_state is null");
return (Criteria) this;
}
public Criteria andQueryStateIsNotNull() {
addCriterion("query_state is not null");
return (Criteria) this;
}
public Criteria andQueryStateEqualTo(Integer value) {
addCriterion("query_state =", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateNotEqualTo(Integer value) {
addCriterion("query_state <>", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateGreaterThan(Integer value) {
addCriterion("query_state >", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateGreaterThanOrEqualTo(Integer value) {
addCriterion("query_state >=", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateLessThan(Integer value) {
addCriterion("query_state <", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateLessThanOrEqualTo(Integer value) {
addCriterion("query_state <=", value, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateIn(List<Integer> values) {
addCriterion("query_state in", values, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateNotIn(List<Integer> values) {
addCriterion("query_state not in", values, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateBetween(Integer value1, Integer value2) {
addCriterion("query_state between", value1, value2, "queryState");
return (Criteria) this;
}
public Criteria andQueryStateNotBetween(Integer value1, Integer value2) {
addCriterion("query_state not between", value1, value2, "queryState");
return (Criteria) this;
}
public Criteria andChatIdIsNull() {
addCriterion("chat_id is null");
return (Criteria) this;
}
public Criteria andChatIdIsNotNull() {
addCriterion("chat_id is not null");
return (Criteria) this;
}
public Criteria andChatIdEqualTo(Long value) {
addCriterion("chat_id =", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdNotEqualTo(Long value) {
addCriterion("chat_id <>", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdGreaterThan(Long value) {
addCriterion("chat_id >", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdGreaterThanOrEqualTo(Long value) {
addCriterion("chat_id >=", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdLessThan(Long value) {
addCriterion("chat_id <", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdLessThanOrEqualTo(Long value) {
addCriterion("chat_id <=", value, "chatId");
return (Criteria) this;
}
public Criteria andChatIdIn(List<Long> values) {
addCriterion("chat_id in", values, "chatId");
return (Criteria) this;
}
public Criteria andChatIdNotIn(List<Long> values) {
addCriterion("chat_id not in", values, "chatId");
return (Criteria) this;
}
public Criteria andChatIdBetween(Long value1, Long value2) {
addCriterion("chat_id between", value1, value2, "chatId");
return (Criteria) this;
}
public Criteria andChatIdNotBetween(Long value1, Long value2) {
addCriterion("chat_id not between", value1, value2, "chatId");
return (Criteria) this;
}
public Criteria andScoreIsNull() {
addCriterion("score is null");
return (Criteria) this;
}
public Criteria andScoreIsNotNull() {
addCriterion("score is not null");
return (Criteria) this;
}
public Criteria andScoreEqualTo(Integer value) {
addCriterion("score =", value, "score");
return (Criteria) this;
}
public Criteria andScoreNotEqualTo(Integer value) {
addCriterion("score <>", value, "score");
return (Criteria) this;
}
public Criteria andScoreGreaterThan(Integer value) {
addCriterion("score >", value, "score");
return (Criteria) this;
}
public Criteria andScoreGreaterThanOrEqualTo(Integer value) {
addCriterion("score >=", value, "score");
return (Criteria) this;
}
public Criteria andScoreLessThan(Integer value) {
addCriterion("score <", value, "score");
return (Criteria) this;
}
public Criteria andScoreLessThanOrEqualTo(Integer value) {
addCriterion("score <=", value, "score");
return (Criteria) this;
}
public Criteria andScoreIn(List<Integer> values) {
addCriterion("score in", values, "score");
return (Criteria) this;
}
public Criteria andScoreNotIn(List<Integer> values) {
addCriterion("score not in", values, "score");
return (Criteria) this;
}
public Criteria andScoreBetween(Integer value1, Integer value2) {
addCriterion("score between", value1, value2, "score");
return (Criteria) this;
}
public Criteria andScoreNotBetween(Integer value1, Integer value2) {
addCriterion("score not between", value1, value2, "score");
return (Criteria) this;
}
public Criteria andFeedbackIsNull() {
addCriterion("feedback is null");
return (Criteria) this;
}
public Criteria andFeedbackIsNotNull() {
addCriterion("feedback is not null");
return (Criteria) this;
}
public Criteria andFeedbackEqualTo(String value) {
addCriterion("feedback =", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackNotEqualTo(String value) {
addCriterion("feedback <>", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackGreaterThan(String value) {
addCriterion("feedback >", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackGreaterThanOrEqualTo(String value) {
addCriterion("feedback >=", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackLessThan(String value) {
addCriterion("feedback <", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackLessThanOrEqualTo(String value) {
addCriterion("feedback <=", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackLike(String value) {
addCriterion("feedback like", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackNotLike(String value) {
addCriterion("feedback not like", value, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackIn(List<String> values) {
addCriterion("feedback in", values, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackNotIn(List<String> values) {
addCriterion("feedback not in", values, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackBetween(String value1, String value2) {
addCriterion("feedback between", value1, value2, "feedback");
return (Criteria) this;
}
public Criteria andFeedbackNotBetween(String value1, String value2) {
addCriterion("feedback not between", value1, value2, "feedback");
return (Criteria) this;
}
}
/**
* s2_chat_query
*/
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
/**
* s2_chat_query null
*/
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
}
}

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
public enum CostType {
MAPPER(1, "mapper"),
PARSER(2, "parser"),
QUERY(3, "query"),
PROCESSOR(4, "processor");
private Integer type;
private String name;
CostType(Integer type, String name) {
this.type = type;
this.name = name;
}
public Integer getType() {
return type;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
import lombok.Data;
@Data
public class DictConfDO {
private Long id;
private Long modelId;
private String dimValueInfos;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,38 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
import lombok.Data;
import lombok.ToString;
import org.apache.commons.codec.digest.DigestUtils;
@Data
@ToString
public class DictTaskDO {
private Long id;
private String name;
private String description;
private String command;
private String commandMd5;
private String dimIds;
private Integer status;
private String createdBy;
private Date createdAt;
private Double progress;
private Long elapsedMs;
public String getCommandMd5() {
return DigestUtils.md5Hex(command);
}
}

View File

@@ -0,0 +1,37 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import com.tencent.supersonic.chat.core.config.DefaultMetric;
import com.tencent.supersonic.chat.core.config.Dim4Dict;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class DimValueDO {
private Long modelId;
private List<DefaultMetric> defaultMetricDescList = new ArrayList<>();
private List<Dim4Dict> dimensions = new ArrayList<>();
public DimValueDO setModelId(Long modelId) {
this.modelId = modelId;
return this;
}
public DimValueDO setDefaultMetricIds(List<DefaultMetric> defaultMetricDescList) {
this.defaultMetricDescList = defaultMetricDescList;
return this;
}
public DimValueDO setDimensions(List<Dim4Dict> dimensions) {
this.dimensions = dimensions;
return this;
}
}

View File

@@ -0,0 +1,256 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.Date;
public class PluginDO {
/**
*
*/
private Long id;
/**
* DASHBOARD,WIDGET,URL
*/
private String type;
/**
*
*/
private String model;
/**
*
*/
private String pattern;
/**
*
*/
private String parseMode;
/**
*
*/
private String name;
/**
*
*/
private Date createdAt;
/**
*
*/
private String createdBy;
/**
*
*/
private Date updatedAt;
/**
*
*/
private String updatedBy;
/**
*
*/
private String parseModeConfig;
/**
*
*/
private String config;
/**
*
*/
private String comment;
/**
* @return id
*/
public Long getId() {
return id;
}
/**
* @param id
*/
public void setId(Long id) {
this.id = id;
}
/**
* DASHBOARD,WIDGET,URL
*
* @return type DASHBOARD,WIDGET,URL
*/
public String getType() {
return type;
}
/**
* DASHBOARD,WIDGET,URL
*
* @param type DASHBOARD,WIDGET,URL
*/
public void setType(String type) {
this.type = type == null ? null : type.trim();
}
/**
* @return model
*/
public String getModel() {
return model;
}
/**
* @param model
*/
public void setModel(String model) {
this.model = model == null ? null : model.trim();
}
/**
* @return pattern
*/
public String getPattern() {
return pattern;
}
/**
* @param pattern
*/
public void setPattern(String pattern) {
this.pattern = pattern == null ? null : pattern.trim();
}
/**
* @return parse_mode
*/
public String getParseMode() {
return parseMode;
}
/**
* @param parseMode
*/
public void setParseMode(String parseMode) {
this.parseMode = parseMode == null ? null : parseMode.trim();
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* @param name
*/
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
/**
* @return created_at
*/
public Date getCreatedAt() {
return createdAt;
}
/**
* @param createdAt
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/**
* @return created_by
*/
public String getCreatedBy() {
return createdBy;
}
/**
* @param createdBy
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy == null ? null : createdBy.trim();
}
/**
* @return updated_at
*/
public Date getUpdatedAt() {
return updatedAt;
}
/**
* @param updatedAt
*/
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
/**
* @return updated_by
*/
public String getUpdatedBy() {
return updatedBy;
}
/**
* @param updatedBy
*/
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
}
/**
* @return parse_mode_config
*/
public String getParseModeConfig() {
return parseModeConfig;
}
/**
* @param parseModeConfig
*/
public void setParseModeConfig(String parseModeConfig) {
this.parseModeConfig = parseModeConfig == null ? null : parseModeConfig.trim();
}
/**
* @return config
*/
public String getConfig() {
return config;
}
/**
* @param config
*/
public void setConfig(String config) {
this.config = config == null ? null : config.trim();
}
/**
* @return comment
*/
public String getComment() {
return comment;
}
/**
* @param comment
*/
public void setComment(String comment) {
this.comment = comment == null ? null : comment.trim();
}
}

View File

@@ -0,0 +1,960 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class PluginDOExample {
/**
* s2_plugin
*/
protected String orderByClause;
/**
* s2_plugin
*/
protected boolean distinct;
/**
* s2_plugin
*/
protected List<Criteria> oredCriteria;
/**
* s2_plugin
*/
protected Integer limitStart;
/**
* s2_plugin
*/
protected Integer limitEnd;
/**
* @mbg.generated
*/
public PluginDOExample() {
oredCriteria = new ArrayList<Criteria>();
}
/**
* @mbg.generated
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* @mbg.generated
*/
public String getOrderByClause() {
return orderByClause;
}
/**
* @mbg.generated
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* @mbg.generated
*/
public boolean isDistinct() {
return distinct;
}
/**
* @mbg.generated
*/
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
/**
* @mbg.generated
*/
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
/**
* @mbg.generated
*/
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
/**
* @mbg.generated
*/
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
/**
* @mbg.generated
*/
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
/**
* @mbg.generated
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
/**
* @mbg.generated
*/
public void setLimitStart(Integer limitStart) {
this.limitStart = limitStart;
}
/**
* @mbg.generated
*/
public Integer getLimitStart() {
return limitStart;
}
/**
* @mbg.generated
*/
public void setLimitEnd(Integer limitEnd) {
this.limitEnd = limitEnd;
}
/**
* @mbg.generated
*/
public Integer getLimitEnd() {
return limitEnd;
}
/**
* s2_plugin null
*/
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(Long value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(Long value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(Long value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(Long value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(Long value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(Long value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<Long> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<Long> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(Long value1, Long value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(Long value1, Long value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andTypeIsNull() {
addCriterion("type is null");
return (Criteria) this;
}
public Criteria andTypeIsNotNull() {
addCriterion("type is not null");
return (Criteria) this;
}
public Criteria andTypeEqualTo(String value) {
addCriterion("type =", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotEqualTo(String value) {
addCriterion("type <>", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThan(String value) {
addCriterion("type >", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThanOrEqualTo(String value) {
addCriterion("type >=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThan(String value) {
addCriterion("type <", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThanOrEqualTo(String value) {
addCriterion("type <=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLike(String value) {
addCriterion("type like", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotLike(String value) {
addCriterion("type not like", value, "type");
return (Criteria) this;
}
public Criteria andTypeIn(List<String> values) {
addCriterion("type in", values, "type");
return (Criteria) this;
}
public Criteria andTypeNotIn(List<String> values) {
addCriterion("type not in", values, "type");
return (Criteria) this;
}
public Criteria andTypeBetween(String value1, String value2) {
addCriterion("type between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andTypeNotBetween(String value1, String value2) {
addCriterion("type not between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andModelIsNull() {
addCriterion("model is null");
return (Criteria) this;
}
public Criteria andModelIsNotNull() {
addCriterion("model is not null");
return (Criteria) this;
}
public Criteria andModelEqualTo(String value) {
addCriterion("model =", value, "model");
return (Criteria) this;
}
public Criteria andModelNotEqualTo(String value) {
addCriterion("model <>", value, "model");
return (Criteria) this;
}
public Criteria andModelGreaterThan(String value) {
addCriterion("model >", value, "model");
return (Criteria) this;
}
public Criteria andModelGreaterThanOrEqualTo(String value) {
addCriterion("model >=", value, "model");
return (Criteria) this;
}
public Criteria andModelLessThan(String value) {
addCriterion("model <", value, "model");
return (Criteria) this;
}
public Criteria andModelLessThanOrEqualTo(String value) {
addCriterion("model <=", value, "model");
return (Criteria) this;
}
public Criteria andModelLike(String value) {
addCriterion("model like", value, "model");
return (Criteria) this;
}
public Criteria andModelNotLike(String value) {
addCriterion("model not like", value, "model");
return (Criteria) this;
}
public Criteria andModelIn(List<String> values) {
addCriterion("model in", values, "model");
return (Criteria) this;
}
public Criteria andModelNotIn(List<String> values) {
addCriterion("model not in", values, "model");
return (Criteria) this;
}
public Criteria andModelBetween(String value1, String value2) {
addCriterion("model between", value1, value2, "model");
return (Criteria) this;
}
public Criteria andModelNotBetween(String value1, String value2) {
addCriterion("model not between", value1, value2, "model");
return (Criteria) this;
}
public Criteria andPatternIsNull() {
addCriterion("pattern is null");
return (Criteria) this;
}
public Criteria andPatternIsNotNull() {
addCriterion("pattern is not null");
return (Criteria) this;
}
public Criteria andPatternEqualTo(String value) {
addCriterion("pattern =", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternNotEqualTo(String value) {
addCriterion("pattern <>", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternGreaterThan(String value) {
addCriterion("pattern >", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternGreaterThanOrEqualTo(String value) {
addCriterion("pattern >=", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternLessThan(String value) {
addCriterion("pattern <", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternLessThanOrEqualTo(String value) {
addCriterion("pattern <=", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternLike(String value) {
addCriterion("pattern like", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternNotLike(String value) {
addCriterion("pattern not like", value, "pattern");
return (Criteria) this;
}
public Criteria andPatternIn(List<String> values) {
addCriterion("pattern in", values, "pattern");
return (Criteria) this;
}
public Criteria andPatternNotIn(List<String> values) {
addCriterion("pattern not in", values, "pattern");
return (Criteria) this;
}
public Criteria andPatternBetween(String value1, String value2) {
addCriterion("pattern between", value1, value2, "pattern");
return (Criteria) this;
}
public Criteria andPatternNotBetween(String value1, String value2) {
addCriterion("pattern not between", value1, value2, "pattern");
return (Criteria) this;
}
public Criteria andParseModeIsNull() {
addCriterion("parse_mode is null");
return (Criteria) this;
}
public Criteria andParseModeIsNotNull() {
addCriterion("parse_mode is not null");
return (Criteria) this;
}
public Criteria andParseModeEqualTo(String value) {
addCriterion("parse_mode =", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeNotEqualTo(String value) {
addCriterion("parse_mode <>", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeGreaterThan(String value) {
addCriterion("parse_mode >", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeGreaterThanOrEqualTo(String value) {
addCriterion("parse_mode >=", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeLessThan(String value) {
addCriterion("parse_mode <", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeLessThanOrEqualTo(String value) {
addCriterion("parse_mode <=", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeLike(String value) {
addCriterion("parse_mode like", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeNotLike(String value) {
addCriterion("parse_mode not like", value, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeIn(List<String> values) {
addCriterion("parse_mode in", values, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeNotIn(List<String> values) {
addCriterion("parse_mode not in", values, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeBetween(String value1, String value2) {
addCriterion("parse_mode between", value1, value2, "parseMode");
return (Criteria) this;
}
public Criteria andParseModeNotBetween(String value1, String value2) {
addCriterion("parse_mode not between", value1, value2, "parseMode");
return (Criteria) this;
}
public Criteria andNameIsNull() {
addCriterion("name is null");
return (Criteria) this;
}
public Criteria andNameIsNotNull() {
addCriterion("name is not null");
return (Criteria) this;
}
public Criteria andNameEqualTo(String value) {
addCriterion("name =", value, "name");
return (Criteria) this;
}
public Criteria andNameNotEqualTo(String value) {
addCriterion("name <>", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThan(String value) {
addCriterion("name >", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThanOrEqualTo(String value) {
addCriterion("name >=", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThan(String value) {
addCriterion("name <", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThanOrEqualTo(String value) {
addCriterion("name <=", value, "name");
return (Criteria) this;
}
public Criteria andNameLike(String value) {
addCriterion("name like", value, "name");
return (Criteria) this;
}
public Criteria andNameNotLike(String value) {
addCriterion("name not like", value, "name");
return (Criteria) this;
}
public Criteria andNameIn(List<String> values) {
addCriterion("name in", values, "name");
return (Criteria) this;
}
public Criteria andNameNotIn(List<String> values) {
addCriterion("name not in", values, "name");
return (Criteria) this;
}
public Criteria andNameBetween(String value1, String value2) {
addCriterion("name between", value1, value2, "name");
return (Criteria) this;
}
public Criteria andNameNotBetween(String value1, String value2) {
addCriterion("name not between", value1, value2, "name");
return (Criteria) this;
}
public Criteria andCreatedAtIsNull() {
addCriterion("created_at is null");
return (Criteria) this;
}
public Criteria andCreatedAtIsNotNull() {
addCriterion("created_at is not null");
return (Criteria) this;
}
public Criteria andCreatedAtEqualTo(Date value) {
addCriterion("created_at =", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotEqualTo(Date value) {
addCriterion("created_at <>", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtGreaterThan(Date value) {
addCriterion("created_at >", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtGreaterThanOrEqualTo(Date value) {
addCriterion("created_at >=", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtLessThan(Date value) {
addCriterion("created_at <", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtLessThanOrEqualTo(Date value) {
addCriterion("created_at <=", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtIn(List<Date> values) {
addCriterion("created_at in", values, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotIn(List<Date> values) {
addCriterion("created_at not in", values, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtBetween(Date value1, Date value2) {
addCriterion("created_at between", value1, value2, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotBetween(Date value1, Date value2) {
addCriterion("created_at not between", value1, value2, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedByIsNull() {
addCriterion("created_by is null");
return (Criteria) this;
}
public Criteria andCreatedByIsNotNull() {
addCriterion("created_by is not null");
return (Criteria) this;
}
public Criteria andCreatedByEqualTo(String value) {
addCriterion("created_by =", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotEqualTo(String value) {
addCriterion("created_by <>", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByGreaterThan(String value) {
addCriterion("created_by >", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByGreaterThanOrEqualTo(String value) {
addCriterion("created_by >=", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLessThan(String value) {
addCriterion("created_by <", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLessThanOrEqualTo(String value) {
addCriterion("created_by <=", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLike(String value) {
addCriterion("created_by like", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotLike(String value) {
addCriterion("created_by not like", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByIn(List<String> values) {
addCriterion("created_by in", values, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotIn(List<String> values) {
addCriterion("created_by not in", values, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByBetween(String value1, String value2) {
addCriterion("created_by between", value1, value2, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotBetween(String value1, String value2) {
addCriterion("created_by not between", value1, value2, "createdBy");
return (Criteria) this;
}
public Criteria andUpdatedAtIsNull() {
addCriterion("updated_at is null");
return (Criteria) this;
}
public Criteria andUpdatedAtIsNotNull() {
addCriterion("updated_at is not null");
return (Criteria) this;
}
public Criteria andUpdatedAtEqualTo(Date value) {
addCriterion("updated_at =", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotEqualTo(Date value) {
addCriterion("updated_at <>", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtGreaterThan(Date value) {
addCriterion("updated_at >", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtGreaterThanOrEqualTo(Date value) {
addCriterion("updated_at >=", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtLessThan(Date value) {
addCriterion("updated_at <", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtLessThanOrEqualTo(Date value) {
addCriterion("updated_at <=", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtIn(List<Date> values) {
addCriterion("updated_at in", values, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotIn(List<Date> values) {
addCriterion("updated_at not in", values, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtBetween(Date value1, Date value2) {
addCriterion("updated_at between", value1, value2, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotBetween(Date value1, Date value2) {
addCriterion("updated_at not between", value1, value2, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedByIsNull() {
addCriterion("updated_by is null");
return (Criteria) this;
}
public Criteria andUpdatedByIsNotNull() {
addCriterion("updated_by is not null");
return (Criteria) this;
}
public Criteria andUpdatedByEqualTo(String value) {
addCriterion("updated_by =", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotEqualTo(String value) {
addCriterion("updated_by <>", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByGreaterThan(String value) {
addCriterion("updated_by >", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByGreaterThanOrEqualTo(String value) {
addCriterion("updated_by >=", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLessThan(String value) {
addCriterion("updated_by <", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLessThanOrEqualTo(String value) {
addCriterion("updated_by <=", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLike(String value) {
addCriterion("updated_by like", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotLike(String value) {
addCriterion("updated_by not like", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByIn(List<String> values) {
addCriterion("updated_by in", values, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotIn(List<String> values) {
addCriterion("updated_by not in", values, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByBetween(String value1, String value2) {
addCriterion("updated_by between", value1, value2, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotBetween(String value1, String value2) {
addCriterion("updated_by not between", value1, value2, "updatedBy");
return (Criteria) this;
}
}
/**
* s2_plugin
*/
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
/**
* s2_plugin null
*/
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
}
}

View File

@@ -0,0 +1,31 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.Data;
@Data
public class QueryDO {
public String aggregator = "trend";
public String startTime;
public String endTime;
private long id;
private long questionId;
private String createTime;
private String time;
private String userName;
private String question;
private Object queryResults;
private int state;
private String dataContent;
private String name;
private int queryType;
private int isDeleted;
private String module;
private long chatId;
private int topNum;
private String querySql;
private Object queryColumn;
private Object entityInfo;
private int score;
private String feedback;
}

View File

@@ -0,0 +1,54 @@
package com.tencent.supersonic.chat.server.persistence.dataobject;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import java.util.Date;
@Data
@Builder
@NoArgsConstructor
@Getter
@AllArgsConstructor
public class StatisticsDO {
/**
* questionId
*/
private Long questionId;
/**
* chatId
*/
private Long chatId;
/**
* createTime
*/
private Date createTime;
/**
* queryText
*/
private String queryText;
/**
* userName
*/
private String userName;
/**
* interface
*/
private String interfaceName;
/**
* cost
*/
private Integer cost;
private Integer type;
}

View File

@@ -0,0 +1,71 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDOExample;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface AgentDOMapper {
/**
*
* @mbg.generated
*/
long countByExample(AgentDOExample example);
/**
*
* @mbg.generated
*/
int deleteByPrimaryKey(Integer id);
/**
*
* @mbg.generated
*/
int insert(AgentDO record);
/**
*
* @mbg.generated
*/
int insertSelective(AgentDO record);
/**
*
* @mbg.generated
*/
List<AgentDO> selectByExample(AgentDOExample example);
/**
*
* @mbg.generated
*/
AgentDO selectByPrimaryKey(Integer id);
/**
*
* @mbg.generated
*/
int updateByExampleSelective(@Param("record") AgentDO record, @Param("example") AgentDOExample example);
/**
*
* @mbg.generated
*/
int updateByExample(@Param("record") AgentDO record, @Param("example") AgentDOExample example);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(AgentDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKey(AgentDO record);
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.config.ChatConfigFilterInternal;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatConfigDO;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChatConfigMapper {
Long addConfig(ChatConfigDO chaConfigPO);
Long editConfig(ChatConfigDO chaConfigPO);
List<ChatConfigDO> search(ChatConfigFilterInternal filterInternal);
ChatConfigDO fetchConfigByModelId(Long modelId);
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatContextDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChatContextMapper {
ChatContextDO getContextByChatId(int chatId);
int updateContext(ChatContextDO contextDO);
int addContext(ChatContextDO contextDO);
}

View File

@@ -0,0 +1,25 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.QueryDO;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ChatMapper {
boolean createChat(ChatDO chatDO);
List<ChatDO> getAll(String creator, Integer agentId);
Boolean updateChatName(Long chatId, String chatName, String lastTime, String creator);
Boolean updateLastQuestion(Long chatId, String lastQuestion, String lastTime);
Boolean updateConversionIsTop(Long chatId, int isTop);
boolean updateFeedback(QueryDO queryDO);
Boolean deleteChat(Long chatId, String userName);
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ChatParseMapper {
boolean batchSaveParseInfo(@Param("list") List<ChatParseDO> list);
boolean updateParseInfo(ChatParseDO chatParseDO);
ChatParseDO getParseInfo(Long questionId, int parseId);
List<ChatParseDO> getParseInfoList(List<Long> questionIds);
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDOExample;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ChatQueryDOMapper {
int insert(ChatQueryDO record);
List<ChatQueryDO> selectByExampleWithBLOBs(ChatQueryDOExample example);
int updateByPrimaryKeyWithBLOBs(ChatQueryDO record);
Boolean deleteByPrimaryKey(Long questionId);
ChatQueryDO selectByPrimaryKey(Long questionId);
}

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictConfDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DictConfMapper {
Boolean createDictConf(DictConfDO dictConfDO);
Boolean editDictConf(DictConfDO dictConfDO);
Boolean upsertDictInfo(DictConfDO dictConfDO);
DictConfDO getDictInfoByModelId(Long modelId);
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictTaskDO;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DictTaskMapper {
Long createDimValueTask(DictTaskDO dictTaskDO);
Boolean updateTaskStatus(DictTaskDO dictTaskDO);
List<DictTaskDO> searchDictTaskList(DictTaskFilterReq filter);
}

View File

@@ -0,0 +1,69 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDOExample;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface PluginDOMapper {
/**
*
* @mbg.generated
*/
long countByExample(PluginDOExample example);
/**
*
* @mbg.generated
*/
int deleteByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int insert(PluginDO record);
/**
*
* @mbg.generated
*/
int insertSelective(PluginDO record);
/**
*
* @mbg.generated
*/
List<PluginDO> selectByExampleWithBLOBs(PluginDOExample example);
/**
*
* @mbg.generated
*/
List<PluginDO> selectByExample(PluginDOExample example);
/**
*
* @mbg.generated
*/
PluginDO selectByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(PluginDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeyWithBLOBs(PluginDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKey(PluginDO record);
}

View File

@@ -0,0 +1,12 @@
package com.tencent.supersonic.chat.server.persistence.mapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface StatisticsMapper {
boolean batchSaveStatistics(@Param("list") List<StatisticsDO> list);
}

View File

@@ -0,0 +1,12 @@
package com.tencent.supersonic.chat.server.persistence.mapper.custom;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ShowCaseCustomMapper {
List<ChatQueryDO> queryShowCase(int start, int limit, int agentId, String userName);
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO;
import java.util.List;
public interface AgentRepository {
List<AgentDO> getAgents();
void createAgent(AgentDO agentDO);
void updateAgent(AgentDO agentDO);
AgentDO getAgent(Integer id);
void deleteAgent(Integer id);
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import java.util.List;
public interface ChatConfigRepository {
Long createConfig(ChatConfig chaConfig);
Long updateConfig(ChatConfig chaConfig);
List<ChatConfigResp> getChatConfig(ChatConfigFilter filter);
ChatConfigResp getConfigByModelId(Long modelId);
}

View File

@@ -0,0 +1,12 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
public interface ChatContextRepository {
ChatContext getOrCreateContext(int chatId);
void updateContext(ChatContext chatCtx);
}

View File

@@ -0,0 +1,40 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import java.util.List;
public interface ChatQueryRepository {
PageInfo<QueryResp> getChatQuery(PageQueryInfoReq pageQueryInfoCommend, Long chatId);
QueryResp getChatQuery(Long queryId);
ChatQueryDO getChatQueryDO(Long queryId);
List<QueryResp> queryShowCase(PageQueryInfoReq pageQueryInfoCommend, int agentId);
void updateChatParseInfo(List<ChatParseDO> chatParseDOS);
ChatQueryDO getLastChatQuery(long chatId);
int updateChatQuery(ChatQueryDO chatQueryDO);
List<ChatParseDO> batchSaveParseInfo(ChatContext chatCtx, QueryReq queryReq,
ParseResp parseResult,
List<SemanticParseInfo> candidateParses);
ChatParseDO getParseInfo(Long questionId, int parseId);
List<ChatParseDO> getParseInfoList(List<Long> questionIds);
Boolean deleteChatQuery(Long questionId);
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.server.persistence.dataobject.QueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import java.util.List;
public interface ChatRepository {
boolean createChat(ChatDO chatDO);
List<ChatDO> getAll(String creator, Integer agentId);
Boolean updateChatName(Long chatId, String chatName, String lastTime, String creator);
Boolean updateLastQuestion(Long chatId, String lastQuestion, String lastTime);
Boolean updateConversionIsTop(Long chatId, int isTop);
boolean updateFeedback(QueryDO queryDO);
Boolean deleteChat(Long chatId, String userName);
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import com.tencent.supersonic.chat.core.knowledge.DictConfig;
import com.tencent.supersonic.chat.core.knowledge.DimValueDictInfo;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictTaskDO;
import java.util.List;
public interface DictRepository {
Long createDimValueDictTask(DictTaskDO dictTaskDO);
Boolean updateDictTaskStatus(Integer status, DictTaskDO dictTaskDO);
List<DimValueDictInfo> searchDictTaskList(DictTaskFilterReq filter);
DictConfig getDictInfoByModelId(Long modelId);
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDOExample;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDO;
import java.util.List;
public interface PluginRepository {
List<PluginDO> getPlugins();
List<PluginDO> fetchPluginDOs(String queryText, String type);
void createPlugin(PluginDO pluginDO);
void updatePlugin(PluginDO pluginDO);
PluginDO getPlugin(Long id);
List<PluginDO> query(PluginDOExample pluginDOExample);
void deletePlugin(Long id);
}

View File

@@ -0,0 +1,11 @@
package com.tencent.supersonic.chat.server.persistence.repository;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import java.util.List;
public interface StatisticsRepository {
void batchSaveStatistics(List<StatisticsDO> list);
}

View File

@@ -0,0 +1,43 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDOExample;
import com.tencent.supersonic.chat.server.persistence.mapper.AgentDOMapper;
import com.tencent.supersonic.chat.server.persistence.repository.AgentRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class AgentRepositoryImpl implements AgentRepository {
private AgentDOMapper agentDOMapper;
public AgentRepositoryImpl(AgentDOMapper agentDOMapper) {
this.agentDOMapper = agentDOMapper;
}
@Override
public List<AgentDO> getAgents() {
return agentDOMapper.selectByExample(new AgentDOExample());
}
@Override
public void createAgent(AgentDO agentDO) {
agentDOMapper.insert(agentDO);
}
@Override
public void updateAgent(AgentDO agentDO) {
agentDOMapper.updateByPrimaryKey(agentDO);
}
@Override
public AgentDO getAgent(Integer id) {
return agentDOMapper.selectByPrimaryKey(id);
}
@Override
public void deleteAgent(Integer id) {
agentDOMapper.deleteByPrimaryKey(id);
}
}

View File

@@ -0,0 +1,68 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.server.config.ChatConfigFilterInternal;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatConfigDO;
import com.tencent.supersonic.chat.server.persistence.mapper.ChatConfigMapper;
import com.tencent.supersonic.chat.server.util.ChatConfigHelper;
import com.tencent.supersonic.chat.server.persistence.repository.ChatConfigRepository;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
@Repository
@Primary
public class ChatConfigRepositoryImpl implements ChatConfigRepository {
private final ChatConfigHelper chatConfigHelper;
private final ChatConfigMapper chatConfigMapper;
public ChatConfigRepositoryImpl(ChatConfigHelper chatConfigHelper,
ChatConfigMapper chatConfigMapper) {
this.chatConfigHelper = chatConfigHelper;
this.chatConfigMapper = chatConfigMapper;
}
@Override
public Long createConfig(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = chatConfigHelper.chatConfig2DO(chaConfig);
chatConfigMapper.addConfig(chaConfigDO);
return chaConfigDO.getId();
}
@Override
public Long updateConfig(ChatConfig chaConfig) {
ChatConfigDO chaConfigDO = chatConfigHelper.chatConfig2DO(chaConfig);
return chatConfigMapper.editConfig(chaConfigDO);
}
@Override
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(chatConfigHelper
.chatConfigDO2Descriptor(chaConfigDO.getModelId(), chaConfigDO)));
}
return chaConfigDescriptorList;
}
@Override
public ChatConfigResp getConfigByModelId(Long modelId) {
ChatConfigDO chaConfigPO = chatConfigMapper.fetchConfigByModelId(modelId);
return chatConfigHelper.chatConfigDO2Descriptor(modelId, chaConfigPO);
}
}

View File

@@ -0,0 +1,73 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.google.gson.Gson;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatContextDO;
import com.tencent.supersonic.chat.server.persistence.mapper.ChatContextMapper;
import com.tencent.supersonic.chat.server.persistence.repository.ChatContextRepository;
import com.tencent.supersonic.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@Repository
@Primary
@Slf4j
public class ChatContextRepositoryImpl implements ChatContextRepository {
@Autowired(required = false)
private final ChatContextMapper chatContextMapper;
public ChatContextRepositoryImpl(ChatContextMapper chatContextMapper) {
this.chatContextMapper = chatContextMapper;
}
@Override
public ChatContext getOrCreateContext(int chatId) {
ChatContextDO context = chatContextMapper.getContextByChatId(chatId);
if (context == null) {
ChatContext chatContext = new ChatContext();
chatContext.setChatId(chatId);
return chatContext;
}
return cast(context);
}
@Override
public void updateContext(ChatContext chatCtx) {
ChatContextDO context = cast(chatCtx);
if (chatContextMapper.getContextByChatId(chatCtx.getChatId()) == null) {
chatContextMapper.addContext(context);
} else {
chatContextMapper.updateContext(context);
}
}
private ChatContext cast(ChatContextDO contextDO) {
ChatContext chatContext = new ChatContext();
chatContext.setChatId(contextDO.getChatId());
chatContext.setUser(contextDO.getUser());
chatContext.setQueryText(contextDO.getQueryText());
if (contextDO.getSemanticParse() != null && !contextDO.getSemanticParse().isEmpty()) {
log.info("--->: {}", contextDO.getSemanticParse());
SemanticParseInfo semanticParseInfo = JsonUtil.toObject(contextDO.getSemanticParse(),
SemanticParseInfo.class);
chatContext.setParseInfo(semanticParseInfo);
}
return chatContext;
}
private ChatContextDO cast(ChatContext chatContext) {
ChatContextDO chatContextDO = new ChatContextDO();
chatContextDO.setChatId(chatContext.getChatId());
chatContextDO.setQueryText(chatContext.getQueryText());
chatContextDO.setUser(chatContext.getUser());
if (chatContext.getParseInfo() != null) {
Gson g = new Gson();
chatContextDO.setSemanticParse(g.toJson(chatContext.getParseInfo()));
}
return chatContextDO;
}
}

View File

@@ -0,0 +1,208 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.api.pojo.response.SimilarQueryRecallResp;
import com.tencent.supersonic.chat.server.persistence.mapper.custom.ShowCaseCustomMapper;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDOExample;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDOExample.Criteria;
import com.tencent.supersonic.chat.server.persistence.mapper.ChatParseMapper;
import com.tencent.supersonic.chat.server.persistence.mapper.ChatQueryDOMapper;
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.common.util.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Repository
@Primary
@Slf4j
public class ChatQueryRepositoryImpl implements ChatQueryRepository {
private final ChatQueryDOMapper chatQueryDOMapper;
private final ChatParseMapper chatParseMapper;
private final ShowCaseCustomMapper showCaseCustomMapper;
public ChatQueryRepositoryImpl(ChatQueryDOMapper chatQueryDOMapper,
ChatParseMapper chatParseMapper,
ShowCaseCustomMapper showCaseCustomMapper) {
this.chatQueryDOMapper = chatQueryDOMapper;
this.chatParseMapper = chatParseMapper;
this.showCaseCustomMapper = showCaseCustomMapper;
}
@Override
public PageInfo<QueryResp> getChatQuery(PageQueryInfoReq pageQueryInfoReq, Long chatId) {
ChatQueryDOExample example = new ChatQueryDOExample();
example.setOrderByClause("question_id desc");
Criteria criteria = example.createCriteria();
if (chatId != null) {
criteria.andChatIdEqualTo(chatId);
}
if (StringUtils.isNotBlank(pageQueryInfoReq.getUserName())) {
criteria.andUserNameEqualTo(pageQueryInfoReq.getUserName());
}
if (!CollectionUtils.isEmpty(pageQueryInfoReq.getIds())) {
criteria.andQuestionIdIn(pageQueryInfoReq.getIds());
}
PageInfo<ChatQueryDO> pageInfo = PageHelper.startPage(pageQueryInfoReq.getCurrent(),
pageQueryInfoReq.getPageSize())
.doSelectPageInfo(() -> chatQueryDOMapper.selectByExampleWithBLOBs(example));
PageInfo<QueryResp> chatQueryVOPageInfo = PageUtils.pageInfo2PageInfoVo(pageInfo);
chatQueryVOPageInfo.setList(
pageInfo.getList().stream().filter(o -> !StringUtils.isEmpty(o.getQueryResult())).map(this::convertTo)
.sorted(Comparator.comparingInt(o -> o.getQuestionId().intValue()))
.collect(Collectors.toList()));
return chatQueryVOPageInfo;
}
@Override
public QueryResp getChatQuery(Long queryId) {
ChatQueryDO chatQueryDO = getChatQueryDO(queryId);
if (Objects.isNull(chatQueryDO)) {
return new QueryResp();
}
return convertTo(chatQueryDO);
}
@Override
public ChatQueryDO getChatQueryDO(Long queryId) {
return chatQueryDOMapper.selectByPrimaryKey(queryId);
}
@Override
public List<QueryResp> queryShowCase(PageQueryInfoReq pageQueryInfoReq, int agentId) {
return showCaseCustomMapper.queryShowCase(pageQueryInfoReq.getLimitStart(),
pageQueryInfoReq.getPageSize(), agentId, pageQueryInfoReq.getUserName())
.stream().map(this::convertTo)
.collect(Collectors.toList());
}
private QueryResp convertTo(ChatQueryDO chatQueryDO) {
QueryResp queryResp = new QueryResp();
BeanUtils.copyProperties(chatQueryDO, queryResp);
QueryResult queryResult = JsonUtil.toObject(chatQueryDO.getQueryResult(), QueryResult.class);
if (queryResult != null) {
queryResult.setQueryId(chatQueryDO.getQuestionId());
queryResp.setQueryResult(queryResult);
}
if (StringUtils.isNotBlank(chatQueryDO.getSimilarQueries())) {
List<SimilarQueryRecallResp> similarQueries = JSONObject.parseArray(chatQueryDO.getSimilarQueries(),
SimilarQueryRecallResp.class);
queryResp.setSimilarQueries(similarQueries);
}
return queryResp;
}
public Long createChatQuery(ParseResp parseResult, ChatContext chatCtx, QueryReq queryReq) {
ChatQueryDO chatQueryDO = new ChatQueryDO();
chatQueryDO.setChatId(Long.valueOf(chatCtx.getChatId()));
chatQueryDO.setCreateTime(new java.util.Date());
chatQueryDO.setUserName(queryReq.getUser().getName());
chatQueryDO.setQueryText(queryReq.getQueryText());
chatQueryDO.setAgentId(queryReq.getAgentId());
chatQueryDO.setQueryResult("");
try {
chatQueryDOMapper.insert(chatQueryDO);
} catch (Exception e) {
log.info("database insert has an exception:{}", e.toString());
}
Long queryId = chatQueryDO.getQuestionId();
parseResult.setQueryId(queryId);
return queryId;
}
@Override
public List<ChatParseDO> batchSaveParseInfo(ChatContext chatCtx, QueryReq queryReq,
ParseResp parseResult, List<SemanticParseInfo> candidateParses) {
Long queryId = createChatQuery(parseResult, chatCtx, queryReq);
List<ChatParseDO> chatParseDOList = new ArrayList<>();
getChatParseDO(chatCtx, queryReq, queryId, candidateParses, chatParseDOList);
if (!CollectionUtils.isEmpty(candidateParses)) {
chatParseMapper.batchSaveParseInfo(chatParseDOList);
}
return chatParseDOList;
}
@Override
public void updateChatParseInfo(List<ChatParseDO> chatParseDOS) {
for (ChatParseDO chatParseDO : chatParseDOS) {
chatParseMapper.updateParseInfo(chatParseDO);
}
}
public void getChatParseDO(ChatContext chatCtx, QueryReq queryReq, Long queryId,
List<SemanticParseInfo> parses, List<ChatParseDO> chatParseDOList) {
for (int i = 0; i < parses.size(); i++) {
ChatParseDO chatParseDO = new ChatParseDO();
chatParseDO.setChatId(Long.valueOf(chatCtx.getChatId()));
chatParseDO.setQuestionId(queryId);
chatParseDO.setQueryText(queryReq.getQueryText());
chatParseDO.setParseInfo(JsonUtil.toString(parses.get(i)));
chatParseDO.setIsCandidate(1);
if (i == 0) {
chatParseDO.setIsCandidate(0);
}
chatParseDO.setParseId(parses.get(i).getId());
chatParseDO.setCreateTime(new java.util.Date());
chatParseDO.setUserName(queryReq.getUser().getName());
chatParseDOList.add(chatParseDO);
}
}
@Override
public ChatQueryDO getLastChatQuery(long chatId) {
ChatQueryDOExample example = new ChatQueryDOExample();
example.setOrderByClause("question_id desc");
example.setLimitEnd(1);
example.setLimitStart(0);
Criteria criteria = example.createCriteria();
criteria.andChatIdEqualTo(chatId);
List<ChatQueryDO> chatQueryDOS = chatQueryDOMapper.selectByExampleWithBLOBs(example);
if (!CollectionUtils.isEmpty(chatQueryDOS)) {
return chatQueryDOS.get(0);
}
return null;
}
@Override
public int updateChatQuery(ChatQueryDO chatQueryDO) {
return chatQueryDOMapper.updateByPrimaryKeyWithBLOBs(chatQueryDO);
}
public ChatParseDO getParseInfo(Long questionId, int parseId) {
return chatParseMapper.getParseInfo(questionId, parseId);
}
@Override
public List<ChatParseDO> getParseInfoList(List<Long> questionIds) {
return chatParseMapper.getParseInfoList(questionIds);
}
@Override
public Boolean deleteChatQuery(Long questionId) {
return chatQueryDOMapper.deleteByPrimaryKey(questionId);
}
}

View File

@@ -0,0 +1,58 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.server.persistence.dataobject.QueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.persistence.mapper.ChatMapper;
import com.tencent.supersonic.chat.server.persistence.repository.ChatRepository;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@Repository
@Primary
@Slf4j
public class ChatRepositoryImpl implements ChatRepository {
private final ChatMapper chatMapper;
public ChatRepositoryImpl(ChatMapper chatMapper) {
this.chatMapper = chatMapper;
}
@Override
public boolean createChat(ChatDO chatDO) {
return chatMapper.createChat(chatDO);
}
@Override
public List<ChatDO> getAll(String creator, Integer agentId) {
return chatMapper.getAll(creator, agentId);
}
@Override
public Boolean updateChatName(Long chatId, String chatName, String lastTime, String creator) {
return chatMapper.updateChatName(chatId, chatName, lastTime, creator);
}
@Override
public Boolean updateLastQuestion(Long chatId, String lastQuestion, String lastTime) {
return chatMapper.updateLastQuestion(chatId, lastQuestion, lastTime);
}
@Override
public Boolean updateConversionIsTop(Long chatId, int isTop) {
return chatMapper.updateConversionIsTop(chatId, isTop);
}
@Override
public boolean updateFeedback(QueryDO queryDO) {
return chatMapper.updateFeedback(queryDO);
}
@Override
public Boolean deleteChat(Long chatId, String userName) {
return chatMapper.deleteChat(chatId, userName);
}
}

View File

@@ -0,0 +1,83 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import com.tencent.supersonic.chat.core.knowledge.DictConfig;
import com.tencent.supersonic.chat.core.knowledge.DimValueDictInfo;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictConfDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictTaskDO;
import com.tencent.supersonic.chat.server.persistence.mapper.DictConfMapper;
import com.tencent.supersonic.chat.server.persistence.mapper.DictTaskMapper;
import com.tencent.supersonic.chat.server.persistence.repository.DictRepository;
import com.tencent.supersonic.chat.server.util.DictTaskConverter;
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
import com.tencent.supersonic.common.util.JsonUtil;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
@Repository
@Slf4j
public class DictRepositoryImpl implements DictRepository {
private final DictTaskMapper dictTaskMapper;
private final DictConfMapper dictConfMapper;
public DictRepositoryImpl(DictTaskMapper dictTaskMapper,
DictConfMapper dictConfMapper) {
this.dictTaskMapper = dictTaskMapper;
this.dictConfMapper = dictConfMapper;
}
@Override
public Long createDimValueDictTask(DictTaskDO dictTaskDO) {
dictTaskMapper.createDimValueTask(dictTaskDO);
return dictTaskDO.getId();
}
@Override
public Boolean updateDictTaskStatus(Integer status, DictTaskDO dictTaskDO) {
dictTaskDO.setStatus(status);
Date createdAt = dictTaskDO.getCreatedAt();
long elapsedMs = System.currentTimeMillis() - createdAt.getTime();
dictTaskDO.setElapsedMs(elapsedMs);
dictTaskMapper.updateTaskStatus(dictTaskDO);
return true;
}
@Override
public List<DimValueDictInfo> searchDictTaskList(DictTaskFilterReq filter) {
List<DimValueDictInfo> dimValueDictDescList = new ArrayList<>();
log.info("filter:{}", filter);
List<DictTaskDO> dictTaskDOList = dictTaskMapper.searchDictTaskList(filter);
if (!CollectionUtils.isEmpty(dictTaskDOList)) {
dictTaskDOList.stream().forEach(dictTaskDO -> {
DimValueDictInfo dimValueDictDesc = new DimValueDictInfo();
BeanUtils.copyProperties(dictTaskDO, dimValueDictDesc);
dimValueDictDesc.setStatus(TaskStatusEnum.of(dictTaskDO.getStatus()));
if (StringUtils.isNotEmpty(dictTaskDO.getDimIds())) {
Set<Long> dimIds = JsonUtil.toSet(dictTaskDO.getDimIds(), Long.class);
dimValueDictDesc.setDimIds(dimIds);
}
dimValueDictDescList.add(dimValueDictDesc);
});
}
return dimValueDictDescList;
}
@Override
public DictConfig getDictInfoByModelId(Long modelId) {
DictConfDO dictConfDO = dictConfMapper.getDictInfoByModelId(modelId);
if (Objects.isNull(dictConfDO)) {
return null;
}
return DictTaskConverter.dictConfPO2Config(dictConfDO);
}
}

View File

@@ -0,0 +1,81 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDOExample;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDO;
import com.tencent.supersonic.chat.server.persistence.mapper.PluginDOMapper;
import com.tencent.supersonic.chat.server.persistence.repository.PluginRepository;
import com.tencent.supersonic.common.util.ContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Repository
@Slf4j
public class PluginRepositoryImpl implements PluginRepository {
private PluginDOMapper pluginDOMapper;
public PluginRepositoryImpl(PluginDOMapper pluginDOMapper) {
this.pluginDOMapper = pluginDOMapper;
}
@Override
public List<PluginDO> getPlugins() {
return pluginDOMapper.selectByExampleWithBLOBs(new PluginDOExample());
}
@Override
public List<PluginDO> fetchPluginDOs(String queryText, String type) {
List<PluginDO> pluginDOList = new ArrayList<>();
PluginRepository pluginRepository = ContextUtils.getBean(PluginRepository.class);
List<PluginDO> pluginDOS = pluginRepository.getPlugins();
for (PluginDO pluginDO : pluginDOS) {
String pattern = pluginDO.getPattern();
if (Strings.isNotEmpty(pattern)) {
Pattern pluginPattern = Pattern.compile(pattern);
Matcher pluginMatcher = pluginPattern.matcher(queryText);
if (pluginMatcher.find()) {
log.info("pluginMatcher.find() is true, queryText:{}", queryText);
log.info("pluginDO:{}", pluginDO);
pluginDOList.add(pluginDO);
}
}
}
return pluginDOList;
}
@Override
public void createPlugin(PluginDO pluginDO) {
pluginDOMapper.insert(pluginDO);
}
@Override
public void updatePlugin(PluginDO pluginDO) {
pluginDOMapper.updateByPrimaryKeyWithBLOBs(pluginDO);
}
@Override
public PluginDO getPlugin(Long id) {
return pluginDOMapper.selectByPrimaryKey(id);
}
@Override
public List<PluginDO> query(PluginDOExample pluginDOExample) {
return pluginDOMapper.selectByExampleWithBLOBs(pluginDOExample);
}
@Override
public void deletePlugin(Long id) {
pluginDOMapper.deleteByPrimaryKey(id);
}
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.chat.server.persistence.repository.impl;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import com.tencent.supersonic.chat.server.persistence.mapper.StatisticsMapper;
import com.tencent.supersonic.chat.server.persistence.repository.StatisticsRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@Primary
@Slf4j
public class StatisticsRepositoryImpl implements StatisticsRepository {
private final StatisticsMapper statisticsMapper;
public StatisticsRepositoryImpl(StatisticsMapper statisticsMapper) {
this.statisticsMapper = statisticsMapper;
}
public void batchSaveStatistics(List<StatisticsDO> list) {
statisticsMapper.batchSaveStatistics(list);
}
}

View File

@@ -0,0 +1,8 @@
package com.tencent.supersonic.chat.server.processor;
/**
* A ResultProcessor wraps things up before returning results to users.
*/
public interface ResultProcessor {
}

View File

@@ -0,0 +1,73 @@
package com.tencent.supersonic.chat.server.processor.execute;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.RelatedSchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.service.SemanticService;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
/**
* DimensionRecommendProcessor recommend some dimensions
* related to metrics based on configuration
*/
public class DimensionRecommendProcessor implements ExecuteResultProcessor {
private static final int recommend_dimension_size = 5;
@Override
public void process(QueryResult queryResult, SemanticParseInfo semanticParseInfo, ExecuteQueryReq queryReq) {
if (!QueryType.METRIC.equals(semanticParseInfo.getQueryType())
|| CollectionUtils.isEmpty(semanticParseInfo.getMetrics())) {
return;
}
SchemaElement element = semanticParseInfo.getMetrics().iterator().next();
List<SchemaElement> dimensionRecommended = getDimensions(element.getId(), element.getModel());
queryResult.setRecommendedDimensions(dimensionRecommended);
}
private List<SchemaElement> getDimensions(Long metricId, Long modelId) {
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
ModelSchema modelSchema = semanticService.getModelSchema(modelId);
List<Long> drillDownDimensions = Lists.newArrayList();
Set<SchemaElement> metricElements = modelSchema.getMetrics();
if (!CollectionUtils.isEmpty(metricElements)) {
Optional<SchemaElement> metric = metricElements.stream().filter(schemaElement ->
metricId.equals(schemaElement.getId())
&& !CollectionUtils.isEmpty(schemaElement.getRelatedSchemaElements()))
.findFirst();
if (metric.isPresent()) {
drillDownDimensions = metric.get().getRelatedSchemaElements().stream()
.map(RelatedSchemaElement::getDimensionId).collect(Collectors.toList());
}
}
final List<Long> drillDownDimensionsFinal = drillDownDimensions;
return modelSchema.getDimensions().stream()
.filter(dim -> filterDimension(drillDownDimensionsFinal, dim))
.sorted(Comparator.comparing(SchemaElement::getUseCnt).reversed())
.limit(recommend_dimension_size)
.collect(Collectors.toList());
}
private boolean filterDimension(List<Long> drillDownDimensions, SchemaElement dimension) {
if (Objects.isNull(dimension)) {
return false;
}
if (!CollectionUtils.isEmpty(drillDownDimensions)) {
return drillDownDimensions.contains(dimension.getId());
}
return Objects.nonNull(dimension.getUseCnt());
}
}

View File

@@ -0,0 +1,15 @@
package com.tencent.supersonic.chat.server.processor.execute;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.processor.ResultProcessor;
/**
* A ExecuteResultProcessor wraps things up before returning results to users in execute stage.
*/
public interface ExecuteResultProcessor extends ResultProcessor {
void process(QueryResult queryResult, SemanticParseInfo semanticParseInfo, ExecuteQueryReq queryReq);
}

View File

@@ -0,0 +1,83 @@
package com.tencent.supersonic.chat.server.processor.execute;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.common.config.EmbeddingConfig;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.util.ComponentFactory;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.embedding.Retrieval;
import com.tencent.supersonic.common.util.embedding.RetrieveQuery;
import com.tencent.supersonic.common.util.embedding.RetrieveQueryResult;
import com.tencent.supersonic.common.util.embedding.S2EmbeddingStore;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
/**
* MetricRecommendProcessor fills recommended metrics based on embedding similarity.
*/
public class MetricRecommendProcessor implements ExecuteResultProcessor {
private static final int METRIC_RECOMMEND_SIZE = 5;
private S2EmbeddingStore s2EmbeddingStore = ComponentFactory.getS2EmbeddingStore();
@Override
public void process(QueryResult queryResult, SemanticParseInfo semanticParseInfo, ExecuteQueryReq queryReq) {
fillSimilarMetric(queryResult.getChatContext());
}
private void fillSimilarMetric(SemanticParseInfo parseInfo) {
if (!parseInfo.getQueryType().equals(QueryType.METRIC)
|| parseInfo.getMetrics().size() > METRIC_RECOMMEND_SIZE
|| CollectionUtils.isEmpty(parseInfo.getMetrics())) {
return;
}
List<String> metricNames = Collections.singletonList(parseInfo.getMetrics().iterator().next().getName());
Map<String, String> filterCondition = new HashMap<>();
filterCondition.put("modelId", parseInfo.getMetrics().iterator().next().getModel().toString());
filterCondition.put("type", SchemaElementType.METRIC.name());
RetrieveQuery retrieveQuery = RetrieveQuery.builder().queryTextsList(metricNames)
.filterCondition(filterCondition).queryEmbeddings(null).build();
EmbeddingConfig embeddingConfig = ContextUtils.getBean(EmbeddingConfig.class);
List<RetrieveQueryResult> retrieveQueryResults = s2EmbeddingStore.retrieveQuery(
embeddingConfig.getMetaCollectionName(), retrieveQuery, METRIC_RECOMMEND_SIZE + 1);
if (CollectionUtils.isEmpty(retrieveQueryResults)) {
return;
}
List<Retrieval> retrievals = retrieveQueryResults.stream()
.flatMap(retrieveQueryResult -> retrieveQueryResult.getRetrieval().stream())
.sorted(Comparator.comparingDouble(Retrieval::getDistance))
.distinct().collect(Collectors.toList());
Set<Long> metricIds = parseInfo.getMetrics().stream().map(SchemaElement::getId).collect(Collectors.toSet());
int metricOrder = 0;
for (SchemaElement metric : parseInfo.getMetrics()) {
metric.setOrder(metricOrder++);
}
for (Retrieval retrieval : retrievals) {
if (!metricIds.contains(Retrieval.getLongId(retrieval.getId()))) {
SchemaElement schemaElement = JSONObject.parseObject(JSONObject.toJSONString(retrieval.getMetadata()),
SchemaElement.class);
if (retrieval.getMetadata().containsKey("modelId")) {
String modelId = retrieval.getMetadata().get("modelId").toString();
schemaElement.setModel(Long.parseLong(modelId));
}
schemaElement.setOrder(++metricOrder);
parseInfo.getMetrics().add(schemaElement);
}
}
}
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.core.query.QueryManager;
import com.tencent.supersonic.chat.core.query.llm.analytics.MetricAnalyzeQuery;
import com.tencent.supersonic.chat.server.service.SemanticService;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
/**
* EntityInfoProcessor fills core attributes of an entity so that
* users get to know which entity is parsed out.
*/
public class EntityInfoProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
List<SemanticQuery> semanticQueries = queryContext.getCandidateQueries();
if (CollectionUtils.isEmpty(semanticQueries)) {
return;
}
List<SemanticParseInfo> selectedParses = semanticQueries.stream().map(SemanticQuery::getParseInfo)
.collect(Collectors.toList());
QueryReq queryReq = queryContext.getRequest();
selectedParses.forEach(parseInfo -> {
String queryMode = parseInfo.getQueryMode();
if (QueryManager.containsPluginQuery(queryMode)
|| MetricAnalyzeQuery.QUERY_MODE.equalsIgnoreCase(queryMode)) {
return;
}
//1. set entity info
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
EntityInfo entityInfo = semanticService.getEntityInfo(parseInfo, queryReq.getUser());
if (QueryManager.isTagQuery(queryMode)
|| QueryManager.isMetricQuery(queryMode)) {
parseInfo.setEntityInfo(entityInfo);
}
});
}
}

View File

@@ -0,0 +1,220 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.RelatedSchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.server.service.SemanticService;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserRemoveHelper;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
/**
* MetricCheckProcessor verifies whether the dimensions
* involved in the query in metric mode can drill down on the metric.
*/
@Slf4j
public class MetricCheckProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
List<SemanticQuery> semanticQueries = queryContext.getCandidateQueries();
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
SemanticSchema semanticSchema = semanticService.getSemanticSchema();
for (SemanticQuery semanticQuery : semanticQueries) {
SemanticParseInfo parseInfo = semanticQuery.getParseInfo();
if (!QueryType.METRIC.equals(parseInfo.getQueryType())) {
continue;
}
String correctSqlProcessed = processCorrectSql(parseInfo, semanticSchema);
log.info("correct sql:{}", correctSqlProcessed);
parseInfo.getSqlInfo().setCorrectS2SQL(correctSqlProcessed);
}
semanticQueries.removeIf(semanticQuery -> {
if (!QueryType.METRIC.equals(semanticQuery.getParseInfo().getQueryType())) {
return false;
}
String correctSql = semanticQuery.getParseInfo().getSqlInfo().getCorrectS2SQL();
if (StringUtils.isBlank(correctSql)) {
return false;
}
return !checkHasMetric(correctSql, semanticSchema);
});
}
public String processCorrectSql(SemanticParseInfo parseInfo, SemanticSchema semanticSchema) {
String correctSql = parseInfo.getSqlInfo().getCorrectS2SQL();
List<String> groupByFields = SqlParserSelectHelper.getGroupByFields(correctSql);
List<String> metricFields = SqlParserSelectHelper.getAggregateFields(correctSql);
List<String> whereFields = SqlParserSelectHelper.getWhereFields(correctSql);
List<String> dimensionFields = getDimensionFields(groupByFields, whereFields);
if (CollectionUtils.isEmpty(metricFields) || StringUtils.isBlank(correctSql)) {
return correctSql;
}
Set<String> metricToRemove = Sets.newHashSet();
Set<String> groupByToRemove = Sets.newHashSet();
Set<String> whereFieldsToRemove = Sets.newHashSet();
for (String metricName : metricFields) {
SchemaElement metricElement = semanticSchema.getElementByName(SchemaElementType.METRIC, metricName);
if (metricElement == null) {
metricToRemove.add(metricName);
}
if (!checkNecessaryDimension(metricElement, semanticSchema, dimensionFields)) {
metricToRemove.add(metricName);
}
}
for (String dimensionName : whereFields) {
if (TimeDimensionEnum.containsTimeDimension(dimensionName)) {
continue;
}
if (!checkInModelSchema(dimensionName, SchemaElementType.DIMENSION, semanticSchema)) {
whereFieldsToRemove.add(dimensionName);
}
if (!checkDrillDownDimension(dimensionName, metricFields, semanticSchema)) {
whereFieldsToRemove.add(dimensionName);
}
}
for (String dimensionName : groupByFields) {
if (TimeDimensionEnum.containsTimeDimension(dimensionName)) {
continue;
}
if (!checkInModelSchema(dimensionName, SchemaElementType.DIMENSION, semanticSchema)) {
groupByToRemove.add(dimensionName);
}
if (!checkDrillDownDimension(dimensionName, metricFields, semanticSchema)) {
groupByToRemove.add(dimensionName);
}
}
return removeFieldInSql(correctSql, metricToRemove, groupByToRemove, whereFieldsToRemove);
}
/**
* To check whether the dimension bound to the metric exists,
* eg: metric like UV is calculated in a certain dimension, it cannot be used on other dimensions.
*/
private boolean checkNecessaryDimension(SchemaElement metric, SemanticSchema semanticSchema,
List<String> dimensionFields) {
List<String> necessaryDimensions = getNecessaryDimensionNames(metric, semanticSchema);
if (CollectionUtils.isEmpty(necessaryDimensions)) {
return true;
}
for (String dimension : necessaryDimensions) {
if (!dimensionFields.contains(dimension)) {
return false;
}
}
return true;
}
/**
* To check whether the dimension can drill down the metric,
* eg: some descriptive dimensions are not suitable as drill-down dimensions
*/
private boolean checkDrillDownDimension(String dimensionName, List<String> metrics,
SemanticSchema semanticSchema) {
List<SchemaElement> metricElements = semanticSchema.getMetrics().stream()
.filter(schemaElement -> metrics.contains(schemaElement.getName()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(metricElements)) {
return false;
}
List<String> relateDimensions = metricElements.stream()
.filter(schemaElement -> !CollectionUtils.isEmpty(schemaElement.getRelatedSchemaElements()))
.map(schemaElement -> schemaElement.getRelatedSchemaElements().stream()
.map(RelatedSchemaElement::getDimensionId).collect(Collectors.toList()))
.flatMap(Collection::stream)
.map(id -> convertDimensionIdToName(id, semanticSchema))
.filter(Objects::nonNull)
.collect(Collectors.toList());
//if no metric has drill down dimension, return true
if (CollectionUtils.isEmpty(relateDimensions)) {
return true;
}
//if this dimension not in relate drill-down dimensions, return false
return relateDimensions.contains(dimensionName);
}
private List<String> getNecessaryDimensionNames(SchemaElement metric, SemanticSchema semanticSchema) {
List<Long> necessaryDimensionIds = getNecessaryDimensions(metric);
return necessaryDimensionIds.stream().map(id -> convertDimensionIdToName(id, semanticSchema))
.filter(Objects::nonNull).collect(Collectors.toList());
}
private List<Long> getNecessaryDimensions(SchemaElement metric) {
if (metric == null) {
return Lists.newArrayList();
}
List<RelatedSchemaElement> relateSchemaElements = metric.getRelatedSchemaElements();
if (CollectionUtils.isEmpty(relateSchemaElements)) {
return Lists.newArrayList();
}
return relateSchemaElements.stream()
.filter(RelatedSchemaElement::isNecessary).map(RelatedSchemaElement::getDimensionId)
.collect(Collectors.toList());
}
private List<String> getDimensionFields(List<String> groupByFields, List<String> whereFields) {
List<String> dimensionFields = Lists.newArrayList();
if (!CollectionUtils.isEmpty(groupByFields)) {
dimensionFields.addAll(groupByFields);
}
if (!CollectionUtils.isEmpty(whereFields)) {
dimensionFields.addAll(whereFields);
}
return dimensionFields;
}
private String convertDimensionIdToName(Long id, SemanticSchema semanticSchema) {
SchemaElement schemaElement = semanticSchema.getElement(SchemaElementType.DIMENSION, id);
if (schemaElement == null) {
return null;
}
return schemaElement.getName();
}
private boolean checkInModelSchema(String name, SchemaElementType type, SemanticSchema semanticSchema) {
SchemaElement schemaElement = semanticSchema.getElementByName(type, name);
return schemaElement != null;
}
private boolean checkHasMetric(String correctSql, SemanticSchema semanticSchema) {
List<String> selectFields = SqlParserSelectHelper.getSelectFields(correctSql);
List<String> aggFields = SqlParserSelectHelper.getAggregateFields(correctSql);
List<String> collect = semanticSchema.getMetrics().stream()
.map(SchemaElement::getName).collect(Collectors.toList());
for (String field : selectFields) {
if (collect.contains(field)) {
return true;
}
}
return !CollectionUtils.isEmpty(aggFields);
}
private static String removeFieldInSql(String sql, Set<String> metricToRemove,
Set<String> dimensionByToRemove, Set<String> whereFieldsToRemove) {
sql = SqlParserRemoveHelper.removeWhereCondition(sql, whereFieldsToRemove);
sql = SqlParserRemoveHelper.removeSelect(sql, metricToRemove);
sql = SqlParserRemoveHelper.removeSelect(sql, dimensionByToRemove);
sql = SqlParserRemoveHelper.removeGroupBy(sql, dimensionByToRemove);
sql = SqlParserRemoveHelper.removeNumberFilter(sql);
return sql;
}
}

View File

@@ -0,0 +1,211 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.SqlInfo;
import com.tencent.supersonic.chat.server.service.impl.SchemaService;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.jsqlparser.FieldExpression;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.CollectionUtils;
/**
* ParseInfoProcessor extracts structured info from S2SQL so that
* users get to know the details.
**/
@Slf4j
public class ParseInfoProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
List<SemanticQuery> candidateQueries = queryContext.getCandidateQueries();
if (CollectionUtils.isEmpty(candidateQueries)) {
return;
}
List<SemanticParseInfo> candidateParses = candidateQueries.stream()
.map(SemanticQuery::getParseInfo).collect(Collectors.toList());
candidateParses.forEach(this::updateParseInfo);
}
public void updateParseInfo(SemanticParseInfo parseInfo) {
SqlInfo sqlInfo = parseInfo.getSqlInfo();
String correctS2SQL = sqlInfo.getCorrectS2SQL();
if (StringUtils.isBlank(correctS2SQL)) {
return;
}
// if S2SQL equals correctS2SQL, then not update the parseInfo.
if (correctS2SQL.equals(sqlInfo.getS2SQL())) {
return;
}
List<FieldExpression> expressions = SqlParserSelectHelper.getFilterExpression(correctS2SQL);
//set dataInfo
try {
if (!org.apache.commons.collections.CollectionUtils.isEmpty(expressions)) {
DateConf dateInfo = getDateInfo(expressions);
if (dateInfo != null && parseInfo.getDateInfo() == null) {
parseInfo.setDateInfo(dateInfo);
}
}
} catch (Exception e) {
log.error("set dateInfo error :", e);
}
//set filter
Set<Long> modelIds = parseInfo.getModel().getModelIds();
try {
Map<String, SchemaElement> fieldNameToElement = getNameToElement(modelIds);
List<QueryFilter> result = getDimensionFilter(fieldNameToElement, expressions);
parseInfo.getDimensionFilters().addAll(result);
} catch (Exception e) {
log.error("set dimensionFilter error :", e);
}
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
if (Objects.isNull(semanticSchema)) {
return;
}
List<String> allFields = getFieldsExceptDate(SqlParserSelectHelper.getAllFields(sqlInfo.getCorrectS2SQL()));
Set<SchemaElement> metrics = getElements(modelIds, allFields, semanticSchema.getMetrics());
parseInfo.setMetrics(metrics);
if (QueryType.METRIC.equals(parseInfo.getQueryType())) {
List<String> groupByFields = SqlParserSelectHelper.getGroupByFields(sqlInfo.getCorrectS2SQL());
List<String> groupByDimensions = getFieldsExceptDate(groupByFields);
parseInfo.setDimensions(getElements(modelIds, groupByDimensions, semanticSchema.getDimensions()));
} else if (QueryType.TAG.equals(parseInfo.getQueryType())) {
List<String> selectFields = SqlParserSelectHelper.getSelectFields(sqlInfo.getCorrectS2SQL());
List<String> selectDimensions = getFieldsExceptDate(selectFields);
parseInfo.setDimensions(getElements(modelIds, selectDimensions, semanticSchema.getDimensions()));
}
}
private Set<SchemaElement> getElements(Set<Long> modelIds, List<String> allFields, List<SchemaElement> elements) {
return elements.stream()
.filter(schemaElement -> modelIds.contains(schemaElement.getModel()) && allFields.contains(
schemaElement.getName())
).collect(Collectors.toSet());
}
private List<String> getFieldsExceptDate(List<String> allFields) {
if (org.springframework.util.CollectionUtils.isEmpty(allFields)) {
return new ArrayList<>();
}
return allFields.stream()
.filter(entry -> !TimeDimensionEnum.DAY.getChName().equalsIgnoreCase(entry))
.collect(Collectors.toList());
}
private List<QueryFilter> getDimensionFilter(Map<String, SchemaElement> fieldNameToElement,
List<FieldExpression> fieldExpressions) {
List<QueryFilter> result = Lists.newArrayList();
for (FieldExpression expression : fieldExpressions) {
QueryFilter dimensionFilter = new QueryFilter();
dimensionFilter.setValue(expression.getFieldValue());
SchemaElement schemaElement = fieldNameToElement.get(expression.getFieldName());
if (Objects.isNull(schemaElement)) {
continue;
}
dimensionFilter.setName(schemaElement.getName());
dimensionFilter.setBizName(schemaElement.getBizName());
dimensionFilter.setElementID(schemaElement.getId());
FilterOperatorEnum operatorEnum = FilterOperatorEnum.getSqlOperator(expression.getOperator());
dimensionFilter.setOperator(operatorEnum);
dimensionFilter.setFunction(expression.getFunction());
result.add(dimensionFilter);
}
return result;
}
private DateConf getDateInfo(List<FieldExpression> fieldExpressions) {
List<FieldExpression> dateExpressions = fieldExpressions.stream()
.filter(expression -> TimeDimensionEnum.DAY.getChName().equalsIgnoreCase(expression.getFieldName()))
.collect(Collectors.toList());
if (org.apache.commons.collections.CollectionUtils.isEmpty(dateExpressions)) {
return null;
}
DateConf dateInfo = new DateConf();
dateInfo.setDateMode(DateConf.DateMode.BETWEEN);
FieldExpression firstExpression = dateExpressions.get(0);
FilterOperatorEnum firstOperator = FilterOperatorEnum.getSqlOperator(firstExpression.getOperator());
if (FilterOperatorEnum.EQUALS.equals(firstOperator) && Objects.nonNull(firstExpression.getFieldValue())) {
dateInfo.setStartDate(firstExpression.getFieldValue().toString());
dateInfo.setEndDate(firstExpression.getFieldValue().toString());
dateInfo.setDateMode(DateConf.DateMode.BETWEEN);
return dateInfo;
}
if (containOperators(firstExpression, firstOperator, FilterOperatorEnum.GREATER_THAN,
FilterOperatorEnum.GREATER_THAN_EQUALS)) {
dateInfo.setStartDate(firstExpression.getFieldValue().toString());
if (hasSecondDate(dateExpressions)) {
dateInfo.setEndDate(dateExpressions.get(1).getFieldValue().toString());
}
}
if (containOperators(firstExpression, firstOperator, FilterOperatorEnum.MINOR_THAN,
FilterOperatorEnum.MINOR_THAN_EQUALS)) {
dateInfo.setEndDate(firstExpression.getFieldValue().toString());
if (hasSecondDate(dateExpressions)) {
dateInfo.setStartDate(dateExpressions.get(1).getFieldValue().toString());
}
}
return dateInfo;
}
private boolean containOperators(FieldExpression expression, FilterOperatorEnum firstOperator,
FilterOperatorEnum... operatorEnums) {
return (Arrays.asList(operatorEnums).contains(firstOperator) && Objects.nonNull(
expression.getFieldValue()));
}
private boolean hasSecondDate(List<FieldExpression> dateExpressions) {
return dateExpressions.size() > 1 && Objects.nonNull(dateExpressions.get(1).getFieldValue());
}
protected Map<String, SchemaElement> getNameToElement(Set<Long> modelIds) {
SemanticSchema semanticSchema = ContextUtils.getBean(SchemaService.class).getSemanticSchema();
List<SchemaElement> dimensions = semanticSchema.getDimensions(modelIds);
List<SchemaElement> metrics = semanticSchema.getMetrics(modelIds);
List<SchemaElement> allElements = Lists.newArrayList();
allElements.addAll(dimensions);
allElements.addAll(metrics);
//support alias
return allElements.stream()
.flatMap(schemaElement -> {
Set<Pair<String, SchemaElement>> result = new HashSet<>();
result.add(Pair.of(schemaElement.getName(), schemaElement));
List<String> aliasList = schemaElement.getAlias();
if (!org.springframework.util.CollectionUtils.isEmpty(aliasList)) {
for (String alias : aliasList) {
result.add(Pair.of(alias, schemaElement));
}
}
return result.stream();
})
.collect(Collectors.toMap(pair -> pair.getLeft(), pair -> pair.getRight(),
(value1, value2) -> value2));
}
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.server.processor.ResultProcessor;
/**
* A ParseResultProcessor wraps things up before returning results to users in parse stage.
*/
public interface ParseResultProcessor extends ResultProcessor {
void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext);
}

View File

@@ -0,0 +1,83 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.core.query.rule.RuleSemanticQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* QueryRankProcessor ranks candidate parsing results based on
* a heuristic scoring algorithm and then takes topN.
**/
@Slf4j
public class QueryRankProcessor implements ParseResultProcessor {
private static final int candidateTopSize = 5;
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
List<SemanticQuery> candidateQueries = queryContext.getCandidateQueries();
candidateQueries = rank(candidateQueries);
queryContext.setCandidateQueries(candidateQueries);
}
public List<SemanticQuery> rank(List<SemanticQuery> candidateQueries) {
log.debug("pick before [{}]", candidateQueries);
if (CollectionUtils.isEmpty(candidateQueries)) {
return candidateQueries;
}
List<SemanticQuery> selectedQueries = new ArrayList<>();
if (candidateQueries.size() == 1) {
selectedQueries.addAll(candidateQueries);
} else {
selectedQueries = getTopCandidateQuery(candidateQueries);
}
generateParseInfoId(selectedQueries);
log.debug("pick after [{}]", selectedQueries);
return selectedQueries;
}
public List<SemanticQuery> getTopCandidateQuery(List<SemanticQuery> semanticQueries) {
return semanticQueries.stream()
.filter(query -> !checkFullyInherited(query))
.sorted((o1, o2) -> {
if (o1.getParseInfo().getScore() < o2.getParseInfo().getScore()) {
return 1;
} else if (o1.getParseInfo().getScore() > o2.getParseInfo().getScore()) {
return -1;
}
return 0;
}).limit(candidateTopSize)
.collect(Collectors.toList());
}
private void generateParseInfoId(List<SemanticQuery> semanticQueries) {
for (int i = 0; i < semanticQueries.size(); i++) {
SemanticQuery query = semanticQueries.get(i);
query.getParseInfo().setId(i + 1);
}
}
private boolean checkFullyInherited(SemanticQuery query) {
SemanticParseInfo parseInfo = query.getParseInfo();
if (!(query instanceof RuleSemanticQuery)) {
return false;
}
for (SchemaElementMatch match : parseInfo.getElementMatches()) {
if (!match.isInherited()) {
return false;
}
}
return parseInfo.getDateInfo() == null || parseInfo.getDateInfo().isInherited();
}
}

View File

@@ -0,0 +1,88 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.SimilarQueryRecallResp;
import com.tencent.supersonic.chat.core.utils.SimilarQueryManager;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
/**
* MetricRecommendProcessor fills recommended query based on embedding similarity.
*/
@Slf4j
public class QueryRecommendProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
CompletableFuture.runAsync(() -> doProcess(parseResp, queryContext));
}
@SneakyThrows
private void doProcess(ParseResp parseResp, QueryContext queryContext) {
Long queryId = parseResp.getQueryId();
List<SimilarQueryRecallResp> solvedQueries = getSimilarQueries(queryContext.getRequest().getQueryText(),
queryContext.getRequest().getAgentId());
ChatQueryDO chatQueryDO = getChatQuery(queryId);
chatQueryDO.setSimilarQueries(JSONObject.toJSONString(solvedQueries));
updateChatQuery(chatQueryDO);
}
public List<SimilarQueryRecallResp> getSimilarQueries(String queryText, Integer agentId) {
//1. recall solved query by queryText
SimilarQueryManager solvedQueryManager = ContextUtils.getBean(SimilarQueryManager.class);
List<SimilarQueryRecallResp> similarQueries = solvedQueryManager.recallSimilarQuery(queryText, agentId);
if (CollectionUtils.isEmpty(similarQueries)) {
return Lists.newArrayList();
}
//2. remove low score query
List<Long> queryIds = similarQueries.stream()
.map(SimilarQueryRecallResp::getQueryId).collect(Collectors.toList());
int lowScoreThreshold = 3;
List<QueryResp> queryResps = getChatQuery(queryIds);
if (CollectionUtils.isEmpty(queryResps)) {
return Lists.newArrayList();
}
Set<Long> lowScoreQueryIds = queryResps.stream().filter(queryResp ->
queryResp.getScore() != null && queryResp.getScore() <= lowScoreThreshold)
.map(QueryResp::getQuestionId).collect(Collectors.toSet());
return similarQueries.stream().filter(solvedQueryRecallResp ->
!lowScoreQueryIds.contains(solvedQueryRecallResp.getQueryId()))
.collect(Collectors.toList());
}
private ChatQueryDO getChatQuery(Long queryId) {
ChatQueryRepository chatQueryRepository = ContextUtils.getBean(ChatQueryRepository.class);
return chatQueryRepository.getChatQueryDO(queryId);
}
private List<QueryResp> getChatQuery(List<Long> queryIds) {
ChatQueryRepository chatQueryRepository = ContextUtils.getBean(ChatQueryRepository.class);
PageQueryInfoReq pageQueryInfoReq = new PageQueryInfoReq();
pageQueryInfoReq.setIds(queryIds);
pageQueryInfoReq.setPageSize(100);
pageQueryInfoReq.setCurrent(1);
PageInfo<QueryResp> queryRespPageInfo = chatQueryRepository.getChatQuery(pageQueryInfoReq, null);
return queryRespPageInfo.getList();
}
private void updateChatQuery(ChatQueryDO chatQueryDO) {
ChatQueryRepository chatQueryRepository = ContextUtils.getBean(ChatQueryRepository.class);
chatQueryRepository.updateChatQuery(chatQueryDO);
}
}

View File

@@ -0,0 +1,39 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.server.service.ChatService;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
/**
* RespBuildProcessor fill response object with parsing results.
**/
@Slf4j
public class RespBuildProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
QueryReq queryReq = queryContext.getRequest();
parseResp.setChatId(queryReq.getChatId());
parseResp.setQueryText(queryReq.getQueryText());
List<SemanticQuery> candidateQueries = queryContext.getCandidateQueries();
ChatService chatService = ContextUtils.getBean(ChatService.class);
if (candidateQueries.size() > 0) {
List<SemanticParseInfo> candidateParses = candidateQueries.stream()
.map(SemanticQuery::getParseInfo).collect(Collectors.toList());
parseResp.setSelectedParses(candidateParses);
parseResp.setState(ParseResp.ParseState.COMPLETED);
} else {
parseResp.setState(ParseResp.ParseState.FAILED);
}
chatService.batchAddParse(chatContext, queryReq, parseResp);
}
}

View File

@@ -0,0 +1,69 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.SqlInfo;
import com.tencent.supersonic.chat.core.query.QueryManager;
import com.tencent.supersonic.chat.core.query.llm.s2sql.LLMSqlQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* SqlInfoProcessor adds S2SQL to the parsing results so that
* technical users could verify SQL by themselves.
**/
public class SqlInfoProcessor implements ParseResultProcessor {
private static final Logger keyPipelineLog = LoggerFactory.getLogger("keyPipeline");
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
QueryReq queryReq = queryContext.getRequest();
List<SemanticQuery> semanticQueries = queryContext.getCandidateQueries();
if (CollectionUtils.isEmpty(semanticQueries)) {
return;
}
List<SemanticParseInfo> selectedParses = semanticQueries.stream().map(SemanticQuery::getParseInfo)
.collect(Collectors.toList());
long startTime = System.currentTimeMillis();
addSqlInfo(queryReq, selectedParses);
parseResp.getParseTimeCost().setSqlTime(System.currentTimeMillis() - startTime);
}
private void addSqlInfo(QueryReq queryReq, List<SemanticParseInfo> semanticParseInfos) {
if (CollectionUtils.isEmpty(semanticParseInfos)) {
return;
}
semanticParseInfos.forEach(parseInfo -> {
addSqlInfo(queryReq, parseInfo);
});
}
private void addSqlInfo(QueryReq queryReq, SemanticParseInfo parseInfo) {
SemanticQuery semanticQuery = QueryManager.createQuery(parseInfo.getQueryMode());
if (Objects.isNull(semanticQuery)) {
return;
}
semanticQuery.setParseInfo(parseInfo);
String explainSql = semanticQuery.explain(queryReq.getUser());
if (StringUtils.isBlank(explainSql)) {
return;
}
SqlInfo sqlInfo = parseInfo.getSqlInfo();
if (semanticQuery instanceof LLMSqlQuery) {
keyPipelineLog.info("\ns2sql:{}\ncorrectS2SQL:{}\nquerySQL:{}", sqlInfo.getS2SQL(),
sqlInfo.getCorrectS2SQL(), explainSql);
}
sqlInfo.setQuerySQL(explainSql);
}
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.chat.server.processor.parse;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import lombok.extern.slf4j.Slf4j;
/**
* TimeCostProcessor adds time cost of parsing.
**/
@Slf4j
public class TimeCostProcessor implements ParseResultProcessor {
@Override
public void process(ParseResp parseResp, QueryContext queryContext, ChatContext chatContext) {
long parseStartTime = parseResp.getParseTimeCost().getParseStartTime();
parseResp.getParseTimeCost().setParseTime(
System.currentTimeMillis() - parseStartTime - parseResp.getParseTimeCost().getSqlTime());
}
}

View File

@@ -0,0 +1,57 @@
package com.tencent.supersonic.chat.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.core.agent.Agent;
import com.tencent.supersonic.chat.server.service.AgentService;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping({"/api/chat/agent", "/openapi/chat/agent"})
public class AgentController {
private AgentService agentService;
public AgentController(AgentService agentService) {
this.agentService = agentService;
}
@PostMapping
public boolean createAgent(@RequestBody Agent agent,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
agentService.createAgent(agent, user);
return true;
}
@PutMapping
public boolean updateAgent(@RequestBody Agent agent,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
agentService.updateAgent(agent, user);
return true;
}
@DeleteMapping("/{id}")
public boolean deleteAgent(@PathVariable("id") Integer id) {
agentService.deleteAgent(id);
return true;
}
@RequestMapping("/getAgentList")
public List<Agent> getAgentList() {
return agentService.getAgents();
}
}

View File

@@ -0,0 +1,123 @@
package com.tencent.supersonic.chat.server.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.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigBaseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.headless.api.request.PageDimensionReq;
import com.tencent.supersonic.headless.api.request.PageMetricReq;
import com.tencent.supersonic.headless.api.response.DimensionResp;
import com.tencent.supersonic.headless.api.response.DomainResp;
import com.tencent.supersonic.headless.api.response.MetricResp;
import com.tencent.supersonic.headless.api.response.ModelResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping({"/api/chat/conf", "/openapi/chat/conf"})
public class ChatConfigController {
@Autowired
private ConfigService configService;
private SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
@PostMapping
public Long addChatConfig(@RequestBody ChatConfigBaseReq extendBaseCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.addConfig(extendBaseCmd, user);
}
@PutMapping
public Long editModelExtend(@RequestBody ChatConfigEditReqReq extendEditCmd,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.editConfig(extendEditCmd, user);
}
@PostMapping("/search")
public List<ChatConfigResp> search(@RequestBody ChatConfigFilter filter,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return configService.search(filter, user);
}
@GetMapping("/richDesc/{modelId}")
public ChatConfigRichResp getModelExtendRichInfo(@PathVariable("modelId") Long modelId) {
return configService.getConfigRichInfo(modelId);
}
@GetMapping("/richDesc/all")
public List<ChatConfigRichResp> getAllChatRichConfig() {
return configService.getAllChatRichConfig();
}
@GetMapping("/modelList/{domainId}")
public List<ModelResp> getModelList(@PathVariable("domainId") Long domainId,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticInterpreter.getModelList(AuthType.ADMIN, domainId, user);
}
@GetMapping("/modelList")
public List<ModelResp> getModelList(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticInterpreter.getModelList(AuthType.ADMIN, null, user);
}
@GetMapping("/domainList")
public List<DomainResp> getDomainList(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticInterpreter.getDomainList(user);
}
@GetMapping("/modelList/view")
public List<ModelResp> getModelListVisible(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticInterpreter.getModelList(AuthType.VISIBLE, null, user);
}
@PostMapping("/dimension/page")
public PageInfo<DimensionResp> getDimension(@RequestBody PageDimensionReq pageDimensionReq,
HttpServletRequest request,
HttpServletResponse response) {
return semanticInterpreter.getDimensionPage(pageDimensionReq);
}
@PostMapping("/metric/page")
public PageInfo<MetricResp> getMetric(@RequestBody PageMetricReq pageMetricReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return semanticInterpreter.getMetricPage(pageMetricReq, user);
}
}

View File

@@ -0,0 +1,94 @@
package com.tencent.supersonic.chat.server.rest;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.ShowCaseResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.service.ChatService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping({"/api/chat/manage", "/openapi/chat/manage"})
public class ChatController {
private final ChatService chatService;
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
@PostMapping("/save")
public Boolean save(@RequestParam(value = "chatName") String chatName,
@RequestParam(value = "agentId", required = false) Integer agentId,
HttpServletRequest request, HttpServletResponse response) {
return chatService.addChat(UserHolder.findUser(request, response), chatName, agentId);
}
@GetMapping("/getAll")
public List<ChatDO> getAllConversions(@RequestParam(value = "agentId", required = false) Integer agentId,
HttpServletRequest request, HttpServletResponse response) {
String userName = UserHolder.findUser(request, response).getName();
return chatService.getAll(userName, agentId);
}
@PostMapping("/delete")
public Boolean deleteConversion(@RequestParam(value = "chatId") long chatId,
HttpServletRequest request, HttpServletResponse response) {
String userName = UserHolder.findUser(request, response).getName();
return chatService.deleteChat(chatId, userName);
}
@PostMapping("/updateChatName")
public Boolean updateConversionName(@RequestParam(value = "chatId") Long chatId,
@RequestParam(value = "chatName") String chatName,
HttpServletRequest request, HttpServletResponse response) {
String userName = UserHolder.findUser(request, response).getName();
return chatService.updateChatName(chatId, chatName, userName);
}
@PostMapping("/updateQAFeedback")
public Boolean updateQAFeedback(@RequestParam(value = "id") Integer id,
@RequestParam(value = "score") Integer score,
@RequestParam(value = "feedback", required = false) String feedback) {
return chatService.updateFeedback(id, score, feedback);
}
@PostMapping("/updateChatIsTop")
public Boolean updateConversionIsTop(@RequestParam(value = "chatId") Long chatId,
@RequestParam(value = "isTop") int isTop) {
return chatService.updateChatIsTop(chatId, isTop);
}
@PostMapping("/pageQueryInfo")
public PageInfo<QueryResp> pageQueryInfo(@RequestBody PageQueryInfoReq pageQueryInfoCommand,
@RequestParam(value = "chatId") long chatId,
HttpServletRequest request,
HttpServletResponse response) {
pageQueryInfoCommand.setUserName(UserHolder.findUser(request, response).getName());
return chatService.queryInfo(pageQueryInfoCommand, chatId);
}
@GetMapping("/getChatQuery/{queryId}")
public QueryResp getChatQuery(@PathVariable("queryId") Long queryId) {
return chatService.getChatQuery(queryId);
}
@PostMapping("/queryShowCase")
public ShowCaseResp queryShowCase(@RequestBody PageQueryInfoReq pageQueryInfoCommand,
@RequestParam(value = "agentId") int agentId) {
return chatService.queryShowCase(pageQueryInfoCommand, agentId);
}
}

View File

@@ -0,0 +1,88 @@
package com.tencent.supersonic.chat.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.DimensionValueReq;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryDataReq;
import com.tencent.supersonic.chat.server.service.QueryService;
import com.tencent.supersonic.chat.server.service.SearchService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* query controller
*/
@RestController
@RequestMapping({"/api/chat/query", "/openapi/chat/query"})
public class ChatQueryController {
@Autowired
@Qualifier("chatQueryService")
private QueryService queryService;
@Autowired
private SearchService searchService;
@PostMapping("search")
public Object search(@RequestBody QueryReq queryCtx, HttpServletRequest request,
HttpServletResponse response) {
queryCtx.setUser(UserHolder.findUser(request, response));
return searchService.search(queryCtx);
}
@PostMapping("parse")
public Object parse(@RequestBody QueryReq queryCtx, HttpServletRequest request, HttpServletResponse response)
throws Exception {
queryCtx.setUser(UserHolder.findUser(request, response));
return queryService.performParsing(queryCtx);
}
@PostMapping("execute")
public Object execute(@RequestBody ExecuteQueryReq queryReq,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
queryReq.setUser(UserHolder.findUser(request, response));
return queryService.performExecution(queryReq);
}
@PostMapping("queryContext")
public Object queryContext(@RequestBody QueryReq queryCtx, HttpServletRequest request,
HttpServletResponse response) throws Exception {
queryCtx.setUser(UserHolder.findUser(request, response));
return queryService.queryContext(queryCtx);
}
@PostMapping("queryData")
public Object queryData(@RequestBody QueryDataReq queryData,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
queryData.setUser(UserHolder.findUser(request, response));
return queryService.executeDirectQuery(queryData, UserHolder.findUser(request, response));
}
@PostMapping("queryDimensionValue")
public Object queryDimensionValue(@RequestBody @Valid DimensionValueReq dimensionValueReq,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return queryService.queryDimensionValue(dimensionValueReq, UserHolder.findUser(request, response));
}
@RequestMapping("/getEntityInfo")
public Object getEntityInfo(Long queryId, Integer parseId,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return queryService.getEntityInfo(queryId, parseId, user);
}
}

View File

@@ -0,0 +1,114 @@
package com.tencent.supersonic.chat.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.DictLatestTaskReq;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import com.tencent.supersonic.chat.api.pojo.response.DictLatestTaskResp;
import com.tencent.supersonic.chat.core.knowledge.DimValue2DictCommand;
import com.tencent.supersonic.chat.core.knowledge.DimValueDictInfo;
import com.tencent.supersonic.chat.server.listener.ApplicationStartedListener;
import com.tencent.supersonic.chat.server.service.KnowledgeTaskService;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/chat/dict")
public class KnowledgeController {
@Autowired
private KnowledgeTaskService knowledgeTaskService;
@Autowired
private ApplicationStartedListener applicationStartedListener;
/**
* addDictInfo
* write specific dimension values to the knowledge base
*
* @param dimValue2DictCommend
*/
@PostMapping("/task")
public Long addDictTask(@RequestBody DimValue2DictCommand dimValue2DictCommend,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return knowledgeTaskService.addDictTask(dimValue2DictCommend, user);
}
/**
* deleteDictInfo
* remove specific dimension values from the knowledge base
*
* @param dimValue2DictCommend
*/
@PostMapping("/task/delete")
public Long deleteDictTask(@RequestBody DimValue2DictCommand dimValue2DictCommend,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return knowledgeTaskService.deleteDictTask(dimValue2DictCommend, user);
}
/**
* searchDictTaskList
*
* @param filter
*/
@PostMapping("/task/search")
public List<DimValueDictInfo> searchDictTaskList(@RequestBody DictTaskFilterReq filter,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return knowledgeTaskService.searchDictTaskList(filter, user);
}
/**
* searchDictLatestTaskList
*/
@PostMapping("/task/search/latest")
public List<DictLatestTaskResp> searchDictLatestTaskList(@RequestBody @Valid DictLatestTaskReq filter,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return knowledgeTaskService.searchDictLatestTaskList(filter, user);
}
/**
* getDictRootPath
* get knowledge base file directory
*
* @return
*/
@GetMapping("/rootPath")
public String getDictRootPath(HttpServletRequest request,
HttpServletResponse response) {
return knowledgeTaskService.getDictRootPath();
}
/**
* updateDimValue
* update in-memory dictionary files in real time
*
* @param request
* @param response
* @return
*/
@PutMapping("/knowledge/dimValue")
public Boolean updateDimValue(HttpServletRequest request,
HttpServletResponse response) {
return applicationStartedListener.updateKnowledgeDimValue();
}
}

View File

@@ -0,0 +1,64 @@
package com.tencent.supersonic.chat.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.chat.api.pojo.request.PluginQueryReq;
import com.tencent.supersonic.chat.core.plugin.Plugin;
import com.tencent.supersonic.chat.server.service.PluginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/chat/plugin")
public class PluginController {
@Autowired
protected PluginService pluginService;
@PostMapping
public boolean createPlugin(@RequestBody Plugin plugin,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
pluginService.createPlugin(plugin, user);
return true;
}
@PutMapping
public boolean updatePlugin(@RequestBody Plugin plugin,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
pluginService.updatePlugin(plugin, user);
return true;
}
@DeleteMapping("/{id}")
public boolean deletePlugin(@PathVariable("id") Long id) {
pluginService.deletePlugin(id);
return true;
}
@RequestMapping("/getPluginList")
public List<Plugin> getPluginList() {
return pluginService.getPluginList();
}
@PostMapping("/query")
List<Plugin> query(@RequestBody PluginQueryReq pluginQueryReq,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
return pluginService.queryWithAuthCheck(pluginQueryReq, user);
}
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.chat.server.rest;
import com.tencent.supersonic.chat.api.pojo.request.RecommendReq;
import com.tencent.supersonic.chat.api.pojo.response.RecommendQuestionResp;
import com.tencent.supersonic.chat.api.pojo.response.RecommendResp;
import com.tencent.supersonic.chat.server.service.RecommendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* recommend controller
*/
@RestController
@RequestMapping({"/api/chat/", "/openapi/chat/"})
public class RecommendController {
@Autowired
private RecommendService recommendService;
@GetMapping("recommend/{modelId}")
public RecommendResp recommend(@PathVariable("modelId") Long modelId,
@RequestParam(value = "limit", required = false) Long limit) {
RecommendReq recommendReq = new RecommendReq();
recommendReq.setModelId(modelId);
return recommendService.recommend(recommendReq, limit);
}
@GetMapping("recommend/metric/{modelId}")
public RecommendResp recommendMetricMode(@PathVariable("modelId") Long modelId,
@RequestParam(value = "metricId", required = false) Long metricId,
@RequestParam(value = "limit", required = false) Long limit) {
RecommendReq recommendReq = new RecommendReq();
recommendReq.setModelId(modelId);
recommendReq.setMetricId(metricId);
return recommendService.recommendMetricMode(recommendReq, limit);
}
@GetMapping("recommend/question")
public List<RecommendQuestionResp> recommendQuestion(
@RequestParam(value = "modelId", required = false) Long modelId) {
return recommendService.recommendQuestion(modelId);
}
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.agent.Agent;
import java.util.List;
public interface AgentService {
List<Agent> getAgents();
void createAgent(Agent agent, User user);
void updateAgent(Agent agent, User user);
Agent getAgent(Integer id);
void deleteAgent(Integer id);
}

View File

@@ -0,0 +1,60 @@
package com.tencent.supersonic.chat.server.service;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.api.pojo.response.ShowCaseResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import java.util.List;
import java.util.Set;
public interface ChatService {
/***
* get the model from context
* @param chatId
* @return
*/
Set<Long> getContextModel(Integer chatId);
ChatContext getOrCreateContext(int chatId);
void updateContext(ChatContext chatCtx);
Boolean addChat(User user, String chatName, Integer agentId);
List<ChatDO> getAll(String userName, Integer agentId);
boolean updateChatName(Long chatId, String chatName, String userName);
boolean updateFeedback(Integer id, Integer score, String feedback);
boolean updateChatIsTop(Long chatId, int isTop);
Boolean deleteChat(Long chatId, String userName);
PageInfo<QueryResp> queryInfo(PageQueryInfoReq pageQueryInfoCommend, long chatId);
QueryResp getChatQuery(Long queryId);
ShowCaseResp queryShowCase(PageQueryInfoReq pageQueryInfoCommend, int agentId);
List<ChatParseDO> batchAddParse(ChatContext chatCtx, QueryReq queryReq, ParseResp parseResult);
ChatQueryDO getLastQuery(long chatId);
int updateQuery(ChatQueryDO chatQueryDO);
void updateQuery(Long questionId, int parseId, QueryResult queryResult, ChatContext chatCtx);
ChatParseDO getParseInfo(Long questionId, int parseId);
Boolean deleteChatQuery(Long questionId);
}

View File

@@ -0,0 +1,35 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigBaseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.request.ItemNameVisibilityInfo;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import java.util.List;
import java.util.Map;
public interface ConfigService {
Long addConfig(ChatConfigBaseReq extendBaseCmd, User user);
Long editConfig(ChatConfigEditReqReq extendEditCmd, User user);
ItemNameVisibilityInfo getItemNameVisibility(ChatConfig chatConfig);
ItemNameVisibilityInfo getVisibilityByModelId(Long modelId);
List<ChatConfigResp> search(ChatConfigFilter filter, User user);
ChatConfigRichResp getConfigRichInfo(Long modelId);
ChatConfigResp fetchConfigByModelId(Long modelId);
List<ChatConfigRichResp> getAllChatRichConfig();
Map<Long, ChatConfigRichResp> getModelIdToChatRichConfig();
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import java.util.List;
public interface KnowledgeService {
void updateSemanticKnowledge(List<DictWord> natures);
void reloadAllData(List<DictWord> natures);
void updateOnlineKnowledge(List<DictWord> natures);
}

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.request.DictLatestTaskReq;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import com.tencent.supersonic.chat.api.pojo.response.DictLatestTaskResp;
import com.tencent.supersonic.chat.core.knowledge.DictConfig;
import com.tencent.supersonic.chat.core.knowledge.DimValue2DictCommand;
import com.tencent.supersonic.chat.core.knowledge.DimValueDictInfo;
import java.util.List;
public interface KnowledgeTaskService {
Long addDictTask(DimValue2DictCommand dimValue2DictCommend, User user);
Long deleteDictTask(DimValue2DictCommand dimValue2DictCommend, User user);
List<DimValueDictInfo> searchDictTaskList(DictTaskFilterReq filter, User user);
DictConfig getDictInfoByModelId(Long modelId);
String getDictRootPath();
List<DictLatestTaskResp> searchDictLatestTaskList(DictLatestTaskReq filter, User user);
}

View File

@@ -0,0 +1,32 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.request.PluginQueryReq;
import com.tencent.supersonic.chat.core.plugin.Plugin;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public interface PluginService {
void createPlugin(Plugin plugin, User user);
void updatePlugin(Plugin plugin, User user);
void deletePlugin(Long id);
List<Plugin> getPluginList();
List<Plugin> fetchPluginDOs(String queryText, String type);
List<Plugin> query(PluginQueryReq pluginQueryReq);
Optional<Plugin> getPluginByName(String name);
List<Plugin> queryWithAuthCheck(PluginQueryReq pluginQueryReq, User user);
Map<String, Plugin> getNameToPlugin();
}

View File

@@ -0,0 +1,31 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.DimensionValueReq;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.api.pojo.request.QueryDataReq;
import org.apache.calcite.sql.parser.SqlParseException;
/***
* QueryService for query and search
*/
public interface QueryService {
ParseResp performParsing(QueryReq queryReq);
QueryResult performExecution(ExecuteQueryReq queryReq) throws Exception;
SemanticParseInfo queryContext(QueryReq queryReq);
QueryResult executeDirectQuery(QueryDataReq queryData, User user) throws SqlParseException;
EntityInfo getEntityInfo(Long queryId, Integer parseId, User user);
Object queryDimensionValue(DimensionValueReq dimensionValueReq, User user) throws Exception;
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.api.pojo.request.RecommendReq;
import com.tencent.supersonic.chat.api.pojo.response.RecommendQuestionResp;
import com.tencent.supersonic.chat.api.pojo.response.RecommendResp;
import java.util.List;
/***
* Recommend Service
*/
public interface RecommendService {
RecommendResp recommend(RecommendReq recommendReq, Long limit);
RecommendResp recommendMetricMode(RecommendReq recommendReq, Long limit);
List<RecommendQuestionResp> recommendQuestion(Long modelId);
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.SearchResult;
import java.util.List;
/**
* search service
*/
public interface SearchService {
List<SearchResult> search(QueryReq queryCtx);
}

View File

@@ -0,0 +1,278 @@
package com.tencent.supersonic.chat.server.service;
import com.google.common.collect.Sets;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.api.pojo.request.ChatDefaultConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDefaultRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.DataInfo;
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
import com.tencent.supersonic.chat.api.pojo.response.ModelInfo;
import com.tencent.supersonic.chat.core.config.AggregatorConfig;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import com.tencent.supersonic.chat.core.utils.QueryReqBuilder;
import com.tencent.supersonic.chat.server.service.impl.SchemaService;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
import com.tencent.supersonic.common.pojo.ModelCluster;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.headless.api.request.QueryStructReq;
import com.tencent.supersonic.headless.api.response.QueryResultWithSchemaResp;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
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.Service;
import org.springframework.util.CollectionUtils;
@Service
@Slf4j
public class SemanticService {
@Autowired
private SchemaService schemaService;
@Autowired
private ConfigService configService;
@Autowired
private AggregatorConfig aggregatorConfig;
private SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
public SemanticSchema getSemanticSchema() {
return schemaService.getSemanticSchema();
}
public ModelSchema getModelSchema(Long id) {
return schemaService.getModelSchema(id);
}
public EntityInfo getEntityInfo(SemanticParseInfo parseInfo, User user) {
if (parseInfo != null && parseInfo.getModelId() > 0) {
EntityInfo entityInfo = getEntityInfo(parseInfo.getModelId());
if (parseInfo.getDimensionFilters().size() <= 0 || entityInfo.getModelInfo() == null) {
entityInfo.setMetrics(null);
entityInfo.setDimensions(null);
return entityInfo;
}
String primaryKey = entityInfo.getModelInfo().getPrimaryKey();
if (StringUtils.isNotBlank(primaryKey)) {
String modelInfoId = "";
for (QueryFilter chatFilter : parseInfo.getDimensionFilters()) {
if (chatFilter != null && chatFilter.getBizName() != null && chatFilter.getBizName()
.equals(primaryKey)) {
if (chatFilter.getOperator().equals(FilterOperatorEnum.EQUALS)) {
modelInfoId = chatFilter.getValue().toString();
}
}
}
try {
setMainModel(entityInfo, parseInfo, modelInfoId, user);
return entityInfo;
} catch (Exception e) {
log.error("setMainModel error", e);
}
}
}
return null;
}
public EntityInfo getEntityInfo(Long model) {
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(model);
if (Objects.isNull(chaConfigRichDesc) || Objects.isNull(chaConfigRichDesc.getChatDetailRichConfig())) {
return new EntityInfo();
}
return getEntityInfo(chaConfigRichDesc);
}
private EntityInfo getEntityInfo(ChatConfigRichResp chaConfigRichDesc) {
EntityInfo entityInfo = new EntityInfo();
Long modelId = chaConfigRichDesc.getModelId();
if (Objects.nonNull(chaConfigRichDesc) && Objects.nonNull(modelId)) {
SemanticService schemaService = ContextUtils.getBean(SemanticService.class);
ModelSchema modelSchema = schemaService.getModelSchema(modelId);
if (Objects.isNull(modelSchema) || Objects.isNull(modelSchema.getEntity())) {
return entityInfo;
}
ModelInfo modelInfo = new ModelInfo();
modelInfo.setItemId(modelId.intValue());
modelInfo.setName(modelSchema.getModel().getName());
modelInfo.setWords(modelSchema.getModel().getAlias());
modelInfo.setBizName(modelSchema.getModel().getBizName());
if (Objects.nonNull(modelSchema.getEntity())) {
modelInfo.setPrimaryKey(modelSchema.getEntity().getBizName());
}
entityInfo.setModelInfo(modelInfo);
List<DataInfo> dimensions = new ArrayList<>();
List<DataInfo> metrics = new ArrayList<>();
if (Objects.nonNull(chaConfigRichDesc) && Objects.nonNull(chaConfigRichDesc.getChatDetailRichConfig())
&& Objects.nonNull(chaConfigRichDesc.getChatDetailRichConfig().getChatDefaultConfig())) {
ChatDefaultRichConfigResp chatDefaultConfig = chaConfigRichDesc.getChatDetailRichConfig()
.getChatDefaultConfig();
if (!CollectionUtils.isEmpty(chatDefaultConfig.getDimensions())) {
for (SchemaElement dimensionDesc : chatDefaultConfig.getDimensions()) {
DataInfo mainEntityDimension = new DataInfo();
mainEntityDimension.setItemId(dimensionDesc.getId().intValue());
mainEntityDimension.setName(dimensionDesc.getName());
mainEntityDimension.setBizName(dimensionDesc.getBizName());
dimensions.add(mainEntityDimension);
}
entityInfo.setDimensions(dimensions);
}
if (!CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())) {
for (SchemaElement metricDesc : chatDefaultConfig.getMetrics()) {
DataInfo dataInfo = new DataInfo();
dataInfo.setName(metricDesc.getName());
dataInfo.setBizName(metricDesc.getBizName());
dataInfo.setItemId(metricDesc.getId().intValue());
metrics.add(dataInfo);
}
entityInfo.setMetrics(metrics);
}
}
}
return entityInfo;
}
public void setMainModel(EntityInfo modelInfo, SemanticParseInfo parseInfo, String entity, User user) {
if (StringUtils.isEmpty(entity)) {
return;
}
List<String> entities = Collections.singletonList(entity);
QueryResultWithSchemaResp queryResultWithColumns = getQueryResultWithSchemaResp(modelInfo, parseInfo, entities,
user);
if (queryResultWithColumns != null) {
if (!CollectionUtils.isEmpty(queryResultWithColumns.getResultList())
&& queryResultWithColumns.getResultList().size() > 0) {
Map<String, Object> result = queryResultWithColumns.getResultList().get(0);
for (Map.Entry<String, Object> entry : result.entrySet()) {
String entryKey = getEntryKey(entry);
if (entry.getValue() == null || entryKey == null) {
continue;
}
modelInfo.getDimensions().stream().filter(i -> entryKey.equals(i.getBizName()))
.forEach(i -> i.setValue(entry.getValue().toString()));
modelInfo.getMetrics().stream().filter(i -> entryKey.equals(i.getBizName()))
.forEach(i -> i.setValue(entry.getValue().toString()));
}
}
}
}
public QueryResultWithSchemaResp getQueryResultWithSchemaResp(EntityInfo modelInfo, SemanticParseInfo parseInfo,
List<String> entities, User user) {
if (CollectionUtils.isEmpty(entities)) {
return null;
}
ModelSchema modelSchema = schemaService.getModelSchema(parseInfo.getModelId());
modelInfo.setEntityId(entities.get(0));
SemanticParseInfo semanticParseInfo = new SemanticParseInfo();
semanticParseInfo.setModel(ModelCluster.build(Sets.newHashSet(parseInfo.getModelId())));
semanticParseInfo.setQueryType(QueryType.TAG);
semanticParseInfo.setMetrics(getMetrics(modelInfo));
semanticParseInfo.setDimensions(getDimensions(modelInfo));
DateConf dateInfo = new DateConf();
int unit = 1;
ChatConfigResp chatConfigInfo =
configService.fetchConfigByModelId(modelSchema.getModel().getId());
if (Objects.nonNull(chatConfigInfo) && Objects.nonNull(chatConfigInfo.getChatDetailConfig())
&& Objects.nonNull(chatConfigInfo.getChatDetailConfig().getChatDefaultConfig())) {
ChatDefaultConfigReq chatDefaultConfig = chatConfigInfo.getChatDetailConfig().getChatDefaultConfig();
unit = chatDefaultConfig.getUnit();
String date = LocalDate.now().plusDays(-unit).toString();
dateInfo.setDateMode(DateMode.BETWEEN);
dateInfo.setStartDate(date);
dateInfo.setEndDate(date);
} else {
dateInfo.setUnit(unit);
dateInfo.setDateMode(DateMode.RECENT);
}
semanticParseInfo.setDateInfo(dateInfo);
// add filter
QueryFilter chatFilter = getQueryFilter(modelInfo, entities);
Set<QueryFilter> chatFilters = new LinkedHashSet();
chatFilters.add(chatFilter);
semanticParseInfo.setDimensionFilters(chatFilters);
QueryResultWithSchemaResp queryResultWithColumns = null;
try {
QueryStructReq queryStructReq = QueryReqBuilder.buildStructReq(semanticParseInfo);
queryResultWithColumns = semanticInterpreter.queryByStruct(queryStructReq, user);
} catch (Exception e) {
log.warn("setMainModel queryByStruct error, e:", e);
}
return queryResultWithColumns;
}
private QueryFilter getQueryFilter(EntityInfo modelInfo, List<String> entities) {
QueryFilter chatFilter = new QueryFilter();
if (entities.size() == 1) {
chatFilter.setValue(entities.get(0));
chatFilter.setOperator(FilterOperatorEnum.EQUALS);
} else {
chatFilter.setValue(entities);
chatFilter.setOperator(FilterOperatorEnum.IN);
}
chatFilter.setBizName(getEntityPrimaryName(modelInfo));
return chatFilter;
}
private Set<SchemaElement> getDimensions(EntityInfo modelInfo) {
Set<SchemaElement> dimensions = new LinkedHashSet();
for (DataInfo mainEntityDimension : modelInfo.getDimensions()) {
SchemaElement dimension = new SchemaElement();
dimension.setBizName(mainEntityDimension.getBizName());
dimensions.add(dimension);
}
return dimensions;
}
private String getEntryKey(Map.Entry<String, Object> entry) {
// metric parser special handle, TODO delete
String entryKey = entry.getKey();
if (entryKey.contains("__")) {
entryKey = entryKey.split("__")[1];
}
return entryKey;
}
private Set<SchemaElement> getMetrics(EntityInfo modelInfo) {
Set<SchemaElement> metrics = new LinkedHashSet();
for (DataInfo metricValue : modelInfo.getMetrics()) {
SchemaElement metric = new SchemaElement();
BeanUtils.copyProperties(metricValue, metric);
metrics.add(metric);
}
return metrics;
}
private String getEntityPrimaryName(EntityInfo modelInfo) {
return modelInfo.getModelInfo().getPrimaryKey();
}
}

View File

@@ -0,0 +1,9 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import java.util.List;
public interface StatisticsService {
void batchSaveStatistics(List<StatisticsDO> list);
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.chat.server.service;
import java.lang.annotation.Documented;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimeCost {
}

View File

@@ -0,0 +1,33 @@
package com.tencent.supersonic.chat.server.service;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@Aspect
public class TimeCostAOP {
@Pointcut("@annotation(com.tencent.supersonic.chat.server.service.TimeCost)")
private void timeCostAdvicePointcut() {
}
@Around("timeCostAdvicePointcut()")
public Object timeCostAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("begin to add time cost!");
Long startTime = System.currentTimeMillis();
Object object = joinPoint.proceed();
if (object instanceof QueryResult) {
QueryResult queryResult = (QueryResult) object;
queryResult.setQueryTimeCost(System.currentTimeMillis() - startTime);
return queryResult;
}
return object;
}
}

View File

@@ -0,0 +1,83 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.agent.Agent;
import com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO;
import com.tencent.supersonic.chat.server.persistence.repository.AgentRepository;
import com.tencent.supersonic.chat.server.service.AgentService;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@Service
public class AgentServiceImpl implements AgentService {
private AgentRepository agentRepository;
public AgentServiceImpl(AgentRepository agentRepository) {
this.agentRepository = agentRepository;
}
@Override
public List<Agent> getAgents() {
return getAgentDOList().stream()
.map(this::convert).collect(Collectors.toList());
}
@Override
public void createAgent(Agent agent, User user) {
agentRepository.createAgent(convert(agent, user));
}
@Override
public void updateAgent(Agent agent, User user) {
agentRepository.updateAgent(convert(agent, user));
}
@Override
public Agent getAgent(Integer id) {
if (id == null) {
return null;
}
return convert(agentRepository.getAgent(id));
}
@Override
public void deleteAgent(Integer id) {
agentRepository.deleteAgent(id);
}
private List<AgentDO> getAgentDOList() {
return agentRepository.getAgents();
}
private Agent convert(AgentDO agentDO) {
if (agentDO == null) {
return null;
}
Agent agent = new Agent();
BeanUtils.copyProperties(agentDO, agent);
agent.setAgentConfig(agentDO.getConfig());
agent.setExamples(JSONObject.parseArray(agentDO.getExamples(), String.class));
return agent;
}
private AgentDO convert(Agent agent, User user) {
AgentDO agentDO = new AgentDO();
BeanUtils.copyProperties(agent, agentDO);
agentDO.setConfig(agent.getAgentConfig());
agentDO.setExamples(JSONObject.toJSONString(agent.getExamples()));
agentDO.setCreatedAt(new Date());
agentDO.setCreatedBy(user.getName());
agentDO.setUpdatedAt(new Date());
agentDO.setUpdatedBy(user.getName());
if (agentDO.getStatus() == null) {
agentDO.setStatus(1);
}
return agentDO;
}
}

View File

@@ -0,0 +1,264 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.request.DictLatestTaskReq;
import com.tencent.supersonic.chat.api.pojo.request.DictTaskFilterReq;
import com.tencent.supersonic.chat.api.pojo.response.DictLatestTaskResp;
import com.tencent.supersonic.chat.core.config.DefaultMetric;
import com.tencent.supersonic.chat.core.config.Dim4Dict;
import com.tencent.supersonic.chat.core.knowledge.DictConfig;
import com.tencent.supersonic.chat.core.knowledge.DictUpdateMode;
import com.tencent.supersonic.chat.core.knowledge.DimValue2DictCommand;
import com.tencent.supersonic.chat.core.knowledge.DimValueDictInfo;
import com.tencent.supersonic.chat.core.knowledge.FileHandler;
import com.tencent.supersonic.chat.core.utils.DictQueryHelper;
import com.tencent.supersonic.chat.server.listener.ApplicationStartedListener;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictTaskDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.DimValueDO;
import com.tencent.supersonic.chat.server.persistence.repository.DictRepository;
import com.tencent.supersonic.chat.server.service.KnowledgeTaskService;
import com.tencent.supersonic.chat.server.util.DictMetaHelper;
import com.tencent.supersonic.chat.server.util.DictTaskConverter;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
import com.tencent.supersonic.common.util.JsonUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Slf4j
@Service
public class ChatKnowledgeTaskServiceImpl implements KnowledgeTaskService {
private final DictMetaHelper metaUtils;
private final DictQueryHelper dictQueryHelper;
private final FileHandler fileHandler;
private final DictRepository dictRepository;
private final ApplicationStartedListener applicationStartedListener;
@Value("${dict.flush.enable:true}")
private Boolean dictFlushEnable;
@Value("${dict.flush.daily.enable:true}")
private Boolean dictFlushDailyEnable;
@Value("${dict.file.type:txt}")
private String dictFileType;
private String dimValue = "DimValue_%d_%d";
public ChatKnowledgeTaskServiceImpl(DictMetaHelper metaUtils,
DictQueryHelper dictQueryHelper,
FileHandler fileHandler,
DictRepository dictRepository,
ApplicationStartedListener applicationStartedListener) {
this.metaUtils = metaUtils;
this.dictQueryHelper = dictQueryHelper;
this.fileHandler = fileHandler;
this.dictRepository = dictRepository;
this.applicationStartedListener = applicationStartedListener;
}
@Scheduled(cron = "${knowledge.dimension.value.cron:0 0 0 * * ?}")
public Boolean dailyDictTask() {
log.info("[dailyDictTask] start");
if (!dictFlushDailyEnable) {
log.info("dictFlushDailyEnable is false, now finish dailyDictTask");
}
DimValue2DictCommand dimValue2DictCommend = new DimValue2DictCommand();
dimValue2DictCommend.setUpdateMode(DictUpdateMode.OFFLINE_FULL);
User user = User.getFakeUser();
addDictTask(dimValue2DictCommend, user);
log.info("[dailyDictTask] finish");
return true;
}
@Override
public Long addDictTask(DimValue2DictCommand dimValue2DictCommend, User user) {
if (!dictFlushEnable) {
return 0L;
}
if (DictUpdateMode.REALTIME_DELETE.equals(dimValue2DictCommend.getUpdateMode())) {
return deleteDictTask(dimValue2DictCommend, user);
}
DictTaskDO dictTaskDO = DictTaskConverter.generateDimValueDictTaskDO(dimValue2DictCommend, user);
log.info("[addDictTask] dictTaskDO:{}", dictTaskDO);
// todo check dimension can not be searched
dictRepository.createDimValueDictTask(dictTaskDO);
runDictTask(dictTaskDO, user);
return dictTaskDO.getId();
}
public Long runDictTask(DictTaskDO dictTaskDO, User user) {
if (Objects.isNull(dictTaskDO)) {
return -1L;
}
DimValue2DictCommand command = JsonUtil.toObject(dictTaskDO.getCommand(), DimValue2DictCommand.class);
try {
//1. construct internal dictionary requirements
List<DimValueDO> dimValueDOList = metaUtils.generateDimValueInfo(command);
Set<Long> dimIds = generateDimSet(dimValueDOList);
dictTaskDO.setDimIds(JsonUtil.toString(dimIds));
dictRepository.updateDictTaskStatus(TaskStatusEnum.RUNNING.getCode(), dictTaskDO);
log.debug("dimValueDOList:{}", dimValueDOList);
//2. query dimension value information
for (DimValueDO dimValueDO : dimValueDOList) {
Long modelId = dimValueDO.getModelId();
DefaultMetric defaultMetricDesc = dimValueDO.getDefaultMetricDescList().get(0);
for (Dim4Dict dim4Dict : dimValueDO.getDimensions()) {
List<String> data = dictQueryHelper.fetchDimValueSingle(modelId, defaultMetricDesc, dim4Dict, user);
//3. local file changes
String fileName = String.format(dimValue + Constants.DOT + dictFileType, modelId,
dim4Dict.getDimId());
fileHandler.writeFile(data, fileName, false);
}
}
applicationStartedListener.updateKnowledgeDimValue();
log.debug("updateDictTaskStatus to SUCCESS");
dictRepository.updateDictTaskStatus(TaskStatusEnum.SUCCESS.getCode(), dictTaskDO);
} catch (Exception e) {
log.warn("addDictInfo exception:", e);
dictRepository.updateDictTaskStatus(TaskStatusEnum.ERROR.getCode(), dictTaskDO);
}
return 1L;
}
private Set<Long> generateDimSet(List<DimValueDO> dimValueDOList) {
Set<Long> dimIds = new HashSet<>();
if (!CollectionUtils.isEmpty(dimValueDOList)) {
dimValueDOList.stream().forEach(dimValueDO -> {
if (!CollectionUtils.isEmpty(dimValueDO.getDimensions())) {
dimValueDO.getDimensions().stream().forEach(dim4Dict -> dimIds.add(dim4Dict.getDimId()));
}
});
}
return dimIds;
}
@Override
public Long deleteDictTask(DimValue2DictCommand dimValue2DictCommand, User user) {
if (!dictFlushEnable) {
return 0L;
}
if (Objects.isNull(dimValue2DictCommand) || !DictUpdateMode.REALTIME_DELETE.equals(
dimValue2DictCommand.getUpdateMode())) {
throw new RuntimeException("illegal parameter");
}
DictTaskDO dictTaskDO = DictTaskConverter.generateDimValueDictTaskDO(dimValue2DictCommand, user);
log.info("[deleteDictTask] dictTaskDO:{}", dictTaskDO);
Set<Long> dimIds = generateDimSetFromCommand(dimValue2DictCommand.getModelAndDimPair());
dictTaskDO.setDimIds(JsonUtil.toString(dimIds));
dictRepository.createDimValueDictTask(dictTaskDO);
Map<Long, List<Long>> modelAndDimPair = dimValue2DictCommand.getModelAndDimPair();
if (CollectionUtils.isEmpty(modelAndDimPair)) {
return 0L;
}
for (Long modelId : modelAndDimPair.keySet()) {
if (CollectionUtils.isEmpty(modelAndDimPair.get(modelId))) {
continue;
}
for (Long dimId : modelAndDimPair.get(modelId)) {
String fileName = String.format(dimValue + Constants.DOT + dictFileType, modelId, dimId);
fileHandler.deleteDictFile(fileName);
}
}
applicationStartedListener.updateKnowledgeDimValue();
dictRepository.updateDictTaskStatus(TaskStatusEnum.SUCCESS.getCode(), dictTaskDO);
applicationStartedListener.updateKnowledgeDimValue();
return 1L;
}
private Set<Long> generateDimSetFromCommand(Map<Long, List<Long>> modelAndDimPair) {
Set<Long> dimIds = new HashSet<>();
if (!CollectionUtils.isEmpty(modelAndDimPair)) {
modelAndDimPair.forEach((k, v) -> dimIds.addAll(v));
}
return dimIds;
}
@Override
public String getDictRootPath() {
return fileHandler.getDictRootPath();
}
@Override
public List<DictLatestTaskResp> searchDictLatestTaskList(DictLatestTaskReq latestFilter, User user) {
DictTaskFilterReq filter = new DictTaskFilterReq();
BeanUtils.copyProperties(latestFilter, filter);
List<DimValueDictInfo> dimValueDictInfoList = searchDictTaskList(filter, user);
return extractLatestTask(dimValueDictInfoList, latestFilter.getDimIds());
}
private List<DictLatestTaskResp> extractLatestTask(List<DimValueDictInfo> dimValueDictInfoList, List<Long> dimIds) {
List<DictLatestTaskResp> dictLatestTaskRespList = new ArrayList<>();
Map<Long, DictLatestTaskResp> dimAndTaskPair = new HashMap<>(50);
for (DimValueDictInfo dimValueDictInfo : dimValueDictInfoList) {
//1. filter
if (Objects.isNull(dimValueDictInfo) || CollectionUtils.isEmpty(dimValueDictInfo.getDimIds())) {
continue;
}
if (!CollectionUtils.isEmpty(dimIds)) {
Set<Long> tmp = dimValueDictInfo.getDimIds();
tmp.retainAll(dimIds);
dimValueDictInfo.setDimIds(tmp);
if (tmp.size() <= 0) {
continue;
}
}
// 2. extract
Set<Long> dimIdList = dimValueDictInfo.getDimIds();
for (Long dimId : dimIdList) {
DictLatestTaskResp dictLatestTaskResp = new DictLatestTaskResp();
if (!dimAndTaskPair.containsKey(dimId)) {
BeanUtils.copyProperties(dimValueDictInfo, dictLatestTaskResp);
dictLatestTaskResp.setDimId(dimId);
} else {
DictLatestTaskResp dictLatestTaskExist = dimAndTaskPair.get(dimId);
if (dictLatestTaskExist.getCreatedAt().before(dimValueDictInfo.getCreatedAt())) {
BeanUtils.copyProperties(dimValueDictInfo, dictLatestTaskResp);
dictLatestTaskResp.setDimId(dimId);
} else {
dictLatestTaskResp = dictLatestTaskExist;
}
}
dimAndTaskPair.put(dimId, dictLatestTaskResp);
}
}
if (dimAndTaskPair.size() >= 0 && !CollectionUtils.isEmpty(dimAndTaskPair.values())) {
dimAndTaskPair.values().stream()
.filter(v -> !v.getCommand().contains(DictUpdateMode.REALTIME_DELETE.name()))
.forEach(v -> dictLatestTaskRespList.add(v));
}
return dictLatestTaskRespList;
}
@Override
public List<DimValueDictInfo> searchDictTaskList(DictTaskFilterReq filter, User user) {
return dictRepository.searchDictTaskList(filter);
}
@Override
public DictConfig getDictInfoByModelId(Long modelId) {
return dictRepository.getDictInfoByModelId(modelId);
}
}

View File

@@ -0,0 +1,237 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.request.PageQueryInfoReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.api.pojo.response.ShowCaseResp;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.QueryDO;
import com.tencent.supersonic.chat.server.persistence.repository.ChatContextRepository;
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
import com.tencent.supersonic.chat.server.persistence.repository.ChatRepository;
import com.tencent.supersonic.chat.server.service.ChatService;
import com.tencent.supersonic.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service("ChatService")
@Primary
@Slf4j
public class ChatServiceImpl implements ChatService {
private ChatContextRepository chatContextRepository;
private ChatRepository chatRepository;
private ChatQueryRepository chatQueryRepository;
public ChatServiceImpl(ChatContextRepository chatContextRepository, ChatRepository chatRepository,
ChatQueryRepository chatQueryRepository) {
this.chatContextRepository = chatContextRepository;
this.chatRepository = chatRepository;
this.chatQueryRepository = chatQueryRepository;
}
@Override
public Set<Long> getContextModel(Integer chatId) {
if (Objects.isNull(chatId)) {
return null;
}
ChatContext chatContext = getOrCreateContext(chatId);
if (Objects.isNull(chatContext)) {
return null;
}
SemanticParseInfo originalSemanticParse = chatContext.getParseInfo();
if (Objects.nonNull(originalSemanticParse) && Objects.nonNull(originalSemanticParse.getModel().getModelIds())) {
return originalSemanticParse.getModel().getModelIds();
}
return null;
}
@Override
public ChatContext getOrCreateContext(int chatId) {
return chatContextRepository.getOrCreateContext(chatId);
}
@Override
public void updateContext(ChatContext chatCtx) {
log.debug("save ChatContext {}", chatCtx);
chatContextRepository.updateContext(chatCtx);
}
@Override
public Boolean addChat(User user, String chatName, Integer agentId) {
ChatDO chatDO = new ChatDO();
chatDO.setChatName(chatName);
chatDO.setCreator(user.getName());
chatDO.setCreateTime(getCurrentTime());
chatDO.setIsDelete(0);
chatDO.setLastTime(getCurrentTime());
chatDO.setLastQuestion("Hello, welcome to using supersonic");
chatDO.setIsTop(0);
chatDO.setAgentId(agentId);
return chatRepository.createChat(chatDO);
}
@Override
public List<ChatDO> getAll(String userName, Integer agentId) {
return chatRepository.getAll(userName, agentId);
}
@Override
public boolean updateChatName(Long chatId, String chatName, String userName) {
return chatRepository.updateChatName(chatId, chatName, getCurrentTime(), userName);
}
@Override
public boolean updateFeedback(Integer id, Integer score, String feedback) {
QueryDO intelligentQueryDO = new QueryDO();
intelligentQueryDO.setId(id);
intelligentQueryDO.setScore(score);
intelligentQueryDO.setFeedback(feedback);
return chatRepository.updateFeedback(intelligentQueryDO);
}
@Override
public boolean updateChatIsTop(Long chatId, int isTop) {
return chatRepository.updateConversionIsTop(chatId, isTop);
}
@Override
public Boolean deleteChat(Long chatId, String userName) {
return chatRepository.deleteChat(chatId, userName);
}
@Override
public PageInfo<QueryResp> queryInfo(PageQueryInfoReq pageQueryInfoReq, long chatId) {
PageInfo<QueryResp> queryRespPageInfo = chatQueryRepository.getChatQuery(pageQueryInfoReq, chatId);
if (CollectionUtils.isEmpty(queryRespPageInfo.getList())) {
return queryRespPageInfo;
}
fillParseInfo(queryRespPageInfo.getList());
return queryRespPageInfo;
}
@Override
public QueryResp getChatQuery(Long queryId) {
return chatQueryRepository.getChatQuery(queryId);
}
@Override
public ShowCaseResp queryShowCase(PageQueryInfoReq pageQueryInfoReq, int agentId) {
ShowCaseResp showCaseResp = new ShowCaseResp();
showCaseResp.setCurrent(pageQueryInfoReq.getCurrent());
showCaseResp.setPageSize(pageQueryInfoReq.getPageSize());
List<QueryResp> queryResps = chatQueryRepository.queryShowCase(pageQueryInfoReq, agentId);
if (CollectionUtils.isEmpty(queryResps)) {
return showCaseResp;
}
queryResps.removeIf(queryResp -> {
if (queryResp.getQueryResult() == null) {
return true;
}
if (queryResp.getQueryResult().getResponse() != null) {
return false;
}
if (CollectionUtils.isEmpty(queryResp.getQueryResult().getQueryResults())) {
return true;
}
Map<String, Object> data = queryResp.getQueryResult().getQueryResults().get(0);
return CollectionUtils.isEmpty(data);
});
queryResps = new ArrayList<>(queryResps.stream()
.collect(Collectors.toMap(QueryResp::getQueryText, Function.identity(),
(existing, replacement) -> existing, LinkedHashMap::new)).values());
fillParseInfo(queryResps);
Map<Long, List<QueryResp>> showCaseMap = queryResps.stream()
.collect(Collectors.groupingBy(QueryResp::getChatId));
showCaseResp.setShowCaseMap(showCaseMap);
return showCaseResp;
}
private void fillParseInfo(List<QueryResp> queryResps) {
List<Long> queryIds = queryResps.stream()
.map(QueryResp::getQuestionId).collect(Collectors.toList());
List<ChatParseDO> chatParseDOs = chatQueryRepository.getParseInfoList(queryIds);
if (CollectionUtils.isEmpty(chatParseDOs)) {
return;
}
Map<Long, List<ChatParseDO>> chatParseMap = chatParseDOs.stream()
.collect(Collectors.groupingBy(ChatParseDO::getQuestionId));
for (QueryResp queryResp : queryResps) {
List<ChatParseDO> chatParseDOList = chatParseMap.get(queryResp.getQuestionId());
if (CollectionUtils.isEmpty(chatParseDOList)) {
continue;
}
List<SemanticParseInfo> parseInfos = chatParseDOList.stream().map(chatParseDO ->
JsonUtil.toObject(chatParseDO.getParseInfo(), SemanticParseInfo.class))
.sorted(Comparator.comparingDouble(SemanticParseInfo::getScore).reversed())
.collect(Collectors.toList());
queryResp.setParseInfos(parseInfos);
}
}
@Override
public void updateQuery(Long questionId, int parseId, QueryResult queryResult, ChatContext chatCtx) {
//The history record only retains the query result of the first parse
if (parseId > 1) {
return;
}
ChatQueryDO chatQueryDO = new ChatQueryDO();
chatQueryDO.setQuestionId(questionId);
chatQueryDO.setQueryResult(JsonUtil.toString(queryResult));
chatQueryDO.setQueryState(1);
updateQuery(chatQueryDO);
chatRepository.updateLastQuestion(chatCtx.getChatId().longValue(),
chatCtx.getQueryText(), getCurrentTime());
}
@Override
public int updateQuery(ChatQueryDO chatQueryDO) {
return chatQueryRepository.updateChatQuery(chatQueryDO);
}
@Override
public List<ChatParseDO> batchAddParse(ChatContext chatCtx, QueryReq queryReq, ParseResp parseResult) {
List<SemanticParseInfo> candidateParses = parseResult.getSelectedParses();
return chatQueryRepository.batchSaveParseInfo(chatCtx, queryReq, parseResult, candidateParses);
}
@Override
public ChatQueryDO getLastQuery(long chatId) {
return chatQueryRepository.getLastChatQuery(chatId);
}
private String getCurrentTime() {
SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return tempDate.format(new java.util.Date());
}
public ChatParseDO getParseInfo(Long questionId, int parseId) {
return chatQueryRepository.getParseInfo(questionId, parseId);
}
public Boolean deleteChatQuery(Long questionId) {
return chatQueryRepository.deleteChatQuery(questionId);
}
}

View File

@@ -0,0 +1,366 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.request.ChatAggConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigBaseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.request.ChatDefaultConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.Entity;
import com.tencent.supersonic.chat.api.pojo.request.ItemNameVisibilityInfo;
import com.tencent.supersonic.chat.api.pojo.request.ItemVisibility;
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeInfoReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatAggRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDefaultRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDetailRichConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.EntityRichInfoResp;
import com.tencent.supersonic.chat.api.pojo.response.ItemVisibilityInfo;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import com.tencent.supersonic.chat.server.util.ChatConfigHelper;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import com.tencent.supersonic.chat.server.util.VisibilityEvent;
import com.tencent.supersonic.chat.server.persistence.repository.ChatConfigRepository;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.chat.server.service.SemanticService;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.headless.api.pojo.SchemaItem;
import com.tencent.supersonic.headless.api.response.DimensionResp;
import com.tencent.supersonic.headless.api.response.MetricResp;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.MetricService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
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;
@Slf4j
@Service
public class ConfigServiceImpl implements ConfigService {
private final ChatConfigRepository chatConfigRepository;
private final ChatConfigHelper chatConfigHelper;
private final DimensionService dimensionService;
private final MetricService metricService;
@Autowired
private SemanticService semanticService;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
private SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
public ConfigServiceImpl(ChatConfigRepository chatConfigRepository,
ChatConfigHelper chatConfigHelper,
DimensionService dimensionService,
MetricService metricService) {
this.chatConfigRepository = chatConfigRepository;
this.chatConfigHelper = chatConfigHelper;
this.dimensionService = dimensionService;
this.metricService = metricService;
}
@Override
public Long addConfig(ChatConfigBaseReq configBaseCmd, User user) {
log.info("[create model extend] object:{}", JsonUtil.toString(configBaseCmd, true));
duplicateCheck(configBaseCmd.getModelId());
ChatConfig chaConfig = chatConfigHelper.newChatConfig(configBaseCmd, user);
Long id = chatConfigRepository.createConfig(chaConfig);
applicationEventPublisher.publishEvent(new VisibilityEvent(this, chaConfig));
return id;
}
private void duplicateCheck(Long modelId) {
ChatConfigFilter filter = new ChatConfigFilter();
filter.setModelId(modelId);
List<ChatConfigResp> chaConfigDescList = chatConfigRepository.getChatConfig(filter);
if (!CollectionUtils.isEmpty(chaConfigDescList)) {
throw new RuntimeException("chat config existed, no need to add repeatedly");
}
}
@Override
public Long editConfig(ChatConfigEditReqReq configEditCmd, User user) {
log.info("[edit model extend] object:{}", JsonUtil.toString(configEditCmd, true));
if (Objects.isNull(configEditCmd) || Objects.isNull(configEditCmd.getId()) && Objects.isNull(
configEditCmd.getModelId())) {
throw new RuntimeException("editConfig, id and modelId are not allowed to be empty at the same time");
}
ChatConfig chaConfig = chatConfigHelper.editChatConfig(configEditCmd, user);
chatConfigRepository.updateConfig(chaConfig);
applicationEventPublisher.publishEvent(new VisibilityEvent(this, chaConfig));
return configEditCmd.getId();
}
public ItemNameVisibilityInfo getVisibilityByModelId(Long modelId) {
ChatConfigResp chatConfigResp = fetchConfigByModelId(modelId);
ChatConfig chatConfig = new ChatConfig();
chatConfig.setModelId(modelId);
chatConfig.setChatAggConfig(chatConfigResp.getChatAggConfig());
chatConfig.setChatDetailConfig(chatConfigResp.getChatDetailConfig());
ItemNameVisibilityInfo itemNameVisibility = getItemNameVisibility(chatConfig);
return itemNameVisibility;
}
public ItemNameVisibilityInfo getItemNameVisibility(ChatConfig chatConfig) {
Long modelId = chatConfig.getModelId();
List<Long> blackDimIdList = new ArrayList<>();
if (Objects.nonNull(chatConfig.getChatAggConfig()) && Objects.nonNull(chatConfig.getChatAggConfig())) {
blackDimIdList.addAll(chatConfig.getChatAggConfig().getVisibility().getBlackDimIdList());
}
if (Objects.nonNull(chatConfig.getChatDetailConfig()) && Objects.nonNull(chatConfig.getChatDetailConfig())) {
blackDimIdList.addAll(chatConfig.getChatDetailConfig().getVisibility().getBlackDimIdList());
}
List<Long> filterDimIdList = blackDimIdList.stream().distinct().collect(Collectors.toList());
List<Long> blackMetricIdList = new ArrayList<>();
if (Objects.nonNull(chatConfig.getChatAggConfig()) && Objects.nonNull(chatConfig.getChatAggConfig())) {
blackMetricIdList.addAll(chatConfig.getChatAggConfig().getVisibility().getBlackMetricIdList());
}
if (Objects.nonNull(chatConfig.getChatDetailConfig()) && Objects.nonNull(chatConfig.getChatDetailConfig())) {
blackMetricIdList.addAll(chatConfig.getChatDetailConfig().getVisibility().getBlackMetricIdList());
}
List<Long> filterMetricIdList = blackMetricIdList.stream().distinct().collect(Collectors.toList());
ItemNameVisibilityInfo itemNameVisibility = new ItemNameVisibilityInfo();
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
if (!CollectionUtils.isEmpty(blackDimIdList)) {
List<DimensionResp> dimensionRespList = dimensionService.getDimensions(metaFilter);
List<String> blackDimNameList = dimensionRespList.stream().filter(o -> filterDimIdList.contains(o.getId()))
.map(SchemaItem::getName).collect(Collectors.toList());
itemNameVisibility.setBlackDimNameList(blackDimNameList);
}
if (!CollectionUtils.isEmpty(blackMetricIdList)) {
List<MetricResp> metricRespList = metricService.getMetrics(metaFilter);
List<String> blackMetricList = metricRespList.stream().filter(o -> filterMetricIdList.contains(o.getId()))
.map(SchemaItem::getName).collect(Collectors.toList());
itemNameVisibility.setBlackMetricNameList(blackMetricList);
}
return itemNameVisibility;
}
@Override
public List<ChatConfigResp> search(ChatConfigFilter filter, User user) {
log.info("[search model extend] object:{}", JsonUtil.toString(filter, true));
List<ChatConfigResp> chaConfigDescList = chatConfigRepository.getChatConfig(filter);
return chaConfigDescList;
}
@Override
public ChatConfigResp fetchConfigByModelId(Long modelId) {
return chatConfigRepository.getConfigByModelId(modelId);
}
private ItemVisibilityInfo fetchVisibilityDescByConfig(ItemVisibility visibility,
ModelSchema modelSchema) {
ItemVisibilityInfo itemVisibilityDesc = new ItemVisibilityInfo();
List<Long> dimIdAllList = chatConfigHelper.generateAllDimIdList(modelSchema);
List<Long> metricIdAllList = chatConfigHelper.generateAllMetricIdList(modelSchema);
List<Long> blackDimIdList = new ArrayList<>();
List<Long> blackMetricIdList = new ArrayList<>();
if (Objects.nonNull(visibility)) {
if (!CollectionUtils.isEmpty(visibility.getBlackDimIdList())) {
blackDimIdList.addAll(visibility.getBlackDimIdList());
}
if (!CollectionUtils.isEmpty(visibility.getBlackMetricIdList())) {
blackMetricIdList.addAll(visibility.getBlackMetricIdList());
}
}
List<Long> whiteMetricIdList = metricIdAllList.stream()
.filter(id -> !blackMetricIdList.contains(id) && metricIdAllList.contains(id))
.collect(Collectors.toList());
List<Long> whiteDimIdList = dimIdAllList.stream()
.filter(id -> !blackDimIdList.contains(id) && dimIdAllList.contains(id))
.collect(Collectors.toList());
itemVisibilityDesc.setBlackDimIdList(blackDimIdList);
itemVisibilityDesc.setBlackMetricIdList(blackMetricIdList);
itemVisibilityDesc.setWhiteDimIdList(Objects.isNull(whiteDimIdList) ? new ArrayList<>() : whiteDimIdList);
itemVisibilityDesc.setWhiteMetricIdList(
Objects.isNull(whiteMetricIdList) ? new ArrayList<>() : whiteMetricIdList);
return itemVisibilityDesc;
}
@Override
public ChatConfigRichResp getConfigRichInfo(Long modelId) {
ChatConfigRichResp chatConfigRich = new ChatConfigRichResp();
ChatConfigResp chatConfigResp = chatConfigRepository.getConfigByModelId(modelId);
if (Objects.isNull(chatConfigResp)) {
log.info("there is no chatConfigDesc for modelId:{}", modelId);
return chatConfigRich;
}
BeanUtils.copyProperties(chatConfigResp, chatConfigRich);
ModelSchema modelSchema = semanticService.getModelSchema(modelId);
if (modelSchema == null) {
return chatConfigRich;
}
chatConfigRich.setBizName(modelSchema.getModel().getBizName());
chatConfigRich.setModelName(modelSchema.getModel().getName());
chatConfigRich.setChatAggRichConfig(fillChatAggRichConfig(modelSchema, chatConfigResp));
chatConfigRich.setChatDetailRichConfig(fillChatDetailRichConfig(modelSchema, chatConfigRich, chatConfigResp));
return chatConfigRich;
}
private ChatDetailRichConfigResp fillChatDetailRichConfig(ModelSchema modelSchema,
ChatConfigRichResp chatConfigRich,
ChatConfigResp chatConfigResp) {
if (Objects.isNull(chatConfigResp) || Objects.isNull(chatConfigResp.getChatDetailConfig())) {
return null;
}
ChatDetailRichConfigResp detailRichConfig = new ChatDetailRichConfigResp();
ChatDetailConfigReq chatDetailConfig = chatConfigResp.getChatDetailConfig();
ItemVisibilityInfo itemVisibilityInfo = fetchVisibilityDescByConfig(
chatDetailConfig.getVisibility(), modelSchema);
detailRichConfig.setVisibility(itemVisibilityInfo);
detailRichConfig.setKnowledgeInfos(fillKnowledgeBizName(chatDetailConfig.getKnowledgeInfos(), modelSchema));
detailRichConfig.setGlobalKnowledgeConfig(chatDetailConfig.getGlobalKnowledgeConfig());
detailRichConfig.setChatDefaultConfig(fetchDefaultConfig(chatDetailConfig.getChatDefaultConfig(),
modelSchema, itemVisibilityInfo));
return detailRichConfig;
}
private EntityRichInfoResp generateRichEntity(Entity entity, ModelSchema modelSchema) {
EntityRichInfoResp entityRichInfo = new EntityRichInfoResp();
if (Objects.isNull(entity) || Objects.isNull(entity.getEntityId())) {
return entityRichInfo;
}
BeanUtils.copyProperties(entity, entityRichInfo);
Map<Long, SchemaElement> dimIdAndRespPair = modelSchema.getDimensions().stream()
.collect(Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
entityRichInfo.setDimItem(dimIdAndRespPair.get(entity.getEntityId()));
return entityRichInfo;
}
private ChatAggRichConfigResp fillChatAggRichConfig(ModelSchema modelSchema, ChatConfigResp chatConfigResp) {
if (Objects.isNull(chatConfigResp) || Objects.isNull(chatConfigResp.getChatAggConfig())) {
return null;
}
ChatAggConfigReq chatAggConfig = chatConfigResp.getChatAggConfig();
ChatAggRichConfigResp chatAggRichConfig = new ChatAggRichConfigResp();
ItemVisibilityInfo itemVisibilityInfo = fetchVisibilityDescByConfig(chatAggConfig.getVisibility(), modelSchema);
chatAggRichConfig.setVisibility(itemVisibilityInfo);
chatAggRichConfig.setKnowledgeInfos(fillKnowledgeBizName(chatAggConfig.getKnowledgeInfos(), modelSchema));
chatAggRichConfig.setGlobalKnowledgeConfig(chatAggConfig.getGlobalKnowledgeConfig());
chatAggRichConfig.setChatDefaultConfig(fetchDefaultConfig(chatAggConfig.getChatDefaultConfig(),
modelSchema, itemVisibilityInfo));
return chatAggRichConfig;
}
private ChatDefaultRichConfigResp fetchDefaultConfig(ChatDefaultConfigReq chatDefaultConfig,
ModelSchema modelSchema,
ItemVisibilityInfo itemVisibilityInfo) {
ChatDefaultRichConfigResp defaultRichConfig = new ChatDefaultRichConfigResp();
if (Objects.isNull(chatDefaultConfig)) {
return defaultRichConfig;
}
BeanUtils.copyProperties(chatDefaultConfig, defaultRichConfig);
Map<Long, SchemaElement> dimIdAndRespPair = modelSchema.getDimensions().stream()
.collect(Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
Map<Long, SchemaElement> metricIdAndRespPair = modelSchema.getMetrics().stream()
.collect(Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
List<SchemaElement> dimensions = new ArrayList<>();
List<SchemaElement> metrics = new ArrayList<>();
if (!CollectionUtils.isEmpty(chatDefaultConfig.getDimensionIds())) {
chatDefaultConfig.getDimensionIds().stream()
.filter(dimId -> dimIdAndRespPair.containsKey(dimId)
&& itemVisibilityInfo.getWhiteDimIdList().contains(dimId))
.forEach(dimId -> {
SchemaElement dimSchemaResp = dimIdAndRespPair.get(dimId);
if (Objects.nonNull(dimSchemaResp)) {
SchemaElement dimSchema = new SchemaElement();
BeanUtils.copyProperties(dimSchemaResp, dimSchema);
dimensions.add(dimSchema);
}
});
}
if (!CollectionUtils.isEmpty(chatDefaultConfig.getMetricIds())) {
chatDefaultConfig.getMetricIds().stream()
.filter(metricId -> metricIdAndRespPair.containsKey(metricId)
&& itemVisibilityInfo.getWhiteMetricIdList().contains(metricId))
.forEach(metricId -> {
SchemaElement metricSchemaResp = metricIdAndRespPair.get(metricId);
if (Objects.nonNull(metricSchemaResp)) {
SchemaElement metricSchema = new SchemaElement();
BeanUtils.copyProperties(metricSchemaResp, metricSchema);
metrics.add(metricSchema);
}
});
}
defaultRichConfig.setDimensions(dimensions);
defaultRichConfig.setMetrics(metrics);
return defaultRichConfig;
}
private List<KnowledgeInfoReq> fillKnowledgeBizName(List<KnowledgeInfoReq> knowledgeInfos,
ModelSchema modelSchema) {
if (CollectionUtils.isEmpty(knowledgeInfos)) {
return new ArrayList<>();
}
Map<Long, SchemaElement> dimIdAndRespPair = modelSchema.getDimensions().stream()
.collect(Collectors.toMap(SchemaElement::getId, Function.identity(), (k1, k2) -> k1));
knowledgeInfos.stream().forEach(knowledgeInfo -> {
if (Objects.nonNull(knowledgeInfo)) {
SchemaElement dimSchemaResp = dimIdAndRespPair.get(knowledgeInfo.getItemId());
if (Objects.nonNull(dimSchemaResp)) {
knowledgeInfo.setBizName(dimSchemaResp.getBizName());
}
}
});
return knowledgeInfos;
}
@Override
public List<ChatConfigRichResp> getAllChatRichConfig() {
List<ChatConfigRichResp> chatConfigRichInfoList = new ArrayList<>();
List<ModelSchema> modelSchemas = semanticInterpreter.getModelSchema();
modelSchemas.stream().forEach(modelSchema -> {
ChatConfigRichResp chatConfigRichInfo = getConfigRichInfo(modelSchema.getModel().getId());
if (Objects.nonNull(chatConfigRichInfo)) {
chatConfigRichInfoList.add(chatConfigRichInfo);
}
});
return chatConfigRichInfoList;
}
@Override
public Map<Long, ChatConfigRichResp> getModelIdToChatRichConfig() {
List<ChatConfigRichResp> allChatRichConfig = getAllChatRichConfig();
return allChatRichConfig.stream()
.collect(Collectors.toMap(ChatConfigRichResp::getModelId, value -> value, (k1, k2) -> k1));
}
}

View File

@@ -0,0 +1,54 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import com.tencent.supersonic.chat.core.knowledge.SearchService;
import com.tencent.supersonic.chat.core.utils.HanlpHelper;
import com.tencent.supersonic.chat.server.service.KnowledgeService;
import com.tencent.supersonic.common.pojo.enums.DictWordType;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class KnowledgeServiceImpl implements KnowledgeService {
public void updateSemanticKnowledge(List<DictWord> natures) {
List<DictWord> prefixes = natures.stream()
.filter(entry -> !entry.getNatureWithFrequency().contains(DictWordType.SUFFIX.getType()))
.collect(Collectors.toList());
for (DictWord nature : prefixes) {
HanlpHelper.addToCustomDictionary(nature);
}
List<DictWord> suffixes = natures.stream()
.filter(entry -> entry.getNatureWithFrequency().contains(DictWordType.SUFFIX.getType()))
.collect(Collectors.toList());
SearchService.loadSuffix(suffixes);
}
public void reloadAllData(List<DictWord> natures) {
// 1. reload custom knowledge
try {
HanlpHelper.reloadCustomDictionary();
} catch (Exception e) {
log.error("reloadCustomDictionary error", e);
}
// 2. update online knowledge
updateOnlineKnowledge(natures);
}
public void updateOnlineKnowledge(List<DictWord> natures) {
try {
updateSemanticKnowledge(natures);
} catch (Exception e) {
log.error("updateSemanticKnowledge error", e);
}
}
}

View File

@@ -0,0 +1,232 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.request.PluginQueryReq;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.core.plugin.Plugin;
import com.tencent.supersonic.chat.core.plugin.PluginParseConfig;
import com.tencent.supersonic.chat.core.plugin.event.PluginAddEvent;
import com.tencent.supersonic.chat.core.plugin.event.PluginDelEvent;
import com.tencent.supersonic.chat.core.plugin.event.PluginUpdateEvent;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.PluginDOExample;
import com.tencent.supersonic.chat.server.persistence.repository.PluginRepository;
import com.tencent.supersonic.chat.server.service.PluginService;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.headless.api.response.ModelResp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
@Slf4j
public class PluginServiceImpl implements PluginService {
private PluginRepository pluginRepository;
private ApplicationEventPublisher publisher;
public PluginServiceImpl(PluginRepository pluginRepository,
ApplicationEventPublisher publisher) {
this.pluginRepository = pluginRepository;
this.publisher = publisher;
}
@Override
public synchronized void createPlugin(Plugin plugin, User user) {
PluginDO pluginDO = convert(plugin, user);
pluginRepository.createPlugin(pluginDO);
//compatible with H2 db
List<Plugin> plugins = getPluginList();
publisher.publishEvent(new PluginAddEvent(this, plugins.get(plugins.size() - 1)));
}
@Override
public void updatePlugin(Plugin plugin, User user) {
Long id = plugin.getId();
PluginDO pluginDO = pluginRepository.getPlugin(id);
Plugin oldPlugin = convert(pluginDO);
convert(plugin, pluginDO, user);
pluginRepository.updatePlugin(pluginDO);
publisher.publishEvent(new PluginUpdateEvent(this, oldPlugin, plugin));
}
@Override
public void deletePlugin(Long id) {
PluginDO pluginDO = pluginRepository.getPlugin(id);
if (pluginDO != null) {
pluginRepository.deletePlugin(id);
publisher.publishEvent(new PluginDelEvent(this, convert(pluginDO)));
}
}
@Override
public List<Plugin> getPluginList() {
List<Plugin> plugins = Lists.newArrayList();
List<PluginDO> pluginDOS = pluginRepository.getPlugins();
if (CollectionUtils.isEmpty(pluginDOS)) {
return plugins;
}
return pluginDOS.stream().map(this::convert).collect(Collectors.toList());
}
@Override
public List<Plugin> fetchPluginDOs(String queryText, String type) {
List<PluginDO> pluginDOS = pluginRepository.fetchPluginDOs(queryText, type);
return convertList(pluginDOS);
}
@Override
public List<Plugin> query(PluginQueryReq pluginQueryReq) {
PluginDOExample pluginDOExample = new PluginDOExample();
pluginDOExample.createCriteria();
if (StringUtils.isNotBlank(pluginQueryReq.getType())) {
pluginDOExample.getOredCriteria().get(0).andTypeEqualTo(pluginQueryReq.getType());
}
if (StringUtils.isNotBlank(pluginQueryReq.getModel())) {
pluginDOExample.getOredCriteria().get(0).andModelLike('%' + pluginQueryReq.getModel() + '%');
}
if (StringUtils.isNotBlank(pluginQueryReq.getParseMode())) {
pluginDOExample.getOredCriteria().get(0).andParseModeEqualTo(pluginQueryReq.getParseMode());
}
if (StringUtils.isNotBlank(pluginQueryReq.getName())) {
pluginDOExample.getOredCriteria().get(0).andNameLike('%' + pluginQueryReq.getName() + '%');
}
if (StringUtils.isNotBlank(pluginQueryReq.getPattern())) {
pluginDOExample.getOredCriteria().get(0).andPatternLike('%' + pluginQueryReq.getPattern() + '%');
}
if (StringUtils.isNotBlank(pluginQueryReq.getCreatedBy())) {
pluginDOExample.getOredCriteria().get(0).andCreatedByEqualTo(pluginQueryReq.getCreatedBy());
}
List<PluginDO> pluginDOS = pluginRepository.query(pluginDOExample);
if (StringUtils.isNotBlank(pluginQueryReq.getPattern())) {
pluginDOS = pluginDOS.stream().filter(pluginDO ->
pluginDO.getPattern().contains(pluginQueryReq.getPattern())
|| (pluginDO.getName() != null
&& pluginDO.getName().contains(pluginQueryReq.getPattern())))
.collect(Collectors.toList());
}
return convertList(pluginDOS);
}
@Override
public Optional<Plugin> getPluginByName(String name) {
log.info("name:{}", name);
return getPluginList().stream()
.filter(plugin -> {
PluginParseConfig functionCallConfig = getPluginParseConfig(plugin);
if (functionCallConfig == null) {
return false;
}
return functionCallConfig.getName().equalsIgnoreCase(name);
})
.findFirst();
}
private PluginParseConfig getPluginParseConfig(Plugin plugin) {
if (StringUtils.isBlank(plugin.getParseModeConfig())) {
return null;
}
PluginParseConfig functionCallConfig = JsonUtil.toObject(
plugin.getParseModeConfig(), PluginParseConfig.class);
if (Objects.isNull(functionCallConfig) || StringUtils.isEmpty(functionCallConfig.getName())) {
return null;
}
if (StringUtils.isBlank(functionCallConfig.getName())) {
return null;
}
return functionCallConfig;
}
@Override
public List<Plugin> queryWithAuthCheck(PluginQueryReq pluginQueryReq, User user) {
return authCheck(query(pluginQueryReq), user);
}
@Override
public Map<String, Plugin> getNameToPlugin() {
List<Plugin> pluginList = getPluginList();
return pluginList.stream()
.filter(plugin -> {
PluginParseConfig functionCallConfig = getPluginParseConfig(plugin);
if (functionCallConfig == null) {
return false;
}
return true;
})
.collect(Collectors.toMap(a -> {
PluginParseConfig functionCallConfig = JsonUtil.toObject(
a.getParseModeConfig(), PluginParseConfig.class);
return functionCallConfig.getName();
}, a -> a, (k1, k2) -> k1));
}
private List<Plugin> authCheck(List<Plugin> plugins, User user) {
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
List<Long> modelIdAuthorized = semanticInterpreter.getModelList(AuthType.ADMIN, null, user).stream()
.map(ModelResp::getId).collect(Collectors.toList());
plugins = plugins.stream().filter(plugin -> {
if (CollectionUtils.isEmpty(plugin.getModelList()) || plugin.isContainsAllModel()) {
return true;
}
for (Long modelId : plugin.getModelList()) {
if (modelIdAuthorized.contains(modelId)) {
return true;
}
}
return false;
}).collect(Collectors.toList());
return plugins;
}
public Plugin convert(PluginDO pluginDO) {
Plugin plugin = new Plugin();
BeanUtils.copyProperties(pluginDO, plugin);
if (StringUtils.isNotBlank(pluginDO.getModel())) {
plugin.setModelList(Arrays.stream(pluginDO.getModel().split(","))
.map(Long::parseLong).collect(Collectors.toList()));
}
return plugin;
}
public PluginDO convert(Plugin plugin, User user) {
PluginDO pluginDO = new PluginDO();
BeanUtils.copyProperties(plugin, pluginDO);
pluginDO.setCreatedAt(new Date());
pluginDO.setCreatedBy(user.getName());
pluginDO.setUpdatedAt(new Date());
pluginDO.setUpdatedBy(user.getName());
pluginDO.setModel(StringUtils.join(plugin.getModelList(), ","));
return pluginDO;
}
public PluginDO convert(Plugin plugin, PluginDO pluginDO, User user) {
BeanUtils.copyProperties(plugin, pluginDO);
pluginDO.setUpdatedAt(new Date());
pluginDO.setUpdatedBy(user.getName());
pluginDO.setModel(StringUtils.join(plugin.getModelList(), ","));
return pluginDO;
}
public List<Plugin> convertList(List<PluginDO> pluginDOS) {
if (!CollectionUtils.isEmpty(pluginDOS)) {
return pluginDOS.stream().map(this::convert).collect(Collectors.toList());
}
return Lists.newArrayList();
}
}

View File

@@ -0,0 +1,700 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaMapInfo;
import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.api.pojo.request.DimensionValueReq;
import com.tencent.supersonic.chat.api.pojo.request.ExecuteQueryReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryDataReq;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.request.SimilarQueryReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
import com.tencent.supersonic.chat.core.agent.Agent;
import com.tencent.supersonic.chat.core.corrector.SemanticCorrector;
import com.tencent.supersonic.chat.core.knowledge.HanlpMapResult;
import com.tencent.supersonic.chat.core.knowledge.SearchService;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.core.mapper.SchemaMapper;
import com.tencent.supersonic.chat.core.parser.SemanticParser;
import com.tencent.supersonic.chat.core.plugin.Plugin;
import com.tencent.supersonic.chat.core.pojo.ChatContext;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.core.query.QueryManager;
import com.tencent.supersonic.chat.core.query.SemanticQuery;
import com.tencent.supersonic.chat.core.query.llm.s2sql.LLMSqlQuery;
import com.tencent.supersonic.chat.core.query.rule.RuleSemanticQuery;
import com.tencent.supersonic.chat.core.utils.HanlpHelper;
import com.tencent.supersonic.chat.core.utils.NatureHelper;
import com.tencent.supersonic.chat.core.utils.SimilarQueryManager;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatParseDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.CostType;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import com.tencent.supersonic.chat.server.processor.execute.ExecuteResultProcessor;
import com.tencent.supersonic.chat.server.processor.parse.ParseResultProcessor;
import com.tencent.supersonic.chat.server.service.AgentService;
import com.tencent.supersonic.chat.server.service.ChatService;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.chat.server.service.PluginService;
import com.tencent.supersonic.chat.server.service.QueryService;
import com.tencent.supersonic.chat.server.service.SemanticService;
import com.tencent.supersonic.chat.server.service.StatisticsService;
import com.tencent.supersonic.chat.server.service.TimeCost;
import com.tencent.supersonic.chat.server.util.ComponentFactory;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.QueryColumn;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.enums.QueryType;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.DateUtils;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.common.util.jsqlparser.FieldExpression;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserRemoveHelper;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserReplaceHelper;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
import com.tencent.supersonic.headless.api.request.QueryStructReq;
import com.tencent.supersonic.headless.api.response.QueryResultWithSchemaResp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.schema.Column;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
@Component("chatQueryService")
@Primary
@Slf4j
public class QueryServiceImpl implements QueryService {
@Autowired
private ChatService chatService;
@Autowired
private StatisticsService statisticsService;
@Autowired
private SimilarQueryManager similarQueryManager;
@Autowired
private SchemaService schemaService;
@Autowired
private AgentService agentService;
@Autowired
private ConfigService configService;
@Autowired
private PluginService pluginService;
@Value("${time.threshold: 100}")
private Integer timeThreshold;
private List<SchemaMapper> schemaMappers = ComponentFactory.getSchemaMappers();
private List<SemanticParser> semanticParsers = ComponentFactory.getSemanticParsers();
private List<ParseResultProcessor> parseProcessors = ComponentFactory.getParseProcessors();
private List<ExecuteResultProcessor> executeProcessors = ComponentFactory.getExecuteProcessors();
private List<SemanticCorrector> semanticCorrectors = ComponentFactory.getSemanticCorrectors();
@Override
public ParseResp performParsing(QueryReq queryReq) {
ParseResp parseResult = new ParseResp();
// build queryContext and chatContext
QueryContext queryCtx = buildQueryContext(queryReq);
// in order to support multi-turn conversation, chat context is needed
ChatContext chatCtx = chatService.getOrCreateContext(queryReq.getChatId());
List<StatisticsDO> timeCostDOList = new ArrayList<>();
// 1. mapper
schemaMappers.forEach(mapper -> {
long startTime = System.currentTimeMillis();
mapper.map(queryCtx);
timeCostDOList.add(StatisticsDO.builder().cost((int) (System.currentTimeMillis() - startTime))
.interfaceName(mapper.getClass().getSimpleName()).type(CostType.MAPPER.getType()).build());
});
// 2. parser
semanticParsers.forEach(parser -> {
long startTime = System.currentTimeMillis();
parser.parse(queryCtx, chatCtx);
timeCostDOList.add(StatisticsDO.builder().cost((int) (System.currentTimeMillis() - startTime))
.interfaceName(parser.getClass().getSimpleName()).type(CostType.PARSER.getType()).build());
log.info("{} result:{}", parser.getClass().getSimpleName(), JsonUtil.toString(queryCtx));
});
// 3. corrector
List<SemanticQuery> candidateQueries = queryCtx.getCandidateQueries();
if (CollectionUtils.isNotEmpty(candidateQueries)) {
for (SemanticQuery semanticQuery : candidateQueries) {
// the rules are not being corrected.
if (semanticQuery instanceof RuleSemanticQuery) {
continue;
}
semanticCorrectors.forEach(corrector -> {
corrector.correct(queryCtx, semanticQuery.getParseInfo());
});
}
}
// 4. processor
parseProcessors.forEach(processor -> {
long startTime = System.currentTimeMillis();
processor.process(parseResult, queryCtx, chatCtx);
timeCostDOList.add(StatisticsDO.builder().cost((int) (System.currentTimeMillis() - startTime))
.interfaceName(processor.getClass().getSimpleName())
.type(CostType.PROCESSOR.getType()).build());
log.info("{} result:{}", processor.getClass().getSimpleName(), JsonUtil.toString(queryCtx));
});
if (Objects.nonNull(parseResult.getQueryId()) && timeCostDOList.size() > 0) {
saveTimeCostInfo(timeCostDOList, queryReq.getQueryText(), parseResult.getQueryId(),
queryReq.getUser().getName(), queryReq.getChatId().longValue());
}
return parseResult;
}
private QueryContext buildQueryContext(QueryReq queryReq) {
Integer agentId = queryReq.getAgentId();
Agent agent = agentService.getAgent(agentId);
SemanticSchema semanticSchema = schemaService.getSemanticSchema();
Map<Long, ChatConfigRichResp> modelIdToChatRichConfig = configService.getModelIdToChatRichConfig();
Map<String, Plugin> nameToPlugin = pluginService.getNameToPlugin();
QueryContext queryCtx = QueryContext.builder()
.request(queryReq)
.semanticSchema(semanticSchema)
.candidateQueries(new ArrayList<>())
.mapInfo(new SchemaMapInfo())
.agent(agent)
.modelIdToChatRichConfig(modelIdToChatRichConfig)
.nameToPlugin(nameToPlugin)
.build();
return queryCtx;
}
@Override
@TimeCost
public QueryResult performExecution(ExecuteQueryReq queryReq) throws Exception {
ChatParseDO chatParseDO = chatService.getParseInfo(queryReq.getQueryId(), queryReq.getParseId());
ChatQueryDO chatQueryDO = chatService.getLastQuery(queryReq.getChatId());
List<StatisticsDO> timeCostDOList = new ArrayList<>();
SemanticParseInfo parseInfo = JsonUtil.toObject(chatParseDO.getParseInfo(), SemanticParseInfo.class);
SemanticQuery semanticQuery = QueryManager.createQuery(parseInfo.getQueryMode());
if (semanticQuery == null) {
return null;
}
semanticQuery.setParseInfo(parseInfo);
// in order to support multi-turn conversation, chat context is needed
ChatContext chatCtx = chatService.getOrCreateContext(queryReq.getChatId());
chatCtx.setAgentId(queryReq.getAgentId());
Long startTime = System.currentTimeMillis();
QueryResult queryResult = semanticQuery.execute(queryReq.getUser());
if (queryResult != null) {
timeCostDOList.add(StatisticsDO.builder().cost((int) (System.currentTimeMillis() - startTime))
.interfaceName(semanticQuery.getClass().getSimpleName()).type(CostType.QUERY.getType()).build());
queryResult.setQueryTimeCost(timeCostDOList.get(0).getCost().longValue());
saveTimeCostInfo(timeCostDOList, queryReq.getQueryText(), queryReq.getQueryId(),
queryReq.getUser().getName(), queryReq.getChatId().longValue());
queryResult.setChatContext(parseInfo);
// update chat context after a successful semantic query
if (QueryState.SUCCESS.equals(queryResult.getQueryState())) {
chatCtx.setParseInfo(parseInfo);
chatService.updateContext(chatCtx);
saveSolvedQuery(queryReq, parseInfo, chatQueryDO, queryResult);
}
chatCtx.setQueryText(queryReq.getQueryText());
chatCtx.setUser(queryReq.getUser().getName());
for (ExecuteResultProcessor executeResultProcessor : executeProcessors) {
executeResultProcessor.process(queryResult, parseInfo, queryReq);
}
chatService.updateQuery(queryReq.getQueryId(), queryReq.getParseId(), queryResult, chatCtx);
} else {
chatService.deleteChatQuery(queryReq.getQueryId());
}
return queryResult;
}
/**
* save time cost data
*
* @param timeCostDOList
* @param queryText
* @param queryId
* @param userName
* @param chatId
*/
private void saveTimeCostInfo(List<StatisticsDO> timeCostDOList,
String queryText, Long queryId,
String userName, Long chatId) {
List<StatisticsDO> list = timeCostDOList.stream()
.filter(o -> o.getCost() > timeThreshold).collect(Collectors.toList());
list.forEach(o -> {
o.setQueryText(queryText);
o.setQuestionId(queryId);
o.setUserName(userName);
o.setChatId(chatId);
o.setCreateTime(new java.util.Date());
});
if (list.size() > 0) {
log.info("filterStatistics size:{},data:{}", list.size(), JsonUtil.toString(list));
statisticsService.batchSaveStatistics(list);
}
}
private void saveSolvedQuery(ExecuteQueryReq queryReq, SemanticParseInfo parseInfo,
ChatQueryDO chatQueryDO, QueryResult queryResult) {
if (queryResult.getResponse() == null && CollectionUtils.isEmpty(queryResult.getQueryResults())) {
return;
}
similarQueryManager.saveSimilarQuery(SimilarQueryReq.builder().parseId(queryReq.getParseId())
.queryId(queryReq.getQueryId())
.agentId(chatQueryDO.getAgentId())
.modelId(parseInfo.getModelClusterKey())
.queryText(queryReq.getQueryText()).build());
}
@Override
public SemanticParseInfo queryContext(QueryReq queryCtx) {
ChatContext context = chatService.getOrCreateContext(queryCtx.getChatId());
return context.getParseInfo();
}
//mainly used for executing after revising filters,for example:"fans_cnt>=100000"->"fans_cnt>500000",
//"style='流行'"->"style in ['流行','爱国']"
@Override
@TimeCost
public QueryResult executeDirectQuery(QueryDataReq queryData, User user) throws SqlParseException {
ChatParseDO chatParseDO = chatService.getParseInfo(queryData.getQueryId(),
queryData.getParseId());
SemanticParseInfo parseInfo = getSemanticParseInfo(queryData, chatParseDO);
SemanticSchema semanticSchema = schemaService.getSemanticSchema();
SemanticQuery semanticQuery = QueryManager.createQuery(parseInfo.getQueryMode());
semanticQuery.setParseInfo(parseInfo);
List<String> fields = new ArrayList<>();
if (Objects.nonNull(parseInfo.getSqlInfo())
&& StringUtils.isNotBlank(parseInfo.getSqlInfo().getCorrectS2SQL())) {
String correctorSql = parseInfo.getSqlInfo().getCorrectS2SQL();
fields = SqlParserSelectHelper.getAllFields(correctorSql);
}
if (LLMSqlQuery.QUERY_MODE.equalsIgnoreCase(parseInfo.getQueryMode())
&& checkMetricReplace(fields, queryData.getMetrics())) {
//replace metrics
log.info("llm begin replace metrics!");
SchemaElement metricToReplace = queryData.getMetrics().iterator().next();
replaceMetrics(parseInfo, metricToReplace);
} else if (LLMSqlQuery.QUERY_MODE.equalsIgnoreCase(parseInfo.getQueryMode())) {
log.info("llm begin revise filters!");
String correctorSql = reviseCorrectS2SQL(queryData, parseInfo);
parseInfo.getSqlInfo().setCorrectS2SQL(correctorSql);
semanticQuery.setParseInfo(parseInfo);
String explainSql = semanticQuery.explain(user);
if (StringUtils.isNotBlank(explainSql)) {
parseInfo.getSqlInfo().setQuerySQL(explainSql);
}
} else {
log.info("rule begin replace metrics and revise filters!");
//remove unvalid filters
validFilter(semanticQuery.getParseInfo().getDimensionFilters());
validFilter(semanticQuery.getParseInfo().getMetricFilters());
//init s2sql
semanticQuery.initS2Sql(semanticSchema, user);
QueryReq queryReq = new QueryReq();
queryReq.setQueryFilters(new QueryFilters());
queryReq.setUser(user);
}
QueryResult queryResult = semanticQuery.execute(user);
queryResult.setChatContext(semanticQuery.getParseInfo());
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
EntityInfo entityInfo = semanticService.getEntityInfo(parseInfo, user);
queryResult.setEntityInfo(entityInfo);
return queryResult;
}
private boolean checkMetricReplace(List<String> oriFields, Set<SchemaElement> metrics) {
if (CollectionUtils.isEmpty(oriFields)) {
return false;
}
if (CollectionUtils.isEmpty(metrics)) {
return false;
}
List<String> metricNames = metrics.stream().map(SchemaElement::getName).collect(Collectors.toList());
return !oriFields.containsAll(metricNames);
}
public String reviseCorrectS2SQL(QueryDataReq queryData, SemanticParseInfo parseInfo) {
Map<String, Map<String, String>> filedNameToValueMap = new HashMap<>();
Map<String, Map<String, String>> havingFiledNameToValueMap = new HashMap<>();
String correctorSql = parseInfo.getSqlInfo().getCorrectS2SQL();
log.info("correctorSql before replacing:{}", correctorSql);
// get where filter and having filter
List<FieldExpression> whereExpressionList = SqlParserSelectHelper.getWhereExpressions(correctorSql);
List<FieldExpression> havingExpressionList = SqlParserSelectHelper.getHavingExpressions(correctorSql);
List<Expression> addWhereConditions = new ArrayList<>();
List<Expression> addHavingConditions = new ArrayList<>();
Set<String> removeWhereFieldNames = new HashSet<>();
Set<String> removeHavingFieldNames = new HashSet<>();
// replace where filter
updateFilters(whereExpressionList, queryData.getDimensionFilters(),
parseInfo.getDimensionFilters(), addWhereConditions, removeWhereFieldNames);
updateDateInfo(queryData, parseInfo, filedNameToValueMap,
whereExpressionList, addWhereConditions, removeWhereFieldNames);
correctorSql = SqlParserReplaceHelper.replaceValue(correctorSql, filedNameToValueMap);
correctorSql = SqlParserRemoveHelper.removeWhereCondition(correctorSql, removeWhereFieldNames);
// replace having filter
updateFilters(havingExpressionList, queryData.getDimensionFilters(),
parseInfo.getDimensionFilters(), addHavingConditions, removeHavingFieldNames);
correctorSql = SqlParserReplaceHelper.replaceHavingValue(correctorSql, havingFiledNameToValueMap);
correctorSql = SqlParserRemoveHelper.removeHavingCondition(correctorSql, removeHavingFieldNames);
correctorSql = SqlParserAddHelper.addWhere(correctorSql, addWhereConditions);
correctorSql = SqlParserAddHelper.addHaving(correctorSql, addHavingConditions);
log.info("correctorSql after replacing:{}", correctorSql);
return correctorSql;
}
private void replaceMetrics(SemanticParseInfo parseInfo, SchemaElement metric) {
List<String> oriMetrics = parseInfo.getMetrics().stream()
.map(SchemaElement::getName).collect(Collectors.toList());
String correctorSql = parseInfo.getSqlInfo().getCorrectS2SQL();
log.info("before replaceMetrics:{}", correctorSql);
log.info("filteredMetrics:{},metrics:{}", oriMetrics, metric);
Map<String, Pair<String, String>> fieldMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(oriMetrics) && !oriMetrics.contains(metric.getName())) {
fieldMap.put(oriMetrics.get(0), Pair.of(metric.getName(), metric.getDefaultAgg()));
correctorSql = SqlParserReplaceHelper.replaceAggFields(correctorSql, fieldMap);
}
log.info("after replaceMetrics:{}", correctorSql);
parseInfo.getSqlInfo().setCorrectS2SQL(correctorSql);
}
@Override
public EntityInfo getEntityInfo(Long queryId, Integer parseId, User user) {
ChatParseDO chatParseDO = chatService.getParseInfo(queryId, parseId);
SemanticParseInfo parseInfo = JsonUtil.toObject(chatParseDO.getParseInfo(), SemanticParseInfo.class);
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
return semanticService.getEntityInfo(parseInfo, user);
}
private void updateDateInfo(QueryDataReq queryData, SemanticParseInfo parseInfo,
Map<String, Map<String, String>> filedNameToValueMap,
List<FieldExpression> fieldExpressionList,
List<Expression> addConditions,
Set<String> removeFieldNames) {
if (Objects.isNull(queryData.getDateInfo())) {
return;
}
Map<String, String> map = new HashMap<>();
String dateField = TimeDimensionEnum.DAY.getChName();
if (queryData.getDateInfo().getUnit() > 1) {
queryData.getDateInfo().setStartDate(DateUtils.getBeforeDate(queryData.getDateInfo().getUnit() + 1));
queryData.getDateInfo().setEndDate(DateUtils.getBeforeDate(1));
}
// startDate equals to endDate
if (queryData.getDateInfo().getStartDate().equals(queryData.getDateInfo().getEndDate())) {
for (FieldExpression fieldExpression : fieldExpressionList) {
if (TimeDimensionEnum.DAY.getChName().equals(fieldExpression.getFieldName())) {
//sql where condition exists 'equals' operator about date,just replace
if (fieldExpression.getOperator().equals(FilterOperatorEnum.EQUALS)) {
dateField = fieldExpression.getFieldName();
map.put(fieldExpression.getFieldValue().toString(),
queryData.getDateInfo().getStartDate());
filedNameToValueMap.put(dateField, map);
} else {
// first remove,then add
removeFieldNames.add(TimeDimensionEnum.DAY.getChName());
EqualsTo equalsTo = new EqualsTo();
Column column = new Column(TimeDimensionEnum.DAY.getChName());
StringValue stringValue = new StringValue(queryData.getDateInfo().getStartDate());
equalsTo.setLeftExpression(column);
equalsTo.setRightExpression(stringValue);
addConditions.add(equalsTo);
}
break;
}
}
} else {
for (FieldExpression fieldExpression : fieldExpressionList) {
if (TimeDimensionEnum.DAY.getChName().equals(fieldExpression.getFieldName())) {
dateField = fieldExpression.getFieldName();
//just replace
if (FilterOperatorEnum.GREATER_THAN_EQUALS.getValue().equals(fieldExpression.getOperator())
|| FilterOperatorEnum.GREATER_THAN.getValue().equals(fieldExpression.getOperator())) {
map.put(fieldExpression.getFieldValue().toString(),
queryData.getDateInfo().getStartDate());
}
if (FilterOperatorEnum.MINOR_THAN_EQUALS.getValue().equals(fieldExpression.getOperator())
|| FilterOperatorEnum.MINOR_THAN.getValue().equals(fieldExpression.getOperator())) {
map.put(fieldExpression.getFieldValue().toString(),
queryData.getDateInfo().getEndDate());
}
filedNameToValueMap.put(dateField, map);
// first remove,then add
if (FilterOperatorEnum.EQUALS.getValue().equals(fieldExpression.getOperator())) {
removeFieldNames.add(TimeDimensionEnum.DAY.getChName());
GreaterThanEquals greaterThanEquals = new GreaterThanEquals();
addTimeFilters(queryData.getDateInfo().getStartDate(), greaterThanEquals, addConditions);
MinorThanEquals minorThanEquals = new MinorThanEquals();
addTimeFilters(queryData.getDateInfo().getEndDate(), minorThanEquals, addConditions);
}
}
}
}
parseInfo.setDateInfo(queryData.getDateInfo());
}
private <T extends ComparisonOperator> void addTimeFilters(String date,
T comparisonExpression,
List<Expression> addConditions) {
Column column = new Column(TimeDimensionEnum.DAY.getChName());
StringValue stringValue = new StringValue(date);
comparisonExpression.setLeftExpression(column);
comparisonExpression.setRightExpression(stringValue);
addConditions.add(comparisonExpression);
}
private void updateFilters(List<FieldExpression> fieldExpressionList,
Set<QueryFilter> metricFilters,
Set<QueryFilter> contextMetricFilters,
List<Expression> addConditions,
Set<String> removeFieldNames) {
if (CollectionUtils.isEmpty(metricFilters)) {
return;
}
for (QueryFilter dslQueryFilter : metricFilters) {
for (FieldExpression fieldExpression : fieldExpressionList) {
if (fieldExpression.getFieldName() != null
&& fieldExpression.getFieldName().contains(dslQueryFilter.getName())) {
removeFieldNames.add(dslQueryFilter.getName());
if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.EQUALS)) {
EqualsTo equalsTo = new EqualsTo();
addWhereFilters(dslQueryFilter, equalsTo, contextMetricFilters, addConditions);
} else if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.GREATER_THAN_EQUALS)) {
GreaterThanEquals greaterThanEquals = new GreaterThanEquals();
addWhereFilters(dslQueryFilter, greaterThanEquals, contextMetricFilters, addConditions);
} else if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.GREATER_THAN)) {
GreaterThan greaterThan = new GreaterThan();
addWhereFilters(dslQueryFilter, greaterThan, contextMetricFilters, addConditions);
} else if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.MINOR_THAN_EQUALS)) {
MinorThanEquals minorThanEquals = new MinorThanEquals();
addWhereFilters(dslQueryFilter, minorThanEquals, contextMetricFilters, addConditions);
} else if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.MINOR_THAN)) {
MinorThan minorThan = new MinorThan();
addWhereFilters(dslQueryFilter, minorThan, contextMetricFilters, addConditions);
} else if (dslQueryFilter.getOperator().equals(FilterOperatorEnum.IN)) {
InExpression inExpression = new InExpression();
addWhereInFilters(dslQueryFilter, inExpression, contextMetricFilters, addConditions);
}
break;
}
}
}
}
// add in condition to sql where condition
private void addWhereInFilters(QueryFilter dslQueryFilter,
InExpression inExpression,
Set<QueryFilter> contextMetricFilters,
List<Expression> addConditions) {
Column column = new Column(dslQueryFilter.getName());
ExpressionList expressionList = new ExpressionList();
List<Expression> expressions = new ArrayList<>();
List<String> valueList = JsonUtil.toList(
JsonUtil.toString(dslQueryFilter.getValue()), String.class);
if (CollectionUtils.isEmpty(valueList)) {
return;
}
valueList.stream().forEach(o -> {
StringValue stringValue = new StringValue(o);
expressions.add(stringValue);
});
expressionList.setExpressions(expressions);
inExpression.setLeftExpression(column);
inExpression.setRightItemsList(expressionList);
addConditions.add(inExpression);
contextMetricFilters.stream().forEach(o -> {
if (o.getName().equals(dslQueryFilter.getName())) {
o.setValue(dslQueryFilter.getValue());
o.setOperator(dslQueryFilter.getOperator());
}
});
}
// add where filter
private <T extends ComparisonOperator> void addWhereFilters(QueryFilter dslQueryFilter,
T comparisonExpression,
Set<QueryFilter> contextMetricFilters,
List<Expression> addConditions) {
String columnName = dslQueryFilter.getName();
if (StringUtils.isNotBlank(dslQueryFilter.getFunction())) {
columnName = dslQueryFilter.getFunction() + "(" + dslQueryFilter.getName() + ")";
}
if (Objects.isNull(dslQueryFilter.getValue())) {
return;
}
Column column = new Column(columnName);
comparisonExpression.setLeftExpression(column);
if (StringUtils.isNumeric(dslQueryFilter.getValue().toString())) {
LongValue longValue = new LongValue(Long.parseLong(dslQueryFilter.getValue().toString()));
comparisonExpression.setRightExpression(longValue);
} else {
StringValue stringValue = new StringValue(dslQueryFilter.getValue().toString());
comparisonExpression.setRightExpression(stringValue);
}
addConditions.add(comparisonExpression);
contextMetricFilters.stream().forEach(o -> {
if (o.getName().equals(dslQueryFilter.getName())) {
o.setValue(dslQueryFilter.getValue());
o.setOperator(dslQueryFilter.getOperator());
}
});
}
private SemanticParseInfo getSemanticParseInfo(QueryDataReq queryData, ChatParseDO chatParseDO) {
SemanticParseInfo parseInfo = JsonUtil.toObject(chatParseDO.getParseInfo(), SemanticParseInfo.class);
if (LLMSqlQuery.QUERY_MODE.equals(parseInfo.getQueryMode())) {
return parseInfo;
}
if (CollectionUtils.isNotEmpty(queryData.getDimensions())) {
parseInfo.setDimensions(queryData.getDimensions());
}
if (CollectionUtils.isNotEmpty(queryData.getMetrics())) {
parseInfo.setMetrics(queryData.getMetrics());
}
if (CollectionUtils.isNotEmpty(queryData.getDimensionFilters())) {
parseInfo.setDimensionFilters(queryData.getDimensionFilters());
}
if (CollectionUtils.isNotEmpty(queryData.getMetricFilters())) {
parseInfo.setMetricFilters(queryData.getMetricFilters());
}
if (Objects.nonNull(queryData.getDateInfo())) {
parseInfo.setDateInfo(queryData.getDateInfo());
}
return parseInfo;
}
private void validFilter(Set<QueryFilter> filters) {
for (QueryFilter queryFilter : filters) {
if (Objects.isNull(queryFilter.getValue())) {
filters.remove(queryFilter);
}
if (queryFilter.getOperator().equals(FilterOperatorEnum.IN) && CollectionUtils.isEmpty(
JsonUtil.toList(JsonUtil.toString(queryFilter.getValue()), String.class))) {
filters.remove(queryFilter);
}
}
}
@Override
public Object queryDimensionValue(DimensionValueReq dimensionValueReq, User user) throws Exception {
QueryResultWithSchemaResp queryResultWithSchemaResp = new QueryResultWithSchemaResp();
SemanticService semanticService = ContextUtils.getBean(SemanticService.class);
SemanticSchema semanticSchema = semanticService.getSemanticSchema();
SchemaElement schemaElement = semanticSchema.getDimensions(dimensionValueReq.getElementID());
Set<Long> detectModelIds = new HashSet<>();
detectModelIds.add(schemaElement.getModel());
dimensionValueReq.setModelId(schemaElement.getModel());
List<String> dimensionValues = getDimensionValues(dimensionValueReq, detectModelIds);
// if the search results is null,search dimensionValue from database
if (CollectionUtils.isEmpty(dimensionValues)) {
queryResultWithSchemaResp = queryDatabase(dimensionValueReq, user);
return queryResultWithSchemaResp;
}
List<QueryColumn> columns = new ArrayList<>();
QueryColumn queryColumn = new QueryColumn();
queryColumn.setNameEn(dimensionValueReq.getBizName());
queryColumn.setShowType("CATEGORY");
queryColumn.setAuthorized(true);
queryColumn.setType("CHAR");
columns.add(queryColumn);
List<Map<String, Object>> resultList = new ArrayList<>();
dimensionValues.stream().forEach(o -> {
Map<String, Object> map = new HashMap<>();
map.put(dimensionValueReq.getBizName(), o);
resultList.add(map);
});
queryResultWithSchemaResp.setColumns(columns);
queryResultWithSchemaResp.setResultList(resultList);
return queryResultWithSchemaResp;
}
private List<String> getDimensionValues(DimensionValueReq dimensionValueReq, Set<Long> detectModelIds) {
//if value is null ,then search from NATURE_TO_VALUES
if (StringUtils.isBlank(dimensionValueReq.getValue())) {
return SearchService.getDimensionValue(dimensionValueReq);
}
//search from prefixSearch
List<HanlpMapResult> hanlpMapResultList = SearchService.prefixSearch(dimensionValueReq.getValue(),
2000, dimensionValueReq.getAgentId(), detectModelIds);
HanlpHelper.transLetterOriginal(hanlpMapResultList);
return hanlpMapResultList.stream()
.filter(o -> {
for (String nature : o.getNatures()) {
Long elementID = NatureHelper.getElementID(nature);
if (dimensionValueReq.getElementID().equals(elementID)) {
return true;
}
}
return false;
})
.map(mapResult -> mapResult.getName())
.collect(Collectors.toList());
}
private QueryResultWithSchemaResp queryDatabase(DimensionValueReq dimensionValueReq, User user) {
QueryStructReq queryStructReq = new QueryStructReq();
DateConf dateConf = new DateConf();
dateConf.setDateMode(DateConf.DateMode.RECENT);
dateConf.setUnit(1);
dateConf.setPeriod("DAY");
queryStructReq.setDateInfo(dateConf);
queryStructReq.setLimit(20L);
queryStructReq.setModelId(dimensionValueReq.getModelId());
queryStructReq.setQueryType(QueryType.ID);
List<String> groups = new ArrayList<>();
groups.add(dimensionValueReq.getBizName());
queryStructReq.setGroups(groups);
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
return semanticInterpreter.queryByStruct(queryStructReq, user);
}
}

View File

@@ -0,0 +1,142 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.RelatedSchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigFilter;
import com.tencent.supersonic.chat.api.pojo.request.RecommendReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.api.pojo.response.RecommendQuestionResp;
import com.tencent.supersonic.chat.api.pojo.response.RecommendResp;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.chat.server.service.RecommendService;
import com.tencent.supersonic.chat.server.service.SemanticService;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
/***
* Recommend Service impl
*/
@Service
@Slf4j
public class RecommendServiceImpl implements RecommendService {
@Autowired
private ConfigService configService;
@Autowired
private SemanticService semanticService;
@Override
public RecommendResp recommend(RecommendReq recommendReq, Long limit) {
if (Objects.isNull(limit) || limit <= 0) {
limit = Long.MAX_VALUE;
}
log.debug("limit:{}", limit);
Long modelId = recommendReq.getModelId();
if (Objects.isNull(modelId)) {
return new RecommendResp();
}
ModelSchema modelSchema = semanticService.getModelSchema(modelId);
if (Objects.isNull(modelSchema)) {
return new RecommendResp();
}
List<Long> drillDownDimensions = Lists.newArrayList();
Set<SchemaElement> metricElements = modelSchema.getMetrics();
if (recommendReq.getMetricId() != null && !CollectionUtils.isEmpty(metricElements)) {
Optional<SchemaElement> metric = metricElements.stream().filter(schemaElement ->
recommendReq.getMetricId().equals(schemaElement.getId())
&& !CollectionUtils.isEmpty(schemaElement.getRelatedSchemaElements()))
.findFirst();
if (metric.isPresent()) {
drillDownDimensions = metric.get().getRelatedSchemaElements().stream()
.map(RelatedSchemaElement::getDimensionId).collect(Collectors.toList());
}
}
final List<Long> drillDownDimensionsFinal = drillDownDimensions;
List<SchemaElement> dimensions = modelSchema.getDimensions().stream()
.filter(dim -> {
if (Objects.isNull(dim)) {
return false;
}
if (!CollectionUtils.isEmpty(drillDownDimensionsFinal)) {
return drillDownDimensionsFinal.contains(dim.getId());
} else {
return Objects.nonNull(dim.getUseCnt());
}
})
.sorted(Comparator.comparing(SchemaElement::getUseCnt).reversed())
.limit(limit)
.map(dimSchemaDesc -> {
SchemaElement item = new SchemaElement();
item.setModel(modelId);
item.setName(dimSchemaDesc.getName());
item.setBizName(dimSchemaDesc.getBizName());
item.setId(dimSchemaDesc.getId());
item.setAlias(dimSchemaDesc.getAlias());
return item;
}).collect(Collectors.toList());
List<SchemaElement> metrics = modelSchema.getMetrics().stream()
.filter(metric -> Objects.nonNull(metric) && Objects.nonNull(metric.getUseCnt()))
.sorted(Comparator.comparing(SchemaElement::getUseCnt).reversed())
.limit(limit)
.map(metricSchemaDesc -> {
SchemaElement item = new SchemaElement();
item.setModel(modelId);
item.setName(metricSchemaDesc.getName());
item.setBizName(metricSchemaDesc.getBizName());
item.setId(metricSchemaDesc.getId());
item.setAlias(metricSchemaDesc.getAlias());
return item;
}).collect(Collectors.toList());
RecommendResp response = new RecommendResp();
response.setDimensions(dimensions);
response.setMetrics(metrics);
return response;
}
@Override
public RecommendResp recommendMetricMode(RecommendReq recommendReq, Long limit) {
return recommend(recommendReq, limit);
}
@Override
public List<RecommendQuestionResp> recommendQuestion(Long modelId) {
List<RecommendQuestionResp> recommendQuestions = new ArrayList<>();
ChatConfigFilter chatConfigFilter = new ChatConfigFilter();
chatConfigFilter.setModelId(modelId);
List<ChatConfigResp> chatConfigRespList = configService.search(chatConfigFilter, null);
if (!CollectionUtils.isEmpty(chatConfigRespList)) {
chatConfigRespList.stream().forEach(chatConfigResp -> {
if (Objects.nonNull(chatConfigResp)
&& !CollectionUtils.isEmpty(chatConfigResp.getRecommendedQuestions())) {
recommendQuestions.add(
new RecommendQuestionResp(chatConfigResp.getModelId(),
chatConfigResp.getRecommendedQuestions()));
}
});
return recommendQuestions;
}
return new ArrayList<>();
}
private List<SchemaElement> filterBlackItem(List<SchemaElement> itemList, List<Long> blackDimIdList) {
if (CollectionUtils.isEmpty(blackDimIdList) || CollectionUtils.isEmpty(itemList)) {
return itemList;
}
return itemList.stream().filter(dim -> !blackDimIdList.contains(dim.getId())).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,46 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SchemaService {
public static final String ALL_CACHE = "all";
private static final Integer META_CACHE_TIME = 30;
private SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
private LoadingCache<String, SemanticSchema> cache = CacheBuilder.newBuilder()
.expireAfterWrite(META_CACHE_TIME, TimeUnit.SECONDS)
.build(
new CacheLoader<String, SemanticSchema>() {
@Override
public SemanticSchema load(String key) {
log.info("load getDomainSchemaInfo cache [{}]", key);
return new SemanticSchema(semanticInterpreter.getModelSchema());
}
}
);
public ModelSchema getModelSchema(Long id) {
return semanticInterpreter.getModelSchema(id, true);
}
public SemanticSchema getSemanticSchema() {
return cache.getUnchecked(ALL_CACHE);
}
public LoadingCache<String, SemanticSchema> getCache() {
return cache;
}
}

View File

@@ -0,0 +1,357 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.github.benmanes.caffeine.cache.Cache;
import com.google.common.collect.Lists;
import com.hankcs.hanlp.seg.common.Term;
import com.tencent.supersonic.chat.core.pojo.QueryContext;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.api.pojo.request.ItemNameVisibilityInfo;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
import com.tencent.supersonic.chat.api.pojo.request.QueryFilters;
import com.tencent.supersonic.chat.api.pojo.request.QueryReq;
import com.tencent.supersonic.chat.api.pojo.response.SearchResult;
import com.tencent.supersonic.chat.core.agent.Agent;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import com.tencent.supersonic.chat.core.knowledge.HanlpMapResult;
import com.tencent.supersonic.chat.core.knowledge.ModelInfoStat;
import com.tencent.supersonic.chat.core.mapper.MapperHelper;
import com.tencent.supersonic.chat.core.mapper.MatchText;
import com.tencent.supersonic.chat.core.mapper.ModelWithSemanticType;
import com.tencent.supersonic.chat.core.mapper.SearchMatchStrategy;
import com.tencent.supersonic.chat.core.utils.HanlpHelper;
import com.tencent.supersonic.chat.core.utils.NatureHelper;
import com.tencent.supersonic.chat.server.service.AgentService;
import com.tencent.supersonic.chat.server.service.ChatService;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.chat.server.service.SearchService;
import com.tencent.supersonic.common.pojo.enums.DictWordType;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
/**
* search service impl
*/
@Service
@Slf4j
public class SearchServiceImpl implements SearchService {
private static final int RESULT_SIZE = 10;
@Autowired
private SchemaService schemaService;
@Autowired
private ChatService chatService;
@Autowired
private SearchMatchStrategy searchMatchStrategy;
@Autowired
private AgentService agentService;
@Autowired
@Qualifier("searchCaffeineCache")
private Cache<Long, Object> caffeineCache;
@Autowired
private ConfigService configService;
@Override
public List<SearchResult> search(QueryReq queryReq) {
// 1. check search enable
Integer agentId = queryReq.getAgentId();
if (agentId != null) {
Agent agent = agentService.getAgent(agentId);
if (!agent.enableSearch()) {
return Lists.newArrayList();
}
}
String queryText = queryReq.getQueryText();
// 2.get meta info
SemanticSchema semanticSchemaDb = schemaService.getSemanticSchema();
List<SchemaElement> metricsDb = semanticSchemaDb.getMetrics();
final Map<Long, String> modelToName = semanticSchemaDb.getModelIdToName();
// 3.detect by segment
List<Term> originals = HanlpHelper.getTerms(queryText);
log.info("hanlp parse result: {}", originals);
MapperHelper mapperHelper = ContextUtils.getBean(MapperHelper.class);
Set<Long> detectModelIds = mapperHelper.getModelIds(queryReq, agentService.getAgent(agentId));
QueryContext queryContext = new QueryContext();
queryContext.setRequest(queryReq);
Map<MatchText, List<HanlpMapResult>> regTextMap =
searchMatchStrategy.match(queryContext, originals, detectModelIds);
regTextMap.entrySet().stream().forEach(m -> HanlpHelper.transLetterOriginal(m.getValue()));
// 4.get the most matching data
Optional<Entry<MatchText, List<HanlpMapResult>>> mostSimilarSearchResult = regTextMap.entrySet()
.stream()
.filter(entry -> CollectionUtils.isNotEmpty(entry.getValue()))
.reduce((entry1, entry2) ->
entry1.getKey().getDetectSegment().length() >= entry2.getKey().getDetectSegment().length()
? entry1 : entry2);
// 5.optimize the results after the query
if (!mostSimilarSearchResult.isPresent()) {
return Lists.newArrayList();
}
Map.Entry<MatchText, List<HanlpMapResult>> searchTextEntry = mostSimilarSearchResult.get();
log.info("searchTextEntry:{},queryReq:{}", searchTextEntry, queryReq);
Set<SearchResult> searchResults = new LinkedHashSet();
ModelInfoStat modelStat = NatureHelper.getModelStat(originals);
List<Long> possibleModels = getPossibleModels(queryReq, originals, modelStat, queryReq.getModelId());
// 5.1 priority dimension metric
boolean existMetricAndDimension = searchMetricAndDimension(new HashSet<>(possibleModels), modelToName,
searchTextEntry, searchResults);
// 5.2 process based on dimension values
MatchText matchText = searchTextEntry.getKey();
Map<String, String> natureToNameMap = getNatureToNameMap(searchTextEntry, new HashSet<>(possibleModels));
log.debug("possibleModels:{},natureToNameMap:{}", possibleModels, natureToNameMap);
for (Map.Entry<String, String> natureToNameEntry : natureToNameMap.entrySet()) {
Set<SearchResult> searchResultSet = searchDimensionValue(metricsDb, modelToName,
modelStat.getMetricModelCount(), existMetricAndDimension,
matchText, natureToNameMap, natureToNameEntry, queryReq.getQueryFilters());
searchResults.addAll(searchResultSet);
}
return searchResults.stream().limit(RESULT_SIZE).collect(Collectors.toList());
}
private List<Long> getPossibleModels(QueryReq queryCtx, List<Term> originals,
ModelInfoStat modelStat, Long webModelId) {
if (Objects.nonNull(webModelId) && webModelId > 0) {
List<Long> result = new ArrayList<>();
result.add(webModelId);
return result;
}
List<Long> possibleModels = NatureHelper.selectPossibleModels(originals);
Set<Long> contextModel = chatService.getContextModel(queryCtx.getChatId());
log.debug("possibleModels:{},modelStat:{},contextModel:{}", possibleModels, modelStat, contextModel);
// If nothing is recognized or only metric are present, then add the contextModel.
if (nothingOrOnlyMetric(modelStat)) {
return contextModel.stream().filter(modelId -> modelId > 0).collect(Collectors.toList());
}
return possibleModels;
}
private boolean nothingOrOnlyMetric(ModelInfoStat modelStat) {
return modelStat.getMetricModelCount() >= 0 && modelStat.getDimensionModelCount() <= 0
&& modelStat.getDimensionValueModelCount() <= 0 && modelStat.getModelCount() <= 0;
}
private boolean effectiveModel(Long contextModel) {
return Objects.nonNull(contextModel) && contextModel > 0;
}
private Set<SearchResult> searchDimensionValue(List<SchemaElement> metricsDb,
Map<Long, String> modelToName,
long metricModelCount,
boolean existMetricAndDimension,
MatchText matchText,
Map<String, String> natureToNameMap,
Map.Entry<String, String> natureToNameEntry,
QueryFilters queryFilters) {
Set<SearchResult> searchResults = new LinkedHashSet();
String nature = natureToNameEntry.getKey();
String wordName = natureToNameEntry.getValue();
Long modelId = NatureHelper.getModelId(nature);
SchemaElementType schemaElementType = NatureHelper.convertToElementType(nature);
if (SchemaElementType.ENTITY.equals(schemaElementType)) {
return searchResults;
}
// If there are no metric/dimension, complete the metric information
SearchResult searchResult = SearchResult.builder()
.modelId(modelId)
.modelName(modelToName.get(modelId))
.recommend(matchText.getRegText() + wordName)
.schemaElementType(schemaElementType)
.subRecommend(wordName)
.build();
ItemNameVisibilityInfo visibility = (ItemNameVisibilityInfo) caffeineCache.getIfPresent(modelId);
if (visibility == null) {
visibility = configService.getVisibilityByModelId(modelId);
caffeineCache.put(modelId, visibility);
}
if (visibility.getBlackMetricNameList().contains(searchResult.getRecommend())
|| visibility.getBlackDimNameList().contains(searchResult.getRecommend())) {
return searchResults;
}
if (metricModelCount <= 0 && !existMetricAndDimension) {
if (filterByQueryFilter(wordName, queryFilters)) {
return searchResults;
}
searchResults.add(searchResult);
int metricSize = getMetricSize(natureToNameMap);
//invisibility to filter metrics
List<String> blackMetricNameList = visibility.getBlackMetricNameList();
List<String> metrics = filerMetricsByModel(metricsDb, modelId, metricSize * 3)
.stream().filter(o -> !blackMetricNameList.contains(o))
.limit(metricSize).collect(Collectors.toList());
for (String metric : metrics) {
SearchResult result = SearchResult.builder()
.modelId(modelId)
.modelName(modelToName.get(modelId))
.recommend(matchText.getRegText() + wordName + DictWordType.SPACE + metric)
.subRecommend(wordName + DictWordType.SPACE + metric)
.isComplete(false)
.build();
searchResults.add(result);
}
} else {
searchResults.add(searchResult);
}
return searchResults;
}
private int getMetricSize(Map<String, String> natureToNameMap) {
int metricSize = RESULT_SIZE / (natureToNameMap.entrySet().size());
if (metricSize <= 1) {
metricSize = 1;
}
return metricSize;
}
private boolean filterByQueryFilter(String wordName, QueryFilters queryFilters) {
if (queryFilters == null || CollectionUtils.isEmpty(queryFilters.getFilters())) {
return false;
}
List<QueryFilter> filters = queryFilters.getFilters();
for (QueryFilter filter : filters) {
if (wordName.equalsIgnoreCase(String.valueOf(filter.getValue()))) {
return false;
}
}
return true;
}
protected List<String> filerMetricsByModel(List<SchemaElement> metricsDb, Long model, int metricSize) {
if (CollectionUtils.isEmpty(metricsDb)) {
return Lists.newArrayList();
}
return metricsDb.stream()
.filter(mapDO -> Objects.nonNull(mapDO) && model.equals(mapDO.getModel()))
.sorted(Comparator.comparing(SchemaElement::getUseCnt).reversed())
.flatMap(entry -> {
List<String> result = new ArrayList<>();
result.add(entry.getName());
return result.stream();
})
.limit(metricSize).collect(Collectors.toList());
}
/***
* convert nature to name
* @param recommendTextListEntry
* @return
*/
private Map<String, String> getNatureToNameMap(Map.Entry<MatchText, List<HanlpMapResult>> recommendTextListEntry,
Set<Long> possibleModels) {
List<HanlpMapResult> recommendValues = recommendTextListEntry.getValue();
return recommendValues.stream()
.flatMap(entry -> entry.getNatures().stream()
.filter(nature -> {
if (CollectionUtils.isEmpty(possibleModels)) {
return true;
}
Long model = NatureHelper.getModelId(nature);
return possibleModels.contains(model);
})
.map(nature -> {
DictWord posDO = new DictWord();
posDO.setWord(entry.getName());
posDO.setNature(nature);
return posDO;
})).sorted(Comparator.comparingInt(a -> a.getWord().length()))
.collect(Collectors.toMap(DictWord::getNature, DictWord::getWord, (value1, value2) -> value1,
LinkedHashMap::new));
}
private boolean searchMetricAndDimension(Set<Long> possibleModels, Map<Long, String> modelToName,
Map.Entry<MatchText, List<HanlpMapResult>> searchTextEntry, Set<SearchResult> searchResults) {
boolean existMetric = false;
log.info("searchMetricAndDimension searchTextEntry:{}", searchTextEntry);
MatchText matchText = searchTextEntry.getKey();
List<HanlpMapResult> hanlpMapResults = searchTextEntry.getValue();
for (HanlpMapResult hanlpMapResult : hanlpMapResults) {
List<ModelWithSemanticType> dimensionMetricClassIds = hanlpMapResult.getNatures().stream()
.map(nature -> new ModelWithSemanticType(NatureHelper.getModelId(nature),
NatureHelper.convertToElementType(nature)))
.filter(entry -> matchCondition(entry, possibleModels)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(dimensionMetricClassIds)) {
continue;
}
for (ModelWithSemanticType modelWithSemanticType : dimensionMetricClassIds) {
existMetric = true;
Long modelId = modelWithSemanticType.getModel();
SchemaElementType schemaElementType = modelWithSemanticType.getSchemaElementType();
SearchResult searchResult = SearchResult.builder()
.modelId(modelId)
.modelName(modelToName.get(modelId))
.recommend(matchText.getRegText() + hanlpMapResult.getName())
.subRecommend(hanlpMapResult.getName())
.schemaElementType(schemaElementType)
.build();
//visibility to filter metrics
ItemNameVisibilityInfo visibility = (ItemNameVisibilityInfo) caffeineCache.getIfPresent(modelId);
if (visibility == null) {
visibility = configService.getVisibilityByModelId(modelId);
caffeineCache.put(modelId, visibility);
}
if (!visibility.getBlackMetricNameList().contains(hanlpMapResult.getName())
&& !visibility.getBlackDimNameList().contains(hanlpMapResult.getName())) {
searchResults.add(searchResult);
}
}
log.info("parseResult:{},dimensionMetricClassIds:{},possibleModels:{}", hanlpMapResult,
dimensionMetricClassIds, possibleModels);
}
log.info("searchMetricAndDimension searchResults:{}", searchResults);
return existMetric;
}
private boolean matchCondition(ModelWithSemanticType entry, Set<Long> possibleModels) {
if (!(SchemaElementType.METRIC.equals(entry.getSchemaElementType()) || SchemaElementType.DIMENSION.equals(
entry.getSchemaElementType()))) {
return false;
}
if (CollectionUtils.isEmpty(possibleModels)) {
return true;
}
return possibleModels.contains(entry.getModel());
}
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.tencent.supersonic.chat.server.persistence.dataobject.StatisticsDO;
import com.tencent.supersonic.chat.server.persistence.repository.StatisticsRepository;
import com.tencent.supersonic.chat.server.service.StatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("statisticsService")
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {
private StatisticsRepository statisticsRepository;
public StatisticsServiceImpl(StatisticsRepository statisticsRepository) {
this.statisticsRepository = statisticsRepository;
}
@Async
@Override
public void batchSaveStatistics(List<StatisticsDO> list) {
statisticsRepository.batchSaveStatistics(list);
}
}

View File

@@ -0,0 +1,50 @@
package com.tencent.supersonic.chat.server.service.impl;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.SemanticSchema;
import com.tencent.supersonic.chat.core.knowledge.DictWord;
import com.tencent.supersonic.chat.core.knowledge.builder.WordBuilderFactory;
import com.tencent.supersonic.chat.core.utils.ComponentFactory;
import com.tencent.supersonic.common.pojo.enums.DictWordType;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class WordService {
private List<DictWord> preDictWords = new ArrayList<>();
public List<DictWord> getAllDictWords() {
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
SemanticSchema semanticSchema = new SemanticSchema(semanticInterpreter.getModelSchema());
List<DictWord> words = new ArrayList<>();
addWordsByType(DictWordType.DIMENSION, semanticSchema.getDimensions(), words);
addWordsByType(DictWordType.METRIC, semanticSchema.getMetrics(), words);
addWordsByType(DictWordType.MODEL, semanticSchema.getModels(), words);
addWordsByType(DictWordType.ENTITY, semanticSchema.getEntities(), words);
addWordsByType(DictWordType.VALUE, semanticSchema.getDimensionValues(), words);
return words;
}
private void addWordsByType(DictWordType value, List<SchemaElement> metas, List<DictWord> natures) {
List<DictWord> natureList = WordBuilderFactory.get(value).getDictWords(metas);
log.debug("nature type:{} , nature size:{}", value.name(), natureList.size());
natures.addAll(natureList);
}
public List<DictWord> getPreDictWords() {
return preDictWords;
}
public void setPreDictWords(List<DictWord> preDictWords) {
this.preDictWords = preDictWords;
}
}

View File

@@ -0,0 +1,154 @@
package com.tencent.supersonic.chat.server.util;
import static com.tencent.supersonic.common.pojo.Constants.ADMIN_LOWER;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.request.ChatAggConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigBaseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatConfigEditReqReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatDetailConfigReq;
import com.tencent.supersonic.chat.api.pojo.request.ItemVisibility;
import com.tencent.supersonic.chat.api.pojo.request.RecommendedQuestionReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigResp;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatConfigDO;
import com.tencent.supersonic.common.pojo.RecordInfo;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.JsonUtil;
import java.util.ArrayList;
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.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Component
@Slf4j
public class ChatConfigHelper {
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);
chatConfig.setRecordInfo(recordInfo);
chatConfig.setStatus(StatusEnum.ONLINE);
return chatConfig;
}
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);
chatConfig.setRecordInfo(recordInfo);
return chatConfig;
}
public List<Long> generateAllDimIdList(ModelSchema modelSchema) {
if (Objects.isNull(modelSchema) || CollectionUtils.isEmpty(modelSchema.getDimensions())) {
return new ArrayList<>();
}
Map<Long, List<SchemaElement>> dimIdAndDescPair = modelSchema.getDimensions()
.stream().collect(Collectors.groupingBy(SchemaElement::getId));
return new ArrayList<>(dimIdAndDescPair.keySet());
}
public List<Long> generateAllMetricIdList(ModelSchema modelSchema) {
if (Objects.isNull(modelSchema) || CollectionUtils.isEmpty(modelSchema.getMetrics())) {
return new ArrayList<>();
}
Map<Long, List<SchemaElement>> metricIdAndDescPair = modelSchema.getMetrics()
.stream().collect(Collectors.groupingBy(SchemaElement::getId));
return new ArrayList<>(metricIdAndDescPair.keySet());
}
public ChatConfigDO chatConfig2DO(ChatConfig chatConfig) {
ChatConfigDO chatConfigDO = new ChatConfigDO();
BeanUtils.copyProperties(chatConfig, chatConfigDO);
chatConfigDO.setChatAggConfig(JsonUtil.toString(chatConfig.getChatAggConfig()));
chatConfigDO.setChatDetailConfig(JsonUtil.toString(chatConfig.getChatDetailConfig()));
chatConfigDO.setRecommendedQuestions(JsonUtil.toString(chatConfig.getRecommendedQuestions()));
if (Objects.isNull(chatConfig.getStatus())) {
chatConfigDO.setStatus(null);
} else {
chatConfigDO.setStatus(chatConfig.getStatus().getCode());
}
chatConfigDO.setCreatedBy(chatConfig.getRecordInfo().getCreatedBy());
chatConfigDO.setCreatedAt(chatConfig.getRecordInfo().getCreatedAt());
chatConfigDO.setUpdatedBy(chatConfig.getRecordInfo().getUpdatedBy());
chatConfigDO.setUpdatedAt(chatConfig.getRecordInfo().getUpdatedAt());
return chatConfigDO;
}
public ChatConfigResp chatConfigDO2Descriptor(Long modelId, ChatConfigDO chatConfigDO) {
ChatConfigResp chatConfigDescriptor = new ChatConfigResp();
if (Objects.isNull(chatConfigDO)) {
// deal empty chatConfigDO
return generateEmptyChatConfigResp(modelId);
}
BeanUtils.copyProperties(chatConfigDO, chatConfigDescriptor);
chatConfigDescriptor.setChatDetailConfig(
JsonUtil.toObject(chatConfigDO.getChatDetailConfig(), ChatDetailConfigReq.class));
chatConfigDescriptor.setChatAggConfig(
JsonUtil.toObject(chatConfigDO.getChatAggConfig(), ChatAggConfigReq.class));
chatConfigDescriptor.setRecommendedQuestions(
JsonUtil.toList(chatConfigDO.getRecommendedQuestions(), RecommendedQuestionReq.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 modelId) {
ChatConfigResp chatConfigResp = new ChatConfigResp();
chatConfigResp.setModelId(modelId);
chatConfigResp.setChatDetailConfig(generateEmptyChatDetailConfigResp());
chatConfigResp.setChatAggConfig(generateEmptyChatAggConfigResp());
return chatConfigResp;
}
private ChatDetailConfigReq generateEmptyChatDetailConfigResp() {
ChatDetailConfigReq chatDetailConfig = new ChatDetailConfigReq();
ItemVisibility visibility = new ItemVisibility();
chatDetailConfig.setVisibility(visibility);
return chatDetailConfig;
}
private ChatAggConfigReq generateEmptyChatAggConfigResp() {
ChatAggConfigReq chatAggConfig = new ChatAggConfigReq();
ItemVisibility visibility = new ItemVisibility();
chatAggConfig.setVisibility(visibility);
return chatAggConfig;
}
}

View File

@@ -0,0 +1,101 @@
package com.tencent.supersonic.chat.server.util;
import com.tencent.supersonic.chat.core.corrector.SemanticCorrector;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.core.mapper.SchemaMapper;
import com.tencent.supersonic.chat.core.parser.JavaLLMProxy;
import com.tencent.supersonic.chat.core.parser.LLMProxy;
import com.tencent.supersonic.chat.core.parser.SemanticParser;
import com.tencent.supersonic.chat.core.parser.sql.llm.ModelResolver;
import com.tencent.supersonic.chat.server.processor.execute.ExecuteResultProcessor;
import com.tencent.supersonic.chat.server.processor.parse.ParseResultProcessor;
import com.tencent.supersonic.common.util.ContextUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.support.SpringFactoriesLoader;
@Slf4j
public class ComponentFactory {
private static List<SchemaMapper> schemaMappers = new ArrayList<>();
private static List<SemanticParser> semanticParsers = new ArrayList<>();
private static List<SemanticCorrector> semanticCorrectors = new ArrayList<>();
private static SemanticInterpreter semanticInterpreter;
private static LLMProxy llmProxy;
private static List<ParseResultProcessor> parseProcessors = new ArrayList<>();
private static List<ExecuteResultProcessor> executeProcessors = new ArrayList<>();
private static ModelResolver modelResolver;
public static List<SchemaMapper> getSchemaMappers() {
return CollectionUtils.isEmpty(schemaMappers) ? init(SchemaMapper.class, schemaMappers) : schemaMappers;
}
public static List<SemanticParser> getSemanticParsers() {
return CollectionUtils.isEmpty(semanticParsers) ? init(SemanticParser.class, semanticParsers) : semanticParsers;
}
public static List<SemanticCorrector> getSemanticCorrectors() {
return CollectionUtils.isEmpty(semanticCorrectors) ? init(SemanticCorrector.class,
semanticCorrectors) : semanticCorrectors;
}
public static List<ParseResultProcessor> getParseProcessors() {
return CollectionUtils.isEmpty(parseProcessors) ? init(ParseResultProcessor.class,
parseProcessors) : parseProcessors;
}
public static List<ExecuteResultProcessor> getExecuteProcessors() {
return CollectionUtils.isEmpty(executeProcessors)
? init(ExecuteResultProcessor.class, executeProcessors) : executeProcessors;
}
public static SemanticInterpreter getSemanticLayer() {
if (Objects.isNull(semanticInterpreter)) {
semanticInterpreter = init(SemanticInterpreter.class);
}
return semanticInterpreter;
}
public static LLMProxy getLLMProxy() {
//1.Preferentially retrieve from environment variables
String llmProxyEnv = System.getenv("llmProxy");
if (StringUtils.isNotBlank(llmProxyEnv)) {
Map<String, LLMProxy> implementations = ContextUtils.getBeansOfType(LLMProxy.class);
llmProxy = implementations.entrySet().stream()
.filter(entry -> entry.getKey().equalsIgnoreCase(llmProxyEnv))
.map(Map.Entry::getValue)
.findFirst()
.orElse(null);
}
//2.default JavaLLMProxy
if (Objects.isNull(llmProxy)) {
llmProxy = ContextUtils.getBean(JavaLLMProxy.class);
}
log.info("llmProxy:{}", llmProxy);
return llmProxy;
}
public static ModelResolver getModelResolver() {
if (Objects.isNull(modelResolver)) {
modelResolver = init(ModelResolver.class);
}
return modelResolver;
}
private static <T> List<T> init(Class<T> factoryType, List list) {
list.addAll(SpringFactoriesLoader.loadFactories(factoryType,
Thread.currentThread().getContextClassLoader()));
return list;
}
private static <T> T init(Class<T> factoryType) {
return SpringFactoriesLoader.loadFactories(factoryType,
Thread.currentThread().getContextClassLoader()).get(0);
}
}

View File

@@ -0,0 +1,246 @@
package com.tencent.supersonic.chat.server.util;
import static com.tencent.supersonic.common.pojo.Constants.DAY;
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.chat.api.pojo.ModelSchema;
import com.tencent.supersonic.chat.api.pojo.SchemaElement;
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeAdvancedConfig;
import com.tencent.supersonic.chat.api.pojo.request.KnowledgeInfoReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatConfigRichResp;
import com.tencent.supersonic.chat.api.pojo.response.ChatDefaultRichConfigResp;
import com.tencent.supersonic.chat.core.config.DefaultMetric;
import com.tencent.supersonic.chat.core.config.Dim4Dict;
import com.tencent.supersonic.chat.core.knowledge.DictUpdateMode;
import com.tencent.supersonic.chat.core.knowledge.DimValue2DictCommand;
import com.tencent.supersonic.chat.core.knowledge.semantic.SemanticInterpreter;
import com.tencent.supersonic.chat.server.persistence.dataobject.DimValueDO;
import com.tencent.supersonic.chat.server.service.ConfigService;
import com.tencent.supersonic.headless.api.request.PageDimensionReq;
import com.tencent.supersonic.headless.api.response.DimensionResp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
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;
@Component
public class DictMetaHelper {
@Autowired
private ConfigService configService;
@Value("${model.internal.metric.suffix:internal_cnt}")
private String internalMetricNameSuffix;
@Value("${model.internal.day.number:2}")
private Integer internalMetricDays;
private SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
public List<DimValueDO> generateDimValueInfo(DimValue2DictCommand dimValue2DictCommend) {
List<DimValueDO> dimValueDOList = new ArrayList<>();
DictUpdateMode updateMode = dimValue2DictCommend.getUpdateMode();
Set<Long> modelIds = new HashSet<>();
switch (updateMode) {
case OFFLINE_MODEL:
modelIds.addAll(dimValue2DictCommend.getModelIds());
dimValueDOList = generateDimValueInfoByModel(modelIds);
break;
case OFFLINE_FULL:
List<ModelSchema> modelSchemaDescList = semanticInterpreter.getModelSchema();
if (CollectionUtils.isEmpty(modelSchemaDescList)) {
break;
}
Map<Long, ModelSchema> modelIdAndDescPair = modelSchemaDescList.stream()
.collect(Collectors.toMap(a -> a.getModel().getId(), schema -> schema, (k1, k2) -> k1));
if (!CollectionUtils.isEmpty(modelIdAndDescPair)) {
modelIds.addAll(modelIdAndDescPair.keySet());
dimValueDOList = generateDimValueInfoByModel(modelIds);
break;
}
break;
case REALTIME_ADD:
dimValueDOList = generateDimValueInfoByModelAndDim(dimValue2DictCommend.getModelAndDimPair());
break;
case NOT_SUPPORT:
throw new RuntimeException("illegal parameter for updateMode");
default:
break;
}
return dimValueDOList;
}
private List<DimValueDO> generateDimValueInfoByModelAndDim(Map<Long, List<Long>> modelAndDimMap) {
List<DimValueDO> dimValueDOList = new ArrayList<>();
if (CollectionUtils.isEmpty(modelAndDimMap)) {
return dimValueDOList;
}
List<ModelSchema> modelSchemaDescList = semanticInterpreter.getModelSchema();
if (CollectionUtils.isEmpty(modelSchemaDescList)) {
return dimValueDOList;
}
Map<Long, ModelSchema> modelIdAndDescPair = modelSchemaDescList.stream()
.collect(Collectors.toMap(a -> a.getModel().getId(), a -> a, (k1, k2) -> k1));
for (Long modelId : modelAndDimMap.keySet()) {
if (!modelIdAndDescPair.containsKey(modelId)) {
continue;
}
Map<Long, SchemaElement> dimIdAndDescPairAll;
dimIdAndDescPairAll = modelIdAndDescPair.get(modelId).getDimensions().stream()
.collect(Collectors.toMap(SchemaElement::getId, dimSchemaDesc -> dimSchemaDesc, (k1, k2) -> k1));
List<Long> dimIdReq = modelAndDimMap.get(modelId);
Map<Long, SchemaElement> dimIdAndDescPairReq = new HashMap<>();
for (Long dimId : dimIdReq) {
if (dimIdAndDescPairAll.containsKey(dimId)) {
dimIdAndDescPairReq.put(dimId, dimIdAndDescPairAll.get(dimId));
}
}
fillDimValueDOList(dimValueDOList, modelId, dimIdAndDescPairReq);
}
return dimValueDOList;
}
private List<DimValueDO> generateDimValueInfoByModel(Set<Long> modelIds) {
List<DimValueDO> dimValueDOList = new ArrayList<>();
List<ModelSchema> modelSchemaDescList = semanticInterpreter.getModelSchema(new ArrayList<>(modelIds));
if (CollectionUtils.isEmpty(modelSchemaDescList)) {
return dimValueDOList;
}
modelSchemaDescList.forEach(modelSchemaDesc -> {
Map<Long, SchemaElement> dimIdAndDescPair = modelSchemaDesc.getDimensions().stream()
.collect(Collectors.toMap(SchemaElement::getId, dimSchemaDesc -> dimSchemaDesc, (k1, k2) -> k1));
fillDimValueDOList(dimValueDOList, modelSchemaDesc.getModel().getId(), dimIdAndDescPair);
});
return dimValueDOList;
}
private void fillDimValueDOList(List<DimValueDO> dimValueDOList, Long modelId,
Map<Long, SchemaElement> dimIdAndDescPair) {
ChatConfigRichResp chaConfigRichDesc = configService.getConfigRichInfo(modelId);
if (Objects.nonNull(chaConfigRichDesc) && Objects.nonNull(chaConfigRichDesc.getChatAggRichConfig())) {
ChatDefaultRichConfigResp chatDefaultConfig =
chaConfigRichDesc.getChatAggRichConfig().getChatDefaultConfig();
List<KnowledgeInfoReq> knowledgeAggInfo =
chaConfigRichDesc.getChatAggRichConfig().getKnowledgeInfos();
List<KnowledgeInfoReq> knowledgeDetailInfo =
chaConfigRichDesc.getChatDetailRichConfig().getKnowledgeInfos();
fillKnowledgeDimValue(knowledgeDetailInfo, chatDefaultConfig, dimValueDOList, dimIdAndDescPair, modelId);
fillKnowledgeDimValue(knowledgeAggInfo, chatDefaultConfig, dimValueDOList, dimIdAndDescPair, modelId);
}
}
private void fillKnowledgeDimValue(List<KnowledgeInfoReq> knowledgeInfos,
ChatDefaultRichConfigResp chatDefaultConfig,
List<DimValueDO> dimValueDOList,
Map<Long, SchemaElement> dimIdAndDescPair, Long modelId) {
Map<Long, DimensionResp> dimIdAndRespPair = queryDimensionRespByModelId(
new ArrayList<>(Arrays.asList(modelId)));
if (!CollectionUtils.isEmpty(knowledgeInfos)) {
List<Dim4Dict> dimensions = new ArrayList<>();
List<DefaultMetric> defaultMetricDescList = new ArrayList<>();
knowledgeInfos.stream()
.filter(knowledgeInfo -> knowledgeInfo.getSearchEnable()
&& !CollectionUtils.isEmpty(dimIdAndDescPair)
&& dimIdAndDescPair.containsKey(knowledgeInfo.getItemId()))
.forEach(knowledgeInfo -> {
SchemaElement dimensionDesc = dimIdAndDescPair.get(knowledgeInfo.getItemId());
Long dimId = dimensionDesc.getId();
String internalMetricName = "";
if (Objects.nonNull(dimId)) {
String datasourceBizName = queryDataSourceByDimId(dimId);
internalMetricName = datasourceBizName + UNDERLINE + internalMetricNameSuffix;
}
if (Objects.isNull(chatDefaultConfig)) {
defaultMetricDescList.add(new DefaultMetric(internalMetricName,
internalMetricDays, DAY));
} else {
String metric = internalMetricName;
if (!CollectionUtils.isEmpty(chatDefaultConfig.getMetrics())) {
metric = chatDefaultConfig.getMetrics().get(0).getBizName();
}
defaultMetricDescList.add(new DefaultMetric(metric,
chatDefaultConfig.getUnit(), chatDefaultConfig.getPeriod()));
}
String bizName = dimensionDesc.getBizName();
Dim4Dict dim4Dict = new Dim4Dict();
dim4Dict.setDimId(knowledgeInfo.getItemId());
dim4Dict.setBizName(bizName);
if (Objects.nonNull(knowledgeInfo.getKnowledgeAdvancedConfig())) {
KnowledgeAdvancedConfig knowledgeAdvancedConfig
= knowledgeInfo.getKnowledgeAdvancedConfig();
BeanUtils.copyProperties(knowledgeAdvancedConfig, dim4Dict);
if (Objects.nonNull(dimIdAndRespPair)
&& dimIdAndRespPair.containsKey(dim4Dict.getDimId())) {
String datasourceFilterSql = dimIdAndRespPair.get(
dim4Dict.getDimId()).getModelFilterSql();
if (StringUtils.isNotEmpty(datasourceFilterSql)) {
dim4Dict.getRuleList().add(datasourceFilterSql);
}
}
}
dimensions.add(dim4Dict);
});
if (!CollectionUtils.isEmpty(dimensions)) {
DimValueDO dimValueDO = new DimValueDO()
.setModelId(modelId)
.setDefaultMetricIds(defaultMetricDescList)
.setDimensions(dimensions);
dimValueDOList.add(dimValueDO);
}
}
}
private Map<Long, DimensionResp> queryDimensionRespByModelId(List<Long> modelIds) {
Map<Long, DimensionResp> dimIdAndRespPair = new HashMap<>();
PageDimensionReq pageDimensionCmd = new PageDimensionReq();
pageDimensionCmd.setModelIds(modelIds);
PageInfo<DimensionResp> dimensionPage = semanticInterpreter.getDimensionPage(pageDimensionCmd);
if (Objects.nonNull(dimensionPage) && !CollectionUtils.isEmpty(dimensionPage.getList())) {
List<DimensionResp> dimList = dimensionPage.getList();
dimIdAndRespPair = dimList.stream().collect(Collectors.toMap(DimensionResp::getId, v -> v, (v1, v2) -> v2));
}
return dimIdAndRespPair;
}
private String queryDataSourceByDimId(Long id) {
PageDimensionReq pageDimensionCmd = new PageDimensionReq();
pageDimensionCmd.setId(id.toString());
PageInfo<DimensionResp> dimensionPage = semanticInterpreter.getDimensionPage(pageDimensionCmd);
if (Objects.nonNull(dimensionPage) && !CollectionUtils.isEmpty(dimensionPage.getList())) {
List<DimensionResp> list = dimensionPage.getList();
return list.get(0).getModelBizName();
}
return "";
}
}

View File

@@ -0,0 +1,46 @@
package com.tencent.supersonic.chat.server.util;
import com.google.common.base.Strings;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.chat.core.knowledge.DictConfig;
import com.tencent.supersonic.chat.core.knowledge.DimValue2DictCommand;
import com.tencent.supersonic.chat.core.knowledge.DimValueInfo;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictConfDO;
import com.tencent.supersonic.chat.server.persistence.dataobject.DictTaskDO;
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
import com.tencent.supersonic.common.util.JsonUtil;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
public class DictTaskConverter {
private static String dateTimeFormatter = "yyyyMMddHHmmss";
public static DictTaskDO generateDimValueDictTaskDO(DimValue2DictCommand dimValue2DictCommend, User user) {
DictTaskDO taskPO = new DictTaskDO();
Date createAt = new Date();
String date = DateTimeFormatter.ofPattern(dateTimeFormatter)
.format(createAt.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
String creator = Strings.isNullOrEmpty(user.getName()) ? "" : user.getName();
String updateMode = dimValue2DictCommend.getUpdateMode().getValue();
String name = String.format("DimValue_dic_%s_%s_%s", updateMode, creator, date);
taskPO.setName(name);
taskPO.setCreatedAt(createAt);
taskPO.setCommand(JsonUtil.toString(dimValue2DictCommend));
taskPO.setStatus(TaskStatusEnum.PENDING.getCode());
taskPO.setCreatedBy(creator);
return taskPO;
}
public static DictConfig dictConfPO2Config(DictConfDO dictConfDO) {
DictConfig dictConfig = new DictConfig();
dictConfig.setModelId(dictConfDO.getModelId());
List<DimValueInfo> dimValueInfos = JsonUtil.toList(dictConfDO.getDimValueInfos(), DimValueInfo.class);
dictConfig.setDimValueInfoList(dimValueInfos);
return dictConfig;
}
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.chat.server.util;
import com.tencent.supersonic.chat.server.config.ChatConfig;
import org.springframework.context.ApplicationEvent;
public class VisibilityEvent extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private ChatConfig chatConfig;
public VisibilityEvent(Object source, ChatConfig chatConfig) {
super(source);
this.chatConfig = chatConfig;
}
public void setChatConfig(ChatConfig chatConfig) {
this.chatConfig = chatConfig;
}
public ChatConfig getChatConfig() {
return chatConfig;
}
}

View File

@@ -0,0 +1,30 @@
package com.tencent.supersonic.chat.server.util;
import com.github.benmanes.caffeine.cache.Cache;
import com.tencent.supersonic.chat.api.pojo.request.ItemNameVisibilityInfo;
import com.tencent.supersonic.chat.server.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class VisibilityListener implements ApplicationListener<VisibilityEvent> {
@Autowired
@Qualifier("searchCaffeineCache")
private Cache<Long, Object> caffeineCache;
@Autowired
private ConfigService configService;
@Override
public void onApplicationEvent(VisibilityEvent event) {
log.info("visibility has changed,so update cache!");
ItemNameVisibilityInfo itemNameVisibility = configService.getItemNameVisibility(event.getChatConfig());
log.info("itemNameVisibility :{}", itemNameVisibility);
caffeineCache.put(event.getChatConfig().getModelId(), itemNameVisibility);
}
}

View File

@@ -0,0 +1,303 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tencent.supersonic.chat.server.persistence.mapper.AgentDOMapper">
<resultMap id="BaseResultMap" type="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="description" jdbcType="VARCHAR" property="description" />
<result column="status" jdbcType="INTEGER" property="status" />
<result column="examples" jdbcType="VARCHAR" property="examples" />
<result column="config" jdbcType="VARCHAR" property="config" />
<result column="created_by" jdbcType="VARCHAR" property="createdBy" />
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
<result column="updated_by" jdbcType="VARCHAR" property="updatedBy" />
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" />
<result column="enable_search" jdbcType="INTEGER" property="enableSearch" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, name, description, status, examples, config, created_by, created_at, updated_by,
updated_at, enable_search
</sql>
<select id="selectByExample" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDOExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from s2_agent
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
<if test="limitStart != null and limitStart>=0">
limit #{limitStart} , #{limitEnd}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from s2_agent
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from s2_agent
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO">
insert into s2_agent (id, name, description,
status, examples, config,
created_by, created_at, updated_by,
updated_at, enable_search)
values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
#{status,jdbcType=INTEGER}, #{examples,jdbcType=VARCHAR}, #{config,jdbcType=VARCHAR},
#{createdBy,jdbcType=VARCHAR}, #{createdAt,jdbcType=TIMESTAMP}, #{updatedBy,jdbcType=VARCHAR},
#{updatedAt,jdbcType=TIMESTAMP}, #{enableSearch,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO">
insert into s2_agent
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
name,
</if>
<if test="description != null">
description,
</if>
<if test="status != null">
status,
</if>
<if test="examples != null">
examples,
</if>
<if test="config != null">
config,
</if>
<if test="createdBy != null">
created_by,
</if>
<if test="createdAt != null">
created_at,
</if>
<if test="updatedBy != null">
updated_by,
</if>
<if test="updatedAt != null">
updated_at,
</if>
<if test="enableSearch != null">
enable_search,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=INTEGER},
</if>
<if test="examples != null">
#{examples,jdbcType=VARCHAR},
</if>
<if test="config != null">
#{config,jdbcType=VARCHAR},
</if>
<if test="createdBy != null">
#{createdBy,jdbcType=VARCHAR},
</if>
<if test="createdAt != null">
#{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedBy != null">
#{updatedBy,jdbcType=VARCHAR},
</if>
<if test="updatedAt != null">
#{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="enableSearch != null">
#{enableSearch,jdbcType=INTEGER},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDOExample" resultType="java.lang.Long">
select count(*) from s2_agent
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update s2_agent
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=INTEGER},
</if>
<if test="record.name != null">
name = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=INTEGER},
</if>
<if test="record.examples != null">
examples = #{record.examples,jdbcType=VARCHAR},
</if>
<if test="record.config != null">
config = #{record.config,jdbcType=VARCHAR},
</if>
<if test="record.createdBy != null">
created_by = #{record.createdBy,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null">
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.updatedBy != null">
updated_by = #{record.updatedBy,jdbcType=VARCHAR},
</if>
<if test="record.updatedAt != null">
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="record.enableSearch != null">
enable_search = #{record.enableSearch,jdbcType=INTEGER},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update s2_agent
set id = #{record.id,jdbcType=INTEGER},
name = #{record.name,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
status = #{record.status,jdbcType=INTEGER},
examples = #{record.examples,jdbcType=VARCHAR},
config = #{record.config,jdbcType=VARCHAR},
created_by = #{record.createdBy,jdbcType=VARCHAR},
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
updated_by = #{record.updatedBy,jdbcType=VARCHAR},
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP},
enable_search = #{record.enableSearch,jdbcType=INTEGER}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO">
update s2_agent
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=VARCHAR},
</if>
<if test="status != null">
status = #{status,jdbcType=INTEGER},
</if>
<if test="examples != null">
examples = #{examples,jdbcType=VARCHAR},
</if>
<if test="config != null">
config = #{config,jdbcType=VARCHAR},
</if>
<if test="createdBy != null">
created_by = #{createdBy,jdbcType=VARCHAR},
</if>
<if test="createdAt != null">
created_at = #{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedBy != null">
updated_by = #{updatedBy,jdbcType=VARCHAR},
</if>
<if test="updatedAt != null">
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="enableSearch != null">
enable_search = #{enableSearch,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.tencent.supersonic.chat.server.persistence.dataobject.AgentDO">
update s2_agent
set name = #{name,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
status = #{status,jdbcType=INTEGER},
examples = #{examples,jdbcType=VARCHAR},
config = #{config,jdbcType=VARCHAR},
created_by = #{createdBy,jdbcType=VARCHAR},
created_at = #{createdAt,jdbcType=TIMESTAMP},
updated_by = #{updatedBy,jdbcType=VARCHAR},
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
enable_search = #{enableSearch,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>

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