Springboot接入OpenAi/Chat GPT的三种方式

2023-10-31

由于现在网上的相关教程并不多外加没有使用代理的demo,所以抛砖引玉,写了三种调用方式,分别是直接访问、非官方SDK访问、官方开源的SDK访问

准备工作

1、导入pom文件(2023.3.30最新版本)

		<dependency>
            <groupId>com.unfbx</groupId>
            <artifactId>chatgpt-java</artifactId>
            <version>1.0.8</version>
        </dependency>
        <dependency>
            <groupId>com.theokanning.openai-gpt3-java</groupId>
            <artifactId>service</artifactId>
            <version>0.11.1</version>
        </dependency>

2、入参
这里的TalkDto 还可以入参maxToken,用于返回最大量的数据,官方计算token大小的方式:中文1字=3token 英文4字=1token。例如: 哈 = 3;ha=1;哈ha=4;哈ha哈h=8
官方计算token地址:https://platform.openai.com/tokenizer

/**
 * @author panx
 * @date 2023/3/29 13:52
 */
public class TalkDto {
    @ApiModelProperty("内容")
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

正文

1、直接访问

  • 优点

    自定义且简便,具有高度的可玩性,所有openAi新增的入参都可以直接用。

  • 缺点

    过于硬核,官方文档为纯英文。已经有轮子了为什么还要自行造车轮呢?

  • 正文

由于我自行封装了请求方式,所以不展示代理怎么进行插入,主要展示Body层,这里是最简单的Body入参。

		Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("model", "gpt-3.5-turbo");
        bodyMap.put("max_tokens", "4096");
        {
            List<Map<String, String>> maps = new ArrayList<>();
            //        Map<String, String> systemMap = new HashMap<>();
            //        systemMap.put("role", "system");
            //        systemMap.put("content", "你是一个分析师");
            //        maps.add(systemMap);
            Map<String, String> contentMap = new HashMap<>();
            contentMap.put("role", "user");
            contentMap.put("content", talkDto.getContent());
            maps.add(contentMap);
            bodyMap.put("messages", maps);
        }
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Authorization", "Bearer 123456789");

出参可以参考官方文档(https://platform.openai.com/docs/api-reference/chat)或下面的TalkResultDto

2、使用com.unfbx.chatgpt-java

  • 项目地址

https://github.com/Grt1228/chatgpt-java

  • 优点

纯中文文档,网上的demo也很多,更新速度也快,针对中国玩家的使用更便捷。

  • 缺点

不支持别的类型的请求?粗略的找了一下没有找到。
有一些默认值无法去除,而不去除某一些值在长段入参中可能会报错,如果需要去除可能要等更新或自行去https://platform.openai.com/playground调试模型。

  • 正文
       
    @ApiOperation("非官方聊天api捏")
    @PostMapping("/talkByService")
    public ReTurnDto<String> talkByService(@RequestBody TalkDto talkDto) {
        //国内访问需要做代理,国外服务器不需要
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.111.111", 1080));
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().proxy(proxy)//自定义代理
                .addInterceptor(httpLoggingInterceptor)//自定义日志输出
                .addInterceptor(new OpenAiResponseInterceptor())//自定义返回值拦截
                .connectTimeout(10, TimeUnit.SECONDS)//自定义超时时间
                .writeTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .readTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .build();
        //构建客户端
        OpenAiClient openAiClient = OpenAiClient.builder()//构建
                .apiKey(Collections.singletonList("1234577987645"))//token
                .okHttpClient(okHttpClient)//注入okhttp
                .build();
        Message message = Message.builder().role(Message.Role.USER).content(talkDto.getContent()).build();
        ChatCompletion.ChatCompletionBuilder builder = ChatCompletion.builder();
        //聊天模型:gpt-3.5
        builder.model("gpt-3.5-turbo");
        builder.messages(Arrays.asList(message));
        ChatCompletion chatCompletion = builder.build();

        ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
        return new ReTurnDto<>(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
    }

3、使用com.theokanning.openai-gpt3-java.service

  • 项目地址

https://github.com/TheoKanning/openai-java

  • 优点

官方SDK。各种类型的请求都有单独的实体类,使用起来非常便捷。

  • 缺点

更新速度没有上面的快,官方文档不太清晰。由于使用了 Retrofit+OkHttp 中国玩家需要进行繁琐的配置才能使用。

  • 正文
    @ApiOperation("官方api聊天捏")
    @PostMapping("/talkByOpen")
    public ReTurnDto<String> talkByOpen(@RequestBody TalkDto talkDto) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

        //国内访问需要做代理,国外服务器不需要
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 1549));
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().proxy(proxy)//自定义代理
                .addInterceptor(new HttpLoggingInterceptor()).addInterceptor(httpLoggingInterceptor)//自定义日志输出
                .addInterceptor(new AuthOpenAiInterceptor("123456789000"))//token
                .connectTimeout(10, TimeUnit.SECONDS)//自定义超时时间
                .writeTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .readTimeout(3000, TimeUnit.SECONDS)//自定义超时时间
                .build();

