Skip to content

Commit 04b1edb

Browse files
authored
(improvement)(chat|common|headless|webapp) 结果分析,改写伪流式输出,加快响应速度 (#2395)
1 parent 9857256 commit 04b1edb

20 files changed

Lines changed: 217 additions & 23 deletions

File tree

chat/api/src/main/java/com/tencent/supersonic/chat/api/pojo/request/ChatExecuteReq.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ public class ChatExecuteReq {
1818
private int parseId;
1919
private String queryText;
2020
private boolean saveAnswer;
21+
private boolean streamingResult;
2122
}

chat/server/src/main/java/com/tencent/supersonic/chat/server/parser/NL2SQLParser.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import dev.langchain4j.model.output.Response;
3333
import dev.langchain4j.provider.ModelProvider;
3434
import lombok.extern.slf4j.Slf4j;
35+
import org.apache.commons.lang3.StringUtils;
3536
import org.slf4j.Logger;
3637
import org.slf4j.LoggerFactory;
3738

@@ -171,23 +172,25 @@ private void rewriteMultiTurn(ParseContext parseContext, QueryNLReq queryNLReq)
171172
return;
172173
}
173174

174-
// derive mapping result of current question and parsing result of last question.
175-
ChatLayerService chatLayerService = ContextUtils.getBean(ChatLayerService.class);
176-
MapResp currentMapResult = chatLayerService.map(queryNLReq);
177-
178175
List<QueryResp> historyQueries =
179176
getHistoryQueries(parseContext.getRequest().getChatId(), 1);
180177
if (historyQueries.isEmpty()) {
181178
return;
182179
}
183180
QueryResp lastQuery = historyQueries.get(0);
184181
SemanticParseInfo lastParseInfo = lastQuery.getParseInfos().get(0);
185-
Long dataId = lastParseInfo.getDataSetId();
182+
String histSQL = lastParseInfo.getSqlInfo().getCorrectedS2SQL();
183+
if (StringUtils.isBlank(histSQL)) // 优化性能,如果问答不是chat bi 则无需重写,因为数据都不全
184+
return;
186185

186+
// derive mapping result of current question and parsing result of last question.
187+
ChatLayerService chatLayerService = ContextUtils.getBean(ChatLayerService.class);
188+
MapResp currentMapResult = chatLayerService.map(queryNLReq); // 优化性能 ,只有满足条件才mapping
189+
190+
Long dataId = lastParseInfo.getDataSetId();
187191
String curtMapStr =
188192
generateSchemaPrompt(currentMapResult.getMapInfo().getMatchedElements(dataId));
189193
String histMapStr = generateSchemaPrompt(lastParseInfo.getElementMatches());
190-
String histSQL = lastParseInfo.getSqlInfo().getCorrectedS2SQL();
191194

192195
Map<String, Object> variables = new HashMap<>();
193196
variables.put("current_question", currentMapResult.getQueryText());

chat/server/src/main/java/com/tencent/supersonic/chat/server/processor/execute/DataInterpretProcessor.java

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
package com.tencent.supersonic.chat.server.processor.execute;
22

3+
import com.alibaba.fastjson.JSON;
4+
import com.alibaba.fastjson.JSONObject;
35
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
46
import com.tencent.supersonic.chat.server.agent.Agent;
7+
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
8+
import com.tencent.supersonic.chat.server.persistence.repository.ChatQueryRepository;
59
import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
610
import com.tencent.supersonic.common.pojo.ChatApp;
711
import com.tencent.supersonic.common.pojo.enums.AppModule;
812
import com.tencent.supersonic.common.util.ChatAppManager;
13+
import com.tencent.supersonic.common.util.ContextUtils;
914
import dev.langchain4j.data.message.AiMessage;
15+
import dev.langchain4j.model.StreamingResponseHandler;
1016
import dev.langchain4j.model.chat.ChatLanguageModel;
17+
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
1118
import dev.langchain4j.model.input.Prompt;
1219
import dev.langchain4j.model.input.PromptTemplate;
1320
import dev.langchain4j.model.output.Response;
@@ -24,9 +31,11 @@
2431
* DataInterpretProcessor interprets query result to make it more readable to the users.
2532
*/
2633
public class DataInterpretProcessor implements ExecuteResultProcessor {
27-
34+
public static String tip = "AI 回答中...\r\n";
2835
private static final Logger keyPipelineLog = LoggerFactory.getLogger("keyPipeline");
2936

37+
private static Map<Long, StringBuffer> resultCache = new HashMap<>();
38+
3039
public static final String APP_KEY = "DATA_INTERPRETER";
3140
private static final String INSTRUCTION = ""
3241
+ "#Role: You are a data expert who communicates with business users everyday."
@@ -41,6 +50,16 @@ public DataInterpretProcessor() {
4150
.appModule(AppModule.CHAT).description("通过大模型对结果数据做提炼总结").enable(false).build());
4251
}
4352

