Unity+讯飞星火大模型+Web api,实现二次元小姐姐AI聊天互动

news2024/11/23 14:54:01

1.简述

        最近讯飞的星火大模型更新了2.0版本,增强了AI的语言生成能力。毕竟是国产大语言模型,我也尝试使用了一下星火大模型的应用广场,体验还是很不错的。应用广场提供了很多AI助手工具,也支持用户创建自己的AI助手,能力不局限于自然语言生成,也有一些图片生成工具、视频生成工具之类的,总的来说,还是很有意思的。

        同时,星火大模型也提供有api服务,可以很方便的集成到自己的应用里。申请api应用的门槛也比较低,简单填写一些信息,就可以申请试用。试用审核大概半个多小时就结束了,官方提供的免费token数量还是比较可观。针对星火大模型V1.5版本以及V2.0版本,各提供了200万的token试用,非常的良心。我的AI二次元小姐姐项目里,使用chatgpt以及一些开源模型的方式,相对来说还是有一定使用门槛,而接入星火大模型门槛就很低了。

        本文就简单介绍一下unity端集成星火大模型API的代码实现,让星火大模型驱动我们的AI二次元小姐姐,与大家聊天吧。

2.开通星火大模型服务

        本节内容将简单介绍一下如何在讯飞星火大模型官网,申请试用星火大模型,并创建星火大模型的应用。

星火大模型官方地址:讯飞星火认知大模型-AI大语言模型-星火大模型-科大讯飞 (xfyun.cn)

        在申请星火大模型服务之前,需要先注册讯飞的账户,使用手机号码验证就可以了,这里不多赘述。在星火大模型官方站点主页,找到【API测试】按钮,可以点击进入API试用申请的页面。

        点击【API测试申请】,即可进入API测试申请界面,如图所示:

        在API申请界面中,填写必填的信息。这里需要注意一下,申请API测试,需要创建一个讯飞的应用,我们可以填写一个自己实现申请号的应用ID,也可以在申请页面点击创建一个新的应用,创建应用成功之后,我们就能够获得应用的密钥,这个在后面的接口对接会使用的到。

        申请提交之后,耐心等待官方审核即可。时间不会太久,我大概是半小时左右,就完成审批,拿到api的试用服务了。

3.对接API服务

        星火大模型应用申请完成之后,我们就可以拿到应用的密钥。进入到讯飞开放平台的控制台界面,选择到新创建的星火大模型服务,我们就可以看到服务剩余的token数,以及应用的密钥信息了。这个页面可以切换查看V1.5和V2.0两个版本的token使用情况。

3.1 API对接流程

        星火大模型的接口对接,考虑到跨平台的兼容性,这里选择采用web方式对接,根据官方文档的说明,我们首先需要调用鉴权接口,获取到接口授权,然后在使用websocket协议与服务端握手,websocket握手成功后,需要在60秒内发送请求。接口采用的是流式输出模式,需要对根据返回的数据判断,并拼接成完整的回复信息,大致流程如下如所示:

        接下来,将描述一下具体的代码实现。

3.2 接口鉴权

        根据官方文档的说明,开发者需要自行先在控制台创建应用,利用应用中提供的appid,APIKey, APISecret进行鉴权,生成最终请求的鉴权url,鉴权参数如下:

参数类型必须说明示例
hoststring请求的主机aichat.xf-yun.com(使用时需替换为实际使用的接口地址)
datestring当前时间戳,采用RFC1123格式,时间偏差需控制在300s内Fri, 05 May 2023 10:43:39 GMT
authorizationstringbase64编码的签名信息参考下方生成方式

        以下是在unity端实现鉴权url的处理代码:

