位置: 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选择器详解)

  • 企业所得税汇算清缴补缴税款分录
  • 出口退税便捷退税操作流程
  • 小规模多计提增值税税率
  • 一般纳税人开劳务发票几个点
  • 小微企业增值税减免政策
  • 企业缴纳增值税后还需缴纳所得税吗
  • 公司三年零申报后注销
  • 结构性存款是
  • 旧设备用于投资是否应按视同销售处理
  • 报销增值税发票和普通发票
  • 工程报废及毁损如何做会计处理合适呢?
  • 增值税普通发票跨月冲红
  • 公司购买短期理财现金流量表怎么填
  • 哪些是非累计带薪缺勤?
  • 应交增值税减免税额期末需要结转吗
  • 盈余公积补亏影响资产吗
  • 商品赠送的内账怎么做账
  • 增值税专用发票怎么开
  • 出纳人员怎么进入会计
  • 如果注册资本没有到账如何处理
  • 预付账款坏账处理流程
  • windows 7如何
  • 政府性基金收入来源
  • php array_search() 函数使用
  • 厂房押金收据范本
  • 公司培训赔偿
  • hotkey osd driver可以卸载吗
  • 全年一次性奖金计税方式
  • 哈勃太空望远镜取得的部分成果有哪些
  • php文件修改后,打开还是显示以前的页面
  • vue3项目实战
  • 毕业设计基于web难还是JAVA
  • php发送http请求的常用方法分析
  • “php”
  • 城市维护建设税属于什么会计科目
  • 选择mysql数据库为当前数据库
  • php安装不上
  • 加油发票怎么报税
  • 累计增长率如何计算公式
  • 公司汽车转卖给个人税率
  • 小额贷款公司如何做账
  • 怎么找回丢失的华为手机
  • 一次还本付息债券定价公式
  • 业务招待费的抵扣限额
  • 个税汇算清缴时劳务报酬怎么计税
  • 什么叫做有限循环小数
  • 个体户季报要抄税吗
  • 劳保用品费用计入什么科目
  • 投资性房地产转为非投资性房地产
  • 投资收益是总账还是明细账
  • 未开票收入如何申报
  • 登记账簿遇到的问题及解决
  • 出口退税进项发票会计分录
  • 信用证保证金的计算公式
  • 支付给烟农的价格怎么算
  • 退回的个税手续费如何账务处理
  • 筹建期间开办费跨年
  • 新单位怎么建账
  • 帐簿凭证的管理方法
  • sqlserver数据库显示单个用户
  • 更新版本
  • windows xp的安装
  • window8输入法怎么设置
  • windows7使用
  • win7系统开机登录不了怎么修复
  • preorder遍历
  • android界面控件
  • 自动登入
  • python语言解析
  • Backbone.js 0.9.2 源码注释中文翻译版
  • jquery获取值的几种方法
  • 火狐firefox浏览器官网
  • js对象的常用方法
  • 湖南税务发票查询系统查不到外省的发票
  • 代扣社保代扣公式是什么
  • 增值税进项发票勾选时间
  • 内蒙古电子税务局开票流程
  • 代理运输服务费和运费的区别
  • 苏州税务局发票查询系统
  • 淮安市地税局电话号码
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设