作为目前全球最火的AI模型ChatGPT
,相信很多小伙伴和我一样,充满好奇心。根据官网所说,ChatGPT
不仅可以完成交互式聊天,可以自然的和人类进行对话,可以通过类比的方式理解和回应自然语言,也可以根据文本信息提取关键字,生成不同创意和格式的文本内容,也可以生成代码,脚本,音乐,视频和信件等。看到如此强大的GPT
,此时是否在考虑如何嵌入到自己的工程项目中,并发挥出其强大的数据处理能力和逻辑处理能力?下面这个Demo就是一个简单的java嵌入,供大家学习参考。
pom
依赖:现在有一些教程是通过HTTP
请求,将认证的一些信息封装在请求头中,然后通过HTTP
调用来完成逻辑与ChatGPT
交互,这种方式可行,但不是很好用,自己需要写一大推Http Client
端的代码。从OpenAI
官方发现,现在已经有封装好的部分SDK,可以直接拿来使用,具体如下:
<dependencies>
<dependency>
<groupId>com.theokanning.openai-gpt3-javagroupId>
<artifactId>apiartifactId>
<version>0.14.0version>
dependency>
<dependency>
<groupId>com.theokanning.openai-gpt3-javagroupId>
<artifactId>clientartifactId>
<version>0.14.0version>
dependency>
<dependency>
<groupId>com.theokanning.openai-gpt3-javagroupId>
<artifactId>serviceartifactId>
<version>0.14.0version>
dependency>
dependencies>
OpenAiService
:因为国内是无法直接访问OpenAi
的,所以即使你有ApiKey
,也需要通过"梯子"来实现proxy
。下面这段代码通过一个静态代码块来初始化一个OpenAiService
,然后根据OpenAiService
来创建一个调用模型,执行你想提问的问题:
protected static OpenAiService openAiService;
//这块可以根据配置文件配置,我直接提出来了
protected static final String enableProxy = "true";
protected static final String apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
static {
//因为我是读取的配置文件,为了简化,我直接写成成员变量,写死了
boolean enable = Boolean.parseBoolean(enableProxy);
if (!enable) {
openAiService = new OpenAiService(apiKey);
} else {
String proxyIp = "localhost";
int proxyPort = Integer.parseInt("7890");
ObjectMapper mapper = defaultObjectMapper();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyIp, proxyPort));
OkHttpClient client = defaultClient(apiKey, Duration.ofSeconds(30))
.newBuilder()
.proxy(proxy)
.build();
Retrofit retrofit = defaultRetrofit(client, mapper);
OpenAiApi api = retrofit.create(OpenAiApi.class);
openAiService = new OpenAiService(api);
}
}
这块我给模型定义了两个角色,一个角色是SYSTEM
,我给他赋能为一个"中餐厨师,需要根据我传入的菜名返回这道菜的主要食材列表",然后我又用了一个助手ASSISTANT
角色,来接收我的提问,我设置的最大返回token数是256
(这块需要注意的新申请的账号是有15刀的token
额度,当token
额度用完之后,是需要购买的。在GPT3.5
中提问和返回的token
价格是一样的,但在GPT4.0
以后,提问和返回的token
价格数是不一样的,这增加了很大的使用成本。还有一点,如果你返回的结果比较长,maxTokens
这个参数设置不够,那么返回的结果是不完整的)。
public static ChatMessage chat(String msg) {
List<ChatMessage> messages = new ArrayList<>();
ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "You are a Chinese chef, you need to return the list of main ingredients of this dish according to the name of the Chinese dish I requested");
messages.add(systemMessage);
ChatMessage firstMsg = new ChatMessage(ChatMessageRole.ASSISTANT.value(), msg);
messages.add(firstMsg);
ChatCompletionRequest request = ChatCompletionRequest
.builder()
.model("gpt-3.5-turbo")
.messages(messages)
.n(1)
.maxTokens(256)
.logitBias(new HashMap<>())
.build();
Flowable<ChatCompletionChunk> flowable = openAiService.streamChatCompletion(request);
ChatMessage chatMessage = openAiService.mapStreamToAccumulator(flowable)
.lastElement()
.blockingGet()
.getAccumulatedMessage();
return chatMessage;
}
通过控制台输入问题,我们可以向ChatGPT提问,以下这个例子成功实现了这样的功能:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("Query: ");
String nextLine = scanner.nextLine();
ChatMessage chat = chat(nextLine);
System.out.println(chat.getContent());
}
}
根据我提问的问题,成功返回了我想要的结果,但目前有一个问题,如何让每次提问返回的结果格式都能保持一致,这个我暂时还没有解决,目前正在研究中,后续有进展会持续跟新。
Query: 中餐 家常香干烧肉 主要食材取top5 只要菜名 json结构形式返回结果
"菜名": "家常香干烧肉",
"主要食材": ["猪肉", "香干", "姜蒜", "葱", "辣椒"]
Query: 中餐 鱼香肉丝 取主要菜名top5 json结构形式返回结果
{
"dish_name": "鱼香肉丝",
"main_ingredients": [
"猪肉",
"木耳",
"胡萝卜",
"香葱",
"辣椒"
]
}
Query: