数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型

这篇具有很好参考价值的文章主要介绍了数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 下载插件:motionverse官网地址:概述 · Motionverse 接口文档 (deepscience.cn)

数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型,chatgpt,语言模型,人工智能


2. 按照官方文档新建Unity工程:对接说明 · Motionverse 接口文档 (deepscience.cn)


3. 通过我们自己的ASR,将语音转换为文本,文本通过大语言模型(chatgpt、文心一言以及其他大语言模型)生成的结果,直接通过生成式AI技术,把文本转化为AI智能体的声音、动作和表情,和大语言模型完美连接,只需要在获取到文本的时候调用以下代码即可:
代码示例:

DriveTask task = new DriveTask();
task.player = player;
task.text = question;
NLPDrive.GetDrive(task);


其中,player即为挂载motionverse插件中Player脚本的对象,question即为大语言模型获取到的答案。

还可以自己生成语音,通过语音链接调用以下代码:

DriveTask task = new DriveTask();

task.player = player;

task.text = audioUrl;

AudioUrlDrive.GetDrive(task);

其中,player即为挂载motionverse插件中Player脚本的对象,audioUrl即为语音链接。

4. 新建脚本AskManager,并挂载到场景中(可新建空物体),脚本代码如下:

using LitJson;
using Motionverse;
using MotionverseSDK;
using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class AskManager : MonoBehaviour
{
    public Player player;
    public Dropdown dropdown;
    public InputField inputField;
    public Button btnSend;

    public string chatGptKey = "";
    private string chatUrl = "https://chatgpt.kazava.io/v1/chat/completions";

    public string wenXinAPI = "";
    public string wenXinSECRET = "";
    private string wenXinToken = "";
    private int curSelectNLP = 0;

    // Start is called before the first frame update
    private void Awake()
    {
        for (int i = 0; i < Display.displays.Length; i++)
        {
            Display.displays[i].Activate();
        }

    }
    void Start()
    {
        dropdown.onValueChanged.AddListener((value) =>
        {
            curSelectNLP = value;
        });
        StartCoroutine(GetWenxinToken());
        btnSend.onClick.AddListener(() =>
        {
            if (string.IsNullOrEmpty(inputField.text))
            {
                Debug.Log("请输入内容!");
            }
            else
            {
                GetAnswer(inputField.text);
            }
        });
    }

    public void GetAnswer(string q)
    {
        StartCoroutine(RealAnswer(q));
    }



    public IEnumerator RealAnswer(string question)
    {
        switch (curSelectNLP)
        {
            case 0:
                DriveTask task = new DriveTask();
                task.player = player;
                task.text = question;
                NLPDrive.GetDrive(task);
                break;
            case 1:
                StartCoroutine(RequestChat(question));
                break;
            case 2:
                StartCoroutine(ChatCompletions(question));
                break;
            default:
                break;
        }

        Invoke("restartRecording", 1);

        yield return null;

    }

    IEnumerator GetWenxinToken()
    {
        string url =$"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={wenXinAPI}&client_secret={wenXinSECRET}";
        UnityWebRequest webRequest = UnityWebRequest.Get(url);
        webRequest.timeout = 5000;

        yield return webRequest.SendWebRequest();

        if (webRequest.result == UnityWebRequest.Result.Success)
        {
            string response = webRequest.downloadHandler.text;
            var result = JsonUtility.FromJson<AccessTokenResponse>(response);
            wenXinToken = result.access_token;
        }
        else
        {
            Debug.LogError("Failed to get access token: " + webRequest.error);
        }
    }

    IEnumerator ChatCompletions(string content)
    {
        string url = $"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token={wenXinToken}";
        WenXinPostData postData = new WenXinPostData();
        postData.messages = new WenXinMessage[1];
        postData.messages[0] = new WenXinMessage();
        postData.messages[0].content = content + "30字以内";
        string data = JsonMapper.ToJson(postData);

        UnityWebRequest webRequest = UnityWebRequest.Post(url, data, "application/json");
        webRequest.timeout = 5000;
        yield return webRequest.SendWebRequest();

        if (webRequest.result == UnityWebRequest.Result.Success)
        {
            string response = webRequest.downloadHandler.text;
            WenXinRequest requestData = JsonMapper.ToObject<WenXinRequest>(response);
            DriveTask task = new DriveTask();
            task.player = player;
            task.text = requestData.result;
            TextDrive.GetDrive(task);
        }
        else
        {
            Debug.LogError("Chat completions request failed: " + webRequest.error);
        }
    }

    private IEnumerator RequestChat(string content)
    {
        using (UnityWebRequest webRequest = new UnityWebRequest(chatUrl, "POST"))
        {
            webRequest.SetRequestHeader("Content-Type", "application/json");
            ChatGPTPostData postData = new ChatGPTPostData();
            postData.key = chatGptKey;
            postData.messages = new PostMessage[1];
            postData.messages[0] = new PostMessage();
            postData.messages[0].content = content + "30字以内"; ;
            string data = JsonMapper.ToJson(postData);
            byte[] jsonToSend = new UTF8Encoding().GetBytes(data);
            webRequest.uploadHandler = new UploadHandlerRaw(jsonToSend);
            webRequest.downloadHandler = new DownloadHandlerBuffer();
            yield return webRequest.SendWebRequest();

            if (webRequest.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError("ChatGPT request error: " + content + webRequest.error);
            }
            else
            {
                string response = webRequest.downloadHandler.text;
                ChatGPTRequestData requestData = JsonMapper.ToObject<ChatGPTRequestData>(response);
                DriveTask task = new DriveTask();
                task.player = player;
                task.text = requestData.choices[0].message.content;
                TextDrive.GetDrive(task);
            }
        }
    }
}