        Retrofit retrofit = new Retrofit.Builder()//构建者
                .client(client).baseUrl("https://api.openai.com/")//url
                .addConverterFactory(JacksonConverterFactory.create(mapper))//jackson
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//
                .build();

        OpenAiApi api = retrofit.create(OpenAiApi.class);
        OpenAiService service = new OpenAiService(api);
        //text-davinci-003
       /* CompletionRequest completionRequest = CompletionRequest.builder()
                .prompt(talkDto.getContent())
                .model("text-davinci-003")
                .maxTokens(2060)
                .build();
        CompletionResult completion = service.createCompletion(completionRequest);
        return new ResponseVo<>(completion.getChoices().get(0).getText());*/
        //gpt-3.5-turbo
        ChatCompletionRequest chatCompletionRequest = new ChatCompletionRequest();
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setRole(ChatMessageRole.USER.value());
        chatMessage.setContent(talkDto.getContent());
        chatCompletionRequest.setModel("gpt-3.5-turbo");
        chatCompletionRequest.setMessages(Collections.singletonList(chatMessage));
        ChatCompletionResult chatCompletion = service.createChatCompletion(chatCompletionRequest);
        return new ReTurnDto<>(chatCompletion.getChoices().get(0).getMessage().getContent());
    }

后期工作

AuthOpenAiInterceptor 如下

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;

/**
 * @author panx
 * @date 2023/3/30 14:22
 */
public class AuthOpenAiInterceptor implements Interceptor {
    private final String token;

    public AuthOpenAiInterceptor(String token) {
        this.token = token;
    }

    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request().newBuilder().header("Authorization", "Bearer " + this.token).build();
        return chain.proceed(request);
    }

}

TalkResultDto 如下

/**
 * @author panx
 * @date 2023/3/29 14:35
 */
public class TalkResultDto {

    private String id;
    private String object;
    private Integer created;
    private String model;
    private UsageDto usage;
    private List<ChoicesDto> choices;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getObject() {
        return object;
    }

    public void setObject(String object) {
        this.object = object;
    }

    public Integer getCreated() {
        return created;
    }

    public void setCreated(Integer created) {
        this.created = created;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public UsageDto getUsage() {
        return usage;
    }

    public void setUsage(UsageDto usage) {
        this.usage = usage;
    }

    public List<ChoicesDto> getChoices() {
        return choices;
    }

    public void setChoices(List<ChoicesDto> choices) {
        this.choices = choices;
    }

    public static class UsageDto {
        private Integer prompt_tokens;
        private Integer completion_tokens;
        private Integer total_tokens;

        public Integer getPrompt_tokens() {
            return prompt_tokens;
        }

        public void setPrompt_tokens(Integer prompt_tokens) {
            this.prompt_tokens = prompt_tokens;
        }

        public Integer getCompletion_tokens() {
            return completion_tokens;
        }

        public void setCompletion_tokens(Integer completion_tokens) {
            this.completion_tokens = completion_tokens;
        }

        public Integer getTotal_tokens() {
            return total_tokens;
        }

        public void setTotal_tokens(Integer total_tokens) {
            this.total_tokens = total_tokens;
        }
    }

    public static class ChoicesDto {
        private MessageDto message;
        private String finish_reason;
        private Integer index;

        public MessageDto getMessage() {
            return message;
        }

        public void setMessage(MessageDto message) {
            this.message = message;
        }

        public String getFinish_reason() {
            return finish_reason;
        }

        public void setFinish_reason(String finish_reason) {
            this.finish_reason = finish_reason;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }

        public static class MessageDto {
            private String role;
            private String content;

            public String getRole() {
                return role;
            }

            public void setRole(String role) {
                this.role = role;
            }

            public String getContent() {
                return content;
            }

            public void setContent(String content) {
                this.content = content;
            }
        }
    }
}

如果没有代理的话,可以去购买一个香港的服务器,将服务部署在香港服务器中

畅爽使用~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot接入OpenAi/Chat GPT的三种方式 的相关文章

