mirror of
https://github.com/CodePhiliaX/Chat2DB.git
synced 2025-08-02 05:20:15 +08:00
Merge remote-tracking branch 'origin/developing' into developing
This commit is contained in:
@ -38,10 +38,6 @@
|
||||
<groupId>com.unfbx</groupId>
|
||||
<artifactId>chatgpt-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.azure</groupId>
|
||||
<artifactId>azure-ai-openai</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.theokanning.openai-gpt3-java</groupId>
|
||||
<artifactId>service</artifactId>
|
||||
|
@ -16,18 +16,18 @@ import ai.chat2db.server.domain.api.param.TableQueryParam;
|
||||
import ai.chat2db.server.domain.api.service.ConfigService;
|
||||
import ai.chat2db.server.domain.api.service.DataSourceService;
|
||||
import ai.chat2db.server.domain.api.service.TableService;
|
||||
import ai.chat2db.server.tools.common.util.I18nUtils;
|
||||
import ai.chat2db.server.web.api.controller.ai.azure.client.AzureOpenAIClient;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.AzureOpenAIEventSourceListener;
|
||||
import ai.chat2db.spi.model.TableColumn;
|
||||
import ai.chat2db.server.tools.base.wrapper.result.DataResult;
|
||||
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.config.LocalCache;
|
||||
import ai.chat2db.server.web.api.controller.ai.converter.ChatConverter;
|
||||
import ai.chat2db.server.web.api.controller.ai.enums.GptVersionType;
|
||||
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.OpenAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.listener.RestAIEventSourceListener;
|
||||
import ai.chat2db.server.web.api.controller.ai.request.ChatQueryRequest;
|
||||
@ -35,10 +35,9 @@ 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.spi.model.TableColumn;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.azure.ai.openai.models.ChatMessage;
|
||||
import com.azure.ai.openai.models.ChatRole;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
@ -357,7 +356,7 @@ public class ChatController {
|
||||
prompt.length() / TOKEN_CONVERT_CHAR_LENGTH);
|
||||
throw new ParamBusinessException();
|
||||
}
|
||||
List<ChatMessage> messages = (List<ChatMessage>)LocalCache.CACHE.get(uid);
|
||||
List<AzureChatMessage> messages = (List<AzureChatMessage>)LocalCache.CACHE.get(uid);
|
||||
if (CollectionUtils.isNotEmpty(messages)) {
|
||||
if (messages.size() >= contextLength) {
|
||||
messages = messages.subList(1, contextLength);
|
||||
@ -365,12 +364,13 @@ public class ChatController {
|
||||
} else {
|
||||
messages = Lists.newArrayList();
|
||||
}
|
||||
ChatMessage currentMessage = new ChatMessage(ChatRole.USER).setContent(prompt);
|
||||
AzureChatMessage currentMessage = new AzureChatMessage(AzureChatRole.USER).setContent(prompt);
|
||||
messages.add(currentMessage);
|
||||
|
||||
sseEmitter.send(SseEmitter.event().id(uid).name("sseEmitter connected!!!!").data(LocalDateTime.now()).reconnectTime(3000));
|
||||
sseEmitter.onCompletion(() -> {
|
||||
log.info(LocalDateTime.now() + ", uid#" + uid + ", sseEmitter on completion");
|
||||
SseEmitter.event().id("[DONE]").data("[DONE]");
|
||||
});
|
||||
sseEmitter.onTimeout(
|
||||
() -> log.info(LocalDateTime.now() + ", uid#" + uid + ", sseEmitter on timeout#" + sseEmitter.getTimeout()));
|
||||
|
@ -69,7 +69,8 @@ public class AzureOpenAIClient {
|
||||
deployId = deployConfig.getContent();
|
||||
}
|
||||
log.info("refresh azure openai apikey:{}", maskApiKey(key));
|
||||
OPEN_AI_CLIENT = new AzureOpenAiStreamClient(key, apiEndpoint, deployId);
|
||||
OPEN_AI_CLIENT = AzureOpenAiStreamClient.builder().apiKey(key).endpoint(apiEndpoint).deployId(deployId)
|
||||
.build();
|
||||
apiKey = key;
|
||||
}
|
||||
|
||||
|
@ -2,21 +2,25 @@ package ai.chat2db.server.web.api.controller.ai.azure.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ai.chat2db.server.tools.common.exception.ParamBusinessException;
|
||||
import com.azure.ai.openai.OpenAIClient;
|
||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.ai.openai.models.ChatChoice;
|
||||
import com.azure.ai.openai.models.ChatCompletions;
|
||||
import com.azure.ai.openai.models.ChatCompletionsOptions;
|
||||
import com.azure.ai.openai.models.ChatMessage;
|
||||
import com.azure.ai.openai.models.CompletionsUsage;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
import com.azure.core.util.IterableStream;
|
||||
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 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.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* 自定义AI接口client
|
||||
@ -26,31 +30,116 @@ import org.apache.commons.lang3.StringUtils;
|
||||
@Slf4j
|
||||
public class AzureOpenAiStreamClient {
|
||||
|
||||
/**
|
||||
* apikey
|
||||
*/
|
||||
@Getter
|
||||
@NotNull
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* endpoint
|
||||
*/
|
||||
@Getter
|
||||
@NotNull
|
||||
private String endpoint;
|
||||
|
||||
/**
|
||||
* deployId
|
||||
*/
|
||||
@Getter
|
||||
private String deployId;
|
||||
|
||||
/**
|
||||
* client
|
||||
* okHttpClient
|
||||
*/
|
||||
private OpenAIClient client;
|
||||
@Getter
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
|
||||
/**
|
||||
* 构造实例对象
|
||||
*
|
||||
* @param apiKey
|
||||
* @param endpoint
|
||||
* @param builder
|
||||
*/
|
||||
public AzureOpenAiStreamClient(String apiKey, String endpoint, String deployId) {
|
||||
this.deployId = deployId;
|
||||
if (StringUtils.isBlank(apiKey)) {
|
||||
return;
|
||||
private AzureOpenAiStreamClient(Builder builder) {
|
||||
this.apiKey = builder.apiKey;
|
||||
this.endpoint = builder.endpoint;
|
||||
this.deployId = builder.deployId;
|
||||
if (Objects.isNull(builder.okHttpClient)) {
|
||||
builder.okHttpClient = this.okHttpClient();
|
||||
}
|
||||
this.client = new OpenAIClientBuilder()
|
||||
.credential(new AzureKeyCredential(apiKey))
|
||||
.endpoint(endpoint)
|
||||
.buildClient();
|
||||
okHttpClient = builder.okHttpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* okhttpclient
|
||||
*/
|
||||
private OkHttpClient okHttpClient() {
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.addInterceptor(new AzureHeaderAuthorizationInterceptor(this.apiKey))
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.writeTimeout(50, TimeUnit.SECONDS)
|
||||
.readTimeout(50, TimeUnit.SECONDS)
|
||||
.build();
|
||||
return okHttpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static AzureOpenAiStreamClient.Builder builder() {
|
||||
return new AzureOpenAiStreamClient.Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String apiKey;
|
||||
|
||||
private String endpoint;
|
||||
|
||||
private String deployId;
|
||||
|
||||
/**
|
||||
* 自定义OkhttpClient
|
||||
*/
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public AzureOpenAiStreamClient.Builder apiKey(String apiKeyValue) {
|
||||
this.apiKey = apiKeyValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endpointValue
|
||||
* @return
|
||||
*/
|
||||
public AzureOpenAiStreamClient.Builder endpoint(String endpointValue) {
|
||||
this.endpoint = endpointValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param deployIdValue
|
||||
* @return
|
||||
*/
|
||||
public AzureOpenAiStreamClient.Builder deployId(String deployIdValue) {
|
||||
this.deployId = deployIdValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AzureOpenAiStreamClient.Builder okHttpClient(OkHttpClient val) {
|
||||
this.okHttpClient = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AzureOpenAiStreamClient build() {
|
||||
return new AzureOpenAiStreamClient(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,49 +148,40 @@ public class AzureOpenAiStreamClient {
|
||||
* @param chatMessages
|
||||
* @param eventSourceListener
|
||||
*/
|
||||
public void streamCompletions(List<ChatMessage> chatMessages, EventSourceListener eventSourceListener) {
|
||||
public void streamCompletions(List<AzureChatMessage> chatMessages, EventSourceListener eventSourceListener) {
|
||||
if (CollectionUtils.isEmpty(chatMessages)) {
|
||||
log.error("参数异常:Azure Prompt不能为空");
|
||||
log.error("param error:Azure Prompt cannot be empty");
|
||||
throw new ParamBusinessException("prompt");
|
||||
}
|
||||
if (Objects.isNull(eventSourceListener)) {
|
||||
log.error("参数异常:AzureEventSourceListener不能为空");
|
||||
log.error("param error:AzureEventSourceListener cannot be empty");
|
||||
throw new ParamBusinessException();
|
||||
}
|
||||
log.info("开始调用Azure Open AI, prompt:{}", chatMessages.get(chatMessages.size() - 1).getContent());
|
||||
log.info("Azure Open AI, prompt:{}", chatMessages.get(chatMessages.size() - 1).getContent());
|
||||
try {
|
||||
IterableStream<ChatCompletions> chatCompletionsStream = client.getChatCompletionsStream(deployId,
|
||||
new ChatCompletionsOptions(chatMessages));
|
||||
|
||||
chatCompletionsStream.forEach(chatCompletions -> {
|
||||
String text = "";
|
||||
log.info("Model ID={} is created at {}.", chatCompletions.getId(),
|
||||
chatCompletions.getCreated());
|
||||
for (ChatChoice choice : chatCompletions.getChoices()) {
|
||||
ChatMessage message = choice.getDelta();
|
||||
if (message != null) {
|
||||
log.info("Index: {}, Chat Role: {}", choice.getIndex(), message.getRole());
|
||||
text = message.getContent();
|
||||
}
|
||||
}
|
||||
if (Objects.nonNull(text)) {
|
||||
eventSourceListener.onEvent(null, "[DATA]", null, text);
|
||||
}
|
||||
CompletionsUsage 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());
|
||||
}
|
||||
});
|
||||
log.info("结束调用非流式输出自定义AI");
|
||||
AzureChatCompletionsOptions chatCompletionsOptions = new AzureChatCompletionsOptions(chatMessages);
|
||||
chatCompletionsOptions.setStream(true);
|
||||
chatCompletionsOptions.setModel(this.deployId);
|
||||
|
||||
EventSource.Factory factory = EventSources.createFactory(this.okHttpClient);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String requestBody = mapper.writeValueAsString(chatCompletionsOptions);
|
||||
if (!endpoint.endsWith("/")) {
|
||||
endpoint = endpoint + "/";
|
||||
}
|
||||
String url = this.endpoint + "openai/deployments/"+ deployId + "/chat/completions?api-version=2023-05-15";
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody))
|
||||
.build();
|
||||
//创建事件
|
||||
EventSource eventSource = factory.newEventSource(request, eventSourceListener);
|
||||
log.info("finish invoking azure ai");
|
||||
} catch (Exception e) {
|
||||
log.error("请求参数解析异常", e);
|
||||
log.error("azure ai error", e);
|
||||
eventSourceListener.onFailure(null, e, null);
|
||||
throw new ParamBusinessException();
|
||||
} finally {
|
||||
eventSourceListener.onEvent(null, "[DONE]", null, "[DONE]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,42 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.interceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.http.ContentType;
|
||||
import cn.hutool.http.Header;
|
||||
import lombok.Getter;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 描述:请求增加header apikey
|
||||
*
|
||||
* @author grt
|
||||
* @since 2023-03-23
|
||||
*/
|
||||
@Getter
|
||||
public class AzureHeaderAuthorizationInterceptor implements Interceptor {
|
||||
|
||||
private String apiKey;
|
||||
|
||||
public AzureHeaderAuthorizationInterceptor(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request original = chain.request();
|
||||
Request request = original.newBuilder()
|
||||
.header("api-key", apiKey)
|
||||
.header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
|
||||
.method(original.method(), original.body())
|
||||
.build();
|
||||
return chain.proceed(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
// 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;
|
||||
|
||||
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 chat 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 AzureChatChoice {
|
||||
|
||||
/*
|
||||
* The chat message for a given chat completions prompt.
|
||||
*/
|
||||
@JsonProperty(value = "message")
|
||||
private AzureChatMessage message;
|
||||
|
||||
/*
|
||||
* The ordered index associated with this chat completions choice.
|
||||
*/
|
||||
@JsonProperty(value = "index")
|
||||
private int index;
|
||||
|
||||
/*
|
||||
* The reason that this chat completions choice completed its generated.
|
||||
*/
|
||||
@JsonProperty(value = "finish_reason")
|
||||
private AzureCompletionsFinishReason finishReason;
|
||||
|
||||
/*
|
||||
* The delta message content for a streaming response.
|
||||
*/
|
||||
@JsonProperty(value = "delta")
|
||||
private AzureChatMessage delta;
|
||||
|
||||
/**
|
||||
* Creates an instance of ChatChoice class.
|
||||
*
|
||||
* @param index the index value to set.
|
||||
* @param finishReason the finishReason value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private AzureChatChoice(
|
||||
@JsonProperty(value = "index") int index,
|
||||
@JsonProperty(value = "finish_reason") AzureCompletionsFinishReason finishReason) {
|
||||
this.index = index;
|
||||
this.finishReason = finishReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message property: The chat message for a given chat completions prompt.
|
||||
*
|
||||
* @return the message value.
|
||||
*/
|
||||
public AzureChatMessage getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index property: The ordered index associated with this chat completions choice.
|
||||
*
|
||||
* @return the index value.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finishReason property: The reason that this chat completions choice completed its generated.
|
||||
*
|
||||
* @return the finishReason value.
|
||||
*/
|
||||
public AzureCompletionsFinishReason getFinishReason() {
|
||||
return this.finishReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delta property: The delta message content for a streaming response.
|
||||
*
|
||||
* @return the delta value.
|
||||
*/
|
||||
public AzureChatMessage getDelta() {
|
||||
return this.delta;
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AzureChatCompletions {
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* 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<AzureChatChoice> choices;
|
||||
|
||||
/*
|
||||
* Usage information for tokens processed and generated as part of this completions operation.
|
||||
*/
|
||||
private AzureCompletionsUsage 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 AzureChatCompletions(
|
||||
@JsonProperty(value = "id") String id,
|
||||
@JsonProperty(value = "created") int created,
|
||||
@JsonProperty(value = "choices") List<AzureChatChoice> choices,
|
||||
@JsonProperty(value = "usage") AzureCompletionsUsage usage) {
|
||||
this.id = id;
|
||||
this.created = created;
|
||||
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<AzureChatChoice> 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 AzureCompletionsUsage getUsage() {
|
||||
return this.usage;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,395 @@
|
||||
// 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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 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 AzureChatCompletionsOptions {
|
||||
|
||||
/*
|
||||
* 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<AzureChatMessage> messages;
|
||||
|
||||
///*
|
||||
// * The maximum number of tokens to generate.
|
||||
// */
|
||||
////@JsonProperty(value = "max_tokens")
|
||||
//private Integer maxTokens;
|
||||
//
|
||||
///*
|
||||
// * The sampling temperature to use that controls the apparent creativity of generated completions.
|
||||
// * Higher values will make output more random while lower values will make results more focused
|
||||
// * and deterministic.
|
||||
// * It is not recommended to modify temperature and top_p for the same completions request as the
|
||||
// * interaction of these two settings is difficult to predict.
|
||||
// */
|
||||
////@JsonProperty(value = "temperature")
|
||||
//private Double temperature;
|
||||
//
|
||||
///*
|
||||
// * An alternative to sampling with temperature called nucleus sampling. This value causes the
|
||||
// * model to consider the results of tokens with the provided probability mass. As an example, a
|
||||
// * value of 0.15 will cause only the tokens comprising the top 15% of probability mass to be
|
||||
// * considered.
|
||||
// * It is not recommended to modify temperature and top_p for the same completions request as the
|
||||
// * interaction of these two settings is difficult to predict.
|
||||
// */
|
||||
////@JsonProperty(value = "top_p")
|
||||
//private Double topP;
|
||||
//
|
||||
///*
|
||||
// * A map between GPT token IDs and bias scores that influences the probability of specific tokens
|
||||
// * appearing in a completions response. Token IDs are computed via external tokenizer tools, while
|
||||
// * bias scores reside in the range of -100 to 100 with minimum and maximum values corresponding to
|
||||
// * a full ban or exclusive selection of a token, respectively. The exact behavior of a given bias
|
||||
// * score varies by model.
|
||||
// */
|
||||
////@JsonProperty(value = "logit_bias")
|
||||
//private Map<String, Integer> logitBias;
|
||||
//
|
||||
///*
|
||||
// * An identifier for the caller or end user of the operation. This may be used for tracking
|
||||
// * or rate-limiting purposes.
|
||||
// */
|
||||
////@JsonProperty(value = "user")
|
||||
//private String user;
|
||||
//
|
||||
///*
|
||||
// * The number of chat completions choices that should be generated for a chat completions
|
||||
// * response.
|
||||
// * Because this setting can generate many completions, it may quickly consume your token quota.
|
||||
// * Use carefully and ensure reasonable settings for max_tokens and stop.
|
||||
// */
|
||||
////@JsonProperty(value = "n")
|
||||
//private Integer n;
|
||||
//
|
||||
///*
|
||||
// * A collection of textual sequences that will end completions generation.
|
||||
// */
|
||||
////@JsonProperty(value = "stop")
|
||||
//private List<String> stop;
|
||||
//
|
||||
///*
|
||||
// * A value that influences the probability of generated tokens appearing based on their existing
|
||||
// * presence in generated text.
|
||||
// * Positive values will make tokens less likely to appear when they already exist and increase the
|
||||
// * model's likelihood to output new topics.
|
||||
// */
|
||||
////@JsonProperty(value = "presence_penalty")
|
||||
//private Double presencePenalty;
|
||||
//
|
||||
///*
|
||||
// * A value that influences the probability of generated tokens appearing based on their cumulative
|
||||
// * frequency in generated text.
|
||||
// * Positive values will make tokens less likely to appear as their frequency increases and
|
||||
// * decrease the likelihood of the model repeating the same statements verbatim.
|
||||
// */
|
||||
////@JsonProperty(value = "frequency_penalty")
|
||||
//private Double frequencyPenalty;
|
||||
|
||||
/*
|
||||
* A value indicating whether chat completions should be streamed for this request.
|
||||
*/
|
||||
//@JsonProperty(value = "stream")
|
||||
private Boolean stream;
|
||||
//
|
||||
/*
|
||||
* The model name to provide as part of this completions request.
|
||||
* Not applicable to Azure OpenAI, where deployment information should be included in the Azure
|
||||
* resource URI that's connected to.
|
||||
*/
|
||||
//@JsonProperty(value = "model")
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* Creates an instance of ChatCompletionsOptions class.
|
||||
*
|
||||
* @param messages the messages value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
public AzureChatCompletionsOptions(@JsonProperty(value = "messages") List<AzureChatMessage> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
//
|
||||
///**
|
||||
// * Get the messages property: 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.
|
||||
// *
|
||||
// * @return the messages value.
|
||||
// */
|
||||
//public List<AzureChatMessage> getMessages() {
|
||||
// return this.messages;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the maxTokens property: The maximum number of tokens to generate.
|
||||
// *
|
||||
// * @return the maxTokens value.
|
||||
// */
|
||||
//public Integer getMaxTokens() {
|
||||
// return this.maxTokens;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the maxTokens property: The maximum number of tokens to generate.
|
||||
// *
|
||||
// * @param maxTokens the maxTokens value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setMaxTokens(Integer maxTokens) {
|
||||
// this.maxTokens = maxTokens;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the temperature property: The sampling temperature to use that controls the apparent creativity of generated
|
||||
// * completions. Higher values will make output more random while lower values will make results more focused and
|
||||
// * deterministic. It is not recommended to modify temperature and top_p for the same completions request as the
|
||||
// * interaction of these two settings is difficult to predict.
|
||||
// *
|
||||
// * @return the temperature value.
|
||||
// */
|
||||
//public Double getTemperature() {
|
||||
// return this.temperature;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the temperature property: The sampling temperature to use that controls the apparent creativity of generated
|
||||
// * completions. Higher values will make output more random while lower values will make results more focused and
|
||||
// * deterministic. It is not recommended to modify temperature and top_p for the same completions request as the
|
||||
// * interaction of these two settings is difficult to predict.
|
||||
// *
|
||||
// * @param temperature the temperature value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setTemperature(Double temperature) {
|
||||
// this.temperature = temperature;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the topP property: An alternative to sampling with temperature called nucleus sampling. This value causes the
|
||||
// * model to consider the results of tokens with the provided probability mass. As an example, a value of 0.15 will
|
||||
// * cause only the tokens comprising the top 15% of probability mass to be considered. It is not recommended to
|
||||
// * modify temperature and top_p for the same completions request as the interaction of these two settings is
|
||||
// * difficult to predict.
|
||||
// *
|
||||
// * @return the topP value.
|
||||
// */
|
||||
//public Double getTopP() {
|
||||
// return this.topP;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the topP property: An alternative to sampling with temperature called nucleus sampling. This value causes the
|
||||
// * model to consider the results of tokens with the provided probability mass. As an example, a value of 0.15 will
|
||||
// * cause only the tokens comprising the top 15% of probability mass to be considered. It is not recommended to
|
||||
// * modify temperature and top_p for the same completions request as the interaction of these two settings is
|
||||
// * difficult to predict.
|
||||
// *
|
||||
// * @param topP the topP value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setTopP(Double topP) {
|
||||
// this.topP = topP;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the logitBias property: A map between GPT token IDs and bias scores that influences the probability of
|
||||
// * specific tokens appearing in a completions response. Token IDs are computed via external tokenizer tools, while
|
||||
// * bias scores reside in the range of -100 to 100 with minimum and maximum values corresponding to a full ban or
|
||||
// * exclusive selection of a token, respectively. The exact behavior of a given bias score varies by model.
|
||||
// *
|
||||
// * @return the logitBias value.
|
||||
// */
|
||||
//public Map<String, Integer> getLogitBias() {
|
||||
// return this.logitBias;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the logitBias property: A map between GPT token IDs and bias scores that influences the probability of
|
||||
// * specific tokens appearing in a completions response. Token IDs are computed via external tokenizer tools, while
|
||||
// * bias scores reside in the range of -100 to 100 with minimum and maximum values corresponding to a full ban or
|
||||
// * exclusive selection of a token, respectively. The exact behavior of a given bias score varies by model.
|
||||
// *
|
||||
// * @param logitBias the logitBias value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setLogitBias(Map<String, Integer> logitBias) {
|
||||
// this.logitBias = logitBias;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the user property: An identifier for the caller or end user of the operation. This may be used for tracking
|
||||
// * or rate-limiting purposes.
|
||||
// *
|
||||
// * @return the user value.
|
||||
// */
|
||||
//public String getUser() {
|
||||
// return this.user;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the user property: An identifier for the caller or end user of the operation. This may be used for tracking
|
||||
// * or rate-limiting purposes.
|
||||
// *
|
||||
// * @param user the user value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setUser(String user) {
|
||||
// this.user = user;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the n property: The number of chat completions choices that should be generated for a chat completions
|
||||
// * response. Because this setting can generate many completions, it may quickly consume your token quota. Use
|
||||
// * carefully and ensure reasonable settings for max_tokens and stop.
|
||||
// *
|
||||
// * @return the n value.
|
||||
// */
|
||||
//public Integer getN() {
|
||||
// return this.n;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the n property: The number of chat completions choices that should be generated for a chat completions
|
||||
// * response. Because this setting can generate many completions, it may quickly consume your token quota. Use
|
||||
// * carefully and ensure reasonable settings for max_tokens and stop.
|
||||
// *
|
||||
// * @param n the n value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setN(Integer n) {
|
||||
// this.n = n;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the stop property: A collection of textual sequences that will end completions generation.
|
||||
// *
|
||||
// * @return the stop value.
|
||||
// */
|
||||
//public List<String> getStop() {
|
||||
// return this.stop;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the stop property: A collection of textual sequences that will end completions generation.
|
||||
// *
|
||||
// * @param stop the stop value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setStop(List<String> stop) {
|
||||
// this.stop = stop;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the presencePenalty property: A value that influences the probability of generated tokens appearing based on
|
||||
// * their existing presence in generated text. Positive values will make tokens less likely to appear when they
|
||||
// * already exist and increase the model's likelihood to output new topics.
|
||||
// *
|
||||
// * @return the presencePenalty value.
|
||||
// */
|
||||
//public Double getPresencePenalty() {
|
||||
// return this.presencePenalty;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the presencePenalty property: A value that influences the probability of generated tokens appearing based on
|
||||
// * their existing presence in generated text. Positive values will make tokens less likely to appear when they
|
||||
// * already exist and increase the model's likelihood to output new topics.
|
||||
// *
|
||||
// * @param presencePenalty the presencePenalty value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setPresencePenalty(Double presencePenalty) {
|
||||
// this.presencePenalty = presencePenalty;
|
||||
// return this;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Get the frequencyPenalty property: A value that influences the probability of generated tokens appearing based on
|
||||
// * their cumulative frequency in generated text. Positive values will make tokens less likely to appear as their
|
||||
// * frequency increases and decrease the likelihood of the model repeating the same statements verbatim.
|
||||
// *
|
||||
// * @return the frequencyPenalty value.
|
||||
// */
|
||||
//public Double getFrequencyPenalty() {
|
||||
// return this.frequencyPenalty;
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * Set the frequencyPenalty property: A value that influences the probability of generated tokens appearing based on
|
||||
// * their cumulative frequency in generated text. Positive values will make tokens less likely to appear as their
|
||||
// * frequency increases and decrease the likelihood of the model repeating the same statements verbatim.
|
||||
// *
|
||||
// * @param frequencyPenalty the frequencyPenalty value to set.
|
||||
// * @return the ChatCompletionsOptions object itself.
|
||||
// */
|
||||
//public AzureChatCompletionsOptions setFrequencyPenalty(Double frequencyPenalty) {
|
||||
// this.frequencyPenalty = frequencyPenalty;
|
||||
// return this;
|
||||
//}
|
||||
|
||||
/**
|
||||
* 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 AzureChatCompletionsOptions 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 Azure
|
||||
* OpenAI, where deployment information should be included in the Azure 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 Azure
|
||||
* OpenAI, where deployment information should be included in the Azure resource URI that's connected to.
|
||||
*
|
||||
* @param model the model value to set.
|
||||
* @return the ChatCompletionsOptions object itself.
|
||||
*/
|
||||
public AzureChatCompletionsOptions setModel(String model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AzureChatMessage {
|
||||
|
||||
|
||||
/*
|
||||
* The role associated with this message payload.
|
||||
*/
|
||||
@JsonProperty(value = "role")
|
||||
private AzureChatRole 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 AzureChatMessage(@JsonProperty(value = "role") AzureChatRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the role property: The role associated with this message payload.
|
||||
*
|
||||
* @return the role value.
|
||||
*/
|
||||
public AzureChatRole 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 AzureChatMessage setContent(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
public class AzureChatRole extends AzureExpandableStringEnum<AzureChatRole> {
|
||||
|
||||
/** The role that instructs or sets the behavior of the assistant. */
|
||||
public static final AzureChatRole SYSTEM = fromString("system");
|
||||
|
||||
/** The role that provides responses to system-instructed, user-prompted input. */
|
||||
public static final AzureChatRole ASSISTANT = fromString("assistant");
|
||||
|
||||
/** The role that provides input for chat completions. */
|
||||
public static final AzureChatRole USER = fromString("user");
|
||||
|
||||
/**
|
||||
* Creates a new instance of ChatRole value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public AzureChatRole() {}
|
||||
|
||||
/**
|
||||
* Creates or finds a ChatRole from its string representation.
|
||||
*
|
||||
* @param name a name to look for.
|
||||
* @return the corresponding ChatRole.
|
||||
*/
|
||||
@JsonCreator
|
||||
public static AzureChatRole fromString(String name) {
|
||||
return fromString(name, AzureChatRole.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets known ChatRole values.
|
||||
*
|
||||
* @return known ChatRole values.
|
||||
*/
|
||||
public static Collection<AzureChatRole> values() {
|
||||
return values(AzureChatRole.class);
|
||||
}
|
||||
}
|
@ -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.azure.models;
|
||||
|
||||
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 AzureChoice {
|
||||
|
||||
/*
|
||||
* 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 = "logprobs")
|
||||
private AzureCompletionsLogProbabilityModel logprobs;
|
||||
|
||||
/*
|
||||
* Reason for finishing
|
||||
*/
|
||||
@JsonProperty(value = "finish_reason")
|
||||
private AzureCompletionsFinishReason finishReason;
|
||||
|
||||
/**
|
||||
* Creates an instance of Choice class.
|
||||
*
|
||||
* @param text the text value to set.
|
||||
* @param index the index value to set.
|
||||
* @param logprobs the logprobs value to set.
|
||||
* @param finishReason the finishReason value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private AzureChoice(
|
||||
@JsonProperty(value = "text") String text,
|
||||
@JsonProperty(value = "index") int index,
|
||||
@JsonProperty(value = "logprobs") AzureCompletionsLogProbabilityModel logprobs,
|
||||
@JsonProperty(value = "finish_reason") AzureCompletionsFinishReason finishReason) {
|
||||
this.text = text;
|
||||
this.index = index;
|
||||
this.logprobs = logprobs;
|
||||
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 AzureCompletionsLogProbabilityModel getLogprobs() {
|
||||
return this.logprobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the finishReason property: Reason for finishing.
|
||||
*
|
||||
* @return the finishReason value.
|
||||
*/
|
||||
public AzureCompletionsFinishReason getFinishReason() {
|
||||
return this.finishReason;
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.models;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AzureCompletions {
|
||||
|
||||
/*
|
||||
* A unique identifier associated with this completions response.
|
||||
*/
|
||||
@JsonProperty(value = "id")
|
||||
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.
|
||||
*/
|
||||
@JsonProperty(value = "created")
|
||||
private int created;
|
||||
|
||||
/*
|
||||
* 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<AzureChoice> choices;
|
||||
|
||||
/*
|
||||
* Usage information for tokens processed and generated as part of this completions operation.
|
||||
*/
|
||||
@JsonProperty(value = "usage")
|
||||
private AzureCompletionsUsage usage;
|
||||
|
||||
/**
|
||||
* Creates an instance of Completions 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 AzureCompletions(
|
||||
@JsonProperty(value = "id") String id,
|
||||
@JsonProperty(value = "created") int created,
|
||||
@JsonProperty(value = "choices") List<AzureChoice> choices,
|
||||
@JsonProperty(value = "usage") AzureCompletionsUsage usage) {
|
||||
this.id = id;
|
||||
this.created = created;
|
||||
this.choices = choices;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id property: A unique identifier associated with this 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<AzureChoice> 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 AzureCompletionsUsage 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.azure.models;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
/** Representation of the manner in which a completions response concluded. */
|
||||
public final class AzureCompletionsFinishReason extends AzureExpandableStringEnum<AzureCompletionsFinishReason> {
|
||||
|
||||
/** Completions ended normally and reached its end of token generation. */
|
||||
public static final AzureCompletionsFinishReason STOPPED = fromString("stopped");
|
||||
|
||||
/** Completions exhausted available token limits before generation could complete. */
|
||||
public static final AzureCompletionsFinishReason TOKEN_LIMIT_REACHED = fromString("tokenLimitReached");
|
||||
|
||||
/**
|
||||
* Completions generated a response that was identified as potentially sensitive per content moderation policies.
|
||||
*/
|
||||
public static final AzureCompletionsFinishReason CONTENT_FILTERED = fromString("contentFiltered");
|
||||
|
||||
/**
|
||||
* Creates a new instance of CompletionsFinishReason value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public AzureCompletionsFinishReason() {}
|
||||
|
||||
/**
|
||||
* Creates or finds a CompletionsFinishReason from its string representation.
|
||||
*
|
||||
* @param name a name to look for.
|
||||
* @return the corresponding CompletionsFinishReason.
|
||||
*/
|
||||
@JsonCreator
|
||||
public static AzureCompletionsFinishReason fromString(String name) {
|
||||
return fromString(name, AzureCompletionsFinishReason.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets known CompletionsFinishReason values.
|
||||
*
|
||||
* @return known CompletionsFinishReason values.
|
||||
*/
|
||||
public static Collection<AzureCompletionsFinishReason> values() {
|
||||
return values(AzureCompletionsFinishReason.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
// 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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/** Representation of a log probabilities model for a completions generation. */
|
||||
@Data
|
||||
public final class AzureCompletionsLogProbabilityModel {
|
||||
|
||||
/*
|
||||
* The textual forms of tokens evaluated in this probability model.
|
||||
*/
|
||||
@JsonProperty(value = "tokens")
|
||||
private List<String> tokens;
|
||||
|
||||
/*
|
||||
* A collection of log probability values for the tokens in this completions data.
|
||||
*/
|
||||
@JsonProperty(value = "token_logprobs")
|
||||
private List<Double> tokenLogprobs;
|
||||
|
||||
/*
|
||||
* A mapping of tokens to maximum log probability values in this completions data.
|
||||
*/
|
||||
@JsonProperty(value = "top_logprobs")
|
||||
private List<Map<String, Double>> topLogprobs;
|
||||
|
||||
/*
|
||||
* The text offsets associated with tokens in this completions data.
|
||||
*/
|
||||
@JsonProperty(value = "text_offset")
|
||||
private List<Integer> textOffset;
|
||||
|
||||
/**
|
||||
* Creates an instance of CompletionsLogProbabilityModel class.
|
||||
*
|
||||
* @param tokens the tokens value to set.
|
||||
* @param tokenLogprobs the tokenLogprobs value to set.
|
||||
* @param topLogprobs the topLogprobs value to set.
|
||||
* @param textOffset the textOffset value to set.
|
||||
*/
|
||||
@JsonCreator
|
||||
private AzureCompletionsLogProbabilityModel(
|
||||
@JsonProperty(value = "tokens") List<String> tokens,
|
||||
@JsonProperty(value = "token_logprobs") List<Double> tokenLogprobs,
|
||||
@JsonProperty(value = "top_logprobs") List<Map<String, Double>> topLogprobs,
|
||||
@JsonProperty(value = "text_offset") List<Integer> textOffset) {
|
||||
this.tokens = tokens;
|
||||
this.tokenLogprobs = tokenLogprobs;
|
||||
this.topLogprobs = topLogprobs;
|
||||
this.textOffset = textOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tokens property: The textual forms of tokens evaluated in this probability model.
|
||||
*
|
||||
* @return the tokens value.
|
||||
*/
|
||||
public List<String> getTokens() {
|
||||
return this.tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tokenLogprobs property: A collection of log probability values for the tokens in this completions data.
|
||||
*
|
||||
* @return the tokenLogprobs value.
|
||||
*/
|
||||
public List<Double> getTokenLogprobs() {
|
||||
return this.tokenLogprobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the topLogprobs property: A mapping of tokens to maximum log probability values in this completions data.
|
||||
*
|
||||
* @return the topLogprobs value.
|
||||
*/
|
||||
public List<Map<String, Double>> getTopLogprobs() {
|
||||
return this.topLogprobs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the textOffset property: The text offsets associated with tokens in this completions data.
|
||||
*
|
||||
* @return the textOffset value.
|
||||
*/
|
||||
public List<Integer> getTextOffset() {
|
||||
return this.textOffset;
|
||||
}
|
||||
}
|
@ -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.azure.models;
|
||||
|
||||
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 AzureCompletionsUsage {
|
||||
|
||||
/*
|
||||
* 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 AzureCompletionsUsage(
|
||||
@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.azure.models;
|
||||
|
||||
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 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 static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
/**
|
||||
* Base implementation for expandable, single string enums.
|
||||
*
|
||||
* @param <T> a specific expandable enum type
|
||||
*/
|
||||
public abstract class AzureExpandableStringEnum<T extends AzureExpandableStringEnum<T>> {
|
||||
private static final Map<Class<?>, MethodHandle> CONSTRUCTORS = new ConcurrentHashMap<>();
|
||||
private static final Map<Class<?>, ConcurrentHashMap<String, ? extends AzureExpandableStringEnum<?>>> VALUES
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AzureExpandableStringEnum.class);
|
||||
private String name;
|
||||
private Class<T> clazz;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link AzureExpandableStringEnum} without a {@link #toString()} value.
|
||||
* <p>
|
||||
* This constructor shouldn't be called as it will produce a {@link AzureExpandableStringEnum} which doesn't
|
||||
* have a String enum value.
|
||||
*
|
||||
* @deprecated Use the {@link #fromString(String, Class)} factory method.
|
||||
*/
|
||||
@Deprecated
|
||||
public AzureExpandableStringEnum() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AzureExpandableStringEnum<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, AzureExpandableStringEnum::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 {}, make sure corresponding package is open to azure-core", 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 AzureExpandableStringEnum<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 ((AzureExpandableStringEnum<T>) obj).name == null;
|
||||
} else {
|
||||
return this.name.equals(((AzureExpandableStringEnum<T>) obj).name);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package ai.chat2db.server.web.api.controller.ai.azure.util;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Utility methods that aid in performing reflective operations.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public final class AzureReflectionUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AzureReflectionUtils.class);
|
||||
|
||||
private static final boolean MODULE_BASED;
|
||||
|
||||
private static final MethodHandle CLASS_GET_MODULE_METHOD_HANDLE;
|
||||
private static final MethodHandle MODULE_IS_NAMED_METHOD_HANDLE;
|
||||
private static final MethodHandle MODULE_ADD_READS_METHOD_HANDLE;
|
||||
private static final MethodHandle METHOD_HANDLES_PRIVATE_LOOKUP_IN_METHOD_HANDLE;
|
||||
private static final MethodHandle MODULE_IS_OPEN_UNCONDITIONALLY_METHOD_HANDLE;
|
||||
private static final MethodHandle MODULE_IS_OPEN_TO_OTHER_MODULE_METHOD_HANDLE;
|
||||
|
||||
private static final MethodHandles.Lookup LOOKUP;
|
||||
private static final Object CORE_MODULE;
|
||||
|
||||
private static final MethodHandle JDK_INTERNAL_PRIVATE_LOOKUP_IN_CONSTRUCTOR;
|
||||
|
||||
static {
|
||||
boolean moduleBased = false;
|
||||
MethodHandle classGetModule = null;
|
||||
MethodHandle moduleIsNamed = null;
|
||||
MethodHandle moduleAddReads = null;
|
||||
MethodHandle methodHandlesPrivateLookupIn = null;
|
||||
MethodHandle moduleIsOpenUnconditionally = null;
|
||||
MethodHandle moduleIsOpenToOtherModule = null;
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
Object coreModule = null;
|
||||
|
||||
MethodHandle jdkInternalPrivateLookupInConstructor = null;
|
||||
|
||||
try {
|
||||
Class<?> moduleClass = Class.forName("java.lang.Module");
|
||||
classGetModule = lookup.unreflect(Class.class.getDeclaredMethod("getModule"));
|
||||
moduleIsNamed = lookup.unreflect(moduleClass.getDeclaredMethod("isNamed"));
|
||||
moduleAddReads = lookup.unreflect(moduleClass.getDeclaredMethod("addReads", moduleClass));
|
||||
methodHandlesPrivateLookupIn = lookup.findStatic(MethodHandles.class, "privateLookupIn",
|
||||
MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class));
|
||||
moduleIsOpenUnconditionally = lookup.unreflect(moduleClass.getDeclaredMethod("isOpen", String.class));
|
||||
moduleIsOpenToOtherModule = lookup.unreflect(
|
||||
moduleClass.getDeclaredMethod("isOpen", String.class, moduleClass));
|
||||
|
||||
coreModule = classGetModule.invokeWithArguments(AzureReflectionUtils.class);
|
||||
moduleBased = true;
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof Error) {
|
||||
throw (Error) throwable;
|
||||
} else {
|
||||
LOGGER.error("Unable to create MethodHandles to use Java 9+ MethodHandles.privateLookupIn. "
|
||||
+ "Will attempt to fallback to using the package-private constructor.", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!moduleBased) {
|
||||
try {
|
||||
Constructor<MethodHandles.Lookup> privateLookupInConstructor =
|
||||
MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
|
||||
|
||||
if (!privateLookupInConstructor.isAccessible()) {
|
||||
privateLookupInConstructor.setAccessible(true);
|
||||
}
|
||||
|
||||
jdkInternalPrivateLookupInConstructor = lookup.unreflectConstructor(privateLookupInConstructor);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
LOGGER.error("Unable to use package-private MethodHandles.Lookup constructor.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_BASED = moduleBased;
|
||||
CLASS_GET_MODULE_METHOD_HANDLE = classGetModule;
|
||||
MODULE_IS_NAMED_METHOD_HANDLE = moduleIsNamed;
|
||||
MODULE_ADD_READS_METHOD_HANDLE = moduleAddReads;
|
||||
METHOD_HANDLES_PRIVATE_LOOKUP_IN_METHOD_HANDLE = methodHandlesPrivateLookupIn;
|
||||
MODULE_IS_OPEN_UNCONDITIONALLY_METHOD_HANDLE = moduleIsOpenUnconditionally;
|
||||
MODULE_IS_OPEN_TO_OTHER_MODULE_METHOD_HANDLE = moduleIsOpenToOtherModule;
|
||||
LOOKUP = lookup;
|
||||
CORE_MODULE = coreModule;
|
||||
JDK_INTERNAL_PRIVATE_LOOKUP_IN_CONSTRUCTOR = jdkInternalPrivateLookupInConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link MethodHandles.Lookup} to use when performing reflective operations.
|
||||
* <p>
|
||||
* If Java 8 is being used this will always return {@link MethodHandles.Lookup#publicLookup()} as Java 8 doesn't
|
||||
* have module boundaries that will prevent reflective access to the {@code targetClass}.
|
||||
* <p>
|
||||
* If Java 9 or above is being used this will return a {@link MethodHandles.Lookup} based on whether the module
|
||||
* containing the {@code targetClass} exports the package containing the class. Otherwise, the
|
||||
* {@link MethodHandles.Lookup} associated to {@code com.azure.core} will attempt to read the module containing
|
||||
* {@code targetClass}.
|
||||
*
|
||||
* @param targetClass The {@link Class} that will need to be reflectively accessed.
|
||||
* @return The {@link MethodHandles.Lookup} that will allow {@code com.azure.core} to access the {@code targetClass}
|
||||
* reflectively.
|
||||
* @throws Exception If the underlying reflective calls throw an exception.
|
||||
*/
|
||||
public static MethodHandles.Lookup getLookupToUse(Class<?> targetClass) throws Exception {
|
||||
try {
|
||||
if (MODULE_BASED) {
|
||||
Object responseModule = CLASS_GET_MODULE_METHOD_HANDLE.invoke(targetClass);
|
||||
|
||||
// The unnamed module is opened unconditionally, have Core read it and use a private proxy lookup to
|
||||
// enable all lookup scenarios.
|
||||
if (!(boolean) MODULE_IS_NAMED_METHOD_HANDLE.invoke(responseModule)) {
|
||||
MODULE_ADD_READS_METHOD_HANDLE.invokeWithArguments(CORE_MODULE, responseModule);
|
||||
return performSafePrivateLookupIn(targetClass);
|
||||
}
|
||||
|
||||
|
||||
// If the response module is the Core module return the Core private lookup.
|
||||
if (responseModule == CORE_MODULE) {
|
||||
return LOOKUP;
|
||||
}
|
||||
|
||||
// Next check if the target class module is opened either unconditionally or to Core's module. If so,
|
||||
// also use a private proxy lookup to enable all lookup scenarios.
|
||||
String packageName = targetClass.getPackage().getName();
|
||||
if ((boolean) MODULE_IS_OPEN_UNCONDITIONALLY_METHOD_HANDLE
|
||||
.invokeWithArguments(responseModule, packageName)
|
||||
|| (boolean) MODULE_IS_OPEN_TO_OTHER_MODULE_METHOD_HANDLE
|
||||
.invokeWithArguments(responseModule, packageName, CORE_MODULE)) {
|
||||
MODULE_ADD_READS_METHOD_HANDLE.invokeWithArguments(CORE_MODULE, responseModule);
|
||||
return performSafePrivateLookupIn(targetClass);
|
||||
}
|
||||
|
||||
// Otherwise, return the public lookup as there are no specialty ways to access the other module.
|
||||
return MethodHandles.publicLookup();
|
||||
} else {
|
||||
return (MethodHandles.Lookup) JDK_INTERNAL_PRIVATE_LOOKUP_IN_CONSTRUCTOR.invoke(targetClass);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
// invoke(Class<?) throws a Throwable as the underlying method being called through reflection can throw
|
||||
// anything, but the constructor being called is owned by the Java SDKs which won't throw Throwable. So,
|
||||
// only Error needs to be inspected and handled specially, otherwise it can be assumed the Throwable is
|
||||
// a type of Exception which can be thrown based on this method having Exception checked.
|
||||
if (throwable instanceof Error) {
|
||||
throw (Error) throwable;
|
||||
} else {
|
||||
throw (Exception) throwable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static MethodHandles.Lookup performSafePrivateLookupIn(Class<?> targetClass) throws Throwable {
|
||||
// MethodHandles::privateLookupIn() throws SecurityException if denied by the security manager
|
||||
if (System.getSecurityManager() == null) {
|
||||
return (MethodHandles.Lookup) METHOD_HANDLES_PRIVATE_LOOKUP_IN_METHOD_HANDLE
|
||||
.invokeExact(targetClass, LOOKUP);
|
||||
} else {
|
||||
return java.security.AccessController.doPrivileged((PrivilegedExceptionAction<MethodHandles.Lookup>) () -> {
|
||||
try {
|
||||
return (MethodHandles.Lookup) METHOD_HANDLES_PRIVATE_LOOKUP_IN_METHOD_HANDLE
|
||||
.invokeExact(targetClass, LOOKUP);
|
||||
} catch (Throwable throwable) {
|
||||
if (throwable instanceof Error) {
|
||||
throw (Error) throwable;
|
||||
} else {
|
||||
throw (Exception) throwable;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isModuleBased() {
|
||||
return MODULE_BASED;
|
||||
}
|
||||
|
||||
AzureReflectionUtils() {
|
||||
}
|
||||
}
|
@ -2,7 +2,12 @@ package ai.chat2db.server.web.api.controller.ai.listener;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.azure.ai.openai.models.Completions;
|
||||
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 com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import lombok.SneakyThrows;
|
||||
@ -25,6 +30,8 @@ public class AzureOpenAIEventSourceListener extends EventSourceListener {
|
||||
|
||||
private SseEmitter sseEmitter;
|
||||
|
||||
private ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
|
||||
public AzureOpenAIEventSourceListener(SseEmitter sseEmitter) {
|
||||
this.sseEmitter = sseEmitter;
|
||||
}
|
||||
@ -53,8 +60,31 @@ public class AzureOpenAIEventSourceListener extends EventSourceListener {
|
||||
sseEmitter.complete();
|
||||
return;
|
||||
}
|
||||
|
||||
AzureChatCompletions chatCompletions = mapper.readValue(data, AzureChatCompletions.class);
|
||||
String text = "";
|
||||
log.info("Model ID={} is created at {}.", chatCompletions.getId(),
|
||||
chatCompletions.getCreated());
|
||||
for (AzureChatChoice choice : chatCompletions.getChoices()) {
|
||||
AzureChatMessage message = choice.getDelta();
|
||||
if (message != null) {
|
||||
log.info("Index: {}, Chat Role: {}", choice.getIndex(), message.getRole());
|
||||
if (message.getContent() != null) {
|
||||
text = message.getContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AzureCompletionsUsage 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(data);
|
||||
message.setContent(text);
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id(null)
|
||||
.data(message)
|
||||
@ -89,16 +119,19 @@ public class AzureOpenAIEventSourceListener extends EventSourceListener {
|
||||
return;
|
||||
}
|
||||
ResponseBody body = response.body();
|
||||
String bodyString = null;
|
||||
String bodyString = Objects.nonNull(t) ? t.getMessage() : "";
|
||||
if (Objects.nonNull(body)) {
|
||||
bodyString = body.string();
|
||||
log.error("Azure OpenAI sse连接异常data:{},异常:{}", bodyString, t);
|
||||
if (StringUtils.isBlank(bodyString) && Objects.nonNull(t)) {
|
||||
bodyString = t.getMessage();
|
||||
}
|
||||
log.error("Azure OpenAI sse response:{}", bodyString);
|
||||
} else {
|
||||
log.error("Azure OpenAI sse连接异常data:{},异常:{}", response, t);
|
||||
log.error("Azure OpenAI sse response:{},error:{}", response, t);
|
||||
}
|
||||
eventSource.cancel();
|
||||
Message message = new Message();
|
||||
message.setContent("Azure OpenAI出现异常,请在帮助中查看详细日志:" + bodyString);
|
||||
message.setContent("Azure OpenAI error:" + bodyString);
|
||||
sseEmitter.send(SseEmitter.event()
|
||||
.id("[ERROR]")
|
||||
.data(message));
|
||||
|
Reference in New Issue
Block a user