十分钟编码实战springboot对接ChatGPT

Java后端

        pom.xml添加ChatGPT的依赖

<dependency><groupId>com.unfbx</groupId><artifactId>chatgpt-java</artifactId><version>1.0.10</version><!--排除子依赖 slf4j-simple 不然会有冲突 --><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId></exclusion></exclusions>
</dependency>

SpringBootApplication启动文件配置

@SpringBootApplication
public class NotesApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(NotesApplication.class, args);}@Overridepublic void run(String... args) throws Exception {}@Value("${chatgpt.apiKey}")private List<String> apiKey;@Value("${chatgpt.apiHost}")private String apiHost;@Beanpublic OpenAiStreamClientSub openAiStreamClient() {//本地开发调试条件: 1. 配置科学上网   2.配置IP代理Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 17890));HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger());//!!!!!!测试或者发布到服务器千万不要配置Level == BODY!!!!httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);OkHttpClient okHttpClient = new OkHttpClient.Builder().proxy(proxy).addInterceptor(httpLoggingInterceptor).connectTimeout(30, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).readTimeout(600, TimeUnit.SECONDS).build();System.out.println("使用的key:" + apiKey);return OpenAiStreamClientSub.builder().apiHost(apiHost).apiKey(apiKey)//自定义key使用策略 默认随机策略.keyStrategy(new KeyRandomStrategy()).okHttpClient(okHttpClient).build();}
}

注意本地开发配置条件:.配置IP代理   很关键,缺一不可

控制器Controller

/*** AI助手端 SSE 服务端 推送 客户端* @param headers*/@RequestMapping("/v1/chat/completions")@CrossOriginpublic SseEmitter sseCompletions(@RequestHeader Map<String, String> headers)  {String uuid = headers.get("uuid");//解码 内容部分String promptContent = headers.get("promptcontent");String content = null;try {content = URLDecoder.decode(promptContent, "utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}log.info("content:{}", content);//默认30秒超时,设置为0L则永不超时SseEmitter sseEmitter = new SseEmitter(0L);long startTime = System.currentTimeMillis();customChatGpt.sseCompletions(sseEmitter, uuid,  content);long endTime = System.currentTimeMillis();log.info("请求耗时:{} ms", (endTime-startTime)/1000);return sseEmitter;
}
  1. 需要配置 @CrossOrigin 注解: 全称"跨域资源共享"(Cross-origin resource sharing)

解决跨域问题,实现CORS的关键在于服务器,只要服务器实现CORS接口,就可以实现跨域通信

返回值为SseEmitter ,此处采用SSE推送技术实现,SseEmitter简介:SpringMVC提供的一种技术,可以实现服务端向客户端实时推送数据的功能,用法在Contorller中提供一个接口,返回SseEmitter对象,发送数据可以在另一个接口调用其send方法发送数据,SpringBoot已经集成这个功能因此直接使用

生成ChatGPT喜欢的聊天列表,用于ChatGPT更好的理解与用户聊天的上下文

 public void sseCompletions(SseEmitter sseEmitter, String uuid, String question) {String key = String.format(messagesKey, uuid);List<Message> messages = redisCache.getCacheObject(key);if (StringUtils.isNotNull(messages)) {if (messages.size() >= 5) {messages = messages.subList(1, 5);}Message currentMessage = Message.builder().content(question).role(Message.Role.USER).build();messages.add(currentMessage);} else {messages = new ArrayList<>();Message currentMessage = Message.builder().content(question).role(Message.Role.USER).build();messages.add(currentMessage);}OpenAISSEEventSourceListener eventSourceListener = new OpenAISSEEventSourceListener(sseEmitter);openAiStreamClientSub.streamChatCompletion(messages, eventSourceListener);redisCache.setCacheObject(key, messages, 50, TimeUnit.MINUTES );
}1.3 重载 EventSourceListener 监听器 重写 onEvent 回调接口
@SneakyThrows@Overridepublic void onEvent(EventSource eventSource, String id, String type, String data) {log.info("OpenAI返回数据:{}", data);if (data.equals("[DONE]")) {log.info("OpenAI返回数据结束了");sseEmitter.send(SseEmitter.event().id("[DONE]").data("[DONE]").reconnectTime(3000));return;}ObjectMapper mapper = new ObjectMapper();// 读取JsonChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class);sseEmitter.send(SseEmitter.event().id(completionResponse.getId()).data(completionResponse.getChoices().get(0).getDelta()).reconnectTime(3000));}

 构造http请求 v1/chat/completions 接口,发起对话

public void streamChatCompletion(ChatCompletion chatCompletion, EventSourceListener eventSourceListener) {if (Objects.isNull(eventSourceListener)) {log.error("参数异常:EventSourceListener不能为空,可以参考:com.unfbx.chatgpt.sse.ConsoleEventSourceListener");throw new BaseException(CommonError.PARAM_ERROR);} else {if (!chatCompletion.isStream()) {chatCompletion.setStream(true);}try {EventSource.Factory factory = EventSources.createFactory(this.okHttpClient);ObjectMapper mapper = new ObjectMapper();String requestBody = mapper.writeValueAsString(chatCompletion);Request request = (new okhttp3.Request.Builder()).url(this.apiHost + "v1/chat/completions").post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody)).build();factory.newEventSource(request, eventSourceListener);} catch (JsonProcessingException var8) {log.error("请求参数解析异常:{}", var8);var8.printStackTrace();} catch (Exception var9) {log.error("请求参数解析异常:{}", var9);var9.printStackTrace();}}}