  • 如何在测试套件中定义 JUnit 方法规则?

    我有一个类 它是 JUnit 测试类的 JUnit 套件 我想定义一个规则on the suite 这是可以做到的 但需要做一些工作 您还需要定义自己的 Suite 运行程序和测试运行程序 然后在测试运行程序中重写 runChild 使用以
  • 是否可以在 Spring Batch 中结合分区和并行步骤?

    我只是想知道它在 Spring Batch 中可行吗 Step1Step2 流程 gt 流程1 流程2 流程3 Step3 其中每个flow1 gt 划分为 5 个 GridSizeflow2 gt 划分为 5 个 GridSizeflow
  • 任务“:app:dexDebug”执行失败

    我目前正在处理我的项目 我决定将我的 Android Studio 更新到新版本 但在我导入项目后 它显示如下错误 Information Gradle tasks app assembleDebug app preBuild UP TO
  • 用 @DataJpaTest 注释的测试不是用 @Autowired 注释的自动装配字段

    我有一个 Spring Boot 应用程序 其中包含 Spring Data Jpa 存储库 我需要围绕这个存储库运行单元 或组件 测试 我对 Spring Data Jpa 没有太多经验 这是我的测试 这很简单 我无法让它通过 impor
  • 将链接对象转换为流或集合

    我想迭代堆栈跟踪 堆栈跟踪由可抛出对象组成 其 getCause 返回下一个可抛出对象 最后一次调用 getCause 返回 null 示例 a gt b gt null 我尝试使用 Stream iterable 这会导致 NullPoi
  • 如何从另一个xml文件动态更新xml文件?

    我想从另一个 xml 文件更新 xml 文件 我使用了一个 xml 文件 如下所示 one xml
  • JTree 节点不会被直观地选择

    不知何故 我无法为我的 JTree 节点启用 选择突出显示 我正在我的项目中使用自定义单元格渲染器 这很可能导致此问题 这是完整的渲染器类代码 protected class ProfessionTreeCellRenderer exten
  • 无法加载 jar 文件的主类

    我使用 Eclipse IDE 开发了一个应用程序 创建应用程序后 我以 jar 格式导出项目 当我尝试运行此 jar 文件时 出现错误 无法加载主类 请帮忙 当您将项目导出为 jar 时 请参阅此所以问题 https stackoverf
  • PropertySources 中各种源的优先级

    Spring引入了新的注释 PropertySources对于所有标记为的类 Configuration since 4 0 需要不同的 PropertySource作为论证 PropertySources PropertySource c
  • 如何将 Spotlight for Help 插入本地化的 macOS 应用程序?

    我正在 macOS 上使用 Swing GUI 框架实现 Java 应用程序 当使用system外观和感觉以及screen菜单栏 Swing 自动插入一个搜索栏 called 聚光灯寻求帮助 https developer apple co
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • Java替换特定字符

    这是我在这个网站上的第一个问题 所以我会尽量不要成为一个十足的菜鸟 我目前正在用java 创建刽子手游戏 所以我问你的问题是我们是否被赋予了 幽灵 这个词 并将 Ghost 替换为 hiddenWord ghost length for i
  • cucumber-junit-platform-engine 中的功能文件发现

