1 Commits

Author SHA1 Message Date
jerryjzhang
71feb6c4eb [feature](headless)Add request user to data events.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-10-21 23:28:42 +08:00
32 changed files with 100 additions and 284 deletions

View File

@@ -15,6 +15,4 @@ public class UserReq {
@NotBlank(message = "password can not be null") @NotBlank(message = "password can not be null")
private String newPassword; private String newPassword;
private String role;
} }

View File

@@ -18,5 +18,4 @@ public class ChatExecuteReq {
private int parseId; private int parseId;
private String queryText; private String queryText;
private boolean saveAnswer; private boolean saveAnswer;
private boolean streamingResult;
} }

View File

@@ -32,7 +32,6 @@ import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.output.Response; import dev.langchain4j.model.output.Response;
import dev.langchain4j.provider.ModelProvider; import dev.langchain4j.provider.ModelProvider;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -172,6 +171,10 @@ public class NL2SQLParser implements ChatQueryParser {
return; return;
} }
// derive mapping result of current question and parsing result of last question.
ChatLayerService chatLayerService = ContextUtils.getBean(ChatLayerService.class);
MapResp currentMapResult = chatLayerService.map(queryNLReq);
List<QueryResp> historyQueries = List<QueryResp> historyQueries =
getHistoryQueries(parseContext.getRequest().getChatId(), 1); getHistoryQueries(parseContext.getRequest().getChatId(), 1);
if (historyQueries.isEmpty()) { if (historyQueries.isEmpty()) {
@@ -179,18 +182,12 @@ public class NL2SQLParser implements ChatQueryParser {
} }
QueryResp lastQuery = historyQueries.get(0); QueryResp lastQuery = historyQueries.get(0);
SemanticParseInfo lastParseInfo = lastQuery.getParseInfos().get(0); SemanticParseInfo lastParseInfo = lastQuery.getParseInfos().get(0);
String histSQL = lastParseInfo.getSqlInfo().getCorrectedS2SQL();
if (StringUtils.isBlank(histSQL)) // 优化性能,如果问答不是chat bi 则无需重写,因为数据都不全
return;
// derive mapping result of current question and parsing result of last question.
ChatLayerService chatLayerService = ContextUtils.getBean(ChatLayerService.class);
MapResp currentMapResult = chatLayerService.map(queryNLReq); // 优化性能 ,只有满足条件才mapping
Long dataId = lastParseInfo.getDataSetId(); Long dataId = lastParseInfo.getDataSetId();
String curtMapStr = String curtMapStr =
generateSchemaPrompt(currentMapResult.getMapInfo().getMatchedElements(dataId)); generateSchemaPrompt(currentMapResult.getMapInfo().getMatchedElements(dataId));
String histMapStr = generateSchemaPrompt(lastParseInfo.getElementMatches()); String histMapStr = generateSchemaPrompt(lastParseInfo.getElementMatches());
String histSQL = lastParseInfo.getSqlInfo().getCorrectedS2SQL();
Map<String, Object> variables = new HashMap<>(); Map<String, Object> variables = new HashMap<>();
variables.put("current_question", currentMapResult.getQueryText()); variables.put("current_question", currentMapResult.getQueryText());

View File

@@ -1,20 +1,13 @@
package com.tencent.supersonic.chat.server.processor.execute; package com.tencent.supersonic.chat.server.processor.execute;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult; import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.agent.Agent; import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
import com.tencent.supersonic.chat.server.pojo.ExecuteContext; import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
import com.tencent.supersonic.common.pojo.ChatApp; import com.tencent.supersonic.common.pojo.ChatApp;
import com.tencent.supersonic.common.pojo.enums.AppModule; import com.tencent.supersonic.common.pojo.enums.AppModule;
import com.tencent.supersonic.common.util.ChatAppManager; import com.tencent.supersonic.common.util.ChatAppManager;
import com.tencent.supersonic.common.util.ContextUtils;
import dev.langchain4j.data.message.AiMessage; import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.StreamingResponseHandler;
import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.input.Prompt; import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate; import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.output.Response; import dev.langchain4j.model.output.Response;
@@ -31,10 +24,8 @@ import java.util.Objects;
* DataInterpretProcessor interprets query result to make it more readable to the users. * DataInterpretProcessor interprets query result to make it more readable to the users.
*/ */
public class DataInterpretProcessor implements ExecuteResultProcessor { public class DataInterpretProcessor implements ExecuteResultProcessor {
public static String tip = "AI 回答中...\r\n";
private static final Logger keyPipelineLog = LoggerFactory.getLogger("keyPipeline");
private static Map<Long, StringBuffer> resultCache = new HashMap<>(); private static final Logger keyPipelineLog = LoggerFactory.getLogger("keyPipeline");
public static final String APP_KEY = "DATA_INTERPRETER"; public static final String APP_KEY = "DATA_INTERPRETER";
private static final String INSTRUCTION = "" private static final String INSTRUCTION = ""
@@ -50,16 +41,6 @@ public class DataInterpretProcessor implements ExecuteResultProcessor {
.appModule(AppModule.CHAT).description("通过大模型对结果数据做提炼总结").enable(false).build()); .appModule(AppModule.CHAT).description("通过大模型对结果数据做提炼总结").enable(false).build());
} }
public static String getTextSummary(Long queryId) {
if (resultCache.get(queryId) != null) {
return resultCache.get(queryId).toString();
}
return "";
}
public static Map<Long, StringBuffer> getResultCache() {
return resultCache;
}
@Override @Override
public boolean accept(ExecuteContext executeContext) { public boolean accept(ExecuteContext executeContext) {
@@ -90,49 +71,14 @@ public class DataInterpretProcessor implements ExecuteResultProcessor {
variable.put("data", queryResult.getTextResult()); variable.put("data", queryResult.getTextResult());
Prompt prompt = PromptTemplate.from(chatApp.getPrompt()).apply(variable); Prompt prompt = PromptTemplate.from(chatApp.getPrompt()).apply(variable);
if (executeContext.getRequest().isStreamingResult()) { ChatLanguageModel chatLanguageModel =
StreamingChatLanguageModel chatLanguageModel = ModelProvider.getChatModel(chatApp.getChatModelConfig());
ModelProvider.getChatStreamingModel(chatApp.getChatModelConfig()); Response<AiMessage> response = chatLanguageModel.generate(prompt.toUserMessage());
final Long queryId = executeContext.getRequest().getQueryId(); String anwser = response.content().text();
resultCache.put(queryId, new StringBuffer(tip)); keyPipelineLog.info("DataInterpretProcessor modelReq:\n{} \nmodelResp:\n{}", prompt.text(),
chatLanguageModel.generate(prompt.toUserMessage(), anwser);
new StreamingResponseHandler<AiMessage>() { if (StringUtils.isNotBlank(anwser)) {
@Override queryResult.setTextSummary(anwser);
public void onNext(String token) {
resultCache.get(queryId).append(token);
}
@Override
public void onComplete(Response<AiMessage> response) {
ChatQueryRepository chatQueryRepository =
ContextUtils.getBean(ChatQueryRepository.class);
ChatQueryDO chatQueryDO = chatQueryRepository.getChatQueryDO(queryId);
JSONObject queryResult = JSON.parseObject(chatQueryDO.getQueryResult());
queryResult.put("textSummary",
resultCache.get(queryId).toString().substring(tip.length()));
chatQueryDO.setQueryResult(queryResult.toJSONString());
chatQueryRepository.updateChatQuery(chatQueryDO);
resultCache.remove(queryId);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
resultCache.remove(queryId);
}
});
} else {
ChatLanguageModel chatLanguageModel =
ModelProvider.getChatModel(chatApp.getChatModelConfig());
Response<AiMessage> response = chatLanguageModel.generate(prompt.toUserMessage());
String anwser = response.content().text();
keyPipelineLog.info("DataInterpretProcessor modelReq:\n{} \nmodelResp:\n{}",
prompt.text(), anwser);
if (StringUtils.isNotBlank(anwser)) {
queryResult.setTextSummary(anwser);
}
} }
} }
} }

