讯飞开放平台--星火认知大模型--开发技术文档--js实例代码详解

news2024/11/16 12:55:11

 阿丹:

        之前调用写过调用百度的文心一言写网站,讯飞的星火认知模型开放了,这次尝试一下使用流式来进行用户的交互。

官网:

平台简介 | 讯飞开放平台文档中心

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

简介:

        本文章主要开发的是一个web应用。

值得一提的是官网很贴心的给了代码!!!

 我这里展示的js的小demo

阅读解析一下demo代码--js

解析了一下代码结构:
主要的核心代码是在index.html为简单的页面。

index.js中封装了方法,惊喜的发现前台使用的流式相应是使用的websocket协议。

解读分析一下代码:

index.html

<!--
 * @Autor: lycheng
 * @Date: 2020-01-13 16:12:22
 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>产品体验-大模型</title>
</head>
<body>
<div>
    <div>
        <h2>产品体验-大模型</h2>
        <div class="page-main">
            <div>
                <textarea id="input_text" placeholder="请输入您要问大模型的问题" style="width: 600px">秦始皇的儿子是谁?</textarea>
            </div>
            <div>
                <button class="audio-ctrl-btn">立即提问</button>
            </div>
            <br>
            <div>
                <textarea id="output_text" style="width: 800px;height: 500px"></textarea>
            </div>
        </div>
    </div>
</div>
</body>
</html>

 其实这个主页没有太多解释的地方。

我们来看一下封装的方法--index.js

我们将后台代码分模块进行研究

构造与后台建立websocket连接的url