    In cucumber junit我使用的库 CucumberOptions定义功能文件位置 package com mycompany cucumber import cucumber api CucumberOptions import
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • Java:VM 如何在 32 位处理器上处理 64 位“long”

    JVM 如何在 32 位处理器上处理 64 位的原始 long 在多核 32 位机器上可以并行利用多个核心吗 64 位操作在 32 位机器上慢了多少 它可能使用多个核心来运行不同的线程 但不会并行使用它们进行 64 位计算 64 位长基本上
  • 参数动态时如何构建 JPQL 查询?

    我想知道是否有一个好的解决方案来构建基于过滤器的 JPQL 查询 我的查询太 富有表现力 我无法使用 Criteria 就像是 query Select from Ent if parameter null query WHERE fiel
  • 覆盖 MATLAB 默认静态 javaclasspath 的最佳方法

    MATLAB 配置为在搜索用户可修改的动态路径之前搜索其静态 java 类路径 不幸的是 静态路径包含相当多非常旧的公共库 因此如果您尝试使用新版本 您可能最终会加载错误的实现并出现错误 例如 静态路径包含 google collectio
  • jmap - 组织和堆操作会给 jvm 带来开销吗?

    正如标题所述 需要多少开销jmap histo and jmap heap分别带到jvm 如果一个内存敏感的 Java 进程处于OutOfMemory 例如 大约 96 的堆已满 并且无法通过 full gc 清除 其中一项操作是否有可能将
  • 从 Stax XMLStreamReader 读取以解组部分

    我正在使用 Stax 游标 API 从大型 xml 文件中提取数据 当前 我转到特殊标签的开头并使用 JAXB 解组该标签 这对于格式良好的 xml 文件效果很好 但不久前我有一个文档 其中数十万个标签中有一个未关闭 JAXB 使用 XML
  • 在 Selenium WebDriver 上如何从 Span 标签获取文本

    在 Selenium Webdriver 上 如何从 span 标记检索文本并打印 我需要提取文本UPS Overnight Free HTML代码如下 div id customSelect 3 class select wrapper

随机推荐

  • Oracle 性能最大化

    配置和优化有什么不同 获得最大的性能 配置操作系统 配置Oracle Oracle 性能 调整和配置数据库对象 优化Oracle 最大化 如果你问很多Oracle DBA 你工作中最大的一部分是什么 几乎所有的回答都是 数据库的配置和优化
  • google cartographer参数配置和话题转发

    为了对google cartographer进行实验仿真 安装完成后首先用官方rosbag进行实验没问题后再尝试用自己的rosbag文件 重要的参考资料 https google cartographer ros readthedocs i
  • win10安装TeXLive2019

    下载安装包 到TeX Live官网下载iso安装包 Acquiring TeX Live as an ISO image 点击上图中的链接 会根据网络选择合适的镜像 方便我们下载 我的镜像是上海交通大学的 http mirrors sjtu
  • Pytorch 图像增强 实现翻转裁剪色调等 附代码(全)

    目录 前言 1 裁剪 1 1 中心裁剪 1 2 随机裁剪 1 3 随机尺寸裁剪 2 翻转 2 1 水平翻转 2 2 垂直翻转 2 3 随机旋转 3 色调 3 1 灰度变换 3 2 色彩抖动 3 3 随机翻转颜色 3 4 随机调整锐度 3 5
  • 微信 支付和回调

    1 微信支付 兼容小程序 app h5等方式 RequestMapping value recharge getSign public JSONMessage getSign RequestParam int payType Request
  • Ubuntu 20.04虚拟机开机卡在 /dev/sda* clean ,针对AMD核显的解决办法

    问题描述如标题 此类问题存在的普遍解释是 1 存储空间不足 2 显卡驱动问题 因此在解决问题之前需要先判断自己的问题 首先重启 开机时按Esc建 进入Grub界面 选择第一个选项Ubuntu 之后选择Advanced options for
  • Java中的数据库连接--JDBC