View File

@@ -5,7 +5,6 @@ import com.tencent.supersonic.chat.api.pojo.request.ChatExecuteReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq; import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatQueryDataReq; import com.tencent.supersonic.chat.api.pojo.request.ChatQueryDataReq;
import com.tencent.supersonic.chat.api.pojo.response.ChatParseResp; import com.tencent.supersonic.chat.api.pojo.response.ChatParseResp;
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.service.ChatQueryService; import com.tencent.supersonic.chat.server.service.ChatQueryService;
import com.tencent.supersonic.common.pojo.User; import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException; import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
@@ -51,14 +50,6 @@ public class ChatQueryController {
return chatQueryService.execute(chatExecuteReq); return chatQueryService.execute(chatExecuteReq);
} }
@PostMapping("getExecuteSummary")
public Object getExecuteSummary(@RequestBody ChatExecuteReq chatExecuteReq,
HttpServletRequest request, HttpServletResponse response) {
chatExecuteReq.setUser(UserHolder.findUser(request, response));
QueryResult res = chatQueryService.getTextSummary(chatExecuteReq);
return res;
}
@PostMapping("/") @PostMapping("/")
public Object query(@RequestBody ChatParseReq chatParseReq, HttpServletRequest request, public Object query(@RequestBody ChatParseReq chatParseReq, HttpServletRequest request,
HttpServletResponse response) throws Exception { HttpServletResponse response) throws Exception {

View File

@@ -35,8 +35,6 @@ public interface ChatManageService {
QueryResp getChatQuery(Long queryId); QueryResp getChatQuery(Long queryId);
ChatQueryDO getChatQueryDO(Long queryId);
List<QueryResp> getChatQueries(Integer chatId); List<QueryResp> getChatQueries(Integer chatId);
ShowCaseResp queryShowCase(PageQueryInfoReq pageQueryInfoReq, int agentId); ShowCaseResp queryShowCase(PageQueryInfoReq pageQueryInfoReq, int agentId);

View File

@@ -19,8 +19,6 @@ public interface ChatQueryService {
QueryResult execute(ChatExecuteReq chatExecuteReq) throws Exception; QueryResult execute(ChatExecuteReq chatExecuteReq) throws Exception;
QueryResult getTextSummary(ChatExecuteReq chatExecuteReq);
QueryResult parseAndExecute(ChatParseReq chatParseReq); QueryResult parseAndExecute(ChatParseReq chatParseReq);
Object queryData(ChatQueryDataReq chatQueryDataReq, User user) throws Exception; Object queryData(ChatQueryDataReq chatQueryDataReq, User user) throws Exception;

View File

@@ -123,11 +123,6 @@ public class ChatManageServiceImpl implements ChatManageService {
return chatQueryRepository.getChatQuery(queryId); return chatQueryRepository.getChatQuery(queryId);
} }
@Override
public ChatQueryDO getChatQueryDO(Long queryId) {
return chatQueryRepository.getChatQueryDO(queryId);
}
@Override @Override
public List<QueryResp> getChatQueries(Integer chatId) { public List<QueryResp> getChatQueries(Integer chatId) {
List<QueryResp> queries = chatQueryRepository.getChatQueries(chatId); List<QueryResp> queries = chatQueryRepository.getChatQueries(chatId);

View File

@@ -1,6 +1,5 @@
package com.tencent.supersonic.chat.server.service.impl; package com.tencent.supersonic.chat.server.service.impl;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.tencent.supersonic.chat.api.pojo.request.ChatExecuteReq; import com.tencent.supersonic.chat.api.pojo.request.ChatExecuteReq;
import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq; import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
@@ -10,10 +9,8 @@ import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
import com.tencent.supersonic.chat.server.agent.Agent; import com.tencent.supersonic.chat.server.agent.Agent;
import com.tencent.supersonic.chat.server.executor.ChatQueryExecutor; import com.tencent.supersonic.chat.server.executor.ChatQueryExecutor;
import com.tencent.supersonic.chat.server.parser.ChatQueryParser; import com.tencent.supersonic.chat.server.parser.ChatQueryParser;
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
import com.tencent.supersonic.chat.server.pojo.ExecuteContext; import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
import com.tencent.supersonic.chat.server.pojo.ParseContext; import com.tencent.supersonic.chat.server.pojo.ParseContext;
import com.tencent.supersonic.chat.server.processor.execute.DataInterpretProcessor;
import com.tencent.supersonic.chat.server.processor.execute.ExecuteResultProcessor; import com.tencent.supersonic.chat.server.processor.execute.ExecuteResultProcessor;
import com.tencent.supersonic.chat.server.processor.parse.ParseResultProcessor; import com.tencent.supersonic.chat.server.processor.parse.ParseResultProcessor;
import com.tencent.supersonic.chat.server.service.AgentService; import com.tencent.supersonic.chat.server.service.AgentService;
@@ -21,11 +18,7 @@ import com.tencent.supersonic.chat.server.service.ChatManageService;
import com.tencent.supersonic.chat.server.service.ChatQueryService; import com.tencent.supersonic.chat.server.service.ChatQueryService;
import com.tencent.supersonic.chat.server.util.ComponentFactory; import com.tencent.supersonic.chat.server.util.ComponentFactory;
import com.tencent.supersonic.chat.server.util.QueryReqConverter; import com.tencent.supersonic.chat.server.util.QueryReqConverter;
import com.tencent.supersonic.common.jsqlparser.FieldExpression; import com.tencent.supersonic.common.jsqlparser.*;
import com.tencent.supersonic.common.jsqlparser.SqlAddHelper;
import com.tencent.supersonic.common.jsqlparser.SqlRemoveHelper;
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.common.pojo.User; import com.tencent.supersonic.common.pojo.User;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum; import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.util.DateUtils; import com.tencent.supersonic.common.util.DateUtils;
@@ -51,11 +44,7 @@ import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue; import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ComparisonOperator; import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -64,14 +53,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j @Slf4j
@@ -128,8 +110,6 @@ public class ChatQueryServiceImpl implements ChatQueryService {
} }
if (!parseContext.needFeedback()) { if (!parseContext.needFeedback()) {
parseContext.getResponse().getParseTimeCost().setParseTime(System.currentTimeMillis()
- parseContext.getResponse().getParseTimeCost().getParseStartTime());
chatManageService.batchAddParse(chatParseReq, parseContext.getResponse()); chatManageService.batchAddParse(chatParseReq, parseContext.getResponse());
chatManageService.updateParseCostTime(parseContext.getResponse()); chatManageService.updateParseCostTime(parseContext.getResponse());
} }
@@ -163,21 +143,6 @@ public class ChatQueryServiceImpl implements ChatQueryService {
return queryResult; return queryResult;
} }
@Override
public QueryResult getTextSummary(ChatExecuteReq chatExecuteReq) {
String text = DataInterpretProcessor.getTextSummary(chatExecuteReq.getQueryId());
if (StringUtils.isNotBlank(text)) {
QueryResult res = new QueryResult();
res.setTextSummary(text);
res.setQueryId(chatExecuteReq.getQueryId());
return res;
} else {
ChatQueryDO chatQueryDo = chatManageService.getChatQueryDO(chatExecuteReq.getQueryId());
QueryResult res = JSON.parseObject(chatQueryDo.getQueryResult(), QueryResult.class);
return res;
}
}
@Override @Override
public QueryResult parseAndExecute(ChatParseReq chatParseReq) { public QueryResult parseAndExecute(ChatParseReq chatParseReq) {
ChatParseResp parseResp = parse(chatParseReq); ChatParseResp parseResp = parse(chatParseReq);

View File

@@ -108,7 +108,6 @@ public class PluginServiceImpl implements PluginService {
if (StringUtils.isNotBlank(pluginQueryReq.getCreatedBy())) { if (StringUtils.isNotBlank(pluginQueryReq.getCreatedBy())) {
queryWrapper.lambda().eq(PluginDO::getCreatedBy, pluginQueryReq.getCreatedBy()); queryWrapper.lambda().eq(PluginDO::getCreatedBy, pluginQueryReq.getCreatedBy());
} }
queryWrapper.orderByAsc("name");
List<PluginDO> pluginDOS = pluginRepository.query(queryWrapper); List<PluginDO> pluginDOS = pluginRepository.query(queryWrapper);
if (StringUtils.isNotBlank(pluginQueryReq.getPattern())) { if (StringUtils.isNotBlank(pluginQueryReq.getPattern())) {
pluginDOS = pluginDOS.stream() pluginDOS = pluginDOS.stream()

View File

@@ -15,8 +15,7 @@ public class DataEvent extends ApplicationEvent {
private final String userName; private final String userName;
public DataEvent(Object source, List<DataItem> dataItems, EventType eventType, public DataEvent(Object source, List<DataItem> dataItems, EventType eventType, String userName) {
String userName) {
super(source); super(source);
this.dataItems = dataItems; this.dataItems = dataItems;
this.eventType = eventType; this.eventType = eventType;

View File

@@ -15,5 +15,5 @@ public interface ChatModelService {
ChatModel updateChatModel(ChatModel chatModel, User user); ChatModel updateChatModel(ChatModel chatModel, User user);
void deleteChatModel(Integer id, User user); void deleteChatModel(Integer id);
} }

View File

@@ -79,12 +79,7 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
} }
@Override @Override
public void deleteChatModel(Integer id, User user) { public void deleteChatModel(Integer id) {
ChatModel chatModel = getChatModel(id);
if (!checkAdminPermission(user, chatModel)) {
throw new RuntimeException("没有权限删除该大模型");
}
removeById(id); removeById(id);
} }
@@ -108,13 +103,4 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
chatModelDO.setConfig(JsonUtil.toString(chatModel.getConfig())); chatModelDO.setConfig(JsonUtil.toString(chatModel.getConfig()));
return chatModelDO; return chatModelDO;
} }
private boolean checkAdminPermission(User user, ChatModel chatModel) {
String admin = chatModel.getAdmin();
if (user.isSuperAdmin()) {
return true;
}
return admin != null && admin.equals(user.getName())
|| chatModel.getCreatedBy().equals(user.getName());
}
} }

View File

@@ -16,7 +16,6 @@ import org.springframework.util.CollectionUtils;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Service @Service
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfigDO> public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfigDO>
@@ -39,8 +38,8 @@ public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, Sys
return systemConfigDb; return systemConfigDb;
} }
private SystemConfig getSystemConfigFromDB() { // 加上id ,如果有多条记录,会出错 private SystemConfig getSystemConfigFromDB() {
List<SystemConfigDO> list = this.lambdaQuery().eq(SystemConfigDO::getId, 1).list(); List<SystemConfigDO> list = list();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
SystemConfig systemConfig = new SystemConfig(); SystemConfig systemConfig = new SystemConfig();
systemConfig.setId(1); systemConfig.setId(1);

View File

@@ -7,7 +7,6 @@ import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.dify.DifyAiChatModel; import dev.langchain4j.model.dify.DifyAiChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel; import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -26,11 +25,6 @@ public class DifyModelFactory implements ModelFactory, InitializingBean {
.modelName(modelConfig.getModelName()).timeOut(modelConfig.getTimeOut()).build(); .modelName(modelConfig.getModelName()).timeOut(modelConfig.getTimeOut()).build();
} }
@Override
public OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig) {
throw new RuntimeException("待开发");
}
@Override @Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) { public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return OpenAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl()) return OpenAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())

