mirror of
https://github.com/CodePhiliaX/Chat2DB.git
synced 2025-08-01 08:52:11 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@ -21,8 +21,8 @@ import ai.chat2db.server.tools.common.exception.ParamBusinessException;
|
||||
import ai.chat2db.server.tools.common.util.EasyEnumUtils;
|
||||
import ai.chat2db.server.web.api.aspect.ConnectionInfoAspect;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.client.AzureOpenAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatRole;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatRole;
|
||||
import ai.chat2db.server.web.api.controller.ai.chat2db.client.Chat2dbAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.claude.client.ClaudeAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.claude.model.ClaudeChatCompletionsOptions;
|
||||
@ -30,15 +30,19 @@ import ai.chat2db.server.web.api.controller.ai.claude.model.ClaudeChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.config.LocalCache;
|
||||
import ai.chat2db.server.web.api.controller.ai.converter.ChatConverter;
|
||||
import ai.chat2db.server.web.api.controller.ai.enums.PromptType;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.AzureOpenAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.ClaudeAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.OpenAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.RestAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.listener.AzureOpenAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.claude.listener.ClaudeAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.client.FastChatAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.listener.FastChatAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatRole;
|
||||
import ai.chat2db.server.web.api.controller.ai.openai.listener.OpenAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.rest.listener.RestAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.request.ChatQueryRequest;
|
||||
import ai.chat2db.server.web.api.controller.ai.request.ChatRequest;
|
||||
import ai.chat2db.server.web.api.controller.ai.rest.client.RestAIClient;
|
||||
import ai.chat2db.server.web.api.util.ApplicationContextUtil;
|
||||
import ai.chat2db.server.web.api.util.OpenAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.openai.client.OpenAIClient;
|
||||
import ai.chat2db.spi.model.TableColumn;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
@ -218,6 +222,8 @@ public class ChatController {
|
||||
return chatWithAzureAi(queryRequest, sseEmitter, uid);
|
||||
case CLAUDEAI:
|
||||
return chatWithClaudeAi(queryRequest, sseEmitter, uid);
|
||||
case FASTCHATAI:
|
||||
return chatWithFastChatAi(queryRequest, sseEmitter, uid);
|
||||
}
|
||||
return chatWithOpenAi(queryRequest, sseEmitter, uid);
|
||||
}
|
||||
@ -332,6 +338,36 @@ public class ChatController {
|
||||
return sseEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* chat with fast chat openai
|
||||
*
|
||||
* @param queryRequest
|
||||
* @param sseEmitter
|
||||
* @param uid
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private SseEmitter chatWithFastChatAi(ChatQueryRequest queryRequest, SseEmitter sseEmitter, String uid) throws IOException {
|
||||
String prompt = buildPrompt(queryRequest);
|
||||
List<FastChatMessage> messages = (List<FastChatMessage>)LocalCache.CACHE.get(uid);
|
||||
if (CollectionUtils.isNotEmpty(messages)) {
|
||||
if (messages.size() >= contextLength) {
|
||||
messages = messages.subList(1, contextLength);
|
||||
}
|
||||
} else {
|
||||
messages = Lists.newArrayList();
|
||||
}
|
||||
FastChatMessage currentMessage = new FastChatMessage(FastChatRole.USER).setContent(prompt);
|
||||
messages.add(currentMessage);
|
||||
|
||||
buildSseEmitter(sseEmitter, uid);
|
||||
|
||||
FastChatAIEventSourceListener sourceListener = new FastChatAIEventSourceListener(sseEmitter);
|
||||
FastChatAIClient.getInstance().streamCompletions(messages, sourceListener);
|
||||
LocalCache.CACHE.put(uid, messages, LocalCache.TIMEOUT);
|
||||
return sseEmitter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* chat with claude ai
|
||||
|
@ -6,8 +6,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ai.chat2db.server.tools.common.exception.ParamBusinessException;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.interceptor.AzureHeaderAuthorizationInterceptor;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatCompletionsOptions;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatCompletionsOptions;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatMessage;
|
||||
import cn.hutool.http.ContentType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Getter;
|
||||
|
@ -1,13 +1,12 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.listener;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.listener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatChoice;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatCompletions;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.models.AzureCompletionsUsage;
|
||||
import ai.chat2db.server.web.api.controller.ai.response.ChatCompletionResponse;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatChoice;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatCompletions;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureChatMessage;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.model.AzureCompletionsUsage;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -1,10 +1,9 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.model;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.listener;
|
||||
package ai.chat2db.server.web.api.controller.ai.claude.listener;
|
||||
|
||||
import ai.chat2db.server.web.api.controller.ai.claude.model.ClaudeCompletionResponse;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
@ -0,0 +1,75 @@
|
||||
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.client;
|
||||
|
||||
import ai.chat2db.server.domain.api.model.Config;
|
||||
import ai.chat2db.server.domain.api.service.ConfigService;
|
||||
import ai.chat2db.server.web.api.util.ApplicationContextUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* @author moji
|
||||
* @date 23/09/26
|
||||
*/
|
||||
@Slf4j
|
||||
public class FastChatAIClient {
|
||||
|
||||
/**
|
||||
* FASTCHAT OPENAI KEY
|
||||
*/
|
||||
public static final String FASTCHAT_API_KEY = "fastchat.chatgpt.apiKey";
|
||||
|
||||
/**
|
||||
* FASTCHAT OPENAI HOST
|
||||
*/
|
||||
public static final String FASTCHAT_HOST = "fastchat.host";
|
||||
|
||||
/**
|
||||
* FASTCHAT OPENAI model
|
||||
*/
|
||||
public static final String FASTCHAT_MODEL= "fastchat.model";
|
||||
|
||||
private static FastChatAIStreamClient FASTCHAT_AI_CLIENT;
|
||||
|
||||
|
||||
public static FastChatAIStreamClient getInstance() {
|
||||
if (FASTCHAT_AI_CLIENT != null) {
|
||||
return FASTCHAT_AI_CLIENT;
|
||||
} else {
|
||||
return singleton();
|
||||
}
|
||||
}
|
||||
|
||||
private static FastChatAIStreamClient singleton() {
|
||||
if (FASTCHAT_AI_CLIENT == null) {
|
||||
synchronized (FastChatAIClient.class) {
|
||||
if (FASTCHAT_AI_CLIENT == null) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
return FASTCHAT_AI_CLIENT;
|
||||
}
|
||||
|
||||
public static void refresh() {
|
||||
String apiKey = "";
|
||||
String apiHost = "";
|
||||
String model = "";
|
||||
ConfigService configService = ApplicationContextUtil.getBean(ConfigService.class);
|
||||
Config apiHostConfig = configService.find(FASTCHAT_HOST).getData();
|
||||
if (apiHostConfig != null && StringUtils.isNotBlank(apiHostConfig.getContent())) {
|
||||
apiHost = apiHostConfig.getContent();
|
||||
}
|
||||
Config config = configService.find(FASTCHAT_API_KEY).getData();
|
||||
if (config != null && StringUtils.isNotBlank(config.getContent())) {
|
||||
apiKey = config.getContent();
|
||||
}
|
||||
Config deployConfig = configService.find(FASTCHAT_MODEL).getData();
|
||||
if (deployConfig != null && StringUtils.isNotBlank(deployConfig.getContent())) {
|
||||
model = deployConfig.getContent();
|
||||
}
|
||||
FASTCHAT_AI_CLIENT = FastChatAIStreamClient.builder().apiKey(apiKey).apiHost(apiHost).model(model)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.client;
|
||||
|
||||
import ai.chat2db.server.tools.common.exception.ParamBusinessException;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.interceptor.FastChatHeaderAuthorizationInterceptor;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatCompletionsOptions;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatMessage;
|
||||
import cn.hutool.http.ContentType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.sse.EventSource;
|
||||
import okhttp3.sse.EventSourceListener;
|
||||
import okhttp3.sse.EventSources;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Fast Chat Aligned Client
|
||||
*
|
||||
* @author moji
|
||||
*/
|
||||
@Slf4j
|
||||
public class FastChatAIStreamClient {
|
||||
|
||||
/**
|
||||
* apikey
|
||||
*/
|
||||
@Getter
|
||||
@NotNull
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* apiHost
|
||||
*/
|
||||
@Getter
|
||||
@NotNull
|
||||
private String apiHost;
|
||||
|
||||
/**
|
||||
* model
|
||||
*/
|
||||
@Getter
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* okHttpClient
|
||||
*/
|
||||
@Getter
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
|
||||
/**
|
||||
* @param builder
|
||||
*/
|
||||
private FastChatAIStreamClient(Builder builder) {
|
||||
this.apiKey = builder.apiKey;
|
||||
this.apiHost = builder.apiHost;
|
||||
this.model = builder.model;
|
||||
if (Objects.isNull(builder.okHttpClient)) {
|
||||
builder.okHttpClient = this.okHttpClient();
|
||||
}
|
||||
okHttpClient = builder.okHttpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* okhttpclient
|
||||
*/
|
||||
private OkHttpClient okHttpClient() {
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.addInterceptor(new FastChatHeaderAuthorizationInterceptor(this.apiKey))
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(50, TimeUnit.SECONDS)
|
||||
.readTimeout(50, TimeUnit.SECONDS)
|
||||
.build();
|
||||
return okHttpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static FastChatAIStreamClient.Builder builder() {
|
||||
return new FastChatAIStreamClient.Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* builder
|
||||
*/
|
||||
public static final class Builder {
|
||||
private String apiKey;
|
||||
|
||||
private String apiHost;
|
||||
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* OkhttpClient
|
||||
*/
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public FastChatAIStreamClient.Builder apiKey(String apiKeyValue) {
|
||||
this.apiKey = apiKeyValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param apiHostValue
|
||||
* @return
|
||||
*/
|
||||
public FastChatAIStreamClient.Builder apiHost(String apiHostValue) {
|
||||
this.apiHost = apiHostValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modelValue
|
||||
* @return
|
||||
*/
|
||||
public FastChatAIStreamClient.Builder model(String modelValue) {
|
||||
this.model = modelValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastChatAIStreamClient.Builder okHttpClient(OkHttpClient val) {
|
||||
this.okHttpClient = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastChatAIStreamClient build() {
|
||||
return new FastChatAIStreamClient(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 问答接口 stream 形式
|
||||
*
|
||||
* @param chatMessages
|
||||
* @param eventSourceListener
|
||||
*/
|
||||
public void streamCompletions(List<FastChatMessage> chatMessages, EventSourceListener eventSourceListener) {
|
||||
if (CollectionUtils.isEmpty(chatMessages)) {
|
||||
log.error("param error:Fast Chat Prompt cannot be empty");
|
||||
throw new ParamBusinessException("prompt");
|
||||
}
|
||||
if (Objects.isNull(eventSourceListener)) {
|
||||
log.error("param error:FastChatEventSourceListener cannot be empty");
|
||||
throw new ParamBusinessException();
|
||||
}
|
||||
log.info("Fast Chat AI, prompt:{}", chatMessages.get(chatMessages.size() - 1).getContent());
|
||||
try {
|
||||
|
||||
FastChatCompletionsOptions chatCompletionsOptions = new FastChatCompletionsOptions(chatMessages);
|
||||
chatCompletionsOptions.setStream(true);
|
||||
chatCompletionsOptions.setModel(this.model);
|
||||
|
||||
EventSource.Factory factory = EventSources.createFactory(this.okHttpClient);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String requestBody = mapper.writeValueAsString(chatCompletionsOptions);
|
||||
Request request = new Request.Builder()
|
||||
.url(apiHost)
|
||||
.post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
|
||||
.build();
|
||||
//创建事件
|
||||
EventSource eventSource = factory.newEventSource(request, eventSourceListener);
|
||||
log.info("finish invoking fast chat ai");
|
||||
} catch (Exception e) {
|
||||
log.error("fast chat ai error", e);
|
||||
eventSourceListener.onFailure(null, e, null);
|
||||
throw new ParamBusinessException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.interceptor;
|
||||
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.http.Header;
|
||||
import lombok.Getter;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* header apikey
|
||||
*
|
||||
* @author grt
|
||||
* @since 2023-03-23
|
||||
*/
|
||||
@Getter
|
||||
public class FastChatHeaderAuthorizationInterceptor implements Interceptor {
|
||||
|
||||
private String apiKey;
|
||||
|
||||
public FastChatHeaderAuthorizationInterceptor(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request original = chain.request();
|
||||
Request request = original.newBuilder()
|
||||
.header("apiKey", apiKey) // replace to your corresponding field and value
|
||||
.header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
|
||||
.method(original.method(), original.body())
|
||||
.build();
|
||||
return chain.proceed(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.listener;
|
||||
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatChoice;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatCompletions;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatCompletionsUsage;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatMessage;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.sse.EventSource;
|
||||
import okhttp3.sse.EventSourceListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 描述:OpenAIEventSourceListener
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @date 2023-02-22
|
||||
*/
|
||||
@Slf4j
|
||||
public class FastChatAIEventSourceListener extends EventSourceListener {
|
||||
|
||||
private SseEmitter sseEmitter;
|
||||
|
||||
private ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
|
||||
public FastChatAIEventSourceListener(SseEmitter sseEmitter) {
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onOpen(EventSource eventSource, Response response) {
|
||||
log.info("Fast Chat Sse connecting...");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void onEvent(EventSource eventSource, String id, String type, String data) {
|
||||
log.info("Fast Chat AI response data:{}", data);
|
||||
if (data.equals("[DONE]")) {
|
||||
log.info("Fast Chat AI closed");
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]")
|
||||
.reconnectTime(3000));
|
||||
sseEmitter.complete();
|
||||
return;
|
||||
}
|
||||
|
||||
FastChatCompletions chatCompletions = mapper.readValue(data, FastChatCompletions.class);
|
||||
String text = "";
|
||||
log.info("Model={} is created at {}.", chatCompletions.getId(),
|
||||
chatCompletions.getCreated());
|
||||
for (FastChatChoice choice : chatCompletions.getChoices()) {
|
||||
FastChatMessage message = choice.getMessage();
|
||||
if (message != null) {
|
||||
log.info("Index: {}, Chat Role: {}", choice.getIndex(), message.getRole());
|
||||
if (message.getContent() != null) {
|
||||
text = message.getContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FastChatCompletionsUsage usage = chatCompletions.getUsage();
|
||||
if (usage != null) {
|
||||
log.info(
|
||||
"Usage: number of prompt token is {}, number of completion token is {}, and number of total "
|
||||
+ "tokens in request and response is {}.%n", usage.getPromptTokens(),
|
||||
usage.getCompletionTokens(), usage.getTotalTokens());
|
||||
}
|
||||
|
||||
Message message = new Message();
|
||||
message.setContent(text);
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(null)
|
||||
.data(message)
|
||||
.reconnectTime(3000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(EventSource eventSource) {
|
||||
try {
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
sseEmitter.complete();
|
||||
log.info("FastChatAI close sse connection...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(EventSource eventSource, Throwable t, Response response) {
|
||||
try {
|
||||
if (Objects.isNull(response)) {
|
||||
String message = t.getMessage();
|
||||
Message sseMessage = new Message();
|
||||
sseMessage.setContent(message);
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[ERROR]")
|
||||
.data(sseMessage));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]"));
|
||||
sseEmitter.complete();
|
||||
return;
|
||||
}
|
||||
ResponseBody body = response.body();
|
||||
String bodyString = Objects.nonNull(t) ? t.getMessage() : "";
|
||||
if (Objects.nonNull(body)) {
|
||||
bodyString = body.string();
|
||||
if (StringUtils.isBlank(bodyString) && Objects.nonNull(t)) {
|
||||
bodyString = t.getMessage();
|
||||
}
|
||||
log.error("Fast Chat AI sse response:{}", bodyString);
|
||||
} else {
|
||||
log.error("Fast Chat AI sse response:{},error:{}", response, t);
|
||||
}
|
||||
eventSource.cancel();
|
||||
Message message = new Message();
|
||||
message.setContent("Fast Chat AI error:" + bodyString);
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[ERROR]")
|
||||
.data(message));
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[DONE]")
|
||||
.data("[DONE]"));
|
||||
sseEmitter.complete();
|
||||
} catch (Exception exception) {
|
||||
log.error("Fast Chat AI send data error:", exception);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* The representation of a single prompt completion as part of an overall completions request. Generally, `n` choices
|
||||
* are generated per provided prompt with a default value of 1. Token limits and other settings may limit the number of
|
||||
* choices generated.
|
||||
*/
|
||||
@Data
|
||||
public final class FastChatChoice {
|
||||
|
||||
/*
|
||||
* The generated text for a given completions prompt.
|
||||
*/
|
||||
@JsonProperty(value = "text")
|
||||
private String text;
|
||||
|
||||
/*
|
||||
* The ordered index associated with this completions choice.
|
||||
*/
|
||||
@JsonProperty(value = "index")
|
||||
private int index;
|
||||
|
||||
/*
|
||||
* The log probabilities model for tokens associated with this completions choice.
|
||||
*/
|
||||
@JsonProperty(value = "message")
|
||||
private FastChatMessage message;
|
||||
|
||||
/*
|
||||
* Reason for finishing
|
||||
*/
|
||||
@JsonProperty(value = "finish_reason")
|
||||
private FastChatCompletionsFinishReason finishReason;
|
||||
|
||||
/**
|
||||
* Creates an instance of Choice class.
|
||||
*
|
||||
* @param text the text value to set.
|
||||
* @param index the index value to set.
|
||||
* @param message the message value to set
|
||||
* @param finishReason the finishReason value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private FastChatChoice(
|
||||
@JsonProperty(value = "text") String text,
|
||||
@JsonProperty(value = "index") int index,
|
||||
@JsonProperty(value = "message") FastChatMessage message,
|
||||
@JsonProperty(value = "finish_reason") FastChatCompletionsFinishReason finishReason) {
|
||||
this.text = text;
|
||||
this.index = index;
|
||||
this.message = message;
|
||||
this.finishReason = finishReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text property: The generated text for a given completions prompt.
|
||||
*
|
||||
* @return the text value.
|
||||
*/
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index property: The ordered index associated with this completions choice.
|
||||
*
|
||||
* @return the index value.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logprobs property: The log probabilities model for tokens associated with this completions choice.
|
||||
*
|
||||
* @return the logprobs value.
|
||||
*/
|
||||
public FastChatMessage getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finishReason property: Reason for finishing.
|
||||
*
|
||||
* @return the finishReason value.
|
||||
*/
|
||||
public FastChatCompletionsFinishReason getFinishReason() {
|
||||
return this.finishReason;
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class FastChatCompletions {
|
||||
|
||||
/*
|
||||
* A unique identifier associated with this chat completions response.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/*
|
||||
* The first timestamp associated with generation activity for this completions response,
|
||||
* represented as seconds since the beginning of the Unix epoch of 00:00 on 1 Jan 1970.
|
||||
*/
|
||||
private int created;
|
||||
|
||||
/**
|
||||
* model
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* object
|
||||
*/
|
||||
private String object;
|
||||
|
||||
/*
|
||||
* The collection of completions choices associated with this completions response.
|
||||
* Generally, `n` choices are generated per provided prompt with a default value of 1.
|
||||
* Token limits and other settings may limit the number of choices generated.
|
||||
*/
|
||||
@JsonProperty(value = "choices")
|
||||
private List<FastChatChoice> choices;
|
||||
|
||||
/*
|
||||
* Usage information for tokens processed and generated as part of this completions operation.
|
||||
*/
|
||||
private FastChatCompletionsUsage usage;
|
||||
|
||||
/**
|
||||
* Creates an instance of ChatCompletions class.
|
||||
*
|
||||
* @param id the id value to set.
|
||||
* @param created the created value to set.
|
||||
* @param choices the choices value to set.
|
||||
* @param usage the usage value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private FastChatCompletions(
|
||||
@JsonProperty(value = "id") String id,
|
||||
@JsonProperty(value = "created") int created,
|
||||
@JsonProperty(value = "model") String model,
|
||||
@JsonProperty(value = "object") String object,
|
||||
@JsonProperty(value = "choices") List<FastChatChoice> choices,
|
||||
@JsonProperty(value = "usage") FastChatCompletionsUsage usage) {
|
||||
this.id = id;
|
||||
this.created = created;
|
||||
this.model = model;
|
||||
this.object = object;
|
||||
this.choices = choices;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id property: A unique identifier associated with this chat completions response.
|
||||
*
|
||||
* @return the id value.
|
||||
*/
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the created property: The first timestamp associated with generation activity for this completions response,
|
||||
* represented as seconds since the beginning of the Unix epoch of 00:00 on 1 Jan 1970.
|
||||
*
|
||||
* @return the created value.
|
||||
*/
|
||||
public int getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the choices property: The collection of completions choices associated with this completions response.
|
||||
* Generally, `n` choices are generated per provided prompt with a default value of 1. Token limits and other
|
||||
* settings may limit the number of choices generated.
|
||||
*
|
||||
* @return the choices value.
|
||||
*/
|
||||
public List<FastChatChoice> getChoices() {
|
||||
return this.choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the usage property: Usage information for tokens processed and generated as part of this completions
|
||||
* operation.
|
||||
*
|
||||
* @return the usage value.
|
||||
*/
|
||||
public FastChatCompletionsUsage getUsage() {
|
||||
return this.usage;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/** Representation of the manner in which a completions response concluded. */
|
||||
public final class FastChatCompletionsFinishReason extends FastChatExpandableStringEnum<FastChatCompletionsFinishReason> {
|
||||
|
||||
/** Completions ended normally and reached its end of token generation. */
|
||||
public static final FastChatCompletionsFinishReason STOPPED = fromString("stopped");
|
||||
|
||||
/** Completions exhausted available token limits before generation could complete. */
|
||||
public static final FastChatCompletionsFinishReason TOKEN_LIMIT_REACHED = fromString("tokenLimitReached");
|
||||
|
||||
/**
|
||||
* Completions generated a response that was identified as potentially sensitive per content moderation policies.
|
||||
*/
|
||||
public static final FastChatCompletionsFinishReason CONTENT_FILTERED = fromString("contentFiltered");
|
||||
|
||||
/**
|
||||
* Creates a new instance of CompletionsFinishReason value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public FastChatCompletionsFinishReason() {}
|
||||
|
||||
/**
|
||||
* Creates or finds a CompletionsFinishReason from its string representation.
|
||||
*
|
||||
* @param name a name to look for.
|
||||
* @return the corresponding CompletionsFinishReason.
|
||||
*/
|
||||
@JsonCreator
|
||||
public static FastChatCompletionsFinishReason fromString(String name) {
|
||||
return fromString(name, FastChatCompletionsFinishReason.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets known CompletionsFinishReason values.
|
||||
*
|
||||
* @return known CompletionsFinishReason values.
|
||||
*/
|
||||
public static Collection<FastChatCompletionsFinishReason> values() {
|
||||
return values(FastChatCompletionsFinishReason.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The configuration information for a chat completions request. Completions support a wide variety of tasks and
|
||||
* generate text that continues from or "completes" provided prompt data.
|
||||
*/
|
||||
@Data
|
||||
public final class FastChatCompletionsOptions {
|
||||
|
||||
/*
|
||||
* The collection of context messages associated with this chat completions request.
|
||||
* Typical usage begins with a chat message for the System role that provides instructions for
|
||||
* the behavior of the assistant, followed by alternating messages between the User and
|
||||
* Assistant roles.
|
||||
*/
|
||||
private List<FastChatMessage> messages;
|
||||
|
||||
|
||||
/*
|
||||
* A value indicating whether chat completions should be streamed for this request.
|
||||
*/
|
||||
private Boolean stream;
|
||||
//
|
||||
/*
|
||||
* The model name to provide as part of this completions request.
|
||||
* Not applicable to Fast Chat AI, where deployment information should be included in the Fast Chat
|
||||
* resource URI that's connected to.
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* Creates an instance of ChatCompletionsOptions class.
|
||||
*
|
||||
* @param messages the messages value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
public FastChatCompletionsOptions(@JsonProperty(value = "messages") List<FastChatMessage> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the stream property: A value indicating whether chat completions should be streamed for this request.
|
||||
*
|
||||
* @return the stream value.
|
||||
*/
|
||||
public Boolean isStream() {
|
||||
return this.stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stream property: A value indicating whether chat completions should be streamed for this request.
|
||||
*
|
||||
* @param stream the stream value to set.
|
||||
* @return the ChatCompletionsOptions object itself.
|
||||
*/
|
||||
public FastChatCompletionsOptions setStream(Boolean stream) {
|
||||
this.stream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model property: The model name to provide as part of this completions request. Not applicable to Fast Chat AI,
|
||||
* where deployment information should be included in the Fast Chat AI resource URI that's connected to.
|
||||
*
|
||||
* @return the model value.
|
||||
*/
|
||||
public String getModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the model property: The model name to provide as part of this completions request. Not applicable to Fast Chat AI,
|
||||
* where deployment information should be included in the Fast Chat AI resource URI that's connected to.
|
||||
*
|
||||
* @param model the model value to set.
|
||||
* @return the ChatCompletionsOptions object itself.
|
||||
*/
|
||||
public FastChatCompletionsOptions setModel(String model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Representation of the token counts processed for a completions request. Counts consider all tokens across prompts,
|
||||
* choices, choice alternates, best_of generations, and other consumers.
|
||||
*/
|
||||
@Data
|
||||
public final class FastChatCompletionsUsage {
|
||||
|
||||
/*
|
||||
* The number of tokens generated across all completions emissions.
|
||||
*/
|
||||
@JsonProperty(value = "completion_tokens")
|
||||
private int completionTokens;
|
||||
|
||||
/*
|
||||
* The number of tokens in the provided prompts for the completions request.
|
||||
*/
|
||||
@JsonProperty(value = "prompt_tokens")
|
||||
private int promptTokens;
|
||||
|
||||
/*
|
||||
* The total number of tokens processed for the completions request and response.
|
||||
*/
|
||||
@JsonProperty(value = "total_tokens")
|
||||
private int totalTokens;
|
||||
|
||||
/**
|
||||
* Creates an instance of CompletionsUsage class.
|
||||
*
|
||||
* @param completionTokens the completionTokens value to set.
|
||||
* @param promptTokens the promptTokens value to set.
|
||||
* @param totalTokens the totalTokens value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private FastChatCompletionsUsage(
|
||||
@JsonProperty(value = "completion_tokens") int completionTokens,
|
||||
@JsonProperty(value = "prompt_tokens") int promptTokens,
|
||||
@JsonProperty(value = "total_tokens") int totalTokens) {
|
||||
this.completionTokens = completionTokens;
|
||||
this.promptTokens = promptTokens;
|
||||
this.totalTokens = totalTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the completionTokens property: The number of tokens generated across all completions emissions.
|
||||
*
|
||||
* @return the completionTokens value.
|
||||
*/
|
||||
public int getCompletionTokens() {
|
||||
return this.completionTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the promptTokens property: The number of tokens in the provided prompts for the completions request.
|
||||
*
|
||||
* @return the promptTokens value.
|
||||
*/
|
||||
public int getPromptTokens() {
|
||||
return this.promptTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the totalTokens property: The total number of tokens processed for the completions request and response.
|
||||
*
|
||||
* @return the totalTokens value.
|
||||
*/
|
||||
public int getTotalTokens() {
|
||||
return this.totalTokens;
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.util.AzureReflectionUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
/**
|
||||
* Base implementation for expandable, single string enums.
|
||||
*
|
||||
* @param <T> a specific expandable enum type
|
||||
*/
|
||||
public abstract class FastChatExpandableStringEnum<T extends FastChatExpandableStringEnum<T>> {
|
||||
private static final Map<Class<?>, MethodHandle> CONSTRUCTORS = new ConcurrentHashMap<>();
|
||||
private static final Map<Class<?>, ConcurrentHashMap<String, ? extends FastChatExpandableStringEnum<?>>> VALUES
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FastChatExpandableStringEnum.class);
|
||||
private String name;
|
||||
private Class<T> clazz;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link FastChatExpandableStringEnum} without a {@link #toString()} value.
|
||||
* <p>
|
||||
* This constructor shouldn't be called as it will produce a {@link FastChatExpandableStringEnum} which doesn't
|
||||
* have a String enum value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String, Class)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public FastChatExpandableStringEnum() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the specific expandable string enum from a String.
|
||||
*
|
||||
* @param name The value to create the instance from.
|
||||
* @param clazz The class of the expandable string enum.
|
||||
* @param <T> the class of the expandable string enum.
|
||||
* @return The expandable string enum instance.
|
||||
*
|
||||
* @throws RuntimeException wrapping implementation class constructor exception (if any is thrown).
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "deprecation"})
|
||||
protected static <T extends FastChatExpandableStringEnum<T>> T fromString(String name, Class<T> clazz) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ConcurrentHashMap<String, ?> clazzValues = VALUES.computeIfAbsent(clazz, key -> new ConcurrentHashMap<>());
|
||||
T value = (T) clazzValues.get(name);
|
||||
|
||||
if (value != null) {
|
||||
return value;
|
||||
} else {
|
||||
MethodHandle ctor = CONSTRUCTORS.computeIfAbsent(clazz, FastChatExpandableStringEnum::getDefaultConstructor);
|
||||
|
||||
if (ctor == null) {
|
||||
// logged in ExpandableStringEnum::getDefaultConstructor
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
value = (T) ctor.invoke();
|
||||
} catch (Throwable e) {
|
||||
LOGGER.warn("Failed to create {}, default constructor threw exception", clazz.getName(), e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return value.nameAndAddValue(name, value, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> MethodHandle getDefaultConstructor(Class<T> clazz) {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = AzureReflectionUtils.getLookupToUse(clazz);
|
||||
return lookup.findConstructor(clazz, methodType(void.class));
|
||||
} catch (NoSuchMethodException | IllegalAccessException e) {
|
||||
LOGGER.info("Can't find or access default constructor for {}", clazz.getName(), e);
|
||||
} catch (Exception e) {
|
||||
LOGGER.info("Failed to get lookup for {}", clazz.getName(), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T nameAndAddValue(String name, T value, Class<T> clazz) {
|
||||
this.name = name;
|
||||
this.clazz = clazz;
|
||||
|
||||
((ConcurrentHashMap<String, T>) VALUES.get(clazz)).put(name, value);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collection of all known values to an expandable string enum type.
|
||||
*
|
||||
* @param clazz the class of the expandable string enum.
|
||||
* @param <T> the class of the expandable string enum.
|
||||
* @return A collection of all known values for the given {@code clazz}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static <T extends FastChatExpandableStringEnum<T>> Collection<T> values(Class<T> clazz) {
|
||||
return new ArrayList<T>((Collection<T>) VALUES.getOrDefault(clazz, new ConcurrentHashMap<>()).values());
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonValue
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.clazz, this.name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
} else if (clazz == null || !clazz.isAssignableFrom(obj.getClass())) {
|
||||
return false;
|
||||
} else if (obj == this) {
|
||||
return true;
|
||||
} else if (this.name == null) {
|
||||
return ((FastChatExpandableStringEnum<T>) obj).name == null;
|
||||
} else {
|
||||
return this.name.equals(((FastChatExpandableStringEnum<T>) obj).name);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FastChatMessage {
|
||||
|
||||
|
||||
/*
|
||||
* The role associated with this message payload.
|
||||
*/
|
||||
@JsonProperty(value = "role")
|
||||
private FastChatRole role;
|
||||
|
||||
/*
|
||||
* The text associated with this message payload.
|
||||
*/
|
||||
@JsonProperty(value = "content")
|
||||
private String content;
|
||||
|
||||
/**
|
||||
* Creates an instance of ChatMessage class.
|
||||
*
|
||||
* @param role the role value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
public FastChatMessage(@JsonProperty(value = "role") FastChatRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the role property: The role associated with this message payload.
|
||||
*
|
||||
* @return the role value.
|
||||
*/
|
||||
public FastChatRole getRole() {
|
||||
return this.role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content property: The text associated with this message payload.
|
||||
*
|
||||
* @return the content value.
|
||||
*/
|
||||
public String getContent() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content property: The text associated with this message payload.
|
||||
*
|
||||
* @param content the content value to set.
|
||||
* @return the ChatMessage object itself.
|
||||
*/
|
||||
public FastChatMessage setContent(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.fastchat.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class FastChatRole extends FastChatExpandableStringEnum<FastChatRole> {
|
||||
|
||||
/** The role that instructs or sets the behavior of the assistant. */
|
||||
public static final FastChatRole SYSTEM = fromString("system");
|
||||
|
||||
/** The role that provides responses to system-instructed, user-prompted input. */
|
||||
public static final FastChatRole ASSISTANT = fromString("assistant");
|
||||
|
||||
/** The role that provides input for chat completions. */
|
||||
public static final FastChatRole USER = fromString("user");
|
||||
|
||||
/**
|
||||
* Creates a new instance of ChatRole value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public FastChatRole() {}
|
||||
|
||||
/**
|
||||
* Creates or finds a ChatRole from its string representation.
|
||||
*
|
||||
* @param name a name to look for.
|
||||
* @return the corresponding ChatRole.
|
||||
*/
|
||||
@JsonCreator
|
||||
public static FastChatRole fromString(String name) {
|
||||
return fromString(name, FastChatRole.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets known ChatRole values.
|
||||
*
|
||||
* @return known ChatRole values.
|
||||
*/
|
||||
public static Collection<FastChatRole> values() {
|
||||
return values(FastChatRole.class);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
|
||||
package ai.chat2db.server.web.api.util;
|
||||
package ai.chat2db.server.web.api.controller.ai.openai.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
@ -8,6 +8,7 @@ import java.util.Objects;
|
||||
import ai.chat2db.server.domain.api.model.Config;
|
||||
import ai.chat2db.server.domain.api.service.ConfigService;
|
||||
|
||||
import ai.chat2db.server.web.api.util.ApplicationContextUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.unfbx.chatgpt.OpenAiStreamClient;
|
||||
import com.unfbx.chatgpt.constant.OpenAIConst;
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.listener;
|
||||
package ai.chat2db.server.web.api.controller.ai.openai.listener;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.listener;
|
||||
package ai.chat2db.server.web.api.controller.ai.rest.listener;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -14,10 +14,11 @@ import ai.chat2db.server.tools.base.wrapper.result.DataResult;
|
||||
import ai.chat2db.server.web.api.aspect.ConnectionInfoAspect;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.client.AzureOpenAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.chat2db.client.Chat2dbAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.fastchat.client.FastChatAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.rest.client.RestAIClient;
|
||||
import ai.chat2db.server.web.api.controller.config.request.AIConfigCreateRequest;
|
||||
import ai.chat2db.server.web.api.controller.config.request.SystemConfigRequest;
|
||||
import ai.chat2db.server.web.api.util.OpenAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.openai.client.OpenAIClient;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -83,6 +84,9 @@ public class ConfigController {
|
||||
case AZUREAI:
|
||||
saveAzureAIConfig(request);
|
||||
break;
|
||||
case FASTCHATAI:
|
||||
saveFastChatAIConfig(request);
|
||||
break;
|
||||
}
|
||||
return ActionResult.isSuccess();
|
||||
}
|
||||
@ -159,6 +163,24 @@ public class ConfigController {
|
||||
AzureOpenAIClient.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* save common fast chat ai config
|
||||
*
|
||||
* @param request
|
||||
*/
|
||||
private void saveFastChatAIConfig(AIConfigCreateRequest request) {
|
||||
SystemConfigParam apikeyParam = SystemConfigParam.builder().code(FastChatAIClient.FASTCHAT_API_KEY)
|
||||
.content(request.getApiKey()).build();
|
||||
configService.createOrUpdate(apikeyParam);
|
||||
SystemConfigParam apiHostParam = SystemConfigParam.builder().code(FastChatAIClient.FASTCHAT_HOST)
|
||||
.content(request.getApiHost()).build();
|
||||
configService.createOrUpdate(apiHostParam);
|
||||
SystemConfigParam modelParam = SystemConfigParam.builder().code(FastChatAIClient.FASTCHAT_MODEL)
|
||||
.content(request.getModel()).build();
|
||||
configService.createOrUpdate(modelParam);
|
||||
FastChatAIClient.refresh();
|
||||
}
|
||||
|
||||
@GetMapping("/system_config/{code}")
|
||||
public DataResult<Config> getSystemConfig(@PathVariable("code") String code) {
|
||||
DataResult<Config> result = configService.find(code);
|
||||
@ -221,6 +243,14 @@ public class ConfigController {
|
||||
config.setStream(Objects.nonNull(restAiHttpMethod.getData()) ? Boolean.valueOf(
|
||||
restAiHttpMethod.getData().getContent()) : Boolean.TRUE);
|
||||
break;
|
||||
case FASTCHATAI:
|
||||
DataResult<Config> fastChatApiKey = configService.find(FastChatAIClient.FASTCHAT_API_KEY);
|
||||
DataResult<Config> fastChatApiHost = configService.find(FastChatAIClient.FASTCHAT_HOST);
|
||||
DataResult<Config> fastChatModel = configService.find(FastChatAIClient.FASTCHAT_MODEL);
|
||||
config.setApiKey(Objects.nonNull(fastChatApiKey.getData()) ? fastChatApiKey.getData().getContent() : "");
|
||||
config.setApiHost(Objects.nonNull(fastChatApiHost.getData()) ? fastChatApiHost.getData().getContent() : "");
|
||||
config.setModel(Objects.nonNull(fastChatModel.getData()) ? fastChatModel.getData().getContent() : "");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -228,153 +258,4 @@ public class ConfigController {
|
||||
return DataResult.of(config);
|
||||
}
|
||||
|
||||
///**
|
||||
// * save ai config
|
||||
// *
|
||||
// * @param request
|
||||
// * @return
|
||||
// */
|
||||
//@PostMapping("/system_config/chatgpt")
|
||||
//public ActionResult addAiSystemConfig(@RequestBody AISystemConfigRequest request) {
|
||||
// String sqlSource = StringUtils.isNotBlank(request.getAiSqlSource()) ? request.getAiSqlSource()
|
||||
// : AiSqlSourceEnum.CHAT2DBAI.getCode();
|
||||
// AiSqlSourceEnum aiSqlSourceEnum = AiSqlSourceEnum.getByName(sqlSource);
|
||||
// if (Objects.isNull(aiSqlSourceEnum)) {
|
||||
// aiSqlSourceEnum = AiSqlSourceEnum.CHAT2DBAI;
|
||||
// sqlSource = AiSqlSourceEnum.CHAT2DBAI.getCode();
|
||||
// }
|
||||
// SystemConfigParam param = SystemConfigParam.builder().code(RestAIClient.AI_SQL_SOURCE).content(sqlSource)
|
||||
// .build();
|
||||
// configService.createOrUpdate(param);
|
||||
//
|
||||
// switch (Objects.requireNonNull(aiSqlSourceEnum)) {
|
||||
// case OPENAI :
|
||||
// saveOpenAIConfig(request);
|
||||
// break;
|
||||
// case CHAT2DBAI:
|
||||
// saveChat2dbAIConfig(request);
|
||||
// break;
|
||||
// case RESTAI :
|
||||
// saveRestAIConfig(request);
|
||||
// break;
|
||||
// case AZUREAI :
|
||||
// saveAzureAIConfig(request);
|
||||
// break;
|
||||
// }
|
||||
// return ActionResult.isSuccess();
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * 保存OPENAI相关配置
|
||||
// *
|
||||
// * @param request
|
||||
// */
|
||||
//private void saveOpenAIConfig(AISystemConfigRequest request) {
|
||||
// SystemConfigParam param = SystemConfigParam.builder().code(OpenAIClient.OPENAI_KEY).content(
|
||||
// request.getApiKey()).build();
|
||||
// configService.createOrUpdate(param);
|
||||
// SystemConfigParam hostParam = SystemConfigParam.builder().code(OpenAIClient.OPENAI_HOST).content(
|
||||
// request.getApiHost()).build();
|
||||
// configService.createOrUpdate(hostParam);
|
||||
// SystemConfigParam httpProxyHostParam = SystemConfigParam.builder().code(OpenAIClient.PROXY_HOST).content(
|
||||
// request.getHttpProxyHost()).build();
|
||||
// configService.createOrUpdate(httpProxyHostParam);
|
||||
// SystemConfigParam httpProxyPortParam = SystemConfigParam.builder().code(OpenAIClient.PROXY_PORT).content(
|
||||
// request.getHttpProxyPort()).build();
|
||||
// configService.createOrUpdate(httpProxyPortParam);
|
||||
// OpenAIClient.refresh();
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * 保存RESTAI接口相关配置
|
||||
// *
|
||||
// * @param request
|
||||
// */
|
||||
//private void saveRestAIConfig(AISystemConfigRequest request) {
|
||||
// SystemConfigParam restParam = SystemConfigParam.builder().code(RestAIClient.REST_AI_URL).content(
|
||||
// request.getRestAiUrl())
|
||||
// .build();
|
||||
// configService.createOrUpdate(restParam);
|
||||
// SystemConfigParam methodParam = SystemConfigParam.builder().code(RestAIClient.REST_AI_STREAM_OUT).content(
|
||||
// request.getRestAiStream().toString()).build();
|
||||
// configService.createOrUpdate(methodParam);
|
||||
// RestAIClient.refresh();
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * 保存azure配置
|
||||
// *
|
||||
// * @param request
|
||||
// */
|
||||
//private void saveAzureAIConfig(AISystemConfigRequest request) {
|
||||
// SystemConfigParam apikeyParam = SystemConfigParam.builder().code(AzureOpenAIClient.AZURE_CHATGPT_API_KEY)
|
||||
// .content(
|
||||
// request.getAzureApiKey()).build();
|
||||
// configService.createOrUpdate(apikeyParam);
|
||||
// SystemConfigParam endpointParam = SystemConfigParam.builder().code(AzureOpenAIClient
|
||||
// .AZURE_CHATGPT_ENDPOINT).content(
|
||||
// request.getAzureEndpoint()).build();
|
||||
// configService.createOrUpdate(endpointParam);
|
||||
// SystemConfigParam modelParam = SystemConfigParam.builder().code(AzureOpenAIClient
|
||||
// .AZURE_CHATGPT_DEPLOYMENT_ID).content(
|
||||
// request.getAzureDeploymentId()).build();
|
||||
// configService.createOrUpdate(modelParam);
|
||||
// AzureOpenAIClient.refresh();
|
||||
//}
|
||||
|
||||
///**
|
||||
// * 查询ChatGPT相关配置
|
||||
// *
|
||||
// * @return
|
||||
// */
|
||||
//@GetMapping("/system_config/chatgpt")
|
||||
//public DataResult<ChatGptConfig> getChatGptSystemConfig() {
|
||||
// DataResult<Config> apiKey = configService.find(OpenAIClient.OPENAI_KEY);
|
||||
// DataResult<Config> apiHost = configService.find(OpenAIClient.OPENAI_HOST);
|
||||
// DataResult<Config> httpProxyHost = configService.find(OpenAIClient.PROXY_HOST);
|
||||
// DataResult<Config> httpProxyPort = configService.find(OpenAIClient.PROXY_PORT);
|
||||
// DataResult<Config> aiSqlSource = configService.find(RestAIClient.AI_SQL_SOURCE);
|
||||
// DataResult<Config> restAiUrl = configService.find(RestAIClient.REST_AI_URL);
|
||||
// DataResult<Config> restAiHttpMethod = configService.find(RestAIClient.REST_AI_STREAM_OUT);
|
||||
// DataResult<Config> azureApiKey = configService.find(AzureOpenAIClient.AZURE_CHATGPT_API_KEY);
|
||||
// DataResult<Config> azureEndpoint = configService.find(AzureOpenAIClient.AZURE_CHATGPT_ENDPOINT);
|
||||
// DataResult<Config> azureDeployId = configService.find(AzureOpenAIClient.AZURE_CHATGPT_DEPLOYMENT_ID);
|
||||
// ChatGptConfig config = new ChatGptConfig();
|
||||
//
|
||||
// String sqlSource = Objects.nonNull(aiSqlSource.getData()) ? aiSqlSource.getData().getContent() :
|
||||
// AiSqlSourceEnum.CHAT2DBAI.getCode();
|
||||
// AiSqlSourceEnum aiSqlSourceEnum = AiSqlSourceEnum.getByName(sqlSource);
|
||||
// if (Objects.isNull(aiSqlSourceEnum)) {
|
||||
// aiSqlSourceEnum = AiSqlSourceEnum.CHAT2DBAI;
|
||||
// sqlSource = AiSqlSourceEnum.CHAT2DBAI.getCode();
|
||||
// }
|
||||
// config.setAiSqlSource(sqlSource);
|
||||
// switch (Objects.requireNonNull(aiSqlSourceEnum)) {
|
||||
// case OPENAI :
|
||||
// config.setApiKey(Objects.nonNull(apiKey.getData()) ? apiKey.getData().getContent() : null);
|
||||
// config.setApiHost(Objects.nonNull(apiHost.getData()) ? apiHost.getData().getContent() : null);
|
||||
// config.setChat2dbApiKey("");
|
||||
// config.setChat2dbApiHost("");
|
||||
// break;
|
||||
// case CHAT2DBAI:
|
||||
// config.setApiKey("");
|
||||
// config.setApiHost("");
|
||||
// config.setChat2dbApiKey(Objects.nonNull(apiKey.getData()) ? apiKey.getData().getContent() : null);
|
||||
// config.setChat2dbApiHost(Objects.nonNull(apiHost.getData()) ? apiHost.getData().getContent() : null);
|
||||
// break;
|
||||
// }
|
||||
// config.setRestAiUrl(Objects.nonNull(restAiUrl.getData()) ? restAiUrl.getData().getContent() : null);
|
||||
// config.setRestAiStream(Objects.nonNull(restAiHttpMethod.getData()) ? Boolean.valueOf(
|
||||
// restAiHttpMethod.getData().getContent()) : Boolean.TRUE);
|
||||
// config.setHttpProxyHost(Objects.nonNull(httpProxyHost.getData()) ? httpProxyHost.getData().getContent() :
|
||||
// null);
|
||||
// config.setHttpProxyPort(Objects.nonNull(httpProxyPort.getData()) ? httpProxyPort.getData().getContent() :
|
||||
// null);
|
||||
// config.setAzureApiKey(Objects.nonNull(azureApiKey.getData()) ? azureApiKey.getData().getContent() : null);
|
||||
// config.setAzureEndpoint(Objects.nonNull(azureEndpoint.getData()) ? azureEndpoint.getData().getContent() :
|
||||
// null);
|
||||
// config.setAzureDeploymentId(Objects.nonNull(azureDeployId.getData()) ? azureDeployId.getData().getContent()
|
||||
// : null);
|
||||
// return DataResult.of(config);
|
||||
//}
|
||||
}
|
||||
|
Reference in New Issue
Block a user