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.openApiconst 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、完整代码

  
{{ item.content }}
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('\n\n') 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' }) }) }, },}.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; }}

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

  
. . . export default { name: 'baseLoading',}.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); }}

7、示例

8、注意

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