aaaaaaa## 使用OpenAI API解决语言处理任务

概述

OpenAI为开发者提供了强大的API接口,以访问其先进的语言模型。这些API能够帮助开发者执行各种自然语言处理(NLP)任务,如内容生成、摘要提取、分类和语义分析以及翻译等。

主要功能

  • 内容生成:根据给定的提示或上下文生成文本。
  • 摘要:从较长的文章中提取关键点并生成简短摘要。
  • 分类及语义分析:对文本进行分类,并分析其中的情感倾向。
  • 翻译:将一种语言的文本翻译成另一种语言。

API入门

Completions API

Completions API是与OpenAI的语言模型交互的主要方式。用户可以向API发送一段文本,然后API会基于提供的文本和指定的参数返回相应的完成文本。

访问API
  • 通过HTTP请求调用API。
  • 需要使用个人的API key来验证身份。
请求格式

在构造请求时,开发者需要提供必要的信息,比如使用的模型、输入的提示文本以及其他可选参数,以便获得期望的结果。

1
2
3
4
5
6
7
8
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": "user", "content": "Say this is a test!"}],
     "temperature": 0.7
   }'

支持的模型有7个。

  • GPT-4 Limited beta: GPT-3.5 之上的改进,对自然语言的理解和处理更强。
  • GPT-3.5:在GPT-3 基础上改进的,对自然语言的理解和处理更强。
  • DALL·E Beta: 图像处理。
  • Whisper Beta: 音频转文本。
  • Embeddings:将文本转成嵌入向量。
  • Moderation:检测敏感信息和非安全内容。
  • GPT-3:自然语言理解和处理的模型。

有了这些API,在我们的程序中就可以使用它们,也可以用这些API做出我们自己的插件来。

程序中调用OpenAI的API

在Spring中用HTTPClient直接调用OpenAI 的API。我们从 /v1/chat/completions、 /v1/completions、/v1/edits 与 /v1/images/generations四个API入手,一步步进行封装。

先定义一个 基础请求实体类,供service使用,参考如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.api.request;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BaseRequest {
    @NotBlank(message = "openai_apiKey cannot be blank")
    private String apiKey;
}

再按照我们示例的几种API,定义多种请求实体类。