/// <summary>
    /// 获取鉴权url
    /// </summary>
    /// <returns></returns>
    private string GetAuthUrl()
    {
        string date = DateTime.UtcNow.ToString("r");

        Uri uri = new Uri(url);
        StringBuilder builder = new StringBuilder("host: ").Append(uri.Host).Append("\n").//
                                Append("date: ").Append(date).Append("\n").//
                                Append("GET ").Append(uri.LocalPath).Append(" HTTP/1.1");

        string sha = HMACsha256(m_XunfeiSettings.m_APISecret, builder.ToString());
        string authorization = string.Format("api_key=\"{0}\", algorithm=\"{1}\", headers=\"{2}\", signature=\"{3}\"", m_XunfeiSettings.m_APIKey, "hmac-sha256", "host date request-line", sha);

        string NewUrl = "https://" + uri.Host + uri.LocalPath;

        string path1 = "authorization" + "=" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(authorization));
        date = date.Replace(" ", "%20").Replace(":", "%3A").Replace(",", "%2C");
        string path2 = "date" + "=" + date;
        string path3 = "host" + "=" + uri.Host;

        NewUrl = NewUrl + "?" + path1 + "&" + path2 + "&" + path3;
        return NewUrl;
    }

    public string HMACsha256(string apiSecretIsKey, string buider)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(apiSecretIsKey);
        System.Security.Cryptography.HMACSHA256 hMACSHA256 = new System.Security.Cryptography.HMACSHA256(bytes);
        byte[] date = System.Text.Encoding.UTF8.GetBytes(buider);
        date = hMACSHA256.ComputeHash(date);
        hMACSHA256.Clear();

        return Convert.ToBase64String(date);

    }

3.3 接口请求

       3.3.1 接口费用与服务地址

        根据官方文档说明,星火大模型的1.5版本以及2.0版本的计费模型以及资源地址是不同的,当然我们免费申请的服务是不需要额外付费的,但超过额度了的话,就需要付费了,token的价格如下所示:

服务引擎单价
讯飞星火认知大模型V1.50.18元/万tokens
讯飞星火认知大模型V2.00.36元/万tokens

        两个版本的api地址分别是:

        ①星火大模型1.5版本请求地址,对应的domain参数为general

ws(s)://spark-api.xf-yun.com/v1.1/chat

        ②星火大模型1.5版本请求地址,对应的domain参数为generalv2:

ws(s)://spark-api.xf-yun.com/v2.1/chat

3.3.2 发送报文结构        

        星火大模型的API服务对接部分,按照文档说明,使用websocket协议握手成功之后,就可以根据报文格式发送信息了。请求参数参数部分的接口说明如下:

header部分

参数名称类型必传参数要求参数说明
app_idstring应用appid,从开放平台控制台创建的应用中获取
uidstring最大长度32每个用户的id,用于区分不同用户

parameter.chat部分

参数名称类型必传参数要求参数说明
domainstring取值为[general,generalv2]指定访问的领域,general指向V1.5版本 generalv2指向V2版本。注意:不同的取值对应的url也不一样!
temperaturefloat取值为[0,1],默认为0.5核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高
max_tokensint取值为[1,4096],默认为2048模型回答的tokens的最大长度
top_kint取值为[1,6],默认为4从k个候选中随机选择⼀个(⾮等概率)
chat_idstring需要保障用户下的唯一性用于关联用户会话

payload.message.text部分

注:text下所有content累计内容 tokens需要控制在8192内

参数名称类型必传参数要求参数说明
rolestring取值为[user,assistant]user表示是用户的问题,assistant表示AI的回复
contentstring所有content的累计tokens需控制8192以内用户和AI的对话内容

报文示例:

{
        "header": {
            "app_id": "12345",
            "uid": "12345"
        },
        "parameter": {
            "chat": {
                "domain": "general",
                "temperature": 0.5,
                "max_tokens": 1024, 
            }
        },
        "payload": {
            "message": {
                # 如果想获取结合上下文的回答,需要开发者每次将历史问答信息一起传给服务端,如下示例
                # 注意:text里面的所有content内容加一起的tokens需要控制在8192以内,开发者如有较长对话需求,需要适当裁剪历史信息
                "text": [
                    {"role": "user", "content": "你是谁"} # 用户的历史问题
                    {"role": "assistant", "content": "....."}  # AI的历史回答结果
                    # ....... 省略的历史对话
                    {"role": "user", "content": "你会做什么"}  # 最新的一条问题,如无需上下文,可只传最新一条问题
                ]
        }
    }
}

        3.3.3 响应报文结构

        接口服务将采用流式输出方式,返回回复信息,我们需要解析返回的报文信息,拼接成完整的回复信息。接口响应的报文结构如下所示:

header部分

