保姆级JAVA对接ChatGPT教程 使用 openai-gpt3-java

news2024/11/21 20:40:51

1. 前言

必须要有chatGTP 账号,如果需要测试账号可以关注公众号 疯狂的野猿 如果有chatGTP 账号就直接往下看。还需要一台外网服务器使用 nginx 代理来访问chatGTP 如果都没有,可以关注公众号联系作者。 还有笔者已经对接完成了,需要源码的关注公众号获取

2. 申请 API-Key的获取

2.1 获取Api-key

点击此链接获取 API-KEYS https://platform.openai.com/account/api-keys

1.点击图中 view API key
在这里插入图片描述
2. 点击 Create new secret key 创建新的key 将key 一定要复制出来,后期代码中需要。
点击 Create new secret key 创建新的key

2.创建一个 springboot 项目

2.1 导入chatGPT 依赖

国外友人已经对chatGPT 已经封装好,所以直接拿过来改造使用。

        <dependency>
            <groupId>com.theokanning.openai-gpt3-java</groupId>
            <artifactId>api</artifactId>
            <version>0.12.0</version>
        </dependency>
        <dependency>
            <groupId>com.theokanning.openai-gpt3-java</groupId>
            <artifactId>client</artifactId>
            <version>0.12.0</version>
        </dependency>
        <dependency>
            <groupId>com.theokanning.openai-gpt3-java</groupId>
            <artifactId>service</artifactId>
            <version>0.12.0</version>
        </dependency>

2.2 导入成功之后修改 openai-gpt3-java 让接口可以访问chatGPT

2.2.1 重写 OpenAiService

因为OpenAiService 中 BASE_URL 是写死的,咋们需要代理,所有重写他。重写完成之后就可以正常调用了。

package com.github.binarywang.demo.wx.mp.service;

import com.theokanning.openai.OpenAiApi;
import com.theokanning.openai.service.AuthenticationInterceptor;
import com.theokanning.openai.service.OpenAiService;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

/**
 * @ClassName MyOpenAiService
 * @Description TODO
 * @Author
 * @Date 2023/3/25 15:25
 * @Version 1.0
 */
public class MyOpenAiService extends OpenAiService {

    private static String BASE_URL = "请求openAI的地址,nginx代理的地址";


    private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(1000L);
    private final OpenAiApi api;
    public MyOpenAiService(String token,String baseUrl) {
        this(token, DEFAULT_TIMEOUT,baseUrl);
    }

    public MyOpenAiService(String token, Duration timeout, String baseUrl) {
        this(buildApi(token, timeout,baseUrl));
    }
    public MyOpenAiService(OpenAiApi api) {
        super(api);
        this.api = api;
    }

    public static OpenAiApi buildApi(String token, Duration timeout, String baseUrl) {
        BASE_URL = baseUrl;
        ObjectMapper mapper = defaultObjectMapper();
        OkHttpClient client = defaultClient(token, timeout);
        Retrofit retrofit = defaultRetrofit(client, mapper);
        return (OpenAiApi)retrofit.create(OpenAiApi.class);
    }

    public static OkHttpClient defaultClient(String token, Duration timeout) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        builder.addInterceptor(new MyAuthenticationInterceptor(token))
                .connectionPool(new ConnectionPool(5, 1L, TimeUnit.SECONDS))
                .readTimeout(timeout.toMillis(), TimeUnit.MILLISECONDS);

//        builder.addInterceptor(new HttpLogInterceptor());

        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        });
        OkHttpClient build = builder.build();
        return build;
    }

    public static Retrofit defaultRetrofit(OkHttpClient client, ObjectMapper mapper) {
        return (new retrofit2.Retrofit.Builder()).baseUrl(BASE_URL)
                .client(client).addConverterFactory(JacksonConverterFactory.create(mapper))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
    }
}

2.2.2 调用 MyOpenAiService

因为作者是和微信公众号打通所以 传了appid 如果正常使用无需传值。

package com.github.binarywang.demo.wx.mp.service.impl;

import com.github.binarywang.demo.wx.mp.service.MyOpenAiService;
import com.github.binarywang.demo.wx.mp.service.OpenAiServiceInterface;
import com.theokanning.openai.completion.CompletionRequest;
import com.theokanning.openai.completion.CompletionResult;
import com.theokanning.openai.completion.chat.*;
import com.theokanning.openai.edit.EditChoice;
import com.theokanning.openai.edit.EditRequest;
import com.theokanning.openai.edit.EditResult;
import com.theokanning.openai.model.Model;
import com.theokanning.openai.service.OpenAiService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @ClassName OpenAiService
 * @Description TODO
 * @Author
 * @Date 2023/3/22 21:46
 * @Version 1.0
 */
