讯飞星火大模型-AI大语言模型-星火大模型-科大讯飞

先讯飞注册申请到APPID 、APISecret 、APIKey

查看配置

星火认知大模型Web API文档 | 讯飞开放平台文档中心

报错返回码查看

星火认知大模型服务说明 | 讯飞开放平台文档中心

这里用得是vue+element plus 测试

先安装依赖 pnpm install crypto-js 

<script setup lang="ts">
import CryptoJs from "crypto-js";
import { ref, unref } from "vue";
import { ElMessage } from "element-plus";


// 请填写讯飞申请资料

const GLOBAL_SPARK_AI_APPID = "";
const GLOBAL_SPARK_AI_APISECRET = "";
const GLOBAL_SPARK_AI_APIKEY = "";
/**
 * 大模型版本对照表
 * 官方文档参考: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
 */
const GLOBAL_VERSION = "/v4.0/chat";   //目前用得是Spark4.0 Ultra 或者根据需要看文档改

interface Message {
  role: "user" | "assistant";
  content: string;
}

const messages = ref<Message[]>([]);
const isLoading = ref(false);
const sMsg = ref("");

const getWebsocketUrl = () => {
  let url = "wss://spark-api.xf-yun.com" + GLOBAL_VERSION;
  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";
  let signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${GLOBAL_VERSION} HTTP/1.1`;
  let signatureSha = CryptoJs.HmacSHA256(
    signatureOrigin,
    GLOBAL_SPARK_AI_APISECRET
  );
  let signature = CryptoJs.enc.Base64.stringify(signatureSha);
  let authorizationOrigin = `${apiKeyName}="${GLOBAL_SPARK_AI_APIKEY}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
  let authorization = btoa(authorizationOrigin);
  return `${url}?authorization=${authorization}&date=${encodeURI(
    date
  )}&host=${host}`;
};

const sendMsg = () => {
  if (unref(isLoading)) {
    ElMessage.warning("加载中...");
    return;
  }
  if (!unref(sMsg)) {
    ElMessage.warning("请输入内容");
    return;
  }

  // 添加用户消息
  messages.value.push({
    role: "user",
    content: unref(sMsg),
  });

  const socket = new WebSocket(getWebsocketUrl());
  let aiResponse = "";

  socket.addEventListener("open", () => {
    isLoading.value = true;
    const params = {
      header: {
        app_id: GLOBAL_SPARK_AI_APPID,
        uid: "讯飞ai测试",
      },
      parameter: {
        chat: {
          domain: "4.0Ultra",
          temperature: 0.5,
          max_tokens: 1024,
        },
      },
      payload: {
        message: {
          text: [
            ...messages.value.map((msg) => ({
              role: msg.role,
              content: msg.content,
            })),
          ],
        },
      },
    };
    socket.send(JSON.stringify(params));
  });

  socket.addEventListener("message", ({ data }) => {
    const response  = JSON.parse(data);
    aiResponse += response.payload.choices.text[0].content;
    // 更新或添加AI响应消息
    const lastMessage = messages.value[messages.value.length - 1];
    if (lastMessage.role === "assistant") {
      lastMessage.content = aiResponse;
    } else {
      messages.value.push({
        role: "assistant",
        content: aiResponse,
      });
    }
  });

  socket.addEventListener("close", () => {
    isLoading.value = false;
    sMsg.value = "";
  });

  socket.addEventListener("error", (error) => {
    isLoading.value = false;
    ElMessage.error("连接出错,请重试");
    console.error("WebSocket error:", error);
  });
};
</script>

<template>
  <div class="container">
    <div class="chat-content">
      <div
        v-for="(msg, index) in messages"
        :key="index"
        :class="['msg', msg.role === 'user' ? 'msg-user' : 'msg-ai']"
      >
        <div class="msg-content" v-html="msg.content"></div>
      </div>
      <div v-if="isLoading" class="loading-indicator">
        <span>AI思考中</span>
        <span class="dots">...</span>
      </div>
    </div>
    <div class="ask-content">
      <el-input
        type="textarea"
        v-model="sMsg"
        :disabled="isLoading"
        placeholder="请输入您的问题"
        @keyup.enter.ctrl="sendMsg"
      />
      <div class="opt">
        <el-button
          type="primary"
          size="large"
          @click="sendMsg"
          :loading="isLoading"
          >发送</el-button
        >
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #f2f2f2;

  .chat-content {
    flex: 1;
    overflow-y: auto;
    padding: 20px;

    .msg {
      margin-bottom: 20px;
      max-width: 80%;

      &.msg-user {
        margin-left: auto;
        text-align: right;

        .msg-content {
          background: #007aff;
          color: white;
          border-radius: 15px 15px 0 15px;
        }
      }

      &.msg-ai {
        margin-right: auto;
        text-align: left;

        .msg-content {
          background: white;
          border-radius: 15px 15px 15px 0;
        }
      }

      .msg-content {
        padding: 12px 16px;
        display: inline-block;
        word-break: break-word;
      }
    }

    .loading-indicator {
      text-align: center;
      color: #666;
      padding: 10px;

      .dots {
        display: inline-block;
        animation: dotAnimation 1.5s infinite;
      }
    }
  }

  .ask-content {
    background: white;
    border-top: 1px solid #eee;
    padding: 16px;
    position: relative;

    :deep(.el-textarea__inner) {
      border: none;
      background: #f5f5f5;
      padding: 12px;
      min-height: 80px !important;
      resize: none;

      &:focus {
        box-shadow: none;
      }
    }

    .opt {
      text-align: right;
      margin-top: 8px;
    }
  }
}

@keyframes dotAnimation {
  0%,
  20% {
    content: ".";
  }
  40% {
    content: "..";
  }
  60% {
    content: "...";
  }
  80%,
  100% {
    content: "";
  }
}
</style>

最终效果,样式有点丑哈,可以根据需求修改哦

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