字段名类型字段说明
codeint错误码,0表示正常,非0表示出错;详细释义可在接口说明文档最后的错误码说明了解
messagestring会话是否成功的描述信息
sidstring会话的唯一id,用于讯飞技术人员查询服务端会话日志使用,出现调用错误时建议留存该字段
statusint会话状态,取值为[0,1,2];0代表首次结果;1代表中间结果;2代表最后一个结果

payload.choices部分

字段名类型字段说明
statusint文本响应状态,取值为[0,1,2]; 0代表首个文本结果;1代表中间文本结果;2代表最后一个文本结果
seqint返回的数据序号,取值为[0,9999999]
contentstringAI的回答内容
rolestring角色标识,固定为assistant,标识角色为AI
indexint结果序号,取值为[0,10]; 当前为保留字段,开发者可忽略

payload.usage部分(在最后一次结果返回)

字段名类型字段说明
question_tokensint保留字段,可忽略
prompt_tokensint包含历史问题的总tokens大小
completion_tokensint回答的tokens大小
total_tokensintprompt_tokens和completion_tokens的和,也是本次交互计费的tokens大小

        接口响应报文结构示例:

# 接口为流式返回,此示例为最后一次返回结果,开发者需要将接口多次返回的结果进行拼接展示
{
    "header":{
        "code":0,
        "message":"Success",
        "sid":"cht000cb087@dx18793cd421fb894542",
        "status":2
    },
    "payload":{
        "choices":{
            "status":2,
            "seq":0,
            "text":[
                {
                    "content":"我可以帮助你的吗?",
                    "role":"assistant",
                    "index":0
                }
            ]
        },
        "usage":{
            "text":{
                "question_tokens":4,
                "prompt_tokens":5,
                "completion_tokens":9,
                "total_tokens":14
            }
        }
    }
}

3.3.4 接口对接代码示例

        使用websocket协议与服务端握手成功后,按照报文格式要求发送信息,等待接口响应,并解析响应数据拼接成完整的回复信息。代码示例如下所示:

    #region websocket连接
    /// <summary>
    /// websocket
    /// </summary>
    private ClientWebSocket m_WebSocket;
    private CancellationToken m_CancellationToken;
    /// <summary>
    /// 连接服务器,获取回复
    /// </summary>
    private async void ConnectHost(string text,Action<string> _callback)
    {
        try
        {
            stopwatch.Restart();

            m_WebSocket = new ClientWebSocket();
            m_CancellationToken = new CancellationToken();
            string authUrl = GetAuthUrl();
            string url = authUrl.Replace("http://", "ws://").Replace("https://", "wss://");

            //Uri uri = new Uri(GetUrl());
            Uri uri = new Uri(url);
            await m_WebSocket.ConnectAsync(uri, m_CancellationToken);

            //发送json
            string _jsonData = text;
            await m_WebSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(_jsonData)), WebSocketMessageType.Binary, true, m_CancellationToken); //发送数据
            StringBuilder sb = new StringBuilder();
            //用于拼接返回的答复
            string _callBackMessage = "";

            //播放队列.Clear();
            while (m_WebSocket.State == WebSocketState.Open)
            {
                var result = new byte[4096];
                await m_WebSocket.ReceiveAsync(new ArraySegment<byte>(result), m_CancellationToken);//接受数据
                List<byte> list = new List<byte>(result); while (list[list.Count - 1] == 0x00) list.RemoveAt(list.Count - 1);//去除空字节  
                var str = Encoding.UTF8.GetString(list.ToArray());
                sb.Append(str);
                if (str.EndsWith("}"))
                {
                    //获取返回的数据
                    ResponseData _responseData = JsonUtility.FromJson<ResponseData>(sb.ToString());
                    sb.Clear();

                    if (_responseData.header.code != 0)
                    {
                        //返回错误
                        //PrintErrorLog(_responseData.code);
                        Debug.Log("错误码:" + _responseData.header.code);
                        m_WebSocket.Abort();
                        break;
                    }
                    //没有回复数据
                    if (_responseData.payload.choices.text.Count == 0)
                    {
                        Debug.LogError("没有获取到回复的信息!");
                        m_WebSocket.Abort();
                        break;
                    }
                    //拼接回复的数据
                    _callBackMessage += _responseData.payload.choices.text[0].content;

                    if (_responseData.payload.choices.status == 2)
                    {
                        stopwatch.Stop();
                        Debug.Log("ChatSpark耗时:" + stopwatch.Elapsed.TotalSeconds);

                        //添加记录
                        m_DataList.Add(new SendData("assistant", _callBackMessage));

                        //回调
                        _callback(_callBackMessage);
                        m_WebSocket.Abort();
                        break;
                    }
                }
            }

        }
        catch (Exception ex)
        {
            Debug.LogError("报错信息: " + ex.Message);
            m_WebSocket.Dispose();
        }
    }

    #endregion