    JDBC Java DataBase Connectivity 即Java数据库连接 就是使用Java语言操作数据库 JDBC的本质 官方定义的定义的一套操作所有关系型数据库的规则 即接口 这边使用MySQL数据库进行测试 1 快速入门 首
  • 非常有趣的的免费API接口,基本上很全了

    一 图灵聊天机器人 http doc tuling123 com openapi2 263611 二 百度地图开放平台 http lbsyun baidu com index php title webapi 三 Eolinker API
  • 【吐血整理】mysql密码正确但无法登陆

    一面 1 二叉搜索树和平衡二叉树有什么关系 强平衡二叉树 AVL 树 和弱平衡二叉树 2 B 树和 B 树的区别 为什么 MySQL 要使用 B 树 3 HashMap 如何解决 Hash 冲突 4 epoll 和 poll 的区别 及其应
  • C++ 语言的单元测试与代码覆盖率

    点击蓝字 关注我们 来源于网络 侵删 前言 测试是软件开发过程中一个必须的环节 测试确保软件的质量符合预期 对于工程师自己来说 单元测试也是提升自信心的一种方式 直接交付没有经过测试的代码是不太好的 因为这很可能会浪费整个团队的时间 在一些
  • Mysql 的安装与配置

    一 windows 服务器下的 mysql 1 安装软件安装 按软件提示一路确定下去 2 压缩包安装 1 解压安装包到自定义路径 2 修改 my ini 配置文件 复制解压好的文件路径 记事本打开 my ini 文件 将basedir 与
  • tie-aware的检索指标

    检索常用指标 P precision R recall F1 AP average precision RR reciprocal rank NDCG normalized discounted cumulative gain ACG av
  • 我对GPIO的的理解

    首先 要先说下GPIO和引脚的区别 整理下网上提出的问题和答案 GPIO的英文全称General Purpose Input Output Ports 中文意思是通用I O端口 在单片机上 单片机有很多管脚 PIN 除了一些特殊的PIN 比
  • 深入理解CAS算法原理

    转载自 深入理解CAS算法原理 https mp weixin qq com s biz MzI3ODcxMzQzMw mid 2247483728 idx 1 sn 3d734dc972a244891406cfbc443eabed chk
  • sugarcrm mysql_SugarCRM安装踩雷(一)

    安装SugarCRM前置条件 1 找对平台 正确版本的安装包 2 APACHE MYSQL TOMCAT环境先确保OK 坑1 进入安装参数设置步骤的MYSQL用户密码 这里根据Mysql的登陆用户名和密码来填写 如果不是单独安装的Mysql
  • 贝叶斯推断及其互联网应用(二):过滤垃圾邮件

    上一次 我介绍了贝叶斯推断的原理 今天讲如何将它用于垃圾邮件过滤 贝叶斯推断及其互联网应用 作者 阮一峰 接上文 七 什么是贝叶斯过滤器 垃圾邮件是一种令人头痛的顽症 困扰着所有的互联网用户 正确识别垃圾邮件的技术难度非常大 传统的垃圾邮件
  • Android 中使用Volley进行网络请求和图片加载详解

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 Volley概述 Volley既可以访问网络取得数据 也可以加载图片 并且在性能方面进行了大幅度的调整 它的设计目标就是适合进行数
  • TRIZ创新方法——技术矛盾机器解决原理

    TRIZ创新方法 技术矛盾及其解决原理 1 什么是矛盾 2 什么是技术矛盾 3 通用工程参数 4 矛盾矩阵 5 运用阿奇舒勒矛盾矩阵解决技术矛盾的步骤 6 案例分析 7 课后习题 技术矛盾的解决 发明原理的第一个应用 早期TRIZ重要内容之
  • Base Model

    1 Deep Residual Learning for Image Recognition 简介 残差网络ResNet是近年来最有效的base model之一 过去 叠加神经网络层数会导致网络退化 degradation 的问题 当层数达
  • Springboot接入OpenAi/Chat GPT的三种方式

    由于现在网上的相关教程并不多外加没有使用代理的demo 所以抛砖引玉 写了三种调用方式 分别是直接访问 非官方SDK访问 官方开源的SDK访问 准备工作 1 导入pom文件 2023 3 30最新版本