Vue openAi

  • Vue openAi已关闭评论
  • 83 次浏览
  • A+
所属分类:Web前端
摘要

Tips: 请求返回的数据格式为数组,一个字一个数组,需要自己进行数据整理和拼接。


1、提示

  1. 由于国内注册 https://api.openai.com 比较麻烦,直接购买的第三方接口和key
  2. 淘宝购买,几块钱1个月
    3、自己娱乐够用

2、前端框架

  1. Vant 移动端使用
  2. axios

3、创建拦截器,api/request.js

/*  * @Descripttion: 文件说明  * @version: 0.0.1  * @Author: pengshuai  * @Date: 2023-11-01 10:39:22  * @LastEditors: PengShuai  * @LastEditTime: 2023-11-02 10:33:28  */ import axios from 'axios' // 创建axios实例 const service = axios.create({   timeout: 300 * 1000, // ms请求超时时间 })  // request拦截器 service.interceptors.request.use(   (config) => {     return config   },   (error) => {     // Do something with request error     Promise.reject(error)   } )  // respone拦截器 service.interceptors.response.use(   (response) => {     const res = response     if (res.status !== 200) {       return Promise.reject(response)     } else {       if (res.status === 200) {         return res.data       } else {         return Promise.reject(res.data.message)       }     }   },   (error) => {     return Promise.reject(error)   } )  export default service  

4、创建接口 api/index.js

import service from './request' // 访问接口地址 const baseUrl = window.configUrl.openApi const openAi = (data) =>   service({     url: baseUrl + '/v1/chat/completions',     method: 'post',     headers: {       'content-type': 'application/json',       Authorization:         'Bearer YOU-KEY-63D8A64444655655C56a0838490e',     },     data,   }) export default { openAi }  

5、完整代码