5. 新建脚本RealtimeAsrManager,代码如下:

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityWebSocket;


namespace Motionverse
{
    public class RealtimeAsrManager : MonoBehaviour
    {
        private IWebSocket webSocket;
        private Status status = Status.FirstFrame;
        private bool lockReconnect = false;
        [HideInInspector]
        public static Action<string> Asr;

        [SerializeField]
        private GameObject TextBG;
        //百度
        public int AsrAppId;
        public string AsrAppkey = "";


        void Start()
        {
            CreateWebSocket();
            RecorderManager.DataAvailable += OnDataAvailable;
        }
        private void OnDisable()
        {
            RecorderManager.DataAvailable -= OnDataAvailable;
        }
        void CreateWebSocket()
        {
            try
            {
                string uril = "wss://vop.baidu.com/realtime_asr?sn=" + Guid.NewGuid().ToString();
                webSocket = new WebSocket(uril);
                InitHandle();
                webSocket.ConnectAsync();
            }
            catch (Exception e)
            {
                Debug.Log("websocket连接异常:" + e.Message);
                ReConnect();
            }

        }


        private void InitHandle()
        {
            RemoveHandle();
            webSocket.OnOpen += OnOpen;
            webSocket.OnMessage += OnMessage;
            webSocket.OnClose += OnClose;
            webSocket.OnError += OnError;


        }
        void RemoveHandle()
        {
            webSocket.OnOpen -= OnOpen;
            webSocket.OnMessage -= OnMessage;
            webSocket.OnClose -= OnClose;
            webSocket.OnError -= OnError;
        }
        //请求开始
        private void OnDataAvailable(byte[] data)
        {
            if (webSocket == null || (webSocket != null && webSocket.ReadyState != WebSocketState.Open))
                return;

            switch (status)
            {
                case Status.FirstFrame://握手
                    {
                        var firstFrame = new FirstFrame();
                        firstFrame.data.appid= AsrAppId;
                        firstFrame.data.appkey = AsrAppkey;

                        webSocket.SendAsync(JsonUtility.ToJson(firstFrame));
                        status = Status.ContinueFrame;
                    }
                    break;
                case Status.ContinueFrame://开始发送
                    {
                        if (data.Length > 0)
                        {
                            webSocket.SendAsync(data);
                        }
                    }
                    break;
                case Status.LastFrame://关闭
                    {
                        webSocket.SendAsync(JsonUtility.ToJson(new LastFrame()));
                    }
                    break;
                default:
                    break;
            }
        }

        void ReConnect()
        {
            if (this.lockReconnect)
                return;
            this.lockReconnect = true;
            StartCoroutine(SetReConnect());
        }