View File

@@ -5,7 +5,6 @@ import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.S2OnnxEmbeddingModel; import dev.langchain4j.model.embedding.S2OnnxEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -36,11 +35,6 @@ public class InMemoryModelFactory implements ModelFactory, InitializingBean {
return EmbeddingModelConstant.BGE_SMALL_ZH_MODEL; return EmbeddingModelConstant.BGE_SMALL_ZH_MODEL;
} }
@Override
public OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig) {
throw new RuntimeException("待开发");
}
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
ModelProvider.add(PROVIDER, this); ModelProvider.add(PROVIDER, this);

View File

@@ -6,7 +6,6 @@ import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.localai.LocalAiChatModel; import dev.langchain4j.model.localai.LocalAiChatModel;
import dev.langchain4j.model.localai.LocalAiEmbeddingModel; import dev.langchain4j.model.localai.LocalAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -28,11 +27,6 @@ public class LocalAiModelFactory implements ModelFactory, InitializingBean {
.build(); .build();
} }
@Override
public OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig) {
throw new RuntimeException("待开发");
}
@Override @Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel) { public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel) {
return LocalAiEmbeddingModel.builder().baseUrl(embeddingModel.getBaseUrl()) return LocalAiEmbeddingModel.builder().baseUrl(embeddingModel.getBaseUrl())

View File

@@ -4,12 +4,9 @@ import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig; import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
public interface ModelFactory { public interface ModelFactory {
ChatLanguageModel createChatModel(ChatModelConfig modelConfig); ChatLanguageModel createChatModel(ChatModelConfig modelConfig);
OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig);
EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel); EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel);
} }

