对接讯飞聊天机器人接口--复盘

1、准备工作

        1)、进入以下平台进行注册,登录后,点击红框处

        2)、点击个人免费包(会弹出实名认证,先进行实名认证)

     3)、认证后,会进入以下界面,先添加应用

     4)、添加应用

    5)、选择套餐,提交订单

   6)、返回主页,点击控制台,找到自己的应用,点击进入应用

   7)、进入应用后找到自己的APPID、APISecret、APIKey。


2、先看效果 

3、前端完整代码

★★★注意★★★:个人只是写了前端代码,聊天记录刷新后就没有了。

<template>
  <a-layout style="max-width: 800px; margin: auto">
    <a-layout-content
      :style="{
        border: '3px solid #4fc3f7',
        borderRadius: '8px',
        boxShadow: '0 8px 16px rgba(0, 0, 0, 0.3)',
        overflow: 'hidden',
      }"
    >
      <h2 style="margin-bottom: 20px; text-align: center; color: #4fc3f7">
        Chat Record
      </h2>
      <div class="divider"></div>
      <div class="chat-messages" ref="chatMessages">
        <!-- 聊天记录显示区域Q -->
        <div v-if="dialogueHistory.length === 0" class="no-data-message">
          暂无数据
        </div>
        <div
          v-for="message in dialogueHistory"
          :key="message.id"
          class="message-container"
        >
          <!-- 修改部分 -->
          <div
            :class="[
              message.type === 'question'
                ? 'user-name-aline'
                : 'robot-name-aline',
            ]"
          >
            <div>{{ message.name }}:</div>
          </div>
          <div class="divider"></div>
          <div
            :class="[
              message.type === 'question' ? 'user-message' : 'bot-message',
              message.isCode ? 'code-message' : '',
            ]"
            style="position: relative"
          >
            <template v-if="message.isCode">
              <!-- 使用 extractCodeAndLanguage 函数 -->
              <pre
                v-html="
                  highlightCode(extractCodeAndLanguage(message.text).code)
                "
                style="
                  background-color: #f0f0f0;
                  padding: 15px;
                  box-shadow: #999999;
                  border-radius: 5px;
                  margin: 0;
                "
              ></pre>
            </template>
            <template v-else>
              {{ message.text }}
            </template>
            <!-- 添加复制按钮 -->
            <button
              v-if="message.isCode"
              @click="copyCode(message.text)"
              class="copy-button"
              style="
                position: absolute;
                top: 7px;
                right: 7px;
                cursor: pointer;
                border: none;
                background: transparent;
                color: #3498db;
              "
            >
              Copy
            </button>
          </div>
          <!-- 结束修改部分 -->
        </div>
      </div>
      <div class="user-input-container">
        <!-- 用户输入框 -->
        <a-input
          v-model="inputVal"
          @pressEnter="sendMsg"
          placeholder="请输入消息..."
          style="
            flex-grow: 1;
            padding: 8px;
            border: 1px solid #3498db;
            border-radius: 5px;
            margin-right: 10px;
          "
        />
        <!-- 发送按钮 -->
        <a-button type="primary" @click="sendMsg" style="cursor: pointer">
          发送
        </a-button>
      </div>
    </a-layout-content>
  </a-layout>
</template>
<script setup>
import { ref } from "vue";
import * as base64 from "base-64";
import CryptoJs from "crypto-js";
import hljs from "highlight.js/lib/core";
import "highlight.js/styles/default.css"; // 选择适合你项目的样式

// 导入你需要的语言支持
import javascript from "highlight.js/lib/languages/javascript";
import css from "highlight.js/lib/languages/css";
import html from "highlight.js/lib/languages/xml";
import ClipboardJS from "clipboard";

// 注册语言支持
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("css", css);
hljs.registerLanguage("html", html);
const requestObj = {
  APPID: "填你自己的",
  APISecret: "填你自己的",
  APIKey: "填你自己的",
  Uid: "0",
  sparkResult: "",
};

const inputVal = ref("");
const result = ref("");
const dialogueHistory = ref([]);

const isCopyButtonClicked = ref(false);

// 检测回复是否为代码
const isCode = (text) => {
  // 简单的检测逻辑,您可以根据需要进行调整
  return text.startsWith("```") && text.endsWith("```");
};