        private IEnumerator SetReConnect()
        {
            yield return new WaitForSeconds(1);
            CreateWebSocket();
            lockReconnect = false;
        }

        #region WebSocket Event Handlers

        private void OnOpen(object sender, OpenEventArgs e)
        {
            status = Status.FirstFrame;
        }

        private void OnMessage(object sender, MessageEventArgs e)
        {
            var err_msg = Utils.GetJsonValue(e.Data, "err_msg");
            var type = Utils.GetJsonValue(e.Data, "type");
           
            if (err_msg == "OK" && type == "MID_TEXT")
            {
                var result = Utils.GetJsonValue(e.Data, "result");
                TextBG.GetComponentInChildren<Text>().text = result;
            }

            if (err_msg == "OK" && type == "FIN_TEXT")
            {
                var result = Utils.GetJsonValue(e.Data, "result");
                TextBG.GetComponentInChildren<Text>().text = result;
                if (result.Length > 1)
                {
                    RecorderManager.Instance.EndRecording();
                    Asr?.Invoke(result);
                }
               
            }

        }

        private void OnClose(object sender, CloseEventArgs e)
        {
            Debug.Log("websocket关闭," + string.Format("Closed: StatusCode: {0}, Reason: {1}", e.StatusCode, e.Reason));
            webSocket = null;
            ReConnect();
        }

        private void OnError(object sender, ErrorEventArgs e)
        {
            if (e != null)
                Debug.Log("websocket连接异常:" + e.Message);
            webSocket = null;
            ReConnect();
        }

        #endregion
    }
}


6. 新建脚本RecorderManager,代码如下:

using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using Unity.VisualScripting;
namespace Motionverse
{
    public class RecorderManager : Singleton<RecorderManager>
    {
        //标记是否有麦克风
        private bool isHaveMic = false;
        //当前录音设备名称
        private string currentDeviceName = string.Empty;
        //表示录音的最大时长
        int recordMaxLength = 600;
        //录音频率,控制录音质量(16000)
        int recordFrequency = 16000;
        [HideInInspector]
        public static Action<byte[]> DataAvailable;
        [SerializeField]
        private GameObject micON;
        [SerializeField]
        private GameObject micOFF;
        [SerializeField]
        private Image micAmount;
        [SerializeField]
        private GameObject TextBG;
        private AudioClip saveAudioClip;

        int offsetSamples = 0;
        private void Start()
        {
            Debug.Log(Microphone.devices[0]);
            if (Microphone.devices.Length > 0)
            {
                isHaveMic = true;
                currentDeviceName = Microphone.devices[0];
                StartCoroutine(GetAudioFrames());
                StartRecording();
            }

        }

        /// <summary>
        /// 开始录音
        /// </summary>
        /// <returns></returns>
        public void StartRecording() //16000
        {
            if (isHaveMic == false || Microphone.IsRecording(currentDeviceName))
            {
                return;
            }
            micOFF.gameObject.SetActive(false);
            micON.gameObject.SetActive(true);
            TextBG.GetComponentInChildren<Text>().text = null;
            offsetSamples = 0;
            saveAudioClip = Microphone.Start(currentDeviceName, true, recordMaxLength, recordFrequency);

        }
        public void OnButtonClick()
        {
            if (Microphone.IsRecording(currentDeviceName))
            {
                EndRecording();
            }
            else
            {
                StartRecording();
            }
        }
        public void EndRecording()
        {

            if (isHaveMic == false || !Microphone.IsRecording(currentDeviceName))
            {
                return;
            }
            micOFF.gameObject.SetActive(true);
            micON.gameObject.SetActive(false);
            //结束录音
            Microphone.End(currentDeviceName);
        }
        public bool IsRecording()
        {
            return Microphone.IsRecording(currentDeviceName);
        }
        IEnumerator GetAudioFrames()
        {

            while (true)
            {
                if (Microphone.IsRecording(currentDeviceName))
                {
                    int lenght = Microphone.GetPosition(currentDeviceName) * saveAudioClip.channels - offsetSamples;
                    if (lenght > 0)
                    {
                        float[] samples = new float[lenght];
                        saveAudioClip.GetData(samples, offsetSamples);

                        var samplesShort = new short[samples.Length];
                        for (var index = 0; index < samples.Length; index++)
                        {
                            samplesShort[index] = (short)(samples[index] * short.MaxValue);
                        }
                        byte[] binaryData = new byte[samplesShort.Length * 2];
                        Buffer.BlockCopy(samplesShort, 0, binaryData, 0, binaryData.Length);

                        offsetSamples += lenght;
                        DataAvailable?.Invoke(binaryData);
                    }

                    yield return new WaitForSeconds(0.16f);
                }
                else
                {
                    yield return new WaitForSeconds(0.16f);
                    byte[] binaryData = new byte[2];
                    DataAvailable?.Invoke(binaryData);
                }

            }
        }

