├── .gitignore ├── LICENSE ├── README.md ├── core ├── pom.xml └── src │ └── main │ └── java │ └── xyz │ └── felh │ ├── IAPIObject.java │ ├── baidu │ ├── BaiduApiObjectWithId.java │ ├── BaiduError.java │ ├── BaiduHttpException.java │ ├── IBaiduApiObject.java │ ├── IBaiduApiRequest.java │ ├── IBaiduApiResponse.java │ ├── IBaiduBean.java │ ├── Usage.java │ ├── chat │ │ ├── ChatCompletion.java │ │ ├── ChatMessage.java │ │ ├── ChatMessageRole.java │ │ ├── CreateChatCompletionRequest.java │ │ ├── ModelType.java │ │ └── SearchInfo.java │ └── tokenizer │ │ ├── CreateTokenizerRequest.java │ │ └── Tokenizer.java │ ├── openai │ ├── DeleteResponse.java │ ├── IOpenAiApiObject.java │ ├── IOpenAiApiRequest.java │ ├── IOpenAiApiResponse.java │ ├── IOpenAiBean.java │ ├── LastError.java │ ├── OpenAiApiListResponse.java │ ├── OpenAiApiObjectWithId.java │ ├── OpenAiError.java │ ├── OpenAiHttpException.java │ ├── assistant │ │ ├── AssistToolResources.java │ │ ├── Assistant.java │ │ ├── AssistantTool.java │ │ ├── CreateAssistantRequest.java │ │ ├── IncompleteDetails.java │ │ ├── ModifyAssistantRequest.java │ │ ├── message │ │ │ ├── CreateMessageRequest.java │ │ │ ├── Message.java │ │ │ ├── MessageContent.java │ │ │ └── ModifyMessageRequest.java │ │ ├── run │ │ │ ├── CreateRunRequest.java │ │ │ ├── CreateThreadAndRunRequest.java │ │ │ ├── ModifyRunRequest.java │ │ │ ├── RequiredAction.java │ │ │ ├── Run.java │ │ │ ├── SubmitToolOutputsRequest.java │ │ │ ├── Thread.java │ │ │ ├── ToolChoice.java │ │ │ ├── ToolOutput.java │ │ │ └── TruncationStrategy.java │ │ ├── runstep │ │ │ ├── RunStep.java │ │ │ ├── StepDetails.java │ │ │ └── StepToolCall.java │ │ ├── stream │ │ │ ├── StreamEvent.java │ │ │ ├── message │ │ │ │ ├── MessageDelta.java │ │ │ │ └── MessageDeltaContent.java │ │ │ └── runstep │ │ │ │ ├── RunStepDelta.java │ │ │ │ └── RunStepDeltaContent.java │ │ ├── thread │ │ │ ├── CreateThreadRequest.java │ │ │ ├── ModifyThreadRequest.java │ │ │ └── Thread.java │ │ └── vector │ │ │ └── store │ │ │ ├── CreateVectorStoreRequest.java │ │ │ ├── FileCounts.java │ │ │ ├── ModifyVectorStoreRequest.java │ │ │ ├── VectorStore.java │ │ │ └── file │ │ │ ├── CreateVectorStoreFileRequest.java │ │ │ ├── VectorStoreFile.java │ │ │ └── batch │ │ │ ├── CreateVectorStoreFileBatchRequest.java │ │ │ └── VectorStoreFileBatch.java │ ├── audio │ │ ├── AudioModelType.java │ │ ├── AudioResponse.java │ │ ├── CreateAudioTranscriptionRequest.java │ │ ├── CreateAudioTranslationRequest.java │ │ └── CreateSpeechRequest.java │ ├── batch │ │ ├── Batch.java │ │ ├── BatchInputLineObject.java │ │ ├── BatchOutputLineObject.java │ │ └── CreateBatchRequest.java │ ├── chat │ │ ├── ChatAudio.java │ │ ├── ChatAudioFormat.java │ │ ├── ChatAudioVoice.java │ │ ├── ChatCompletion.java │ │ ├── ChatCompletionChoice.java │ │ ├── ChatMessage.java │ │ ├── ChatMessageRole.java │ │ ├── ChatModality.java │ │ ├── CreateChatCompletionRequest.java │ │ ├── Logprobs.java │ │ ├── RequestResponseFormat.java │ │ └── tool │ │ │ ├── Function.java │ │ │ ├── FunctionCall.java │ │ │ ├── Tool.java │ │ │ ├── ToolCall.java │ │ │ ├── ToolChoice.java │ │ │ └── Type.java │ ├── embedding │ │ ├── CreateEmbeddingRequest.java │ │ ├── CreateEmbeddingResponse.java │ │ └── Embedding.java │ ├── file │ │ └── File.java │ ├── fineTuning │ │ ├── CreateFineTuningJobRequest.java │ │ ├── FineTuningJob.java │ │ ├── FineTuningJobError.java │ │ ├── FineTuningJobEvent.java │ │ └── Hyperparameters.java │ ├── image │ │ ├── BaseRequest.java │ │ ├── CreateImageRequest.java │ │ ├── Image.java │ │ ├── ImageModelType.java │ │ ├── ImageQuality.java │ │ ├── ImageResponse.java │ │ ├── ImageResponseFormat.java │ │ ├── ImageSize.java │ │ ├── ImageStyle.java │ │ ├── edit │ │ │ └── CreateEditRequest.java │ │ └── variation │ │ │ └── CreateVariationRequest.java │ ├── model │ │ └── Model.java │ ├── moderation │ │ ├── CreateModerationRequest.java │ │ ├── CreateModerationResponse.java │ │ ├── Moderation.java │ │ ├── ModerationCategories.java │ │ └── ModerationCategoryScores.java │ └── usage │ │ ├── CompletionTokensDetails.java │ │ ├── PromptTokensDetails.java │ │ └── Usage.java │ └── utils │ ├── DateUtils.java │ ├── ListUtils.java │ └── Preconditions.java ├── jtokkit ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── xyz │ │ │ └── felh │ │ │ └── openai │ │ │ └── jtokkit │ │ │ ├── AbstractEncodingRegistry.java │ │ │ ├── ByteArrayWrapper.java │ │ │ ├── DefaultEncodingRegistry.java │ │ │ ├── EncodingFactory.java │ │ │ ├── Encodings.java │ │ │ ├── GptBytePairEncoding.java │ │ │ ├── LazyEncodingRegistry.java │ │ │ ├── SpecialEncoder.java │ │ │ ├── TokenEncoder.java │ │ │ ├── TokenEncoderLarge.java │ │ │ ├── api │ │ │ ├── Encoding.java │ │ │ ├── EncodingRegistry.java │ │ │ ├── EncodingResult.java │ │ │ ├── EncodingType.java │ │ │ ├── GptBytePairEncodingParams.java │ │ │ └── ModelType.java │ │ │ └── utils │ │ │ ├── ArgumentFormat.java │ │ │ ├── FunctionFormat.java │ │ │ ├── TikTokenUtils.java │ │ │ └── ToolContentFormat.java │ └── resources │ │ └── xyz │ │ └── felh │ │ └── openai │ │ └── jtokkit │ │ ├── cl100k_base.tiktoken │ │ ├── o200k_base.tiktoken │ │ ├── p50k_base.tiktoken │ │ └── r50k_base.tiktoken │ └── test │ └── java │ └── xyz │ └── felh │ └── openai │ └── jtokkit │ ├── BaseEncodingRegistryTest.java │ └── LazyEncodingRegistryTest.java ├── miniprogram_430.jpg ├── pom.xml ├── service ├── pom.xml └── src │ ├── main │ └── java │ │ └── xyz │ │ └── felh │ │ ├── StreamListener.java │ │ ├── baidu │ │ ├── BaiduAiApi.java │ │ ├── BaiduAiService.java │ │ ├── auth │ │ │ └── BceV1Signer.java │ │ ├── bean │ │ │ └── ResponseHeaders.java │ │ ├── constant │ │ │ └── BaiduAiConstants.java │ │ └── interceptor │ │ │ ├── AuthenticationInterceptor.java │ │ │ └── ExtractHeaderInterceptor.java │ │ ├── openai │ │ ├── OpenAiApi.java │ │ ├── OpenAiService.java │ │ ├── StreamToolCallsReceiver.java │ │ ├── bean │ │ │ ├── ResponseHeaders.java │ │ │ └── StreamToolCallsRequest.java │ │ ├── constant │ │ │ └── OpenAiConstants.java │ │ └── interceptor │ │ │ ├── AuthenticationInterceptor.java │ │ │ └── ExtractHeaderInterceptor.java │ │ └── utils │ │ └── SchemaUtils.java │ └── test │ └── java │ └── xyz │ └── felh │ └── openai │ ├── BaiduAiServiceTest.java │ ├── OpenAiAssistantsTest.java │ ├── OpenAiServiceTest.java │ └── OpenAiTokkitTest.java └── web.felh.xyz.png /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | target/ 3 | pom.xml.versionsBackup 4 | */pom.xml.versionsBackup -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Wang Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | xyz.felh 8 | openai-java 9 | 4.0.2024102501 10 | 11 | 12 | core 13 | jar 14 | 15 | Core of OpenAI API 16 | Core of OpenAI API 17 | https://github.com/forestwanglin/openai-java/tree/main/core 18 | 19 | 20 | 21 21 | 21 22 | 21 23 | UTF-8 24 | 25 | 26 | 27 | 28 | 29 | com.alibaba.fastjson2 30 | fastjson2 31 | 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | 37 | 38 | 39 | com.fasterxml.jackson.core 40 | jackson-annotations 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/IAPIObject.java: -------------------------------------------------------------------------------- 1 | package xyz.felh; 2 | 3 | import java.io.Serializable; 4 | 5 | public interface IAPIObject extends Serializable { 6 | } 7 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/BaiduApiObjectWithId.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * An abstract class of OpenAi API Response 9 | */ 10 | @Data 11 | public abstract class BaiduApiObjectWithId implements IBaiduApiObject { 12 | 13 | /** 14 | * A unique identifier for the chat completion. 15 | */ 16 | @JSONField(name = "id") 17 | @JsonProperty("id") 18 | private String id; 19 | 20 | /** 21 | * The object type 22 | */ 23 | @JSONField(name = "object") 24 | @JsonProperty("object") 25 | private String object; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/BaiduError.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class BaiduError implements IBaiduApiObject { 13 | 14 | @JSONField(name = "error_code") 15 | @JsonProperty("error_code") 16 | private String errorCode; 17 | 18 | @JSONField(name = "error_msg") 19 | @JsonProperty("error_msg") 20 | private String errorMsg; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/BaiduHttpException.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | /** 4 | * Runtime Exception for HTTP 5 | */ 6 | public class BaiduHttpException extends RuntimeException { 7 | 8 | public BaiduHttpException(BaiduError error, Exception parent) { 9 | super(error.getErrorMsg(), parent); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/IBaiduApiObject.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import xyz.felh.IAPIObject; 4 | 5 | /** 6 | * An interface class for all api return bean 7 | */ 8 | public interface IBaiduApiObject extends IAPIObject { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/IBaiduApiRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for request 7 | */ 8 | public interface IBaiduApiRequest extends Serializable { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/IBaiduApiResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | /** 4 | * Interface for all response 5 | */ 6 | public interface IBaiduApiResponse extends IBaiduApiObject { 7 | } 8 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/IBaiduBean.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for bean 7 | */ 8 | public interface IBaiduBean extends Serializable { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/Usage.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class Usage implements IBaiduApiObject { 9 | 10 | /** 11 | * The number of prompt tokens used. 12 | */ 13 | @JSONField(name = "prompt_tokens") 14 | @JsonProperty("prompt_tokens") 15 | private Long promptTokens; 16 | 17 | /** 18 | * The number of completion tokens used. 19 | */ 20 | @JSONField(name = "completion_tokens") 21 | @JsonProperty("completion_tokens") 22 | private Long completionTokens; 23 | 24 | /** 25 | * The number of total tokens used 26 | */ 27 | @JSONField(name = "total_tokens") 28 | @JsonProperty("total_tokens") 29 | private Long totalTokens; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/chat/ChatCompletion.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.chat; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.baidu.Usage; 8 | import xyz.felh.openai.OpenAiApiObjectWithId; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class ChatCompletion extends OpenAiApiObjectWithId { 13 | 14 | public static String OBJECT = "chat.completion"; 15 | public static String CHUNK_OBJECT = "chat.completion.chunk"; 16 | 17 | /** 18 | * 表示当前子句的序号。只有在流式接口模式下会返回该字段 19 | */ 20 | @JSONField(name = "sentence_id") 21 | @JsonProperty("sentence_id") 22 | private Integer sentenceId; 23 | 24 | /** 25 | * 表示当前子句是否是最后一句。只有在流式接口模式下会返回该字段 26 | */ 27 | @JSONField(name = "is_end") 28 | @JsonProperty("is_end") 29 | private Boolean isEnd; 30 | 31 | /** 32 | * 当前生成的结果是否被截断 33 | */ 34 | @JSONField(name = "is_truncated") 35 | @JsonProperty("is_truncated") 36 | private Boolean isTruncated; 37 | 38 | /** 39 | * 输出内容标识,说明: 40 | * · normal:输出内容完全由大模型生成,未触发截断、替换 41 | * · stop:输出结果命中入参stop中指定的字段后被截断 42 | * · length:达到了最大的token数,根据EB返回结果is_truncated来截断 43 | * · content_filter:输出内容被截断、兜底、替换为**等 44 | */ 45 | @JSONField(name = "finish_reason") 46 | @JsonProperty("finish_reason") 47 | private String finishReason; 48 | 49 | /** 50 | * 搜索数据,当请求参数enable_citation或enable_trace为true,并且触发搜索时,会返回该字段 51 | */ 52 | @JSONField(name = "search_info") 53 | @JsonProperty("search_info") 54 | private SearchInfo searchInfo; 55 | 56 | /** 57 | * 对话返回结果 58 | */ 59 | @JSONField(name = "result") 60 | @JsonProperty("result") 61 | private String result; 62 | 63 | /** 64 | * 表示用户输入是否存在安全风险,是否关闭当前会话,清理历史会话信息 65 | * true:是,表示用户输入存在安全风险,建议关闭当前会话,清理历史会话信息 66 | * false:否,表示用户输入无安全风险 67 | */ 68 | @JSONField(name = "need_clear_history") 69 | @JsonProperty("need_clear_history") 70 | private Boolean needClearHistory; 71 | 72 | /** 73 | * 说明:返回flag表示触发安全 74 | */ 75 | @JSONField(name = "flag") 76 | @JsonProperty("flag") 77 | private Integer flag; 78 | 79 | /** 80 | * 当need_clear_history为true时,此字段会告知第几轮对话有敏感信息,如果是当前问题,ban_round=-1 81 | */ 82 | @JSONField(name = "ban_round") 83 | @JsonProperty("ban_round") 84 | private Integer banRound; 85 | 86 | /** 87 | * token统计信息 88 | */ 89 | @JSONField(name = "usage") 90 | @JsonProperty("usage") 91 | private Usage usage; 92 | 93 | } 94 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/chat/ChatMessage.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.chat; 2 | 3 | 4 | import com.alibaba.fastjson2.annotation.JSONField; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.*; 7 | import xyz.felh.baidu.IBaiduBean; 8 | 9 | @Data 10 | @Builder 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class ChatMessage implements IBaiduBean { 14 | 15 | public ChatMessage(@NonNull ChatMessageRole role, String content) { 16 | this(role, content, null); 17 | } 18 | 19 | /** 20 | * 当前支持以下: 21 | * user: 表示用户 22 | * assistant: 表示对话助手 23 | */ 24 | @NonNull 25 | @JSONField(name = "role") 26 | @JsonProperty("role") 27 | private ChatMessageRole role; 28 | 29 | /** 30 | * 对话内容 31 | */ 32 | @NonNull 33 | @JSONField(name = "content") 34 | @JsonProperty("content") 35 | private String content; 36 | 37 | /** 38 | * message作者 39 | */ 40 | @JSONField(name = "name") 41 | @JsonProperty("name") 42 | private String name; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/chat/ChatMessageRole.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.chat; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | public enum ChatMessageRole { 6 | 7 | /** 8 | * content - Required The contents of the user message. 9 | * role - Required The role of the messages author, in this case user. 10 | */ 11 | USER("user"), 12 | /** 13 | * content - Required The contents of the assistant message. 14 | * role - Required The role of the messages author, in this case assistant. 15 | * tool_calls - Optional The tool calls generated by the model, such as function calls. 16 | */ 17 | ASSISTANT("assistant"); 18 | 19 | private final String value; 20 | 21 | ChatMessageRole(final String value) { 22 | this.value = value; 23 | } 24 | 25 | @JsonValue 26 | public String value() { 27 | return value; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/chat/ModelType.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.chat; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.Arrays; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | import java.util.function.Function; 9 | import java.util.stream.Collectors; 10 | 11 | @Getter 12 | public enum ModelType { 13 | 14 | // 价格参考 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/hlrk4akp7?feedback=1 15 | // 以下系列免费 16 | // ERNIE Speed系列, ERNIE Lite系列, ERNIE Tiny系列 17 | ERNIE_4_0_TURBO_8K("ERNIE-4.0-Turbo-8K", "ernie-4.0-turbo-8k", 20000, 5120, 2048), 18 | ERNIE_4_0_8K("ERNIE-4.0-8K", "completions_pro", 20000, 5120, 2048), 19 | ERNIE_4_0_8K_LATEST("ERNIE-4.0-8K-Latest", "ernie-4.0-8k-latest", 20000, 5120, 2048), 20 | ERNIE_4_0_8K_PREVIEW("ERNIE-4.0-8K-Preview", "ernie-4.0-8k-preview", 20000, 5120, 2048), 21 | ERNIE_3_5_8K("ERNIE-3.5-8K", "completions", 20000, 5120, 2048), 22 | ERNIE_3_5_128K("ERNIE-3.5-128K", "ernie-3.5-128k", 516096, 126976, 4096), 23 | YI_34B_CHAT("Yi-34B-Chat", "yi_34b_chat", 8000, 0, 0), 24 | ERNIE_SPEED_8K("ERNIE-Speed-8K", "ernie_speed", 24000, 6144, 2048), 25 | ERNIE_SPEED_128K("ERNIE-Speed-128K", "ernie-speed-128k", 516096, 126976, 4096), 26 | ERNIE_LITE_8K("ERNIE-Lite-8K", "ernie-lite-8k", 24000, 6144, 2048), 27 | ERNIE_LITE_8K_0922("ERNIE-Lite-8K-0922", "eb-instant", 11200, 7168, 1024), 28 | ERNIE_TINY_8K("ERNIE-Tiny-8K", "ERNIE_LITE_8K", 24000, 6144, 2048), 29 | ; 30 | private static final Map nameToModelType = Arrays.stream(values()) 31 | .collect(Collectors.toMap(ModelType::getName, Function.identity())); 32 | 33 | private final String name; 34 | private final String path; 35 | private final int maxContextLength; 36 | private final int maxInputToken; 37 | private final int maxOutputToken; 38 | 39 | ModelType(String name, String path, int maxContextLength, int maxInputToken, int maxOutputToken) { 40 | this.name = name; 41 | this.path = path; 42 | this.maxContextLength = maxContextLength; 43 | this.maxInputToken = maxInputToken; 44 | this.maxOutputToken = maxOutputToken; 45 | } 46 | 47 | public static Optional fromName(final String name) { 48 | return Optional.ofNullable(nameToModelType.get(name)); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/chat/SearchInfo.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.chat; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.baidu.IBaiduBean; 7 | 8 | @Data 9 | @Builder 10 | public class SearchInfo implements IBaiduBean { 11 | 12 | /** 13 | * 序号 14 | */ 15 | @JSONField(name = "index") 16 | @JsonProperty("index") 17 | private Integer index; 18 | 19 | /** 20 | * 搜索结果URL 21 | */ 22 | @JSONField(name = "url") 23 | @JsonProperty("url") 24 | private String url; 25 | 26 | /** 27 | * 搜索结果标题 28 | */ 29 | @JSONField(name = "title") 30 | @JsonProperty("title") 31 | private String title; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/tokenizer/CreateTokenizerRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.tokenizer; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.baidu.IBaiduApiRequest; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor(force = true) 12 | public class CreateTokenizerRequest implements IBaiduApiRequest { 13 | 14 | /** 15 | * prompt内容,最大 512000 字符 16 | */ 17 | @NonNull 18 | @JSONField(name = "prompt") 19 | @JsonProperty("prompt") 20 | private String prompt; 21 | 22 | /** 23 | * (1)如果填写此参数,模型可选值如下: 24 | * · ERNIE 4.0系列:ernie-4.0-8k 25 | * · ERNIE 3.5系列:ernie-3.5-8k 26 | * · ERNIE Speed系列: ernie-speed-8k、ernie-speed-128k 27 | * · ERNIE Lite系列:ernie-lite-8k 28 | * · 其他,可选值为 ernie-tiny-8k、ernie-char-8k 29 | * (2)如果值不在上述范围,model入参可以为空 30 | */ 31 | @JSONField(name = "model") 32 | @JsonProperty("model") 33 | private String model; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/baidu/tokenizer/Tokenizer.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.tokenizer; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.baidu.Usage; 8 | import xyz.felh.openai.OpenAiApiObjectWithId; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class Tokenizer extends OpenAiApiObjectWithId { 13 | 14 | public static String OBJECT = "tokenizer.erniebot"; 15 | 16 | /** 17 | * token统计信息 18 | */ 19 | @JSONField(name = "usage") 20 | @JsonProperty("usage") 21 | private Usage usage; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/DeleteResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class DeleteResponse implements IOpenAiApiResponse { 9 | 10 | /** 11 | * The id of the object. 12 | */ 13 | @JSONField(name = "id") 14 | @JsonProperty("id") 15 | private String id; 16 | 17 | /** 18 | * The type of object deleted, for example "file" or "model" 19 | */ 20 | @JSONField(name = "object") 21 | @JsonProperty("object") 22 | private String object; 23 | 24 | /** 25 | * True if successfully deleted 26 | */ 27 | @JSONField(name = "deleted") 28 | @JsonProperty("deleted") 29 | private boolean deleted; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/IOpenAiApiObject.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import xyz.felh.IAPIObject; 4 | 5 | /** 6 | * An interface class for all api return bean 7 | */ 8 | public interface IOpenAiApiObject extends IAPIObject { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/IOpenAiApiRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for request 7 | */ 8 | public interface IOpenAiApiRequest extends Serializable { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/IOpenAiApiResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | /** 4 | * Interface for all response 5 | */ 6 | public interface IOpenAiApiResponse extends IOpenAiApiObject { 7 | } 8 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/IOpenAiBean.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Interface for bean 7 | */ 8 | public interface IOpenAiBean extends Serializable { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/LastError.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class LastError implements IOpenAiBean { 9 | 10 | /** 11 | * One of server_error or rate_limit_exceeded. 12 | */ 13 | @JSONField(name = "code") 14 | @JsonProperty("code") 15 | private String code; 16 | 17 | /** 18 | * A human-readable description of the error. 19 | */ 20 | @JSONField(name = "message") 21 | @JsonProperty("message") 22 | private String message; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/OpenAiApiListResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * A List wrapper class of OpenAi API endpoints 11 | * 12 | * @param 13 | */ 14 | @Data 15 | public class OpenAiApiListResponse implements IOpenAiApiResponse { 16 | 17 | /** 18 | * always "list" 19 | */ 20 | @JSONField(name = "object") 21 | @JsonProperty("object") 22 | private String object; 23 | 24 | /** 25 | * A list containing the actual results 26 | */ 27 | @JSONField(name = "data") 28 | @JsonProperty("data") 29 | private List data; 30 | 31 | 32 | /** 33 | * 是否有更多 34 | */ 35 | @JSONField(name = "has_more") 36 | @JsonProperty("has_more") 37 | private Boolean hasMore; 38 | 39 | /** 40 | * add when list assistants 41 | */ 42 | @JSONField(name = "first_id") 43 | @JsonProperty("first_id") 44 | private String firstId; 45 | 46 | /** 47 | * add when list assistants 48 | */ 49 | @JSONField(name = "last_id") 50 | @JsonProperty("last_id") 51 | private String lastId; 52 | 53 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/OpenAiApiObjectWithId.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * An abstract class of OpenAi API Response 9 | */ 10 | @Data 11 | public abstract class OpenAiApiObjectWithId implements IOpenAiApiObject { 12 | 13 | /** 14 | * A unique identifier for the chat completion. 15 | */ 16 | @JSONField(name = "id") 17 | @JsonProperty("id") 18 | private String id; 19 | 20 | /** 21 | * The object type 22 | */ 23 | @JSONField(name = "object") 24 | @JsonProperty("object") 25 | private String object; 26 | 27 | /** 28 | * 时间戳 29 | */ 30 | @JSONField(name = "created") 31 | @JsonProperty("created") 32 | private Long created; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/OpenAiError.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class OpenAiError implements IOpenAiApiObject { 13 | 14 | @JSONField(name = "error") 15 | @JsonProperty("error") 16 | private ErrorDetail error; 17 | 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public static class ErrorDetail implements IOpenAiApiObject { 22 | /** 23 | * Human-readable error message 24 | */ 25 | @JSONField(name = "message") 26 | @JsonProperty("message") 27 | private String message; 28 | 29 | /** 30 | * OpenAI error type, for example "invalid_request_error" 31 | * Reference 32 | */ 33 | @JSONField(name = "type") 34 | @JsonProperty("type") 35 | private String type; 36 | 37 | @JSONField(name = "param") 38 | @JsonProperty("param") 39 | private String param; 40 | 41 | /** 42 | * OpenAI error code, for example "invalid_api_key" 43 | */ 44 | @JSONField(name = "code") 45 | @JsonProperty("code") 46 | private String code; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/OpenAiHttpException.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | /** 7 | * Runtime Exception for HTTP 8 | */ 9 | public class OpenAiHttpException extends RuntimeException { 10 | 11 | /** 12 | * HTTP status code 13 | */ 14 | @JSONField(name = "status_code") 15 | @JsonProperty("status_code") 16 | public final int statusCode; 17 | 18 | /** 19 | * OpenAI error code, for example "invalid_api_key" 20 | */ 21 | @JSONField(name = "code") 22 | @JsonProperty("code") 23 | public final String code; 24 | 25 | @JSONField(name = "param") 26 | @JsonProperty("param") 27 | public final String param; 28 | 29 | /** 30 | * OpenAI error type, for example "invalid_request_error" 31 | * https://platform.openai.com/docs/guides/error-codes/python-library-error-types 32 | */ 33 | public final String type; 34 | 35 | public OpenAiHttpException(OpenAiError error, Exception parent, int statusCode) { 36 | super(error.getError().getMessage(), parent); 37 | this.statusCode = statusCode; 38 | this.code = error.getError().getCode(); 39 | this.param = error.getError().getParam(); 40 | this.type = error.getError().getType(); 41 | } 42 | 43 | public static void main(String[] args) { 44 | System.out.println("ffff"); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/AssistToolResources.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiObject; 10 | import xyz.felh.openai.IOpenAiBean; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | 16 | @Data 17 | @Builder 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class AssistToolResources implements IOpenAiBean { 21 | 22 | @JSONField(name = "code_interpreter") 23 | @JsonProperty("code_interpreter") 24 | private ToolResourcesCodeInterpreter codeInterpreter; 25 | 26 | @JSONField(name = "file_search") 27 | @JsonProperty("file_search") 28 | private ToolResourcesFileSearch fileSearch; 29 | 30 | 31 | @Data 32 | @Builder 33 | @NoArgsConstructor 34 | @AllArgsConstructor 35 | public static class ToolResourcesCodeInterpreter implements IOpenAiApiObject { 36 | 37 | /** 38 | * A list of file IDs made available to the code_interpreter tool. There can be a maximum of 20 files associated with the tool. 39 | */ 40 | @JSONField(name = "file_ids") 41 | @JsonProperty("file_ids") 42 | private List fileIds; 43 | 44 | } 45 | 46 | @Data 47 | @Builder 48 | @NoArgsConstructor 49 | @AllArgsConstructor 50 | public static class ToolResourcesFileSearch implements IOpenAiApiObject { 51 | 52 | /** 53 | * A list of file IDs made available to the code_interpreter tool. There can be a maximum of 20 files associated with the tool. 54 | */ 55 | @JSONField(name = "vector_store_ids") 56 | @JsonProperty("vector_store_ids") 57 | private List vectorStoreIds; 58 | 59 | /** 60 | * A helper to create a vector store with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant. 61 | */ 62 | @JSONField(name = "vector_stores") 63 | @JsonProperty("vector_stores") 64 | private List vectorStores; 65 | 66 | } 67 | 68 | @Data 69 | @Builder 70 | @NoArgsConstructor 71 | @AllArgsConstructor 72 | public static class ToolResourcesFileSearchVectorStore implements IOpenAiApiObject { 73 | 74 | /** 75 | * A list of file IDs to add to the vector store. There can be a maximum of 10000 files in a vector store. 76 | */ 77 | @JSONField(name = "file_ids") 78 | @JsonProperty("file_ids") 79 | private List fileIds; 80 | 81 | /** 82 | * Set of 16 key-value pairs that can be attached to a vector store. This can be useful for storing additional information about the vector store in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 83 | */ 84 | @JSONField(name = "metadata") 85 | @JsonProperty("metadata") 86 | private Map metadata; 87 | 88 | } 89 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/AssistantTool.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.*; 7 | import xyz.felh.openai.IOpenAiBean; 8 | import xyz.felh.openai.chat.tool.Function; 9 | 10 | @Data 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class AssistantTool implements IOpenAiBean { 15 | 16 | /** 17 | * The type of tool being defined: code_interpreter, file_search, function 18 | */ 19 | @JSONField(name = "type") 20 | @JsonProperty("type") 21 | private Type type; 22 | 23 | /** 24 | * When type is function 25 | *