// 获取鉴权 URL
const getWebsocketUrl = async () => {
  return new Promise((resolve, reject) => {
    const url = "wss://spark-api.xf-yun.com/v3.1/chat";
    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 /v3.1/chat HTTP/1.1`;
    const signatureSha = CryptoJs.HmacSHA256(
      signatureOrigin,
      requestObj.APISecret
    );
    const signature = CryptoJs.enc.Base64.stringify(signatureSha);

    const authorizationOrigin = `${apiKeyName}="${requestObj.APIKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;

    const authorization = base64.encode(authorizationOrigin);

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

// 发送消息
const sendMsg = async () => {
  const myUrl = await getWebsocketUrl();
  const socket = new WebSocket(myUrl);

  socket.onopen = (event) => {
    // 发送消息的逻辑
    // 发送消息
    const params = {
      header: {
        app_id: requestObj.APPID,
        uid: "redrun",
      },
      parameter: {
        chat: {
          domain: "generalv3",
          temperature: 0.5,
          max_tokens: 1024,
        },
      },
      payload: {
        message: {
          text: [{ role: "user", content: inputVal.value }],
        },
      },
    };
    dialogueHistory.value.push({
      type: "question",
      name: "我",
      text: inputVal.value,
      // timestamp: getTimestamp(),
    });
    socket.send(JSON.stringify(params));
  };

  socket.onmessage = (event) => {
    const data = JSON.parse(event.data);

    if (data.header.code !== 0) {
      console.error("Error:", data.header.code, data.header.message);
      socket.close();
      return;
    }

    // 累积所有接收到的消息
    if (data.payload.choices.text) {
      // 连接新接收到的消息片段
      const newMessage = data.payload.choices.text[0].content;

      if (
        dialogueHistory.value.length > 0 &&
        dialogueHistory.value[dialogueHistory.value.length - 1].type ===
          "answer"
      ) {
        // 连接新接收到的消息片段到最后一个回答
        dialogueHistory.value[dialogueHistory.value.length - 1].text +=
          newMessage;
      } else {
        // 添加新的回答
        dialogueHistory.value.push({
          type: "answer",
          name: "智能助手",
          text: newMessage,
          // timestamp: getTimestamp(),
        });
      }
      // 如果回复是代码,添加相应的标记和样式
      if (isCode(newMessage)) {
        dialogueHistory.value[dialogueHistory.value.length - 1].isCode = true;
      }
    }
    // 如果对话完成或者发生错误,则关闭 socket
    if (data.header.status === 2 || data.header.code !== 0) {
      setTimeout(() => {
        socket.close();
      }, 1000);
    }
  };

  socket.onclose = (event) => {
    inputVal.value = "";
  };

  socket.onerror = (event) => {
    console.error("WebSocket error:", event);
  };
};
// 移除代码块的标记和语言标识符
const extractCodeAndLanguage = (text) => {
  if (isCode(text)) {
    const lines = text.split("\n");
    const language = lines[0].substring(3).trim();
    const code = lines.slice(1, -1).join("\n");
    return { language, code };
  }
  return { language: null, code: text };
};
// 高亮代码的方法
const highlightCode = (code) => {
  // 判断是否包含代码标识符
  if (code.startsWith("```") && code.endsWith("```")) {
    // 去掉头尾的```标识符
    code = code.slice(3, -3);
  }
  const highlighted = hljs.highlightAuto(code);
  return highlighted.value;
};
//
// // 获取当前时间戳
// const getTimestamp = () => {
//   return Math.floor(new Date().getTime() / 1000);
// };
//
// // 格式化时间戳为可读的时间格式
// const formatTimestamp = (timestamp) => {
//   const date = new Date(timestamp * 1000);
//   const hours = date.getHours();
//   const minutes = "0" + date.getMinutes();
//   return `${hours}:${minutes.substr(-2)}`;
// };
const copyCode = (code) => {
  // 使用 clipboard.js 复制文本到剪贴板
  const parentButton = document.querySelector(".message-container button");

  // 获取处理后的代码,如果是代码块,提取其中的代码
  const processedCode =
    code.startsWith("```") && code.endsWith("```")
      ? extractCodeAndLanguage(code).code
      : code;
  // 获取按钮元素
  const copyButton = document.querySelector(".copy-button");

  // 按钮初始文本
  const initialButtonText = copyButton.innerText;

  // 修改按钮文本为勾
  copyButton.innerText = "✔ Copied";

  // 3秒后将按钮文本还原
  setTimeout(() => {
    copyButton.innerText = initialButtonText;
  }, 3000);

  if (parentButton && parentButton.parentNode) {
    const clipboard = new ClipboardJS(parentButton, {
      text: function () {
        return processedCode;
      },
    });

    clipboard.on("success", function (e) {
      console.log("Text copied to clipboard:", e.text);
      clipboard.destroy(); // 销毁 clipboard 实例,防止重复绑定
    });

    clipboard.on("error", function (e) {
      console.error("Unable to copy text to clipboard:", e.action);
      clipboard.destroy(); // 销毁 clipboard 实例,防止重复绑定
    });
  } else {
    console.error("Parent button or its parent node is null or undefined.");
  }
};
</script>

<style scoped>
#ChatRobotView {
  max-width: 800px;
  margin: auto;
}

.chat-container {
  border: 1px solid #ccc;
  border-radius: 8px;
  overflow: hidden;
}

.chat-messages {
  padding: 10px;
  max-height: 400px;
  overflow-y: auto;
}

.message {
  margin-bottom: 10px;
}

.user-message {
  background-color: #3498db;
  color: #ffffff;
  padding: 10px;
  border-radius: 5px;
  align-self: flex-end;
}

.bot-message {
  background-color: #e0e0e0;
  color: #000000;
  padding: 10px;
  border-radius: 5px;
  align-self: flex-start;
}

.user-input-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  border-top: 1px solid #ddd;
}

.user-input-container input {
  flex-grow: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 5px;
  margin-right: 10px;
}

.user-input-container button {
  background-color: #4caf50;
  color: #fff;
  border: none;
  padding: 8px 16px;
  border-radius: 5px;
  cursor: pointer;
}

.message-container {
  display: flex;
  flex-direction: column;
  margin-bottom: 10px;
}

.message-info {
  font-size: 12px;
  color: #888;
  margin-bottom: 5px;
}

.user-name-aline {
  align-self: flex-end;
  margin-bottom: 5px;
}

.robot-name-aline {
  align-self: flex-start;
  margin-bottom: 5px;
}

.no-data-message {
  font-size: large;
  color: #8c8c8c;
  height: 200px;

  display: flex;
  align-items: center;
  justify-content: center;
}

.message-container button.copy-button:active {
  background-color: #4caf50; /* 按下时的背景色 */
  color: #fff;
}

.divider {
  width: 100%;
  height: 1px;
  background-color: #4fc3f7;
  margin: 5px 0;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302746.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

栈的经典算法问题(算法村第四关白银挑战)

括号匹配问题 有效的括号 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类…

滴水逆向1

八进制加法乘法表 EF11101111 j记住其映射关系 十进制的定义&#xff1a;由十个符号组成&#xff0c;分别是0 1 2 3 4 5 6 7 8 9 逢十进一。九进制的定义&#xff1a;由九个符号组成&#xff0c;分别是0 1 2 3 4 5 6 7 8 逢九进一。十六进制的定义&#xff1a;由十六个符号组成…

鸿蒙开发解决agconnect sdk not initialized. please call initialize()

文章目录 项目场景:问题描述原因分析:解决方案:总结:项目场景: 鸿蒙开发报错: agconnect sdk not initialized. please call initialize() 问题描述 报错内容为: 10-25 11:41:01.152 6076-16676 E A0c0d0/JSApp: app Log: 数据查询失败: {“code”:1100001,“messag…

在Kubernetes中优雅地导出和清理Ingress资源

引言 Kubernetes的Ingress资源是定义外部访问集群服务的规则。随着微服务架构和容器化技术的普及&#xff0c;Ingress作为路由流量的关键组件变得愈发重要。当我们需要在环境之间迁移Ingress资源或者备份当前的配置时&#xff0c;就会用到导出功能。然而&#xff0c;直接使用k…

听GPT 讲Rust源代码--compiler(29)

File: rust/compiler/rustc_const_eval/src/util/check_validity_requirement.rs 在Rust编译器的源代码中&#xff0c;rust/compiler/rustc_const_eval/src/util/check_validity_requirement.rs文件的作用是进行验证要求的检查。具体而言&#xff0c;该文件定义了函数check_val…

一文讲透使用Python绘制双纵轴线图

双纵轴线图主要用来展示两个因变量和一个自变量的关系&#xff0c;并且两个因变量的数值单位不同。具体来说&#xff0c;双纵轴线图是指在一幅图上有一个横轴和两个纵轴&#xff0c;适用于三个变量。两个纵轴分别表示一个变量&#xff0c;横轴变量同时适用于两个纵轴上的变量&a…

C++力扣题目--94,144,145二叉树非递归(迭代)遍历

为什么可以用迭代法&#xff08;非递归的方式&#xff09;来实现二叉树的前后中序遍历呢&#xff1f; 我们在栈与队列&#xff1a;匹配问题都是栈的强项 (opens new window)中提到了&#xff0c;递归的实现就是&#xff1a;每一次递归调用都会把函数的局部变量、参数值和返回地…

Azure Machine Learning - 人脸识别任务概述与技术实战

Azure AI 人脸服务提供了可检测、识别和分析图像中的人脸的 AI 算法。 人脸识别软件在许多不同情形中都十分重要&#xff0c;例如识别、无接触访问控制和实现隐私的人脸模糊。你可以通过客户端库 SDK&#xff0c;或者直接调用 REST API 使用人脸服务。 目录 一、人脸识别服务场…

Python print()函数高级用法和 len()函数详解:获取字符串长度或字节数

Python print()函数高级用法 我们使用 print() 函数时&#xff0c;都只输出了一个变量&#xff0c;但实际上 print() 函数完全可以同时输出多个变量&#xff0c;而且它具有更多丰富的功能。 print() 函数的详细语法格式如下&#xff1a; print (value,...,sep,end\n,filesys.s…

词嵌入位置编码的实现(基于pytorch)

背景介绍 在transformers架构当中&#xff0c;对于词向量的输入需要加上原本词对应的位置信息&#xff0c;作为输入到模型中训练的input&#xff0c;那具体的位置编码如何实现呢&#xff1f;本篇博客就跟大家一起分享一下对应的步骤 位置编码的公式 对于词向量的位置编码的方…

LaTex引用字体变色

使用下面这条语句进行修改。 ‘citecolor’改变参考文献颜色&#xff0c; ‘linkcolor’改变图标公式引用的颜色&#xff0c; ‘urlcolor’ 文本网站超链接颜色。 \usepackage[colorlinks,bookmarksopen,bookmarksnumbered,citecolorblue, linkcolorblue, urlcolorblue]{hyper…

黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目——第四部分

黑马程序员Java项目实战《瑞吉外卖》&#xff0c;轻松掌握springboot mybatis plus开发核心技术的真java实战项目——第四部分 1. 套餐管理1.1 新增套餐1.1.1 添加菜品数据回显 1.2 保存添加套餐1.3 套餐信息分页查询1.4 删除套餐1.5 需要自己单独实现的功能1.5.1 套餐管理的启…

leecode-代码随想录-学习笔记1

编程语言基础课&#xff0c;重新学习 kamacoder.com 基础语法&#xff1b;ACM输入输出通用模板&#xff1b;之前Java狂神说的学习笔记&#xff08;但是还是按照编程习惯用了C&#xff0c;感觉更底层好写代码&#xff09;。 正式开始&#xff1a; 下面按照题目-我的解答思路和…

深度解析Nginx负载均衡算法及配置实例

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

每天刷两道题——第十天

1.1和为k的子数组 给你一个整数数组 n u m s nums nums 和一个整数 k k k &#xff0c;请你统计并返回 该数组中和为 k k k 的子数组的个数 。子数组是数组中元素的连续非空序列。 输入&#xff1a;nums [1,2,3], k 3 输出&#xff1a;2 前缀和 1.2如何使用 前缀和的…

VSCode搭建 .netcore 开发环境

一、MacOS 笔者笔记本电脑上安装的是macOS High Sierra(10.13)&#xff0c;想要尝试一下新版本的.netcore&#xff0c;之前系统是10.12时&#xff0c;.netcore 3.1刚出来时安装过3.1版本&#xff0c;很久没更新了&#xff0c;最近.net8出来了&#xff0c;想试一下&#xff0c;…

【回溯算法】n-皇后

导航 题目来源题目描述示例思路完整代码 题目来源 n-皇后 题目描述 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一…

thinkphp学习02-目录结构、控制器、路由、配置文件

目录结构 www WEB部署目录&#xff08;或者子目录&#xff09; ├─app 应用目录 │ ├─controller 控制器目录 │ ├─model 模型目录 │ ├─ ... 更多类库目录 │ │ │ ├─common.php 公共函数文件 │ └─event.ph…

STM32MP157D-DK1 STM32CubeID使用与M核开发

STM32MP157具有A7内核核M4内核&#xff0c;前面介绍的一些文章&#xff0c;都是在A7内核上进行的&#xff0c;本篇来介绍M4内核的开发&#xff0c;以及开发时要用到的STM32 CubeIDE软件的使用。 1 STM32 CubeIDE创建LED工程 STM32CubeIDE是一体式多操作系统开发工具&#xff…

Python 全栈体系【四阶】(十一)

第四章 机器学习 机器学习&#xff1a; 传统的机器学习&#xff1a;以算法为核心深度学习&#xff1a;以数据和计算为核心 感知机 perceptron&#xff08;人工神经元&#xff09; 可以做简单的分类任务掀起了第一波 AI 浪潮 感知机不能解决线性不可分问题&#xff0c;浪潮…