View File

@@ -5,9 +5,7 @@ import com.tencent.supersonic.common.pojo.ChatModelConfig;
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig; import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
import com.tencent.supersonic.common.util.ContextUtils; import com.tencent.supersonic.common.util.ContextUtils;
import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
@@ -43,20 +41,6 @@ public class ModelProvider {
"Unsupported ChatLanguageModel provider: " + modelConfig.getProvider()); "Unsupported ChatLanguageModel provider: " + modelConfig.getProvider());
} }
public static StreamingChatLanguageModel getChatStreamingModel(ChatModelConfig modelConfig) {
if (modelConfig == null || StringUtils.isBlank(modelConfig.getProvider())
|| StringUtils.isBlank(modelConfig.getBaseUrl())) {
modelConfig = DEMO_CHAT_MODEL;
}
ModelFactory modelFactory = factories.get(modelConfig.getProvider().toUpperCase());
if (modelFactory != null) {
return modelFactory.createChatStreamingModel(modelConfig);
}
throw new RuntimeException(
"Unsupported ChatLanguageModel provider: " + modelConfig.getProvider());
}
public static EmbeddingModel getEmbeddingModel() { public static EmbeddingModel getEmbeddingModel() {
return getEmbeddingModel(null); return getEmbeddingModel(null);
} }