@Service
public class OpenAiServiceImpl implements OpenAiServiceInterface {

    private OpenAiService openAiService = null;
    @Value("${openAi.OPENAI_TOKEN}")
    private String OPENAI_TOKEN = "申请的openAI 的key ";
    @Value("${openAi.BASE_URL}")
    private String BASE_URL = "请求openAI的地址,nginx代理的地址";


    List<ChatMessage> messages = new ArrayList<>();

    @Override
    public String buildChat(String appid,String content) throws NoSuchFieldException, IllegalAccessException {

        if(Objects.isNull(openAiService)) {
            openAiService = new MyOpenAiService(OPENAI_TOKEN,BASE_URL);
        }
        ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), content);
        messages.add(chatMessage);

        ChatCompletionRequest completionRequest = ChatCompletionRequest.builder()
                .model("gpt-3.5-turbo")
                .messages(messages)
                .user(ChatMessageRole.USER.value())
                .n(3)
                .build();


        ChatCompletionResult chatCompletion = openAiService.createChatCompletion(completionRequest);
        List<ChatCompletionChoice> choiceList = chatCompletion.getChoices();
        if(CollectionUtils.isEmpty(choiceList)) {
            return null;
        }
        return choiceList.iterator().next().getMessage().getContent();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(电脑硬件)台式机主板音频端口功能详解

当你想给你的主机插上音响或者耳机时&#xff0c;你会发现主板上有6个接口&#xff0c;同样都是3.5mm接口&#xff0c;你知道该插哪个吗&#xff1f; 一般情况下&#xff0c;后置输入输出端口面板中&#xff0c;大多数的主板音频部分是彩色的。这一类颜色跟功能基本是固定的。当…

竟然支持在流程图、架构图中添加数学公式,安利一款纯免费的画图工具,真不错!

1. 简介 考虑到在绘图中需要添加数学表达式的场景&#xff0c;PDDON提供了LaTeX表达式编辑能力&#xff0c;可以在任何可以编辑的组件上启用LaTeX功能&#xff0c;使用LaTeX语法编写数学公式即可。 LaTeX表达式简介&#xff1a; LaTeX&#xff08;LATEX&#xff0c;音译“拉泰赫…

【偏门技巧】C语言编程实现对IPV4地址的合法性判断(使用正则表达式)

C语言编程实现对IPV4地址的合法性判断&#xff08;使用正则表达式&#xff09; 有了解过我的朋友&#xff0c;可能有点印象&#xff0c;我在N年前的博客中&#xff0c;就写了这个主题&#xff0c;当时确实是工作中遇到了这个问题。本想着等工作搞完之后&#xff0c;就把这个问题…

C++小知识点(for,nullptr)

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

Ubuntu用户与用户组相关操作

目录 一、用户与用户组信息查看 二、用户管理 1、user1 2、user2 3、设置密码与删除用户 三、用户组管理 四、用户的切换 一、用户与用户组信息查看 查看用户&#xff0c;首先调出终端窗口&#xff0c;&#xff08;“sudo cat /etc/passwd”&#xff09;&#xff0c;输…

Day 50 小结

50.1 比较分析各种查找算法 顺序查找&#xff1a;时间复杂度&#xff1a;O(n)&#xff1b;可用于有序或无序数据&#xff1b;按顺序查找元素。 折半查找&#xff1a;时间复杂度&#xff1a;O(logn)&#xff1b;只能用于有序数据&#xff1b;从中间元素开始查找&#xff0c;每…

Linux 内核启动流程与入口函数分析

从启动引导程序 bootloader&#xff08;uboot&#xff09;跳转到 Linux 内核后&#xff0c;Linux 内核开始启动&#xff0c;今天我们分析一下 Linux 内核启动入口。 跳转过去初始化肯定是在汇编文件中&#xff0c;根据架构可以选择不同的平台&#xff0c;这里看一下链接汇编文…

STM32 Simulink 自动代码生成电机控制——记录一次电机初始位置检测及NS极的判断实验

目录 前言 基本原理 仿真实现 代码生成及开发板验证 前言 之前做了脉振高频注入的仿真到代码生成开发板运行的实验&#xff0c;电机可以通过高频注入计算出角度&#xff0c;但是在初始位置检测的时候&#xff0c;尝试了不少方法但是效果一般&#xff0c;很容易反转&#xff…

服务器模型 setsockopt 网络超时检测 广播组播和unix域套接字 5.23

四.服务器模型 1.循环服务器 TCP服务器 TCP服务器端运行后等待客户端的连接请求。 TCP服务器接受一个客户端的连接后开始处理&#xff0c;完成了客户的所有请求后断开连接。 TCP循环服务器一次只能处理一个客户端的请求。 只有在当前客户的所有请求都完成后&#xff0c;服务…