4.结束语

        这次的文章简单介绍了讯飞星火大模型的web api的对接流程,并针对接口对接的流程进行了介绍,包括接口的鉴权、websocket握手以及发送报文、响应报文的结构说明,并提供了针对全流程在unity端的实现代码示例。通过上述的代码实现,我们就可以在unity引擎中,使用星火大模型的api来驱动AI二次元小姐姐的对话交互。

        上述代码只包含了核心的代码实现,完整的代码工程可以从我的开源项目下载使用,项目包含了针对多种GPT应用的集成工具,以及语音服务的集成,对我这个项目感兴趣的朋友,可以上我的B站号查看,我也做有详细的教程,相关源码可以在的哔哩哔哩主站找到相关视频,在视频介绍以及评论区获取。

国产星火大模型驱动AI小姐姐聊天,unity开源工具包,手把手打造自己的二次元老婆~


上述项目地址传送门:

AI二次元老婆开源项目(unity-AI-Chat-Toolkit):

Github地址:https://github.com/zhangliwei7758/unity-AI-Chat-Toolkit

Gitee地址:https://gitee.com/DammonSpace/unity-ai-chat-toolkit

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

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

相关文章

算法基础第三章

算法基础第三章 1、dfs(深度搜索)1.1、 递归回溯1.2、递归剪枝&#xff08;剪枝就是判断接下来的递归都不会满足条件&#xff0c;直接回溯&#xff0c;不再继续往下无意义的递归&#xff09; 2、bfs(广度搜索)2.1、最优路径&#xff08;只适合于边权都相等的题&#xff09; 3、…

使用 Netty 实现群聊功能的步骤和注意事项

文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍&#xff0c;我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…

QT登陆注册界面练习