53+
public static String getTextSummary(Long queryId) {
54+
if (resultCache.get(queryId) != null) {
55+
return resultCache.get(queryId).toString();
56+
}
57+
return "";
58+
}
59+
60+
public static Map<Long, StringBuffer> getResultCache() {
61+
return resultCache;
62+
}
4463

4564
@Override
4665
public boolean accept(ExecuteContext executeContext) {
@@ -71,14 +90,49 @@ public void process(ExecuteContext executeContext) {
7190
variable.put("data", queryResult.getTextResult());
7291

7392
Prompt prompt = PromptTemplate.from(chatApp.getPrompt()).apply(variable);
74-
ChatLanguageModel chatLanguageModel =
75-
ModelProvider.getChatModel(chatApp.getChatModelConfig());
76-
Response<AiMessage> response = chatLanguageModel.generate(prompt.toUserMessage());
77-
String anwser = response.content().text();
78-
keyPipelineLog.info("DataInterpretProcessor modelReq:\n{} \nmodelResp:\n{}", prompt.text(),
79-
anwser);
80-
if (StringUtils.isNotBlank(anwser)) {
81-
queryResult.setTextSummary(anwser);
93+
if (executeContext.getRequest().isStreamingResult()) {
94+
StreamingChatLanguageModel chatLanguageModel =
95+
ModelProvider.getChatStreamingModel(chatApp.getChatModelConfig());
96+
final Long queryId = executeContext.getRequest().getQueryId();
97+
resultCache.put(queryId, new StringBuffer(tip));
98+
chatLanguageModel.generate(prompt.toUserMessage(),
99+
new StreamingResponseHandler<AiMessage>() {
100+
@Override
101+
public void onNext(String token) {
102+
resultCache.get(queryId).append(token);
103+
}
104+
105+
@Override
106+
public void onComplete(Response<AiMessage> response) {
107+
ChatQueryRepository chatQueryRepository =
108+
ContextUtils.getBean(ChatQueryRepository.class);
109+
ChatQueryDO chatQueryDO = chatQueryRepository.getChatQueryDO(queryId);
110+
JSONObject queryResult = JSON.parseObject(chatQueryDO.getQueryResult());
111+
queryResult.put("textSummary",
112+
resultCache.get(queryId).toString().substring(tip.length()));
113+
chatQueryDO.setQueryResult(queryResult.toJSONString());
114+
chatQueryRepository.updateChatQuery(chatQueryDO);
115+
resultCache.remove(queryId);
116+
}
117+
118+
@Override
119+
public void onError(Throwable error) {
120+
error.printStackTrace();
121+
resultCache.remove(queryId);
122+
}
123+
});
124+
} else {
125+
ChatLanguageModel chatLanguageModel =
126+
ModelProvider.getChatModel(chatApp.getChatModelConfig());
127+
Response<AiMessage> response = chatLanguageModel.generate(prompt.toUserMessage());
128+
String anwser = response.content().text();
129+
keyPipelineLog.info("DataInterpretProcessor modelReq:\n{} \nmodelResp:\n{}",
130+
prompt.text(), anwser);
131+
if (StringUtils.isNotBlank(anwser)) {
132+
queryResult.setTextSummary(anwser);
133+
}
82134
}
135+
136+
83137
}
84138
}

chat/server/src/main/java/com/tencent/supersonic/chat/server/rest/ChatQueryController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
66
import com.tencent.supersonic.chat.api.pojo.request.ChatQueryDataReq;
77
import com.tencent.supersonic.chat.api.pojo.response.ChatParseResp;
8+
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
89
import com.tencent.supersonic.chat.server.service.ChatQueryService;
910
import com.tencent.supersonic.common.pojo.User;
1011
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
@@ -50,6 +51,14 @@ public Object execute(@RequestBody ChatExecuteReq chatExecuteReq, HttpServletReq
5051
return chatQueryService.execute(chatExecuteReq);
5152
}
5253

54+
@PostMapping("getExecuteSummary")
55+
public Object getExecuteSummary(@RequestBody ChatExecuteReq chatExecuteReq,
56+
HttpServletRequest request, HttpServletResponse response) {
57+
chatExecuteReq.setUser(UserHolder.findUser(request, response));
58+
QueryResult res = chatQueryService.getTextSummary(chatExecuteReq);
59+
return res;
60+
}
61+
5362
@PostMapping("/")
5463
public Object query(@RequestBody ChatParseReq chatParseReq, HttpServletRequest request,
5564
HttpServletResponse response) throws Exception {

chat/server/src/main/java/com/tencent/supersonic/chat/server/service/ChatManageService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public interface ChatManageService {
3535

3636
QueryResp getChatQuery(Long queryId);
3737

38+
ChatQueryDO getChatQueryDO(Long queryId);
39+
3840
List<QueryResp> getChatQueries(Integer chatId);
3941

4042
ShowCaseResp queryShowCase(PageQueryInfoReq pageQueryInfoReq, int agentId);

chat/server/src/main/java/com/tencent/supersonic/chat/server/service/ChatQueryService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public interface ChatQueryService {
1919

2020
QueryResult execute(ChatExecuteReq chatExecuteReq) throws Exception;
2121

22+
QueryResult getTextSummary(ChatExecuteReq chatExecuteReq);
23+
2224
QueryResult parseAndExecute(ChatParseReq chatParseReq);
2325

2426
Object queryData(ChatQueryDataReq chatQueryDataReq, User user) throws Exception;

chat/server/src/main/java/com/tencent/supersonic/chat/server/service/impl/ChatManageServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ public QueryResp getChatQuery(Long queryId) {
123123
return chatQueryRepository.getChatQuery(queryId);
124124
}
125125

126+
@Override
127+
public ChatQueryDO getChatQueryDO(Long queryId) {
128+
return chatQueryRepository.getChatQueryDO(queryId);
129+
}
130+
126131
@Override
127132
public List<QueryResp> getChatQueries(Integer chatId) {
128133
List<QueryResp> queries = chatQueryRepository.getChatQueries(chatId);

chat/server/src/main/java/com/tencent/supersonic/chat/server/service/impl/ChatQueryServiceImpl.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.tencent.supersonic.chat.server.service.impl;
22

3+
import com.alibaba.fastjson.JSONObject;
4+
import com.alibaba.fastjson2.JSON;
35
import com.google.common.collect.Lists;
46
import com.tencent.supersonic.chat.api.pojo.request.ChatExecuteReq;
57
import com.tencent.supersonic.chat.api.pojo.request.ChatParseReq;
@@ -9,8 +11,10 @@
911
import com.tencent.supersonic.chat.server.agent.Agent;
1012
import com.tencent.supersonic.chat.server.executor.ChatQueryExecutor;
1113
import com.tencent.supersonic.chat.server.parser.ChatQueryParser;
14+
import com.tencent.supersonic.chat.server.persistence.dataobject.ChatQueryDO;
1215
import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
1316
import com.tencent.supersonic.chat.server.pojo.ParseContext;
17+
import com.tencent.supersonic.chat.server.processor.execute.DataInterpretProcessor;
1418
import com.tencent.supersonic.chat.server.processor.execute.ExecuteResultProcessor;
1519
import com.tencent.supersonic.chat.server.processor.parse.ParseResultProcessor;
1620
import com.tencent.supersonic.chat.server.service.AgentService;
@@ -143,6 +147,21 @@ public QueryResult execute(ChatExecuteReq chatExecuteReq) {
143147
return queryResult;
144148
}
145149

150+
@Override
151+
public QueryResult getTextSummary(ChatExecuteReq chatExecuteReq) {
152+
String text = DataInterpretProcessor.getTextSummary(chatExecuteReq.getQueryId());
153+
if (StringUtils.isNotBlank(text)) {
154+
QueryResult res = new QueryResult();
155+
res.setTextSummary(text);
156+
res.setQueryId(chatExecuteReq.getQueryId());
157+
return res;
158+
} else {
159+
ChatQueryDO chatQueryDo = chatManageService.getChatQueryDO(chatExecuteReq.getQueryId());
160+
QueryResult res = JSON.parseObject(chatQueryDo.getQueryResult(), QueryResult.class);
161+
return res;
162+
}
163+
}
164+
146165
@Override
147166
public QueryResult parseAndExecute(ChatParseReq chatParseReq) {
148167
ChatParseResp parseResp = parse(chatParseReq);

chat/server/src/main/java/com/tencent/supersonic/chat/server/service/impl/PluginServiceImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public List<ChatPlugin> query(PluginQueryReq pluginQueryReq) {
108108
if (StringUtils.isNotBlank(pluginQueryReq.getCreatedBy())) {
109109
queryWrapper.lambda().eq(PluginDO::getCreatedBy, pluginQueryReq.getCreatedBy());
110110
}
111+
queryWrapper.orderByAsc("name");
111112
List<PluginDO> pluginDOS = pluginRepository.query(queryWrapper);
112113
if (StringUtils.isNotBlank(pluginQueryReq.getPattern())) {
113114
pluginDOS = pluginDOS.stream()

common/src/main/java/com/tencent/supersonic/common/service/impl/SystemConfigServiceImpl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.util.List;
1818
import java.util.concurrent.atomic.AtomicReference;
19+
import java.util.stream.Collectors;
1920

2021
@Service
2122
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfigDO>
@@ -38,8 +39,8 @@ public SystemConfig getSystemConfig() {
3839
return systemConfigDb;
3940
}
4041

41-
private SystemConfig getSystemConfigFromDB() {
42-
List<SystemConfigDO> list = list();
42+
private SystemConfig getSystemConfigFromDB() { // 加上id ,如果有多条记录,会出错
43+
List<SystemConfigDO> list = this.lambdaQuery().eq(SystemConfigDO::getId, 1).list();
4344
if (CollectionUtils.isEmpty(list)) {
4445
SystemConfig systemConfig = new SystemConfig();
4546
systemConfig.setId(1);

0 commit comments

Comments
 (0)