mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 11:07:06 +00:00
(improvement)(Headless) support multiturn text-to-sql (#983)
This commit is contained in:
@@ -1,18 +1,47 @@
|
||||
package com.tencent.supersonic.chat.server.parser;
|
||||
|
||||
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
|
||||
import com.tencent.supersonic.chat.server.pojo.ChatParseContext;
|
||||
import com.tencent.supersonic.chat.server.util.QueryReqConverter;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
import com.tencent.supersonic.common.util.JsonUtil;
|
||||
import com.tencent.supersonic.headless.api.pojo.SchemaMapInfo;
|
||||
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.QueryReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.ParseResp;
|
||||
import com.tencent.supersonic.headless.core.chat.mapper.SchemaMapper;
|
||||
import com.tencent.supersonic.headless.core.chat.parser.llm.LLMRequestService;
|
||||
import com.tencent.supersonic.headless.core.chat.parser.llm.RewriteQueryGeneration;
|
||||
import com.tencent.supersonic.headless.core.chat.query.llm.s2sql.LLMReq;
|
||||
import com.tencent.supersonic.headless.core.chat.query.llm.s2sql.LLMSqlQuery;
|
||||
import com.tencent.supersonic.headless.core.pojo.QueryContext;
|
||||
import com.tencent.supersonic.headless.server.service.ChatQueryService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
import com.tencent.supersonic.headless.server.service.impl.ChatQueryServiceImpl;
|
||||
import com.tencent.supersonic.headless.server.utils.ComponentFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static com.tencent.supersonic.common.pojo.Constants.CONTEXT;
|
||||
|
||||
@Slf4j
|
||||
public class NL2SQLParser implements ChatParser {
|
||||
|
||||
private int contextualNum = 5;
|
||||
|
||||
private List<SchemaMapper> schemaMappers = ComponentFactory.getSchemaMappers();
|
||||
|
||||
@Override
|
||||
public void parse(ChatParseContext chatParseContext, ParseResp parseResp) {
|
||||
if (!chatParseContext.enableNL2SQL()) {
|
||||
@@ -21,7 +50,15 @@ public class NL2SQLParser implements ChatParser {
|
||||
if (checkSkip(parseResp)) {
|
||||
return;
|
||||
}
|
||||
considerMultiturn(chatParseContext, parseResp);
|
||||
QueryReq queryReq = QueryReqConverter.buildText2SqlQueryReq(chatParseContext);
|
||||
|
||||
Environment environment = ContextUtils.getBean(Environment.class);
|
||||
String multiTurn = environment.getProperty("multi.turn");
|
||||
if (StringUtils.isNotBlank(multiTurn) && Boolean.parseBoolean(multiTurn)) {
|
||||
queryReq.setMapInfo(new SchemaMapInfo());
|
||||
}
|
||||
|
||||
ChatQueryService chatQueryService = ContextUtils.getBean(ChatQueryService.class);
|
||||
ParseResp text2SqlParseResp = chatQueryService.performParsing(queryReq);
|
||||
if (!ParseResp.ParseState.FAILED.equals(text2SqlParseResp.getState())) {
|
||||
@@ -30,6 +67,100 @@ public class NL2SQLParser implements ChatParser {
|
||||
parseResp.getParseTimeCost().setSqlTime(text2SqlParseResp.getParseTimeCost().getSqlTime());
|
||||
}
|
||||
|
||||
private void considerMultiturn(ChatParseContext chatParseContext, ParseResp parseResp) {
|
||||
Environment environment = ContextUtils.getBean(Environment.class);
|
||||
RewriteQueryGeneration rewriteQueryGeneration = ContextUtils.getBean(RewriteQueryGeneration.class);
|
||||
String multiTurn = environment.getProperty("multi.turn");
|
||||
String multiNum = environment.getProperty("multi.num");
|
||||
if (StringUtils.isBlank(multiTurn) || !Boolean.parseBoolean(multiTurn)) {
|
||||
return;
|
||||
}
|
||||
log.info("multi turn text-to-sql!");
|
||||
List<ParseResp> contextualList = getContextualList(parseResp, multiNum);
|
||||
List<String> contextualQuestions = getContextualQuestionsWithLink(contextualList);
|
||||
StringBuffer currentPromptSb = new StringBuffer();
|
||||
if (contextualQuestions.size() == 0) {
|
||||
currentPromptSb.append("contextualQuestions:" + "\n");
|
||||
} else {
|
||||
currentPromptSb.append("contextualQuestions:" + "\n" + String.join("\n", contextualQuestions) + "\n");
|
||||
}
|
||||
String currentQuestion = getQueryLinks(chatParseContext);
|
||||
currentPromptSb.append("currentQuestion:" + currentQuestion + "\n");
|
||||
currentPromptSb.append("rewritingCurrentQuestion:\n");
|
||||
String rewriteQuery = rewriteQueryGeneration.generation(currentPromptSb.toString());
|
||||
log.info("rewriteQuery:{}", rewriteQuery);
|
||||
chatParseContext.setQueryText(rewriteQuery);
|
||||
}
|
||||
|
||||
private List<String> getContextualQuestionsWithLink(List<ParseResp> contextualList) {
|
||||
List<String> contextualQuestions = new ArrayList<>();
|
||||
contextualList.stream().forEach(o -> {
|
||||
Map<String, Object> map = JsonUtil.toMap(JsonUtil.toString(
|
||||
o.getSelectedParses().get(0).getProperties().get(CONTEXT)), String.class, Object.class);
|
||||
LLMReq llmReq = JsonUtil.toObject(JsonUtil.toString(map.get("llmReq")), LLMReq.class);
|
||||
List<LLMReq.ElementValue> linking = llmReq.getLinking();
|
||||
List<String> priorLinkingList = new ArrayList<>();
|
||||
for (LLMReq.ElementValue priorLinking : linking) {
|
||||
String fieldName = priorLinking.getFieldName();
|
||||
String fieldValue = priorLinking.getFieldValue();
|
||||
priorLinkingList.add("‘" + fieldValue + "‘是一个‘" + fieldName + "‘");
|
||||
}
|
||||
String linkingListStr = String.join(",", priorLinkingList);
|
||||
String questionAugmented = String.format("%s (补充信息:%s) ", o.getQueryText(), linkingListStr);
|
||||
contextualQuestions.add(questionAugmented);
|
||||
});
|
||||
return contextualQuestions;
|
||||
}
|
||||
|
||||
private List<ParseResp> getContextualList(ParseResp parseResp, String multiNum) {
|
||||
ChatQueryRepository chatQueryRepository = ContextUtils.getBean(ChatQueryRepository.class);
|
||||
List<ParseResp> contextualParseInfoList = chatQueryRepository.getContextualParseInfo(
|
||||
parseResp.getChatId()).stream().filter(o -> o.getSelectedParses().get(0)
|
||||
.getQueryMode().equals(LLMSqlQuery.QUERY_MODE)
|
||||
).collect(Collectors.toList());
|
||||
if (StringUtils.isNotBlank(multiNum) && StringUtils.isNumeric(multiNum)) {
|
||||
int num = Integer.parseInt(multiNum);
|
||||
contextualNum = Math.min(contextualNum, num);
|
||||
}
|
||||
List<ParseResp> contextualList = contextualParseInfoList.subList(0,
|
||||
Math.min(contextualNum, contextualParseInfoList.size()));
|
||||
Collections.reverse(contextualList);
|
||||
return contextualList;
|
||||
}
|
||||
|
||||
private String getQueryLinks(ChatParseContext chatParseContext) {
|
||||
QueryReq queryReq = QueryReqConverter.buildText2SqlQueryReq(chatParseContext);
|
||||
|
||||
ChatQueryServiceImpl chatQueryService = ContextUtils.getBean(ChatQueryServiceImpl.class);
|
||||
// build queryContext and chatContext
|
||||
QueryContext queryCtx = chatQueryService.buildQueryContext(queryReq);
|
||||
|
||||
// 1. mapper
|
||||
if (Objects.isNull(chatParseContext.getMapInfo())
|
||||
|| MapUtils.isEmpty(chatParseContext.getMapInfo().getDataSetElementMatches())) {
|
||||
schemaMappers.forEach(mapper -> {
|
||||
mapper.map(queryCtx);
|
||||
});
|
||||
}
|
||||
LLMRequestService requestService = ContextUtils.getBean(LLMRequestService.class);
|
||||
Long dataSetId = requestService.getDataSetId(queryCtx);
|
||||
log.info("dataSetId:{}", dataSetId);
|
||||
if (dataSetId == null) {
|
||||
return null;
|
||||
}
|
||||
List<LLMReq.ElementValue> linkingValues = requestService.getValueList(queryCtx, dataSetId);
|
||||
List<String> priorLinkingList = new ArrayList<>();
|
||||
for (LLMReq.ElementValue priorLinking : linkingValues) {
|
||||
String fieldName = priorLinking.getFieldName();
|
||||
String fieldValue = priorLinking.getFieldValue();
|
||||
priorLinkingList.add("‘" + fieldValue + "‘是一个‘" + fieldName + "‘");
|
||||
}
|
||||
String linkingListStr = String.join(",", priorLinkingList);
|
||||
String questionAugmented = String.format("%s (补充信息:%s) ", chatParseContext.getQueryText(), linkingListStr);
|
||||
log.info("questionAugmented:{}", questionAugmented);
|
||||
return questionAugmented;
|
||||
}
|
||||
|
||||
private boolean checkSkip(ParseResp parseResp) {
|
||||
List<SemanticParseInfo> selectedParses = parseResp.getSelectedParses();
|
||||
for (SemanticParseInfo semanticParseInfo : selectedParses) {
|
||||
|
||||
@@ -18,4 +18,6 @@ public interface ChatParseMapper {
|
||||
|
||||
List<ChatParseDO> getParseInfoList(List<Long> questionIds);
|
||||
|
||||
List<ChatParseDO> getContextualParseInfo(Integer chatId);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,4 +36,6 @@ public interface ChatQueryRepository {
|
||||
|
||||
Boolean deleteChatQuery(Long questionId);
|
||||
|
||||
List<ParseResp> getContextualParseInfo(Integer chatId);
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ 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;
|
||||
@@ -44,8 +45,8 @@ public class ChatQueryRepositoryImpl implements ChatQueryRepository {
|
||||
private final ShowCaseCustomMapper showCaseCustomMapper;
|
||||
|
||||
public ChatQueryRepositoryImpl(ChatQueryDOMapper chatQueryDOMapper,
|
||||
ChatParseMapper chatParseMapper,
|
||||
ShowCaseCustomMapper showCaseCustomMapper) {
|
||||
ChatParseMapper chatParseMapper,
|
||||
ShowCaseCustomMapper showCaseCustomMapper) {
|
||||
this.chatQueryDOMapper = chatQueryDOMapper;
|
||||
this.chatParseMapper = chatParseMapper;
|
||||
this.showCaseCustomMapper = showCaseCustomMapper;
|
||||
@@ -131,7 +132,7 @@ public class ChatQueryRepositoryImpl implements ChatQueryRepository {
|
||||
|
||||
@Override
|
||||
public List<ChatParseDO> batchSaveParseInfo(ChatParseReq chatParseReq,
|
||||
ParseResp parseResult, List<SemanticParseInfo> candidateParses) {
|
||||
ParseResp parseResult, List<SemanticParseInfo> candidateParses) {
|
||||
List<ChatParseDO> chatParseDOList = new ArrayList<>();
|
||||
getChatParseDO(chatParseReq, parseResult.getQueryId(), candidateParses, chatParseDOList);
|
||||
if (!CollectionUtils.isEmpty(candidateParses)) {
|
||||
@@ -141,7 +142,7 @@ public class ChatQueryRepositoryImpl implements ChatQueryRepository {
|
||||
}
|
||||
|
||||
public void getChatParseDO(ChatParseReq chatParseReq, Long queryId,
|
||||
List<SemanticParseInfo> parses, List<ChatParseDO> chatParseDOList) {
|
||||
List<SemanticParseInfo> parses, List<ChatParseDO> chatParseDOList) {
|
||||
for (int i = 0; i < parses.size(); i++) {
|
||||
ChatParseDO chatParseDO = new ChatParseDO();
|
||||
chatParseDO.setChatId(Long.valueOf(chatParseReq.getChatId()));
|
||||
@@ -193,4 +194,17 @@ public class ChatQueryRepositoryImpl implements ChatQueryRepository {
|
||||
return chatQueryDOMapper.deleteByPrimaryKey(questionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParseResp> getContextualParseInfo(Integer chatId) {
|
||||
List<ChatParseDO> chatParseDOList = chatParseMapper.getContextualParseInfo(chatId);
|
||||
List<ParseResp> semanticParseInfoList = chatParseDOList.stream().map(parseInfo -> {
|
||||
ParseResp parseResp = new ParseResp(chatId, parseInfo.getQueryText());
|
||||
List<SemanticParseInfo> selectedParses = new ArrayList<>();
|
||||
selectedParses.add(JSONObject.parseObject(parseInfo.getParseInfo(), SemanticParseInfo.class));
|
||||
parseResp.setSelectedParses(selectedParses);
|
||||
return parseResp;
|
||||
}).collect(Collectors.toList());
|
||||
return semanticParseInfoList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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.ChatManageService;
|
||||
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;
|
||||
@@ -24,11 +25,8 @@ import java.util.List;
|
||||
@RequestMapping({"/api/chat/manage", "/openapi/chat/manage"})
|
||||
public class ChatController {
|
||||
|
||||
private final ChatManageService chatService;
|
||||
|
||||
public ChatController(ChatManageService chatService) {
|
||||
this.chatService = chatService;
|
||||
}
|
||||
@Autowired
|
||||
private ChatManageService chatService;
|
||||
|
||||
@PostMapping("/save")
|
||||
public Boolean save(@RequestParam(value = "chatName") String chatName,
|
||||
|
||||
@@ -64,6 +64,7 @@ public class ChatServiceImpl implements ChatService {
|
||||
|
||||
@Override
|
||||
public ParseResp performParsing(ChatParseReq chatParseReq) {
|
||||
String queryText = chatParseReq.getQueryText();
|
||||
ParseResp parseResp = new ParseResp(chatParseReq.getChatId(), chatParseReq.getQueryText());
|
||||
chatManageService.createChatQuery(chatParseReq, parseResp);
|
||||
ChatParseContext chatParseContext = buildParseContext(chatParseReq);
|
||||
@@ -73,6 +74,8 @@ public class ChatServiceImpl implements ChatService {
|
||||
for (ParseResultProcessor processor : parseResultProcessors) {
|
||||
processor.process(chatParseContext, parseResp);
|
||||
}
|
||||
parseResp.setQueryText(queryText);
|
||||
chatParseReq.setQueryText(queryText);
|
||||
chatManageService.batchAddParse(chatParseReq, parseResp);
|
||||
return parseResp;
|
||||
}
|
||||
|
||||
@@ -46,4 +46,10 @@
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="getContextualParseInfo" resultMap="ChatParse">
|
||||
select *
|
||||
from s2_chat_parse
|
||||
where chat_id = #{chatId} order by question_id desc limit 10
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -143,7 +143,7 @@ public class LLMRequestService {
|
||||
return extraInfoSb.toString();
|
||||
}
|
||||
|
||||
protected List<ElementValue> getValueList(QueryContext queryCtx, Long dataSetId) {
|
||||
public List<ElementValue> getValueList(QueryContext queryCtx, Long dataSetId) {
|
||||
Map<Long, String> itemIdToName = getItemIdToName(queryCtx, dataSetId);
|
||||
List<SchemaElementMatch> matchedElements = queryCtx.getMapInfo().getMatchedElements(dataSetId);
|
||||
if (CollectionUtils.isEmpty(matchedElements)) {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.tencent.supersonic.headless.core.chat.parser.llm;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.tencent.supersonic.common.util.JsonUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RewriteExamplarLoader {
|
||||
|
||||
private static final String EXAMPLE_JSON_FILE = "rewrite_examplar.json";
|
||||
|
||||
private TypeReference<List<RewriteExample>> valueTypeRef = new TypeReference<List<RewriteExample>>() {
|
||||
};
|
||||
|
||||
public List<RewriteExample> getRewriteExamples() {
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource(EXAMPLE_JSON_FILE);
|
||||
InputStream inputStream = resource.getInputStream();
|
||||
return JsonUtil.INSTANCE.getObjectMapper().readValue(inputStream, valueTypeRef);
|
||||
} catch (Exception e) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.tencent.supersonic.headless.core.chat.parser.llm;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RewriteExample {
|
||||
|
||||
private String contextualQuestions;
|
||||
|
||||
private String currentQuestion;
|
||||
|
||||
private String rewritingCurrentQuestion;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.tencent.supersonic.headless.core.chat.parser.llm;
|
||||
|
||||
import com.tencent.supersonic.common.util.JsonUtil;
|
||||
import dev.langchain4j.data.message.AiMessage;
|
||||
import dev.langchain4j.model.chat.ChatLanguageModel;
|
||||
import dev.langchain4j.model.input.Prompt;
|
||||
import dev.langchain4j.model.input.PromptTemplate;
|
||||
import dev.langchain4j.model.output.Response;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class RewriteQueryGeneration {
|
||||
|
||||
private static final Logger keyPipelineLog = LoggerFactory.getLogger("keyPipeline");
|
||||
@Autowired
|
||||
private ChatLanguageModel chatLanguageModel;
|
||||
|
||||
@Autowired
|
||||
private RewriteExamplarLoader rewriteExamplarLoader;
|
||||
|
||||
@Autowired
|
||||
private SqlPromptGenerator sqlPromptGenerator;
|
||||
|
||||
public String generation(String currentPromptStr) {
|
||||
//1.retriever sqlExamples
|
||||
|
||||
List<Map<String, String>> rewriteExamples = rewriteExamplarLoader.getRewriteExamples().stream().map(o -> {
|
||||
return JsonUtil.toMap(JsonUtil.toString(o), String.class, String.class);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
//2.generator linking and sql prompt by sqlExamples,and generate response.
|
||||
String promptStr = sqlPromptGenerator.generateRewritePrompt(rewriteExamples) + currentPromptStr;
|
||||
|
||||
Prompt prompt = PromptTemplate.from(JsonUtil.toString(promptStr)).apply(new HashMap<>());
|
||||
keyPipelineLog.info("request prompt:{}", prompt.toSystemMessage());
|
||||
Response<AiMessage> response = chatLanguageModel.generate(prompt.toSystemMessage());
|
||||
String result = response.content().text();
|
||||
keyPipelineLog.info("model response:{}", result);
|
||||
//3.format response.
|
||||
String rewriteQuery = response.content().text();
|
||||
|
||||
return rewriteQuery;
|
||||
}
|
||||
}
|
||||
@@ -129,4 +129,19 @@ public class SqlPromptGenerator {
|
||||
return sqlPromptPool;
|
||||
}
|
||||
|
||||
public String generateRewritePrompt(List<Map<String, String>> rewriteExamples) {
|
||||
String instruction = "#this is a multi-turn text-to-sql scenes,you need consider the contextual "
|
||||
+ "questions and semantics, rewriting current question for expressing complete semantics of "
|
||||
+ "the current question based on the contextual questions.";
|
||||
List<String> exampleKeys = Arrays.asList("contextualQuestions", "currentQuestion", "rewritingCurrentQuestion");
|
||||
StringBuilder rewriteSb = new StringBuilder();
|
||||
rewriteExamples.stream().forEach(o -> {
|
||||
exampleKeys.stream().forEach(example -> {
|
||||
rewriteSb.append(example + ":" + o.get(example) + "\n");
|
||||
});
|
||||
rewriteSb.append("\n");
|
||||
});
|
||||
return instruction + InputFormat.SEPERATOR + rewriteSb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class ChatQueryServiceImpl implements ChatQueryService {
|
||||
return parseResult;
|
||||
}
|
||||
|
||||
private QueryContext buildQueryContext(QueryReq queryReq) {
|
||||
public QueryContext buildQueryContext(QueryReq queryReq) {
|
||||
|
||||
SemanticSchema semanticSchema = semanticService.getSemanticSchema();
|
||||
Map<Long, List<Long>> modelIdToDataSetIds = dataSetService.getModelIdToDataSetIds();
|
||||
|
||||
@@ -102,3 +102,6 @@ inMemoryEmbeddingStore:
|
||||
query:
|
||||
optimizer:
|
||||
enable: true
|
||||
multi:
|
||||
turn: false
|
||||
num: 5
|
||||
|
||||
122
launchers/standalone/src/main/resources/rewrite_examplar.json
Normal file
122
launchers/standalone/src/main/resources/rewrite_examplar.json
Normal file
@@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"contextualQuestions": "[“近7天纯音乐的歌曲播放量 (补充信息:’ '纯音乐'‘是一个’语种‘。)”]",
|
||||
"currentQuestion": "对比翻唱版呢 (补充信息:’ '翻唱版'‘是一个’歌曲版本‘。)",
|
||||
"rewritingCurrentQuestion": "对比近7天翻唱版和纯音乐的歌曲播放量"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[]",
|
||||
"currentQuestion": "robinlee在内容库的访问次数 (补充信息:’ 'robinlee'‘是一个’用户名‘。)",
|
||||
"rewritingCurrentQuestion": "robinlee在内容库的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"robinlee在内容库的访问次数 (补充信息:’ 'robinlee'‘是一个’用户名‘。)\"]",
|
||||
"currentQuestion": "对比jackjchen呢? (补充信息:’ 'jackjchen'‘是一个’用户名‘。)",
|
||||
"rewritingCurrentQuestion": "robinlee对比jackjchen在内容库的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"robinlee在内容库的访问次数 (补充信息:’ 'robinlee'‘是一个’用户名‘。)\",\"对比jackjchen呢? (补充信息:’ 'jackjchen'‘是一个’用户名‘。)\"]。",
|
||||
"currentQuestion": "内容库近12个月访问人数按部门",
|
||||
"rewritingCurrentQuestion": "内容库近12个月访问人数按部门"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"robinlee在内容库的访问次数 (补充信息:’ 'robinlee'‘是一个’用户名‘。)\",\"对比jackjchen呢? (补充信息:’ 'jackjchen'‘是一个’用户名‘。)\",\"内容库近12个月访问人数按部门\"]",
|
||||
"currentQuestion": "访问次数呢?",
|
||||
"rewritingCurrentQuestion": "内容库近12个月访问次数按部门"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[]",
|
||||
"currentQuestion": "近3天海田飞系MPPM结算播放份额 (补充信息:’'海田飞系'‘是一个’严选版权归属系‘)",
|
||||
"rewritingCurrentQuestion": "近3天海田飞系MPPM结算播放份额"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"近3天海田飞系MPPM结算播放份额(补充信息:’'海田飞系'‘是一个’严选版权归属系‘) \"]",
|
||||
"currentQuestion": "近60天呢",
|
||||
"rewritingCurrentQuestion": "近60天海田飞系MPPM结算播放份额"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"近3天海田飞系MPPM结算播放份额(补充信息:’'海田飞系'‘是一个’严选版权归属系‘) \",\"近60天呢\"]",
|
||||
"currentQuestion": "飞天系呢(补充信息:’'飞天系'‘是一个’严选版权归属系‘)",
|
||||
"rewritingCurrentQuestion": "近60天飞天系MPPM结算播放份额"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“近90天袁亚伟播放量是多少 (补充信息:'袁亚伟'是一个歌手名)”]",
|
||||
"currentQuestion": "平均值是多少",
|
||||
"rewritingCurrentQuestion": "近90天袁亚伟播放量的平均值是多少"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“近90天袁亚伟播放量是多少 (补充信息:'袁亚伟'是一个歌手名)”,\"平均值是多少\",\"总和是多少\"]",
|
||||
"currentQuestion": "总和是多少",
|
||||
"rewritingCurrentQuestion": "近90天袁亚伟播放量的总和是多少"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"播放量大于1万的歌曲有多少\"]",
|
||||
"currentQuestion": "下载量大于10万的呢",
|
||||
"rewritingCurrentQuestion": "下载量大于10万的歌曲有多少"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"周杰伦2023年6月之后发布的歌曲有哪些(补充信息:'周杰伦'是一个歌手名)\"]",
|
||||
"currentQuestion": "这些歌曲有哪些播放量大于500W的?",
|
||||
"rewritingCurrentQuestion": "周杰伦2023年6月之后发布的歌曲,有哪些播放量大于500W的?"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“陈奕迅唱的所有的播放量大于20万的歌曲有哪些(补充信息:'陈奕迅'是一个歌手名)”]",
|
||||
"currentQuestion": "大于100万的呢",
|
||||
"rewritingCurrentQuestion": "陈奕迅唱的所有的播放量大于100万的歌曲有哪些"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“陈奕迅唱的所有的播放量大于20万的歌曲有哪些(补充信息:'陈奕迅'是一个歌手名)”,\"大于100万的呢\"]",
|
||||
"currentQuestion": "周杰伦去年发布的歌曲有哪些(补充信息:'周杰伦'是一个歌手名)",
|
||||
"rewritingCurrentQuestion": "周杰伦去年发布的歌曲有哪些"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“陈奕迅唱的所有的播放量大于20万的歌曲有哪些(补充信息:'陈奕迅'是一个歌手名)”,\"大于100万的呢\",\"周杰伦去年发布的歌曲有哪些(补充信息:'周杰伦'是一个歌手名)\"]",
|
||||
"currentQuestion": "他今年发布的呢",
|
||||
"rewritingCurrentQuestion": "周杰伦今年发布的歌曲有哪些"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“陈奕迅唱的所有的播放量大于20万的歌曲有哪些(补充信息:'陈奕迅'是一个歌手名)”,\"大于100万的呢\",\"周杰伦去年发布的歌曲有哪些(补充信息:'周杰伦'是一个歌手名)\",\"他今年发布的呢\"]",
|
||||
"currentQuestion": "我想要近半年签约的播放量前十的歌手有哪些",
|
||||
"rewritingCurrentQuestion": "我想要近半年签约的播放量前十的歌手有哪些"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[]",
|
||||
"currentQuestion": "最近一年发行的歌曲中,有哪些在近7天播放超过一千万的",
|
||||
"rewritingCurrentQuestion": "最近一年发行的歌曲中,有哪些在近7天播放超过一千万的"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“最近一年发行的歌曲中,有哪些在近7天播放超过一千万的”]",
|
||||
"currentQuestion": "今年以来呢?",
|
||||
"rewritingCurrentQuestion": "今年以来发行的歌曲中,有哪些在近7天播放超过一千万的"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[“最近一年发行的歌曲中,有哪些在近7天播放超过一千万的”,\"今年以来呢?\"]",
|
||||
"currentQuestion": "2023年以来呢?",
|
||||
"rewritingCurrentQuestion": "2023年以来发行的歌曲中,有哪些在近7天播放超过一千万的"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"内容库近20天访问次数\"]",
|
||||
"currentQuestion": "按部门看一下",
|
||||
"rewritingCurrentQuestion": "内容库近20天按部门的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"内容库近20天访问次数\",\"按部门看一下\"]",
|
||||
"currentQuestion": "按模块看一下",
|
||||
"rewritingCurrentQuestion": "内容库近20天按模块的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"内容库近20天访问次数\",\"按部门看一下\",\"按模块看一下\"]",
|
||||
"currentQuestion": "看一下技术部的 (补充信息:’'技术部'‘是一个’部门‘)",
|
||||
"rewritingCurrentQuestion": "技术部在内容库近20天的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"内容库近20天访问次数\",\"按部门看一下\",\"按模块看一下\",\"看一下技术部的 (补充信息:’'技术部'‘是一个’部门‘)\"]",
|
||||
"currentQuestion": "看一下产品部的 (补充信息:’'产品部'‘是一个’部门‘)",
|
||||
"rewritingCurrentQuestion": "产品部在内容库近20天的访问次数"
|
||||
},
|
||||
{
|
||||
"contextualQuestions": "[\"内容库近20天访问次数\",\"按部门看一下\",\"按模块看一下\",\"看一下技术部的 (补充信息:’'技术部'‘是一个’部门‘)\",\"看一下产品部的 (补充信息:’'产品部'‘是一个’部门‘)\"]",
|
||||
"currentQuestion": "对比一下技术部、产品部(补充信息:'技术部'、‘产品部’分别是一个’部门‘)",
|
||||
"rewritingCurrentQuestion": "对比一下技术部、产品部在内容库近20天的访问次数"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user