<!--  * @Descripttion: 人工智障  * @version: 0.0.1  * @Author: PengShuai  * @Date: 2023-11-10 10:22:33  * @LastEditors: PengShuai  * @LastEditTime: 2023-11-10 16:02:25 --> <template>   <div class="page">     <div class="header">       <nav-bar         title="人工智障"         right-text="清空"         @click-right="onClickRight"       ></nav-bar>     </div>     <div class="main" ref="mainScroll">       <div         class="list"         v-for="(item, index) in params.messages"         :key="index"         :class="item.role + 'tr'"       >         <div :class="item.role">{{ item.content }}</div>         <base-loading           v-if="             item.role === 'user' &&             index === params.messages.length - 1 &&             loading           "         ></base-loading>       </div>     </div>     <div class="footer">       <van-field placeholder="请输入..." v-model="messages.content">         <template #button>           <van-button             size="small"             icon="guide-o"             type="primary"             @click="onSend"             @keyup.enter="onSend"           ></van-button>         </template>       </van-field>     </div>     <div class="popup" v-if="loading"></div>   </div> </template>  <script> import api from '@/api' import { NavBar, Field, Button, Notify } from 'vant' import baseLoading from '@/components/baseLoading' export default {   name: 'HomePage',   components: {     baseLoading,     NavBar,     [Notify.name]: Notify,     [Field.name]: Field,     [Button.name]: Button,   },   data() {     return {       // 参数       params: {         messages: [           {             role: 'system',             content: '你好,我是彭帅的人工智障,有什么可以帮您?',           },         ],         stream: true,         model: 'gpt-3.5-turbo',         temperature: 0.5,         presence_penalty: 0,         frequency_penalty: 0,         top_p: 1,       },       // 消息列表       infoList: [],       // 消息       messages: {         role: 'user',         content: '',       },       loading: false,     }   },   methods: {     /**      *@Descripttion:点击右侧清空      *@Author: PengShuai      *@Date: 2023-11-10 13:13:51      */     onClickRight() {       this.params = {         messages: [           {             role: 'system',             content: '你好,我是彭帅的人工智障,有什么可以帮您?',           },         ],         stream: true,         model: 'gpt-3.5-turbo',         temperature: 0.5,         presence_penalty: 0,         frequency_penalty: 0,         top_p: 1,       }       this.messages.content = ''     },     /**      *@Descripttion:点击发送      *@Author: PengShuai      *@Date: 2023-11-10 13:34:06      */     onSend() {       this.loading = true       this.params.messages.push(JSON.parse(JSON.stringify(this.messages)))       let obj = {         role: '',         content: '',       }       this.messages.content = ''       this.onBottomScrollClick()       api         .openAi(this.params)         .then((res) => {           if (res) {             let info = null             info = res.split('nn')             info = info.map((obj) => obj.substring(5))             info.splice(-2)             info = info.map((obj) => JSON.parse(obj))             if (info.length > 0) {               info.forEach((item) => {                 if (item.choices.length > 0) {                   item.choices.forEach((o) => {                     if (o.delta.role) {                       obj.role = o.delta.role                     } else if (o.delta.content) {                       obj.content += o.delta.content                     }                   })                 }               })               this.infoList.push(obj)             }             this.params.messages.push(this.infoList[this.infoList.length - 1])             this.loading = false             this.onBottomScrollClick()           }         })         .catch((err) => {           this.loading = false           Notify({ type: 'danger', message: err })         })     },     /**      *@Descripttion:滚动条到底部      *@Author: PengShuai      *@Date: 2023-11-10 15:38:21      */     onBottomScrollClick() {       this.$nextTick(() => {         let scroll = this.$refs.mainScroll         scroll.scrollTo({ top: scroll.scrollHeight, behavior: 'smooth' })       })     },   }, } </script>  <style lang="less" scoped> .page {   width: 100%;   height: 100%;   display: flex;   flex-direction: column;   .header {     border-bottom: 1px solid #ddd;   }   .footer {     border: 1px solid #ddd;   }   .main {     flex: 1;     margin: 10px 0;     border: 1px solid #ddd;     overflow: auto;   }    .usertr {     text-align: right;   }   .list {     .system,     .assistant {       margin: 10px 10px 10px 35px;       text-align: left;       position: relative;       padding: 5px 0;       color: #878787;       border-bottom: 1px solid #ddd;       display: inline-block;       &::after {         content: '智';         position: absolute;         left: -25px;         top: 5px;         background: #07c160;         border-radius: 50%;         width: 22px;         height: 22px;         line-height: 22px;         text-align: center;         color: #fff;         font-size: 12px;       }     }     .user {       margin: 10px 40px 10px 10px;       text-align: right;       position: relative;       padding: 5px 0;       color: #505050;       border-bottom: 1px solid #ddd;       display: inline-block;       &::after {         content: '帅';         position: absolute;         right: -25px;         top: 5px;         background: #07c160;         border-radius: 50%;         width: 22px;         height: 22px;         line-height: 22px;         text-align: center;         color: #fff;         font-size: 12px;       }     }   }   .popup {     width: 100%;     height: 100%;     position: fixed;     top: 0;     left: 0;     z-index: 99;     display: flex;     justify-content: center;     align-items: center;   } } </style>  

6、提示 baseLoading 请求loading 组件 可删除自己写

<template>   <div class="baseLoading">     <div class="loading">       <span style="--time: 1">智</span>       <span style="--time: 2">障</span>       <span style="--time: 3">正</span>       <span style="--time: 4">在</span>       <span style="--time: 5">思</span>       <span style="--time: 6">考</span>       <span style="--time: 7">中</span>       <span style="--time: 8">.</span>       <span style="--time: 9">.</span>       <span style="--time: 10">.</span>     </div>   </div> </template>  <script> export default {   name: 'baseLoading', } </script>  <style lang="less" scoped> .loading {   text-align: center; }  .loading span {   display: inline-block;   font-size: 12px;   font-weight: bold;   font-family: 'Courier New', Courier, monospace;   animation: loading 1s ease-in-out infinite;   animation-delay: calc(0.1s * var(--time));   color: #919191; }  @keyframes loading {   0% {     transform: translateY(0px);   }    25% {     transform: translateY(-20px);   }    50%,   100% {     transform: translateY(0px);   } } </style>   

7、示例

Vue openAi

8、注意

Tips: 请求返回的数据格式为数组,一个字一个数组,需要自己进行数据整理和拼接。