1
2
3
4
5
6
7
8
package com.example.chatgptdemo.api.request;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ChatCompletionRequest extends BaseRequest{
    private String content;
}
1
2
3
4
5
6
7
8
package com.example.chatgptdemo.api.request;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CompletionRequest extends BaseRequest{
    private String prompt;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.api.request;

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EditRequest extends BaseRequest{
    private String input;
    private String instruction;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.api.request;

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ImageGenerationRequest extends BaseRequest {
    private String prompt;
    private Integer n;
}

然后定义返回给调用方的Response类。

1
2
3
4
5
6
7
8
package com.example.chatgptdemo.api.response;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ChatCompletionResponse {
    private String content;
}
1
2
3
4
5
6
7
8
package com.example.chatgptdemo.api.response;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CompletionResponse {
    private String text;
}
1
2
3
4
5
6
7
8
9
package com.example.chatgptdemo.api.response;

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EditResponse {
    private String text;
}
1
2
3
4
5
6
7
8
9
package com.example.chatgptdemo.api.response;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class ImageGenerationResponse {
    private List<String> urls;
}

接下来则 定义Service层,这也是我们进行核心业务定制的部分。定义ChatgptDemoService接口和ChatgptDemoServiceImpl实现类。

1
2
3
4
5
6
7
8
package com.example.chatgptdemo.service;

public interface ChatgptDemoService {
    ChatCompletionResponse chatCompletions(ChatCompletionRequest request);
    CompletionResponse completions(CompletionRequest request);
    EditResponse edits(EditRequest request);
    ImageGenerationResponse imageGenerations(ImageGenerationRequest request);
}

Service的实现如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.example.chatgptdemo.service.impl;
@Service
public class ChatgptDemoServiceImpl implements ChatgptDemoService {
    final private ChatgptNetworkService networkService;
    @Autowired
    public ChatgptDemoServiceImpl(ChatgptNetworkService networkService) {
        this.networkService = networkService;
    }
    @Override
    public ChatCompletionResponse chatCompletions(ChatCompletionRequest request) {
        MessageObject message = new MessageObject();
        message.setContent(request.getContent());
        message.setRole("user");
        ChatCompletionModel model = new ChatCompletionModel();
        model.setModel("gpt-3.5-turbo");
        model.setMessages(Collections.singletonList(message));
        model.setTemperature(0.7);
        ChatCompletionResult result = networkService.ChatCompletions(model, request.getApiKey());
        Optional<ChoiceResult> firstResultOptional = result.getChoices().stream().findFirst();
        ChatCompletionResponse response = new ChatCompletionResponse();
        if (firstResultOptional.isEmpty()) {
            return response;
        }
        ChoiceResult choiceResult = firstResultOptional.get();
        response.setContent(choiceResult.getMessage().getContent());
        return response;
    }
    @Override
    public CompletionResponse completions(CompletionRequest request) {
        CompletionModel model = new CompletionModel();
        model.setModel("text-davinci-003");
        model.setPrompt(request.getPrompt());
        model.setMaxTokens(7);
        model.setN(1);
        model.setTopP(1);
        model.setStream(false);
        CompletionResult result = networkService.completions(model, request.getApiKey());
        Optional<ChoiceResult> firstResultOptional = result.getChoices().stream().findFirst();
        CompletionResponse response = new CompletionResponse();
        if (firstResultOptional.isEmpty()) {
            return response;
        }
        ChoiceResult choiceResult = firstResultOptional.get();
        response.setText(choiceResult.getText());
        return response;
    }
    @Override
    public EditResponse edits(EditRequest request) {
        EditModel model = new EditModel();
        model.setInput(request.getInput());
        model.setInstruction(request.getInstruction());
        EditResult result = networkService.edits(model, request.getApiKey());
        Optional<ChoiceResult> firstResultOptional = result.getChoices().stream().findFirst();
        EditResponse response = new EditResponse();
        if (firstResultOptional.isEmpty()) {
            return response;
        }
        ChoiceResult choiceResult = firstResultOptional.get();
        response.setText(choiceResult.getText());
        return response;
    }
    @Override
    public ImageGenerationResponse imageGenerations(ImageGenerationRequest request) {
        ImageGenerationModel model = new ImageGenerationModel();
        model.setPrompt(request.getPrompt());
        model.setN(request.getN());
        model.setSize("1024x1024");
        ImageGenerationResult result = networkService.imageGenerations(model, request.getApiKey());
        List<ImageGenerationResult.ImageGenerationData> resultList =
                result.getData().stream().toList();
        List<String> urls = new ArrayList<>(resultList.size());
        resultList.forEach(r -> urls.add(r.getUrl()));
        ImageGenerationResponse response = new ImageGenerationResponse();
        response.setUrls(urls);
        return response;
    }
}

通过实现类的代码可以看出,基本是围绕构造OpenAI提供的API调用参数作文章。只不过为了验证,我们写死了很多参数,在实际实操过程中我们可以依据自身业务情况,进行动态调整。 我们使用了ChatgptNetworkService这样一个Bean作为通讯基础,而这个Bean的功能正是对OpenAI的API进行调用。我们直接使用RestTemplate访问的API。 为了构造API调用,我们定义了xxxModel作为API调用的请求参数实体类,还定义了xxxResult作为API接口返回值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package com.example.chatgptdemo.network.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CompletionModel {
    private String model;
    private String prompt;
    @JsonProperty("max_tokens")
    private Integer maxTokens;
    private Integer n;
    @JsonProperty("top_p")
    private Integer topP;
    private Boolean stream;
}
1
2
3
4
5
6
7
8
9
package com.example.chatgptdemo.network.model;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class MessageObject {
    private String role;
    private String content;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package com.example.chatgptdemo.network.model.chat;
import com.example.chatgptdemo.network.model.MessageObject;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class ChatCompletionModel {
    private String model;
    private List<MessageObject> messages;
    private Double temperature;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.network.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EditModel {
    private String model;
    private String input;
    private String instruction;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.network.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ImageGenerationModel {
    private String prompt;
    private Integer n;
    private String size;
}

Result实体类:

1
2
3
4
5
6
7
8
package com.example.chatgptdemo.network.result;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CreatedResult {
    private Long created;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.example.chatgptdemo.network.result;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ObjectResult extends CreatedResult{
    private String id;
    private String object;
    private String model;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.example.chatgptdemo.network.result;
import com.example.chatgptdemo.network.model.MessageObject;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ChoiceResult {
    private MessageObject message;
    private String text;
    @JsonProperty("finish_reason")
    private String finishReason;
    private Integer index;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.example.chatgptdemo.network.result;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UsageResult {
    @JsonProperty("prompt_tokens")
    private Integer promptTokens;
    @JsonProperty("completion_tokens")
    private Integer completionTokens;
    @JsonProperty("total_tokens")
    private Integer totalTokens;
}
1
2
3
4
5
6
7
package com.example.chatgptdemo.network.result;
@Getter
@Setter
public class CompletionResult {
    private UsageResult usage;
    private List<ChoiceResult> choices;
}
1
2
3
4
5
package com.example.chatgptdemo.network.result.chat;
@Getter
@Setter
public class ChatCompletionResult extends CompletionResult {
}
1
2
3
4
5
6
7
package com.example.chatgptdemo.network.result;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EditResult extends CompletionResult {
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.example.chatgptdemo.network.result;
import com.example.chatgptdemo.api.response.ImageGenerationResponse;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class ImageGenerationResult extends CreatedResult{
    private List<ImageGenerationData> data;
    @Getter
    @Setter
    public static class ImageGenerationData {
        private String url;
    }
}

在实体类定义完毕之后,接下来我们着手实现ChatGptNetworkService,看看Spring中如何通过RestTemplate调用OpenAI的API。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.example.chatgptdemo.network;
@Service
public class ChatgptNetworkService {
    Gson gson = new Gson();
    private static final Logger logger = LoggerFactory.getLogger(ChatgptNetworkService.class);
    final private RestTemplate restTemplate;
    @Autowired
    public ChatgptNetworkService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    public ChatCompletionResult ChatCompletions(ChatCompletionModel model, String apiKey) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        HttpEntity<?> entity = new HttpEntity<>(model, headers);
        URI uri = UriComponentsBuilder.newInstance()
                .scheme("https")
                .host("api.openai.com")
                .path("/v1/chat/completions")
                .build()
                .toUri();
        logger.info("The parameters for request API {}: {}", uri, gson.toJson(entity));
        ResponseEntity<ChatCompletionResult> response = restTemplate.postForEntity(uri, entity, ChatCompletionResult.class);
        logger.info("The response result from API {}: {}", uri, gson.toJson(response));
        if (response.getStatusCode().isError()) {
            throw new RuntimeException(gson.toJson(response.getBody()));
        }
        return response.getBody();
    }
    public CompletionResult completions(CompletionModel model, String apiKey) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        HttpEntity<?> entity = new HttpEntity<>(model, headers);
        URI uri = UriComponentsBuilder.newInstance()
                .scheme("https")
                .host("api.openai.com")
                .path("/v1/completions")
                .build()
                .toUri();
        logger.info("The parameters for request API {}: {}", uri, gson.toJson(entity));
        ResponseEntity<CompletionResult> response = restTemplate.postForEntity(uri, entity, CompletionResult.class);
        logger.info("The response result from API {}: {}", uri, gson.toJson(response));
        if (response.getStatusCode().isError()) {
            throw new RuntimeException(gson.toJson(response.getBody()));
        }
        return response.getBody();
    }
    public EditResult edits(EditModel model, String apiKey) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        HttpEntity<?> entity = new HttpEntity<>(model, headers);
        URI uri = UriComponentsBuilder.newInstance()
                .scheme("https")
                .host("api.openai.com")
                .path("/v1/edits")
                .build()
                .toUri();
        logger.info("The parameters for request API {}: {}", uri, gson.toJson(entity));
        ResponseEntity<EditResult> response = restTemplate.postForEntity(uri, entity, EditResult.class);
        logger.info("The response result from API {}: {}", uri, gson.toJson(response));
        if (response.getStatusCode().isError()) {
            throw new RuntimeException(gson.toJson(response.getBody()));
        }
        return response.getBody();
    }
    public ImageGenerationResult imageGenerations(ImageGenerationModel model, String apiKey) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);
        HttpEntity<?> entity = new HttpEntity<>(model, headers);
        URI uri = UriComponentsBuilder.newInstance()
                .scheme("https")
                .host("api.openai.com")
                .path("/v1/images/generations")
                .build()
                .toUri();
        logger.info("The parameters for request API {}: {}", uri, gson.toJson(entity));
        ResponseEntity<ImageGenerationResult> response = restTemplate.postForEntity(uri, entity, ImageGenerationResult.class);
        logger.info("The response result from API {}: {}", uri, gson.toJson(response));
        if (response.getStatusCode().isError()) {
            throw new RuntimeException(gson.toJson(response.getBody()));
        }
        return response.getBody();
    }
}

代码一点都不复杂,就是按照API的规定进行常规的HTTP REST请求。

有了这个service,再定义Controller层。这层是整个系统与外部调用API的门户。我们先定义ChatgptDemoController类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.example.chatgptdemo.controller;

@RestController
public class ChatgptDemoController {
    final private ChatgptDemoService chatgptDemoService;
    @Autowired
    public ChatgptDemoController(ChatgptDemoService chatgptDemoService) {
        this.chatgptDemoService = chatgptDemoService;
    }
    @PostMapping("/v1/chat/completions")
    public ChatCompletionResponse chatCompletions(@Validated @RequestBody ChatCompletionRequest request) {
        return chatgptDemoService.chatCompletions(request);
    }
    @PostMapping("/v1/completions")
    public CompletionResponse completions(@Validated @RequestBody CompletionRequest request) {
        return chatgptDemoService.completions(request);
    }
    @PostMapping("/v1/edits")
    public EditResponse edits(@Validated @RequestBody EditRequest request) {
        return chatgptDemoService.edits(request);
    }
    @PostMapping("/v1/images/generations")
    public ImageGenerationResponse imageGenerations(@Validated @RequestBody ImageGenerationRequest request) {
        return chatgptDemoService.imageGenerations(request);
    }
}

在这里,我们使用的接口路径与OpenAI的API保持一致,以便于理解和使用。接下来,基于封装好的框架,我们通过几个常见的例子来实际调用API。例如,我们将自然语言转换成程序代码:利用API编写“hello world”程序。请求参数如下:

1
2
3
4
5
6
7
POST http://localhost:8080/v1/chat/completions
Content-Type: application/json

{
    "apiKey": "sk-xxxxxx",
    "content": "Please output helloworld in Java"
}

在这里我们本地启动Springboot项目,传入 apiKey(填入在OpenAI官网上申请的Open_API_KEY,均为sk前缀开头)。content字段则敲入自然语言表达我们的意图。

返回结果如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 May 2023 00:42:59 GMT
Connection: close
{
  "content": "Here's the code to output \"Hello World\" in Java:\n\n```  
\npublic class HelloWorld {\n  public static void main(String[] args) {\n    System.out.println(\"Hello World\");\n  }\n}\n  
```"
}

```  
## 生成SQL语句
SQL是开发过程中不可或缺的一部分,我们可以通过API来辅助编写SQL语句。下面是一个简单的示例:在学生表中查询所有学生的姓名。
### 请求参数
以下是请求参数的详细说明:

- **表名**:学生表

- **查询字段**:姓名
### SQL语句示例
根据上述请求参数,我们可以生成如下的SQL查询语句:
```sql
SELECT 姓名 FROM 学生表;
```
这个SQL语句的作用是从学生表中选择所有学生的姓名字段。  
```xml
POST http://localhost:8080/v1/chat/completions
Content-Type: application/json

{
    "apiKey": "sk-xxxxxx",
    "content": "Please select all students' name from Student table in SQL"
}

```  


返回结果如下:

  
```xml
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 May 2023 00:50:11 GMT
Connection: close
{
  "content": "SELECT name FROM Student;"
}

```  


1. 查找图片

我们还可以通过描述查询对应的图片,一般描述越精确,图片准确度越高。你可以看一下这个示例。

请求参数:

  
```xml
POST http://localhost:8080/v1/images/generations
Content-Type: application/json

{
    "apiKey": "sk-xxxxxx",
    "prompt": "find a tiger image",
    "n": 1
}

```  


返回参数如下:

  
```xml
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 May 2023 04:12:48 GMT
Connection: close
{
  "urls": [
    "https://oaidalleapiprodscus.blob.core.windows.net/private/org-mnyBsdtqxGUtwxCfi4SnEVIR/user-TapQIQ3nCgz483OGGnKll1N3/img-szYL9tqKuKPKZ00ywwofigLY.png?st=2023-05-02T03%3A12%3A48Z&se=2023-05-02T05%3A12%3A48Z&sp=r&sv=2021-08-06&sr=b&rscd=inline&rsct=image/png&skoid=6aaadede-4fb3-4698-a8f6-684d7786b067&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2023-05-01T17%3A37%3A04Z&ske=2023-05-02T17%3A37%3A04Z&sks=b&skv=2021-08-06&sig=qnREx8BFjeikttJyA71Qp4WrXT3RuvRHhzU1xUr1Le8%3D"
  ]
}

```  
## 图片搜索功能说明
可以通过特定的API接口来获取与请求参数中语义尽可能一致的图片URL数组。返回的图片URL数量将根据请求参数`n`的值来确定。
### 拼写检查功能
拼写错误是文本编辑中常见的问题,通常难以被发现。为此,我们提供了一个拼写检查接口来帮助用户识别并修正这些错误。
#### 请求参数
在使用拼写检查接口时,请确保提供正确的请求参数。具体的参数详情请参考相关文档。

aaaaaaa以上是对图片搜索和拼写检查功能的简要介绍。  
```xml
POST http://8.218.233.184:8080/v1/edits
Content-Type: application/json

{
    "apiKey": "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",
    "input": "It is an rainn day",
    "instruction": "Fix the spell mistakes"
}

```  


返回参数如下:

  
```xml
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 May 2023 05:25:38 GMT
Connection: close
{
  "text": "It is a rainy day\n"
}

```  
# 冒泡排序算法实现
这是一个简单的冒泡排序算法实现。为了解析方便,我们使用了很多换行符来将多行代码压缩到一行。以下是代码及其注释:
```python
# 定义冒泡排序函数
def bubble_sort(arr):
    # 获取数组长度
    n = len(arr)
    # 遍历所有数组元素
    for i in range(n):
        # 最后i个元素已经是排好序的了,不需要再比较
        for j in range(0, n-i-1):
            # 遍历数组从0到n-i-1
            # 交换如果发现元素e[j]比e[j+1]大,则交换之
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr
# 测试冒泡排序函数
arr = [64, 34, 25, 12, 22, 11, 90]
sorted_arr = bubble_sort(arr)
print("Sorted array is: ", sorted_arr)
```
请求参数:

- `arr`: 待排序的数组。  
```xml
POST http://localhost:8080/v1/edits
Content-Type: application/json

{
    "apiKey": "sk-xxxxx",
    "input": "public static void sort(int[] arrays) { \nif (arrays.length == 0) { \nreturn;  \n}  \nfor (int i = 0; i < arrays.length; i++) {  \nfor (int j = 0; j < i; j++) { \nif (arrays[j] > arrays[j + 1]) { \n  int temp = arrays[j];       \narrays[j] = arrays[j + 1];       \narrays[j + 1] = temp;\n}\n}\n}\n}",
    "instruction": "Explain this Java code"
}

```  


返回参数如下:

  
```xml
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 May 2023 23:45:37 GMT
Connection: close
{
  "text": "/** Java\nI discovered this code from a tutorial from edx from Havard but the idea is based of \ntheese steps:\n1) Complete these steps in the *sort* method:\n* Compare the first two elements of the array\n* If elem 1 is greater than elem 2, swap them\n* Repeat this step until all pairs are sorted\n* Repeat this step while traversing the array\n\n2) Complete these steps in the *sort2* method:\n* Create the two arrays needed (one with the first half the size of the original array, one with the \nsecond half of the array)\n* Use a for loop to find the first half of the array\n* Use another for loop to find the second half of the array\n\n3) Complete the rest of the *mergeSortedArrays* method\n* Merge the arrays back into a single sorted array\n*/\n\n// Try recreating it without looking at the code\n\npublic static void sort(int[] arrays) { \nif (arrays.length == 0) { \nreturn; \n}\nfor (int i = 0; i < arrays.length; i++) { \n    for (int j = 0; j < i; j++) {\n        if (arrays[j] > arrays[j + 1]) {\n        int temp = arrays[j];      \n        arrays[j] = arrays[j + 1];       \n        arrays[j + 1] = temp;\n       }\n    }\n }\n}\n}\n\n/**\nThis algorithm can also sort lists but to use list you have to type this code at the top\npublic static void sort(List<Integer> list) {\t\nThis is how array list works: \nFirst is the value of the array and the array name which is list, in the similiar fashion\nof calling a array and giving it a value.\n\npublic static void main(String[] args) {\n    List<Integer> list = new ArrayList<>();\n    list.add(10);\n    list.add(5);\n    list.add(1);\n    list.add(12);\n    list.add(6);\t\nSo you call a add function from ArrayList and set the number to the array list,\nalthough this is not setting the values it is just an example.\n\nint[] arrays = new int[]{10, 5, 1, 12, 6};\nsort(arrays);\nfor (int elem:arrays) {\n    System.out.print(elem + \" \");\n}  \nThis code is basically traversing through the array to print the output and to add the sort function\nand it prints out this output: 1 5 6 10 12 (To show that it is sorted)\n\nThe intarray code is similiar but it defines the construtor of the array and gives it a \nvalue like this: new int []{10, 5, 1, 12, 6}\n\nThe sort function is is sorted algorithm which is just one function of the sort method.\nHowever, to get this work without the arrays you have to call a public static void\nsort method but with a list instead or you varible name for the array.\nExample:      \npublic static void sort(List<Integer> varible) {\n\nCreated a mergeSortedArrays\n\nif (firstArray.length == 0 || secondArray.length == 0'd) {\n    return;  \n    }  \n\nThis makes sure that nothing is printed if the first array length or second array\nlength is empty.\n\nint[] mergedArray = new int[firstArray.length + secondArray.length];\nint firstArrayPointer = 0;\nint secondArrayPointer = 0;\t\nAs said above, we stick values to the array to merge into a storeage usage. The first part\nis the array name which is mergedArray and the second is the value. The plus method is used to \nadd variables and make them a whole array.\n\nfor (int mergedArrayPointer = 0; mergedArrayPointer < firstArray.length \n                            + secondArray.length; mergedArrayPointer++) {\n\tThis code is saying is that if the count of the array pointer is going to be smaller that\n\tthe leangth of the firstArray and secondArray then the array pointer is going to count \n\tand only going to contine to one not adding any more to the count.\n\tsecondArrayPointer++ means adding one more to the count and on so forth. \n\t\n\tmergedArray[mergedArrayPointer] = (firstArray[firstArrayPointer] <= \n                       secondArray[secondArrayPointer])?firstArray[firstArrayPointer\n                                      ]:secondArray[secondArrayPointer];\t\nIf the value of firstArray is greater than secondArrayPointer OR equal to then it is going to\nmerge to the mergedArray so we got an array sorting inside another array. \n */\n"
}

```  
# 课程总结
在这节课中,我们深入探讨了OpenAI API的强大功能,包括内容生成、摘要、分类及语义分析、翻译等。以下是本节课的核心内容和收获。
## OpenAI API的基础能力

- **内容生成**:利用API生成各种文本内容。

- **摘要**:自动提取文本的核心要点。

- **分类及语义分析**:对文本进行分类和深入分析。

- **翻译**:实现不同语言之间的文本转换。
## 实际应用

- **编程助手**:通过API辅助编写代码、生成SQL语句、查找图片、检查拼写等。

- **工作效率提升**:自动化繁琐任务,提高编程效率。

- **低代码平台**:构建基于API的低代码平台和工具集。

- **业务领域模型训练**:训练特定业务领域的大模型以适应不同需求。
## 拥抱变化

- 将GPT视为编程助手,提高工作效率。

- 编写标准程序单元、测试用例、生成注释说明。

- 利用API构建低代码平台和工具集,进一步训练特定业务领域的大模型。
## 结语

- 引用软件大师Alan Kay的话:"The best way to predict the future is to invent it."

- 鼓励大家积极参与到这个变化中,共同推动新时代的到来。
## 互动邀请

- 如果你觉得这节课的内容对你有帮助,欢迎分享给朋友。

- 同时,也欢迎你在评论区分享你的感悟和思考,与我一起讨论。