function getWebsocketUrl() {
    return new Promise((resolve, reject) => {
        var apiKey = API_KEY
        var apiSecret = API_SECRET
        var url = 'wss://spark-api.xf-yun.com/v1.1/chat'
        var host = location.host
        var date = new Date().toGMTString()
        var algorithm = 'hmac-sha256'
        var headers = 'host date request-line'
        var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v1.1/chat HTTP/1.1`
        var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
        var signature = CryptoJS.enc.Base64.stringify(signatureSha)
        var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
        var authorization = btoa(authorizationOrigin)
        url = `${url}?authorization=${authorization}&date=${date}&host=${host}`
        resolve(url)
    })
}

代码解析:

  1. function getWebsocketUrl() { 定义了一个名为 getWebsocketUrl 的函数。
  2. return new Promise((resolve, reject) => { 使用 Promise 构造函数创建了一个异步操作,并传入 resolve 和 reject 回调函数。
  3. var apiKey = API_KEY 声明了一个变量 apiKey,并将其初始化为 API_KEY 的值。
  4. var apiSecret = API_SECRET 声明了一个变量 apiSecret,并将其初始化为 API_SECRET 的值。
  5. var url = 'wss://spark-api.xf-yun.com/v1.1/chat' 声明了一个变量 url,并将其初始化为一个 WebSocket 连接的 URL。
  6. var host = location.host 声明了一个变量 host,并将其初始化为当前页面的主机名。
  7. var date = new Date().toGMTString() 声明了一个变量 date,并将其初始化为当前时间的 GMT 表示形式。
  8. var algorithm = 'hmac-sha256' 声明了一个变量 algorithm,并将其初始化为字符串 'hmac-sha256'
  9. var headers = 'host date request-line' 声明了一个变量 headers,并将其初始化为字符串 'host date request-line'
  10. var signatureOrigin = host: ${host}\ndate: ${date}\nGET /v1.1/chat HTTP/1.1`` 声明了一个变量 signatureOrigin,并将其初始化为一个字符串,包含了请求的头部信息。
  11. var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret) 使用 CryptoJS 的 HMAC-SHA256 算法对 signatureOrigin 进行哈希运算,并将结果存储在变量 signatureSha 中。
  12. var signature = CryptoJS.enc.Base64.stringify(signatureSha) 将 signatureSha 转换为 Base64 编码的字符串,并将结果存储在变量 signature 中。
  13. var authorizationOrigin = api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"声明了一个变量authorizationOrigin`,并将其初始化为一个包含授权信息的字符串。
  14. var authorization = btoa(authorizationOrigin) 使用 btoa 函数将 authorizationOrigin 转换为 Base64 编码的字符串,并将结果存储在变量 authorization 中。
  15. url = ${url}?authorization=${authorization}&date=${date}&host=${host}将带有授权信息的 URL 拼接在原始 URL 的后面,并将结果存储回变量url` 中。
  16. resolve(url) 调用 resolve 回调函数,并将带有授权信息的 URL 作为参数传递给它。
  17. }) } 结束异步操作块和函数定义。
  18. return new Promise((resolve, reject) => { ... } ) } 返回一个 Promise 对象,该对象将在异步操作完成后通过调用 resolve 回调函数来解析 URL。

这段代码的目的是通过使用 HMAC-SHA256 算法对请求进行签名,并添加授权信息到 WebSocket 连接 URL 中,以获取一个合法的 WebSocket 连接 URL。

封装的调用的工具类

class TTSRecorder {
    constructor({
                    appId = APPID
                } = {}) {
        this.appId = appId
        this.status = 'init'
    }

    // 修改状态
    setStatus(status) {
        this.onWillStatusChange && this.onWillStatusChange(this.status, status)
        this.status = status
    }

    // 连接websocket
    connectWebSocket() {
        this.setStatus('ttsing')
        return getWebsocketUrl().then(url => {
            let ttsWS
            if ('WebSocket' in window) {
                ttsWS = new WebSocket(url)
            } else if ('MozWebSocket' in window) {
                ttsWS = new MozWebSocket(url)
            } else {
                alert('浏览器不支持WebSocket')
                return
            }
            this.ttsWS = ttsWS
            ttsWS.onopen = e => {
                this.webSocketSend()
            }
            ttsWS.onmessage = e => {
                this.result(e.data)
            }
            ttsWS.onerror = e => {
                clearTimeout(this.playTimeout)
                this.setStatus('error')
                alert('WebSocket报错,请f12查看详情')
                console.error(`详情查看:${encodeURI(url.replace('wss:', 'https:'))}`)
            }
            ttsWS.onclose = e => {
                console.log(e)
            }
        })
    }


    // websocket发送数据
    webSocketSend() {
        var params = {
            "header": {
                "app_id": this.appId,
                "uid": "fd3f47e4-d"
            },
            "parameter": {
                "chat": {
                    "domain": "general",
                    "temperature": 0.5,
                    "max_tokens": 1024
                }
            },
            "payload": {
                "message": {
                    "text": [
                        {
                            "role": "user",
                            "content": "中国第一个皇帝是谁?"
                        },
                        {
                            "role": "assistant",
                            "content": "秦始皇"
                        },
                        {
                            "role": "user",
                            "content": "秦始皇修的长城吗"
                        },
                        {
                            "role": "assistant",
                            "content": "是的"
                        },
                        {
                            "role": "user",
                            "content": $('#input_text').text()
                        }
                    ]
                }
            }
        }
        console.log(JSON.stringify(params))
        this.ttsWS.send(JSON.stringify(params))
    }

    start() {
        total_res = ""; // 请空回答历史
        this.connectWebSocket()
    }

    // websocket接收数据的处理
    result(resultData) {
        let jsonData = JSON.parse(resultData)
        total_res = total_res + resultData
        $('#output_text').val(total_res)
        // console.log(resultData)
        // 提问失败
        if (jsonData.header.code !== 0) {
            alert(`提问失败: ${jsonData.header.code}:${jsonData.header.message}`)
            console.error(`${jsonData.header.code}:${jsonData.header.message}`)
            return
        }
        if (jsonData.header.code === 0 && jsonData.header.status === 2) {
            this.ttsWS.close()
            bigModel.setStatus("init")
        }
    }
}

代码解释: 

在构造函数中,有一个可选的参数appId,默认值为"APPID"。该函数会将appId赋值给隶属于类的属性this.appId,并将状态初始化为"init"。

setStatus(status)是一个方法,用于改变状态。在调用该方法之前,可以通过设置onWillStatusChange回调函数来执行一些额外操作。该方法会将状态设置为传入的status值。

connectWebSocket()是一个方法,用于建立WebSocket连接。在开始建立连接之前,会将状态设置为"ttsing"。然后,通过调用getWebsocketUrl()方法获取WebSocket的URL,并创建一个WebSocket实例,保存在ttsWS属性中。如果浏览器不支持WebSocket,则会弹出一个警告,而后续的操作将中止。

创建WebSocket实例后,定义了几个回调函数:onopenonmessageonerroronclose。在连接成功时,会调用webSocketSend()方法发送数据;接收到消息时,会调用result()方法处理数据;发生错误时,会更改状态为"error";关闭连接时,在控制台打印相关信息。

webSocketSend()方法用于向WebSocket发送数据。首先,创建了一个包含参数的params对象,其中包括应用ID、用户ID、聊天参数和要转换为语音的文本。通过调用JSON.stringify()方法将参数对象转换为字符串,并使用WebSocket实例的send()方法发送。

start()方法是启动TTS录制的入口。在该方法中,将总的回答历史total_res初始化为空字符串,然后调用connectWebSocket()方法建立WebSocket连接。

result(resultData)方法用于处理接收到的WebSocket数据。首先,将接收到的JSON字符串转换为对象,将结果累加到total_res变量中,并将其值显示在output_text元素中。如果提问失败(header.code不为0),会弹出一个警告并输出错误信息。如果提问成功但会话结束(header.status为2),则关闭WebSocket连接,并将状态设置为"init"。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

恒驰QA | 我们到底是做什么的?和恒大恒驰有什么关系?

5个关键问题解答&#xff0c;带您走进恒驰信息 Q&#xff1a;恒驰信息和恒大恒驰是什么关系&#xff1f; A&#xff1a;答案是没有关系。 这是我们被问到比较频繁的问题&#xff0c;只能说纯属同名啦&#xff01;恒驰信息成立于2005年&#xff0c;比恒大恒驰创立早上14年之久。…

【视觉SLAM入门】7.2. 从卡尔曼滤波到扩展卡尔曼滤波,引入、代码、原理、实战,C++实现以及全部源码

"觇其平生&#xff0c;岂能容物&#xff1f;" 0. 简单认识1. 公式对比解读2. 应用举例3. 解决方案(公式---代码对应)3.1 初始化3.2 EKF3.2.1 预测---状态方程3.2.2 系统协方差矩阵3.2.3 预测---系统协方差矩阵3.2.4 设置测量矩阵3.2.5 更新---状态变量&#xff0c;卡…

搞懂三极管

三极管的电流放大作用应该算是模拟电路里面的一个难点内容&#xff0c;我想用这几个动画简单的解释下为什么小电流Ib能控制大电流Ic的大小&#xff0c;以及放大电路的原理。 我这里的三极管也叫双极型晶体管,模电的放大电路和数电的简单逻辑电路里面都会用到。有集电极c、基极b…

docker-compose 升级

此方法针对Linux版本生效&#xff0c;请测试有效&#xff1b;记录以方面日后能使用到&#xff1b; ## 安装docker 使用常用命名安装即可, 以下命令安装若提示找不到安装包&#xff0c;直接update 即可。 yum install docker OR apt install docker OR apt install do…

2023 年全国大学生数学建模B题目-多波束测线问题

B题目感觉属于平面几何和立体几何的问题&#xff0c;本质上需要推导几何变换情况&#xff0c;B题目属于有标准答案型&#xff0c;没太大的把握不建议选择&#xff0c;可发挥型不大。 第一问 比较简单&#xff0c;就一个2维平面的问题&#xff0c;但有点没理解&#xff0c;这个…

【2023最新版】腾讯云CODING平台使用教程(Pycharm/命令:本地项目推送到CODING)

目录 一、CODING简介 网址 二、CODING使用 1. 创建项目 2. 创建代码仓库 三、PyCharm&#xff1a;本地项目推送到CODING 1. 管理远程 2. 提交 3. 推送 4. 结果 四、使用命令推送 1. 打开终端 2. 初始化 Git 仓库 3. 添加远程仓库 4. 添加文件到暂存区 5. 提交更…

【代码随想录】Day 48 动态规划9 (打家劫舍Ⅰ Ⅱ Ⅲ)

打家劫舍 https://leetcode.cn/problems/house-robber/ 注意要是i-1没偷&#xff0c;那么dp[i] dp[i-2] nums[i]&#xff0c;而不是dp[i-1]&#xff1a; class Solution { public:int rob(vector<int>& nums) {if (nums.size() 0) return 0;if (nums.size() 1…

【图文并茂】C++介绍之串

1.1串 引子—— ​ 字符串简称为串&#xff0c;串是由字符元素构成的&#xff0c;其中元素的逻辑关系也是一种线性关系。串的处理在计算机非数值处理中占用重要的地位&#xff0c;如信息检索系统&#xff0c;文字编辑等都是以串数据作为处理对象 串是由零个或多个字符组成的…

OSCP系列靶场-Esay-Sumo

OSCP系列靶场-Esay-Sumo 总结 getwebshell : nikto扫描 → 发现shellshock漏洞 → 漏洞利用 → getwebshell 提 权 思 路 : 内网信息收集 → 内核版本较老 →脏牛提权 准备工作 启动VPN 获取攻击机IP → 192.168.45.194 启动靶机 获取目标机器IP → 192.168.190.87 信息收…

【LeetCode75】第四十九题 数组中的第K个最大元素

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目很简单&#xff0c;就是给我们一个数组&#xff0c;让我们返回第K大的元素。 那么很直观的一个做法就是我们直接对数组进行降序排序…

【恒生电子内推码】

Hello&#xff0c;我是恒生电子股份有限公司的校园大使&#xff0c;不想简历投递后“泡池子”&#xff0c;登录链接&#xff1a;campus.hundsun.com/campus/jobs&#xff0c;填写我的推荐码&#xff1a;EZVJR0&#xff0c;投递&#xff0c;简历第一时间送到HR面前&#xff0c;快…

STM32-DMA

1 DMA简介 DMA&#xff08;Direct Memory Access&#xff09;,中文名为直接内存访问&#xff0c;它是一些计算机总线架构提供的功能&#xff0c;能使数据从附加设备&#xff08;如磁盘驱动器&#xff09;直接发送到计算机主板的内存上。对应嵌入式处理器来说&#xff0c;DMA可…

【2023年数学建模国赛】赛题发布

2023数学建模国赛赛题已经发布啦&#xff0c;距离赛题发布已经过去三个小时了&#xff0c;大家是否已经确定题目呢&#xff1f;学姐后续会持续更新赛题思路与代码~

TINA如何导入spice模型

本文介绍如何使用TINA仿真运算放大器电路。TINA是TI公司自己的spice仿真软件&#xff0c;各个大厂为了更好的让客户使用自己的器件&#xff0c;都纷纷推出自己的仿真软件&#xff0c;ADI也有类似的软件&#xff0c;有机会我们介绍&#xff0c;这期我们主要简单介绍下如何使用TI…

Jmeter系列-Jmeter面板介绍和常用配置(2)

Jmeter面板介绍 常用菜单栏 分布式运行相关的 选项&#xff0c;可以打开日志&#xff0c;修改语言、函数助手对话框&#xff0c;还有管理插件 常用的图标 从左到右依次 新建测试计划选择测试计划模板创建一个新的测试计划打开jmeter脚本保存jmeter脚本剪切复制粘贴展开目录…

大数据课程K18——Spark的ALS算法与显式矩阵分解

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Spark的ALS算法与显式矩阵分解; ⚪ 掌握Spark的ALS算法原理; 一、ALS算法与显式矩阵分解 1. 概述 我们在实现推荐系统时,当要处理的那些数据是由用户所提供的自身的偏好数据,这些…

Apache nginx解析漏洞复现

文章目录 空字节漏洞安装环境漏洞复现 背锅解析漏洞安装环境漏洞复现 空字节漏洞 安装环境 将nginx解压后放到c盘根目录下&#xff1a; 运行startup.bat启动环境&#xff1a; 在HTML文件夹下有它的主页文件&#xff1a; 漏洞复现 nginx在遇到后缀名有php的文件时&#xff0c;…

微信小程序组件的创建与引用

组件的创建 <view><swiper class"myswiper" interval"{{interval}}" circular autoplay"{{autoplay}}" indicator-dots"{{indicatorDots}}"><swiper-item><image mode"widthFix" src"/image/l…

【JAVA】面向对象的编程语言(继承篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言继承类的继承方式继承的各种类型多继承继承的特性各种继承关键字extends关键字implements关键字super 与 this 关键字super 关键字this 关键字 final 关键字 前言 在之前的…

sklearn中make_blobs方法:聚类数据生成器

sklearn中make_blobs()方法参数&#xff1a; n_samples:表示数据样本点个数,默认值100 n_features:是每个样本的特征&#xff08;或属性&#xff09;数&#xff0c;也表示数据的维度&#xff0c;默认值是2。默认为 2 维数据&#xff0c;测试选取 2 维数据也方便进行可视化展示…