2727import ai .chat2db .server .web .api .controller .ai .claude .model .ClaudeChatMessage ;
2828import ai .chat2db .server .web .api .controller .ai .config .LocalCache ;
2929import ai .chat2db .server .web .api .controller .ai .converter .ChatConverter ;
30+ import ai .chat2db .server .web .api .controller .ai .dify .client .DifyChatAIClient ;
31+ import ai .chat2db .server .web .api .controller .ai .dify .listener .DifyChatAIEventSourceListener ;
32+ import ai .chat2db .server .web .api .controller .ai .dify .model .DifyChatConstant ;
3033import ai .chat2db .server .web .api .controller .ai .enums .PromptType ;
3134import ai .chat2db .server .web .api .controller .ai .fastchat .client .FastChatAIClient ;
3235import ai .chat2db .server .web .api .controller .ai .fastchat .embeddings .FastChatEmbeddingResponse ;
@@ -132,7 +135,7 @@ public class ChatController {
132135 /**
133136 * 自定义模型流式输出接口DEMO
134137 * <p>
135- * Note:使用自己本地的流式输出的自定义AI,接口输入和输出需与该样例保持一致
138+ * Note:使用自己本地的流式输出的自定义AI,接口输入和输出需与该样例保持一致
136139 * </p>
137140 *
138141 * @param queryRequest
@@ -171,7 +174,7 @@ public SseEmitter customChat(@RequestBody ChatRequest queryRequest) throws IOExc
171174 /**
172175 * 自定义模型非流式输出接口DEMO
173176 * <p>
174- * Note:使用自己本地的飞流式输出自定义AI,接口输入和输出需与该样例保持一致
177+ * Note:使用自己本地的飞流式输出自定义AI,接口输入和输出需与该样例保持一致
175178 * </p>
176179 *
177180 * @param queryRequest
@@ -196,7 +199,7 @@ public String customNonStreamChat(@RequestBody ChatRequest queryRequest) throws
196199 @ GetMapping ("/chat" )
197200 @ CrossOrigin
198201 public SseEmitter completions (ChatQueryRequest queryRequest , @ RequestHeader Map <String , String > headers )
199- throws IOException {
202+ throws IOException {
200203 //默认30秒超时,设置为0L则永不超时
201204 SseEmitter sseEmitter = new SseEmitter (CHAT_TIMEOUT );
202205 String uid = headers .get ("uid" );
@@ -230,14 +233,14 @@ public SseEmitter distributeAISql(ChatQueryRequest queryRequest, SseEmitter sseE
230233 }
231234 uid = aiSqlSourceEnum .getCode () + uid ;
232235 switch (Objects .requireNonNull (aiSqlSourceEnum )) {
233- case OPENAI :
236+ case OPENAI :
234237 return chatWithOpenAi (queryRequest , sseEmitter , uid );
235238 case CHAT2DBAI :
236239 return chatWithChat2dbAi (queryRequest , sseEmitter , uid );
237- case RESTAI :
240+ case RESTAI :
238241 case FASTCHATAI :
239242 return chatWithFastChatAi (queryRequest , sseEmitter , uid );
240- case AZUREAI :
243+ case AZUREAI :
241244 return chatWithAzureAi (queryRequest , sseEmitter , uid );
242245 case CLAUDEAI :
243246 return chatWithClaudeAi (queryRequest , sseEmitter , uid );
@@ -249,10 +252,35 @@ public SseEmitter distributeAISql(ChatQueryRequest queryRequest, SseEmitter sseE
249252 return chatWithTongyiChatAi (queryRequest , sseEmitter , uid );
250253 case ZHIPUAI :
251254 return chatWithZhipuChatAi (queryRequest , sseEmitter , uid );
255+ case DIFYCHAT :
256+ return chatWithDifyChatAi (queryRequest , sseEmitter , uid );
252257 }
253258 return chatWithOpenAi (queryRequest , sseEmitter , uid );
254259 }
255260
261+ private SseEmitter chatWithDifyChatAi (ChatQueryRequest queryRequest , SseEmitter sseEmitter , String uid ) throws IOException {
262+ String prompt = buildPrompt (queryRequest );
263+ if (prompt .length () / TOKEN_CONVERT_CHAR_LENGTH > MAX_PROMPT_LENGTH ) {
264+ log .error ("exceed max token length:{},input length:{}" , MAX_PROMPT_LENGTH ,
265+ prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
266+ throw new ParamBusinessException ();
267+ }
268+
269+ prompt = prompt .replaceAll ("#" , "" );
270+ log .info (prompt );
271+
272+ Message currentMessage = Message .builder ().content (prompt ).role (Message .Role .USER ).build ();
273+ List <Message > messages = new ArrayList <>();
274+ messages .add (currentMessage );
275+ buildSseEmitter (sseEmitter , uid );
276+
277+ DifyChatAIEventSourceListener eventSourceListener = new DifyChatAIEventSourceListener (sseEmitter , uid );
278+ String conversationId = (String ) LocalCache .CACHE .get (DifyChatConstant .CONVERSATION_CACHE_PREFIX + uid );
279+ DifyChatAIClient .getInstance ().streamCompletions (messages , eventSourceListener , uid , conversationId );
280+ LocalCache .CACHE .put (uid , JSONUtil .toJsonStr (messages ), LocalCache .TIMEOUT );
281+ return sseEmitter ;
282+ }
283+
256284 /**
257285 * 使用自定义AI接口进行聊天
258286 *
@@ -276,11 +304,11 @@ private SseEmitter chatWithRestAi(ChatQueryRequest prompt, SseEmitter sseEmitter
276304 * @throws IOException
277305 */
278306 private SseEmitter chatWithOpenAi (ChatQueryRequest queryRequest , SseEmitter sseEmitter , String uid )
279- throws IOException {
307+ throws IOException {
280308 String prompt = buildPrompt (queryRequest );
281309 if (prompt .length () / TOKEN_CONVERT_CHAR_LENGTH > MAX_PROMPT_LENGTH ) {
282310 log .error ("提示语超出最大长度:{},输入长度:{}, 请重新输入" , MAX_PROMPT_LENGTH ,
283- prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
311+ prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
284312 throw new ParamBusinessException ();
285313 }
286314
@@ -307,11 +335,11 @@ private SseEmitter chatWithOpenAi(ChatQueryRequest queryRequest, SseEmitter sseE
307335 * @throws IOException
308336 */
309337 private SseEmitter chatWithChat2dbAi (ChatQueryRequest queryRequest , SseEmitter sseEmitter , String uid )
310- throws IOException {
338+ throws IOException {
311339 String prompt = buildPrompt (queryRequest );
312340 if (prompt .length () / TOKEN_CONVERT_CHAR_LENGTH > MAX_PROMPT_LENGTH ) {
313341 log .error ("exceed max token length:{},input length:{}" , MAX_PROMPT_LENGTH ,
314- prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
342+ prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
315343 throw new ParamBusinessException ();
316344 }
317345
@@ -344,7 +372,7 @@ private SseEmitter chatWithAzureAi(ChatQueryRequest queryRequest, SseEmitter sse
344372 prompt .length () / TOKEN_CONVERT_CHAR_LENGTH );
345373 throw new ParamBusinessException ();
346374 }
347- List <AzureChatMessage > messages = (List <AzureChatMessage >)LocalCache .CACHE .get (uid );
375+ List <AzureChatMessage > messages = (List <AzureChatMessage >) LocalCache .CACHE .get (uid );
348376 if (CollectionUtils .isNotEmpty (messages )) {
349377 if (messages .size () >= contextLength ) {
350378 messages = messages .subList (1 , contextLength );
@@ -363,6 +391,7 @@ private SseEmitter chatWithAzureAi(ChatQueryRequest queryRequest, SseEmitter sse
363391 return sseEmitter ;
364392 }
365393
394+
366395 /**
367396 * chat with fast chat openai
368397 *
@@ -455,7 +484,7 @@ private SseEmitter chatWithBaichuanAi(ChatQueryRequest queryRequest, SseEmitter
455484 * @return
456485 */
457486 private List <FastChatMessage > getFastChatMessage (String uid , String prompt ) {
458- List <FastChatMessage > messages = (List <FastChatMessage >)LocalCache .CACHE .get (uid );
487+ List <FastChatMessage > messages = (List <FastChatMessage >) LocalCache .CACHE .get (uid );
459488 if (CollectionUtils .isNotEmpty (messages )) {
460489 if (messages .size () >= contextLength ) {
461490 messages = messages .subList (1 , contextLength );
@@ -531,17 +560,17 @@ private SseEmitter buildSseEmitter(SseEmitter sseEmitter, String uid) throws IOE
531560 log .info (LocalDateTime .now () + ", uid#" + uid + ", on completion" );
532561 });
533562 sseEmitter .onTimeout (
534- () -> log .info (LocalDateTime .now () + ", uid#" + uid + ", on timeout#" + sseEmitter .getTimeout ()));
563+ () -> log .info (LocalDateTime .now () + ", uid#" + uid + ", on timeout#" + sseEmitter .getTimeout ()));
535564 sseEmitter .onError (
536- throwable -> {
537- try {
538- log .info (LocalDateTime .now () + ", uid#" + "765431" + ", on error#" + throwable .toString ());
539- sseEmitter .send (SseEmitter .event ().id ("765431" ).name ("发生异常!" ).data (throwable .getMessage ())
540- .reconnectTime (3000 ));
541- } catch (IOException e ) {
542- e .printStackTrace ();
565+ throwable -> {
566+ try {
567+ log .info (LocalDateTime .now () + ", uid#" + "765431" + ", on error#" + throwable .toString ());
568+ sseEmitter .send (SseEmitter .event ().id ("765431" ).name ("发生异常!" ).data (throwable .getMessage ())
569+ .reconnectTime (3000 ));
570+ } catch (IOException e ) {
571+ e .printStackTrace ();
572+ }
543573 }
544- }
545574 );
546575 return sseEmitter ;
547576 }
@@ -554,13 +583,13 @@ private SseEmitter buildSseEmitter(SseEmitter sseEmitter, String uid) throws IOE
554583 * @return
555584 */
556585 private String buildTableColumn (TableQueryParam tableQueryParam ,
557- List <String > tableNames ) {
586+ List <String > tableNames ) {
558587 if (CollectionUtils .isEmpty (tableNames )) {
559588 return "" ;
560589 }
561590 List <String > schemaContent = Lists .newArrayList ();
562591 try {
563- schemaContent = tableNames .stream ().map (tableName -> {
592+ schemaContent = tableNames .stream ().map (tableName -> {
564593 tableQueryParam .setTableName (tableName );
565594 return queryTableDdl (tableName , tableQueryParam );
566595 }).collect (Collectors .toList ());
@@ -610,19 +639,19 @@ private String buildPrompt(ChatQueryRequest queryRequest) {
610639 }
611640 String prompt = queryRequest .getMessage ();
612641 String promptType = StringUtils .isBlank (queryRequest .getPromptType ()) ? PromptType .NL_2_SQL .getCode ()
613- : queryRequest .getPromptType ();
642+ : queryRequest .getPromptType ();
614643 PromptType pType = EasyEnumUtils .getEnum (PromptType .class , promptType );
615644 String ext = StringUtils .isNotBlank (queryRequest .getExt ()) ? queryRequest .getExt () : "" ;
616645 String schemaProperty = StringUtils .isNotEmpty (properties ) ? String .format (
617- "### 请根据以下table properties和SQL input%s. %s\n #\n ### %s SQL tables, with their properties:\n #\n # "
618- + "%s\n #\n #\n ### SQL input: %s" , pType .getDescription (), ext , dataSourceType ,
619- properties , prompt ) : String .format ("### 请根据以下SQL input%s. %s\n #\n ### SQL input: %s" ,
620- pType .getDescription (), ext , prompt );
646+ "### 请根据以下table properties和SQL input%s. %s\n #\n ### %s SQL tables, with their properties:\n #\n # "
647+ + "%s\n #\n #\n ### SQL input: %s" , pType .getDescription (), ext , dataSourceType ,
648+ properties , prompt ) : String .format ("### 请根据以下SQL input%s. %s\n #\n ### SQL input: %s" ,
649+ pType .getDescription (), ext , prompt );
621650 switch (pType ) {
622651 case SQL_2_SQL :
623652 schemaProperty = StringUtils .isNotBlank (queryRequest .getDestSqlType ()) ? String .format (
624- "%s\n #\n ### 目标SQL类型: %s" , schemaProperty , queryRequest .getDestSqlType ()) : String .format (
625- "%s\n #\n ### 目标SQL类型: %s" , schemaProperty , dataSourceType );
653+ "%s\n #\n ### 目标SQL类型: %s" , schemaProperty , queryRequest .getDestSqlType ()) : String .format (
654+ "%s\n #\n ### 目标SQL类型: %s" , schemaProperty , dataSourceType );
626655 default :
627656 break ;
628657 }
@@ -711,7 +740,7 @@ public String queryDatabaseSchema(ChatQueryRequest queryRequest) {
711740 DataResult <TableSchemaResponse > result = gatewayClientService .schemaVectorSearch (tableSchemaRequest );
712741 List <String > schemas = Lists .newArrayList ();
713742 if (Objects .nonNull (result .getData ()) && CollectionUtils .isNotEmpty (result .getData ().getTableSchemas ())) {
714- for (TableSchema data : result .getData ().getTableSchemas ()){
743+ for (TableSchema data : result .getData ().getTableSchemas ()) {
715744 schemas .add (data .getTableSchema ());
716745 }
717746 }
@@ -751,7 +780,7 @@ public String querySchemaByEs(ChatQueryRequest queryRequest) {
751780 DataResult <EsTableSchemaResponse > result = gatewayClientService .schemaEsSearch (tableSchemaRequest );
752781 List <String > schemas = Lists .newArrayList ();
753782 if (Objects .nonNull (result .getData ()) && CollectionUtils .isNotEmpty (result .getData ().getTableSchemas ())) {
754- for (EsTableSchema data : result .getData ().getTableSchemas ()){
783+ for (EsTableSchema data : result .getData ().getTableSchemas ()) {
755784 schemas .add (data .getTableSchemaContent ());
756785 }
757786 }
0 commit comments