等待ChatGPT流式回答,效果如下

H5前端

下载依赖: npm  install event-source-polyfill

创建SSE连接

createSSE(item){let that = thisconst itemAss = {type: 'chat',content: '回答中...',my: false,loading: true,};that.messages.push(itemAss)that.disableInput()that.setScroll()if(window.EventSource){this.eventSource = new EventSourcePolyfill(//${config.baseUrl}/sse/openApi/chatGPT/v1/chat/sseCompletions`http://localhost:7091/openApi/chatGPT/v1/chat/completions`, {// 设置重连时间heartbeatTimeout: 60 * 60 * 1000,// 添加tokenheaders: {'Authorization': `Bearer `,'uuid': that.userName,'promptcontent': encodeURIComponent(item.content)},});this.eventSource.onopen = (e) => {console.log("已建立SSE连接~")}this.eventSource.onmessage = (e) => {//隐藏加载框// uni.hideLoading();let item = that.messages[that.messages.length - 1]console.log("消息入栈:", e.data)let result = e.data//数据流开始标记if(result === '{"role":"assistant"}'){item.content  = ''}//数据流结束标记if(result === '[DONE]'){uni.setStorageSync('isOpen', true)that.closeSSE()}//内容if(result.includes('content')){let jsonResult = JSON.parse(result)//内容进行拼接item.content += jsonResult.contentthat.setScroll()}}this.eventSource.onerror = (e) => {if (e.readyState == EventSource.CLOSED) {console.log("SSE连接关闭", JSON.stringify(this.eventSource))} else if (this.eventSource.readyState == EventSource.CONNECTING) {console.log("SSE正在重连", JSON.stringify(this.eventSource))} else {console.log('error', e);}};} else {console.log("你的浏览器不支持SSE~")}
},

问题及解决办法

配置本地代理

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅尝对接 ChatGPT 与 DDD 工程

1. SpringBoot DDD 工程 MVC 架构与 DDD 架构简单对比 MVC 架构&#xff1a;老项目将 controller、service、manager、dao、bean 按照系统模块分在一起&#xff0c;随着项目发展每个包中对象逐渐膨胀&#xff0c;导致维护困难、bug 难查DDD 架构&#xff1a;新项目按照功能模块…

ERD Online 4.1.0对接ChatGPT,实现AI建模、SQL自由

ERD Online 是全球第一个开源、免费在线数据建模、元数据管理平台。提供简单易用的元数据设计、关系图设计、SQL查询等功能&#xff0c;辅以版本、导入、导出、数据源、SQL解析、审计、团队协作等功能、方便我们快速、安全的管理数据库中的元数据。 4.1.0 ❝ :memo: fix(erd): …

为什么职场中35岁之后很难找到合适的工作?

(点击即可收听) 为什么职场中35岁之后很难找到合适的工作 无论是初入职场还是,职场多年的老司机,都听过一个35岁危机的一个话题 无论是企业还是一些招聘者,针对35,甚至就是30的人,充满了不是这样,就是那样的偏见的理由 每个公司都喜欢有激情,有想法,有干劲的年轻人,无论哪个公司…

毕业季到底是去大厂还是去小公司

(点击即可收听) 毕业季到底是去大厂还是去小公司 相信很多人在选择大小公司的时候,会比较痛苦,外面的人想进去,里面的人想出来&#xff0c;至于选择大厂还是小公司 这是因人而异的,不同的阶段都可以有不同的选择 进大厂不一定就是对的,进小公司也不一定就是错的,学习东西,增长经…

字节跳动发布自研 Web 构建工具 Rspack

作者 | Rspack Team Rspack 是由 ByteDance Web Infra 团队孵化的基于 Rust 语言开发的 Web 构建工具&#xff0c;拥有高性能、兼容 Webpack 生态、定制性强等多种优点&#xff0c;解决了我们在业务场景中遇到的非常多的问题&#xff0c;让很多开发者的体验有了质的提升。 仓…

Windows 在美国采用率迅速下跌,只剩 57%,已至历史最低点!

整理 | 苏宓 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 流水的操作系统&#xff0c;铁打的 Windows。不过&#xff0c;自 2018 年微软宣布分拆 Windows 部门拥抱 AI 之后&#xff0c;作为一项服务的 Windows&#xff0c;其王者地位还能持续多久&#xff0c;也…

微软 Bing 日活用户破 1 亿, 每日约 1/3 用户与 Bing Chat 交互

整理 | 朱珂欣 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 自 ChatGPT 横空出世以来&#xff0c;新一轮 AI 之战就似乎在无形中被燃起。 2 月 8 日&#xff0c;微软召开了一场闭门媒体发布会&#xff0c;推出了全新的、 由人工智能驱动的 Bing 搜索引擎和 Edg…

终于,GPT-4 将于下周问世!不仅能搞文字,还支持视频

整理 | 郑丽媛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 作为当前全球最火的生成式 AI&#xff0c;ChatGPT 仅用了 3 个月&#xff0c;就几乎搅动了整个科技圈&#xff0c;人们不断惊叹于 ChatGPT 的强大——但微软和 OpenAI 想要的&#xff0c;显然不至于此…

美团以 20.65 亿人民币收购光年之外

美团于香港联交所发布公告&#xff0c;称已完成光年之外境内外主体 100% 股权的收购&#xff0c;收购价约为 20.65 亿人民币 。 此前&#xff0c;光年之外联合创始人王慧文因身体原因&#xff0c;离岗就医及休养。美团在公告中对于并购的解释是&#xff0c;通过收购事项获得领先…

5000亿美元「flag」后,微软 CEO 暂缓员工加薪,现发帖感谢大家,员工:“发钱才实际!”...

整理 | 朱珂欣 出品 | CSDN程序人生&#xff08;ID&#xff1a;coder_life&#xff09; 打工人眼里&#xff0c;没有比「加薪」更能直击心巴&#xff01; 据 Business Insider 报道&#xff0c;本周四&#xff0c;微软 CEO Satya Nadella 为感谢员工在 2023 财年里做出的贡献…

Rust 商标政策引争议,开发者:请放弃这个糟糕的政策吧!

整理 | 王子彧 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 近日&#xff0c;拥有 Rust 和 Cargo 商标的 Rust 基金会正在起草制定一项新商标政策提案。因提案中包含禁止在 Rust 工具或用 Rust 编写的软件的名称、域名或子域名中使用 Rust&#xff0c;引起了争…

GPT-4 让 Python 程序实现自修复 Bug,国外小哥将工具命名为“金刚狼”,并开源!...

整理 | 屠敏 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 继开发者用 GPT-4 制造了一款“贾维斯”代码助手之后&#xff0c;另一位程序员小哥 BioBootloader 再次整活&#xff0c;他利用 Python 和 GPT-4 创建了一个名为 wolverine&#xff08;金刚狼&#xff…

继「丑闻」之后,再爆 Stability AI 高层大换血!网友:“莫非是人心涣散?”...

整理 | 朱珂欣 出品 | CSDN程序人生&#xff08;ID&#xff1a;coder_life&#xff09; Stability AI 被爆「丑闻」不足一月&#xff0c;近日「新瓜」又来了&#xff01; 据彭博社报道&#xff0c;两名高管从 Stability AI 离职&#xff0c;大名指向 —— 研究主管 David Ha…

AIGC行业周刊【2023-0709】【第六期】2023年世界人工智能大会大佬发言汇总

点击加入->【智子纪元-AIGC】技术交流群 一、大咖观点&#xff1a; 0709AI日报&#xff1a;2023年世界人工智能大会大佬发言汇总「5年内&#xff0c;人类程序员没了」&#xff0c;Stability AI老板大胆预测&#xff0c;一众大佬狂怼&#xff1a;大错特错&#xff0c;都懒得…

ChatGPT 给 Linux 工程师带来的革命

作者 | 宋宝华 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 近日&#xff0c;吴军老师写了一篇文章《 ChatGPT 不算新技术革命&#xff0c;带不来什么新机会》&#xff0c;笔者虽然是吴老师的忠实粉丝&#xff0c;吴老师的书几乎都读过&#xff0c;但是此文…

ChatGPT-5即将发布,上千名人士却紧急叫停

ChatGPT4还没有好好体验&#xff0c;比GPT4强大1000倍的ChatGPT5又即将发布&#xff01;届时将彻底改变人工智能领域&#xff0c;并改变我们现有的世界 【ChatGPT 5简介】 OpenAI计划在2023年12月发布其最新且最强大的人工智能模型——ChatGPT 5。该模型具备人工通用智能的能力…

【回答问题】ChatGPT上线了!请使用MATLAB语言写一个谷歌 LaMDA模型?

首先,需要安装 MATLAB 并将 LaMDA 模型的代码下载到本地。然后,可以使用以下步骤来使用 MATLAB 运行 LaMDA 模型: 将 LaMDA 模型的文件夹路径添加到 MATLAB 的搜索路径中,可以使用以下命令实现: 复制 addpath(genpath(/path/to/LaMDA));创建一个用于存储 LaMDA 模型的变…