位置: IT常识 - 正文

国内前端vue对接OpenAI/chatgpt【文本互动/生成图片】(web前端开发 vue)

编辑:rootadmin
国内前端vue对接OpenAI/chatgpt【文本互动/生成图片】

推荐整理分享国内前端vue对接OpenAI/chatgpt【文本互动/生成图片】(web前端开发 vue),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:基于vue的前端架构设计,web前端开发 vue,前端 vue,前端 vue,vue前后端对接,vue前后端对接,vue前端和后端交互,前端 vue,内容如对您有帮助,希望把文章链接给更多的朋友!

 如图;国内通过调用openai接口进行互动,实现图文互动/文本互动

 注意:请求人数较多,需要等待

1、🔔 获取ApiKey

注册 OpenAI 账号,获取你的 ApiKey,过程略。

2、💬 聊天接口

⚠️ 不再推荐使用本接口,后面将废弃。

接口地址 (POST请求)

POST https://api.openai.com/pro/chat/completions

请求参数

参数名类型长度必须备注apiKeyString64是OpenAI 的 ApiKeysessionIdString64是会话ID,关联上下文,推荐使用UUID作为sessionIdcontentString1000是发送的内容

请求示例(Content-Type = application/json)

{    "apiKey": "<your_openai_api_key>",    "sessionId": "8d1cb9b0-d535-43a8-b738-4f61b1608579",    "content": "你是谁?"}国内前端vue对接OpenAI/chatgpt【文本互动/生成图片】(web前端开发 vue)

响应示例

{    "code": 200,    "message": "执行成功",    "data": "我是一名人工智能助手,用于协助回答问题和提供建议。您可以通过与我进行对话来获取您需要的信息或帮助。"}

本接口使用的是 gpt-3.5-turbo 模型,支持通过上下文内容进行连续对话。

本接口对官方的接口进行了封装,开发者只需为每个 ApiKey 下的每个会话分配一个独立的 sessionId 即可实现连续对话 。

推荐使用 uuid 作为 sessionId 以保证全局唯一 ,否则对话可能会“串线”。

对话中的上下文信息有效期为30分钟,过期后再次发送消息无法关联上下文。

# 测试聊天curl https://api.openai.com/v1/chat/completions \                 -H "Content-Type: application/json" \ -H "Authorization: Bearer <your_openai_api_key>" \ -d '{   "model": "gpt-3.5-turbo",   "messages": [{"role": "user", "content": "Hello!"}] }'  # 响应结果   { "id": "chatcmpl-21lvNzPaxlsQJh0BEIb9DqoO0pZUY", "object": "chat.completion", "created": 1680656905, "model": "gpt-3.5-turbo-0301", "usage": {   "prompt_tokens": 10,   "completion_tokens": 10,   "total_tokens": 20 }, "choices": [   {     "message": {       "role": "assistant",       "content": "Hello there! How can I assist you today?"     },     "finish_reason": "stop",     "index": 0   } ]}# 测试生成图片curl https://api.openai.com/v1/images/generations \ -H "Content-Type: application/json" \ -H "Authorization: Bearer <your_openai_api_key>" \ -d '{   "prompt": "A bikini girl",   "n": 2,   "size": "512x512" }'  # 响应结果 { "created": 1680705608, "data": [   {     "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-xxxxxxx"   },   {     "url": "https://oaidalleapiprodscus.blob.core.windows.net/private/org-xxxxxxx"   } ]}

OpenAI本身是没有记忆的,如果你不告诉他你之前说了什么以及他之前回答了什么,那么他只会根据你最近一次发送的内容进行回答。

所以,要想实现“连续对话”,每次发送消息时,你需要将你之前发送的内容(user)以及OpenAI之前返回的内容(assistant),再结合你本次想发送的内容(user) 按 时序 组合成一个 messages[] 数组,然后再将这个数组发送给OpenAI就行了,就是这么简单。

4 、⭐️ 第三方应用

如果你用的是第三方开发者开发的基于OpenAI 的应用可以参考以下:

名称Github地址StarsOpenAI-TranslatorGitHub - yetone/openai-translator: 基于 ChatGPT API 的划词翻译浏览器插件和跨平台桌面端应用 - Browser extension and cross-platform desktop application for translation based on ChatGPT API.ChatGPT-Next-WebGitHub - Yidadaa/ChatGPT-Next-Web: One-Click to deploy well-designed ChatGPT web UI on Vercel. 一键拥有你自己的 ChatGPT 网页服务。ChatGPT-Webhttps://github.com/Chanzhaoyu/chatgpt-web5、💰 查询余额

