前言

本项目主要采用 Vue3 + TypeScript + Vite 构建

项目主要依赖:Element-Plus + mitt + Scss + base-64 + crypto-js

介绍        

        本项目仅供学习如何使用讯飞星火认知大模型,进行简单的 Web 端页面搭建及基本使用,该 demo 项目具备基本的聊天对话功能,可通过左侧选择不同的助手在右侧窗口进行对话,可供实际开发参考使用。本身这部分内容是在我个人的毕业设计中进行了使用,鉴于有部分朋友向我索要 AI 部分的代码,故在此分享。

项目链接

        Github仓库地址:GitHub - xkYZI/SparkDemo

主要代码

1、路径鉴权


import * as base64 from "base-64";
import CryptoJs from "crypto-js";

//这里是讯飞星火大模型工作台的个人信息
export const APPID = "你的APPID";
export const APIKey = "你的APIKey";
export const APISecret = "你的APISecret";
/**
 * 大模型版本对照表
 * 官方文档参考:https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E
 *  Spark4.0 Ultra 请求地址:     domain:4.0Ultra      version:v4.0/chat
 *  Spark Max 请求地址:          domain:generalv3.5   version:v3.5/chat
 *  Spark Pro-128K 请求地址:     domain:pro-128k      version:chat/pro-128k
 *  Spark Pro 请求地址:          domain:generalv3     version:v3.1/chat
 *  Spark V2.0 请求地址:         domain:generalv2     version:v2.1/chat
 *  Spark Lite请求地址:          domain:general       version:v1.1/chat
 */
export const domain = "generalv3.5"
const version = "v3.5/chat"

//获取鉴权url地址
export const getWebsocketUrl = () => {
    //获取鉴权地址
    return new Promise((resolve) => {
        let url = "wss://spark-api.xf-yun.com/" + version;
        let host = "spark-api.xf-yun.com";
        let apiKeyName = "api_key";
        let date = new Date().toUTCString();
        console.log("鉴权url地址", date);
        let algorithm = "hmac-sha256";
        let headers = "host date request-line"
        let signatureOrigin = `host: ${host}\ndate: ${date}\nGET /` + version + ` HTTP/1.1`;
        let signatureSha = CryptoJs.HmacSHA256(
            signatureOrigin,
            APISecret
        );
        let signature = CryptoJs.enc.Base64.stringify(signatureSha);
        let authorizationOrigin = `${apiKeyName}="${APIKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
        let authorization = base64.encode(authorizationOrigin);

        //将空格编码
        url = `${url}?authorization=${authorization}&date=${encodeURI(
            date
        )}&host=${host}`;

        resolve(url);
        console.log("鉴权url地址2", url);
    });
}

2、发送消息开启通信

//发送消息
const sendMsg = async () => {
  //获取请求地址
  let auUrl = await getWebsocketUrl();
  let socket = new WebSocket(auUrl as string);
  //监听websocket各阶段时间
  socket.addEventListener("open", (event) => {
    console.log("开启链接", event);
    //发送消息
    const params = {
      header: {
        app_id: requestObj.value.APPID,
        uid: requestObj.value.Uid,
      },
      parameter: {
        chat: {
          domain: domain,
          temperature: 0.5,
          max_tokens: 1024,
        },
      },
      payload: {
        message: {
          //结合上下文回答,将历史问答信息传给服务端
          text: [
            {
              role: "system",
              content: AI.value.roleDefinitionStatement,
            },
            ...historyList.value,
          ],
        },
      },
    };
    console.log("发送信息");
    inputValue.value = "";
    isLoading.value = true;
    socket.send(JSON.stringify(params));
    // requestObj.sparkResult
  });
  socket.addEventListener("message", (event) => {
    console.log("接受信息", event);
    let data = JSON.parse(event.data);
    console.log(data);
    const str = data.payload.choices.text[0].content;
    replyContent.value += str.replace(/\n/g, "<br>");
    // replyContent.value.replace(/\n/g, "<br>");
    scrollBottom();
    if (data.header.code !== 0) {
      console.log("出错了", data.header.code, ":", data.header.message);
      // 出错了"手动关闭连接"
      socket.close();
    }
    if (data.header.code === 0) {
      // 对话已经完成
      if (data.payload.choices.text && data.header.status === 2) {
        //requestObj.sparkResult += data.payload.choices.text[0].content;
        setTimeout(() => {
          // "对话完成,手动关闭连接"
          reply(replyContent.value);
          // scrollBottom();
          socket.close();
        }, 1000);
      }
    }
  });
  socket.addEventListener("close", (event) => {
    console.log("关闭链接", event);
    //对话完成后socket会关闭
  });
  socket.addEventListener("error", (event) => {
    console.log("错误链接", event);
  });
};

3、限制历史对话长度


//判断历史纪录的长度,如果太长删去前面的一些
function canAddHistory() {
  let history_length = 0;
  historyList.value.forEach((item) => {
    history_length += item.content.length;
  });
  console.log("当前长度:" + history_length);
  if (history_length > 10000) {
    //移除五个元素
    historyList.value.splice(0, 5);
    return false;
  }
  return true;
}

4、页面样例

运行方式

1、从GitHub项目链接下载 SparkDemo v1.0 。

2、在vscode或其他编译器中打开本项目。

3、新建/打开终端。

4、首次启动 需加载项目所需依赖。

npm install

5、启动项目。

npm run dev

注意

        本项目仅供学习交流使用,不得擅自售卖谋利!

结束

部分内容参考了 B 站:red 润大佬的视频:讯飞星火认知大模型接入网页 demo 演示(项目接入大模型功能)

最后再次感谢 red 润大佬的无私分享!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