Lucene(6):分词器

1 分词理解 在对Document中的内容进行索引之前&#xff0c;需要使用分词器进行分词 &#xff0c;分词的目的是为了搜索。分词的主要过程就是先分词后过滤。 分词&#xff1a;采集到的数据会存储到document对象的Field域中&#xff0c;分词就是将Document中Field的value值切分…

netty学习第一课

技术主题 Netty是一个基于Java NIO&#xff08;非阻塞 I/O&#xff09;框架的网络编程框架。它提供了一系列的高级网络编程API&#xff0c;使得开发者可以非常容易地实现高性能、高可靠性的网络应用。Netty具有非常好的可扩展性和灵活性&#xff0c;能够很好地支持多种协议和数…

Fiddler抓包工具之fiddler的介绍及安装

Fiddler简介 Fiddler是比较好用的web代理调试工具之一&#xff0c;它能记录并检查所有客户端与服务端的HTTP/HTTPS请求&#xff0c;能够设置断点&#xff0c;篡改及伪造Request/Response的数据&#xff0c;修改hosts&#xff0c;限制网速&#xff0c;http请求性能统计&#xff…

从零实现一个数据库(DataBase) Go语言实现版 7.空闲列表: 重用页

英文源地址 由于我们的B树时不可变的, 每次对kv存储的更新都会在路径上创建新节点, 而不是更新当前节点, 从而使一些节点无法从最新版本访问到.我们需要从旧版本中重用这些不可访问的节点, 否则, 数据库文件将无限增长. 设计空闲列表 为了重用这些页, 我们将添加一个持久化存…

python处理字符串、文本实例及注释

1、多个界定符切割字符串 代码 line = asdf fjdk; afed, fjek,asdf, foo import re re.split(r[;,\s]\s*, line) 结果 在上面的例子中,分隔符可以是逗号,分号或者是空格,并且后面紧跟着任意个的空格。只要这个模式被找到,那么匹配的分隔符两边的实体都会被当成是结果中…

面了个20k的自动化测试,从腾讯出来的果然都有两把刷子···

现在找个会自动化测试的人真是难呀&#xff0c;10个里面有8个写了会自动化&#xff0c;但一问就是三不知 公司前段时间缺人&#xff0c;也面了不少测试&#xff0c;前面一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在15-20k&#xff0c;面试的…

技巧:如何查看github的热门趋势和star排行

目录 1. 查看github的热门趋势2. 查看github的star排行3. 如何查看项目star增长曲线 1. 查看github的热门趋势 手动找到入口&#xff0c;打开github&#xff0c;登录后&#xff0c;找到Explore并点击进入&#xff0c;找到Trending切换&#xff0c;列出的就是github当天所有语言…

目标检测常用模型之R-CNN、Fast R-CNN、Faster R-CNN

文章目录 一、模型分类1. 一阶段目标检测2. 二阶段目标检测 二、常见模型1. R-CNN2. Fast R-CNN3. Faster R-CNN 一、模型分类 2012年卷积神经网络(Convolutional Neural Networks, CNNs)的兴起将目标检测领域推向了新的台阶。基于CNNs的目标检测算法主要有两条技术发展路线&am…

国外顶尖高校、企业分享人工智能自学课程英文原课程分享

人工智能无疑已经是当下最火热的方向&#xff0c;在很多领域已经融入我们生活&#xff0c;ChatGPT,Midjourney只是其中一个细分热点。目前这个领域&#xff0c;虽说国内也有不少课程&#xff0c;但是大部分源头还得从英文资料中找。如何学到最新最强得人工智能技能&#xff0c;…

Mongodb——快速入门,2个小时足够了

目录 1、Mongodb概述 1.1、为何使用Mongodb&#xff1f; 1.2、业务应用场景 1.3、Mongodb和MySQL的区别 2、Mongodb安装 2.1、Windows系统中安装启动 3、Mongodb的操作 3.1、数据库操作 3.2、集合操作 3.2.1、集合显式创建 3.2.2、集合的隐式创建 3.2.3集合的删除 …

k8s进阶3——资源配额、资源限制

文章目录 一、基本了解1.1 资源计算1.2 调度机制1.3 服务质量等级 二、资源配额 ResourceQuota2.1 支持的限制资源2.2 配额作用域2.3 资源配额选型2.3.1 计算资源配额2.3.2 存储资源配额2.3.3 对象数量配额 三、资源限制 LimitRange3.1 限制资源大小值3.2 设置限制默认值3.3 限…