        /// <summary>
        /// 获取毫秒级别的时间戳,用于计算按下录音时长
        /// </summary>
        /// <returns></returns>
        public double GetTimestampOfNowWithMillisecond()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000;
        }

        private void LateUpdate()
        {
            if (isHaveMic == true && Microphone.IsRecording(currentDeviceName))
            {
                micAmount.fillAmount = Volume;
            }
        }
        public float Volume
        {
            get
            {
                if (Microphone.IsRecording(currentDeviceName))
                {
                    // 采样数
                    int sampleSize = 128;
                    float[] samples = new float[sampleSize];
                    int startPosition = Microphone.GetPosition(currentDeviceName) - (sampleSize + 1);
                    // 得到数据
                    if (startPosition < 0)
                        return 0;

                    saveAudioClip.GetData(samples, startPosition);

                    // Getting a peak on the last 128 samples
                    float levelMax = 0;
                    for (int i = 0; i < sampleSize; ++i)
                    {
                        float wavePeak = samples[i];
                        if (levelMax < wavePeak)
                            levelMax = wavePeak;
                    }

                    return levelMax;
                }
                return 0;
            }
        }
        void OnGUI()
        {
            GUIStyle guiStyle = GUIStyle.none;
            guiStyle.fontSize = 10;
            guiStyle.normal.textColor = Color.white;
            guiStyle.alignment = TextAnchor.UpperLeft;
            Rect tr = new Rect(0, 0, 100, 100);
            GUI.Label(tr, currentDeviceName, guiStyle);
        }
    }
}


7. 新建空物体,挂载脚本RecorderManager和RealtimeAsrManager
8. 输入百度asr的appId和secretKey:

数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型,chatgpt,语言模型,人工智能


9. 输入GPTkey、问心一眼appId和secretKey:

数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型,chatgpt,语言模型,人工智能


10. 根据需求选择相应的NLP方式:

数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型,chatgpt,语言模型,人工智能


注意:如果缺少Singleton文件,可使用如下代码:

using UnityEngine;
namespace Motionverse
{
    public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
    {

        private static T sInstance = null;

        public static T Instance
        {
            get
            {
                if (sInstance == null)
                {
                    GameObject gameObject = new(typeof(T).FullName);
                    sInstance = gameObject.AddComponent<T>();
                }

                return sInstance;
            }
        }

        public static void Clear()
        {
            sInstance = null;
        }

        protected virtual void Awake()
        {
            if (sInstance != null) Debug.LogError(name + "error: already initialized", this);

            sInstance = (T)this;
        }
    }
}

若有收获,就点个赞吧文章来源地址https://www.toymoban.com/news/detail-694401.html