26 | * See {@link Function} 27 | */ 28 | @JSONField(name = "function") 29 | @JsonProperty("function") 30 | private Function function; 31 | 32 | @Getter 33 | public enum Type { 34 | 35 | CODE_INTERPRETER("code_interpreter"), 36 | FILE_SEARCH("file_search"), 37 | FUNCTION("function"); 38 | 39 | Type(final String value) { 40 | this.value = value; 41 | } 42 | 43 | private final String value; 44 | 45 | @JsonValue 46 | public String value() { 47 | return value; 48 | } 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/CreateAssistantRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | @ToString 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class CreateAssistantRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * ID of the model to use. You can use the List models API to see all of your available models, or see our Model overview for descriptions of them. 20 | */ 21 | @NonNull 22 | @JSONField(name = "model") 23 | @JsonProperty("model") 24 | private String model; 25 | 26 | /** 27 | * The name of the assistant. The maximum length is 256 characters. 28 | */ 29 | @JSONField(name = "name") 30 | @JsonProperty("name") 31 | private String name; 32 | 33 | /** 34 | * The description of the assistant. The maximum length is 512 characters. 35 | */ 36 | @JSONField(name = "description") 37 | @JsonProperty("description") 38 | private String description; 39 | 40 | /** 41 | * The system instructions that the assistant uses. The maximum length is 32768 characters. 42 | */ 43 | @JSONField(name = "instructions") 44 | @JsonProperty("instructions") 45 | private String instructions; 46 | 47 | /** 48 | * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types code_interpreter, file_search, or function. 49 | *

50 | * Defaults to [] 51 | *

52 | * See {@link AssistantTool} 53 | */ 54 | @JSONField(name = "tools") 55 | @JsonProperty("tools") 56 | private List tools; 57 | 58 | /** 59 | * A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 60 | */ 61 | @JSONField(name = "tool_resources") 62 | @JsonProperty("tool_resources") 63 | private AssistToolResources toolResources; 64 | 65 | /** 66 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 67 | */ 68 | @JSONField(name = "metadata") 69 | @JsonProperty("metadata") 70 | private Map metadata; 71 | 72 | /** 73 | * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. 74 | */ 75 | @JSONField(name = "temperature") 76 | @JsonProperty("temperature") 77 | private Double temperature; 78 | 79 | /** 80 | * An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. 81 | *

82 | * We generally recommend altering this or temperature but not both. 83 | */ 84 | @JSONField(name = "top_p") 85 | @JsonProperty("top_p") 86 | private Double topP; 87 | 88 | /** 89 | * Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models since gpt-3.5-turbo-1106. 90 | *

91 | * Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. 92 | *

93 | * Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length. 94 | */ 95 | @JSONField(name = "response_format") 96 | @JsonProperty("response_format") 97 | private Object responseFormat; 98 | 99 | } 100 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/IncompleteDetails.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class IncompleteDetails implements IOpenAiBean { 16 | 17 | /** 18 | * The reason the message is incomplete. 19 | */ 20 | @JSONField(name = "reason") 21 | @JsonProperty("reason") 22 | private String reason; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/ModifyAssistantRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | @ToString 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class ModifyAssistantRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * ID of the model to use. You can use the List models API to see all of your available models, or see our Model overview for descriptions of them. 20 | */ 21 | @JSONField(name = "model") 22 | @JsonProperty("model") 23 | private String model; 24 | 25 | /** 26 | * The name of the assistant. The maximum length is 256 characters. 27 | */ 28 | @JSONField(name = "name") 29 | @JsonProperty("name") 30 | private String name; 31 | 32 | /** 33 | * The description of the assistant. The maximum length is 512 characters. 34 | */ 35 | @JSONField(name = "description") 36 | @JsonProperty("description") 37 | private String description; 38 | 39 | /** 40 | * The system instructions that the assistant uses. The maximum length is 32768 characters. 41 | */ 42 | @JSONField(name = "instructions") 43 | @JsonProperty("instructions") 44 | private String instructions; 45 | 46 | /** 47 | * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types code_interpreter, retrieval, or function. 48 | *

49 | * Defaults to [] 50 | *

51 | * See {@link AssistantTool} 52 | */ 53 | @JSONField(name = "tools") 54 | @JsonProperty("tools") 55 | private List tools; 56 | 57 | /** 58 | * A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 59 | */ 60 | @JSONField(name = "tool_resources") 61 | @JsonProperty("tool_resources") 62 | private AssistToolResources toolResources; 63 | 64 | /** 65 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 66 | */ 67 | @JSONField(name = "metadata") 68 | @JsonProperty("metadata") 69 | private Map metadata; 70 | 71 | /** 72 | * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. 73 | */ 74 | @JSONField(name = "temperature") 75 | @JsonProperty("temperature") 76 | private Double temperature; 77 | 78 | /** 79 | * An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. 80 | *

81 | * We generally recommend altering this or temperature but not both. 82 | */ 83 | @JSONField(name = "top_p") 84 | @JsonProperty("top_p") 85 | private Double topP; 86 | 87 | /** 88 | * Specifies the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models since gpt-3.5-turbo-1106. 89 | *

90 | * Setting to { "type": "json_object" } enables JSON mode, which guarantees the message the model generates is valid JSON. 91 | *

92 | * Important: when using JSON mode, you must also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if finish_reason="length", which indicates the generation exceeded max_tokens or the conversation exceeded the max context length. 93 | */ 94 | @JSONField(name = "response_format") 95 | @JsonProperty("response_format") 96 | private Object responseFormat; 97 | 98 | } 99 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/message/CreateMessageRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.message; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor(force = true) 16 | public class CreateMessageRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * The role of the entity that is creating the message. Currently only user is supported. 20 | */ 21 | @NonNull 22 | @JSONField(name = "role") 23 | @JsonProperty("role") 24 | private Message.Role role; 25 | 26 | /** 27 | * The content of the message. 28 | */ 29 | @NonNull 30 | @JSONField(name = "content") 31 | @JsonProperty("content") 32 | private String content; 33 | 34 | /** 35 | * A list of files attached to the message, and the tools they were added to. 36 | */ 37 | @JSONField(name = "attachments") 38 | @JsonProperty("attachments") 39 | private List attachments; 40 | 41 | /** 42 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 43 | */ 44 | @JSONField(name = "metadata") 45 | @JsonProperty("metadata") 46 | private Map metadata; 47 | 48 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/message/ModifyMessageRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.message; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | 11 | import java.util.Map; 12 | 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor(force = true) 18 | public class ModifyMessageRequest implements IOpenAiApiRequest { 19 | 20 | /** 21 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 22 | */ 23 | @JSONField(name = "metadata") 24 | @JsonProperty("metadata") 25 | private Map metadata; 26 | 27 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/ModifyRunRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | 11 | import java.util.Map; 12 | 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor(force = true) 17 | public class ModifyRunRequest implements IOpenAiApiRequest { 18 | 19 | /** 20 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 21 | */ 22 | @JSONField(name = "metadata") 23 | @JsonProperty("metadata") 24 | private Map metadata; 25 | 26 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/RequiredAction.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Data; 7 | import lombok.Getter; 8 | import xyz.felh.openai.IOpenAiBean; 9 | import xyz.felh.openai.chat.tool.ToolCall; 10 | 11 | import java.util.List; 12 | 13 | @Data 14 | public class RequiredAction implements IOpenAiBean { 15 | 16 | /** 17 | * For now, this is always submit_tool_outputs. 18 | * See {@link Type} 19 | */ 20 | @JSONField(name = "type") 21 | @JsonProperty("type") 22 | private Type type; 23 | 24 | /** 25 | * Details on the tool outputs needed for this run to continue. 26 | *

27 | * See {@link ToolOutput} 28 | */ 29 | @JSONField(name = "submit_tool_outputs") 30 | @JsonProperty("submit_tool_outputs") 31 | private ToolOutput submitToolOutputs; 32 | 33 | @Data 34 | public static class ToolOutput { 35 | /** 36 | * A list of the relevant tool calls. 37 | *

38 | * See {@link ToolCall} 39 | */ 40 | @JSONField(name = "tool_calls") 41 | @JsonProperty("tool_calls") 42 | private List toolCalls; 43 | } 44 | 45 | @Getter 46 | public enum Type { 47 | 48 | SUBMIT_TOOL_OUTPUTS("submit_tool_outputs"); 49 | 50 | Type(final String value) { 51 | this.value = value; 52 | } 53 | 54 | private final String value; 55 | 56 | @JsonValue 57 | public String value() { 58 | return value; 59 | } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/SubmitToolOutputsRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor(force = true) 14 | public class SubmitToolOutputsRequest implements IOpenAiApiRequest { 15 | 16 | /** 17 | * A list of tools for which the outputs are being submitted. 18 | *

19 | * See {@link ToolOutput} 20 | */ 21 | @NonNull 22 | @JSONField(name = "tool_outputs") 23 | @JsonProperty("tool_outputs") 24 | private List toolOutputs; 25 | 26 | /** 27 | * If true, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a data: [DONE] message. 28 | */ 29 | @JSONField(name = "stream") 30 | @JsonProperty("stream") 31 | private Boolean stream; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/Thread.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiBean; 7 | import xyz.felh.openai.assistant.AssistToolResources; 8 | import xyz.felh.openai.assistant.message.Message; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | @Data 14 | public class Thread implements IOpenAiBean { 15 | 16 | /** 17 | * A list of messages to start the thread with. 18 | *

19 | * See {@link Message} 20 | *

21 | * role and content is required 22 | */ 23 | @JSONField(name = "messages") 24 | @JsonProperty("messages") 25 | private List messages; 26 | 27 | /** 28 | * A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 29 | */ 30 | @JSONField(name = "tool_resources") 31 | @JsonProperty("tool_resources") 32 | private AssistToolResources toolResources; 33 | 34 | /** 35 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 36 | */ 37 | @JSONField(name = "metadata") 38 | @JsonProperty("metadata") 39 | private Map metadata; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/ToolChoice.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | import xyz.felh.openai.assistant.AssistantTool; 11 | import xyz.felh.openai.chat.tool.Function; 12 | 13 | @Data 14 | @Builder 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class ToolChoice implements IOpenAiBean { 18 | 19 | /** 20 | * The type of the tool. If type is function, the function name must be set 21 | */ 22 | @JSONField(name = "type") 23 | @JsonProperty("type") 24 | private AssistantTool.Type type; 25 | 26 | /** 27 | * When type is function 28 | *

29 | * See {@link Function} 30 | */ 31 | @JSONField(name = "function") 32 | @JsonProperty("function") 33 | private Function function; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/ToolOutput.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | @Data 9 | public class ToolOutput implements IOpenAiBean { 10 | 11 | /** 12 | * The ID of the tool call in the required_action object within the run object the output is being submitted for. 13 | */ 14 | @JSONField(name = "tool_call_id") 15 | @JsonProperty("tool_call_id") 16 | private String toolCallId; 17 | 18 | /** 19 | * The output of the tool call to be submitted to continue the run. 20 | */ 21 | @JSONField(name = "output") 22 | @JsonProperty("output") 23 | private String output; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/run/TruncationStrategy.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.run; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.*; 7 | import xyz.felh.openai.IOpenAiBean; 8 | 9 | @Builder 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class TruncationStrategy implements IOpenAiBean { 14 | 15 | /** 16 | * The truncation strategy to use for the thread. The default is auto. If set to last_messages, the thread will be truncated to the n most recent messages in the thread. When set to auto, messages in the middle of the thread will be dropped to fit the context length of the model, max_prompt_tokens. 17 | */ 18 | @JSONField(name = "type") 19 | @JsonProperty("type") 20 | private Type type; 21 | 22 | /** 23 | * The number of most recent messages from the thread when constructing the context for the run. 24 | */ 25 | @JSONField(name = "last_messages") 26 | @JsonProperty("last_messages") 27 | private Integer lastMessages; 28 | 29 | @Getter 30 | public enum Type { 31 | 32 | AUTO("auto"), 33 | LAST_MESSAGES("last_messages"), 34 | MAX_PROMPT_TOKENS("max_prompt_tokens"); 35 | 36 | Type(final String value) { 37 | this.value = value; 38 | } 39 | 40 | private final String value; 41 | 42 | @JsonValue 43 | public String value() { 44 | return value; 45 | } 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/runstep/StepDetails.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.runstep; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Data; 7 | import lombok.Getter; 8 | import xyz.felh.openai.IOpenAiBean; 9 | import xyz.felh.openai.assistant.message.MessageContent; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | @Data 15 | public class StepDetails implements IOpenAiBean { 16 | 17 | /** 18 | * message_creation, tool_calls 19 | */ 20 | @JSONField(name = "type") 21 | @JsonProperty("type") 22 | private Type type; 23 | 24 | /** 25 | * Details of the message creation by the run step. 26 | */ 27 | @JSONField(name = "message_creation") 28 | @JsonProperty("message_creation") 29 | private MessageCreation messageCreation; 30 | 31 | /** 32 | * An array of tool calls the run step was involved in. These can be associated with one of three types of tools: code_interpreter, retrieval, or function. 33 | *

34 | * See {@link StepToolCall} 35 | */ 36 | @JSONField(name = "tool_calls") 37 | @JsonProperty("tool_calls") 38 | private List toolCalls; 39 | 40 | @Data 41 | public static class MessageCreation implements IOpenAiBean { 42 | /** 43 | * The ID of the message that was created by this run step. 44 | */ 45 | @JSONField(name = "message_id") 46 | @JsonProperty("message_id") 47 | private String messageId; 48 | } 49 | 50 | @Getter 51 | public enum Type { 52 | 53 | MESSAGE_CREATION("message_creation"), 54 | TOOL_CALLS("tool_calls"); 55 | 56 | private final String value; 57 | 58 | Type(final String value) { 59 | this.value = value; 60 | } 61 | 62 | @JsonValue 63 | public String value() { 64 | return value; 65 | } 66 | 67 | public static Type findByValue(String value) { 68 | return Arrays.stream(values()).filter(it -> 69 | it.value.equals(value)).findFirst().orElse(null); 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/runstep/StepToolCall.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.runstep; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @Data 12 | public class StepToolCall implements IOpenAiBean { 13 | 14 | /** 15 | * The index of the tool call in the tool calls array. 16 | */ 17 | @JSONField(name = "index") 18 | @JsonProperty("index") 19 | private Integer index; 20 | 21 | /** 22 | * The ID of the tool call object. 23 | */ 24 | @JSONField(name = "id") 25 | @JsonProperty("id") 26 | private String id; 27 | 28 | /** 29 | * The type of tool call. This is always going to be code_interpreter/file_search/function for this type of tool call. 30 | */ 31 | @JSONField(name = "type") 32 | @JsonProperty("type") 33 | private String type; 34 | 35 | /** 36 | * type = file_search 37 | * For now, this is always going to be an empty object. 38 | */ 39 | @JSONField(name = "file_search") 40 | @JsonProperty("file_search") 41 | private Map fileSearch; 42 | 43 | /** 44 | * The Code Interpreter tool call definition. 45 | */ 46 | @JSONField(name = "code_interpreter") 47 | @JsonProperty("code_interpreter") 48 | private CodeInterpreter codeInterpreter; 49 | 50 | /** 51 | * type = function 52 | * The definition of the function that was called. 53 | */ 54 | @JSONField(name = "function") 55 | @JsonProperty("function") 56 | private Function function; 57 | 58 | @Data 59 | public static class CodeInterpreter implements IOpenAiBean { 60 | /** 61 | * The input to the Code Interpreter tool call. 62 | */ 63 | @JSONField(name = "input") 64 | @JsonProperty("input") 65 | private String input; 66 | /** 67 | * The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (logs) or images (image). Each of these are represented by a different object type. 68 | */ 69 | @JSONField(name = "outputs") 70 | @JsonProperty("outputs") 71 | private List outputs; 72 | } 73 | 74 | @Data 75 | public static class CodeInterpreterOutput implements IOpenAiBean { 76 | /** 77 | * logs or image 78 | */ 79 | @JSONField(name = "type") 80 | @JsonProperty("type") 81 | private String type; 82 | 83 | /** 84 | * type = logs 85 | */ 86 | @JSONField(name = "logs") 87 | @JsonProperty("logs") 88 | private String logs; 89 | 90 | /** 91 | * type = image 92 | */ 93 | @JSONField(name = "image") 94 | @JsonProperty("image") 95 | private CodeInterpreterOutputImage image; 96 | } 97 | 98 | @Data 99 | public static class CodeInterpreterOutputImage implements IOpenAiBean { 100 | /** 101 | * The {@link xyz.felh.openai.file.File} ID of the image. 102 | */ 103 | @JSONField(name = "file_id") 104 | @JsonProperty("file_id") 105 | private String fileId; 106 | } 107 | 108 | @Data 109 | public static class Function implements IOpenAiBean { 110 | /** 111 | * The name of the function. 112 | */ 113 | @JSONField(name = "name") 114 | @JsonProperty("name") 115 | private String name; 116 | /** 117 | * The arguments passed to the function. 118 | */ 119 | @JSONField(name = "arguments") 120 | @JsonProperty("arguments") 121 | private String arguments; 122 | /** 123 | * The output of the function. This will be null if the outputs have not been submitted yet. 124 | */ 125 | @JSONField(name = "output") 126 | @JsonProperty("output") 127 | private String output; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/stream/StreamEvent.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.stream; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | /** 9 | * thread.created 10 | * data is a thread 11 | *

12 | * Occurs when a new thread is created. 13 | *

14 | * thread.run.created 15 | * data is a run 16 | *

17 | * Occurs when a new run is created. 18 | *

19 | * thread.run.queued 20 | * data is a run 21 | *

22 | * Occurs when a run moves to a queued status. 23 | *

24 | * thread.run.in_progress 25 | * data is a run 26 | *

27 | * Occurs when a run moves to an in_progress status. 28 | *

29 | * thread.run.requires_action 30 | * data is a run 31 | *

32 | * Occurs when a run moves to a requires_action status. 33 | *

34 | * thread.run.completed 35 | * data is a run 36 | *

37 | * Occurs when a run is completed. 38 | *

39 | * thread.run.failed 40 | * data is a run 41 | *

42 | * Occurs when a run fails. 43 | *

44 | * thread.run.cancelling 45 | * data is a run 46 | *

47 | * Occurs when a run moves to a cancelling status. 48 | *

49 | * thread.run.cancelled 50 | * data is a run 51 | *

52 | * Occurs when a run is cancelled. 53 | *

54 | * thread.run.expired 55 | * data is a run 56 | *

57 | * Occurs when a run expires. 58 | *

59 | * thread.run.step.created 60 | * data is a run step 61 | *

62 | * Occurs when a run step is created. 63 | *

64 | * thread.run.step.in_progress 65 | * data is a run step 66 | *

67 | * Occurs when a run step moves to an in_progress state. 68 | *

69 | * thread.run.step.delta 70 | * data is a run step delta 71 | *

72 | * Occurs when parts of a run step are being streamed. 73 | *

74 | * thread.run.step.completed 75 | * data is a run step 76 | *

77 | * Occurs when a run step is completed. 78 | *

79 | * thread.run.step.failed 80 | * data is a run step 81 | *

82 | * Occurs when a run step fails. 83 | *

84 | * thread.run.step.cancelled 85 | * data is a run step 86 | *

87 | * Occurs when a run step is cancelled. 88 | *

89 | * thread.run.step.expired 90 | * data is a run step 91 | *

92 | * Occurs when a run step expires. 93 | *

94 | * thread.message.created 95 | * data is a message 96 | *

97 | * Occurs when a message is created. 98 | *

99 | * thread.message.in_progress 100 | * data is a message 101 | *

102 | * Occurs when a message moves to an in_progress state. 103 | *

104 | * thread.message.delta 105 | * data is a message delta 106 | *

107 | * Occurs when parts of a Message are being streamed. 108 | *

109 | * thread.message.completed 110 | * data is a message 111 | *

112 | * Occurs when a message is completed. 113 | *

114 | * thread.message.incomplete 115 | * data is a message 116 | *

117 | * Occurs when a message ends before it is completed. 118 | *

119 | * error 120 | * data is an error 121 | *

122 | * Occurs when an error occurs. This can happen due to an internal server error or a timeout. 123 | *

124 | * done 125 | * data is [DONE] 126 | *

127 | * Occurs when a stream ends. 128 | */ 129 | @Data 130 | public class StreamEvent implements IOpenAiApiObject { 131 | 132 | @JSONField(name = "event") 133 | @JsonProperty("event") 134 | private String event; 135 | 136 | @JSONField(name = "data") 137 | @JsonProperty("data") 138 | private IOpenAiApiObject data; 139 | 140 | } 141 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/stream/message/MessageDelta.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.stream.message; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.openai.OpenAiApiObjectWithId; 8 | 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | public class MessageDelta extends OpenAiApiObjectWithId { 13 | 14 | public static String OBJECT = "thread.message.delta"; 15 | 16 | /** 17 | * The delta containing the fields that have changed on the Message. 18 | */ 19 | @JSONField(name = "delta") 20 | @JsonProperty("delta") 21 | private MessageDeltaContent delta; 22 | 23 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/stream/message/MessageDeltaContent.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.stream.message; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiBean; 7 | import xyz.felh.openai.assistant.message.Message; 8 | import xyz.felh.openai.assistant.message.MessageContent; 9 | 10 | import java.util.List; 11 | 12 | @Data 13 | public class MessageDeltaContent implements IOpenAiBean { 14 | 15 | @JSONField(name = "role") 16 | @JsonProperty("role") 17 | private Message.Role role; 18 | 19 | /** 20 | * The content of the message in array of text and/or images. 21 | */ 22 | @JSONField(name = "content") 23 | @JsonProperty("content") 24 | private List content; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/stream/runstep/RunStepDelta.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.stream.runstep; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.openai.OpenAiApiObjectWithId; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | public class RunStepDelta extends OpenAiApiObjectWithId { 12 | 13 | public static String OBJECT = "thread.run.step.delta"; 14 | 15 | @JSONField(name = "delta") 16 | @JsonProperty("delta") 17 | private RunStepDeltaContent delta; 18 | 19 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/stream/runstep/RunStepDeltaContent.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.stream.runstep; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiBean; 7 | import xyz.felh.openai.assistant.runstep.StepDetails; 8 | 9 | @Data 10 | public class RunStepDeltaContent implements IOpenAiBean { 11 | 12 | /** 13 | * The delta containing the fields that have changed on the run step. 14 | *

15 | * See {@link StepDetails} 16 | */ 17 | @JSONField(name = "step_details") 18 | @JsonProperty("step_details") 19 | private StepDetails stepDetails; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/thread/CreateThreadRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.thread; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | import xyz.felh.openai.assistant.AssistToolResources; 11 | import xyz.felh.openai.assistant.message.Message; 12 | 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | @Data 17 | @Builder 18 | @AllArgsConstructor 19 | @NoArgsConstructor(force = true) 20 | public class CreateThreadRequest implements IOpenAiApiRequest { 21 | 22 | /** 23 | * A list of {@link Message} to start the thread with. 24 | *

25 | * required fields: role, content 26 | */ 27 | @JSONField(name = "messages") 28 | @JsonProperty("messages") 29 | private List messages; 30 | 31 | /** 32 | * A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 33 | */ 34 | @JSONField(name = "tool_resources") 35 | @JsonProperty("tool_resources") 36 | private AssistToolResources toolResources; 37 | 38 | /** 39 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 40 | */ 41 | @JSONField(name = "metadata") 42 | @JsonProperty("metadata") 43 | private Map metadata; 44 | 45 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/thread/ModifyThreadRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.thread; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | import xyz.felh.openai.assistant.AssistToolResources; 11 | 12 | import java.util.Map; 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor(force = true) 18 | public class ModifyThreadRequest implements IOpenAiApiRequest { 19 | 20 | /** 21 | * A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 22 | */ 23 | @JSONField(name = "tool_resources") 24 | @JsonProperty("tool_resources") 25 | private AssistToolResources toolResources; 26 | 27 | /** 28 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 29 | */ 30 | @JSONField(name = "metadata") 31 | @JsonProperty("metadata") 32 | private Map metadata; 33 | 34 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/thread/Thread.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.thread; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.openai.OpenAiApiObjectWithId; 8 | import xyz.felh.openai.assistant.AssistToolResources; 9 | 10 | import java.util.Map; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class Thread extends OpenAiApiObjectWithId { 15 | 16 | public static String OBJECT = "thread"; 17 | 18 | /** 19 | * The Unix timestamp (in seconds) for when the thread was created. 20 | */ 21 | @JSONField(name = "created_at") 22 | @JsonProperty("created_at") 23 | private Integer createdAt; 24 | 25 | /** 26 | * A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the code_interpreter tool requires a list of file IDs, while the file_search tool requires a list of vector store IDs. 27 | */ 28 | @JSONField(name = "tool_resources") 29 | @JsonProperty("tool_resources") 30 | private AssistToolResources toolResources; 31 | 32 | /** 33 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 34 | */ 35 | @JSONField(name = "metadata") 36 | @JsonProperty("metadata") 37 | private Map metadata; 38 | 39 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/CreateVectorStoreRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor(force = true) 16 | public class CreateVectorStoreRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * A list of File IDs that the vector store should use. Useful for tools like file_search that can access files. 20 | */ 21 | @JSONField(name = "file_ids") 22 | @JsonProperty("file_ids") 23 | private List fileIds; 24 | 25 | /** 26 | * The name of the vector store. 27 | */ 28 | @JSONField(name = "name") 29 | @JsonProperty("name") 30 | private String name; 31 | 32 | @JSONField(name = "expires_after") 33 | @JsonProperty("expires_after") 34 | private VectorStore.ExpiresAfter expiresAfter; 35 | 36 | /** 37 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 38 | */ 39 | @JSONField(name = "metadata") 40 | @JsonProperty("metadata") 41 | private Map metadata; 42 | 43 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/FileCounts.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Data 15 | public class FileCounts implements IOpenAiBean { 16 | 17 | /** 18 | * The number of files that are currently being processed. 19 | */ 20 | @JSONField(name = "in_progress") 21 | @JsonProperty("in_progress") 22 | private Integer inProgress; 23 | 24 | /** 25 | * The number of files that have been successfully processed. 26 | */ 27 | @JSONField(name = "completed") 28 | @JsonProperty("completed") 29 | private Integer completed; 30 | 31 | /** 32 | * The number of files that have failed to process. 33 | */ 34 | @JSONField(name = "failed") 35 | @JsonProperty("failed") 36 | private Integer failed; 37 | 38 | /** 39 | * The number of files that were cancelled. 40 | */ 41 | @JSONField(name = "cancelled") 42 | @JsonProperty("cancelled") 43 | private Integer cancelled; 44 | 45 | /** 46 | * The total number of files. 47 | */ 48 | @JSONField(name = "total") 49 | @JsonProperty("total") 50 | private Integer total; 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/ModifyVectorStoreRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | 11 | import java.util.Map; 12 | 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor(force = true) 18 | public class ModifyVectorStoreRequest implements IOpenAiApiRequest { 19 | 20 | /** 21 | * The name of the vector store. 22 | */ 23 | @JSONField(name = "name") 24 | @JsonProperty("name") 25 | private String name; 26 | 27 | @JSONField(name = "expires_after") 28 | @JsonProperty("expires_after") 29 | private VectorStore.ExpiresAfter expiresAfter; 30 | 31 | /** 32 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 33 | */ 34 | @JSONField(name = "metadata") 35 | @JsonProperty("metadata") 36 | private Map metadata; 37 | 38 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/VectorStore.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.*; 7 | import xyz.felh.openai.IOpenAiBean; 8 | import xyz.felh.openai.OpenAiApiObjectWithId; 9 | 10 | import java.util.Map; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class VectorStore extends OpenAiApiObjectWithId { 15 | 16 | public static String OBJECT = "vector_store"; 17 | 18 | /** 19 | * The Unix timestamp (in seconds) for when the vector store was created. 20 | */ 21 | @JSONField(name = "created_at") 22 | @JsonProperty("created_at") 23 | private Integer createdAt; 24 | 25 | /** 26 | * The name of the vector store. 27 | */ 28 | @JSONField(name = "name") 29 | @JsonProperty("name") 30 | private String name; 31 | 32 | /** 33 | * The byte size of the vector store. 34 | */ 35 | @JSONField(name = "bytes") 36 | @JsonProperty("bytes") 37 | private Integer bytes; 38 | 39 | @JSONField(name = "file_counts") 40 | @JsonProperty("file_counts") 41 | private FileCounts fileCounts; 42 | 43 | /** 44 | * The status of the vector store, which can be either expired, in_progress, or completed. A status of completed indicates that the vector store is ready for use. 45 | */ 46 | @JSONField(name = "status") 47 | @JsonProperty("status") 48 | private Status status; 49 | 50 | /** 51 | * The expiration policy for a vector store. 52 | */ 53 | @JSONField(name = "expires_after") 54 | @JsonProperty("expires_after") 55 | private ExpiresAfter expiresAfter; 56 | 57 | /** 58 | * The Unix timestamp (in seconds) for when the vector store will expire. 59 | */ 60 | @JSONField(name = "expires_at") 61 | @JsonProperty("expires_at") 62 | private Long expiresAt; 63 | 64 | /** 65 | * The Unix timestamp (in seconds) for when the vector store was last active. 66 | */ 67 | @JSONField(name = "last_active_at") 68 | @JsonProperty("last_active_at") 69 | private Long lastActiveAt; 70 | 71 | /** 72 | * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. 73 | */ 74 | @JSONField(name = "metadata") 75 | @JsonProperty("metadata") 76 | private Map metadata; 77 | 78 | @Getter 79 | public enum Status { 80 | 81 | EXPIRED("expired"), 82 | IN_PROGRESS("in_progress"), 83 | COMPLETED("completed"); 84 | 85 | Status(final String value) { 86 | this.value = value; 87 | } 88 | 89 | private final String value; 90 | 91 | @JsonValue 92 | public String value() { 93 | return value; 94 | } 95 | 96 | } 97 | 98 | 99 | @Data 100 | @Builder 101 | @AllArgsConstructor 102 | @NoArgsConstructor 103 | public static class ExpiresAfter implements IOpenAiBean { 104 | 105 | /** 106 | * Anchor timestamp after which the expiration policy applies. Supported anchors: last_active_at. 107 | */ 108 | @JSONField(name = "anchor") 109 | @JsonProperty("anchor") 110 | private String anchor; 111 | 112 | /** 113 | * The number of days after the anchor time that the vector store will expire. 114 | */ 115 | @JSONField(name = "days") 116 | @JsonProperty("days") 117 | private Integer days; 118 | 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/file/CreateVectorStoreFileRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store.file; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | 11 | 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor(force = true) 16 | public class CreateVectorStoreFileRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * A File ID that the vector store should use. Useful for tools like file_search that can access files. 20 | */ 21 | @JSONField(name = "file_id") 22 | @JsonProperty("file_id") 23 | private String fileId; 24 | 25 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/file/VectorStoreFile.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store.file; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import xyz.felh.openai.LastError; 10 | import xyz.felh.openai.OpenAiApiObjectWithId; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class VectorStoreFile extends OpenAiApiObjectWithId { 15 | 16 | public static String OBJECT = "vector_store.file"; 17 | 18 | /** 19 | * The Unix timestamp (in seconds) for when the vector store was created. 20 | */ 21 | @JSONField(name = "created_at") 22 | @JsonProperty("created_at") 23 | private Integer createdAt; 24 | 25 | /** 26 | * The ID of the vector store that the File is attached to. 27 | */ 28 | @JSONField(name = "vector_store_id") 29 | @JsonProperty("vector_store_id") 30 | private String vectorStoreId; 31 | 32 | /** 33 | * The status of the vector store file, which can be either in_progress, completed, cancelled, or failed. The status completed indicates that the vector store file is ready for use. 34 | */ 35 | @JSONField(name = "status") 36 | @JsonProperty("status") 37 | private Status status; 38 | 39 | /** 40 | * The last error associated with this vector store file. Will be null if there are no errors. 41 | */ 42 | @JSONField(name = "last_error") 43 | @JsonProperty("last_error") 44 | private LastError lastError; 45 | 46 | @Getter 47 | public enum Status { 48 | 49 | IN_PROGRESS("in_progress"), 50 | COMPLETED("completed"), 51 | CANCELLED("cancelled"), 52 | FAILED("failed"); 53 | 54 | Status(final String value) { 55 | this.value = value; 56 | } 57 | 58 | private final String value; 59 | 60 | @JsonValue 61 | public String value() { 62 | return value; 63 | } 64 | 65 | } 66 | 67 | 68 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/file/batch/CreateVectorStoreFileBatchRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store.file.batch; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiApiRequest; 10 | 11 | import java.util.List; 12 | 13 | 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor(force = true) 18 | public class CreateVectorStoreFileBatchRequest implements IOpenAiApiRequest { 19 | 20 | /** 21 | * A list of File IDs that the vector store should use. Useful for tools like file_search that can access files. 22 | */ 23 | @JSONField(name = "file_ids") 24 | @JsonProperty("file_ids") 25 | private List fileIds; 26 | 27 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/assistant/vector/store/file/batch/VectorStoreFileBatch.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.assistant.vector.store.file.batch; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import xyz.felh.openai.OpenAiApiObjectWithId; 10 | import xyz.felh.openai.assistant.vector.store.FileCounts; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | public class VectorStoreFileBatch extends OpenAiApiObjectWithId { 15 | 16 | public static String OBJECT = "vector_store.file_batch"; 17 | 18 | /** 19 | * The Unix timestamp (in seconds) for when the vector store was created. 20 | */ 21 | @JSONField(name = "created_at") 22 | @JsonProperty("created_at") 23 | private Integer createdAt; 24 | 25 | /** 26 | * The ID of the vector store that the File is attached to. 27 | */ 28 | @JSONField(name = "vector_store_id") 29 | @JsonProperty("vector_store_id") 30 | private String vectorStoreId; 31 | 32 | /** 33 | * The status of the vector store file, which can be either in_progress, completed, cancelled, or failed. The status completed indicates that the vector store file is ready for use. 34 | */ 35 | @JSONField(name = "status") 36 | @JsonProperty("status") 37 | private Status status; 38 | 39 | @JSONField(name = "file_counts") 40 | @JsonProperty("file_counts") 41 | private FileCounts fileCounts; 42 | 43 | 44 | @Getter 45 | public enum Status { 46 | 47 | IN_PROGRESS("in_progress"), 48 | COMPLETED("completed"), 49 | CANCELLED("cancelled"), 50 | FAILED("failed"); 51 | 52 | Status(final String value) { 53 | this.value = value; 54 | } 55 | 56 | private final String value; 57 | 58 | @JsonValue 59 | public String value() { 60 | return value; 61 | } 62 | 63 | } 64 | 65 | 66 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/audio/AudioModelType.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.audio; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | import lombok.Getter; 5 | 6 | import java.util.Arrays; 7 | 8 | @Getter 9 | public enum AudioModelType { 10 | 11 | WHISPER_1("whisper-1"), 12 | TTS_1("tts-1"), 13 | TTS_1_HD("tts-1-hd"); 14 | 15 | private final String value; 16 | 17 | AudioModelType(final String value) { 18 | this.value = value; 19 | } 20 | 21 | @JsonValue 22 | public String value() { 23 | return value; 24 | } 25 | 26 | public static AudioModelType findByValue(String value) { 27 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/audio/AudioResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.audio; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiResponse; 6 | import lombok.Data; 7 | 8 | @Data 9 | public class AudioResponse implements IOpenAiApiResponse { 10 | 11 | @JSONField(name = "text") 12 | @JsonProperty("text") 13 | private String text; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/audio/CreateAudioTranscriptionRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.audio; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.SuperBuilder; 10 | 11 | import java.util.List; 12 | 13 | @EqualsAndHashCode(callSuper = true) 14 | @Data 15 | @SuperBuilder(toBuilder = true) 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class CreateAudioTranscriptionRequest extends CreateAudioTranslationRequest { 19 | 20 | /** 21 | * Optional 22 | * The language of the input audio. Supplying the input language in ISO-639-1 format will improve accuracy and latency. 23 | */ 24 | @JSONField(name = "language") 25 | @JsonProperty("language") 26 | private String language; 27 | 28 | /** 29 | * The timestamp granularities to populate for this transcription. 30 | *

31 | * response_format must be set verbose_json to use timestamp granularities. 32 | * Either or both of these options are supported: word, or segment. Note: 33 | * There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency. 34 | */ 35 | @JSONField(name = "timestamp_granularities") 36 | @JsonProperty("timestamp_granularities") 37 | private List timestampGranularities; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/audio/CreateAudioTranslationRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.audio; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | import lombok.*; 8 | import lombok.experimental.SuperBuilder; 9 | import xyz.felh.openai.chat.ChatMessage; 10 | 11 | import java.util.Arrays; 12 | 13 | @Data 14 | @SuperBuilder(toBuilder = true) 15 | @AllArgsConstructor 16 | @NoArgsConstructor(force = true) 17 | public class CreateAudioTranslationRequest implements IOpenAiApiRequest { 18 | 19 | /** 20 | * Required must set filePath or file 21 | *

22 | * The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. 23 | */ 24 | @JSONField(name = "file_path") 25 | @JsonProperty("file_path") 26 | private String filePath; 27 | 28 | @JSONField(name = "file") 29 | @JsonProperty("file") 30 | private byte[] file; 31 | 32 | /** 33 | * The name must contain extension in order to let API know how the file's type 34 | */ 35 | @NonNull 36 | @JSONField(name = "file_name") 37 | @JsonProperty("file_name") 38 | private String fileName; 39 | 40 | /** 41 | * Required 42 | * ID of the model to use. Only whisper-1 is currently available. 43 | */ 44 | @NonNull 45 | @JSONField(name = "model") 46 | @JsonProperty("model") 47 | private String model; 48 | 49 | /** 50 | * Optional 51 | * An optional text to guide the model's style or continue a previous audio segment. The prompt should match the audio language. 52 | */ 53 | @JSONField(name = "prompt") 54 | @JsonProperty("prompt") 55 | private String prompt; 56 | 57 | /** 58 | * Optional Defaults to json 59 | *

60 | * The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. 61 | *

62 | * See {@link ResponseFormat} 63 | */ 64 | @JSONField(name = "response_format") 65 | @JsonProperty("response_format") 66 | private ResponseFormat responseFormat; 67 | 68 | /** 69 | * Optional 70 | * Defaults to 0 71 | *

72 | * The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use log probability to automatically increase the temperature until certain thresholds are hit. 73 | */ 74 | @JSONField(name = "temperature") 75 | @JsonProperty("temperature") 76 | private Double temperature; 77 | 78 | @Getter 79 | public enum ResponseFormat { 80 | 81 | JSON("json"), 82 | TEXT("text"), 83 | SRT("srt"), 84 | VERBOSE_JSON("verbose_json"), 85 | VTT("vtt"); 86 | 87 | private final String value; 88 | 89 | ResponseFormat(final String value) { 90 | this.value = value; 91 | } 92 | 93 | @JsonValue 94 | public String value() { 95 | return value; 96 | } 97 | 98 | public static ResponseFormat findByValue(String value) { 99 | return Arrays.stream(values()).filter(it -> 100 | it.value.equals(value)).findFirst().orElse(null); 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/audio/CreateSpeechRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.audio; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.*; 7 | import lombok.experimental.SuperBuilder; 8 | import xyz.felh.openai.IOpenAiApiRequest; 9 | 10 | import java.util.Arrays; 11 | 12 | @Data 13 | @SuperBuilder(toBuilder = true) 14 | @AllArgsConstructor 15 | @NoArgsConstructor(force = true) 16 | public class CreateSpeechRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * One of the available TTS models: tts-1 or tts-1-hd 20 | */ 21 | @NonNull 22 | @JSONField(name = "model") 23 | @JsonProperty("model") 24 | private String model; 25 | 26 | /** 27 | * The text to generate audio for. The maximum length is 4096 characters. 28 | */ 29 | @NonNull 30 | @JSONField(name = "input") 31 | @JsonProperty("input") 32 | private String input; 33 | 34 | /** 35 | * The voice to use when generating the audio. Supported voices are alloy, echo, fable, onyx, nova, and shimmer. Previews of the voices are available in the Text to speech guide. 36 | *

37 | * See {@link Voice} 38 | */ 39 | @NonNull 40 | @JSONField(name = "voice") 41 | @JsonProperty("voice") 42 | private Voice voice; 43 | 44 | /** 45 | * string Optional Defaults to mp3 46 | *

47 | * The format to audio in. Supported formats are mp3, opus, aac, and flac. 48 | *

49 | * See {@link ResponseFormat} 50 | */ 51 | @JSONField(name = "response_format") 52 | @JsonProperty("response_format") 53 | private ResponseFormat responseFormat; 54 | 55 | /** 56 | * number Optional Defaults to 1 57 | *

58 | * The speed of the generated audio. Select a value from 0.25 to 4.0. 1.0 is the default. 59 | */ 60 | @JSONField(name = "speed") 61 | @JsonProperty("speed") 62 | private Double speed; 63 | 64 | @Getter 65 | public enum Voice { 66 | 67 | ALLOY("alloy"), 68 | ECHO("echo"), 69 | FABLE("fable"), 70 | ONYX("onyx"), 71 | NOVA("nova"), 72 | SHIMMER("shimmer"), 73 | ; 74 | 75 | private final String value; 76 | 77 | Voice(final String value) { 78 | this.value = value; 79 | } 80 | 81 | @JsonValue 82 | public String value() { 83 | return value; 84 | } 85 | 86 | public static Voice findByValue(String value) { 87 | return Arrays.stream(values()).filter(it -> 88 | it.value.equals(value)).findFirst().orElse(null); 89 | } 90 | } 91 | 92 | @Getter 93 | public enum ResponseFormat { 94 | 95 | MP3("mp3"), 96 | OPUS("opus"), 97 | AAC("aac"), 98 | FLAC("flac"), 99 | WAV("wav"); 100 | 101 | private final String value; 102 | 103 | ResponseFormat(final String value) { 104 | this.value = value; 105 | } 106 | 107 | @JsonValue 108 | public String value() { 109 | return value; 110 | } 111 | 112 | public static ResponseFormat findByValue(String value) { 113 | return Arrays.stream(values()).filter(it -> 114 | it.value.equals(value)).findFirst().orElse(null); 115 | } 116 | } 117 | 118 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/batch/BatchInputLineObject.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.batch; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | 11 | import java.util.Map; 12 | 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Data 17 | public class BatchInputLineObject implements IOpenAiBean { 18 | 19 | /** 20 | * A developer-provided per-request id that will be used to match outputs to inputs. Must be unique for each request in a batch. 21 | */ 22 | @JSONField(name = "custom_id") 23 | @JsonProperty("custom_id") 24 | private String customId; 25 | 26 | /** 27 | * The HTTP method to be used for the request. Currently only POST is supported. 28 | */ 29 | @JSONField(name = "method") 30 | @JsonProperty("method") 31 | private String method; 32 | 33 | /** 34 | * The OpenAI API relative URL to be used for the request. Currently only /v1/chat/completions is supported. 35 | */ 36 | @JSONField(name = "url") 37 | @JsonProperty("url") 38 | private String url; 39 | 40 | @JSONField(name = "body") 41 | @JsonProperty("body") 42 | private Map body; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/batch/BatchOutputLineObject.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.batch; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | 11 | import java.util.Map; 12 | 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Data 17 | public class BatchOutputLineObject implements IOpenAiBean { 18 | 19 | @JSONField(name = "id") 20 | @JsonProperty("id") 21 | private String id; 22 | 23 | /** 24 | * A developer-provided per-request id that will be used to match outputs to inputs. Must be unique for each request in a batch. 25 | */ 26 | @JSONField(name = "custom_id") 27 | @JsonProperty("custom_id") 28 | private String customId; 29 | 30 | @JSONField(name = "response") 31 | @JsonProperty("response") 32 | private Response response; 33 | 34 | /** 35 | * For requests that failed with a non-HTTP error, this will contain more information on the cause of the failure. 36 | */ 37 | @JSONField(name = "error") 38 | @JsonProperty("error") 39 | private Error error; 40 | 41 | @Data 42 | @Builder 43 | @NoArgsConstructor 44 | @AllArgsConstructor 45 | public static class Response implements IOpenAiBean { 46 | 47 | /** 48 | * The HTTP status code of the response 49 | */ 50 | @JSONField(name = "status_code") 51 | @JsonProperty("status_code") 52 | private Integer statusCode; 53 | 54 | /** 55 | * An unique identifier for the OpenAI API request. Please include this request ID when contacting support. 56 | */ 57 | @JSONField(name = "request_id") 58 | @JsonProperty("request_id") 59 | private String requestId; 60 | 61 | /** 62 | * The JSON body of the response 63 | */ 64 | @JSONField(name = "body") 65 | @JsonProperty("body") 66 | private Map body; 67 | 68 | } 69 | 70 | @Data 71 | @Builder 72 | @NoArgsConstructor 73 | @AllArgsConstructor 74 | public static class Error implements IOpenAiBean { 75 | 76 | /** 77 | * A machine-readable error code. 78 | */ 79 | @JSONField(name = "code") 80 | @JsonProperty("code") 81 | private String code; 82 | 83 | /** 84 | * A human-readable error message. 85 | */ 86 | @JSONField(name = "message") 87 | @JsonProperty("message") 88 | private String message; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/batch/CreateBatchRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.batch; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor(force = true) 12 | public class CreateBatchRequest implements IOpenAiApiRequest { 13 | 14 | /** 15 | * The ID of an uploaded file that contains requests for the new batch. 16 | *

17 | * See upload file for how to upload a file. 18 | *

19 | * Your input file must be formatted as a JSONL file, and must be uploaded with the purpose batch. 20 | */ 21 | @NonNull 22 | @JSONField(name = "input_file_id") 23 | @JsonProperty("input_file_id") 24 | private String inputFileId; 25 | 26 | /** 27 | * The endpoint to be used for all requests in the batch. Currently only /v1/chat/completions is supported. 28 | */ 29 | @NonNull 30 | @JSONField(name = "endpoint") 31 | @JsonProperty("endpoint") 32 | private String endpoint; 33 | 34 | /** 35 | * The time frame within which the batch should be processed. Currently only '24h' is supported. 36 | */ 37 | @NonNull 38 | @JSONField(name = "completion_window") 39 | @JsonProperty("completion_window") 40 | private String completionWindow; 41 | 42 | /** 43 | * Optional custom metadata for the batch. 44 | */ 45 | @JSONField(name = "metadata") 46 | @JsonProperty("metadata") 47 | private Object metadata; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatAudio.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import xyz.felh.openai.IOpenAiBean; 10 | 11 | /** 12 | * @author Forest Wang 13 | * @package xyz.felh.openai.chat 14 | * @class ChatAudio 15 | * @email forestwanglin@gmail.cn 16 | * @date 2024/10/24 17 | */ 18 | @Data 19 | @Builder 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public class ChatAudio implements IOpenAiBean { 23 | 24 | /** 25 | * Specifies the voice type. Supported voices are alloy, echo, fable, onyx, nova, and shimmer. 26 | */ 27 | @JSONField(name = "voice") 28 | @JsonProperty("voice") 29 | private ChatAudioVoice voice; 30 | 31 | /** 32 | * Specifies the output audio format. Must be one of wav, mp3, flac, opus, or pcm16. 33 | */ 34 | @JSONField(name = "format") 35 | @JsonProperty("format") 36 | private ChatAudioFormat format; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatAudioFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | /** 6 | * @author Forest Wang 7 | * @package xyz.felh.openai.chat 8 | * @class ChatAudioFormat 9 | * @email forestwanglin@gmail.cn 10 | * @date 2024/10/24 11 | */ 12 | public enum ChatAudioFormat { 13 | 14 | WAV("wav"), 15 | MP3("mp3"), 16 | FLAC("flac"), 17 | OPUS("opus"), 18 | PCM16("pcm16"); 19 | 20 | private final String value; 21 | 22 | ChatAudioFormat(final String value) { 23 | this.value = value; 24 | } 25 | 26 | @JsonValue 27 | public String value() { 28 | return value; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatAudioVoice.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | /** 6 | * @author Forest Wang 7 | * @package xyz.felh.openai.chat 8 | * @class ChatAudioVoice 9 | * @email forestwanglin@gmail.cn 10 | * @date 2024/10/24 11 | */ 12 | public enum ChatAudioVoice { 13 | 14 | ALLOY("alloy"), 15 | ECHO("echo"), 16 | FABLE("fable"), 17 | ONYX("onyx"), 18 | NOVA("nova"), 19 | SHIMMER("shimmer"); 20 | 21 | private final String value; 22 | 23 | ChatAudioVoice(final String value) { 24 | this.value = value; 25 | } 26 | 27 | @JsonValue 28 | public String value() { 29 | return value; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatCompletionChoice.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class ChatCompletionChoice implements IOpenAiApiObject { 10 | 11 | /** 12 | * The reason the model stopped generating tokens. This will be stop if the model hit a natural stop point 13 | * or a provided stop sequence, length if the maximum number of tokens specified in the request was reached, 14 | * content_filter if content was omitted due to a flag from our content filters, tool_calls 15 | * if the model called a tool, or function_call (deprecated) if the model called a function. 16 | */ 17 | @JSONField(name = "finish_reason") 18 | @JsonProperty("finish_reason") 19 | private String finishReason; 20 | 21 | /** 22 | * The index of the choice in the list of choices. 23 | */ 24 | @JSONField(name = "index") 25 | @JsonProperty("index") 26 | private Integer index; 27 | 28 | /** 29 | * A chat completion message generated by the model. 30 | *

31 | * See {@link ChatMessage} 32 | */ 33 | @JSONField(name = "message") 34 | @JsonProperty("message") 35 | private ChatMessage message; 36 | 37 | /** 38 | * A chat completion delta generated by streamed model responses. 39 | *

40 | * See {@link ChatMessage} 41 | */ 42 | @JSONField(name = "delta") 43 | @JsonProperty("delta") 44 | private ChatMessage delta; 45 | 46 | /** 47 | * Log probability information for the choice. 48 | *

49 | * See {@link Logprobs} 50 | */ 51 | @JSONField(name = "logprobs") 52 | @JsonProperty("logprobs") 53 | private Logprobs logprobs; 54 | 55 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatMessageRole.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | public enum ChatMessageRole { 6 | 7 | /** 8 | * content - Required The contents of the user message. 9 | * role - Required The role of the messages author, in this case user. 10 | */ 11 | SYSTEM("system"), 12 | /** 13 | * content - Required The contents of the user message. 14 | * role - Required The role of the messages author, in this case user. 15 | */ 16 | USER("user"), 17 | /** 18 | * content - Required The contents of the assistant message. 19 | * role - Required The role of the messages author, in this case assistant. 20 | * tool_calls - Optional The tool calls generated by the model, such as function calls. 21 | */ 22 | ASSISTANT("assistant"), 23 | /** 24 | * role - Required The role of the messages author, in this case tool. 25 | * content - Required The contents of the tool message. 26 | * tool_call_id - Required Tool call that this message is responding to. 27 | */ 28 | TOOL("tool"); 29 | 30 | private final String value; 31 | 32 | ChatMessageRole(final String value) { 33 | this.value = value; 34 | } 35 | 36 | @JsonValue 37 | public String value() { 38 | return value; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/ChatModality.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | /** 6 | * @author Forest Wang 7 | * @package xyz.felh.openai.chat 8 | * @class ChatModality 9 | * @email forestwanglin@gmail.cn 10 | * @date 2024/10/24 11 | */ 12 | public enum ChatModality { 13 | 14 | TEXT("text"), 15 | 16 | AUDIO("audio"); 17 | 18 | private final String value; 19 | 20 | ChatModality(final String value) { 21 | this.value = value; 22 | } 23 | 24 | @JsonValue 25 | public String value() { 26 | return value; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/Logprobs.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | 4 | import com.alibaba.fastjson2.annotation.JSONField; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | import xyz.felh.openai.IOpenAiApiObject; 11 | import xyz.felh.openai.IOpenAiBean; 12 | 13 | import java.util.List; 14 | 15 | @Data 16 | public class Logprobs implements IOpenAiApiObject { 17 | 18 | /** 19 | * A list of message content tokens with log probability information. 20 | *

21 | * See {@link Content} 22 | */ 23 | @JSONField(name = "content") 24 | @JsonProperty("content") 25 | private List content; 26 | 27 | /** 28 | * A list of message refusal tokens with log probability information. 29 | */ 30 | @JSONField(name = "refusal") 31 | @JsonProperty("refusal") 32 | private List refusal; 33 | 34 | @Data 35 | @Builder 36 | @NoArgsConstructor 37 | @AllArgsConstructor 38 | public static class Content implements IOpenAiBean { 39 | 40 | /** 41 | * The token. 42 | */ 43 | @JSONField(name = "token") 44 | @JsonProperty("token") 45 | private String token; 46 | 47 | /** 48 | * The log probability of this token, if it is within the top 20 most likely tokens. 49 | * Otherwise, the value -9999.0 is used to signify that the token is very unlikely. 50 | */ 51 | @JSONField(name = "logprob") 52 | @JsonProperty("logprob") 53 | private Double logprob; 54 | 55 | /** 56 | * A list of integers representing the UTF-8 bytes representation of the token. 57 | * Useful in instances where characters are represented by multiple tokens and their byte representations 58 | * must be combined to generate the correct text representation. Can be null if there is no bytes representation for the token. 59 | */ 60 | @JSONField(name = "bytes") 61 | @JsonProperty("bytes") 62 | private List bytes; 63 | 64 | /** 65 | * List of the most likely tokens and their log probability, at this token position. 66 | * In rare cases, there may be fewer than the number of requested top_logprobs returned. 67 | */ 68 | @JSONField(name = "top_logprobs") 69 | @JsonProperty("top_logprobs") 70 | private List topLogprobs; 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/RequestResponseFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.*; 7 | import xyz.felh.openai.IOpenAiBean; 8 | 9 | import java.util.Arrays; 10 | 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class RequestResponseFormat implements IOpenAiBean { 16 | 17 | /** 18 | * Must be one of text or json_object. 19 | *

20 | * String, Optional 21 | *

22 | * Defaults to text, See {@link TypeValue} 23 | */ 24 | @JSONField(name = "type") 25 | @JsonProperty("type") 26 | private TypeValue type; 27 | 28 | /** 29 | * It is required if type = json_schema 30 | */ 31 | @JSONField(name = "json_schema") 32 | @JsonProperty("json_schema") 33 | private JsonSchema jsonSchema; 34 | 35 | public enum TypeValue { 36 | TEXT("text"), 37 | JSON_OBJECT("json_object"), 38 | JSON_SCHEMA("json_schema"); 39 | 40 | private final String value; 41 | 42 | TypeValue(final String value) { 43 | this.value = value; 44 | } 45 | 46 | @JsonValue 47 | public String value() { 48 | return value; 49 | } 50 | 51 | public static TypeValue findByValue(String value) { 52 | return Arrays.stream(values()).filter(it -> 53 | it.value.equals(value)).findFirst().orElse(null); 54 | } 55 | } 56 | 57 | @Data 58 | @Builder 59 | @NoArgsConstructor 60 | @AllArgsConstructor 61 | public static class JsonSchema implements IOpenAiBean { 62 | 63 | /** 64 | * The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. 65 | */ 66 | @NonNull 67 | @JSONField(name = "name") 68 | @JsonProperty("name") 69 | private String name; 70 | 71 | /** 72 | * string 73 | *

74 | * Optional 75 | * A description of what the response format is for, used by the model to determine how to respond in the format. 76 | */ 77 | @JSONField(name = "description") 78 | @JsonProperty("description") 79 | private String description; 80 | 81 | /** 82 | * The schema for the response format, described as a JSON Schema object. 83 | *

84 | * See Structured Outputs 85 | */ 86 | @JSONField(name = "schema") 87 | @JsonProperty("schema") 88 | private Object schema; 89 | 90 | /** 91 | * boolean or null 92 | *

93 | * Optional 94 | * Defaults to false 95 | * Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the schema field. Only a subset of JSON Schema is supported when strict is true. To learn more, read the Structured Outputs guide. 96 | */ 97 | @JSONField(name = "strict") 98 | @JsonProperty("strict") 99 | private Boolean strict; 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/Function.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | 7 | @Data 8 | @Builder 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class Function { 12 | 13 | /** 14 | * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. 15 | *

16 | * String 17 | */ 18 | @NonNull 19 | @JSONField(name = "name") 20 | @JsonProperty("name") 21 | private String name; 22 | 23 | /** 24 | * A description of what the function does, used by the model to choose when and how to call the function. 25 | *

26 | * string, Optional 27 | */ 28 | @JSONField(name = "description") 29 | @JsonProperty("description") 30 | private String description; 31 | 32 | /** 33 | * The parameters the functions accepts, described as a JSON Schema object. See the guide for examples, and the JSON Schema reference for documentation about the format. 34 | *

35 | * To describe a function that accepts no parameters, provide the value {"type": "object", "properties": {}}. 36 | */ 37 | @JSONField(name = "parameters") 38 | @JsonProperty("parameters") 39 | private Object parameters; 40 | 41 | /** 42 | * boolean or null 43 | *

44 | * Optional 45 | * Defaults to false 46 | * Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the parameters field. Only a subset of JSON Schema is supported when strict is true. Learn more about Structured Outputs in the function calling guide. 47 | */ 48 | @JSONField(name = "strict") 49 | @JsonProperty("strict") 50 | private Boolean strict; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/FunctionCall.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class FunctionCall implements IOpenAiBean { 13 | 14 | /** 15 | * The name of the function to call. 16 | */ 17 | @NonNull 18 | @JSONField(name = "name") 19 | @JsonProperty("name") 20 | private String name; 21 | 22 | /** 23 | * The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. 24 | */ 25 | @NonNull 26 | @JSONField(name = "arguments") 27 | @JsonProperty("arguments") 28 | private String arguments; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/Tool.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Tool implements IOpenAiBean { 13 | 14 | /** 15 | * The type of the tool. Currently, only function is supported. 16 | * 17 | * See {@link Type} 18 | */ 19 | @NonNull 20 | @JSONField(name = "type") 21 | @JsonProperty("type") 22 | private Type type; 23 | 24 | /** 25 | * See {@link Function} 26 | */ 27 | @NonNull 28 | @JSONField(name = "function") 29 | @JsonProperty("function") 30 | private Function function; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/ToolCall.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ToolCall implements IOpenAiBean { 13 | 14 | /** 15 | * The ID of the tool call. 16 | */ 17 | @NonNull 18 | @JSONField(name = "id") 19 | @JsonProperty("id") 20 | private String id; 21 | 22 | /** 23 | * The type of the tool. Currently, only function is supported. 24 | *

25 | * See {@link Type} 26 | */ 27 | @NonNull 28 | @JSONField(name = "type") 29 | @JsonProperty("type") 30 | private Type type; 31 | 32 | /** 33 | * The function that the model called. 34 | *

35 | * See {@link FunctionCall} 36 | */ 37 | @NonNull 38 | @JSONField(name = "function") 39 | @JsonProperty("function") 40 | private FunctionCall function; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/ToolChoice.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiBean; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ToolChoice implements IOpenAiBean { 13 | 14 | /** 15 | * The type of the tool. Currently, only function is supported. 16 | *

17 | * string, Optional 18 | *

19 | * See {@link Type} 20 | */ 21 | @JSONField(name = "type") 22 | @JsonProperty("type") 23 | private Type type; 24 | 25 | /** 26 | * function object 27 | */ 28 | @JSONField(name = "function") 29 | @JsonProperty("function") 30 | private Function function; 31 | 32 | @Data 33 | @Builder 34 | @NoArgsConstructor 35 | @AllArgsConstructor 36 | public static class Function implements IOpenAiBean { 37 | 38 | /** 39 | * The name of the function to call. 40 | *

41 | * string 42 | */ 43 | @NonNull 44 | @JSONField(name = "name") 45 | @JsonProperty("name") 46 | private String name; 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/chat/tool/Type.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.chat.tool; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | import lombok.Getter; 5 | 6 | import java.util.Arrays; 7 | 8 | @Getter 9 | public enum Type { 10 | 11 | FUNCTION("function"), 12 | ; 13 | 14 | private final String value; 15 | 16 | Type(final String value) { 17 | this.value = value; 18 | } 19 | 20 | @JsonValue 21 | public String value() { 22 | return value; 23 | } 24 | 25 | public static Type findByValue(String value) { 26 | return Arrays.stream(values()).filter(it -> 27 | it.value.equals(value)).findFirst().orElse(null); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/embedding/CreateEmbeddingRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.embedding; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | import lombok.*; 8 | import xyz.felh.openai.chat.ChatMessage; 9 | 10 | import java.util.Arrays; 11 | 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor(force = true) 16 | public class CreateEmbeddingRequest implements IOpenAiApiRequest { 17 | 18 | /** 19 | * Required 20 | * ID of the model to use. You can use the List models API to see all of your available models, or see our Model overview for descriptions of them. 21 | */ 22 | @NonNull 23 | @JSONField(name = "model") 24 | @JsonProperty("model") 25 | private String model; 26 | 27 | /** 28 | * string or array Required 29 | *

30 | * Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for text-embedding-ada-002), cannot be an empty string, and any array must be 2048 dimensions or less. Example Python code for counting tokens. 31 | *

32 | * string string - The string that will be turned into an embedding. 33 | *

34 | * array array - The array of strings that will be turned into an embedding. Each line's max is 8191 35 | *

36 | * array array - The array of integers that will be turned into an embedding. 37 | *

38 | * array array - The array of arrays containing integers that will be turned into an embedding. 39 | */ 40 | @NonNull 41 | @JSONField(name = "input") 42 | @JsonProperty("input") 43 | private Object input; 44 | 45 | /** 46 | * string Optional Defaults to float 47 | *

48 | * The format to return the embeddings in. Can be either float or base64. 49 | * See {@link EncodingFormat} 50 | */ 51 | @JSONField(name = "encoding_format") 52 | @JsonProperty("encoding_format") 53 | private EncodingFormat encodingFormat; 54 | 55 | /** 56 | * integer Optional 57 | *

58 | * The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. 59 | */ 60 | @JSONField(name = "dimensions") 61 | @JsonProperty("dimensions") 62 | private Integer dimensions; 63 | 64 | /** 65 | * Optional 66 | *

67 | * A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Learn more. 68 | */ 69 | @JSONField(name = "user") 70 | @JsonProperty("user") 71 | private String user; 72 | 73 | @Getter 74 | public enum EncodingFormat { 75 | 76 | FLOAT("float"), 77 | BASE64("base64"); 78 | 79 | private final String value; 80 | 81 | EncodingFormat(final String value) { 82 | this.value = value; 83 | } 84 | 85 | @JsonValue 86 | public String value() { 87 | return value; 88 | } 89 | 90 | public static EncodingFormat findByValue(String value) { 91 | return Arrays.stream(values()).filter(it -> 92 | it.value.equals(value)).findFirst().orElse(null); 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/embedding/CreateEmbeddingResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.embedding; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiResponse; 6 | import xyz.felh.openai.usage.Usage; 7 | import lombok.Data; 8 | 9 | import java.util.List; 10 | 11 | @Data 12 | public class CreateEmbeddingResponse implements IOpenAiApiResponse { 13 | 14 | @JSONField(name = "model") 15 | @JsonProperty("model") 16 | private String model; 17 | 18 | @JSONField(name = "object") 19 | @JsonProperty("object") 20 | private String object; 21 | 22 | /** 23 | * See {@link Embedding} 24 | */ 25 | @JSONField(name = "data") 26 | @JsonProperty("data") 27 | private List data; 28 | 29 | /** 30 | * See {@link Usage} 31 | */ 32 | @JSONField(name = "usage") 33 | @JsonProperty("usage") 34 | private Usage usage; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/embedding/Embedding.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.embedding; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiObject; 6 | import lombok.Data; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * See document 12 | */ 13 | @Data 14 | public class Embedding implements IOpenAiApiObject { 15 | 16 | public static String OBJECT = "embedding"; 17 | 18 | /** 19 | * The object type, which is always "embedding". 20 | */ 21 | @JSONField(name = "object") 22 | @JsonProperty("object") 23 | private String object; 24 | 25 | /** 26 | * The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the embedding guide. 27 | */ 28 | @JSONField(name = "embedding") 29 | @JsonProperty("embedding") 30 | private List embedding; 31 | 32 | /** 33 | * The index of the embedding in the list of embeddings. 34 | */ 35 | @JSONField(name = "index") 36 | @JsonProperty("index") 37 | private Integer index; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/file/File.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.file; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import lombok.ToString; 10 | import xyz.felh.openai.OpenAiApiObjectWithId; 11 | import xyz.felh.openai.chat.ChatMessage; 12 | 13 | import java.util.Arrays; 14 | 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | @ToString(callSuper = true) 18 | public class File extends OpenAiApiObjectWithId { 19 | 20 | public static String OBJECT = "file"; 21 | 22 | /** 23 | * The size of the file, in bytes. 24 | */ 25 | @JSONField(name = "bytes") 26 | @JsonProperty("bytes") 27 | private Long bytes; 28 | 29 | /** 30 | * The Unix timestamp (in seconds) for when the file was created. 31 | */ 32 | @JSONField(name = "created_at") 33 | @JsonProperty("created_at") 34 | private Long createdAt; 35 | 36 | /** 37 | * The name of the file. 38 | */ 39 | @JSONField(name = "filename") 40 | @JsonProperty("filename") 41 | private String filename; 42 | 43 | /** 44 | * The intended purpose of the file. Supported values are fine-tune, fine-tune-results, assistants, and assistants_output. 45 | *

46 | * See {@link Purpose} 47 | *

48 | * assistants - Supported formats: ['c', 'cpp', 'csv', 'docx', 'html', 'java', 'json', 'md', 'pdf', 'php', 'pptx', 'py', 'rb', 'tex', 'txt', 'css', 'jpeg', 'jpg', 'js', 'gif', 'png', 'tar', 'ts', 'xlsx', 'xml', 'zip'] 49 | */ 50 | @JSONField(name = "purpose") 51 | @JsonProperty("purpose") 52 | private Purpose purpose; 53 | 54 | 55 | @Getter 56 | public enum Purpose { 57 | 58 | FINE_TUNE("fine-tune"), 59 | FINE_TUNE_RESULTS("fine-tune-results"), 60 | ASSISTANTS("assistants"), 61 | ASSISTANTS_OUTPUT("assistants_output"), 62 | VISION("vision"), 63 | BATCH("batch"); 64 | 65 | private final String value; 66 | 67 | Purpose(final String value) { 68 | this.value = value; 69 | } 70 | 71 | @JsonValue 72 | public String value() { 73 | return value; 74 | } 75 | 76 | public static Purpose findByValue(String value) { 77 | return Arrays.stream(values()).filter(it -> 78 | it.value.equals(value)).findFirst().orElse(null); 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/fineTuning/CreateFineTuningJobRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.fineTuning; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor(force = true) 12 | public class CreateFineTuningJobRequest implements IOpenAiApiRequest { 13 | 14 | /** 15 | * The ID of an uploaded file that contains training data. 16 | * Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose fine-tune. 17 | */ 18 | @NonNull 19 | @JSONField(name = "training_file") 20 | @JsonProperty("training_file") 21 | private String trainingFile; 22 | 23 | /** 24 | * Optional 25 | *

26 | * The ID of an uploaded file that contains validation data. 27 | *

28 | * If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. 29 | * These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. 30 | *

31 | * Your dataset must be formatted as a JSONL file. You must upload your file with the purpose fine-tune. 32 | */ 33 | @JSONField(name = "validation_file") 34 | @JsonProperty("validation_file") 35 | private String validationFile; 36 | 37 | /** 38 | * The name of the model to fine-tune. You can select one of the supported models. 39 | */ 40 | @NonNull 41 | @JSONField(name = "model") 42 | @JsonProperty("model") 43 | private String model; 44 | 45 | /** 46 | * Optional 47 | * The hyperparameters used for the fine-tuning job. 48 | */ 49 | @JSONField(name = "hyperparameters") 50 | @JsonProperty("hyperparameters") 51 | private Hyperparameters hyperparameters; 52 | 53 | /** 54 | * A string of up to 18 characters that will be added to your fine-tuned model name. 55 | *

56 | * For example, a suffix of "custom-model-name" would produce a model name like ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel. 57 | */ 58 | @JSONField(name = "suffix") 59 | @JsonProperty("suffix") 60 | private String suffix; 61 | 62 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/fineTuning/FineTuningJobError.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.fineTuning; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class FineTuningJobError implements IOpenAiApiObject { 10 | 11 | /** 12 | * A machine-readable error code. 13 | */ 14 | @JSONField(name = "code") 15 | @JsonProperty("code") 16 | private String code; 17 | 18 | /** 19 | * A human-readable error message. 20 | */ 21 | @JSONField(name = "message") 22 | @JsonProperty("message") 23 | private String message; 24 | 25 | /** 26 | * The parameter that was invalid, usually training_file or validation_file. This field will be null if the failure was not parameter-specific. 27 | */ 28 | @JSONField(name = "param") 29 | @JsonProperty("param") 30 | private String param; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/fineTuning/FineTuningJobEvent.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.fineTuning; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.ToString; 8 | import xyz.felh.openai.OpenAiApiObjectWithId; 9 | 10 | @EqualsAndHashCode(callSuper = true) 11 | @Data 12 | @ToString(callSuper = true) 13 | public class FineTuningJobEvent extends OpenAiApiObjectWithId { 14 | 15 | public static String OBJECT = "fine_tuning.job.event"; 16 | 17 | @JSONField(name = "created_at") 18 | @JsonProperty("created_at") 19 | private Long createdAt; 20 | 21 | @JSONField(name = "level") 22 | @JsonProperty("level") 23 | private String level; 24 | 25 | @JSONField(name = "message") 26 | @JsonProperty("message") 27 | private String message; 28 | 29 | @JSONField(name = "data") 30 | @JsonProperty("data") 31 | private Object data; 32 | 33 | @JSONField(name = "type") 34 | @JsonProperty("type") 35 | private String type; 36 | 37 | } -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/fineTuning/Hyperparameters.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.fineTuning; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class Hyperparameters implements IOpenAiApiObject { 10 | 11 | /** 12 | * string or integer 13 | *

14 | * The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. 15 | */ 16 | @JSONField(name = "n_epochs") 17 | @JsonProperty("n_epochs") 18 | private Object nEpochs; 19 | 20 | /** 21 | * string or integer Optional Defaults to auto 22 | *

23 | * Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. 24 | */ 25 | @JSONField(name = "batch_size") 26 | @JsonProperty("batch_size") 27 | private Object batchSize; 28 | 29 | /** 30 | * string or number Optional Defaults to auto 31 | *

32 | * Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. 33 | */ 34 | @JSONField(name = "learning_rate_multiplier") 35 | @JsonProperty("learning_rate_multiplier") 36 | private Object learningRateMultiplier; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/BaseRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiRequest; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.ToString; 10 | import lombok.experimental.SuperBuilder; 11 | 12 | @Data 13 | @ToString 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @SuperBuilder(toBuilder = true) 17 | public abstract class BaseRequest implements IOpenAiApiRequest { 18 | 19 | /** 20 | * The model to use for image generation. 21 | *

22 | * string, Optional 23 | * Defaults to dall-e-2 24 | *

25 | * When creating edit image 26 | *

27 | * The model to use for image generation. Only dall-e-2 is supported at this time. 28 | */ 29 | @JSONField(name = "model") 30 | @JsonProperty("model") 31 | private String model; 32 | 33 | /** 34 | * The number of images to generate. Must be between 1 and 10. For dall-e-3, only n=1 is supported. 35 | *

36 | * integer or null, Optional 37 | *

38 | * Defaults to 1 39 | */ 40 | @JSONField(name = "n") 41 | @JsonProperty("n") 42 | private Integer n; 43 | 44 | /** 45 | * The size of the generated images. Must be one of 256x256, 512x512, or 1024x1024 for dall-e-2. Must be one of 1024x1024, 1792x1024, or 1024x1792 for dall-e-3 46 | *

47 | * string or null, Optional 48 | *

49 | * Defaults to 1024x1024 50 | *

51 | * See {@link ImageSize} 52 | */ 53 | @JSONField(name = "size") 54 | @JsonProperty("size") 55 | private ImageSize size; 56 | 57 | /** 58 | * The format in which the generated images are returned. Must be one of url or b64_json. 59 | *

60 | * string or null, Optional 61 | *

62 | * Defaults to url 63 | *

64 | * See {@link ImageResponseFormat} 65 | */ 66 | @JSONField(name = "response_format") 67 | @JsonProperty("response_format") 68 | private ImageResponseFormat responseFormat; 69 | 70 | /** 71 | * A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. 72 | *

73 | * Learn more. 74 | *

75 | * string, Optional 76 | */ 77 | @JSONField(name = "user") 78 | @JsonProperty("user") 79 | private String user; 80 | 81 | } 82 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/CreateImageRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import lombok.experimental.SuperBuilder; 7 | 8 | @EqualsAndHashCode(callSuper = true) 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor(force = true) 12 | @ToString(callSuper = true) 13 | @SuperBuilder(toBuilder = true) 14 | public class CreateImageRequest extends BaseRequest { 15 | 16 | /** 17 | * A text description of the desired image(s). The maximum length is 1000 characters for dall-e-2 and 4000 characters for dall-e-3. 18 | *

19 | * string, Required 20 | */ 21 | @NonNull 22 | @JSONField(name = "prompt") 23 | @JsonProperty("prompt") 24 | private String prompt; 25 | 26 | /** 27 | * The quality of the image that will be generated. hd creates images with finer details and greater consistency across the image. This param is only supported for dall-e-3. 28 | *

29 | * string, Optional 30 | *

31 | * Default to standard 32 | *

33 | * See {@link ImageQuality} 34 | */ 35 | @JSONField(name = "quality") 36 | @JsonProperty("quality") 37 | private ImageQuality quality; 38 | 39 | /** 40 | * The style of the generated images. Must be one of vivid or natural. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. This param is only supported for dall-e-3. 41 | *

42 | * string or null, Optional 43 | *

44 | * Defaults to vivid 45 | *

46 | * See {@link ImageStyle} 47 | */ 48 | @JSONField(name = "style") 49 | @JsonProperty("style") 50 | private ImageStyle style; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/Image.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiObject; 6 | import lombok.Data; 7 | 8 | @Data 9 | public class Image implements IOpenAiApiObject { 10 | 11 | /** 12 | * The URL of the generated image, if response_format is url (default). 13 | */ 14 | @JSONField(name = "url") 15 | @JsonProperty("url") 16 | private String url; 17 | 18 | /** 19 | * The base64-encoded JSON of the generated image, if response_format is b64_json. 20 | */ 21 | @JSONField(name = "b64_json") 22 | @JsonProperty("b64_json") 23 | private String b64Json; 24 | 25 | /** 26 | * The prompt that was used to generate the image, if there was any revision to the prompt. 27 | */ 28 | @JSONField(name = "revised_prompt") 29 | @JsonProperty("revised_prompt") 30 | private String revisedPrompt; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageModelType.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | import lombok.Getter; 5 | 6 | import java.util.Arrays; 7 | 8 | @Getter 9 | public enum ImageModelType { 10 | 11 | DALL_E_2("dall-e-2"), 12 | 13 | DALL_E_3("dall-e-3"); 14 | 15 | private final String value; 16 | 17 | ImageModelType(final String value) { 18 | this.value = value; 19 | } 20 | 21 | @JsonValue 22 | public String value() { 23 | return value; 24 | } 25 | 26 | public static ImageModelType findByValue(String value) { 27 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageQuality.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * This param is only supported for dall-e-3 9 | */ 10 | public enum ImageQuality { 11 | 12 | STANDARD("standard"), 13 | 14 | HD("hd"); 15 | 16 | private final String value; 17 | 18 | ImageQuality(final String value) { 19 | this.value = value; 20 | } 21 | 22 | @JsonValue 23 | public String value() { 24 | return value; 25 | } 26 | 27 | public static ImageQuality findByValue(String value) { 28 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiObject; 6 | import xyz.felh.openai.IOpenAiApiResponse; 7 | import lombok.Data; 8 | 9 | import java.util.List; 10 | 11 | @Data 12 | public class ImageResponse implements IOpenAiApiResponse, IOpenAiApiObject { 13 | 14 | @JSONField(name = "created") 15 | @JsonProperty("created") 16 | private Long created; 17 | 18 | @JSONField(name = "data") 19 | @JsonProperty("data") 20 | private List data; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageResponseFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | import java.util.Arrays; 6 | 7 | public enum ImageResponseFormat { 8 | 9 | URL("url"), 10 | 11 | B64_JSON("b64_json"); 12 | 13 | private final String value; 14 | 15 | ImageResponseFormat(final String value) { 16 | this.value = value; 17 | } 18 | 19 | @JsonValue 20 | public String value() { 21 | return value; 22 | } 23 | 24 | public static ImageResponseFormat findByValue(String value) { 25 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageSize.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | import java.util.Arrays; 6 | 7 | public enum ImageSize { 8 | 9 | // dall-e-2 10 | R_256X256("256x256"), 11 | R_512X512("512x512"), 12 | 13 | // dall-e-2 and dall-e-3 14 | R_1024X1024("1024x1024"), 15 | 16 | // dall-e-3 17 | R_1792X1024("1792x1024"), 18 | R_1024X1792("1024x1792"); 19 | 20 | private final String value; 21 | 22 | ImageSize(final String value) { 23 | this.value = value; 24 | } 25 | 26 | @JsonValue 27 | public String value() { 28 | return value; 29 | } 30 | 31 | public static ImageSize findByValue(String value) { 32 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/ImageStyle.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image; 2 | 3 | import com.fasterxml.jackson.annotation.JsonValue; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * This param is only supported for dall-e-3 9 | */ 10 | public enum ImageStyle { 11 | 12 | VIVID("vivid"), 13 | 14 | NATURAL("natural"); 15 | 16 | private final String value; 17 | 18 | ImageStyle(final String value) { 19 | this.value = value; 20 | } 21 | 22 | @JsonValue 23 | public String value() { 24 | return value; 25 | } 26 | 27 | public static ImageStyle findByValue(String value) { 28 | return Arrays.stream(values()).filter(it -> it.value().equals(value)).findFirst().orElse(null); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/edit/CreateEditRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image.edit; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.image.BaseRequest; 6 | import lombok.*; 7 | import lombok.experimental.SuperBuilder; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor(force = true) 13 | @ToString(callSuper = true) 14 | @SuperBuilder(toBuilder = true) 15 | public class CreateEditRequest extends BaseRequest { 16 | 17 | /** 18 | * A text description of the desired image(s). The maximum length is 1000 characters. 19 | *

20 | * string 21 | */ 22 | @NonNull 23 | @JSONField(name = "prompt") 24 | @JsonProperty("prompt") 25 | private String prompt; 26 | 27 | /** 28 | * The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask. 29 | *

30 | * string, Required 31 | */ 32 | @JSONField(name = "image") 33 | @JsonProperty("image") 34 | private byte[] image; 35 | @JSONField(name = "image_path") 36 | @JsonProperty("image_path") 37 | private String imagePath; 38 | 39 | /** 40 | * An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where image should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as image. 41 | *

42 | * string, Optional 43 | */ 44 | @JSONField(name = "mask") 45 | @JsonProperty("mask") 46 | private byte[] mask; 47 | @JSONField(name = "mask_path") 48 | @JsonProperty("mask_path") 49 | private String maskPath; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/image/variation/CreateVariationRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.image.variation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.image.BaseRequest; 6 | import lombok.*; 7 | import lombok.experimental.SuperBuilder; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor(force = true) 13 | @ToString(callSuper = true) 14 | @SuperBuilder(toBuilder = true) 15 | public class CreateVariationRequest extends BaseRequest { 16 | 17 | /** 18 | * The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. 19 | *

20 | * string, Required 21 | */ 22 | @JSONField(name = "image") 23 | @JsonProperty("image") 24 | private byte[] image; 25 | @JSONField(name = "image_path") 26 | @JsonProperty("image_path") 27 | private String imagePath; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/model/Model.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.model; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import xyz.felh.openai.OpenAiApiObjectWithId; 8 | 9 | /** 10 | * List and describe the various models available in the API. 11 | * You can refer to the Models documentation to understand what models are available and the differences between them. 12 | *

13 | * See document 14 | */ 15 | @EqualsAndHashCode(callSuper = true) 16 | @Data 17 | public class Model extends OpenAiApiObjectWithId { 18 | 19 | public static String OBJECT = "model"; 20 | 21 | /** 22 | * The Unix timestamp (in seconds) when the model was created. 23 | */ 24 | @JSONField(name = "created") 25 | @JsonProperty("created") 26 | public Long created; 27 | 28 | /** 29 | * The organization that owns the model. 30 | */ 31 | @JSONField(name = "owned_by") 32 | @JsonProperty("owned_by") 33 | private String ownedBy; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/moderation/CreateModerationRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.moderation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.*; 6 | import xyz.felh.openai.IOpenAiApiRequest; 7 | 8 | @Data 9 | @Builder 10 | @AllArgsConstructor 11 | @NoArgsConstructor(force = true) 12 | public class CreateModerationRequest implements IOpenAiApiRequest { 13 | 14 | /** 15 | * string or array Required 16 | *

17 | * The input text to classify 18 | */ 19 | @NonNull 20 | @JSONField(name = "input") 21 | @JsonProperty("input") 22 | private Object input; 23 | 24 | /** 25 | * Optional Defaults to text-moderation-latest 26 | *

27 | * Two content moderations models are available: text-moderation-stable and text-moderation-latest. 28 | *

29 | * The default is text-moderation-latest which will be automatically upgraded over time. This ensures you are always 30 | * using our most accurate model. If you use text-moderation-stable, we will provide advanced notice before updating the model. 31 | * Accuracy of text-moderation-stable may be slightly lower than for text-moderation-latest. 32 | */ 33 | @JSONField(name = "model") 34 | @JsonProperty("model") 35 | private String model; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/moderation/CreateModerationResponse.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.moderation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiResponse; 6 | import lombok.Data; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | public class CreateModerationResponse implements IOpenAiApiResponse { 12 | 13 | /** 14 | * The unique identifier for the moderation request. 15 | */ 16 | @JSONField(name = "id") 17 | @JsonProperty("id") 18 | private String id; 19 | 20 | /** 21 | * The model used to generate the moderation results. 22 | */ 23 | @JSONField(name = "model") 24 | @JsonProperty("model") 25 | private String model; 26 | 27 | /** 28 | * A list of moderation objects. 29 | *

30 | * See {@link Moderation} 31 | */ 32 | @JSONField(name = "results") 33 | @JsonProperty("results") 34 | private List results; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/moderation/Moderation.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.moderation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import xyz.felh.openai.IOpenAiApiObject; 6 | import lombok.Data; 7 | 8 | @Data 9 | public class Moderation implements IOpenAiApiObject { 10 | 11 | /** 12 | * Whether the content violates OpenAI's usage policies. 13 | */ 14 | @JSONField(name = "flagged") 15 | @JsonProperty("flagged") 16 | private Boolean flagged; 17 | 18 | /** 19 | * A list of the categories, and whether they are flagged or not. 20 | */ 21 | @JSONField(name = "categories") 22 | @JsonProperty("categories") 23 | private ModerationCategories categories; 24 | 25 | /** 26 | * A list of the categories along with their scores as predicted by model. 27 | */ 28 | @JSONField(name = "category_scores") 29 | @JsonProperty("category_scores") 30 | private ModerationCategoryScores categoryScores; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/moderation/ModerationCategories.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.moderation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class ModerationCategories implements IOpenAiApiObject { 10 | 11 | /** 12 | * Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harrassment. 13 | */ 14 | @JSONField(name = "hate") 15 | @JsonProperty("hate") 16 | private Boolean hate; 17 | 18 | /** 19 | * Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. 20 | */ 21 | @JsonProperty("hate/threatening") 22 | @JSONField(name = "hate/threatening") 23 | private Boolean hateThreatening; 24 | 25 | /** 26 | * Content that expresses, incites, or promotes harassing language towards any target. 27 | */ 28 | @JSONField(name = "harassment") 29 | @JsonProperty("harassment") 30 | private Boolean harassment; 31 | 32 | /** 33 | * Harassment content that also includes violence or serious harm towards any target. 34 | */ 35 | @JsonProperty("harassment/threatening") 36 | @JSONField(name = "harassment/threatening") 37 | private Boolean harassmentThreatening; 38 | 39 | /** 40 | * Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders. 41 | */ 42 | @JSONField(name = "self-harm") 43 | @JsonProperty("self-harm") 44 | private Boolean selfHarm; 45 | 46 | /** 47 | * Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders. 48 | */ 49 | @JSONField(name = "self-harm/intent") 50 | @JsonProperty("self-harm/intent") 51 | private Boolean selfHarmIntent; 52 | 53 | /** 54 | * Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts. 55 | */ 56 | @JSONField(name = "self-harm/instructions") 57 | @JsonProperty("self-harm/instructions") 58 | private Boolean selfHarmInstructions; 59 | 60 | /** 61 | * Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness). 62 | */ 63 | @JSONField(name = "sexual") 64 | @JsonProperty("sexual") 65 | private Boolean sexual; 66 | 67 | /** 68 | * Sexual content that includes an individual who is under 18 years old. 69 | */ 70 | @JSONField(name = "sexual/minors") 71 | @JsonProperty("sexual/minors") 72 | private Boolean sexualMinors; 73 | 74 | /** 75 | * Content that depicts death, violence, or physical injury. 76 | */ 77 | @JSONField(name = "violence") 78 | @JsonProperty("violence") 79 | private Boolean violence; 80 | 81 | /** 82 | * Content that depicts death, violence, or physical injury in graphic detail. 83 | */ 84 | @JSONField(name = "violence/graphic") 85 | @JsonProperty("violence/graphic") 86 | private Boolean violenceGraphic; 87 | 88 | } 89 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/moderation/ModerationCategoryScores.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.moderation; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class ModerationCategoryScores implements IOpenAiApiObject { 10 | 11 | /** 12 | * The score for the category 'hate'. 13 | */ 14 | @JSONField(name = "hate") 15 | @JsonProperty("hate") 16 | private Double hate; 17 | 18 | /** 19 | * The score for the category 'hate/threatening'. 20 | */ 21 | @JsonProperty("hate/threatening") 22 | @JSONField(name = "hate/threatening") 23 | private Double hateThreatening; 24 | 25 | /** 26 | * The score for the category 'harassment'. 27 | */ 28 | @JSONField(name = "harassment") 29 | @JsonProperty("harassment") 30 | private Double harassment; 31 | 32 | /** 33 | * The score for the category 'harassment/threatening'. 34 | */ 35 | @JsonProperty("harassment/threatening") 36 | @JSONField(name = "harassment/threatening") 37 | private Double harassmentThreatening; 38 | 39 | /** 40 | * The score for the category 'self-harm'. 41 | */ 42 | @JsonProperty("self-harm") 43 | @JSONField(name = "self-harm") 44 | private Double selfHarm; 45 | 46 | /** 47 | * The score for the category 'self-harm/intent'. 48 | */ 49 | @JsonProperty("self-harm/intent") 50 | @JSONField(name = "self-harm/intent") 51 | private Double selfHarmIntent; 52 | 53 | /** 54 | * The score for the category 'self-harm/instructions'. 55 | */ 56 | @JsonProperty("self-harm/instructions") 57 | @JSONField(name = "self-harm/instructions") 58 | private Double selfHarmInstructions; 59 | 60 | /** 61 | * The score for the category 'sexual'. 62 | */ 63 | @JSONField(name = "sexual") 64 | @JsonProperty("sexual") 65 | private Double sexual; 66 | 67 | /** 68 | * The score for the category 'sexual/minors'. 69 | */ 70 | @JsonProperty("sexual/minors") 71 | @JSONField(name = "sexual/minors") 72 | private Double sexualMinors; 73 | 74 | /** 75 | * The score for the category 'violence'. 76 | */ 77 | @JSONField(name = "violence") 78 | @JsonProperty("violence") 79 | private Double violence; 80 | 81 | /** 82 | * The score for the category 'violence/graphic'. 83 | */ 84 | @JsonProperty("violence/graphic") 85 | @JSONField(name = "violence/graphic") 86 | private Double violenceGraphic; 87 | 88 | } 89 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/usage/CompletionTokensDetails.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.usage; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | /** 9 | * @author Forest Wang 10 | * @package xyz.felh.openai 11 | * @class CompletionTokensDetails 12 | * @email forestwanglin@gmail.cn 13 | * @date 2024/10/25 14 | */ 15 | @Data 16 | public class CompletionTokensDetails implements IOpenAiApiObject { 17 | 18 | /** 19 | * Audio input tokens generated by the model. 20 | */ 21 | @JSONField(name = "audio_tokens") 22 | @JsonProperty("audio_tokens") 23 | private Long audioTokens; 24 | 25 | /** 26 | * Tokens generated by the model for reasoning. 27 | */ 28 | @JSONField(name = "reasoning_tokens") 29 | @JsonProperty("reasoning_tokens") 30 | private Long reasoningTokens; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/usage/PromptTokensDetails.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.usage; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | /** 9 | * @author Forest Wang 10 | * @package xyz.felh.openai.usage 11 | * @class PromptTokensDetails 12 | * @email forestwanglin@gmail.cn 13 | * @date 2024/10/25 14 | */ 15 | @Data 16 | public class PromptTokensDetails implements IOpenAiApiObject { 17 | 18 | /** 19 | * Audio input tokens present in the prompt. 20 | */ 21 | @JSONField(name = "audio_tokens") 22 | @JsonProperty("audio_tokens") 23 | private Long audioTokens; 24 | 25 | /** 26 | * Cached tokens present in the prompt. 27 | */ 28 | @JSONField(name = "cached_tokens") 29 | @JsonProperty("cached_tokens") 30 | private Long cachedTokens; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/openai/usage/Usage.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.usage; 2 | 3 | import com.alibaba.fastjson2.annotation.JSONField; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import xyz.felh.openai.IOpenAiApiObject; 7 | 8 | @Data 9 | public class Usage implements IOpenAiApiObject { 10 | 11 | /** 12 | * The number of prompt tokens used. 13 | */ 14 | @JSONField(name = "prompt_tokens") 15 | @JsonProperty("prompt_tokens") 16 | private Long promptTokens; 17 | 18 | /** 19 | * The number of completion tokens used. 20 | */ 21 | @JSONField(name = "completion_tokens") 22 | @JsonProperty("completion_tokens") 23 | private Long completionTokens; 24 | 25 | /** 26 | * The number of total tokens used 27 | */ 28 | @JSONField(name = "total_tokens") 29 | @JsonProperty("total_tokens") 30 | private Long totalTokens; 31 | 32 | /** 33 | * Breakdown of tokens used in a completion. 34 | */ 35 | @JSONField(name = "completion_tokens_details") 36 | @JsonProperty("completion_tokens_details") 37 | private CompletionTokensDetails completionTokensDetails; 38 | 39 | /** 40 | * Breakdown of tokens used in the prompt. 41 | */ 42 | @JSONField(name = "prompt_tokens_details") 43 | @JsonProperty("prompt_tokens_details") 44 | private PromptTokensDetails promptTokensDetails; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.TimeZone; 6 | 7 | public class DateUtils { 8 | 9 | public static final String FORMAT_UTC_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss'Z'"; 10 | 11 | public static String formatISO8601(Date date) { 12 | SimpleDateFormat sdf = new SimpleDateFormat(); 13 | sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 14 | sdf.applyPattern(FORMAT_UTC_ISO8601); 15 | return sdf.format(date); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/utils/ListUtils.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ListUtils { 7 | 8 | /** 9 | * Cast object to List 10 | * 11 | * @param obj object 12 | * @param clazz class 13 | * @param Type 14 | * @return the list 15 | */ 16 | public static List castList(Object obj, Class clazz) { 17 | List result = new ArrayList<>(); 18 | if (obj instanceof List) { 19 | for (Object o : (List) obj) { 20 | result.add(clazz.cast(o)); 21 | } 22 | return result; 23 | } 24 | return null; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/xyz/felh/utils/Preconditions.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.utils; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author Forest Wang 8 | * @package cn.magicwindow.common.util 9 | * @class Preconditions 10 | * @email forest@magicwindow.cn 11 | * @date 22/08/2017 17:26 12 | * @description Preconditions class 13 | */ 14 | public class Preconditions { 15 | 16 | /** 17 | * check if object is null for List Map String 18 | * 19 | * @param t object 20 | * @param Type T 21 | * @return isBlank 22 | */ 23 | public static boolean isBlank(T t) { 24 | boolean result = false; 25 | if (t == null) { 26 | return true; 27 | } 28 | if (t instanceof List) { 29 | if (((List) t).isEmpty()) { 30 | return true; 31 | } 32 | } else if (t instanceof Map) { 33 | if (((Map) t).isEmpty()) { 34 | return true; 35 | } 36 | } else if (t instanceof Object[]) { 37 | if (((Object[]) t).length == 0) { 38 | return true; 39 | } 40 | } else if (t instanceof String) { 41 | int strLen = ((String) t).length(); 42 | if (strLen == 0) { 43 | return true; 44 | } 45 | for (int i = 0; i < strLen; i++) { 46 | if (!Character.isWhitespace(((String) t).charAt(i))) { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | return result; 53 | } 54 | 55 | public static boolean isNotBlank(T t) { 56 | return !isBlank(t); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /jtokkit/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /jtokkit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | xyz.felh 8 | openai-java 9 | 4.0.2024102501 10 | 11 | 12 | jtokkit 13 | jar 14 | 15 | JTokkit of OpenAI API 16 | JTokkit of OpenAI API 17 | https://github.com/forestwanglin/openai-java/tree/main/jtokkit 18 | 19 | 20 | 21 21 | 21 22 | 21 23 | UTF-8 24 | 3.14.0 25 | 26 | 27 | 28 | 29 | 30 | xyz.felh 31 | core 32 | 4.0.2024102501 33 | 34 | 35 | 36 | org.apache.commons 37 | commons-lang3 38 | ${commons-langs.version} 39 | 40 | 41 | 42 | org.slf4j 43 | slf4j-api 44 | 45 | 46 | 47 | org.slf4j 48 | slf4j-simple 49 | test 50 | 51 | 52 | 53 | org.junit.jupiter 54 | junit-jupiter-api 55 | test 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/ByteArrayWrapper.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import java.util.Arrays; 4 | 5 | class ByteArrayWrapper { 6 | private final byte[] array; 7 | 8 | /* 9 | * Creates a new instance of ByteArrayWrapper from the given array. 10 | * The given array is not copied, so every calling method in this class must make sure 11 | * to never pass an array which reference leaked to the outside. Since some of our 12 | * construction methods already create new arrays, we do not want to copy here in this 13 | * constructor again. 14 | */ 15 | ByteArrayWrapper(byte[] array) { 16 | this.array = array; 17 | } 18 | 19 | /** 20 | * Returns the length of this array. 21 | * 22 | * @return the length of this array. 23 | */ 24 | public int length() { 25 | return array.length; 26 | } 27 | 28 | /** 29 | * Returns the bytes of this array from startIndex (inclusive) to endIndex (exclusive). The returned array is a copy 30 | * of the original array. 31 | * 32 | * @param startIndex the index from which to start copying (inclusive) 33 | * @param endIndex the index at which to stop copying (exclusive) 34 | * @return a new {@link ByteArrayWrapper} containing the bytes from startIndex (inclusive) to endIndex (exclusive) 35 | * @throws IllegalArgumentException if startIndex is out of bounds, endIndex is out of bounds or endIndex is less than 36 | * startIndex 37 | */ 38 | public ByteArrayWrapper getBytesBetween(int startIndex, int endIndex) { 39 | if (startIndex < 0 || startIndex >= array.length) { 40 | throw new IndexOutOfBoundsException("startIndex out of bounds: " + startIndex + " (" + this + ")"); 41 | } else if (endIndex < 0 || endIndex > array.length) { 42 | throw new IndexOutOfBoundsException("endIndex out of bounds: " + endIndex + " (" + this + ")"); 43 | } else if (startIndex >= endIndex) { 44 | throw new IllegalArgumentException("startIndex must be less than endIndex: " + startIndex + " >= " + endIndex); 45 | } 46 | 47 | int length = endIndex - startIndex; 48 | byte[] result = new byte[length]; 49 | System.arraycopy(array, startIndex, result, 0, length); 50 | return new ByteArrayWrapper(result); 51 | } 52 | 53 | @Override 54 | public boolean equals(Object other) { 55 | if (this == other) { 56 | return true; 57 | } else if (other == null || getClass() != other.getClass()) { 58 | return false; 59 | } 60 | 61 | ByteArrayWrapper that = (ByteArrayWrapper) other; 62 | return Arrays.equals(array, that.array); 63 | } 64 | 65 | @Override 66 | public int hashCode() { 67 | return Arrays.hashCode(array); 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return Arrays.toString(array); 73 | } 74 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/DefaultEncodingRegistry.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import xyz.felh.openai.jtokkit.api.EncodingRegistry; 4 | import xyz.felh.openai.jtokkit.api.EncodingType; 5 | 6 | /** 7 | * Thread-safe default implementation of {@link EncodingRegistry}. During initialization, it registers the default encodings 8 | * for the different {@link EncodingType}s. 9 | */ 10 | final class DefaultEncodingRegistry extends AbstractEncodingRegistry { 11 | 12 | /** 13 | * Initializes the registry with the default encodings. 14 | * 15 | * @throws IllegalStateException if an unknown encoding type is encountered 16 | */ 17 | public void initializeDefaultEncodings() { 18 | for (final EncodingType encodingType : EncodingType.values()) { 19 | addEncoding(encodingType); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/Encodings.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import xyz.felh.openai.jtokkit.api.*; 4 | 5 | public final class Encodings { 6 | 7 | /** 8 | * Creates a new {@link EncodingRegistry} with the default encodings found in the {@link EncodingType} enum. 9 | * 10 | * @return the new {@link EncodingRegistry} 11 | */ 12 | public static EncodingRegistry newDefaultEncodingRegistry() { 13 | final DefaultEncodingRegistry registry = new DefaultEncodingRegistry(); 14 | registry.initializeDefaultEncodings(); 15 | return registry; 16 | } 17 | 18 | /** 19 | * Creates a new {@link EncodingRegistry} without any {@link EncodingType} registered. Encodings will be 20 | * loaded on-demand when they are first requested. For example, if you call 21 | * {@link EncodingRegistry#getEncoding(EncodingType)} with {@link EncodingType#CL100K_BASE} for the first time, 22 | * it will be loaded from the classpath. Subsequent calls with {@link EncodingType#CL100K_BASE} will re-use the 23 | * already loaded encoded. 24 | * 25 | * @return the new {@link EncodingRegistry} 26 | */ 27 | public static EncodingRegistry newLazyEncodingRegistry() { 28 | return new LazyEncodingRegistry(); 29 | } 30 | 31 | private Encodings() { 32 | } 33 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/LazyEncodingRegistry.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import xyz.felh.openai.jtokkit.api.Encoding; 4 | import xyz.felh.openai.jtokkit.api.EncodingRegistry; 5 | import xyz.felh.openai.jtokkit.api.EncodingType; 6 | import xyz.felh.openai.jtokkit.api.ModelType; 7 | 8 | import java.util.Optional; 9 | 10 | /** 11 | * A lazy initialization implementation of {@link EncodingRegistry}. It does not register any encoding until either the 12 | * {@link #getEncoding(EncodingType)} or {@link #getEncoding(String)} method is called. 13 | * When one of these methods is called, the requested {@link EncodingType} is registered. 14 | */ 15 | final class LazyEncodingRegistry extends AbstractEncodingRegistry { 16 | 17 | @Override 18 | public Encoding getEncoding(final EncodingType encodingType) { 19 | addEncoding(encodingType); 20 | return super.getEncoding(encodingType); 21 | } 22 | 23 | @Override 24 | public Optional getEncoding(final String encodingName) { 25 | EncodingType.fromName(encodingName).ifPresent(this::addEncoding); 26 | 27 | return super.getEncoding(encodingName); 28 | } 29 | 30 | @Override 31 | public Encoding getEncodingForModel(final ModelType modelType) { 32 | addEncoding(modelType.getEncodingType()); 33 | return super.getEncodingForModel(modelType); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/SpecialEncoder.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import static java.nio.charset.StandardCharsets.UTF_8; 7 | 8 | final class SpecialEncoder { 9 | private static final String SPECIAL_START = "<|"; 10 | private static final String SPECIAL_END = "|>"; 11 | private final Map encodedToDecoded; 12 | 13 | public SpecialEncoder(Map encoder) { 14 | this.encodedToDecoded = new HashMap<>(encoder.size()); 15 | for (Map.Entry entry : encoder.entrySet()) { 16 | String key = entry.getKey(); 17 | Integer value = entry.getValue(); 18 | 19 | assert key.contains(SPECIAL_START) && key.contains(SPECIAL_END) : "Special tokens must contain <| and |> (but was " + key + ")"; 20 | 21 | encodedToDecoded.put(value, key); 22 | } 23 | } 24 | 25 | public byte[] decodeIfPresent(Integer encodedToken) { 26 | String result = encodedToDecoded.get(encodedToken); 27 | return result != null ? result.getBytes(UTF_8) : null; 28 | } 29 | 30 | public void checkForSpecialTokens(String text) { 31 | if (text.contains(SPECIAL_START) && text.contains(SPECIAL_END)) { 32 | for (String specialToken : encodedToDecoded.values()) { 33 | if (text.contains(specialToken)) { 34 | throw new UnsupportedOperationException("Encoding special tokens is not supported yet."); 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/api/EncodingRegistry.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.api; 2 | 3 | 4 | import java.util.Optional; 5 | 6 | /** 7 | * The EncodingRegistry is used to register custom encodings and to retrieve 8 | * encodings by name or type. The out-of-the-box supported encodings are registered automatically. 9 | */ 10 | public interface EncodingRegistry { 11 | 12 | /** 13 | * Returns the encoding with the given name, if it exists. Otherwise, returns an empty Optional. 14 | * Prefer using {@link #getEncoding(EncodingType)} or {@link #getEncodingForModel(ModelType)} for 15 | * built-in encodings. 16 | * 17 | * @param encodingName the name of the encoding 18 | * @return the encoding, if it exists 19 | */ 20 | Optional getEncoding(String encodingName); 21 | 22 | /** 23 | * Returns the encoding with the given type. 24 | * 25 | * @param encodingType the type of the encoding 26 | * @return the encoding 27 | */ 28 | Encoding getEncoding(EncodingType encodingType); 29 | 30 | /** 31 | * Returns the encoding that is used for the given model type, if it exists. Otherwise, returns an 32 | * empty Optional. Prefer using {@link #getEncodingForModel(ModelType)} for built-in encodings. 33 | *

34 | * Note that you can use this method to retrieve the correct encodings for snapshots of models, for 35 | * example "gpt-4-0314" or "gpt-3.5-turbo-0301". 36 | * 37 | * @param modelName the name of the model to get the encoding for 38 | * @return the encoding, if it exists 39 | */ 40 | Optional getEncodingForModel(String modelName); 41 | 42 | /** 43 | * Returns the encoding that is used for the given model type. 44 | * 45 | * @param modelType the model type 46 | * @return the encoding 47 | */ 48 | Encoding getEncodingForModel(ModelType modelType); 49 | 50 | /** 51 | * Registers a new byte pair encoding with the given name. The encoding must be thread-safe. 52 | * 53 | * @param parameters the parameters for the encoding 54 | * @return the registry for method chaining 55 | * @see GptBytePairEncodingParams 56 | * @throws IllegalArgumentException if the encoding name is already registered 57 | */ 58 | EncodingRegistry registerGptBytePairEncoding(GptBytePairEncodingParams parameters); 59 | 60 | /** 61 | * Registers a new custom encoding with the given name. The encoding must be thread-safe. 62 | * 63 | * @param encoding the encoding 64 | * @return the registry for method chaining 65 | * @throws IllegalArgumentException if the encoding name is already registered 66 | */ 67 | EncodingRegistry registerCustomEncoding(Encoding encoding); 68 | 69 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/api/EncodingResult.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.api; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * The result of encoding operation. 7 | */ 8 | public final class EncodingResult { 9 | 10 | private final List tokens; 11 | private final boolean truncated; 12 | private int tokenCount; 13 | 14 | public EncodingResult(List tokens, int tokenCount, boolean truncated) { 15 | this.tokens = tokens; 16 | this.tokenCount = tokenCount; 17 | this.truncated = truncated; 18 | } 19 | 20 | /** 21 | * @return the list of token ids 22 | */ 23 | public List getTokens() { 24 | if (tokens.size() != getTokenCount()) { 25 | throw new IllegalStateException("Token count does not match token list size (tokenCount=" + tokenCount + ", tokens size=" + tokens.size() + ")"); 26 | } 27 | return tokens; 28 | } 29 | 30 | public int getTokenCount() { 31 | if (tokenCount < 0) { 32 | tokenCount = tokens.size(); 33 | } 34 | return tokenCount; 35 | } 36 | 37 | /** 38 | * @return true if the token list was truncated because the maximum token length was exceeded 39 | */ 40 | public boolean isTruncated() { 41 | return truncated; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "EncodingResult{" 47 | + "tokens=" + getTokens() 48 | + ", tokenCount=" + getTokenCount() 49 | + ", truncated=" + truncated 50 | + '}'; 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/api/EncodingType.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.api; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.Arrays; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | import java.util.function.Function; 9 | import java.util.stream.Collectors; 10 | 11 | @Getter 12 | public enum EncodingType { 13 | 14 | R50K_BASE("r50k_base"), 15 | P50K_BASE("p50k_base"), 16 | P50K_EDIT("p50k_edit"), 17 | CL100K_BASE("cl100k_base"), 18 | O200K_BASE("o200k_base"); 19 | 20 | private static final Map nameToEncodingType = Arrays.stream(values()) 21 | .collect(Collectors.toMap(EncodingType::getName, Function.identity())); 22 | 23 | private final String name; 24 | 25 | EncodingType(final String name) { 26 | this.name = name; 27 | } 28 | 29 | public static Optional fromName(final String name) { 30 | return Optional.ofNullable(nameToEncodingType.get(name)); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/api/GptBytePairEncodingParams.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.api; 2 | 3 | import java.util.Map; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * Parameter for the byte pair encoding used to tokenize for the OpenAI GPT models. 8 | *

9 | * This library supports the encodings that are listed in {@link EncodingType} out of the box. 10 | * But if you want to use a custom encoding, you can use this class to pass the parameters to the library. 11 | * Use {@link EncodingRegistry#registerGptBytePairEncoding(GptBytePairEncodingParams)} to register your custom encoding 12 | * to the registry, so that you can easily use your encoding in conjunction with the predefined ones. 13 | *

14 | * The encoding parameters are: 15 | *

    16 | *
  • name: The name of the encoding. This is used to identify the encoding and must be unique.
  • 17 | *
  • pattern: The pattern that is used to split the input text into tokens.
  • 18 | *
  • encoder: The encoder that maps the tokens to their ids.
  • 19 | *
  • specialTokensEncoder: The encoder that maps the special tokens to their ids.
  • 20 | *
21 | */ 22 | public final class GptBytePairEncodingParams { 23 | 24 | private final String name; 25 | private final Pattern pattern; 26 | private final Map encoder; 27 | private final Map specialTokensEncoder; 28 | 29 | /** 30 | * Creates a new instance of {@link GptBytePairEncodingParams}. 31 | * 32 | * @param name the name of the encoding. This is used to identify the encoding and must be unique 33 | * @param pattern the pattern that is used to split the input text into tokens. 34 | * @param encoder the encoder that maps the tokens to their ids 35 | * @param specialTokensEncoder the encoder that maps the special tokens to their ids 36 | */ 37 | public GptBytePairEncodingParams( 38 | final String name, 39 | final Pattern pattern, 40 | final Map encoder, 41 | final Map specialTokensEncoder 42 | ) { 43 | this.name = name; 44 | this.pattern = pattern; 45 | this.encoder = encoder; 46 | this.specialTokensEncoder = specialTokensEncoder; 47 | } 48 | 49 | public String getName() { 50 | return name; 51 | } 52 | 53 | public Pattern getPattern() { 54 | return pattern; 55 | } 56 | 57 | public Map getEncoder() { 58 | return encoder; 59 | } 60 | 61 | public Map getSpecialTokensEncoder() { 62 | return specialTokensEncoder; 63 | } 64 | } -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/utils/ArgumentFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.utils; 2 | 3 | import com.alibaba.fastjson2.JSONArray; 4 | import com.alibaba.fastjson2.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | public class ArgumentFormat { 11 | 12 | public static String formatArguments(String arguments) { 13 | List lines = new ArrayList<>(); 14 | lines.add("{"); 15 | JSONObject jsonObject = JSONObject.parseObject(arguments); 16 | List properties = new ArrayList<>(); 17 | for (String fieldName : jsonObject.keySet()) { 18 | properties.add(String.format("\"%s\":%s", fieldName, formatValue(jsonObject.get(fieldName)))); 19 | } 20 | lines.add(String.join(",\n", properties)); 21 | lines.add("}"); 22 | return String.join("\n", lines); 23 | } 24 | 25 | private static String formatValue(Object value) { 26 | if (value instanceof String || value instanceof Number) { 27 | return String.format("\"%s\"", value); 28 | } 29 | if (value instanceof JSONArray array) { 30 | String result = "["; 31 | if (!array.isEmpty()) { 32 | result += array.stream().map(it -> { 33 | if (it instanceof Number || it instanceof String) { 34 | return String.format("\"%s\"", it); 35 | } else { 36 | return "\"\""; 37 | } 38 | }).collect(Collectors.joining(",")); 39 | } 40 | result += "]"; 41 | return result; 42 | } 43 | return "\"\""; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/utils/FunctionFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.utils; 2 | 3 | import com.alibaba.fastjson2.JSONObject; 4 | import lombok.extern.slf4j.Slf4j; 5 | import xyz.felh.openai.chat.tool.Function; 6 | import xyz.felh.openai.chat.tool.Tool; 7 | import xyz.felh.utils.Preconditions; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | @Slf4j 14 | public class FunctionFormat { 15 | 16 | public static String formatFunctionDefinitions(List tools) { 17 | List lines = new ArrayList<>(); 18 | lines.add("namespace functions {"); 19 | lines.add(""); 20 | for (Tool tool : tools) { 21 | Function function = tool.getFunction(); 22 | if (Preconditions.isNotBlank(function.getDescription())) { 23 | lines.add(String.format("// %s", function.getDescription())); 24 | } 25 | JSONObject p = JSONObject.parseObject(JSONObject.toJSONString(function.getParameters())); 26 | JSONObject properties = p.getJSONObject("properties"); 27 | if (Preconditions.isNotBlank(properties) && Preconditions.isNotBlank(properties.keySet())) { 28 | lines.add(String.format("type %s = (_: {", function.getName())); 29 | lines.add(formatObjectProperties(p, 0)); 30 | lines.add("}) => any;"); 31 | } else { 32 | lines.add(String.format("type %s = () => any;", function.getName())); 33 | } 34 | lines.add(""); 35 | } 36 | lines.add("} // namespace functions"); 37 | return String.join("\n", lines); 38 | } 39 | 40 | private static String formatObjectProperties(JSONObject p, int indent) { 41 | JSONObject properties = p.getJSONObject("properties"); 42 | if (Preconditions.isBlank(properties)) { 43 | return ""; 44 | } 45 | List requiredParams = p.getList("required", String.class); 46 | List lines = new ArrayList<>(); 47 | for (String key : properties.keySet()) { 48 | JSONObject props = properties.getJSONObject(key); 49 | String description = props.getString("description"); 50 | if (Preconditions.isNotBlank(description)) { 51 | lines.add(String.format("// %s", description)); 52 | } 53 | String question = "?"; 54 | if (Preconditions.isNotBlank(requiredParams) && requiredParams.contains(key)) { 55 | question = ""; 56 | } 57 | lines.add(String.format("%s%s: %s,", key, question, formatType(props, indent))); 58 | } 59 | 60 | return lines.stream().map(it -> " ".repeat(Math.max(0, indent)) + it).collect(Collectors.joining("\n")); 61 | } 62 | 63 | private static String formatType(JSONObject props, int indent) { 64 | String type = props.getString("type"); 65 | return switch (type) { 66 | case "string" -> { 67 | if (props.containsKey("enum")) { 68 | yield props.getList("enum", String.class).stream().map(it -> 69 | String.format("\"%s\"", it)).collect(Collectors.joining(" | ")); 70 | } 71 | yield "string"; 72 | } 73 | case "array" -> { 74 | if (props.containsKey("items")) { 75 | yield String.format("%s[]", formatType(props.getJSONObject("items"), indent)); 76 | } 77 | yield "any[]"; 78 | } 79 | case "object" -> String.format("{\n%s\n}", formatObjectProperties(props, indent + 2)); 80 | case "integer", "number" -> { 81 | if (props.containsKey("enum")) { 82 | yield String.join(" | ", props.getList("enum", String.class).stream().map(it -> 83 | String.format("\"%s\"", it)).toList()); 84 | } 85 | yield "number"; 86 | } 87 | case "boolean" -> "boolean"; 88 | case "null" -> "null"; 89 | default -> ""; 90 | }; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /jtokkit/src/main/java/xyz/felh/openai/jtokkit/utils/ToolContentFormat.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit.utils; 2 | 3 | import com.alibaba.fastjson2.JSONArray; 4 | import com.alibaba.fastjson2.JSONObject; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | public class ToolContentFormat { 11 | 12 | public static JSONObject tryFormat(String content) { 13 | try { 14 | return JSONObject.parseObject(content); 15 | } catch (Exception ignored) { 16 | } 17 | return null; 18 | } 19 | 20 | public static boolean isJSONString(String content) { 21 | try { 22 | JSONObject.parseObject(content); 23 | return true; 24 | } catch (Exception ignored) { 25 | } 26 | return false; 27 | } 28 | 29 | public static String format(Object content) { 30 | try { 31 | JSONObject.parseObject(content.toString()); 32 | return formatArguments(content.toString()); 33 | } catch (Exception ex) { 34 | // error 35 | } 36 | return content.toString(); 37 | } 38 | 39 | public static String formatArguments(String arguments) { 40 | List lines = new ArrayList<>(); 41 | lines.add("{"); 42 | JSONObject jsonObject = JSONObject.parseObject(arguments); 43 | List properties = new ArrayList<>(); 44 | for (String fieldName : jsonObject.keySet()) { 45 | properties.add(String.format("\"%s\":%s", fieldName, formatValue(jsonObject.get(fieldName)))); 46 | } 47 | lines.add(String.join(",\n", properties)); 48 | lines.add("}"); 49 | return String.join("\n", lines); 50 | } 51 | 52 | private static String formatValue(Object value) { 53 | switch (value) { 54 | case String str -> { 55 | return String.format("\"%s\"", str); 56 | } 57 | case Number num -> { 58 | return String.format("%s", num); 59 | } 60 | case JSONObject jsonObject -> { 61 | return String.format("%s", formatArguments(jsonObject.toString())); 62 | } 63 | case JSONArray array -> { 64 | String result = "["; 65 | if (!array.isEmpty()) { 66 | result += array.stream().map(ToolContentFormat::formatValue) 67 | .collect(Collectors.joining(",")); 68 | } 69 | result += "]"; 70 | return result; 71 | } 72 | case null, default -> { 73 | return "\"\""; 74 | } 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /jtokkit/src/test/java/xyz/felh/openai/jtokkit/LazyEncodingRegistryTest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.jtokkit; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.junit.jupiter.api.Test; 5 | import xyz.felh.openai.chat.ChatCompletion; 6 | import xyz.felh.openai.chat.ChatMessage; 7 | import xyz.felh.openai.chat.ChatMessageRole; 8 | import xyz.felh.openai.jtokkit.api.Encoding; 9 | import xyz.felh.openai.jtokkit.utils.TikTokenUtils; 10 | 11 | import java.lang.reflect.Field; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertTrue; 17 | 18 | @Slf4j 19 | public class LazyEncodingRegistryTest extends BaseEncodingRegistryTest { 20 | 21 | public LazyEncodingRegistryTest() { 22 | super(new LazyEncodingRegistry()); 23 | } 24 | 25 | @Test 26 | @SuppressWarnings("unchecked") 27 | public void initializeWithEmptyEncoding() throws NoSuchFieldException, IllegalAccessException { 28 | final Field field = AbstractEncodingRegistry.class.getDeclaredField("encodings"); 29 | field.setAccessible(true); 30 | final ConcurrentHashMap encodings = (ConcurrentHashMap) field.get(registry); 31 | assertTrue(encodings.isEmpty()); 32 | } 33 | 34 | @Test 35 | public void testTokens() { 36 | log.info("test tokens"); 37 | List messages = Arrays.asList( 38 | new ChatMessage(ChatMessageRole.SYSTEM, "You are a helpful assistant. Do not include pleasantries in your responses. Mark code language tag if there is code."), 39 | new ChatMessage(ChatMessageRole.USER, "Count 1 to 3"), 40 | new ChatMessage(ChatMessageRole.ASSISTANT, "1,2, 3"), 41 | new ChatMessage(ChatMessageRole.USER, " 中国和美国距离有多远?😄😄😄✅ ")); 42 | log.info("{}", TikTokenUtils.estimateTokensInMessage(ChatCompletion.Model.GPT_4_0613.getName(), messages.getFirst(), 0)); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /miniprogram_430.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestwanglin/openai-java/15cb89d98cbf0a2683cb750eceb30cd1402380de/miniprogram_430.jpg -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/StreamListener.java: -------------------------------------------------------------------------------- 1 | package xyz.felh; 2 | 3 | import lombok.Data; 4 | import lombok.extern.slf4j.Slf4j; 5 | import okhttp3.Response; 6 | import okhttp3.sse.EventSource; 7 | 8 | @Data 9 | @Slf4j 10 | public abstract class StreamListener { 11 | 12 | private EventSource eventSource; 13 | 14 | /** 15 | * Invoked when an event source has been accepted by the remote peer and may begin transmitting 16 | * events. 17 | * 18 | * @param requestId request ID 19 | * @param response OK http response 20 | */ 21 | public void onOpen(String requestId, Response response) { 22 | log.info("onOpen: {}", requestId); 23 | } 24 | 25 | /** 26 | * event line 27 | * 28 | * @param requestId request ID 29 | * @param t return IOpenAiApiObject 30 | */ 31 | public void onEvent(String requestId, T t) { 32 | log.info("onEvent: {}", requestId); 33 | } 34 | 35 | /** 36 | * event message finished, get payload [DONE] 37 | * 38 | * @param requestId request ID 39 | */ 40 | public void onEventDone(String requestId) { 41 | log.info("onEventDone: {}", requestId); 42 | } 43 | 44 | /** 45 | *

46 | * No further calls to this listener will be made. 47 | * 48 | * @param requestId request ID 49 | */ 50 | public void onClosed(String requestId) { 51 | log.info("onClosed: {}", requestId); 52 | } 53 | 54 | /** 55 | * Invoked when an event source has been closed due to an error reading from or writing to the 56 | * network. Incoming events may have been lost. No further calls to this listener will be made. 57 | * 58 | * @param requestId request ID 59 | * @param t throwable 60 | * @param response response 61 | */ 62 | public void onFailure(String requestId, Throwable t, Response response) { 63 | log.error("onFailure: {}", requestId, t); 64 | } 65 | 66 | /** 67 | * cancel eventSource 68 | */ 69 | public void close() { 70 | if (eventSource != null) { 71 | eventSource.cancel(); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/baidu/BaiduAiApi.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu; 2 | 3 | import io.reactivex.rxjava3.core.Single; 4 | import retrofit2.http.Body; 5 | import retrofit2.http.POST; 6 | import retrofit2.http.Path; 7 | import xyz.felh.baidu.chat.ChatCompletion; 8 | import xyz.felh.baidu.chat.CreateChatCompletionRequest; 9 | import xyz.felh.baidu.tokenizer.CreateTokenizerRequest; 10 | import xyz.felh.baidu.tokenizer.Tokenizer; 11 | 12 | /** 13 | * Retrofit2 API interface 14 | */ 15 | public interface BaiduAiApi { 16 | 17 | @POST("/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model_path}") 18 | Single createChat(@Path("model_path") String path, @Body CreateChatCompletionRequest request); 19 | 20 | @POST("/rpc/2.0/ai_custom/v1/wenxinworkshop/tokenizer/erniebot") 21 | Single tokenizer(@Body CreateTokenizerRequest request); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/baidu/bean/ResponseHeaders.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ResponseHeaders implements Serializable { 15 | 16 | private String appId; 17 | 18 | /** 19 | * The maximum number of requests that are permitted before exhausting the rate limit. 20 | * UNIT: RPM 21 | */ 22 | private Integer limitRequests; 23 | 24 | /** 25 | * The maximum number of tokens that are permitted before exhausting the rate limit. 26 | * UNIT: TPM 27 | */ 28 | private Integer limitTokens; 29 | 30 | /** 31 | * The remaining number of requests that are permitted before exhausting the rate limit. 32 | */ 33 | private Integer remainingRequests; 34 | 35 | /** 36 | * The remaining number of tokens that are permitted before exhausting the rate limit. 37 | */ 38 | private Integer remainingTokens; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/baidu/constant/BaiduAiConstants.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.constant; 2 | 3 | public interface BaiduAiConstants { 4 | 5 | 6 | String BASE_URL = "https://aip.baidubce.com"; 7 | 8 | String HEADER_AUTHORIZATION = "Authorization"; 9 | String HEADER_CONTENT_LENGTH = "Content-Length"; 10 | String HEADER_CONTENT_MD5 = "Content-MD5"; 11 | String HEADER_CONTENT_TYPE = "Content-Type"; 12 | String HEADER_HOST = "Host"; 13 | String HEADER_BCE_DATE = "x-bce-date"; 14 | String HEADER_BCE_PREFIX = "x-bce-"; 15 | 16 | String HEADER_X_APP_ID = "appid"; 17 | /** 18 | * 一分钟内允许的最大请求次数 19 | */ 20 | String HEADER_X_RATELIMIT_LIMIT_REQUESTS = "X-Ratelimit-Limit-Requests"; 21 | /** 22 | * 一分钟内允许的最大tokens消耗,包含输入tokens和输出tokens 23 | */ 24 | String HEADER_X_RATELIMIT_LIMIT_TOKENS = "X-Ratelimit-Limit-Tokens"; 25 | /** 26 | * 达到RPM速率限制前,剩余可发送的请求数配额,如果配额用完,将会在0-60s后刷新 27 | */ 28 | String HEADER_X_RATELIMIT_REMAINING_REQEUSTS = "X-Ratelimit-Remaining-Requests"; 29 | /** 30 | * 达到TPM速率限制前,剩余可消耗的tokens数配额,如果配额用完,将会在0-60s后刷新 31 | */ 32 | String HEADER_X_RATELIMIT_REMAINING_TOKENS = "X-Ratelimit-Remaining-Tokens"; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/baidu/interceptor/AuthenticationInterceptor.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.interceptor; 2 | 3 | import lombok.NonNull; 4 | import okhttp3.Interceptor; 5 | import okhttp3.Request; 6 | import okhttp3.Response; 7 | import xyz.felh.baidu.auth.BceV1Signer; 8 | import xyz.felh.utils.DateUtils; 9 | 10 | import java.io.IOException; 11 | import java.util.Date; 12 | import java.util.HashMap; 13 | 14 | import static xyz.felh.baidu.constant.BaiduAiConstants.HEADER_AUTHORIZATION; 15 | import static xyz.felh.baidu.constant.BaiduAiConstants.HEADER_BCE_DATE; 16 | 17 | public class AuthenticationInterceptor implements Interceptor { 18 | 19 | private final String ak; 20 | private final String sk; 21 | 22 | public AuthenticationInterceptor(String ak, String sk) { 23 | this.ak = ak; 24 | this.sk = sk; 25 | } 26 | 27 | @NonNull 28 | @Override 29 | public Response intercept(@NonNull Interceptor.Chain chain) throws IOException { 30 | String iso8601Date = DateUtils.formatISO8601(new Date()); 31 | Request request = chain.request(); 32 | BceV1Signer signer = new BceV1Signer(); 33 | String auth = signer.sign(BceV1Signer.BceRequest.builder() 34 | .uri(request.url().uri()) 35 | .httpMethod(request.method()) 36 | .headers(new HashMap<>() {{ 37 | put(HEADER_BCE_DATE, iso8601Date); 38 | }}) 39 | .build(), 40 | BceV1Signer.BceCredentials.builder() 41 | .accessKey(ak) 42 | .secretKey(sk) 43 | .build()); 44 | Request.Builder requestBuilder = chain.request().newBuilder() 45 | .header(HEADER_BCE_DATE, iso8601Date) 46 | .header(HEADER_AUTHORIZATION, auth); 47 | return chain.proceed(requestBuilder.build()); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/baidu/interceptor/ExtractHeaderInterceptor.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.baidu.interceptor; 2 | 3 | import lombok.NonNull; 4 | import lombok.extern.slf4j.Slf4j; 5 | import okhttp3.Interceptor; 6 | import okhttp3.Response; 7 | import xyz.felh.baidu.bean.ResponseHeaders; 8 | import xyz.felh.utils.Preconditions; 9 | 10 | import java.io.IOException; 11 | import java.util.Objects; 12 | import java.util.function.Consumer; 13 | 14 | import static xyz.felh.baidu.constant.BaiduAiConstants.*; 15 | import static xyz.felh.openai.constant.OpenAiConstants.HEADER_X_RATELIMIT_REMAINING_REQUESTS; 16 | 17 | 18 | /** 19 | * interceptor to get headers from response 20 | */ 21 | @Slf4j 22 | public class ExtractHeaderInterceptor implements Interceptor { 23 | 24 | private final Consumer headersConsumer; 25 | 26 | public ExtractHeaderInterceptor(Consumer headersConsumer) { 27 | this.headersConsumer = headersConsumer; 28 | } 29 | 30 | @NonNull 31 | @Override 32 | public Response intercept(@NonNull Interceptor.Chain chain) throws IOException { 33 | Response response = chain.proceed(chain.request()); 34 | if (Preconditions.isNotBlank(headersConsumer)) { 35 | ResponseHeaders.ResponseHeadersBuilder builder = ResponseHeaders.builder(); 36 | builder.appId(response.headers().get(HEADER_X_APP_ID)); 37 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_LIMIT_REQUESTS))) { 38 | builder.limitRequests(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_LIMIT_REQUESTS)))); 39 | } 40 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_LIMIT_TOKENS))) { 41 | builder.limitTokens(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_LIMIT_TOKENS)))); 42 | } 43 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_REMAINING_REQUESTS))) { 44 | builder.remainingRequests(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_REMAINING_REQUESTS)))); 45 | } 46 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_REMAINING_TOKENS))) { 47 | builder.remainingTokens(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_REMAINING_TOKENS)))); 48 | } 49 | headersConsumer.accept(builder.build()); 50 | } 51 | return response; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/openai/bean/ResponseHeaders.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.io.Serializable; 9 | 10 | @Data 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ResponseHeaders implements Serializable { 15 | 16 | private String model; 17 | 18 | private String organization; 19 | 20 | private Integer processingMs; 21 | 22 | private String version; 23 | 24 | /** 25 | * The maximum number of requests that are permitted before exhausting the rate limit. 26 | * UNIT: RPM 27 | */ 28 | private Integer limitRequests; 29 | 30 | /** 31 | * The maximum number of tokens that are permitted before exhausting the rate limit. 32 | * UNIT: TPM 33 | */ 34 | private Integer limitTokens; 35 | 36 | /** 37 | * The remaining number of requests that are permitted before exhausting the rate limit. 38 | */ 39 | private Integer remainingRequests; 40 | 41 | /** 42 | * The remaining number of tokens that are permitted before exhausting the rate limit. 43 | */ 44 | private Integer remainingTokens; 45 | 46 | /** 47 | * The time until the rate limit (based on requests) resets to its initial state. 48 | */ 49 | private String resetRequests; 50 | 51 | /** 52 | * The time until the rate limit (based on tokens) resets to its initial state. 53 | */ 54 | private String resetTokens; 55 | 56 | /** 57 | * requestId 58 | */ 59 | private String requestId; 60 | 61 | } 62 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/openai/bean/StreamToolCallsRequest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import xyz.felh.openai.chat.CreateChatCompletionRequest; 8 | 9 | import java.io.Serializable; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class StreamToolCallsRequest implements Serializable { 16 | 17 | private String requestId; 18 | 19 | private CreateChatCompletionRequest request; 20 | 21 | } -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/openai/constant/OpenAiConstants.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.constant; 2 | 3 | /** 4 | * OpenAI constants 5 | */ 6 | public interface OpenAiConstants { 7 | 8 | String BASE_URL = "https://api.openai.com"; 9 | 10 | /*********** headers' name from response *************/ 11 | 12 | String HEADER_OPENAI_MODEL = "openai-model"; 13 | String HEADER_OPENAI_ORGANIZATION = "openai-organization"; 14 | String HEADER_OPENAI_PROCESSING_MS = "openai-processing-ms"; 15 | String HEADER_OPENAI_VERSION = "openai-version"; 16 | 17 | 18 | /** 19 | * The maximum number of requests that are permitted before exhausting the rate limit. 20 | * Unit: RPM 21 | */ 22 | String HEADER_X_RATELIMIT_LIMIT_REQUESTS = "x-ratelimit-limit-requests"; 23 | 24 | /** 25 | * The maximum number of tokens that are permitted before exhausting the rate limit. 26 | * Unit: TPM 27 | */ 28 | String HEADER_X_RATELIMIT_LIMIT_TOKENS = "x-ratelimit-limit-tokens"; 29 | 30 | /** 31 | * The remaining number of requests that are permitted before exhausting the rate limit. 32 | */ 33 | String HEADER_X_RATELIMIT_REMAINING_REQUESTS = "x-ratelimit-remaining-requests"; 34 | 35 | /** 36 | * The remaining number of tokens that are permitted before exhausting the rate limit. 37 | */ 38 | String HEADER_X_RATELIMIT_REMAINING_TOKENS = "x-ratelimit-remaining-tokens"; 39 | 40 | /** 41 | * The time until the rate limit (based on requests) resets to its initial state. 42 | */ 43 | String HEADER_X_RATELIMIT_RESET_REQUESTS = "x-ratelimit-reset-requests"; 44 | 45 | /** 46 | * The time until the rate limit (based on tokens) resets to its initial state. 47 | */ 48 | String HEADER_X_RATELIMIT_RESET_TOKENS = "x-ratelimit-reset-tokens"; 49 | 50 | String HEADER_X_REQUEST_ID = "x-request-id"; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/openai/interceptor/AuthenticationInterceptor.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.interceptor; 2 | 3 | import lombok.NonNull; 4 | import okhttp3.Interceptor; 5 | import okhttp3.Request; 6 | import okhttp3.Response; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * OkHttp Interceptor that adds an authorization token header 12 | */ 13 | public class AuthenticationInterceptor implements Interceptor { 14 | 15 | private final String token; 16 | private final String orgId; 17 | private final String projectId; 18 | 19 | /** 20 | * Constructor 21 | * 22 | * @param token OPENAI_API_KEY 23 | */ 24 | public AuthenticationInterceptor(String token) { 25 | this(token, null, null); 26 | } 27 | 28 | /** 29 | * Constructor 30 | * 31 | * @param token OPENAI_API_KEY 32 | * @param orgId ORGANIZATION ID 33 | * @param projectId PROJECT ID 34 | */ 35 | public AuthenticationInterceptor(String token, String orgId, String projectId) { 36 | this.token = token; 37 | this.orgId = orgId; 38 | this.projectId = projectId; 39 | } 40 | 41 | @Override 42 | public @NonNull Response intercept(Chain chain) throws IOException { 43 | Request.Builder requestBuilder = chain.request() 44 | .newBuilder() 45 | .header("Authorization", "Bearer " + token); 46 | if (orgId != null) { 47 | requestBuilder.header("OpenAI-Organization", orgId); 48 | } 49 | if (projectId != null) { 50 | requestBuilder.header("OpenAI-Project", projectId); 51 | } 52 | // https://platform.openai.com/docs/assistants/overview 53 | if (chain.request().url().url().getPath().startsWith("/v1/assistants") 54 | || chain.request().url().url().getPath().startsWith("/v1/threads")) { 55 | requestBuilder.header("OpenAI-Beta", "assistants=v2"); 56 | } 57 | return chain.proceed(requestBuilder.build()); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/openai/interceptor/ExtractHeaderInterceptor.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai.interceptor; 2 | 3 | import lombok.NonNull; 4 | import lombok.extern.slf4j.Slf4j; 5 | import okhttp3.Interceptor; 6 | import okhttp3.Response; 7 | import xyz.felh.openai.bean.ResponseHeaders; 8 | import xyz.felh.utils.Preconditions; 9 | 10 | import java.io.IOException; 11 | import java.util.Objects; 12 | import java.util.function.Consumer; 13 | 14 | import static xyz.felh.openai.constant.OpenAiConstants.*; 15 | 16 | /** 17 | * interceptor to get headers from response 18 | */ 19 | @Slf4j 20 | public class ExtractHeaderInterceptor implements Interceptor { 21 | 22 | private final Consumer headersConsumer; 23 | 24 | public ExtractHeaderInterceptor(Consumer headersConsumer) { 25 | this.headersConsumer = headersConsumer; 26 | } 27 | 28 | @NonNull 29 | @Override 30 | public Response intercept(@NonNull Interceptor.Chain chain) throws IOException { 31 | Response response = chain.proceed(chain.request()); 32 | if (Preconditions.isNotBlank(headersConsumer)) { 33 | ResponseHeaders.ResponseHeadersBuilder builder = ResponseHeaders.builder(); 34 | builder.model(response.headers().get(HEADER_OPENAI_MODEL)) 35 | .organization(response.headers().get(HEADER_OPENAI_ORGANIZATION)) 36 | .version(response.headers().get(HEADER_OPENAI_VERSION)) 37 | .requestId(response.headers().get(HEADER_X_REQUEST_ID)) 38 | .resetRequests(response.headers().get(HEADER_X_RATELIMIT_RESET_REQUESTS)) 39 | .resetTokens(response.headers().get(HEADER_X_RATELIMIT_RESET_TOKENS)); 40 | if (Preconditions.isNotBlank(response.headers().get(HEADER_OPENAI_PROCESSING_MS))) { 41 | builder.processingMs(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_OPENAI_PROCESSING_MS)))); 42 | } 43 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_LIMIT_REQUESTS))) { 44 | builder.limitRequests(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_LIMIT_REQUESTS)))); 45 | } 46 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_LIMIT_TOKENS))) { 47 | builder.limitTokens(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_LIMIT_TOKENS)))); 48 | } 49 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_REMAINING_REQUESTS))) { 50 | builder.remainingRequests(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_REMAINING_REQUESTS)))); 51 | } 52 | if (Preconditions.isNotBlank(response.headers().get(HEADER_X_RATELIMIT_REMAINING_TOKENS))) { 53 | builder.remainingTokens(Integer.parseInt(Objects.requireNonNull(response.headers().get(HEADER_X_RATELIMIT_REMAINING_TOKENS)))); 54 | } 55 | headersConsumer.accept(builder.build()); 56 | } 57 | return response; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /service/src/main/java/xyz/felh/utils/SchemaUtils.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.utils; 2 | 3 | import com.alibaba.fastjson2.JSONObject; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import com.fasterxml.jackson.annotation.JsonPropertyDescription; 6 | import com.fasterxml.jackson.databind.JsonNode; 7 | import com.github.victools.jsonschema.generator.*; 8 | import com.github.victools.jsonschema.module.jackson.JacksonModule; 9 | import com.github.victools.jsonschema.module.jackson.JacksonOption; 10 | import lombok.Data; 11 | 12 | /** 13 | * @author Forest Wang 14 | * @package xyz.felh.utils 15 | * @class SchemaUtils 16 | * @email forestwanglin@gmail.cn 17 | * @date 2024/8/7 18 | *

19 | * See Options 20 | */ 21 | public class SchemaUtils { 22 | 23 | public static JSONObject convert2Schema(Class clazz) { 24 | SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, 25 | OptionPreset.PLAIN_JSON) 26 | .without(Option.SCHEMA_VERSION_INDICATOR) 27 | .with(Option.FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT) 28 | .with(new JacksonModule(JacksonOption.RESPECT_JSONPROPERTY_REQUIRED)); 29 | SchemaGeneratorConfig config = configBuilder.build(); 30 | SchemaGenerator generator = new SchemaGenerator(config); 31 | JsonNode jsonSchema = generator.generateSchema(clazz); 32 | return JSONObject.parseObject(jsonSchema.toString()); 33 | } 34 | 35 | public static void main(String[] args) { 36 | System.out.println(convert2Schema(GetWeatherParam.class)); 37 | } 38 | 39 | @Data 40 | public static class GetWeatherParam { 41 | @JsonPropertyDescription("The city and state, e.g. San Francisco, CA") 42 | @JsonProperty(value = "location", required = true) 43 | private String location; 44 | @JsonProperty("unit") 45 | private Unit unit; 46 | @JsonProperty("age") 47 | private int age; 48 | } 49 | 50 | public enum Unit { 51 | celsius, fahrenheit 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /service/src/test/java/xyz/felh/openai/BaiduAiServiceTest.java: -------------------------------------------------------------------------------- 1 | package xyz.felh.openai; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONObject; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import lombok.extern.slf4j.Slf4j; 7 | import okhttp3.OkHttpClient; 8 | import org.junit.jupiter.api.Test; 9 | import retrofit2.Retrofit; 10 | import xyz.felh.StreamListener; 11 | import xyz.felh.baidu.BaiduAiApi; 12 | import xyz.felh.baidu.BaiduAiService; 13 | import xyz.felh.baidu.chat.*; 14 | import xyz.felh.baidu.interceptor.ExtractHeaderInterceptor; 15 | import xyz.felh.baidu.tokenizer.CreateTokenizerRequest; 16 | 17 | import java.time.Duration; 18 | import java.util.List; 19 | import java.util.concurrent.TimeUnit; 20 | 21 | import static xyz.felh.baidu.BaiduAiService.*; 22 | 23 | @Slf4j 24 | public class BaiduAiServiceTest { 25 | 26 | 27 | private BaiduAiService getBaiduAiService() { 28 | String ak = System.getenv("BAIDU_AK"); 29 | String sk = System.getenv("BAIDU_SK"); 30 | ObjectMapper mapper = defaultObjectMapper(); 31 | OkHttpClient client = defaultClient(ak, sk, Duration.ofMillis(300000)) 32 | .newBuilder() 33 | .addInterceptor(new ExtractHeaderInterceptor(responseHeaders -> log.debug("headers: {}", JSON.toJSONString(responseHeaders)))) 34 | .build(); 35 | Retrofit retrofit = defaultRetrofit(client, mapper); 36 | BaiduAiApi api = retrofit.create(BaiduAiApi.class); 37 | return new BaiduAiService(api, client); 38 | } 39 | 40 | @Test 41 | public void chat() throws InterruptedException { 42 | BaiduAiService service = getBaiduAiService(); 43 | 44 | CreateChatCompletionRequest request = CreateChatCompletionRequest.builder() 45 | .messages( 46 | List.of(ChatMessage.builder() 47 | .role(ChatMessageRole.USER) 48 | .content("你好,请从1 数到20") 49 | .build()) 50 | ) 51 | .build(); 52 | // log.info(JSON.toJSONString(service.chat(ChatCompletion.Model.ERNIE_SPEED_128K, request))); 53 | 54 | // request.setStream(true); 55 | // service.createStreamChat("asdf", ModelType.ERNIE_SPEED_128K, request, new StreamListener<>() { 56 | // @Override 57 | // public void onEvent(String requestId, ChatCompletion t) { 58 | // log.info(JSON.toJSONString(t)); 59 | // } 60 | // }); 61 | // 62 | // TimeUnit.MINUTES.sleep(5); 63 | log.info(JSONObject.toJSONString(service.tokenizer(CreateTokenizerRequest.builder() 64 | .prompt("asdfaksdlf哈哈哈哈") 65 | .model("ernie-4.0-8k") 66 | .build()))); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /web.felh.xyz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestwanglin/openai-java/15cb89d98cbf0a2683cb750eceb30cd1402380de/web.felh.xyz.png --------------------------------------------------------------------------------