一、界面展示 二、主要功能界面代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QMainWindow(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setFixedSize(540,410); //设置固定尺寸th…

【计算机组成 课程笔记】2.1 设计自己的计算机

课程链接&#xff1a; 计算机组成_北京大学_中国大学MOOC(慕课) 2 - 1 - 201-设计自己的计算机&#xff08;14‘24’‘&#xff09;_哔哩哔哩_bilibili 什么是指令系统体系结构&#xff1f;这个问题其实非常简单&#xff0c;但要想解释清楚也没有那么容易。我们还是从一个小故事…

兄弟 Goland 咱能一次性将注释设置好不

大家好&#xff0c;我是阿兵云原生 工作中我们都只是写注释是一个好习惯&#xff0c;作为新生代的农名工&#xff0c;特别烦的就是别人不写注释&#xff0c;但是自己偏偏又不喜欢写注释&#x1f602;&#x1f602;&#x1f602; 对于 golang 的注释&#xff0c;我发现很多新朋…

攻防世界-What-is-this

原题 解题思路 解压后文件 没有后缀&#xff0c;不知道是什么文件。用notepad打开找不到flag。 尝试当成压缩包解压。 用stegsolve以打开图片1&#xff0c; 合成两张图片。

MySQL中的表与视图:解密数据库世界的基石

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

vue中axios请求篇

vue中如何发起请求? 利用axios来发起请求&#xff0c;但是前期需要配置 首先安装axios 可以使用npm、yarn等进行安装 npm安装方式 npm install axios -sava //在项目文件夹中打开cmd或者终端进行安装依赖 yarn安装方式 yarn add axios 引入axios。我一般是在src下创建一个u…

【C++】学习C++STL中的数组——vector

❤️前言 好久不见大家&#xff01;今天的这篇博客是关于我对于STL(C标准模板库)中的容器vector的学习和理解&#xff0c;希望大家能够喜欢。 正文 vector是STL中的一种序列容器&#xff0c;对应着数据结构中的顺序表&#xff0c;也可以说是数组。在我们正式学习了解vector之前…

spring boot 测试用例

依赖包 <dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.5.RELEASE</version><scope>compile</scope></dependency><dependency><groupId>ju…

Autoware.universe部署05:实车调试

文章目录 一、建图1.1 点云地图1.2 高精地图 二、参数配置三、传感器数据通信接口3.1 雷达点云3.2 图像3.3 IMU3.4 GNSS RTK 四、实车调试4.1 编写启动4.2 修改传感器外参4.3 修改车身参数4.4 实车调试 本文介绍了 Autoware.universe 在实车上的部署&#xff0c;本系列其他文章…

《Web安全基础》04. 文件上传漏洞

web 1&#xff1a;文件上传漏洞2&#xff1a;WAF 绕过2.1&#xff1a;数据溢出2.2&#xff1a;符号变异2.3&#xff1a;数据截断2.4&#xff1a;重复数据 本系列侧重方法论&#xff0c;各工具只是实现目标的载体。 命令与工具只做简单介绍&#xff0c;其使用另见《安全工具录》…

2023京东口腔护理赛道行业数据分析(京东销售数据分析)

近年来&#xff0c;口腔护理逐渐成为年轻人重视的健康领域&#xff0c;从口腔护理整体市场来看&#xff0c;牙膏和牙刷等基础口腔护理产品仍占据主导地位。不过&#xff0c;随着口腔护理市场逐步朝向精致化、专业化、多元化等方向发展&#xff0c;不少新兴口腔护理产品受到消费…

C++学习|CUDA内存管理代码实例

前言&#xff1a;之前介绍了CUDA入门知识&#xff0c;对CUDA编程有了一个基本了解&#xff0c;但是实际写起来还是遇到很多问题&#xff0c;例如cpp文件该怎么调用cuda文件、cpu和gpu之间内存数据怎么交换、如何编写.cu和.cuh文件之类的。本篇文章将会以一个实现向量相加的代码…

【数据结构】二叉数的存储与基本操作的实现

文章目录 &#x1f340;二叉树的存储&#x1f333;二叉树的基本操作&#x1f431;‍&#x1f464;二叉树的创建&#x1f431;‍&#x1f453;二叉树的遍历&#x1f3a1;前中后序遍历&#x1f4cc;前序遍历&#x1f4cc;中序遍历&#x1f4cc;后续遍历 &#x1f6eb;层序遍历&am…

什么是Python爬虫分布式架构,可能遇到哪些问题,如何解决

目录 什么是Python爬虫分布式架构 1. 调度中心&#xff08;Scheduler&#xff09;&#xff1a; 2. 爬虫节点&#xff08;Crawler Node&#xff09;&#xff1a; 3. 数据存储&#xff08;Data Storage&#xff09;&#xff1a; 4. 反爬虫处理&#xff08;Anti-Scraping&…

2023-08-30力扣每日一题

链接&#xff1a; 1654. 到家的最少跳跃次数 题意&#xff1a; 从0出发&#xff0c;到X的最少步数 它可以 往前 跳恰好 a 个位置&#xff08;即往右跳&#xff09;。它可以 往后 跳恰好 b 个位置&#xff08;即往左跳&#xff09;。它不能 连续 往后跳 2 次。它不能跳到任何…

2023新版医保目录明细(药品查询)

查询医保目录的主要目的是为了了解医保政策对于特定医疗服务、药品和医疗器械的覆盖范围和支付标准。大众可以通过查看医保目录可以确定哪些药品可以被医保支付以及报销的比例和限额&#xff1b;医药从业者可通过查看医保目录可以即使了解医保政策的变化&#xff0c;便于做出相…

Window10 安装 Lua

1、下载地址&#xff1a;https://luabinaries.sourceforge.net/download.html 2、下载 3、解压后共有4个文件&#xff0c;这里我把这几个文件放到如下目录 D:\Program Files\lua-5.4.2\bin 4、定义环境变量 5、打开 powershell&#xff0c;运行 lua54 -v PS C:\Windows\syste…

qt设计界面

widget.h #ifndef WIDGET_H #define WIDGET_H //防止文件重复包含#include <QWidget> //QWidget类所在的头文件&#xff0c;父类头文件 #include<QIcon> #include<QPushButton> …