接口地址 (GET请求)

GET https://api.openai.com/pro/balance?apiKey=sk-xxxxxxxxxxxxxx

请求参数

参数名类型长度必须备注apiKeyString64是OpenAI 的 ApiKey

响应示例

{    "code": 200,    "message": "执行成功",    "data": {        "total": 18.00,        "balance": 17.92,        "used": 0.08   }}

原OpenAI官方后台查询余额的接口由于被用户滥用,官方给撤销了,现在提供一个折中的方式去计算账户余额。

逻辑是先得到OpenAI给你账户授权的总金额,然后减去最近100天你账户消耗的金额,得到的 balance 即为账户可用余额。

<template> <div class="chat-window"> <div class="top"> <div class="head-pic"> <HeadPortrait :imgUrl="frinedInfo.headImg"></HeadPortrait> </div> <div class="info-detail"> <div class="name">{{ frinedInfo.name }}</div> <div class="detail">{{ frinedInfo.detail }}</div> </div> <div class="other-fun"> <span class="iconfont icon-shipin" @click="video"> </span> <span class="iconfont icon-gf-telephone" @click="telephone"></span> <label for="docFile"> <span class="iconfont icon-wenjian"></span> </label> <label for="imgFile"> <span class="iconfont icon-tupian"></span> </label> <input type="file" name="" id="imgFile" @change="sendImg" accept="image/*" /> <input type="file" name="" id="docFile" @change="sendFile" accept="application/*,text/*" /> <!-- accept="application/*" --> </div> </div> <div class="botoom"> <div class="chat-content" ref="chatContent"> <div class="chat-wrapper" v-for="(item, index) in chatList" :key="item.id" > <!-- <div v-if="isSend && index == chatList.length - 1"> <div class="chat-friend" v-if="item.uid !== '1001'"> <div class="info-time"> <img :src="item.headImg" alt="" /> <span>{{ item.name }}</span> <span>{{ item.time }}</span> </div> <div class="chat-text" v-if="item.chatType == 0"> <span class="flash_cursor"></span> </div> </div> </div>--> <div class="chat-friend" v-if="item.uid !== '1001'"> <div class="info-time"> <img :src="item.headImg" alt="" /> <span>{{ item.name }}</span> <span>{{ item.time }}</span> </div> <div class="chat-text" v-if="item.chatType == 0&&item.type != 1"> <template v-if="isSend && index == chatList.length - 1"> <span class="flash_cursor">请稍后...</span> </template> <template v-else> <pre>{{ item.msg }}</pre> </template> </div> <div class="chat-img" v-if="item.chatType == 1"> <img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" /> <el-image :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image> </div> <div class="chat-img" v-if="item.type == 1"> <img v-for="(items,index) in item.images" :src="items" :key="index" alt="表情" style="width: 100px; height: 100px" /> </div> <div class="chat-img" v-if="item.chatType == 2"> <div class="word-file"> <FileCard :fileType="item.extend.fileType" :file="item.msg" ></FileCard> </div> </div> </div> <div class="chat-me" v-else> <div class="info-time"> <span>{{ item.name }}</span> <span>{{ item.time }}</span> <img :src="item.headImg" alt="" /> </div> <div class="chat-text" v-if="item.chatType == 0"> {{ item.msg }} </div> <div class="chat-img" v-if="item.chatType == 1"> <img :src="item.msg" alt="表情" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" /> <el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else > </el-image> </div> <div class="chat-img" v-if="item.chatType == 2"> <div class="word-file"> <FileCard :fileType="item.extend.fileType" :file="item.msg" ></FileCard> </div> </div> </div> </div> </div> <div class="chatInputs"> <!-- v-show="showEmoji" --> <!-- <div class="emoji boxinput" @click="clickEmoji"> <img src="@/assets/img/emoji/smiling-face.png" alt="" /> </div> --> <div class="emoji-content"> <Emoji @sendEmoji="sendEmoji" v-show="showEmoji" @closeEmoji="clickEmoji" ></Emoji> </div> <input class="inputs" v-model="inputMsg" @keyup.enter="sendText" /> <el-button class="send boxinput" :disabled="isSend" @click="sendText"> <img src="@/assets/img/emoji/rocket.png" alt="" /> </el-button> </div> </div> </div></template><script>import { animation } from "@/util/util";import { getChatMsg, chatgpt } from "@/api/getData";import HeadPortrait from "@/components/HeadPortrait";import Emoji from "@/components/Emoji";import FileCard from "@/components/FileCard.vue";export default { components: { HeadPortrait, Emoji, FileCard, }, props: { frinedInfo: Object, default() { return {}; }, }, watch: { frinedInfo() { this.getFriendChatMsg(); }, }, data() { return { chatList: [], inputMsg: "", showEmoji: false, friendInfo: {}, srcImgList: [], isSend: false, }; }, mounted() { this.getFriendChatMsg(); }, methods: { //获取聊天记录 getFriendChatMsg() { let params = { frinedId: this.frinedInfo.id, }; getChatMsg(params).then((res) => { console.error("333", res); this.chatList = res; // this.chatList.forEach((item) => { // if (item.chatType == 2 && item.extend.imgType == 2) { // this.srcImgList.push(item.msg); // } // }); this.scrollBottom(); }); }, //发送信息 sendMsg(msgList) { this.chatList.push(msgList); this.scrollBottom(); }, //获取窗口高度并滚动至最底层 scrollBottom() { this.$nextTick(() => { const scrollDom = this.$refs.chatContent; animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight); }); }, //关闭标签框 clickEmoji() { this.showEmoji = !this.showEmoji; }, //发送文字信息 sendText() { if (this.inputMsg) { let chatMsg = { headImg: require("@/assets/img/head_portrait.jpg"), name: "", time: new Date().toLocaleTimeString(), msg: this.inputMsg, chatType: 0, //信息类型,0文字,1图片 uid: "1001", //uid }; this.sendMsg(chatMsg); this.$emit("personCardSort", this.frinedInfo.id); this.inputMsg = ""; let data = { // prompt: chatMsg.msg, // temperature: 1, // top_p: 1, // // model: "text-davinci-003", // max_tokens: 2048, // frequency_penalty: 0, // "model": "gpt-3.5-turbo", // "messages": [{"role": "user", "content": "Hello!"}], // presence_penalty: 0, // stop: ["Human:", "AI:"], model: "gpt-3.5-turbo", messages: [{ role: "user", content: chatMsg.msg }], }; this.loading = true; this.isSend = true; let chatGPT = { headImg: require("@/assets/img/head_portrait1.jpg"), name: "小五", time: new Date().toLocaleTimeString(), msg: "", images: [], chatType: 0, //信息类型,0文字,1图片 uid: "1002", //uid }; this.sendMsg(chatGPT); chatgpt(data).then((res) => { this.isSend = false; if (res.data) { this.chatList[this.chatList.length - 1].images=[]; console.error("555", this.chatList); this.chatList[this.chatList.length - 1].type = 1; this.chatList[this.chatList.length - 1].images.push(res.data[0].url); } else { this.chatList[this.chatList.length - 1].msg = res.choices[0].message.content; } }); } else { this.$message({ message: "消息不能为空哦~", type: "warning", }); } }, //发送表情 sendEmoji(msg) { let chatMsg = { headImg: require("@/assets/img/head_portrait.jpg"), name: "大毛是小白", time: new Date().toLocaleTimeString(), msg: msg, chatType: 1, //信息类型,0文字,1图片 extend: { imgType: 1, //(1表情,2本地图片) }, uid: "1001", }; this.sendMsg(chatMsg); this.clickEmoji(); }, //发送本地图片 sendImg(e) { let _this = this; console.log(e.target.files); let chatMsg = { headImg: require("@/assets/img/head_portrait.jpg"), name: "大毛是小白", time: "09:12 AM", msg: "", chatType: 1, //信息类型,0文字,1图片, 2文件 extend: { imgType: 2, //(1表情,2本地图片) }, uid: "1001", }; let files = e.target.files[0]; //图片文件名 if (!e || !window.FileReader) return; // 看是否支持FileReader let reader = new FileReader(); reader.readAsDataURL(files); // 关键一步,在这里转换的 reader.onloadend = function () { chatMsg.msg = this.result; //赋值 _this.srcImgList.push(chatMsg.msg); }; this.sendMsg(chatMsg); e.target.files = null; }, //发送文件 sendFile(e) { let chatMsg = { headImg: require("@/assets/img/head_portrait.jpg"), name: "大毛是小白", time: "09:12 AM", msg: "", chatType: 2, //信息类型,0文字,1图片, 2文件 extend: { fileType: "", //(1word,2excel,3ppt,4pdf,5zpi, 6txt) }, uid: "1001", }; let files = e.target.files[0]; //图片文件名 chatMsg.msg = files; console.log(files); if (files) { switch (files.type) { case "application/msword": case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": chatMsg.extend.fileType = 1; break; case "application/vnd.ms-excel": case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": chatMsg.extend.fileType = 2; break; case "application/vnd.ms-powerpoint": case "application/vnd.openxmlformats-officedocument.presentationml.presentation": chatMsg.extend.fileType = 3; break; case "application/pdf": chatMsg.extend.fileType = 4; break; case "application/zip": case "application/x-zip-compressed": chatMsg.extend.fileType = 5; break; case "text/plain": chatMsg.extend.fileType = 6; break; default: chatMsg.extend.fileType = 0; } this.sendMsg(chatMsg); e.target.files = null; } }, // 发送语音 telephone() { this.$message("敬请期待一下吧~🥳"); }, //发送视频 video() { this.$message("敬请期待一下吧~🥳"); }, },};</script><style lang="scss" scoped>.flash_cursor { width: auto; height: 30px; display: inline-block; background: #d6e3f5; opacity: 1; animation: glow 800ms ease-out infinite alternate;}@keyframes glow { 0% { opacity: 1; } 25% { opacity: 0.5; } 50% { opacity: 0; } 75% { opacity: 0.5; } 100% { opacity: 1; }}.chat-window { width: 100%; height: 100%; margin: 0 auto; position: relative; .top { margin-bottom: 20px; &::after { content: ""; display: block; clear: both; } .head-pic { float: left; } .info-detail { float: left; margin: 5px 20px 0; .name { font-size: 20px; font-weight: 600; color: #fff; } .detail { color: #9e9e9e; font-size: 12px; margin-top: 2px; } } .other-fun { float: right; margin-top: 20px; span { margin-left: 30px; cursor: pointer; } // .icon-tupian { // } input { display: none; } } } .botoom { width: 100%; height: 70vh; background-color: rgb(50, 54, 68); border-radius: 20px; padding: 20px; box-sizing: border-box; position: relative; .chat-content { width: 100%; height: 85%; overflow-y: scroll; padding: 20px; box-sizing: border-box; &::-webkit-scrollbar { width: 0; /* Safari,Chrome 隐藏滚动条 */ height: 0; /* Safari,Chrome 隐藏滚动条 */ display: none; /* 移动端、pad 上Safari,Chrome,隐藏滚动条 */ } .chat-wrapper { position: relative; word-break: break-all; .chat-friend { width: 100%; float: left; margin-bottom: 20px; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; .chat-text { max-width: 90%; padding: 20px; border-radius: 20px 20px 20px 5px; background-color: rgb(56, 60, 75); color: #fff; &:hover { background-color: rgb(39, 42, 55); } pre { white-space: break-spaces; } } .chat-img { img { width: 100px; height: 100px; } } .info-time { margin: 10px 0; color: #fff; font-size: 14px; img { width: 30px; height: 30px; border-radius: 50%; vertical-align: middle; margin-right: 10px; } span:last-child { color: rgb(101, 104, 115); margin-left: 10px; vertical-align: middle; } } } .chat-me { width: 100%; float: right; margin-bottom: 20px; position: relative; display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-end; .chat-text { float: right; max-width: 90%; padding: 20px; border-radius: 20px 20px 5px 20px; background-color: rgb(29, 144, 245); color: #fff; &:hover { background-color: rgb(26, 129, 219); } } .chat-img { img { max-width: 300px; max-height: 200px; border-radius: 10px; } } .info-time { margin: 10px 0; color: #fff; font-size: 14px; display: flex; justify-content: flex-end; img { width: 30px; height: 30px; border-radius: 50%; vertical-align: middle; margin-left: 10px; } span { line-height: 30px; } span:first-child { color: rgb(101, 104, 115); margin-right: 10px; vertical-align: middle; } } } } } .chatInputs { width: 100%; position: absolute; bottom: 0; margin: 0 auto; align-items: center; display: flex; padding-bottom: 15px; .boxinput { width: 50px; height: 50px; background-color: rgb(66, 70, 86); border-radius: 15px; border: 1px solid rgb(80, 85, 103); position: relative; cursor: pointer; img { width: 30px; height: 30px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } } .emoji { transition: 0.3s; &:hover { background-color: rgb(46, 49, 61); border: 1px solid rgb(71, 73, 82); } } .inputs { width: 70%; height: 50px; background-color: rgb(66, 70, 86); border-radius: 15px; border: 2px solid rgb(34, 135, 225); padding: 10px; box-sizing: border-box; transition: 0.2s; margin-right: 10px; font-size: 20px; color: #fff; font-weight: 100; &:focus { outline: none; } } .send { background-color: rgb(29, 144, 245); border: 0; transition: 0.3s; box-shadow: 0px 0px 5px 0px rgba(0, 136, 255); &:hover { box-shadow: 0px 0px 10px 0px rgba(0, 136, 255); } } } }}</style>
本文链接地址:https://www.jiuchutong.com/zhishi/300766.html 转载请保留说明!

上一篇:Vue组件的通信方式有哪些?(vue组件通信方法)

下一篇:CSS的选择器(超详细)(css选择器详解)

  • 出口退税申报的发票无电子信息是什么意思
  • 计提印花税会计分录
  • 加计抵扣10%的进项税 会计处理
  • 股权转让如何交税
  • 简易征收 抵扣进项
  • 承兑汇票区别
  • 空调的折旧年限和残值率
  • 企业收到生育津贴但不发给员工怎么办
  • 小规模纳税人开了3%的专票还能享受1%
  • 复式记账的优点有哪些
  • 加建工程部分结算款如何做会计分录呢?
  • 代发工资开票内容
  • 党组织专项经费项社区服务队项目简介
  • 随同产品销售单独计价的包装物计入
  • 企业征地补偿支出需要什么凭据做账?
  • 外出施工安装的公司发工资怎么记账?
  • 购买原材料已付款怎么记账
  • 案例分析房产税会计分录怎么写?
  • 劳务建筑公司一年可以赚多少
  • 会计人员应掌握的知识
  • 采购商品产生的费用有哪些
  • 小规模纳税人每季度超过30万交税
  • 金税盘开票信息修改
  • 职工食堂对外经营合法吗
  • 跨年度增值税发票作废怎么退税
  • 固定资产评估增值后如何入账
  • win10待机久了自动关机
  • 一个集团的分公司干过活再去另一个分公司会被发现吗
  • 电脑密码解除步数怎么弄
  • ekb install
  • 质量赔偿款要交税吗
  • framework3.5怎么打开
  • 企业所得税股息红利所得来源地
  • 普莱斯德
  • php常用方法
  • 深入php第五版中文版pdf
  • 现在前端的现状
  • openai 入门
  • 热闻丨ChatGPT会替代你我吗?让它写了封情书后,我得到答案
  • php file函数
  • 商业承兑到期后有效期
  • 个体户餐饮服务包括哪些经营范围
  • 增值税发票的规范
  • 资产负债率如何
  • 用友u8固定资产减少怎么撤销
  • 基础电信服务和增值电信服务税率
  • MSSQL output使用
  • 分支机构注销后往来账如何处理?
  • 分公司注销库存车怎么办
  • 购买土地的入账价值包括什么
  • 如何进行税前扣除
  • 代缴社保会计分录
  • 生产配合销售还是销售配合生产
  • 销售的差额如何分录
  • 增值税普通发票查询
  • 房地产实收资本怎么算
  • 开发票时如何添加商品编码?
  • centos rpm安装方法
  • 一条sql语句搞定一个数据
  • mysql mac安装教程
  • mysql5.7压缩包
  • 捷波mig41tm主板
  • windows自带截图软件
  • win7如何连接网络电脑连接网络
  • win7的系统在哪里打开
  • 远程管理是什么意思
  • linux系统中的用户大体可分为三组
  • centos6.5升级到7.5
  • windows开始按钮点了没用
  • windows8怎么进入bios
  • win8怎么更改密码
  • win7的注册表在哪里打开
  • cocos2dx解密
  • python实现人脸识别代码
  • opengl es 2.0是什么
  • js去除hover样式
  • 机票票号怎么查航班
  • 中国体育体制改革的特点
  • 国家税务总局随州市税务局稽查局
  • 印花税会计分录怎么做 印花税需要计提吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设