View File

@@ -6,7 +6,6 @@ import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.ollama.OllamaChatModel; import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.ollama.OllamaEmbeddingModel; import dev.langchain4j.model.ollama.OllamaEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -29,11 +28,6 @@ public class OllamaModelFactory implements ModelFactory, InitializingBean {
.logResponses(modelConfig.getLogResponses()).build(); .logResponses(modelConfig.getLogResponses()).build();
} }
@Override
public OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig) {
throw new RuntimeException("待开发");
}
@Override @Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) { public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
return OllamaEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl()) return OllamaEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())

View File

@@ -6,7 +6,6 @@ import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel; import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -38,16 +37,6 @@ public class OpenAiModelFactory implements ModelFactory, InitializingBean {
return openAiChatModelBuilder.build(); return openAiChatModelBuilder.build();
} }
@Override
public OpenAiStreamingChatModel createChatStreamingModel(ChatModelConfig modelConfig) {
return OpenAiStreamingChatModel.builder().baseUrl(modelConfig.getBaseUrl())
.modelName(modelConfig.getModelName()).apiKey(modelConfig.keyDecrypt())
.temperature(modelConfig.getTemperature()).topP(modelConfig.getTopP())
.timeout(Duration.ofSeconds(modelConfig.getTimeOut()))
.logRequests(modelConfig.getLogRequests())
.logResponses(modelConfig.getLogResponses()).build();
}
@Override @Override
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel) { public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModel) {
return OpenAiEmbeddingModel.builder().baseUrl(embeddingModel.getBaseUrl()) return OpenAiEmbeddingModel.builder().baseUrl(embeddingModel.getBaseUrl())

View File

@@ -42,6 +42,6 @@ public class TextSegmentConvert {
if (Objects.isNull(textSegment) || Objects.isNull(textSegment.metadata())) { if (Objects.isNull(textSegment) || Objects.isNull(textSegment.metadata())) {
return null; return null;
} }
return textSegment.metadata().getString(QUERY_ID); return textSegment.metadata().get(QUERY_ID);
} }
} }