到了这里,关于数字人系列四:Motionverse 接入chatgpt、文心一言等国内外大语言模型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AI百度文心一言大语言模型接入使用(中国版ChatGPT)

    基于百度文心一言语言大模型的智能文本对话AI机器人API,支持聊天对话、行业咨询、语言学习、代码编写等功能. 重要提示:建议使用https协议,当https协议无法使用时再尝试使用http协议 请求方式: POST 序号 参数 是否必须 说明 1 ques 是 你的问题 2 appKey 是 唯一验证AppKey, 可前往官

    2024年02月12日
    浏览(59)
  • 检测文本是否由AI生成,GPT、文心一言等均能被检测

    目前很多机构推出了ChatGPT等AI文本检测工具,但是准确率主打一个模棱两可,基本和抛硬币没啥区别。 先说结论,我们对比了常见的几款AI检测工具,copyleaks检测相比较而言最准确。 来源:GPT3.5 提问词:Redis有什么作用? Redis是一种开源的内存数据库,它具有多种作用和用途

    2024年02月14日
    浏览(71)
  • GBASE首批接入中国版ChatGPT“文心一言“ 打造DB+AI全系服务

    3月 9日,GBASE南大通用宣布成为百度文心一言(英文名:ERNIE Bot)首批生态合作伙伴。后续, GBASE将通过百度智能云全面体验并集成“文心一言”的AI能力,聚焦DB+AI全栈技术及服务。 文心一言是基于百度智能云技术打造出来的大模型。百度在人工智能领域深耕十余年,拥有产

    2024年02月11日
    浏览(92)
  • 百度“文心一言”首批生态合作伙伴公布,Moka接入打造人力资源数字化人AI服务

    近日,百度“文心一言” ( 英文名:ERNIE Bot ) 公布 首批生态合作伙伴,企业级HR SaaS服务商Moka 位列其中 , 将优先体验并接入“文心一言”,以此打造更创新、更智能的人力资源数字化服务。 “文心一言”是百度基于文心大模型技术推出的生成式对话产品。百度在人工智

    2024年02月15日
    浏览(61)
  • Java接入文心一言

    首先需要先申请文心千帆大模型,申请地址:文心一言 (baidu.com),点击加入体验,等通过审核之后就可以进入文心千帆大模型后台进行应用管理了。 在百度智能云首页即可看到文心千帆大模型平台 然后进入后台管理之后,点击应用接入,创建应用即可 创建完应应用之后,便

    2024年02月10日
    浏览(59)
  • 文心一言api接入如何在你的项目里使用文心一言

    基于百度文心一言语言大模型的智能文本对话AI机器人API,支持聊天对话、行业咨询、语言学习、代码编写等功能. 重要提示:建议使用https协议,当https协议无法使用时再尝试使用http协议 请求方式: POST 序号 参数 是否必须 说明 1 ques 是 你的问题 2 appKey 是 唯一验证AppKey, 可前往官

    2024年02月09日
    浏览(58)
  • nodejs文心一言API接入

    需求 在nodejs里面接入文心一言API,官方调用步骤API介绍 - 千帆大模型平台 | 百度智能云文档 大致流程 创建应用——API授权——获取访问凭证——调用接口 创建应用 注册账号创建应用 首先注册百度云智能账号,登录进入百度智能云千帆控制台 ,然后进入控制台创建应用 。

    2024年02月03日
    浏览(39)
  • 文心一言AI大模型,前端接入

    文心一言AI大模型,前端接入 一、参考接口资料 模型广场:https://console.bce.baidu.com/qianfan/modelcenter/model/buildIn/list 我的应用:https://console.bce.baidu.com/qianfan/ais/console/onlineService 千帆大模型调用API介绍: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/flfmc9do2 在线调试: https://console.bce.baidu.co

    2024年02月04日
    浏览(58)
  • 百度文心一言接入教程-Java版

    原文链接 前段时间由于种种原因我的AI BOT https://chat.jylt.top网站停运了数天,后来申请了百度的文心一言和阿里的通义千问开放接口,文心一言的接口很快就通过了,但是文心一言至今杳无音讯。文心一言通过审之后,很快将AI BOT的AI能力接入了文心一言,这里记录一下具体的

    2024年02月15日
    浏览(41)
  • 使用文心一言等智能工具指数级提升嵌入式/物联网(M5Atom/ESP32)和机器人操作系统(ROS1/ROS2)学习研究和开发效率

    以M5AtomS3为例,博客撰写效率提升10倍以上: 0. Linux环境Arduino IDE中配置ATOM S3_zhangrelay的博客-CSDN博客 1. M5ATOMS3基础01按键_zhangrelay的博客-CSDN博客 2. M5ATOMS3基础02传感器MPU6886_zhangrelay的博客-CSDN博客 3. M5ATOMS3基础03给ROS1发一个问候(rosserial)_zhangrelay的博客-CSDN博客 4. M5ATOMS3基

    2024年02月14日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包