uniapp和微信小程序使用Vue连接AI实现聊天咨询等功能

 用的是VUE3组和式开发使用的是科大讯飞的大模型聊天框我是使用了组件开发  需要更加详细的内容可以留言 需要如何拿科大讯飞的appid之内的可以评论到时候我出一篇文章

<template>
  <view style="height: 100%">
    <view style="padding-bottom: 84rpx">
      <view class="cu-chat">
        <view class="cu-item">
          <view class="cu-avatar radius" style="background-image: url(https://image.meiye.art/Fha6tqRTIwHtlLW3xuZBJj8ZXSX3?imageMogr2/thumbnail/450x/interlace/1)"></view>
          <view class="main">
            <view class="content shadow">请输入你想咨询的问题(由AI大模型提供内容仅供参考)</view>
          </view>
        </view>
        <!-- 动态聊天记录 -->
        <view v-for="(item, index) in historyTextList" :key="index" :class="['cu-item', item.role === 'user' || item.role === 'user-typing' ? 'self' : '']">
          <view v-if="item.role !== 'user' && item.role !== 'user-typing'" class="cu-avatar radius" style="background-image: url(https://image.meiye.art/Fha6tqRTIwHtlLW3xuZBJj8ZXSX3?imageMogr2/thumbnail/450x/interlace/1)"></view>
          <view class="main">
            <view :class="['content', item.role === 'user' || item.role === 'user-typing' ? 'bg-green' : 'shadow']">
              <text>{{ item.content }}</text>
            </view>
          </view>
          <view v-if="item.role === 'user' || item.role === 'user-typing'" class="cu-avatar radius" style="background-image: url(https://image.meiye.art/FlqKg5bugFQD5Qzm_QhGM7ET4Mtx?imageMogr2/thumbnail/450x/interlace/1)"></view>
          <view class="date">{{ new Date().toLocaleTimeString() }}</view>
        </view>
      </view>
      <view :class="'cu-bar foot input ' + (InputBottom != 0 ? 'cur' : '')" :style="'bottom:' + InputBottom + 'px'">
        <view class="action">
          <text class="cuIcon-sound text-grey"></text>
        </view>
        <input v-model="TEXT" class="solid-bottom" @focus="InputFocus" @blur="InputBlur" :adjust-position="false" :focus="false" maxlength="300" cursor-spacing="10" />
        <view class="action">
          <text class="cuIcon-emojifill text-grey"></text>
        </view>
        <button class="cu-btn bg-green shadow" @click="sendToSpark()">发送</button>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref } from 'vue';
import * as base64 from 'base-64';
import CryptoJS from 'crypto-js';
import parser from 'fast-xml-parser';
import * as utf8 from 'utf8';
import URL from 'url';

const TEXT = ref('');
const httpUrl = ref("https://spark-api.xf-yun.com/v3.5/chat");
const modelDomain = ref(''); // V1.1-V3.5动态获取,高于以上版本手动指定
const APPID = ref(''); // 需要填写你自己的
const APISecret = ref('');// 需要填写你自己的
const APIKey = ref('=');// 需要填写你自己的
const sparkResult = ref('');
const historyTextList = ref([]); // 历史会话信息,由于最大token12000,可以结合实际使用,进行移出
const tempRes = ref(''); // 临时答复保存
const currentAssistantMessageIndex = ref(-1); // 当前助理消息的索引
const InputBottom = ref(0);

const sendToSpark = async () => {
  let myUrl = await getWebSocketUrl();
  tempRes.value = "";

  const socketTask = uni.connectSocket({
    url: myUrl,
    method: 'GET',
    success: res => {
      console.log(res, "ws成功连接...", myUrl);
    }
  });

  socketTask.onError((res) => {
    console.log("连接发生错误,请检查appid是否填写", res);
  });

  socketTask.onOpen((res) => {
    historyTextList.value.push({
      "role": "user",
      "content": TEXT.value
    });

    let params = {
      "header": {
        "app_id": APPID.value,
        "uid": "aef9f963-7"
      },
      "parameter": {
        "chat": {
          "domain": modelDomain.value,
          "temperature": 0.5,
          "max_tokens": 1024
        }
      },
      "payload": {
        "message": {
         "text": [
            { "role": "system", "content": "你现在扮演一位医生,你专业、严谨,能够准确回答医疗相关问题。接下来请用医生的口吻和用户对话。" },
            ...historyTextList.value.map(item => ({
              role: item.role,
              content: item.content
            })),
            { "role": "user", "content": TEXT.value }
          ]
        }
      }
    };

    socketTask.send({
      data: JSON.stringify(params),
      success() {
        console.log('第一帧发送成功');
      }
    });
    // 清空输入框内容
    TEXT.value = '';
  });

  socketTask.onMessage((res) => {
    console.log('收到API返回的内容:', res.data);
    let obj = JSON.parse(res.data);
    let dataArray = obj.payload.choices.text;
    for (let i = 0; i < dataArray.length; i++) {
      tempRes.value += dataArray[i].content;

      // 如果当前没有助理消息,则创建一个新的
      if (currentAssistantMessageIndex.value === -1) {
        currentAssistantMessageIndex.value = historyTextList.value.length;
        historyTextList.value.push({
          "role": "assistant",
          "content": ""
        });
      }

      // 更新当前助理消息的内容
      historyTextList.value[currentAssistantMessageIndex.value].content += dataArray[i].content;
    }

    let temp = JSON.parse(res.data);
    if (temp.header.code !== 0) {
      console.log(`${temp.header.code}:${temp.message}`);
      socketTask.close({
        success(res) {
          console.log('关闭成功', res);
        },
        fail(err) {
          console.log('关闭失败', err);
        }
      });
    }

    if (temp.header.code === 0) {
      if (res.data && temp.header.status === 2) {
        // 消息接收完毕,重置状态
        currentAssistantMessageIndex.value = -1;
        setTimeout(() => {
          socketTask.close({
            success(res) {
              console.log('关闭成功', res);
            },
            fail(err) {
              console.log('关闭失败', err);
            }
          });
        }, 1000);
      }
    }
  });
};

const getWebSocketUrl = async () => {
  const httpUrlHost = httpUrl.value.substring(8, 28);
  const httpUrlPath = httpUrl.value.substring(28);

  switch (httpUrlPath) {
    case "/v1.1/chat":
      modelDomain.value = "general";
      break;
    case "/v2.1/chat":
      modelDomain.value = "generalv2";
      break;
    case "/v3.1/chat":
      modelDomain.value = "generalv3";
      break;
    case "/v3.5/chat":
      modelDomain.value = "generalv3.5";
      break;
  }

  return new Promise((resolve, reject) => {
    const url = `wss://${httpUrlHost}${httpUrlPath}`;
    const host = "spark-api.xf-yun.com";
    const apiKeyName = "api_key";
    const date = new Date().toGMTString();
    const algorithm = "hmac-sha256";
    const headers = "host date request-line";
    const signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${httpUrlPath} HTTP/1.1`;
    const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, APISecret.value);
    const signature = CryptoJS.enc.Base64.stringify(signatureSha);
    const authorizationOrigin = `${apiKeyName}="${APIKey.value}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
    const authorization = base64.encode(authorizationOrigin);
    const finalUrl = `${url}?authorization=${authorization}&date=${encodeURI(date)}&host=${host}`;
    resolve(finalUrl);
  });
};

const InputFocus = (e) => {
  InputBottom.value = e.detail.height;
};

const InputBlur = (e) => {
  InputBottom.value = 0;
};
</script>
 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值