如果刚开始进行开发, 只用对必须携带的参数进行测试, 等项目熟练了之后再将所有的参数都进行测 查看可用的请求正文 : curl https://api.openai.com/v1/models \ -H “Authorization: Bearer $OPENAI_API_KEY”
请求url: POST https://api.openai.com/v1/chat/completions
有不同的消息对象, 一般的对话消息: 可以有三个参数,System、User、暂时只研究了Tool、Assistant、Function
- content (string,必需):系统消息的内容。
- role (string,必需):消息作者的角色,在这种情况下是system。
- name (string,可选):参与者的可选名称。为模型提供区分相同角色参与者的信息。
如果有其他的模型,ENDPOINT | LATEST MODELS |
|---|---|
/v1/assistants | All models except supported. The tool requires (and subsequent dated model releases) or (and subsequent versions).gpt-3.5-turbo-0301retrievalgpt-4-turbo-previewgpt-3.5-turbo-1106 |
/v1/audio/transcriptions | whisper-1 |
/v1/audio/translations | whisper-1 |
/v1/audio/speech | tts-1, tts-1-hd |
/v1/chat/completions | gpt-4 and dated model releases, and dated model releases, , and dated model releases, and dated model releases, and dated model releases, fine-tuned versions of gpt-4-turbo-previewgpt-4-vision-previewgpt-4-32kgpt-3.5-turbogpt-3.5-turbo-16kgpt-3.5-turbo |
/v1/completions (Legacy) | gpt-3.5-turbo-instruct, , babbage-002davinci-002 |
/v1/embeddings | text-embedding-3-small, , text-embedding-3-largetext-embedding-ada-002 |
/v1/fine_tuning/jobs | gpt-3.5-turbo, , babbage-002davinci-002 |
/v1/moderations | text-moderation-stable, text-moderation-latest |
/v1/images/generations | dall-e-2, dall-e-3 |
type 是一个可选的字符串参数,默认值为 text。此参数指定消息的类型,它必须是以下两个值之一:
- text:表示消息内容是纯文本。这是最常用的消息类型,适用于大多数聊天对话场景,其中消息以简单的文本形式交换。
- json_object:表示消息内容是一个 JSON 对象。这种类型的消息用于更复杂的交互,允许在消息中包含结构化数据,例如当需要传递具有特定属性的数据对象时。工具的属性包括:
- type (string,必需):工具的类型。目前,只支持function类型。
- function (object,必需):关于要调用的函数的详细信息。
function对象的属性:
- description (string,可选):函数功能的描述,模型使用它来决定何时以及如何调用该函数。
- name (string,必需):要调用的函数的名称。名称必须由a-z, A-Z, 0-9组成,或包含下划线和破折号,最大长度为64。
- parameters (object,可选):函数接受的参数,以JSON Schema对象描述。可参考示例指南和JSON Schema参考文档以了解格式详情。
如果省略parameters,则定义了一个参数列表为空的函数。这里我们暂时不用管, auto是默认值, 他允许模型根据对话的上下文和可用的工具自动决定最佳行动路径。
当tool_choice是一个对象时,它指定模型应该使用的具体工具。这允许你强制模型调用特定的函数,通过明确指定函数的名称。
对象必须包含以下属性:
- type (string,必需):工具的类型。当前只支持function。
- function (object,必需):定义要调用的函数的详细信息。
function 对象的属性:
- name (string,必需):要调用的函数的名称。返回:返回一个聊天完成对象,或者如果请求是流式的,则返回一个流式的聊天完成块对象序列。
/**ChatCompletionRequest
* @description 对话聊天,请求信息依照;OpenAI官网API构建参数;https://platform.openai.com/playground
*/
@Data
@Builder
@Slf4j
@JsonInclude(JsonInclude.Include.NON_NULL)
@NoArgsConstructor
@AllArgsConstructor
public class ChatCompletionRequest implements Serializable {
/** 默认模型 */
private String model = Model.GPT_3_5_TURBO.getCode();
/** 问题描述 */
private List<Message> messages;
/** 控制温度【随机性】;0到2之间。较高的值(如0.8)将使输出更加随机,而较低的值(如0.2)将使输出更加集中和确定 */
private double temperature = 0.2;
/** 多样性控制;使用温度采样的替代方法称为核心采样,其中模型考虑具有top_p概率质量的令牌的结果。因此,0.1 意味着只考虑包含前 10% 概率质量的代币 */
@JsonProperty("top_p")
private Double topP = 1d;
/** 为每个提示生成的完成次数 */
private Integer n = 1;
/** 是否为流式输出;就是一蹦一蹦的,出来结果 */
private boolean stream = false;
/** 停止输出标识 */
private List<String> stop;
/** 输出字符串限制;0 ~ 4096 */
@JsonProperty("max_tokens")
private Integer maxTokens = 2048;
/** 频率惩罚;降低模型重复同一行的可能性 */
@JsonProperty("frequency_penalty")
private double frequencyPenalty = 0;
/** 存在惩罚;增强模型谈论新话题的可能性 */
@JsonProperty("presence_penalty")
private double presencePenalty = 0;
/** 生成多个调用结果,只显示最佳的。这样会更多的消耗你的 api token */
@JsonProperty("logit_bias")
private Map logitBias;
/** 调用标识,避免重复调用 */
private String user;
@Getter
@AllArgsConstructor
public enum Model {
/** gpt-3.5-turbo */
GPT_3_5_TURBO("gpt-3.5-turbo"),
/** GPT4.0 */
GPT_4("gpt-4"),
/** GPT4.0 超长上下文 */
GPT_4_32K("gpt-4-32k"),
;
private String code;
}
}
/**
Message
* @description 信息描述
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Message implements Serializable {
private String role;
private String content;
private String name;
public Message() {
}
private Message(Builder builder) {
this.role = builder.role;
this.content = builder.content;
this.name = builder.name;
}
public static Builder builder() {
return new Builder();
}
/**
* 建造者模式
*/
public static final class Builder {
private String role;
private String content;
private String name;
public Builder() {
}
public Builder role(Constants.Role role) {
this.role = role.getCode();
return this;
}
public Builder content(String content) {
this.content = content;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Message build() {
return new Message(this);
}
}
}
choices 的属性包括:
选项的属性:
finish_reason (string):模型停止生成令牌的原因。可能的值包括:
- stop:如果模型遇到一个自然的停止点或提供的停止序列。
- length:如果达到请求中指定的最大令牌数。
- content_filter:如果内容因我们的内容过滤器的标记而被省略。
- tool_calls:如果模型调用了工具。
- function_call (已弃用):如果模型调用了函数。
index (integer):选项在选择列表中的索引。
message (object):模型生成的聊天完成消息。
message 对象的属性:
- logprobs (object or null):选择的对数概率信息。
- logprobs 对象的属性:
content (array or null):带有对数概率信息的消息内容令牌列表。
- content 数组的属性:
- token (string):令牌。
- logprob (number):此令牌的对数概率。
- bytes (array or null):表示令牌的UTF-8字节列表。在字符由多个令牌表示且必须组合其字节表示以生成正确文本表示的情况下有用。如果令牌没有字节表示,则可以为null。
- top_logprobs (array):此令牌位置最可能的令牌及其对数概率的列表。在罕见的情况下,返回的top_logprobs数量可能少于请求的数量。usage 对象的属性可能包括完成请求的具体统计数据,如请求的令牌数量等,但具体细节未在这里提供。这些信息有助于追踪和管理与特定聊天完成请求相关的资源消耗情况。
- completion_tokens (integer):在生成的完成内容中的令牌数量。这个数字反映了模型为回应给定提示而生成的文本的长度。
- prompt_tokens (integer):在提示中的令牌数量。这表示触发模型生成回应的输入文本的长度。
- total_tokens (integer):请求中使用的总令牌数(提示 + 完成)。这个总数是监控成本和限制使用的关键指标,因为许多API的计费模型是基于令牌使用量的。/**
* @description 对话请求结果信息
*/
@Data
public class ChatCompletionResponse implements Serializable {
/** ID */
private String id;
/** 对象 */
private String object;
/** 模型 */
private String model;
/** 对话 */
private List<ChatChoice> choices;
/** 创建 */
private long created;
/** 耗材 */
private Usage usage;
/**
* 该指纹代表模型运行时使用的后端配置。
* https://platform.openai.com/docs/api-reference/chat
*/
@JsonProperty("system_fingerprint")
private String systemFingerprint;
}
/**
ChatChoice
* @description 对话信息
*/
@Data
public class ChatChoice implements Serializable {
private long index;
/** stream = true 请求参数里返回的属性是 delta */
@JsonProperty("delta")
private Message delta;
/** stream = false 请求参数里返回的属性是 delta */
@JsonProperty("message")
private Message message;
@JsonProperty("finish_reason")
private String finishReason;
private String logprobs;
}
我们首先调用默认的必须的参数进测试, 然后通过curl来进行实现。
# 一般如果自己没有host的话,那么就需要使用其他的代理, 此时就需要将https://api.openai.com改成自己的代理
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hello!"
}
]
}'响应的内容
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1677652288,
"model": "gpt-3.5-turbo-0613",
"system_fingerprint": "fp_44709d6fcb",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "\n\nHello there, how may I assist you today?",
},
"logprobs": null,
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 9,
"completion_tokens": 12,
"total_tokens": 21
}
}
/**
* 定义访问接口,这里后续会不断地进行扩展,包括;模型列表、消耗额度、流式对话、画图等各类方法。
* 这个接口是没有对应的硬编码实现类的,它的存在只是定义标准,之后由 Retrofit 工具包进行创建服务.
* 可以把这想象成是对 DAO 接口与数据库的连接数据源之间的操作。
*
* 默认 GPT-3.5 问答模型
* @param chatCompletionRequest 请求信息
* @return 返回结果
*/
String v1_chat_completion = "v1/chat/completions";
@POST(v1_chat_completion)
Single<ChatCompletionResponse> completions(@Body ChatCompletionRequest chatCompletionRequest);这个接口是没有对应的硬编码实现类的,它的存在只是定义标准,之后由 Retrofit 工具包进行创建服务. 例如**IOpenAiApi openAiApi = new Retrofit.Builder()**可以把这想象成是对 DAO 接口与数据库的连接数据源之间的操作
通过OkHTTP发送的请求,之后调用模型进行应答
public static void main(String[] args) {
//1. 先创建一个Http连接
OkHttpClient okHttpClient = new OkHttpClient
.Builder() // 创建了一个OkHttpClient实例, 然后在通过链式创建对应的属性。
// .addInterceptor(httpLoggingInterceptor)
.addInterceptor(chain -> {
Request request = chain.request();
request.url().newBuilder()
.addQueryParameter("token", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4ZmciLCJleHAiOjE3MDU3NTQzNTYsImlhdCI6MTcwNTc1NDA1NiwianRpIjoiMTFkOGRmNWEtZjI3Mi00NTE0LWIyYmItYmMyZGNkYmZkNTZkIiwidXNlcm5hbWUiOiJ4ZmcifQ.Bfsb7Mp9t7wp7pvKuh-U63y2sOhW1nbcppDYHk30fe8")
.build();
request.newBuilder().header(Header.AUTHORIZATION.getValue(), "Bearer " + "sk-dS9kPBZCiUXEN9jh133c8f44A5984dAc8f1350E18c71XXXX")
.method(request.method(), request.body())
.build();
return chain.proceed(request); // 继续请求链
}).build(); // 构建请求实例
//2. 通过Retrofit库实现 将HTTP请求转换为Java接口,这是通过声明式接口的方式实现的
// 关键点在于Retrofit的动态代理功能,它能够从一个接口自动生成实际的HTTP请求和处理逻辑。
// 通过设置 所有请求的基础URL 实现 https://service-d6wuqy4n-1320869466.cd.apigw.tencentcs.com/ +接口: 例如/v1/completions
// 接着在指定特定的okHttpClient为客户端。
// 同时添加了一个调用适配器工厂,用于支持RxJava 2。 和一个转换器工厂,这里使用Jackson库来处理JSON数据。
// 然后就调用build创建了Retrofit实例
// 最后,.create(IOpenAiApi.class)方法通过动态代理机制在Retrofit实例上创建了IOpenAiApi接口的实例。
IOpenAiApi openAiApi = new Retrofit.Builder()
.baseUrl("https://service-d6wuqy4n-1320869466.cd.apigw.tencentcs.com/")
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(JacksonConverterFactory.create())
.build().create(IOpenAiApi.class);
//3. 通过领域层中实现这里需要的问答模型(当然也可以创建其他模型),创建我们需要的Message填写问答内容
Message message = Message.builder().role(Constants.Role.USER).content("写一个java选择排序").build();
//4. 通过创建问答模型的问答请求对象, 然后将上述的Message内容 和 需要的一些其他参数传递进去。
ChatCompletionRequest chatCompletion = ChatCompletionRequest
.builder()
.messages(Collections.singletonList(message))
.model(ChatCompletionRequest.Model.GPT_3_5_TURBO.getCode())
.build();
Single<ChatCompletionResponse> chatCompletionResponseSingle = openAiApi.completions(chatCompletion);
//6. 通过得到的chatCompletionResponseSingle对象使用blockingGet方法,此方法直接返回Single发出的结果,而不是通过回调。
ChatCompletionResponse chatCompletionResponse = chatCompletionResponseSingle.blockingGet();// 是一个阻塞操作,它会暂停当前线程直到Single发出项或错误信号。
chatCompletionResponse.getChoices().forEach(e -> {
System.out.println(e.getMessage());
});
}