View File

@@ -117,17 +117,9 @@ public class MultiCustomDictionary extends DynamicCustomDictionary {
dictWord.setAlias(word.toLowerCase()); dictWord.setAlias(word.toLowerCase());
String[] split = nature.split(DictWordType.NATURE_SPILT); String[] split = nature.split(DictWordType.NATURE_SPILT);
if (split.length >= 2) { if (split.length >= 2) {
try { Long dimId = Long.parseLong(
Long dimId = Long.parseLong( nature.split(DictWordType.NATURE_SPILT)[split.length - 1]);
nature.split(DictWordType.NATURE_SPILT)[split.length - 1]); KnowledgeBaseService.addDimValueAlias(dimId, Arrays.asList(dictWord));
KnowledgeBaseService.addDimValueAlias(dimId,
Arrays.asList(dictWord));
} catch (NumberFormatException e) {
logger.warning(path + " : 非标准文件不存入KnowledgeBaseService");
return true;
}
} }
} }
} }

View File

@@ -46,10 +46,8 @@ public class ChatModelController {
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public boolean deleteModel(@PathVariable("id") Integer id, public boolean deleteModel(@PathVariable("id") Integer id) {
HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { chatModelService.deleteChatModel(id);
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
chatModelService.deleteChatModel(id, user);
return true; return true;
} }

View File

@@ -64,10 +64,8 @@ public class DatabaseController {
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public boolean deleteDatabase(@PathVariable("id") Long id, HttpServletRequest request, public boolean deleteDatabase(@PathVariable("id") Long id) {
HttpServletResponse response) { databaseService.deleteDatabase(id);
User user = UserHolder.findUser(request, response);
databaseService.deleteDatabase(id, user);
return true; return true;
} }

View File

@@ -34,7 +34,7 @@ public interface DatabaseService {
List<DatabaseResp> getDatabaseList(User user); List<DatabaseResp> getDatabaseList(User user);
void deleteDatabase(Long databaseId, User user); void deleteDatabase(Long databaseId);
List<String> getCatalogs(Long id) throws SQLException; List<String> getCatalogs(Long id) throws SQLException;

View File

@@ -138,12 +138,7 @@ public class DatabaseServiceImpl extends ServiceImpl<DatabaseDOMapper, DatabaseD
} }
@Override @Override
public void deleteDatabase(Long databaseId, User user) { public void deleteDatabase(Long databaseId) {
DatabaseResp databaseResp = getDatabase(databaseId);
if (!checkAdminPermission(user, databaseResp)) {
throw new RuntimeException("没有权限删除该数据库");
}
ModelFilter modelFilter = new ModelFilter(); ModelFilter modelFilter = new ModelFilter();
modelFilter.setDatabaseId(databaseId); modelFilter.setDatabaseId(databaseId);
modelFilter.setIncludesDetail(false); modelFilter.setIncludesDetail(false);

View File

@@ -81,8 +81,7 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
public DimensionServiceImpl(DimensionRepository dimensionRepository, ModelService modelService, public DimensionServiceImpl(DimensionRepository dimensionRepository, ModelService modelService,
AliasGenerateHelper aliasGenerateHelper, DatabaseService databaseService, AliasGenerateHelper aliasGenerateHelper, DatabaseService databaseService,
ModelRelaService modelRelaService, DataSetService dataSetService, ModelRelaService modelRelaService, DataSetService dataSetService, ApplicationEventPublisher eventPublisher) {
ApplicationEventPublisher eventPublisher) {
this.modelService = modelService; this.modelService = modelService;
this.dimensionRepository = dimensionRepository; this.dimensionRepository = dimensionRepository;
this.aliasGenerateHelper = aliasGenerateHelper; this.aliasGenerateHelper = aliasGenerateHelper;
@@ -116,11 +115,29 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
.collect(Collectors.toMap(DimensionResp::getBizName, a -> a, (k1, k2) -> k1)); .collect(Collectors.toMap(DimensionResp::getBizName, a -> a, (k1, k2) -> k1));
List<DimensionReq> dimensionToInsert = Lists.newArrayList(); List<DimensionReq> dimensionToInsert = Lists.newArrayList();
List<DimensionReq> dimensionToUpdate = Lists.newArrayList();
List<Long> dimensionToDelete = Lists.newArrayList();
// look for which dimension need to insert, update, delete // look for which dimension need to insert, update, delete
dimensionReqs.forEach(dimension -> { dimensionReqs.stream().forEach(dimension -> {
if (!bizNameMap.containsKey(dimension.getBizName())) { if (!bizNameMap.containsKey(dimension.getBizName())) {
dimensionToInsert.add(dimension); dimensionToInsert.add(dimension);
} else {
DimensionResp dimensionRespByBizName = bizNameMap.get(dimension.getBizName());
if (null != dimensionRespByBizName && isChange(dimension, dimensionRespByBizName)) {
dimension.setId(dimensionRespByBizName.getId());
dimension.updatedBy(user.getName());
dimensionToUpdate.add(dimension);
}
}
});
// the bizNames from alter dimensions
List<String> bizNames =
dimensionReqs.stream().map(DimensionReq::getBizName).collect(Collectors.toList());
bizNameMap.keySet().forEach(bizNameInDb -> {
if (!bizNames.contains(bizNameInDb)) {
dimensionToDelete.add(bizNameMap.get(bizNameInDb).getId());
} }
}); });
@@ -129,6 +146,16 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
createDimensionBatch(dimensionToInsert, user); createDimensionBatch(dimensionToInsert, user);
} }
// update
if (!CollectionUtils.isEmpty(dimensionToUpdate)) {
updateDimensionBatch(dimensionToUpdate, user);
}
// delete
if (!CollectionUtils.isEmpty(dimensionToDelete)) {
deleteDimensionBatch(dimensionToDelete, user);
}
} }
@Override @Override
@@ -516,16 +543,14 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
.domainId(dimensionResp.getDomainId().toString()).type(TypeEnums.DIMENSION).build(); .domainId(dimensionResp.getDomainId().toString()).type(TypeEnums.DIMENSION).build();
} }
private DataEvent getDataEvent(List<DimensionDO> dimensionDOS, EventType eventType, private DataEvent getDataEvent(List<DimensionDO> dimensionDOS, EventType eventType, String userName) {
String userName) {
List<DataItem> dataItems = dimensionDOS.stream().map(this::getDataItem) List<DataItem> dataItems = dimensionDOS.stream().map(this::getDataItem)
.filter(Objects::nonNull).collect(Collectors.toList()); .filter(Objects::nonNull).collect(Collectors.toList());
return new DataEvent(this, dataItems, eventType, userName); return new DataEvent(this, dataItems, eventType, userName);
} }
private void sendEvent(DataItem dataItem, EventType eventType, String userName) { private void sendEvent(DataItem dataItem, EventType eventType, String userName) {
eventPublisher.publishEvent( eventPublisher.publishEvent(new DataEvent(this, Lists.newArrayList(dataItem), eventType, userName));
new DataEvent(this, Lists.newArrayList(dataItem), eventType, userName));
} }
private boolean isChange(DimensionReq dimensionReq, DimensionResp dimensionResp) { private boolean isChange(DimensionReq dimensionReq, DimensionResp dimensionResp) {

View File

@@ -157,9 +157,28 @@ public class MetricServiceImpl extends ServiceImpl<MetricDOMapper, MetricDO>
.collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1)); .collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1));
List<MetricReq> metricToInsert = Lists.newArrayList(); List<MetricReq> metricToInsert = Lists.newArrayList();
metricReqs.forEach(metric -> { List<MetricReq> metricToUpdate = Lists.newArrayList();
List<Long> metricToDelete = Lists.newArrayList();
metricReqs.stream().forEach(metric -> {
if (!bizNameMap.containsKey(metric.getBizName())) { if (!bizNameMap.containsKey(metric.getBizName())) {
metricToInsert.add(metric); metricToInsert.add(metric);
} else {
MetricResp metricRespByBizName = bizNameMap.get(metric.getBizName());
if (null != metricRespByBizName && isChange(metric, metricRespByBizName)) {
metric.setId(metricRespByBizName.getId());
metric.updatedBy(user.getName());
metricToUpdate.add(metric);
}
}
});
// the bizNames from alter dimensions
List<String> bizNames =
metricReqs.stream().map(MetricReq::getBizName).collect(Collectors.toList());
bizNameMap.keySet().forEach(bizNameInDb -> {
if (!bizNames.contains(bizNameInDb)) {
metricToDelete.add(bizNameMap.get(bizNameInDb).getId());
} }
}); });
@@ -168,6 +187,16 @@ public class MetricServiceImpl extends ServiceImpl<MetricDOMapper, MetricDO>
createMetricBatch(metricToInsert, user); createMetricBatch(metricToInsert, user);
} }
// update
if (!CollectionUtils.isEmpty(metricToUpdate)) {
updateMetricBatch(metricToUpdate, user);
}
// delete
if (!CollectionUtils.isEmpty(metricToDelete)) {
deleteMetricBatch(metricToDelete, user);
}
} }
@Override @Override
@@ -713,8 +742,7 @@ public class MetricServiceImpl extends ServiceImpl<MetricDOMapper, MetricDO>
} }
private void sendEvent(DataItem dataItem, EventType eventType, User user) { private void sendEvent(DataItem dataItem, EventType eventType, User user) {
eventPublisher.publishEvent( eventPublisher.publishEvent(new DataEvent(this, Lists.newArrayList(dataItem), eventType, user.getName()));
new DataEvent(this, Lists.newArrayList(dataItem), eventType, user.getName()));
} }
private DataItem getDataItem(MetricDO metricDO) { private DataItem getDataItem(MetricDO metricDO) {

View File

@@ -672,8 +672,7 @@ public class ModelServiceImpl implements ModelService {
private void sendEvent(ModelDO modelDO, EventType eventType, User user) { private void sendEvent(ModelDO modelDO, EventType eventType, User user) {
DataItem dataItem = getDataItem(modelDO); DataItem dataItem = getDataItem(modelDO);
eventPublisher.publishEvent( eventPublisher.publishEvent(new DataEvent(this, Lists.newArrayList(dataItem), eventType, user.getName()));
new DataEvent(this, Lists.newArrayList(dataItem), eventType, user.getName()));
} }
private DataItem getDataItem(ModelDO modelDO) { private DataItem getDataItem(ModelDO modelDO) {

View File

@@ -10,14 +10,7 @@ import {
SimilarQuestionType, SimilarQuestionType,
} from '../../common/type'; } from '../../common/type';
import { createContext, useEffect, useRef, useState } from 'react'; import { createContext, useEffect, useRef, useState } from 'react';
import { import { chatExecute, chatParse, queryData, deleteQuery, switchEntity } from '../../service';
chatExecute,
chatParse,
queryData,
deleteQuery,
switchEntity,
getExecuteSummary,
} from '../../service';
import { PARSE_ERROR_TIP, PREFIX_CLS, SEARCH_EXCEPTION_TIP } from '../../common/constants'; import { PARSE_ERROR_TIP, PREFIX_CLS, SEARCH_EXCEPTION_TIP } from '../../common/constants';
import { message, Spin } from 'antd'; import { message, Spin } from 'antd';
import IconFont from '../IconFont'; import IconFont from '../IconFont';
@@ -176,7 +169,7 @@ const ChatItem: React.FC<Props> = ({
setExecuteLoading(true); setExecuteLoading(true);
} }
try { try {
const res: any = await chatExecute(msg, conversationId!, parseInfoValue, agentId, true); const res: any = await chatExecute(msg, conversationId!, parseInfoValue, agentId);
const valid = updateData(res); const valid = updateData(res);
onMsgDataLoaded?.( onMsgDataLoaded?.(
{ {
@@ -187,20 +180,6 @@ const ChatItem: React.FC<Props> = ({
valid, valid,
isRefresh isRefresh
); );
const queryId = parseInfoValue.queryId; // 伪流式 大模型输出
if (queryId != undefined && res.data.queryState != 'INVALID') {
const getSummary = async (data: any, queryId: number) => {
const res2: any = await getExecuteSummary(queryId);
if (res2.data.queryMode == null) {
res2.data = { ...data, textSummary: res2.data.textSummary };
setData(res2.data);
setTimeout(() => getSummary(data, queryId), 500);
} else {
setData(res2.data);
}
};
setTimeout(() => getSummary(res.data, queryId), 500);
}
} catch (e) { } catch (e) {
const tip = SEARCH_EXCEPTION_TIP; const tip = SEARCH_EXCEPTION_TIP;
setExecuteTip(SEARCH_EXCEPTION_TIP); setExecuteTip(SEARCH_EXCEPTION_TIP);
@@ -444,10 +423,6 @@ const ChatItem: React.FC<Props> = ({
return result; return result;
}, {}); }, {});
}); });
if (exportData.length === 0) {
message.error('该条消息暂不支持该操作');
return;
}
exportCsvFile(exportData); exportCsvFile(exportData);
} }
}; };

View File

@@ -79,8 +79,7 @@ export function chatExecute(
queryText: string, queryText: string,
chatId: number, chatId: number,
parseInfo: ChatContextType, parseInfo: ChatContextType,
agentId?: number, agentId?: number
streamingResult?:boolean
) { ) {
return axios.post<MsgDataType>(`${prefix}/chat/query/execute`, { return axios.post<MsgDataType>(`${prefix}/chat/query/execute`, {
queryText, queryText,
@@ -88,15 +87,6 @@ export function chatExecute(
chatId: chatId || DEFAULT_CHAT_ID, chatId: chatId || DEFAULT_CHAT_ID,
queryId: parseInfo.queryId, queryId: parseInfo.queryId,
parseId: parseInfo.id, parseId: parseInfo.id,
streamingResult:streamingResult
});
}
export function getExecuteSummary(
queryId: number
) {
return axios.post<MsgDataType>(`${prefix}/chat/query/getExecuteSummary`, {
queryId: queryId,
}); });
} }